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

Revision 3474, 5.7 kB (checked in by jerome, 15 years ago)

Changed copyright years.

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