Rewrote ProcessIncludes() to properly detect all legal forms of the include option on the command line.
1 parent c932505 commit 242199fdab484c6a47cb65728412dda2fbb917fe
@tundra tundra authored on 5 Feb 2010
Showing 1 changed file
View
245
tren.py
 
PROGNAME = "tren.py"
BASENAME = PROGNAME.split(".py")[0]
PROGENV = BASENAME.upper()
RCSID = "$Id: tren.py,v 1.144 2010/02/05 05:42:45 tundra Exp $"
RCSID = "$Id: tren.py,v 1.145 2010/02/05 18:05:53 tundra Exp $"
VERSION = RCSID.split()[2]
 
# Copyright Information
 
DEFLEN = 75 # Default output line length
DEFSEP = "=" # Default rename command separator: old=new
ESC = "\\" # Escape character
EXT = "Ext" # Rename target is extension
INCL = "-I" # Include file command line option
INCL = "I" # Include file command line option
NAM = "Nam" # Rename target is name
OPTINTRO = "-" # Option introducer
 
# Internal program state literals
 
DEBUG = "DEBUG"
# Error Messages
#####
 
eBADARG = "Invalid command line: %s!"
eBADINCL = "option %s requires argument" % INCL
eBADINCL = "option -%s requires argument" % INCL
eBADNEWOLD = "Bad -r argument '%s'! Requires exactly one new, old string separator (Default: " + DEFSEP + ")"
eBADLEN = "Bad line length '%s'!"
eERROR = "ERROR"
eFILEOPEN = "Cannot open file '%s': %s!"
#####
 
def ProcessIncludes(OPTIONS):
 
# Resolve include file references allowing for nested includes.
# This has to be done here separate from the command line options so
# that getopt() processing below will "see" the included statements.
""" Resolve include file references allowing for nested includes.
This has to be done here separate from the command line options so
that getopt() processing below will "see" the included statements.
 
This is a bit tricky because we have to handle every possible
legal command line syntax for option specification:
 
-I filename
-Ifilename
-....I filename
-....Ifilename
"""
 
NUMINCLUDES = 0
while " ". join(OPTIONS).find(INCL) > -1:
FoundNewInclude = True
 
while FoundNewInclude:
 
FoundNewInclude = False
i = 0
while i < len(OPTIONS):
 
# Detect all possible command line include constructs,
# isolating the requested filename and replaciing its
# contents at that position in the command line.
 
field = OPTIONS[i]
if field.startswith(OPTINTRO) and (field.find(INCL) > -1):
 
FoundNewInclude = True
lhs, rhs = field.split(INCL)
 
if lhs == OPTINTRO:
lhs = ""
 
if rhs == "":
 
if i < len(OPTIONS)-1:
 
inclfile = OPTIONS[i+1]
OPTIONS = OPTIONS[:i+1] + OPTIONS[i+2:]
 
# We have an include without a filename at the end
# of the command line which is bogus.
else:
ErrorMsg(eBADARG % eBADINCL)
sys.exit(1)
 
 
else:
inclfile = rhs
 
# Before actually doing the include, make sure we've
# not exceeded the limit. This is here mostly to make
# sure we stop recursive/circular includes.
 
NUMINCLUDES += 1
if NUMINCLUDES > MAXINCLUDES:
ErrorMsg(eTOOMANYINC)
sys.exit(1)
 
# Read the included file, stripping out comments
 
try:
n = []
f = open(inclfile)
for line in f.readlines():
line = line.split(COMMENT)[0]
n += line.split()
f.close()
# Get the index of the next include to process.
# It cannot be the last item because this means the filename
# to include is missing.
 
i = OPTIONS.index(INCL)
 
# You can't end a command line with the include option and no argument
 
if i == len(OPTIONS)-1:
ErrorMsg(eBADARG % eBADINCL)
sys.exit(1)
# Keep track of the filenames being included
# Handle the case where the user does- and does not separate
# the option and the filename with a space since both
# forms are legal command line syntax
 
# The use included the space
if OPTIONS[i] == INCL:
file = OPTIONS[i+1] ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+2:]
 
# The the option and filename are not space separated
else:
file = OPTIONS[i].replace(INCL,"") ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+1:]
 
# Keep track of- and limit the number of includes allowed
# This is an easy way to stop circular (infinite) includes.
NUMINCLUDES += 1
if NUMINCLUDES >= MAXINCLUDES:
ErrorMsg(eTOOMANYINC)
sys.exit(1)
# Replace insert option on the command line with that file's contents.
# Handle comments within lines.
try:
n = []
f = open(file)
for l in f.readlines():
l = l.split(COMMENT)[0]
n += l.split()
f.close()
# Keep track of the filenames being included
 
IncludedFiles.append(os.path.abspath(file))
 
OPTIONS = lhs + n + rhs
except IOError as e:
ErrorMsg(eFILEOPEN % (file, e.args[1]))
sys.exit(1)
IncludedFiles.append(os.path.abspath(inclfile))
 
# Insert content of included file at current
# command line position
 
# A non-null left hand side means that there were
# options before the include we need to preserve
 
if lhs:
n = [lhs] + n
 
OPTIONS = OPTIONS[:i] + n + OPTIONS[i+1:]
except IOError as e:
ErrorMsg(eFILEOPEN % (inclfile, e.args[1]))
sys.exit(1)
i += 1
 
return OPTIONS
 
# End of 'ProcessIncludes()'