root / pkpgcounter / trunk / pkpgpdls / newpcl345.py @ 394

Revision 394, 34.2 kB (checked in by jerome, 16 years ago)

Improved logging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
6# (c) 2003, 2004, 2005, 2006 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20#
21# $Id$
22#
23
24"""This modules implements a page counter for PCL3/4/5 documents."""
25
26import sys
27import os
28import mmap
29from struct import unpack
30
31import pdlparser
32import pjl
33
34FORMFEED = chr(12)
35ESCAPE = chr(27)
36
37class Parser(pdlparser.PDLParser) :
38    """A parser for PCL3, PCL4, PCL5 documents."""
39    totiffcommand = 'pcl6 -sDEVICE=pdfwrite -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- - | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(fname)s" -'
40    mediasizes = {  # ESC&l####A
41                    0 : "Default",
42                    1 : "Executive",
43                    2 : "Letter",
44                    3 : "Legal",
45                    6 : "Ledger", 
46                    25 : "A5",
47                    26 : "A4",
48                    27 : "A3",
49                    45 : "JB5",
50                    46 : "JB4",
51                    71 : "HagakiPostcard",
52                    72 : "OufukuHagakiPostcard",
53                    80 : "MonarchEnvelope",
54                    81 : "COM10Envelope",
55                    90 : "DLEnvelope",
56                    91 : "C5Envelope",
57                    100 : "B5Envelope",
58                    101 : "Custom",
59                 }   
60                 
61    mediasources = { # ESC&l####H
62                     0 : "Default",
63                     1 : "Main",
64                     2 : "Manual",
65                     3 : "ManualEnvelope",
66                     4 : "Alternate",
67                     5 : "OptionalLarge",
68                     6 : "EnvelopeFeeder",
69                     7 : "Auto",
70                     8 : "Tray1",
71                   }
72                   
73    orientations = { # ESC&l####O
74                     0 : "Portrait",
75                     1 : "Landscape",
76                     2 : "ReversePortrait",
77                     3 : "ReverseLandscape",
78                   }
79                   
80    mediatypes = { # ESC&l####M
81                     0 : "Plain",
82                     1 : "Bond",
83                     2 : "Special",
84                     3 : "Glossy",
85                     4 : "Transparent",
86                   }
87       
88    def isValid(self) :   
89        """Returns True if data is PCL3/4/5, else False."""
90        if self.firstblock.startswith("\033E\033") or \
91           (self.firstblock.startswith("\033*rbC") and (not self.lastblock[-3:] == "\f\033@")) or \
92           self.firstblock.startswith("\033%8\033") or \
93           (self.firstblock.find("\033%-12345X") != -1) or \
94           (self.firstblock.find("@PJL ENTER LANGUAGE=PCL\012\015\033") != -1) or \
95           (self.firstblock.startswith(chr(0xcd)+chr(0xca)) and self.firstblock.find("\033E\033")) :
96            self.logdebug("DEBUG: Input file is in the PCL3/4/5 format.")
97            return True
98        else :   
99            return False
100       
101    def setPageDict(self, pages, number, attribute, value) :
102        """Initializes a page dictionnary."""
103        dic = pages.setdefault(number, { "copies" : 1, "mediasource" : "Main", "mediasize" : "Default", "mediatype" : "Plain", "orientation" : "Portrait", "escaped" : "", "duplex": 0})
104        dic[attribute] = value
105       
106    def readByte(self) :   
107        """Reads a byte from the input stream."""
108        tag = ord(self.minfile[self.pos])
109        self.pos += 1
110        self.logdebug("BYTE %02x" % tag)
111        return tag
112       
113    def endPage(self) :   
114        """Handle the FF marker."""
115        self.logdebug("FORMFEED %i" % self.pagecount)
116        self.pagecount += 1
117       
118    def escPercent(self) :   
119        """Handles the ESC% sequence."""
120        if self.minfile[self.pos : self.pos+7] == r"-12345X" :
121            self.logdebug("Generic ESCAPE sequence at %08x" % self.pos)
122            self.pos += 7
123       
124    def handleTag(self, tagtable) :   
125        """Handles tags."""
126        tagtable[self.readByte()]()
127       
128    def escape(self) :   
129        """Handles the ESC character."""
130        self.logdebug("ESCAPE")
131        self.handleTag(self.esctags)
132       
133    def escAmp(self) :   
134        """Handles the ESC& sequence."""
135        self.logdebug("AMP")
136        self.handleTag(self.escamptags)
137       
138    def escStar(self) :   
139        """Handles the ESC* sequence."""
140        self.logdebug("STAR")
141        self.handleTag(self.escstartags)
142       
143    def escLeftPar(self) :   
144        """Handles the ESC( sequence."""
145        self.logdebug("LEFTPAR")
146        self.handleTag(self.escleftpartags)
147       
148    def escRightPar(self) :   
149        """Handles the ESC( sequence."""
150        self.logdebug("RIGHTPAR")
151        self.handleTag(self.escrightpartags)
152       
153    def escE(self) :   
154        """Handles the ESCE sequence."""
155        self.logdebug("RESET")
156        self.resets += 1
157       
158    def escAmpl(self) :   
159        """Handles the ESC&l sequence."""
160        self.logdebug("l")
161        while 1 :
162            (value, end) = self.getInteger()
163            if value is None :
164                return
165            if end in ('h', 'H') :
166                mediasource = self.mediasources.get(value, str(value))
167                self.mediasourcesvalues.append(mediasource)
168                self.logdebug("MEDIASOURCE %s" % mediasource)
169            elif end in ('a', 'A') :
170                mediasize = self.mediasizes.get(value, str(value))
171                self.mediasizesvalues.append(mediasize)
172                self.logdebug("MEDIASIZE %s" % mediasize)
173            elif end in ('o', 'O') :
174                orientation = self.orientations.get(value, str(value))
175                self.orientationsvalues.append(orientation)
176                self.logdebug("ORIENTATION %s" % orientation)
177            elif end in ('m', 'M') :
178                mediatype = self.mediatypes.get(value, str(value))
179                self.mediatypesvalues.append(mediatype)
180                self.logdebug("MEDIATYPE %s" % mediatype)
181            elif end == 'X' :
182                self.copies.append(value)
183                self.logdebug("COPIES %i" % value)
184            elif end == 'L' :   
185                self.logdebug("ESC&l%iL" % value)
186               
187    def escStarb(self) :   
188        """Handles the ESC*b sequence."""
189        self.logdebug("b")
190        while 1 :
191            (value, end) = self.getInteger()
192            self.logdebug("%s === %s" % (value, end))
193            if (end is None) and (value is None) :
194                return
195            if end in ('V', 'W', 'v', 'w') :   
196                self.pos += (value or 0)
197                self.logdebug("SKIPTO %08x" % self.pos)
198               
199    def escStaro(self) :   
200        """Handles the ESC*o sequence."""
201        self.logdebug("o")
202        while 1 :
203            (value, end) = self.getInteger()
204            if value is None :
205                return
206            if end == 'M' :
207                self.logdebug("ESC*o%iM" % value)
208               
209    def escStarp(self) :   
210        """Handles the ESC*p sequence."""
211        self.logdebug("p")
212        while 1 :
213            (value, end) = self.getInteger()
214            if value is None :
215                return
216            if end in ('X', 'Y') :   
217                self.logdebug("ESC*p%i%s" % (value, end))
218               
219    def escStarr(self) :   
220        """Handles the ESC*r sequence."""
221        self.logdebug("r")
222        while 1 :
223            (value, end) = self.getInteger()
224            if value is None :
225                if end is None :
226                    return
227                elif end == 'b' :
228                    if self.minfile[self.pos] == 'C' :
229                        self.logdebug("Looks like it's PCL3.")
230                        self.ispcl3 = True
231                        self.pos += 1
232                elif end == 'C' :       
233                    self.logdebug("EndGFX")
234                    if not self.startgfx :
235                        self.logdebug("EndGFX found before StartGFX, ignored.")
236                    else :   
237                        self.endgfx.append(1)
238            if end == 'A' and (0 <= value <= 3) :
239                self.logdebug("StartGFX %i" % value)
240                self.startgfx.append(value)
241            elif end == 'U' :   
242                self.logdebug("ESC*r%iU" % value)
243            elif end == 'S' :   
244                self.logdebug("ESC*r%iS" % value)
245               
246    def escStart(self) :   
247        """Handles the ESC*t sequence."""
248        self.logdebug("t")
249        while 1 :
250            (value, end) = self.getInteger()
251            if value is None :
252                return
253            if end == 'R' :   
254                self.logdebug("ESC*t%iR" % value)
255               
256    def escAmpu(self) :   
257        """Handles the ESC&u sequence."""
258        self.logdebug("u")
259        while 1 :
260            (value, end) = self.getInteger()
261            if value is None :
262                return
263            if end == 'D' :   
264                self.logdebug("ESC&u%iD" % value)
265               
266       
267    def getInteger(self) :   
268        """Returns an integer value and the end character."""
269        sign = 1
270        value = None
271        while 1 :
272            char = chr(self.readByte())
273            if char == ESCAPE :
274                self.pos -= 1 # Adjust position
275                return (None, None)
276            if char == '-' :
277                sign = -1
278            elif not char.isdigit() :
279                if value is not None :
280                    return (sign*value, char)
281                else :
282                    return (value, char)
283            else :   
284                value = ((value or 0) * 10) + int(char)   
285       
286    def getJobSize(self) :     
287        """Count pages in a PCL5 document.
288         
289           Should also work for PCL3 and PCL4 documents.
290           
291           Algorithm from pclcount
292           (c) 2003, by Eduardo Gielamo Oliveira & Rodolfo Broco Manin
293           published under the terms of the GNU General Public Licence v2.
294         
295           Backported from C to Python by Jerome Alet, then enhanced
296           with more PCL tags detected. I think all the necessary PCL tags
297           are recognized to correctly handle PCL5 files wrt their number
298           of pages. The documentation used for this was :
299         
300           HP PCL/PJL Reference Set
301           PCL5 Printer Language Technical Quick Reference Guide
302           http://h20000.www2.hp.com/bc/docs/support/SupportManual/bpl13205/bpl13205.pdf
303        """
304        infileno = self.infile.fileno()
305        self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED)
306        self.ispcl3 = False
307        self.pagecount = 0
308        self.resets = 0
309        self.copies = []
310        self.mediasourcesvalues = []
311        self.mediasizesvalues = []
312        self.orientationsvalues = []
313        self.mediatypesvalues = []
314        self.startgfx = []
315        self.endgfx = []
316       
317        tags = [ lambda : None] * 256
318        tags[ord(FORMFEED)] = self.endPage
319        tags[ord(ESCAPE)] = self.escape
320       
321        self.esctags = [ lambda : None ] * 256
322        self.esctags[ord('%')] = self.escPercent
323        self.esctags[ord('*')] = self.escStar
324        self.esctags[ord('&')] = self.escAmp
325        self.esctags[ord('(')] = self.escLeftPar
326        self.esctags[ord(')')] = self.escRightPar
327        self.esctags[ord('E')] = self.escE
328       
329        self.escamptags = [lambda : None ] * 256
330        self.escamptags[ord('l')] = self.escAmpl
331        self.escamptags[ord('u')] = self.escAmpu
332       
333        self.escstartags = [ lambda : None ] * 256
334        self.escstartags[ord('b')] = self.escStarb
335        self.escstartags[ord('o')] = self.escStaro
336        self.escstartags[ord('p')] = self.escStarp
337        self.escstartags[ord('r')] = self.escStarr
338        self.escstartags[ord('t')] = self.escStart
339       
340        self.pos = 0
341        try :
342            try :
343                while 1 :
344                    tag = self.readByte()
345                    self.logdebug("%08x ===> %02x" % (self.pos-1, tag))
346                    tags[tag]()
347            except IndexError : # EOF ?           
348                pass
349        finally :
350            self.minfile.close()
351       
352            self.logdebug("Pagecount : \t\t%i" % self.pagecount)
353            self.logdebug("Resets : \t\t%i" % self.resets)
354            self.logdebug("Copies : \t\t%s" % self.copies)
355            self.logdebug("MediaTypes : \t\t%s" % self.mediatypesvalues)
356            self.logdebug("MediaSizes : \t\t%s" % self.mediasizesvalues)
357            self.logdebug("MediaSources : \t\t%s" % self.mediasourcesvalues)
358            self.logdebug("Orientations : \t\t%s" % self.orientationsvalues)
359            self.logdebug("StartGfx : \t\t%s" % len(self.startgfx))
360            self.logdebug("EndGfx : \t\t%s" % len(self.endgfx))
361       
362        return self.pagecount
363       
364       
365       
366        """
367        tagsends = { "&n" : "W",
368                     "&b" : "W",
369                     "*i" : "W",
370                     "*l" : "W",
371                     "*m" : "W",
372                     "*v" : "W",
373                     "*c" : "W",
374                     "(f" : "W",
375                     "(s" : "W",
376                     ")s" : "W",
377                     "&p" : "X",
378                     # "&l" : "XHAOM",  # treated specially
379                     "&a" : "G", # TODO : 0 means next side, 1 front side, 2 back side
380                     "*g" : "W",
381                     "*r" : "sbABC",
382                     "*t" : "R",
383                     # "*b" : "VW", # treated specially because it occurs very often
384                   } 
385        irmarker = chr(0xcd) + chr(0xca) # Marker for Canon ImageRunner printers
386        irmarker2 = chr(0x10) + chr(0x02)
387        wasirmarker = 0
388        hasirmarker = (minfile[:2] == (irmarker))
389        pagecount = resets = ejects = backsides = startgfx = endgfx = 0
390        starb = ampl = ispcl3 = escstart = 0
391        mediasourcecount = mediasizecount = orientationcount = mediatypecount = 0
392        tag = None
393        endmark = chr(0x1b) + chr(0x0c) + chr(0x00)
394        asciilimit = chr(0x80)
395        pages = {}
396        pos = 0
397        try :
398            try :
399                while 1 :
400                    if hasirmarker and (minfile[pos:pos+2] == irmarker) :
401                        codop = minfile[pos+2:pos+4]
402                        # self.logdebug("Marker at 0x%08x     (%s)" % (pos, wasirmarker))
403                        length = unpack(">H", minfile[pos+8:pos+10])[0]
404                        pos += 20
405                        if codop != irmarker2 :
406                            pos += length
407                        wasirmarker = 1   
408                    else :       
409                        wasirmarker = 0
410                        elif char == "\033" :   
411                            starb = ampl = 0
412                            if minfile[pos : pos+8] == r"%-12345X" :
413                                endpos = pos + 9
414                                quotes = 0
415                                while (minfile[endpos] not in endmark) and \
416                                      ((minfile[endpos] < asciilimit) or (quotes % 2)) :
417                                    if minfile[endpos] == '"' :
418                                        quotes += 1
419                                    endpos += 1
420                                self.setPageDict(pages, pagecount, "escaped", minfile[pos : endpos])
421                                pos += (endpos - pos)
422                            else :
423                                #
424                                #     <ESC>*b###y#m###v###w... -> PCL3 raster graphics
425                                #     <ESC>*b###W -> Start of a raster data row/block
426                                #     <ESC>*b###V -> Start of a raster data plane
427                                #     <ESC>*c###W -> Start of a user defined pattern
428                                #     <ESC>*i###W -> Start of a viewing illuminant block
429                                #     <ESC>*l###W -> Start of a color lookup table
430                                #     <ESC>*m###W -> Start of a download dither matrix block
431                                #     <ESC>*v###W -> Start of a configure image data block
432                                #     <ESC>*r1A -> Start Gfx
433                                #     <ESC>(s###W -> Start of a characters description block
434                                #     <ESC>)s###W -> Start of a fonts description block
435                                #     <ESC>(f###W -> Start of a symbol set block
436                                #     <ESC>&b###W -> Start of configuration data block
437                                #     <ESC>&l###X -> Number of copies for current page
438                                #     <ESC>&n###W -> Starts an alphanumeric string ID block
439                                #     <ESC>&p###X -> Start of a non printable characters block
440                                #     <ESC>&a2G -> Back side when duplex mode as generated by rastertohp
441                                #     <ESC>*g###W -> Needed for planes in PCL3 output
442                                #     <ESC>&l###H (or only 0 ?) -> Eject if NumPlanes > 1, as generated by rastertohp. Also defines mediasource
443                                #     <ESC>&l###A -> mediasize
444                                #     <ESC>&l###O -> orientation
445                                #     <ESC>&l###M -> mediatype
446                                #     <ESC>*t###R -> gfx resolution
447                                #
448                                tagstart = minfile[pos] ; pos += 1
449                                if tagstart in "E9=YZ" : # one byte PCL tag
450                                    if tagstart == "E" :
451                                        resets += 1
452                                    continue             # skip to next tag
453                                tag = tagstart + minfile[pos] ; pos += 1
454                                if tag == "*b" :
455                                    starb = 1
456                                    tagend = "VW"
457                                elif tag == "&l" :   
458                                    ampl = 1
459                                    tagend = "XHAOM"
460                                else :   
461                                    try :
462                                        tagend = tagsends[tag]
463                                    except KeyError :   
464                                        continue # Unsupported PCL tag
465                                # Now read the numeric argument
466                                size = 0
467                                while 1 :
468                                    char = minfile[pos] ; pos += 1
469                                    if not char.isdigit() :
470                                        break
471                                    size = (size * 10) + int(char)   
472                                if char in tagend :   
473                                    if tag == "&l" :
474                                        if char == "X" :
475                                            self.setPageDict(pages, pagecount, "copies", size)
476                                        elif char == "H" :
477                                            self.setPageDict(pages, pagecount, "mediasource", self.mediasources.get(size, str(size)))
478                                            mediasourcecount += 1
479                                            ejects += 1
480                                        elif char == "A" :
481                                            self.setPageDict(pages, pagecount, "mediasize", self.mediasizes.get(size, str(size)))
482                                            mediasizecount += 1
483                                        elif char == "O" :
484                                            self.setPageDict(pages, pagecount, "orientation", self.orientations.get(size, str(size)))
485                                            orientationcount += 1
486                                        elif char == "M" :
487                                            self.setPageDict(pages, pagecount, "mediatype", self.mediatypes.get(size, str(size)))
488                                            mediatypecount += 1
489                                    elif tag == "*r" :
490                                        # Special tests for PCL3
491                                        if (char == "s") and size :
492                                            while 1 :
493                                                char = minfile[pos] ; pos += 1
494                                                if char == "A" :
495                                                    break
496                                        elif (char == "b") and (minfile[pos] == "C") and not size :
497                                            ispcl3 = 1 # Certainely a PCL3 file
498                                        startgfx += (char == "A") and (minfile[pos - 2] in ("0", "1", "2", "3")) # Start Gfx
499                                        endgfx += (not size) and (char in ("C", "B")) # End Gfx
500                                    elif tag == "*t" :   
501                                        escstart += 1
502                                    elif (tag == "&a") and (size == 2) :
503                                        # We are on the backside, so mark current page as duplex
504                                        self.setPageDict(pages, pagecount, "duplex", 1)
505                                        backsides += 1      # Back side in duplex mode
506                                    else :   
507                                        # we just ignore the block.
508                                        if tag == "&n" :
509                                            # we have to take care of the operation id byte
510                                            # which is before the string itself
511                                            size += 1
512                                        pos += size   
513                        else :                           
514                            if starb :
515                                # special handling of PCL3 in which
516                                # *b introduces combined ESCape sequences
517                                size = 0
518                                while 1 :
519                                    char = minfile[pos] ; pos += 1
520                                    if not char.isdigit() :
521                                        break
522                                    size = (size * 10) + int(char)   
523                                if char in ("w", "v") :   
524                                    ispcl3 = 1  # certainely a PCL3 document
525                                    pos += size - 1
526                                elif char in ("y", "m") :   
527                                    ispcl3 = 1  # certainely a PCL3 document
528                                    pos -= 1    # fix position : we were ahead
529                            elif ampl :       
530                                # special handling of PCL3 in which
531                                # &l introduces combined ESCape sequences
532                                size = 0
533                                while 1 :
534                                    char = minfile[pos] ; pos += 1
535                                    if not char.isdigit() :
536                                        break
537                                    size = (size * 10) + int(char)   
538                                if char in ("a", "o", "h", "m") :   
539                                    ispcl3 = 1  # certainely a PCL3 document
540                                    pos -= 1    # fix position : we were ahead
541                                    if char == "h" :
542                                        self.setPageDict(pages, pagecount, "mediasource", self.mediasources.get(size, str(size)))
543                                        mediasourcecount += 1
544                                    elif char == "a" :
545                                        self.setPageDict(pages, pagecount, "mediasize", self.mediasizes.get(size, str(size)))
546                                        mediasizecount += 1
547                                    elif char == "o" :
548                                        self.setPageDict(pages, pagecount, "orientation", self.orientations.get(size, str(size)))
549                                        orientationcount += 1
550                                    elif char == "m" :
551                                        self.setPageDict(pages, pagecount, "mediatype", self.mediatypes.get(size, str(size)))
552                                        mediatypecount += 1
553            except IndexError : # EOF ?
554                pass
555        finally :
556            minfile.close()
557                           
558        # if pagecount is still 0, we will use the number
559        # of resets instead of the number of form feed characters.
560        # but the number of resets is always at least 2 with a valid
561        # pcl file : one at the very start and one at the very end
562        # of the job's data. So we substract 2 from the number of
563        # resets. And since on our test data we needed to substract
564        # 1 more, we finally substract 3, and will test several
565        # PCL files with this. If resets < 2, then the file is
566        # probably not a valid PCL file, so we use 0
567       
568        if self.debug :
569            sys.stderr.write("pagecount : %s\n" % pagecount)
570            sys.stderr.write("resets : %s\n" % resets)
571            sys.stderr.write("ejects : %s\n" % ejects)
572            sys.stderr.write("backsides : %s\n" % backsides)
573            sys.stderr.write("startgfx : %s\n" % startgfx)
574            sys.stderr.write("endgfx : %s\n" % endgfx)
575            sys.stderr.write("mediasourcecount : %s\n" % mediasourcecount)
576            sys.stderr.write("mediasizecount : %s\n" % mediasizecount)
577            sys.stderr.write("orientationcount : %s\n" % orientationcount)
578            sys.stderr.write("mediatypecount : %s\n" % mediatypecount)
579            sys.stderr.write("escstart : %s\n" % escstart)
580            sys.stderr.write("hasirmarker : %s\n" % hasirmarker)
581       
582        if hasirmarker :
583            self.logdebug("Rule #20 (probably a Canon ImageRunner)")
584            pagecount += 1
585        elif (orientationcount == (pagecount - 1)) and (resets == 1) :
586            if resets == ejects == startgfx == mediasourcecount == escstart == 1 :
587                self.logdebug("Rule #19")
588            else :   
589                self.logdebug("Rule #1")
590                pagecount -= 1
591        elif pagecount and (pagecount == orientationcount) :
592            self.logdebug("Rule #2")
593        elif resets == ejects == mediasourcecount == mediasizecount == escstart == 1 :
594            #if ((startgfx and endgfx) and (startgfx != endgfx)) or (startgfx == endgfx == 0) :
595            if (startgfx and endgfx) or (startgfx == endgfx == 0) :
596                self.logdebug("Rule #3")
597                pagecount = orientationcount
598            elif (endgfx and not startgfx) and (pagecount > orientationcount) :   
599                self.logdebug("Rule #4")
600                pagecount = orientationcount
601            else :     
602                self.logdebug("Rule #5")
603                pagecount += 1
604        elif (ejects == mediasourcecount == orientationcount) and (startgfx == endgfx) :     
605            if (resets == 2) and (orientationcount == (pagecount - 1)) and (orientationcount > 1) :
606                self.logdebug("Rule #6")
607                pagecount = orientationcount
608        elif pagecount == mediasourcecount == escstart :
609            self.logdebug("Rule #7")
610        elif resets == startgfx == endgfx == mediasizecount == orientationcount == escstart == 1 :     
611            self.logdebug("Rule #8")
612        elif resets == startgfx == endgfx == (pagecount - 1) :   
613            self.logdebug("Rule #9")
614        elif (not startgfx) and (not endgfx) :
615            self.logdebug("Rule #10")
616        elif (resets == 2) and (startgfx == endgfx) and (mediasourcecount == 1) :
617            if orientationcount == (pagecount - 1) :
618                self.logdebug("Rule #11")
619                pagecount = orientationcount
620            elif not pagecount :   
621                self.logdebug("Rule #17")
622                pagecount = ejects
623        elif (resets == 1) and (startgfx == endgfx) and (mediasourcecount == 0) :
624            if (startgfx > 1) and (startgfx != (pagecount - 1)) :
625                self.logdebug("Rule #12")
626                pagecount -= 1
627            else :   
628                self.logdebug("Rule #18")
629        elif startgfx == endgfx :   
630            self.logdebug("Rule #13")
631            pagecount = startgfx
632        elif startgfx == (endgfx - 1) :   
633            self.logdebug("Rule #14")
634            pagecount = startgfx
635        elif (startgfx == 1) and not endgfx :   
636            self.logdebug("Rule #15")
637            pass
638        else :   
639            self.logdebug("Rule #16")
640            pagecount = abs(startgfx - endgfx)
641           
642        defaultpjlcopies = 1   
643        defaultduplexmode = "Simplex"
644        defaultpapersize = ""
645        oldpjlcopies = -1
646        oldduplexmode = ""
647        oldpapersize = ""
648        for pnum in range(pagecount) :
649            # if no number of copies defined, take the preceding one else the one set before any page else 1.
650            page = pages.get(pnum, pages.get(pnum - 1, pages.get(0, { "copies" : 1, "mediasource" : "Main", "mediasize" : "Default", "mediatype" : "Plain", "orientation" : "Portrait", "escaped" : "", "duplex": 0})))
651            pjlstuff = page["escaped"]
652            if pjlstuff :
653                pjlparser = pjl.PJLParser(pjlstuff)
654                nbdefaultcopies = int(pjlparser.default_variables.get("COPIES", -1))
655                nbcopies = int(pjlparser.environment_variables.get("COPIES", -1))
656                nbdefaultqty = int(pjlparser.default_variables.get("QTY", -1))
657                nbqty = int(pjlparser.environment_variables.get("QTY", -1))
658                if nbdefaultcopies > -1 :
659                    defaultpjlcopies = nbdefaultcopies
660                if nbdefaultqty > -1 :
661                    defaultpjlcopies = nbdefaultqty
662                if nbcopies > -1 :
663                    pjlcopies = nbcopies
664                elif nbqty > -1 :
665                    pjlcopies = nbqty
666                else :
667                    if oldpjlcopies == -1 :   
668                        pjlcopies = defaultpjlcopies
669                    else :   
670                        pjlcopies = oldpjlcopies   
671                if page["duplex"] :       
672                    duplexmode = "Duplex"
673                else :   
674                    defaultdm = pjlparser.default_variables.get("DUPLEX", "")
675                    if defaultdm :
676                        if defaultdm.upper() == "ON" :
677                            defaultduplexmode = "Duplex"
678                        else :   
679                            defaultduplexmode = "Simplex"
680                    envdm = pjlparser.environment_variables.get("DUPLEX", "")
681                    if envdm :
682                        if envdm.upper() == "ON" :
683                            duplexmode = "Duplex"
684                        else :   
685                            duplexmode = "Simplex"
686                    else :       
687                        duplexmode = oldduplexmode or defaultduplexmode
688                defaultps = pjlparser.default_variables.get("PAPER", "")
689                if defaultps :
690                    defaultpapersize = defaultps
691                envps = pjlparser.environment_variables.get("PAPER", "")
692                if envps :
693                    papersize = envps
694                else :   
695                    if not oldpapersize :
696                        papersize = defaultpapersize
697                    else :   
698                        papersize = oldpapersize
699            else :       
700                if oldpjlcopies == -1 :
701                    pjlcopies = defaultpjlcopies
702                else :   
703                    pjlcopies = oldpjlcopies
704               
705                duplexmode = (page["duplex"] and "Duplex") or oldduplexmode or defaultduplexmode
706                if not oldpapersize :   
707                    papersize = defaultpapersize
708                else :   
709                    papersize = oldpapersize
710                papersize = oldpapersize or page["mediasize"]
711            if page["mediasize"] != "Default" :
712                papersize = page["mediasize"]
713            if not duplexmode :   
714                duplexmode = oldduplexmode or defaultduplexmode
715            oldpjlcopies = pjlcopies   
716            oldduplexmode = duplexmode
717            oldpapersize = papersize
718            copies = pjlcopies * page["copies"]       
719            pagecount += (copies - 1)
720            self.logdebug("%s*%s*%s*%s*%s*%s*BW" % (copies, \
721                                              page["mediatype"], \
722                                              papersize, \
723                                              page["orientation"], \
724                                              page["mediasource"], \
725                                              duplexmode))
726               
727        return pagecount
728        """
729       
730def test() :       
731    """Test function."""
732    if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) :
733        sys.argv.append("-")
734    totalsize = 0   
735    for arg in sys.argv[1:] :
736        if arg == "-" :
737            infile = sys.stdin
738            mustclose = 0
739        else :   
740            infile = open(arg, "rb")
741            mustclose = 1
742        try :
743            parser = Parser(infile, debug=1)
744            totalsize += parser.getJobSize()
745        except pdlparser.PDLParserError, msg :   
746            sys.stderr.write("ERROR: %s\n" % msg)
747            sys.stderr.flush()
748        if mustclose :   
749            infile.close()
750    print "%s" % totalsize
751   
752if __name__ == "__main__" :   
753    test()
Note: See TracBrowser for help on using the browser.