| |
---|
| | |
---|
| | PROGNAME = "tren.py" |
---|
| | BASENAME = PROGNAME.split(".py")[0] |
---|
| | PROGENV = BASENAME.upper() |
---|
| | RCSID = "$Id: tren.py,v 1.172 2010/03/06 16:26:17 tundra Exp $" |
---|
| | RCSID = "$Id: tren.py,v 1.173 2010/03/08 16:41:23 tundra Exp $" |
---|
| | VERSION = RCSID.split()[2] |
---|
| | |
---|
| | # Copyright Information |
---|
| | |
---|
| |
---|
| | ##### |
---|
| | # General Program Constants |
---|
| | ##### |
---|
| | |
---|
| | MAXINCLUDES = 50 # Maximum number of includes allowed |
---|
| | MAXINCLUDES = 1000 # Maximum number of includes allowed - used to catch circular references |
---|
| | MAXNAMELEN = 255 # Maximum file or directory name length |
---|
| | MINNAMELEN = 1 # Minimum file or directory name length |
---|
| | |
---|
| | ##### |
---|
| |
---|
| | PADWIDTH = 30 # Column width |
---|
| | LSTPAD = 13 # Padding to use when dumping lists |
---|
| | WRAPINDENT = 8 # Extra indent on wrapped lines |
---|
| | MINLEN = PADWIDTH + WRAPINDENT + 1 # Minimum line length |
---|
| | |
---|
| | |
---|
| | ##### |
---|
| | # Command Line Option Strings |
---|
| | ##### |
---|
| | |
---|
| | # List all legal command line options that will be processed by getopt() later. |
---|
| | # We exclude -I here because it is parsed manually before the getopt() call. |
---|
| | |
---|
| | OPTIONSLIST = "Ccdfhi:P:qR:r:S:tvw:Xx" # All legal command line options in getopt() format |
---|
| | |
---|
| | |
---|
| | ##### |
---|
| | # Literals |
---|
| |
---|
| | |
---|
| | TOKCMDEXEC = "`" # Delimiter for command execution renaming tokens |
---|
| | TOKDELIM = "/" # Delimiter for all renaming tokens |
---|
| | TOKENV = "$" # Introducer for environment variable replacement tokens |
---|
| | TOKFILGID = "g" # File GID replacement token |
---|
| | TOKFILGRP = "G" # File Group Name replacement token |
---|
| | TOKFILLEN = "L" # File Length replacement token |
---|
| | TOKFILNAM = "F" # File Name replacement token |
---|
| | TOKFILUID = "u" # File UID replacement token |
---|
| | TOKFILUNAM = "U" # File User Name replacement token |
---|
| | TOKFILGID = "GID" # File GID replacement token |
---|
| | TOKFILGRP = "GNAME" # File Group Name replacement token |
---|
| | TOKFILLEN = "LEN" # File Length replacement token |
---|
| | TOKFILNAM = "FNAME" # File Name replacement token |
---|
| | TOKFILUID = "UID" # File UID replacement token |
---|
| | TOKFILUNAM = "UNAME" # File User Name replacement token |
---|
| | |
---|
| | |
---|
| | # Internal program state literals |
---|
| | |
---|
| |
---|
| | " -r old=new Replace old with new in file or directory names", |
---|
| | " -S suffix Suffix to use when renaming existing filenames (Default: %s)" % DEFSUFFIX, |
---|
| | " -t Test mode, don't rename, just show what the program *would* do (Default: False)", |
---|
| | " -v Print detailed program version information and continue (Default: False)", |
---|
| | " -w Line length of diagnostic and error output (Default: %s)" % DEFLEN, |
---|
| | " -w width Line length of diagnostic and error output (Default: %s)" % DEFLEN, |
---|
| | " -X Treat the renaming strings literally (Default)", |
---|
| | " -x Treat the old replacement string as a Python regular expression (Default: False)", |
---|
| | ] |
---|
| | |
---|
| |
---|
| | |
---|
| | 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. |
---|
| | This has to be done here separate from the command line |
---|
| | options so that normal 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 |
---|
| | """ |
---|
| | |
---|
| | # Build a list of all the options that take arguments. This is |
---|
| | # needed to determine whether the include symbol is an include |
---|
| | # option or part of an argument to a preceding option. |
---|
| | |
---|
| | OPTIONSWITHARGS = "" |
---|
| | for i in re.finditer(":", OPTIONSLIST): |
---|
| | OPTIONSWITHARGS += OPTIONSLIST[i.start() - 1] |
---|
| | |
---|
| | NUMINCLUDES = 0 |
---|
| | FoundNewInclude = True |
---|
| | |
---|
| | while FoundNewInclude: |
---|
| |
---|
| | # 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. |
---|
| | position = field.find(INCL) |
---|
| | |
---|
| | if field.startswith(OPTINTRO) and (position > -1): |
---|
| | |
---|
| | |
---|
| | lhs = field[:position] |
---|
| | rhs = field[position+1:] |
---|
| | |
---|
| | # Make sure the include symbol isn't part of some |
---|
| | # previous option argument |
---|
| | |
---|
| | previousopt = False |
---|
| | for c in OPTIONSWITHARGS: |
---|
| | |
---|
| | if c in lhs: |
---|
| | |
---|
| | previousopt = True |
---|
| | break |
---|
| | |
---|
| | # If the include symbol appears in the context of a |
---|
| | # previous option, skip this field, otherwise process |
---|
| | # it as an include. |
---|
| | |
---|
| | |
---|
| | if not previousopt: |
---|
| | |
---|
| | FoundNewInclude = True |
---|
| | 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) |
---|
| | |
---|
| | else: |
---|
| | ErrorMsg(eBADARG % eBADINCL) |
---|
| | |
---|
| | 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) |
---|
| | |
---|
| | # 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() |
---|
| | |
---|
| | # Keep track of the filenames being included |
---|
| | |
---|
| | 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])) |
---|
| | 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) |
---|
| | |
---|
| | # 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() |
---|
| | |
---|
| | # Keep track of the filenames being included for debug output |
---|
| | |
---|
| | 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])) |
---|
| | |
---|
| | i += 1 |
---|
| | |
---|
| | return OPTIONS |
---|
| |
---|
| | |
---|
| | # And parse the command line |
---|
| | |
---|
| | try: |
---|
| | opts, args = getopt.getopt(OPTIONS, 'Ccdfhi:P:qR:r:S:tvw:Xx]') |
---|
| | opts, args = getopt.getopt(OPTIONS, OPTIONSLIST) |
---|
| | except getopt.GetoptError as e: |
---|
| | ErrorMsg(eBADARG % e.args[0]) |
---|
| | |
---|
| | # Create and populate an object with rename targets. This must be |
---|
| |
---|
| | |