diff --git a/tren.py b/tren.py index a618c81..9d8a5fa 100755 --- a/tren.py +++ b/tren.py @@ -8,7 +8,7 @@ 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 @@ -87,8 +87,9 @@ 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 @@ -158,7 +159,7 @@ ##### 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" @@ -686,65 +687,97 @@ 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 + IncludedFiles.append(os.path.abspath(inclfile)) - # The use included the space - if OPTIONS[i] == INCL: - file = OPTIONS[i+1] ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+2:] + # Insert content of included file at current + # command line position - # The the option and filename are not space separated - else: - file = OPTIONS[i].replace(INCL,"") ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+1:] + # A non-null left hand side means that there were + # options before the include we need to preserve - # 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 + if lhs: + n = [lhs] + n - IncludedFiles.append(os.path.abspath(file)) - - OPTIONS = lhs + n + rhs - - except IOError as e: - ErrorMsg(eFILEOPEN % (file, e.args[1])) - sys.exit(1) + OPTIONS = OPTIONS[:i] + n + OPTIONS[i+1:] + + except IOError as e: + ErrorMsg(eFILEOPEN % (inclfile, e.args[1])) + sys.exit(1) + + i += 1 return OPTIONS