| |
---|
| | |
---|
| | # Program Information |
---|
| | |
---|
| | PROGNAME = "tconfpy" |
---|
| | RCSID = "$Id: tconfpy.py,v 1.118 2004/03/16 03:18:19 tundra Exp $" |
---|
| | RCSID = "$Id: tconfpy.py,v 1.119 2004/03/16 10:35:47 tundra Exp $" |
---|
| | VERSION = RCSID.split()[2] |
---|
| | |
---|
| | # Copyright Information |
---|
| | |
---|
| |
---|
| | ########### |
---|
| | |
---|
| | # Formatting Constants |
---|
| | |
---|
| | MSGPOS = 10 # Where to start message output |
---|
| | MSGPROMPT = "%s>" |
---|
| | FILENUM = "[File: %s Line: %s]" # Display filename and linenum |
---|
| | PTR = " ---> " # Textual pointer for debug output |
---|
| | |
---|
| | |
---|
| |
---|
| | None |
---|
| | ] |
---|
| | |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Error, Warning, And Debug Message Strings Stored In A Global Dictionary |
---|
| | ########## |
---|
| | |
---|
| | Messages = {} |
---|
| | |
---|
| | |
---|
| | #----------------------------------------------------------# |
---|
| | # Prompts, & Application Strings # |
---|
| | #----------------------------------------------------------# |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Debug Messages |
---|
| | ########## |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Debug Literals And Messages |
---|
| | ########## |
---|
| | |
---|
| | # Literals |
---|
| | |
---|
| | dDEBUG = "DEBUG" |
---|
| | |
---|
| | dBLANKLINE = "Parsed To Blank Line - Ignored" |
---|
| | dLINEIGNORE = FILENUM + " '%s' " + PTR + "%s\n" |
---|
| | dNOTINCLUDE = "Current Conditional Block False: Line Not Included" |
---|
| | dNUMLINES = "Processing File '%s' Resulted In %d Total Lines Parsed" |
---|
| | dPARSEDLINE = FILENUM + " '%s'" + PTR + "'%s'\n" |
---|
| | |
---|
| | ########### |
---|
| | # Error Messages |
---|
| | ########### |
---|
| | |
---|
| | # Messages |
---|
| | |
---|
| | Messages["dLINEIGNORE"] = FILENUM + " '%s' " + PTR + "%s\n" |
---|
| | Messages["dNUMLINES"] = "Processing File '%s' Resulted In %d Total Lines Parsed" |
---|
| | Messages["dPARSEDLINE"] = FILENUM + " '%s'" + PTR + "'%s'\n" |
---|
| | |
---|
| | |
---|
| | ########### |
---|
| | # Error Literals And Messages |
---|
| | ########### |
---|
| | |
---|
| | # Literals |
---|
| | |
---|
| | eERROR = "ERROR" |
---|
| | eSYNTAX = "Incorrect '%s' Syntax" |
---|
| | |
---|
| | eBADEXPR = FILENUM + " Bad Expression - %s: '%s'" |
---|
| | eCONFOPEN = "Cannot Open The File '%s'" |
---|
| | eENDIFEXTRA = FILENUM + " '" + ENDIF + "' Without Matching Condition" |
---|
| | eENDIFBAD = eSYNTAX % ENDIF |
---|
| | eENDIFMISS = FILENUM + " Missing %d '" + ENDIF + "' Statement(s)" |
---|
| | eIFBAD = eSYNTAX % IF |
---|
| | eINCLBAD = eSYNTAX % INCLUDE |
---|
| | eNOVARREF = "Must Have At Least One Variable Reference" |
---|
| | eVARUNDEF = FILENUM + " " + "Attempt To Reference Undefined Variable '%s'" |
---|
| | |
---|
| | |
---|
| | ########### |
---|
| | # Warning Messages |
---|
| | ########### |
---|
| | |
---|
| | # Messages |
---|
| | |
---|
| | Messages["eBADCOND"] = FILENUM + " Bad Directive - %s %s" |
---|
| | Messages["eCONFOPEN"] = "Cannot Open The File '%s'" |
---|
| | Messages["eENDIFEXTRA"] = FILENUM + " '" + ENDIF + "' Without Matching Condition" |
---|
| | Messages["eENDIFMISS"] = FILENUM + " Missing %d '" + ENDIF + "' Statement(s)" |
---|
| | Messages["eVARUNDEF"] = FILENUM + " " + "Attempt To Reference Undefined Variable '%s'" |
---|
| | |
---|
| | |
---|
| | ########### |
---|
| | # Warning Literals And Messages |
---|
| | ########### |
---|
| | |
---|
| | # Literals |
---|
| | |
---|
| | wWARNING = "WARNING" |
---|
| | |
---|
| | wEXTRATEXT = FILENUM + " '%s' Statements Only Process Variables. Extra Text Ignored" |
---|
| | wTRAILING = FILENUM + " Trailing Text After '%s' Statement Ignored" |
---|
| | # Messages |
---|
| | |
---|
| | Messages["wEXTRATEXT"] = FILENUM + " '%s' Statements Only Process Variables. Extra Text Ignored" |
---|
| | Messages["wTRAILING"] = FILENUM + " Trailing Text After '%s' Statement Ignored" |
---|
| | |
---|
| | |
---|
| | # Determine Length Of Longest Message Type |
---|
| | # Needed for formatting later |
---|
| | |
---|
| | MAXMSG = 0 |
---|
| | for msg in Messages: |
---|
| | l = len(msg) |
---|
| | if l > MAXMSG: |
---|
| | MAXMSG = l |
---|
| | |
---|
| | |
---|
| | #--------------------------- Code Begins Here ---------------------------------# |
---|
| | |
---|
| |
---|
| | ########## |
---|
| | # Create A Debug Message |
---|
| | ########## |
---|
| | |
---|
| | def DebugMsg(dmsg): |
---|
| | def DebugMsg(dmsg, args): |
---|
| | |
---|
| | global DebugMsgs |
---|
| | |
---|
| | DebugMsgs.append(mkmsg(dmsg, dDEBUG)) |
---|
| | DebugMsgs.append(mkmsg(Messages[dmsg] % args, dmsg)) |
---|
| | |
---|
| | # End of 'DebugMsg()' |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Create An Error Message |
---|
| | ########## |
---|
| | |
---|
| | def ErrorMsg(error): |
---|
| | def ErrorMsg(error, args): |
---|
| | |
---|
| | global ErrMsgs |
---|
| | |
---|
| | ErrMsgs.append(mkmsg(error + "!", eERROR)) |
---|
| | ErrMsgs.append(mkmsg(Messages[error] % args + "!", error)) |
---|
| | |
---|
| | # End of 'ErrorMsg()' |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Create A Warning Message |
---|
| | ########## |
---|
| | |
---|
| | def WarningMsg(warning): |
---|
| | def WarningMsg(warning, args): |
---|
| | |
---|
| | global WarnMsgs |
---|
| | |
---|
| | WarnMsgs.append(mkmsg(warning + "!", wWARNING)) |
---|
| | WarnMsgs.append(mkmsg(Messages[warning] % args + "!", warning)) |
---|
| | |
---|
| | # End of 'WarningMsg()' |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Construct A Standard Application Message String |
---|
| | ########## |
---|
| | |
---|
| | def mkmsg(msg, msgtype=""): |
---|
| | |
---|
| | if msgtype: |
---|
| | msgtype += ">" |
---|
| | |
---|
| | pad = " " * (MSGPOS - len(msgtype)) |
---|
| | |
---|
| | return "%s %s%s%s" % (PROGINFO, msgtype, pad, msg) |
---|
| | def mkmsg(msg, msgtype): |
---|
| | |
---|
| | pad = " " * (MAXMSG - len(msgtype) + 2) |
---|
| | |
---|
| | return "%s %s%s%s" % (PROGINFO, MSGPROMPT % msgtype, pad, msg) |
---|
| | |
---|
| | |
---|
| | # End of 'mkmsg()' |
---|
| | |
---|
| |
---|
| | |
---|
| | # Return the parsing results |
---|
| | |
---|
| | if DEBUG: |
---|
| | DebugMsg(dNUMLINES %(cfgfile, TotalLines)) |
---|
| | DebugMsg("dNUMLINES", (cfgfile, TotalLines)) |
---|
| | |
---|
| | return (SymTable, ErrMsgs, WarnMsgs, DebugMsgs) |
---|
| | |
---|
| | |
---|
| |
---|
| | # Attempts to reference undefined variables are legitimate |
---|
| | # in this case and ought not to generate an error message. |
---|
| | |
---|
| | if reporterr: |
---|
| | ErrorMsg(eVARUNDEF % (cfgfile, linenum, sym)) |
---|
| | ErrorMsg("eVARUNDEF", (cfgfile, linenum, sym)) |
---|
| | |
---|
| | ref_ok = False |
---|
| | |
---|
| | return line, ref_ok |
---|
| |
---|
| | |
---|
| | # File open failed for some reason |
---|
| | except: |
---|
| | |
---|
| | ErrorMsg(eCONFOPEN % cfgfile) # Record the error |
---|
| | ErrorMsg("eCONFOPEN", (cfgfile,)) # Record the error |
---|
| | |
---|
| | # Make sure we had all condition blocks balanced with matching '.endif' |
---|
| | |
---|
| | finalcond = len(CondStack) |
---|
| | if finalcond != 1: |
---|
| | ErrorMsg(eENDIFMISS % (cfgfile, linenum, finalcond-1)) |
---|
| | ErrorMsg("eENDIFMISS", (cfgfile, linenum, finalcond-1)) |
---|
| | |
---|
| | # End of 'ParseFile()' |
---|
| | |
---|
| | |
---|
| |
---|
| | if line.startswith(ENDIF): |
---|
| | |
---|
| | # Check for space after conditional |
---|
| | if line.split()[0] != ENDIF: |
---|
| | ErrorMsg(eBADEXPR % (cfgfile, linenum, eENDIFBAD, orig)) |
---|
| | ErrorMsg("eBADCOND", (cfgfile, linenum, eENDIFBAD, "'%s'" % orig)) |
---|
| | |
---|
| | # This should be the only thing on the line |
---|
| | elif line != ENDIF: |
---|
| | WarningMsg(wTRAILING % (cfgfile, linenum, ENDIF)) |
---|
| | WarningMsg("wTRAILING", (cfgfile, linenum, ENDIF)) |
---|
| | |
---|
| | # Remove one level of nesting |
---|
| | CondStack.pop() |
---|
| | |
---|
| | # Error, if there are more .endifs than conditionals |
---|
| | if not CondStack: |
---|
| | ErrorMsg(eENDIFEXTRA % (cfgfile, linenum)) |
---|
| | ErrorMsg("eENDIFEXTRA", (cfgfile, linenum)) |
---|
| | CondStack.append(False) # Inhibit further parsing |
---|
| | |
---|
| | ##### |
---|
| | # Check State Of Parser |
---|
| | ##### |
---|
| | |
---|
| | |
---|
| | if not CondStack[-1]: |
---|
| | if DEBUG: |
---|
| | DebugMsg(dLINEIGNORE % (cfgfile, linenum, orig, dNOTINCLUDE)) |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dNOTINCLUDE)) |
---|
| | return |
---|
| | |
---|
| | ##### |
---|
| | # .include Processing |
---|
| |
---|
| | if line.startswith(INCLUDE): |
---|
| | |
---|
| | # Make sure a space follows the directive |
---|
| | if line.split()[0] != INCLUDE: |
---|
| | ErrorMsg(eBADEXPR % (cfgfile, linenum, eINCLBAD, orig)) |
---|
| | ErrorMsg("eBADCOND", (cfgfile, linenum, eINCLBAD, "'%s'" % orig)) |
---|
| | |
---|
| | else: |
---|
| | ParseFile(line.split(INCLUDE)[1].strip()) |
---|
| | |
---|
| |
---|
| | |
---|
| | # There must be at least one var reference in the condition |
---|
| | |
---|
| | vars = VarRef.findall(line) |
---|
| | if len(vars) > 0: |
---|
| | |
---|
| | # Only variable references are significant - warn on other text. |
---|
| | |
---|
| | # Strip out variable references and see if anything |
---|
| | # other than whitespace is left. |
---|
| | |
---|
| | plain = line |
---|
| | |
---|
| | # Only variable references are significant - warn on other text. |
---|
| | |
---|
| | # Strip out variable references and see if anything |
---|
| | # other than whitespace is left. |
---|
| | |
---|
| | plain = line |
---|
| | if vars: |
---|
| | for v in vars: |
---|
| | plain=plain.replace(v, "") |
---|
| | |
---|
| | if len(plain.strip()): |
---|
| | WarningMsg(wEXTRATEXT % (cfgfile, linenum, IFTYPE)) |
---|
| | if len(plain.strip()): |
---|
| | WarningMsg("wEXTRATEXT", (cfgfile, linenum, IFTYPE)) |
---|
| | |
---|
| | if vars: |
---|
| | |
---|
| | # Go see how many references actually resolve |
---|
| | |
---|
| | resolved = 0 |
---|
| |
---|
| | resolved += 1 |
---|
| | |
---|
| | # And set state accordingly |
---|
| | |
---|
| | state = sTRUE |
---|
| | state = True |
---|
| | if IFTYPE == IFALL and len(vars) != resolved: |
---|
| | state = sFALSE |
---|
| | state = False |
---|
| | |
---|
| | if IFTYPE == IFANY and not resolved: |
---|
| | state = sFALSE |
---|
| | state = False |
---|
| | |
---|
| | if IFTYPE == IFNONE and resolved: |
---|
| | state = sFALSE |
---|
| | state = False |
---|
| | |
---|
| | CondStack.append(state) |
---|
| | line = state |
---|
| | |
---|
| | # Bogus conditional syntax |
---|
| | |
---|
| | # Now reflect this in the parsed line |
---|
| | line = sTRUE |
---|
| | if not state: |
---|
| | line = sFALSE |
---|
| | |
---|
| | # Bogus conditional syntax - no variable refs found |
---|
| | else: |
---|
| | ErrorMsg(eBADEXPR % (cfgfile, linenum, eNOVARREF, orig)) |
---|
| | ErrorMsg("eBADCOND", (cfgfile, linenum, "'%s'" % orig, eNOVARREF)) |
---|
| | |
---|
| | ##### |
---|
| | # (In)Equality Conditionals |
---|
| | ##### |
---|
| |
---|
| | elif line.count(NOTEQUIV): |
---|
| | pass |
---|
| | |
---|
| | ##### |
---|
| | # Line Started With IF, But Was Not In Any Knwon IF Form |
---|
| | # Line Started With IF, But Was Not In Any Known IF Form |
---|
| | ##### |
---|
| | |
---|
| | else: |
---|
| | ErrorMsg(eBADEXPR % (cfgfile, linenum, eIFBAD, orig)) |
---|
| | ErrorMsg("eBADCOND", (cfgfile, linenum, eIFBAD, "'%s'" % orig)) |
---|
| | |
---|
| | |
---|
| | ##### |
---|
| | # Handle New Variable Declaration/Assignment |
---|
| |
---|
| | ########## |
---|
| | # End Of Line Parser |
---|
| | ########## |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Write Fully Parsed Line To Debug Log If Requested |
---|
| | ########## |
---|
| | |
---|
| | if DEBUG: |
---|
| | |
---|
| | # Note blank lines for debug purposes |
---|
| | if not line: |
---|
| | DebugMsg(dLINEIGNORE % (cfgfile, linenum, orig, dBLANKLINE)) |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dBLANKLINE)) |
---|
| | |
---|
| | # All non-blank lines noted here |
---|
| | else: |
---|
| | DebugMsg(dPARSEDLINE % (cfgfile, linenum, orig, line)) |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | |
---|
| | |
---|
| | # End of 'ParseLine' |
---|
| | |