One of the things I need to do on a regular basis is check the JMD of an installation, when things don’t seem to be running as they should. More often than not, someone edited the JMD by hand, missed a quote mark – causing havoc with the table alignments.
At other times I just want to be able to read the JMD so that I know what steps are being taken, without having to load/reload various JMDs. And trust me, reading a raw JMD is not fun…
So I came up with the following python script. I’ll be putting it on my personal website at some point, so you can use it there too. In the mean time, have a go at this, if you have a Python CGI server… TableJMD 0.2a
The following highlighting is a backup taken from the corresponging pygments.org post – in case it gets deleted from pygments.org one day…
#! /Program Files/Python25/python import re,sys,cgi helpnote = """Table JMD 1.1 (C) 2009 Tai Kedzierski http://blogs.adobe.com/an_tai/ This tool reads a JMD and writes HTML to STDOUT representing the JMD in a table, as it would be parsed by Central's JfServer. It also highlights substitution variables not surrounded by double quote marks. This can either be used from the command line, or as a CGI script on a web site. From the command line, type: python tablejmd.py PATH where PATH is the path to the JMD file """ class JMDInvalidLine(Exception): def __init__(self,message): Exception.__init__(self,message)# = "The line was invalid" # don't fail silently! sys.stderr = sys.stdout def readjmdfile(filename): readjmd( open(filename,'rU') ) def readjmd(fileh): jmdline = '.' job_t = dict() task_t = dict() print_t = dict() memory_t = dict() while jmdline: line = fileh.readline() if line == '': # EOF break if re.match(r'(^#)|(^\s*$)',line): # comment or empty line continue jmdline = jmdsplit(line) if jmdline == None: print "<p>Error parsing line: %s</p>" % (line,) continue if jmdline[0] == '!f': if job_t.has_key(jmdline[1] ): job_t[jmdline[1] ].append(jmdline) else: job_t[jmdline[1] ] = [jmdline] elif jmdline[0] == '!x': if task_t.has_key(jmdline[1] ): task_t[jmdline[1] ].append(jmdline) else: task_t[jmdline[1] ] = [jmdline] elif jmdline[0] == '!p': if print_t.has_key(jmdline[1] ): print_t[jmdline[1] ].append(jmdline) else: print_t[jmdline[1] ] = [jmdline] elif jmdline[0] == '!m': if memory_t.has_key(jmdline[1] ): memory_t[jmdline[1] ].append(jmdline) else: memory_t[jmdline[1] ] = [jmdline] print "<h2>Job table ["+str(len(job_t))+" entries]</h2>" print "<table><tbody>" print r'<th>Job name</th> <th>Printer name</th> <th>Form file</th> <th>Preamble file</th> <th>Macro number</th> <th>Load flag</th> <th>Task id</th> <th>Input file</th> <th>Output file</th> <th>On error</th> <th>Comments</th>' dumptablelines(job_t) print "</tbody></table>" print "<h2>Task table ["+str(len(task_t))+" entries]</h2>" print '<p><font color="blue">Blue</font>: not surrounded by doubled double-quotes<br /><font color="red">Red</font>: substitution name does not end with "."</p>' print "<table><tbody>" print r'<th>Task id</th> <th>[This column reserved]</th> <th>Program name</th> <th>Program options</th> <th>Comments</th>' dumptablelines(task_t) print "</tbody></table>" print "<h2>Printer table ["+str(len(print_t))+" entries]</h2>" print "<table><tbody>" print r'<th>Printer name</th> <th>Printer id</th> <th>Physical device</th> <th>Print agent options</th> <th>Priority</th> <th>Comments</th>' dumptablelines(print_t) print "</tbody></table>" print "<h2>Managed Memory table ["+str(len(memory_t))+" entries]</h2>" print "<table><tbody>" print r'<th>Printer id</th> <th>Managed Memory [bytes]</th> <th>Comments</th>' dumptablelines(memory_t) print "</tbody></table>" def dumptablelines(table_t): keyset = table_t.keys() keyset.sort() for entryset in keyset: for entry in range(len(table_t[entryset])): print "<tr>" for col in range(1,len(table_t[entryset][entry]) ): print "<td>",table_t[entryset][entry][col],"</td>", print "</tr>" def jmdsplit(line): '''INPUT: a line of text from the JMD OUTPUT: the line, tokenized into a list ''' if line[0] != '!':# any meaningful line must start with '!' return None oline = line if not line[1] in [ 'f', # job 'x', # task 'p', # printer 'm']: # shared memory raise JMDInvalidLine(line) jmdline = [] try: while line: token, line = readfirsttoken(line) token = atprocess(token) # identify substitution variables and possible errors jmdline.append(token) except JMDInvalidLine,msg: print msg,':',oline return jmdline def atprocess(token): pat = re.compile(r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.(?!""))') # NO r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.?(?!""))' # OK r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.(?!""))' pat2 = re.compile(r'(@[a-zA-Z]+)(?=[^\.a-zA-Z#])') if not type(token) == str: print type(token) token = pat.sub(r'<font color="blue">\1</font>',token) token = pat2.sub(r'<font color="red">\1</font>',token) return token def readfirsttoken(line): line = re.match(r"\s*(.*)",line).group(1) # remove leading whitespace if line == '': return ('','') pos = 0 text = '' inquote = False inarg = True while inarg and pos < len(line): if line[pos] == ' ' and not inquote: inarg = False elif line[pos] == '"' and not inquote: inquote = True text += line[pos] elif line[pos] == '"' and inquote: if len(line) == pos+1: inarg = False inquote = False elif line[pos+1] == '"': text += '"' pos += 1 else: inquote = False inarg = False text += line[pos] else: text += line[pos] pos += 1 if inquote: raise JMDInvalidLine("Unclosed quote") return (text,line[len(text):]) # RUNTIME ================================================ def printJMD(thefile): print """<html><head><style type="text/css"> body {font-size:9pt} td, th { border-left:2px solid #000000; padding: 3px; margin: 2px; font-size:9pt; background-color:#ffffcc; } th { background-color: #ccffcc; } </style> <title>Table JMD - Done</title> </head><body> <h1>Table JMD</h1>""" print "<!-- ",helpnote," -->" readjmd(thefile) print "</body></html>" def printform(): print """<html> <head><title>Table JMD</title></head> <body> <h1>Table JMD</h1> <form action="tablejmd.py" method="POST" name="logprint" enctype="multipart/form-data"> <p>Check your JMD Tables.</p> File: <input type="file" name="jmdfile" /><br /> <input type="submit" /> </form> </body></html> """ # RUNTIME #print "Content-Type: text/plain" #print fs = cgi.FieldStorage() if fs.has_key('jmdfile'): print "Content-Type: text/html" print printJMD(fs['jmdfile'].file) #print '<p><b>Displaying JMD table for '+fs['jmdfile'].filename+'</b></p>' elif len(sys.argv) > 2 and sys.argv[1] == '-f': printJMD(sys.argv[2]) elif len(sys.argv) > 1: if re.match(r'-h|/h|--help|/\?|-\?',sys.argv[1]): print helpnote else: print "Content-Type: text/html" print printform()
