summaryrefslogtreecommitdiff
path: root/gnu/dist/sgmltools-lite/python/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/dist/sgmltools-lite/python/utils.py')
-rw-r--r--gnu/dist/sgmltools-lite/python/utils.py393
1 files changed, 393 insertions, 0 deletions
diff --git a/gnu/dist/sgmltools-lite/python/utils.py b/gnu/dist/sgmltools-lite/python/utils.py
new file mode 100644
index 00000000..1bdc4fda
--- /dev/null
+++ b/gnu/dist/sgmltools-lite/python/utils.py
@@ -0,0 +1,393 @@
+#
+# utils.py - Assorted utilities
+#
+# $Id: utils.py,v 1.6 2001/02/05 01:18:37 dnedrow Exp $
+#
+# SGMLtools - an SGML toolkit.
+# Copyright (C)1998 Cees A. de Groot
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+ This module defines assorted utility functions.
+"""
+
+import sys, tempfile, os, string, re
+
+#
+# Global options and associated help text.
+#
+globalOptions = [
+ ('v', 'verbose', 'Print verbose output'),
+ ('d', 'debug', 'Do not remove temporary files'),
+ ('b:', 'backend=', 'Backend to use (default: onehtml)'),
+ ('j:', 'jade-opt=', 'Options passed on to jade'),
+ ('s:', 'dsssl-spec=', 'DSSSL spec to use'),
+ ('V', 'version', 'Print version number and exit'),
+ ('h', 'help', 'Print usage and exit'),
+ ('l', 'license', 'Print license information')
+]
+
+usagePre = """ sgmltools [OPTION...] [INPUT-FILE...]
+
+Convert SGML files into various output formats.
+
+Options:"""
+
+usagePost = """
+For help on a specific backend, use "--backend xyz --help".
+"""
+
+
+def makeOpts(backendOpts):
+ """Merge the global options with the backend options.
+
+ This function merges the global options with the backend
+ options and returns a tuple usable for getopt.
+ """
+
+ retshort = ''
+ retlong = []
+ optlist = globalOptions + backendOpts.getMoreOptions()
+ for opt in optlist:
+ retshort = retshort + opt[0]
+ retlong.append(opt[1])
+
+ return retshort, retlong
+
+
+def normalizeOpts(backendGlobs, optList):
+ """Normalize the option list returned by getopt by converting short->long
+
+ getopts() returns a mix of short and long options, which is a
+ bit unpractical. This function takes the result of getopts() and
+ normalizes it by replacing the option elements with the long
+ option without any add-on's like dashes and equals signs.
+ """
+
+ options = globalOptions + backendGlobs.getMoreOptions()
+
+ #
+ # Build translation table from short->long.
+ #
+ shortToLong = {}
+ for opt in options:
+ if opt[0][-1] == ':':
+ short = opt[0][:-1]
+ else:
+ short = opt[0]
+ if opt[1][-1] == '=':
+ long = opt[1][:-1]
+ else:
+ long = opt[1]
+
+ shortToLong[short] = long
+
+ #
+ # Normalist list.
+ #
+ retval = []
+ for opt in optList:
+ if opt[0][:2] == '--':
+ newval = (opt[0][2:], opt[1])
+ else:
+ newval = (shortToLong[opt[0][1:]], opt[1])
+ retval.append(newval)
+
+ return retval
+
+
+def findOption(optlist, optname):
+ """Look for an option in an option list and return optval.
+
+ This method checks whether an option appears in an option
+ list and returns optval (or '1' if no optval was set) if
+ the option was found. Otherwise, it returns None.
+ """
+
+ for curopt in optlist:
+ if curopt[0] == optname:
+ if curopt[1] != '':
+ return curopt[1]
+ else:
+ return 1
+ return None
+
+
+def usage(backendGlobs, message):
+ """Print a usage string, the message, and exit.
+
+ This method prints out all possible options and their help
+ texts (including those from the backend, if available), then
+ prints the message, and finally exits.
+ """
+
+ print "Usage:\n"
+ print usagePre
+ if backendGlobs != None:
+ optlist = globalOptions + backendGlobs.getMoreOptions()
+ else:
+ optlist = globalOptions
+ for opt in optlist:
+ print ' -%s, --%-15s %s' % (opt[0][0], opt[1], opt[2])
+
+ if backendGlobs != None:
+ backendGlobs.printHelp(sys.stderr)
+
+ print usagePost
+ print
+ if message != None:
+ print message
+ print
+ sys.exit(1)
+ else:
+ sys.exit(0)
+
+
+def version(sharedir):
+ """This procedure prints a version identifier to stdout"""
+
+ fh = open(os.path.join(sharedir, 'VERSION'))
+ print 'SGMLtools-Lite version ' + string.rstrip(fh.readline())
+ fh.close()
+
+
+tempfiles = []
+def makeTemp():
+ """Make a temporary file which is cleaned up at exit
+
+ This method calls mktemp() to create a temporary filename and
+ stashes the returned file in an array that will be checked at
+ exit time by exitHandler().
+ """
+
+ newname = tempfile.mktemp()
+ global tempfiles
+ tempfiles.append(newname)
+ return newname
+
+def registerTemp(file):
+ """Register a temporary file for cleaning up at exit
+
+ This method registers a temporary file for cleanup at
+ exit. This can be used in order to deal with temporary
+ files whose names are not generated by us (but by, say,
+ TeX).
+ """
+ tempfiles.append(file)
+
+def exitHandler():
+ """Cleaning lady for makeTemp()
+
+ This method walks over the tempfiles list and attempts to remove
+ each element in it.
+ """
+
+ for file in tempfiles:
+ try:
+ os.remove(file)
+ except:
+ pass
+
+#
+# Register us as an exit function
+#
+sys.exitfunc = exitHandler
+
+
+def readAliases(autoconf):
+ """Read %(etcdir)/aliases and ~/.sgmlaliases
+
+ This function reads the SGML alias files and returns a hash
+ containing the merged contents of these files.
+ """
+
+ retval = {}
+ for file in [ os.path.join(autoconf['etcdir'], 'aliases'),
+ os.path.expanduser('~/.sgmlaliases') ]:
+ if not os.path.isfile(file):
+ continue
+
+ fh = open(file, 'r')
+ for line in fh.readlines():
+ line = string.strip(line)
+ if len(line) == 0:
+ continue
+ if line[0] == '#':
+ continue
+
+ key, rest = string.split(line, ' ', 1)
+ retval[key] = string.lstrip(rest)
+ fh.close()
+
+ return retval
+
+#
+# Search our path, SGML_CATALOG_FILES, by reading all them files
+# and looking for our pubid. We really need a catalog file parser...
+#
+def _searchInCat(curcat, id, section):
+ fh = open(curcat, 'r')
+ for line in fh.readlines():
+ #
+ # Check for nested catalogs, recurse if yes.
+ #
+ mo = re.compile(r'CATALOG\s*"([^"]+)"').match(line)
+ if mo != None:
+ retval = _searchInCat(mo.group(1), id, section)
+ if retval != None:
+ return retval;
+
+ if not re.compile(r'^\s*PUBLIC').match(line):
+ continue
+ if string.find(line, id) == -1:
+ continue
+
+ fh.close()
+
+ #
+ # Looks like a good one - extract the relevant parts. If the
+ # sysid is not absolute, prepend the current catalog's
+ # location to it.
+ #
+ retval = re.compile(r'^.*\s\"?([^"\s]+)\"?$').match(line).group(1)
+ if not os.path.isabs(retval):
+ catdir, junk = os.path.split(curcat)
+ retval = os.path.join(catdir, retval)
+ if not os.path.exists(retval):
+ raise IOError, \
+ "Found catalog file %s but it doesn't exist" % retval
+
+ if len(section) > 0:
+ retval = retval + '#' + section
+ return retval
+
+ fh.close()
+ return None
+
+
+def findStylesheet(name, aliases):
+ """Searches for the stylesheet indicated by name
+
+ This function translates a public stylesheet identifier into a
+ system identifier. It uses the alias list to expand aliases.
+ """
+
+ #
+ # Test whether it is already a system identifier
+ #
+ try:
+ (id, section) = string.split(name, '#', 1)
+ except:
+ id = name
+ section = ''
+ if os.path.isfile(id):
+ return name
+
+ #
+ # Expand alias, and retest.
+ #
+ if aliases.has_key(id):
+ name = aliases[id]
+ if len(section) > 0:
+ name = name + '#' + section
+ return findStylesheet(name, aliases)
+
+ for curcat in string.split(os.environ['SGML_CATALOG_FILES'], ':'):
+ if not os.path.isfile(curcat):
+ continue
+
+ retval = _searchInCat(curcat, id, section);
+ if retval != None:
+ return retval;
+
+ raise IOError, "Couldn't resolve pubid [%s]" % id
+
+def shellProtect(file):
+ """Protects a filename against shell interpretation.
+ This is done by putting the name in single quotes, and by
+ escaping single quotes in the filename. If the last character
+ is an asterisk, the asterisk is NOT quoted and is appended
+ after the final single quote.
+ """
+ if file[-1] != '*':
+ return "'%s'" % string.replace(file, "'", "'\\''")
+ else:
+ return "'%s'*" % string.replace(file[:-1], "'", "'\\''")
+
+class Tracer:
+ """Simple tracer class."""
+
+ def __init__(self, doTrace):
+ self._isTracing = doTrace
+
+ def trace(self, message):
+ if self._isTracing:
+ print ('+' + message)
+
+ def system(self, cmd):
+ """Shorthand for the pattern trace(x);os.system(x)"""
+ self.trace(cmd)
+ os.system(cmd)
+
+ def mkdir(self, dir, mode=0755):
+ """Shorthand for the pattern trace('mkdir ' + x);os.mkdir(x)"""
+ self.trace('mkdir ' + dir)
+ os.mkdir(dir, mode)
+
+ def chdir(self, dir):
+ """Shorthand for the pattern trace('chdir ' + x);os.chdir(x)"""
+ self.trace('chdir ' + dir)
+ os.chdir(dir)
+
+ def rmdir(self, dir):
+ """Shorthand for the pattern trace('rmdir ' + x);os.rmdir(x)"""
+ self.trace('rmdir ' + dir)
+ os.rmdir(dir)
+
+ def symlink(self, src, dest):
+ """Shorthand for the pattern trace('symlink... );os.symlink(...)"""
+ self.trace('ln -s ' + src + ' ' + dest)
+ os.symlink(src, dest)
+
+ def mv(self, src, dest):
+ """Shorthand for the pattern trace('mv...);os.system("mv...)."""
+ self.system("mv %s %s" % (shellProtect(src), shellProtect(dest)))
+
+#
+# License information printer
+#
+def license():
+ print """
+ SGMLtools - an SGML toolkit.
+ Copyright (C)1998 Cees A. de Groot
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+ sys.exit(0)