Reintroduced ability to get debug dump as often as we like with multiple command line '-d's.
Reorganized and cleaned up the code and debugging logic.
1 parent 0f39b75 commit 42f4e17b4c6a496ca6f7d393c2acd44e394027b8
@tundra tundra authored on 25 Jan 2010
Showing 1 changed file
View
303
tren.py
# Program Information
 
PROGNAME = "tren.py"
PROGENV = PROGNAME.split(".py")[0].upper()
RCSID = "$Id: tren.py,v 1.109 2010/01/25 23:23:30 tundra Exp $"
RCSID = "$Id: tren.py,v 1.110 2010/01/26 01:15:08 tundra Exp $"
VERSION = RCSID.split()[2]
 
# Copyright Information
 
EXT = "Ext" # Rename target is extension
EXTDELIM = "." # Extension delimeter
INCL = "-I" # Include file command line option
NAM = "Nam" # Rename target is name
SEPARATOR = "-" *70
 
 
#----------------------------------------------------------#
# Prompts, & Application Strings #
#####
 
DEBUGFLAG = "-d"
dCMDLINE = "Command Line"
dCURSTATE = "Current State Of Program Options"
dDEBUG = "DEBUG"
dINCLUDING = "Including file '%s'"
dPAIR = "Option/Target Pair"
dPROGENV = "$" + PROGENV
dRESOLVEDOPTS = "Resolved Command Line"
 
 
# Program toggle and option defaults
 
DEBUG = False # Debugging off
CASE = True # Search is case-sensitive
CASESENSITIVE = True # Search is case-sensitive
ERRORCONTINUE = False # Do not continue after error
EXTDELIM = EXTDELIM # Extension Delimiter
FORCERENAM = False # Do not rename if target already exists
GLOBAL = False # Only rename first instance of old string
 
 
# Global data structures
 
COMMANDLINES = [] # Stores "options... targets" from command line
 
 
 
#--------------------------- Code Begins Here ---------------------------------#
 
 
#####
 
def DumpState():
 
DebugMsg(dCURSTATE)
DebugMsg(SEPARATOR)
 
# Names of all the state variables we want dumped
state = [
"DEBUG",
"CASE",
"CASESENSITIVE",
"ERRORCONTINUE",
"EXTDELIM",
"FORCERENAM",
"GLOBAL",
 
for k in state:
DebugMsg(ColumnPad([k, eval(k)]))
 
DebugMsg(SEPARATOR + "\n")
 
# End of 'DumpState()'
 
 
#####
def PrintStdout(msg, trailing="\n"):
sys.stdout.write(msg + trailing)
 
# End of 'PrintStdout'
 
 
#####
# Process Include Files On The Command Line
#####
 
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.
 
NUMINCLUDES = 0
while " ". join(OPTIONS).find(INCL) > -1:
# 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)
if i == len(OPTIONS)-1:
ErrorMsg(eBADARG % eBADINCL)
sys.exit(1)
file = OPTIONS[i+1] ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+2:]
# 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()
if DEBUG:
DebugMsg(dINCLUDING % file)
 
OPTIONS = lhs + n + rhs
except IOError as e:
ErrorMsg(eFILEOPEN % (file, e.args[1]))
sys.exit(1)
 
return OPTIONS
 
# End of 'ProcessIncludes()'
 
 
#####
# Break The Command Line Into Separate "Option... Target..." Pairs
#####
 
def ProcessOptTgtPair(OPTIONS):
 
DOINGOPTS = True
commandlines = []
cmd = []
 
while OPTIONS:
 
i = OPTIONS[0]
OPTIONS = OPTIONS[1:]
 
# Process options
if i.startswith("-"):
if DOINGOPTS:
cmd.append(i)
 
# Starting a new "options... targets ..." pair
else:
commandlines.append(cmd)
cmd = []
DOINGOPTS = True
cmd.append(i)
 
# Process targets
else:
DOINGOPTS = False
cmd.append(i)
 
 
if cmd:
commandlines.append(cmd)
 
return commandlines
# End of 'ProcessOptTgtPair()'
 
 
#####
# Print Usage Information
envopt = os.getenv(PROGENV)
if envopt:
OPTIONS = envopt.split() + 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.
 
NUMINCLUDES = 0
while " ". join(OPTIONS).find(INCL) > -1:
 
# 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)
if i == len(OPTIONS)-1:
ErrorMsg(eBADARG % eBADINCL)
sys.exit(1)
 
file = OPTIONS[i+1] ; lhs = OPTIONS[:i] ; rhs = OPTIONS[i+2:]
 
# 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()
 
OPTIONS = lhs + n + rhs
 
except IOError as e:
ErrorMsg(eFILEOPEN % (file, e.args[1]))
sys.exit(1)
 
# We also need to detect a request for debugging now
# so we don't have to wait for getopt to parse it
# to begin seeing debugging output
 
# Check for debug manually to see if we want
# debug info about includes
 
if DEBUGFLAG in OPTIONS:
DEBUG = True
while DEBUGFLAG in OPTIONS:
OPTIONS.remove(DEBUGFLAG)
 
# Deal with include files
 
OPTIONS = ProcessIncludes(OPTIONS)
 
# Check for debug manually again before we process the options
# to get debug info on command line expansion
 
if DEBUGFLAG in OPTIONS:
DEBUG = True
 
# Break command line into "option ... targets ..." pairs.
 
options = OPTIONS # Save for later
DOINGOPTS = True
cmd = []
 
while OPTIONS:
 
i = OPTIONS[0]
OPTIONS = OPTIONS[1:]
 
# Process options
if i.startswith("-"):
if DOINGOPTS:
cmd.append(i)
 
# Starting a new "options... targets ..." pair
else:
COMMANDLINES.append(cmd)
cmd = []
DOINGOPTS = True
cmd.append(i)
 
# Process targets
else:
DOINGOPTS = False
cmd.append(i)
 
 
if cmd:
COMMANDLINES.append(cmd)
 
 
pairs = ProcessOptTgtPair(OPTIONS)
 
if DEBUG:
 
# Dump what we know about the command line
 
DebugMsg(ColumnPad([dCMDLINE, sys.argv]))
DebugMsg(ColumnPad([dPROGENV, os.getenv("TREN")]))
DebugMsg(ColumnPad([dRESOLVEDOPTS, options]))
DebugMsg(ColumnPad([dRESOLVEDOPTS, OPTIONS]))
 
 
# Now process the command line in "opts... targets" pairs
 
for commandline in COMMANDLINES:
for commandline in pairs:
if DEBUG:
DebugMsg(ColumnPad([dPAIR, " ".join(commandline)]))
 
try:
opts, args = getopt.getopt(commandline, '1abbCcEefghl:qr:tvXx]')
opts, args = getopt.getopt(commandline, '1abbCcdEefghl:qr:tvXx]')
except getopt.GetoptError as e:
ErrorMsg(eBADARG % e.args[0])
sys.exit(1)
 
TARGET = ALL
if opt == "-b":
TARGET = NAM
if opt == "-C":
CASE = True
CASESENSITIVE = True
if opt == "-c":
CASE = False
CASESENSITIVE = False
if opt == "-d":
DumpState()
if opt == "-E":
ERRORCONTINUE = True
if opt == "-e":
TARGET = EXT