root / pkpgcounter / trunk / pkpgpdls / pjl.py @ 563

Revision 563, 5.9 kB (checked in by jerome, 16 years ago)

Now correctly ignores the EOJ statement and the PCLXL marker statement.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[252]1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
[443]6# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
[463]7# This program is free software: you can redistribute it and/or modify
[252]8# it under the terms of the GNU General Public License as published by
[463]9# the Free Software Foundation, either version 3 of the License, or
[252]10# (at your option) any later version.
[463]11#
[252]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
[463]18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
[252]19#
20# $Id$
21#
22
[472]23"""This modules implements a really minimalist PJL/EJL parser."""
[357]24
[454]25# NOTES : QTY= is the number of collated copies for a job.
26# NOTES : COPIES= is the number of uncollated copies for each page of a job
27
[252]28import sys
29
30class PJLParserError(Exception):
31    """An exception for PJLParser related stuff."""
32    def __init__(self, message = ""):
33        self.message = message
34        Exception.__init__(self, message)
35    def __repr__(self):
36        return self.message
37    __str__ = __repr__
38       
39class PJLParser :
40    """A parser for PJL documents.
41   
[455]42       Information extracted for bpl11897.pdf which was
[454]43       downloaded from Hewlett-Packard's website.
[252]44    """
[472]45    JL = "PJL"
[252]46    def __init__(self, pjljob, debug=0) :
[472]47        """Initializes JL Parser."""
[252]48        self.debug = debug
[472]49        self.jlmarker = "@%s" % self.JL
[252]50        self.statements = pjljob.replace("\r\n", "\n").split("\n")
51        self.default_variables = {}
52        self.environment_variables = {}
53        self.parsed = 0
54        self.parse()
55       
56    def __str__(self) :   
57        """Outputs our variables as a string of text."""
58        if not self.parsed :
59            return ""
60        mybuffer = []
61        if self.default_variables :
62            mybuffer.append("Default variables :")
63            for (k, v) in self.default_variables.items() :
64                mybuffer.append("  %s : %s" % (k, v))
65        if self.environment_variables :       
66            mybuffer.append("Environment variables :")
67            for (k, v) in self.environment_variables.items() :
68                mybuffer.append("  %s : %s" % (k, v))
69        return "\n".join(mybuffer)       
70           
71    def logdebug(self, message) :   
72        """Logs a debug message if needed."""
73        if self.debug :
74            sys.stderr.write("%s\n" % message)
75           
76    def cleanvars(self) :       
77        """Cleans the variables dictionnaries."""
78        for dicname in ("default", "environment") :
79            varsdic = getattr(self, "%s_variables" % dicname)
80            for (k, v) in varsdic.items() :
81                if len(v) == 1 :
82                    varsdic[k] = v[0]
83       
84    def parse(self) :
[472]85        """Parses a JL job."""
[252]86        for i in range(len(self.statements)) :
87            statement = self.statements[i]
[472]88            if statement.startswith(self.jlmarker) :
[252]89                parts = statement.split()
90                nbparts = len(parts)
[472]91                if parts[0] == self.jlmarker :
92                    # this is a valid JL statement, but we don't
[252]93                    # want to examine all of them...
[472]94                    if (nbparts > 2) \
95                         and ((parts[1].upper() in ("SET", "DEFAULT")) \
96                                  or ((self.jlmarker == "@EJL") and (parts[1].upper() == "JI"))) :
[252]97                        # this is what we are interested in !
98                        try :   
[472]99                            (varname, value) = "".join(parts[2:]).split("=", 1) # TODO : parse multiple assignments on the same SET/JI statement
[252]100                        except :   
[472]101                            self.logdebug("Invalid JL SET statement [%s]" % repr(statement))
[252]102                        else :   
103                            # all still looks fine...
104                            if parts[1].upper() == "DEFAULT" :
105                                varsdic = self.default_variables
106                            else :   
107                                varsdic = self.environment_variables 
108                            variable = varsdic.setdefault(varname.upper(), [])
109                            variable.append(value)
110                    else :
[472]111                        self.logdebug("Ignored JL statement [%s]" % repr(statement))
112                        self.logdebug(parts)
[252]113                else :
[472]114                    self.logdebug("Invalid JL statement [%s]" % repr(statement))
[563]115            elif (not statement) \
116                  or (statement == r"%-12345X@PJL EOJ") \
117                  or statement[2:].startswith("HP-PCL XL;") :
118                self.logdebug("Ignored JL statement [%s]" % repr(statement))
[252]119            else :
[472]120                self.logdebug("Invalid JL statement [%s]" % repr(statement))
[252]121        self.cleanvars()
122        self.parsed = 1
[563]123        # self.logdebug("%s\n" % str(self))
[252]124       
[472]125class EJLParser(PJLParser) :
126    """A parser for EJL (Epson Job Language) documents."""
127    JL = "EJL"
128       
[252]129def test() :       
130    """Test function."""
131    if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) :
132        sys.argv.append("-")
133    for arg in sys.argv[1:] :
[472]134        klass = PJLParser
[252]135        if arg == "-" :
136            infile = sys.stdin
137            mustclose = 0
138        else :   
[472]139            if arg.endswith(".ejl") :
140                klass = EJLParser
[252]141            infile = open(arg, "rb")
142            mustclose = 1
143        try :
[472]144            parser = klass(infile.read(), debug=1)
[252]145        except PJLParserError, msg :   
146            sys.stderr.write("ERROR: %s\n" % msg)
147            sys.stderr.flush()
148        if mustclose :   
149            infile.close()
150        print str(parser)           
151   
152if __name__ == "__main__" :   
153    test()
Note: See TracBrowser for help on using the browser.