| |
---|
| | |
---|
| | # Program Information |
---|
| | |
---|
| | PROGNAME = "tconfpy" |
---|
| | RCSID = "$Id: tconfpy.py,v 1.186 2005/01/13 10:36:24 tundra Exp $" |
---|
| | RCSID = "$Id: tconfpy.py,v 1.187 2005/01/13 20:45:50 tundra Exp $" |
---|
| | VERSION = RCSID.split()[2] |
---|
| | |
---|
| | # Copyright Information |
---|
| | |
---|
| |
---|
| | # Global Variables & Data Structures # |
---|
| | #----------------------------------------------------------# |
---|
| | |
---|
| | |
---|
| | ALLOWNEWVAR = True # Allow new variable creation in cfg file |
---|
| | TEMPLATES = {} # Place to hold variable templates |
---|
| | TEMPONLY = False # Allow only template variable creation |
---|
| | LITERALVARS = False |
---|
| | DEBUG = False # Control Debug output |
---|
| | INLITERAL = False # Indicates we are currently in a literal block |
---|
| | |
---|
| | DebugMsg = [] # Place to store and return debug info |
---|
| | ErrMsgs = [] # Place to store and return errors |
---|
| | WarnMsgs = [] # Place to store and return warnings |
---|
| | LiteralLines = [] # Place to store and return unprocessed lines |
---|
| | |
---|
| | |
---|
| | CondStack = [["", True,]] # Conditional stack |
---|
| | TotalLines = 0 # Total number of lines parsed |
---|
| | |
---|
| | |
---|
| | ##### |
---|
| | # Dummy Object Used To Return Parsing Results |
---|
| | ##### |
---|
| | |
---|
| | # This is done so the caller only needs to know the name of |
---|
| | # each result set, not its position in the list of returned items |
---|
| | |
---|
| | |
---|
| | class RetObj(object): |
---|
| | |
---|
| | def __init__(self): |
---|
| | self.SymTable = {} |
---|
| | self.Errors = [] |
---|
| | self.Warnings = [] |
---|
| | self.Debug = [] |
---|
| | self.Literals = [] |
---|
| | |
---|
| | # End of 'RetObj' |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Symbol Table |
---|
| | ########## |
---|
| | |
---|
| | # Symbol Table is a dictionary in the form: |
---|
| | ########## |
---|
| | # Symbol Table Related Classes |
---|
| | ########## |
---|
| | |
---|
| | # Symbol Table is an object containing a dictionary in the form: |
---|
| | # |
---|
| | # {varname : descriptor} |
---|
| | # |
---|
| | # where the descriptor is an object with the following attributes |
---|
| | |
---|
| | class SymbolTable(object): |
---|
| | |
---|
| | Symbols = {} |
---|
| | DebugMsgs = [] |
---|
| | ErrMsgs = [] |
---|
| | WarnMsgs = [] |
---|
| | LiteralLines = [] |
---|
| | ALLOWNEWVAR = True |
---|
| | TEMPLATES = {} |
---|
| | TEMPONLY = False |
---|
| | LITERALVARS = False |
---|
| | INLITERAL = False |
---|
| | DEBUG = False |
---|
| | CondStack = [["", True],] # Always has one entry as a sentinel |
---|
| | TotalLines = 0 |
---|
| | |
---|
| | # End of class 'SymbolTable' |
---|
| | |
---|
| | |
---|
| | # The descriptor is an object with the following attributes |
---|
| | # |
---|
| | # Value, Writeable, Type, Default, LegalVals = [list of legal vals], Min, Max] |
---|
| | |
---|
| | |
---|
| |
---|
| | |
---|
| | # End of class 'VarDescriptor' |
---|
| | |
---|
| | |
---|
| | # Initialize the table using the predefined symbols |
---|
| | |
---|
| | SymTable = {} |
---|
| | |
---|
| | |
---|
| | SymTable = SymbolTable() |
---|
| | |
---|
| | for var in Predefined.keys(): |
---|
| | |
---|
| | d = VarDescriptor() |
---|
| | d.Value = Predefined[var] |
---|
| | d.Writeable = False |
---|
| | SymTable[var] = d |
---|
| | SymTable.Symbols[var] = d |
---|
| | |
---|
| | |
---|
| | ########## |
---|
| | # Error, Warning, And Debug Message Strings Stored In A Global Dictionary |
---|
| |
---|
| | ########## |
---|
| | |
---|
| | def DebugMsg(dmsg, args): |
---|
| | |
---|
| | global DebugMsgs |
---|
| | global SymTable |
---|
| | |
---|
| | DebugMsgs.append(mkmsg(Messages[dmsg] % args, dmsg)) |
---|
| | SymTable.DebugMsgs.append(mkmsg(Messages[dmsg] % args, dmsg)) |
---|
| | |
---|
| | # End of 'DebugMsg()' |
---|
| | |
---|
| | |
---|
| |
---|
| | ########## |
---|
| | |
---|
| | def ErrorMsg(error, args): |
---|
| | |
---|
| | global ErrMsgs |
---|
| | global SymTable |
---|
| | |
---|
| | ErrMsgs.append(mkmsg(Messages[error] % args + "!", error)) |
---|
| | SymTable.ErrMsgs.append(mkmsg(Messages[error] % args + "!", error)) |
---|
| | |
---|
| | # End of 'ErrorMsg()' |
---|
| | |
---|
| | |
---|
| |
---|
| | ########## |
---|
| | |
---|
| | def WarningMsg(warning, args): |
---|
| | |
---|
| | global WarnMsgs |
---|
| | global SymTable |
---|
| | |
---|
| | WarnMsgs.append(mkmsg(Messages[warning] % args + "!", warning)) |
---|
| | SymTable.WarnMsgs.append(mkmsg(Messages[warning] % args + "!", warning)) |
---|
| | |
---|
| | # End of 'WarningMsg()' |
---|
| | |
---|
| | |
---|
| |
---|
| | #----------------------------------------------------------# |
---|
| | |
---|
| | def ParseConfig(cfgfile, |
---|
| | CallingProgram=PROGINFO, |
---|
| | InitialSymTable={}, |
---|
| | InitialSymTable=SymbolTable(), |
---|
| | AllowNewVars=True, |
---|
| | Templates={}, |
---|
| | TemplatesOnly=False, |
---|
| | LiteralVars=False, |
---|
| | ReturnPredefs=True, |
---|
| | Debug=False): |
---|
| | |
---|
| | global DebugMsgs, ErrMsgs, WarnMsgs, LiteralLines |
---|
| | global ALLOWNEWVAR, TEMPLATES, TEMPONLY, LITERALVARS, INLITERAL, DEBUG |
---|
| | global CondStack, SymTable, TotalLines |
---|
| | global SymTable |
---|
| | |
---|
| | # Initialize the globals |
---|
| | |
---|
| | DebugMsgs = [] |
---|
| | ErrMsgs = [] |
---|
| | WarnMsgs = [] |
---|
| | LiteralLines = [] |
---|
| | |
---|
| | ALLOWNEWVAR = AllowNewVars |
---|
| | TEMPLATES = Templates |
---|
| | TEMPONLY = TemplatesOnly |
---|
| | LITERALVARS = LiteralVars |
---|
| | INLITERAL = False |
---|
| | DEBUG = Debug |
---|
| | |
---|
| | CondStack = [["", True],] # Always has one entry as a sentinel |
---|
| | TotalLines = 0 |
---|
| | |
---|
| | # Set the name of the calling program for output messages |
---|
| | |
---|
| | mkmsg.proginfo = CallingProgram |
---|
| | |
---|
| | |
---|
| | # Setup container to return parsing results |
---|
| | |
---|
| | retobj = RetObj() |
---|
| | # Create a new symbol table |
---|
| | |
---|
| | SymTable = SymbolTable() |
---|
| | |
---|
| | # Initialize the globals |
---|
| | |
---|
| | SymTable.ALLOWNEWVAR = AllowNewVars |
---|
| | SymTable.TEMPLATES = Templates |
---|
| | SymTable.TEMPONLY = TemplatesOnly |
---|
| | SymTable.LITERALVARS = LiteralVars |
---|
| | SymTable.INLITERAL = False |
---|
| | SymTable.DEBUG = Debug |
---|
| | |
---|
| | |
---|
| | # Add any passed symbols to the SymbolTable |
---|
| | |
---|
| | deserror = False |
---|
| | for sym in InitialSymTable: |
---|
| | |
---|
| | des = InitialSymTable[sym] |
---|
| | for sym in InitialSymTable.Symbols: |
---|
| | |
---|
| | des = InitialSymTable.Symbols[sym] |
---|
| | |
---|
| | # Make sure a valid descriptor was passed for each variable |
---|
| | |
---|
| | desok = True |
---|
| |
---|
| | ErrorMsg("eDESCRIPTBAD", (eBADMINMAX, sym)) |
---|
| | |
---|
| | # Only load the symbol table with valid entries |
---|
| | if desok: |
---|
| | SymTable[sym] = des |
---|
| | SymTable.Symbols[sym] = des |
---|
| | |
---|
| | # Indicate that a problem was encountered |
---|
| | else: |
---|
| | deserror = True |
---|
| | |
---|
| | # If any of the passed symbols had bogus descriptor contents, we're done |
---|
| | |
---|
| | if deserror: |
---|
| | |
---|
| | retobj.SymTable = SymTable |
---|
| | retobj.Errors = ErrMsgs |
---|
| | retobj.Warnings = WarnMsgs |
---|
| | retobj.Debug = DebugMsgs |
---|
| | retobj.Literals = LiteralLines |
---|
| | return retobj |
---|
| | return SymTable |
---|
| | |
---|
| | |
---|
| | # Symbol Table passed to API was OK, so keep going |
---|
| | |
---|
| | # Make sure the symbol table has a valid namespace |
---|
| | |
---|
| | if NAMESPACE not in SymTable: |
---|
| | SymTable[NAMESPACE] = VarDescriptor() |
---|
| | SymTable[NAMESPACE].Value = "" |
---|
| | if NAMESPACE not in SymTable.Symbols: |
---|
| | SymTable.Symbols[NAMESPACE] = VarDescriptor() |
---|
| | SymTable.Symbols[NAMESPACE].Value = "" |
---|
| | |
---|
| | # Otherwise, ensure that the initial namespace is properly formed. |
---|
| | # If not, revert to root namespace. |
---|
| | |
---|
| | elif not ValidateSymbolName(SymTable[NAMESPACE].Value, STARTUP, STARTUP, AllowEmpty=True): |
---|
| | SymTable[NAMESPACE].Value = "" |
---|
| | elif not ValidateSymbolName(SymTable.Symbols[NAMESPACE].Value, STARTUP, STARTUP, AllowEmpty=True): |
---|
| | SymTable.Symbols[NAMESPACE].Value = "" |
---|
| | |
---|
| | # Report namespace to debug output |
---|
| | |
---|
| | if DEBUG: |
---|
| | DebugMsg("dNAMESPACE", (STARTUP, STARTUP, SymTable[NAMESPACE].Value)) |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dNAMESPACE", (STARTUP, STARTUP, SymTable.Symbols[NAMESPACE].Value)) |
---|
| | |
---|
| | |
---|
| | # Parse the file |
---|
| | |
---|
| | ParseFile(cfgfile, eSTARTUP, 0) |
---|
| | |
---|
| | # Make sure we had all condition blocks balanced with matching '.endif' |
---|
| | |
---|
| | finalcond = len(CondStack) |
---|
| | finalcond = len(SymTable.CondStack) |
---|
| | if finalcond != 1: |
---|
| | ErrorMsg("eENDIFMISS", (cfgfile, ATEOF, finalcond-1)) |
---|
| | |
---|
| | # Make sure we ended any literal processing properly |
---|
| | if INLITERAL: |
---|
| | if SymTable.INLITERAL: |
---|
| | WarningMsg("wENDLITMISS", (cfgfile, ATEOF)) |
---|
| | |
---|
| | # Return the parsing results |
---|
| | |
---|
| | if DEBUG: |
---|
| | DebugMsg("dNUMLINES", (cfgfile, TotalLines)) |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dNUMLINES", (cfgfile, SymTable.TotalLines)) |
---|
| | |
---|
| | # Strip out Prefefined Variables if user does not want them |
---|
| | |
---|
| | if not ReturnPredefs: |
---|
| | |
---|
| | del SymTable[NAMESPACE] |
---|
| | del SymTable.Symbols[NAMESPACE] |
---|
| | for sym in Predefined: |
---|
| | del SymTable[sym] |
---|
| | |
---|
| | |
---|
| | retobj.SymTable = SymTable |
---|
| | retobj.Errors = ErrMsgs |
---|
| | retobj.Warnings = WarnMsgs |
---|
| | retobj.Debug = DebugMsgs |
---|
| | retobj.Literals = LiteralLines |
---|
| | |
---|
| | return retobj |
---|
| | del SymTable.Symbols[sym] |
---|
| | |
---|
| | |
---|
| | return SymTable |
---|
| | |
---|
| | |
---|
| | # End of 'ParseConfig()' |
---|
| | |
---|
| |
---|
| | |
---|
| | # Prepend the current namespace unless we are in the top-level |
---|
| | # namespace. |
---|
| | |
---|
| | elif SymTable[NAMESPACE].Value: |
---|
| | sym = "%s%s%s" % (SymTable[NAMESPACE].Value, NSSEP, sym) |
---|
| | elif SymTable.Symbols[NAMESPACE].Value: |
---|
| | sym = "%s%s%s" % (SymTable.Symbols[NAMESPACE].Value, NSSEP, sym) |
---|
| | |
---|
| | # Handle environment variables |
---|
| | if sym and sym[0] == ENVIRO and sym[1:] in os.environ: |
---|
| | envvar = os.getenv(sym[1:]) |
---|
| | line = line.replace(var, envvar) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dVARREF", (cfgfile, linenum, var, envvar)) |
---|
| | |
---|
| | # Handle variables in symbol table |
---|
| | elif sym in SymTable: |
---|
| | symval = str(SymTable[sym].Value) |
---|
| | elif sym in SymTable.Symbols: |
---|
| | symval = str(SymTable.Symbols[sym].Value) |
---|
| | line = line.replace(var, symval) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dVARREF", (cfgfile, linenum, var, symval)) |
---|
| | |
---|
| | |
---|
| | # Reference to undefined variable |
---|
| |
---|
| | ########## |
---|
| | |
---|
| | def ParseFile(cfgfile, current_cfg, current_linenum): |
---|
| | |
---|
| | global IgnoreCase, MsgList, SymTable, TotalLines |
---|
| | global MsgList, SymTable |
---|
| | |
---|
| | |
---|
| | linenum=0 |
---|
| | |
---|
| |
---|
| | |
---|
| | # Process and massage the configuration file |
---|
| | for line in cf.read().splitlines(): |
---|
| | linenum += 1 |
---|
| | TotalLines += 1 |
---|
| | SymTable.TotalLines += 1 |
---|
| | |
---|
| | # Parse this line |
---|
| | ParseLine(line, cfgfile, linenum) |
---|
| | |
---|
| |
---|
| | ########## |
---|
| | |
---|
| | def ParseLine(line, cfgfile, linenum): |
---|
| | |
---|
| | global CondStack, MsgList, SymTable, INLITERAL |
---|
| | global MsgList, SymTable |
---|
| | |
---|
| | orig = line # May need copy of original for debug output |
---|
| | |
---|
| | |
---|
| |
---|
| | |
---|
| | if line.strip() in (LITERAL, ENDLITERAL): |
---|
| | |
---|
| | if line.strip() == LITERAL: |
---|
| | if INLITERAL: |
---|
| | if SymTable.INLITERAL: |
---|
| | WarningMsg("wLITEXTRA", (cfgfile, linenum)) |
---|
| | else: |
---|
| | INLITERAL = True |
---|
| | SymTable.INLITERAL = True |
---|
| | |
---|
| | # Process ENDLITERAL statements |
---|
| | else: |
---|
| | if not INLITERAL: |
---|
| | if not SymTable.INLITERAL: |
---|
| | WarningMsg("wENDLITEXTRA", (cfgfile, linenum)) |
---|
| | else: |
---|
| | INLITERAL = False |
---|
| | |
---|
| | |
---|
| | if DEBUG: |
---|
| | SymTable.INLITERAL = False |
---|
| | |
---|
| | |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | # literal blocks. But, only if we're inside a True conditional |
---|
| | # block. |
---|
| | ##### |
---|
| | |
---|
| | if INLITERAL: |
---|
| | |
---|
| | if CondStack[-1][1]: |
---|
| | |
---|
| | if LITERALVARS: |
---|
| | if SymTable.INLITERAL: |
---|
| | |
---|
| | if SymTable.CondStack[-1][1]: |
---|
| | |
---|
| | if SymTable.LITERALVARS: |
---|
| | line, ref_ok = DerefVar(line, cfgfile, linenum) |
---|
| | |
---|
| | LiteralLines.append(line) |
---|
| | |
---|
| | if DEBUG: |
---|
| | SymTable.LiteralLines.append(line) |
---|
| | |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | |
---|
| | # Conditional block was false, so just throw away the line, |
---|
| | # noting in debug output if requested. |
---|
| | |
---|
| | else: |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dNOTINCLUDE)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | # Line was blank |
---|
| | if not line: |
---|
| | |
---|
| | # Note blank lines for debug purposes |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dBLANKLINE)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | if line == ELSE: |
---|
| | |
---|
| | # Get the enclosing block type and state |
---|
| | |
---|
| | btyp, bst = CondStack.pop() |
---|
| | btyp, bst = SymTable.CondStack.pop() |
---|
| | |
---|
| | # ELSE is only permitted after an immediately preceding IF form |
---|
| | |
---|
| | |
---|
| | if btyp != IF: |
---|
| | ErrorMsg("eELSENOIF", (cfgfile, linenum)) |
---|
| | CondStack.append(["", False]) # Error makes all that follows False |
---|
| | SymTable.CondStack.append(["", False]) # Error makes all that follows False |
---|
| | |
---|
| | # We *are* in an IF block an ELSE is appropriate. |
---|
| | # To determine whether the ELSE should be taken or not we have |
---|
| | # to look at the state of that IF block AND the state of |
---|
| |
---|
| | |
---|
| | # If the containing block is True, the contained IF state is legitimate. |
---|
| | # The ELSE inverts the IF state in that case. |
---|
| | |
---|
| | if CondStack[-1][1]: |
---|
| | CondStack.append([ELSE, not bst]) |
---|
| | if SymTable.CondStack[-1][1]: |
---|
| | SymTable.CondStack.append([ELSE, not bst]) |
---|
| | |
---|
| | # The containing block is false, so everything within it is also false |
---|
| | |
---|
| | else: |
---|
| | CondStack.append([ELSE, False]) |
---|
| | SymTable.CondStack.append([ELSE, False]) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | |
---|
| | if line == ENDIF: |
---|
| | |
---|
| | # Remove one level of conditional nesting |
---|
| | CondStack.pop() |
---|
| | SymTable.CondStack.pop() |
---|
| | |
---|
| | # Error, if there are more .endifs than conditionals |
---|
| | if not CondStack: |
---|
| | if not SymTable.CondStack: |
---|
| | ErrorMsg("eENDIFEXTRA", (cfgfile, linenum)) |
---|
| | CondStack.append(["", False]) # Restore sentinel & inhibit further parsing |
---|
| | |
---|
| | if DEBUG: |
---|
| | SymTable.CondStack.append(["", False]) # Restore sentinel & inhibit further parsing |
---|
| | |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | ##### |
---|
| | |
---|
| | if FIRSTTOK == INCLUDE: |
---|
| | |
---|
| | if not CondStack[-1][1]: |
---|
| | if DEBUG: |
---|
| | if not SymTable.CondStack[-1][1]: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dNOTINCLUDE)) |
---|
| | return |
---|
| | |
---|
| | line, ref_ok = DerefVar(line.split(INCLUDE)[1].strip(), cfgfile, linenum) |
---|
| |
---|
| | # Only attempt the include if all the variable dereferencing was successful |
---|
| | if ref_ok: |
---|
| | ParseFile(line, cfgfile, linenum) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | # 3) We're dealing with a predefined variable |
---|
| | # 4) We're dealing with the NAMESPACE variable |
---|
| | # 5) The variable name is not escaped |
---|
| | |
---|
| | ns = SymTable[NAMESPACE].Value |
---|
| | ns = SymTable.Symbols[NAMESPACE].Value |
---|
| | |
---|
| | if ns and \ |
---|
| | v[0] != ENVIRO and \ |
---|
| | v not in Predefined and \ |
---|
| |
---|
| | else: |
---|
| | v = "%s%s%s" % (ns, NSSEP, v) |
---|
| | |
---|
| | # Produce debug ouput of actual variable name being checked |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dVAREXISTS", (cfgfile, linenum, v)) |
---|
| | |
---|
| | # Handle environment variables |
---|
| | if v[0] == ENVIRO: |
---|
| | if v[1:] in os.environ: |
---|
| | numexist += 1 |
---|
| | |
---|
| | # Handle local local variables |
---|
| | elif v in SymTable: |
---|
| | elif v in SymTable.Symbols: |
---|
| | numexist += 1 |
---|
| | |
---|
| | # And set the conditional state accordingly |
---|
| | |
---|
| |
---|
| | |
---|
| | # Set parser state based on a successful conditional test |
---|
| | # But it has to be ANDed with the state of the enclosing block |
---|
| | |
---|
| | enclosing = CondStack[-1][1] |
---|
| | CondStack.append([IF, condstate and enclosing]) |
---|
| | enclosing = SymTable.CondStack[-1][1] |
---|
| | SymTable.CondStack.append([IF, condstate and enclosing]) |
---|
| | |
---|
| | # Now reflect this in the parsed line |
---|
| | line = sTRUE |
---|
| | if not condstate: |
---|
| | line = sFALSE |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | # definition/assignment. |
---|
| | |
---|
| | elif EQUAL in line: |
---|
| | |
---|
| | if not CondStack[-1][1]: |
---|
| | if DEBUG: |
---|
| | if not SymTable.CondStack[-1][1]: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dLINEIGNORE", (cfgfile, linenum, orig, dNOTINCLUDE)) |
---|
| | return |
---|
| | |
---|
| | # Catch attempts to dereference without name anywhere in the line |
---|
| | |
---|
| | if line.count(DELIML + DELIMR): |
---|
| | ErrorMsg("eSYMNONAME", (cfgfile, linenum)) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | # variables in the namespace munging below. IOW, Don't |
---|
| | # move this test down into the body of the variable name |
---|
| | # processing where namespace fiddling takes place. |
---|
| | |
---|
| | elif l in SymTable and not SymTable[l].Writeable: |
---|
| | elif l in SymTable.Symbols and not SymTable.Symbols[l].Writeable: |
---|
| | ErrorMsg("eVARREADONLY", (cfgfile, linenum, l)) |
---|
| | |
---|
| | # Load variable into the symbol table |
---|
| | else: |
---|
| |
---|
| | |
---|
| | # In all other cases prepend current namespace |
---|
| | else: |
---|
| | varname = l |
---|
| | ns = SymTable[NAMESPACE].Value |
---|
| | ns = SymTable.Symbols[NAMESPACE].Value |
---|
| | |
---|
| | # Top level namespace variables don't need |
---|
| | # separator. |
---|
| | |
---|
| |
---|
| | # If this is a newly defined variable, set its |
---|
| | # default to be this first value assigned and |
---|
| | # create the new entry |
---|
| | |
---|
| | if l not in SymTable: |
---|
| | if l not in SymTable.Symbols: |
---|
| | |
---|
| | # Only do this if new variable creation allowed |
---|
| | if ALLOWNEWVAR: |
---|
| | if SymTable.ALLOWNEWVAR: |
---|
| | |
---|
| | # Rules for new variable creation: |
---|
| | # |
---|
| | # 1) If var has a template, use it |
---|
| |
---|
| | # 3) If var has no template, and TemplatesOnly=False -> Create new var |
---|
| | |
---|
| | # Rule 1 |
---|
| | |
---|
| | if varname in TEMPLATES: |
---|
| | if varname in SymTable.TEMPLATES: |
---|
| | |
---|
| | # Create the new variable |
---|
| | |
---|
| | SymTable[l] = TEMPLATES[varname] |
---|
| | SymTable.Symbols[l] = SymTable.TEMPLATES[varname] |
---|
| | |
---|
| | # Load the proposed value only if valid |
---|
| | |
---|
| | if ValidateValue(l, r, cfgfile, linenum): |
---|
| | SymTable[l].Value = r |
---|
| | SymTable.Symbols[l].Value = r |
---|
| | |
---|
| | # If value is invalid, remove this |
---|
| | # variable. We cannot create a new |
---|
| | # variable on an error. Errors are |
---|
| | # actually reported by the validation |
---|
| | # function. |
---|
| | |
---|
| | else: |
---|
| | del(SymTable[l]) |
---|
| | del(SymTable.Symbols[l]) |
---|
| | |
---|
| | # Rule 2 |
---|
| | |
---|
| | elif TEMPONLY: |
---|
| | elif SymTable.TEMPONLY: |
---|
| | ErrorMsg("eTEMPONLY", (cfgfile, linenum, varname)) |
---|
| | |
---|
| | # Rule 3 |
---|
| | |
---|
| |
---|
| | |
---|
| | d = VarDescriptor() |
---|
| | d.Default = r |
---|
| | d.Value = r |
---|
| | SymTable[l] = d |
---|
| | SymTable.Symbols[l] = d |
---|
| | |
---|
| | # New vars not allowed |
---|
| | else: |
---|
| | ErrorMsg("eVARNEW", (cfgfile, linenum)) |
---|
| |
---|
| | # Translate various strings to their |
---|
| | # equivalent logical value for boolean |
---|
| | # variables first |
---|
| | |
---|
| | if SymTable[l].Type == TYPE_BOOL: |
---|
| | if SymTable.Symbols[l].Type == TYPE_BOOL: |
---|
| | r = Booleans[r.capitalize()] |
---|
| | |
---|
| | SymTable[l].Value = r |
---|
| | SymTable.Symbols[l].Value = r |
---|
| | |
---|
| | # Produce debug output when we change namespaces |
---|
| | if DEBUG and l == NAMESPACE: |
---|
| | if SymTable.DEBUG and l == NAMESPACE: |
---|
| | DebugMsg("dNAMESPACE", (cfgfile, linenum, r)) |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dPARSEDLINE", (cfgfile, linenum, orig, line)) |
---|
| | |
---|
| | return |
---|
| | |
---|
| |
---|
| | if not ValidateSymbolName(r, cfgfile, linenum, AllowEmpty=True): |
---|
| | update = False # Validation function issues appropriate errors |
---|
| | |
---|
| | |
---|
| | des = SymTable[l] |
---|
| | des = SymTable.Symbols[l] |
---|
| | typ = des.Type |
---|
| | lv = des.LegalVals |
---|
| | low = des.Min |
---|
| | up = des.Max |
---|
| |
---|
| | |
---|
| | # This can be kind of complex, so produce |
---|
| | # debug output here to help the poor user |
---|
| | |
---|
| | if DEBUG: |
---|
| | if SymTable.DEBUG: |
---|
| | DebugMsg("dREGEXMATCH", (cfgfile, linenum, r, rex, l)) |
---|
| | |
---|
| | except: |
---|
| | ErrorMsg("eBADREGEX", (cfgfile, linenum, rex, l)) |
---|
| |
---|
| | #----------------------------------------------------------# |
---|
| | |
---|
| | |
---|
| | __all__ = ["ParseConfig", |
---|
| | "RetObj", |
---|
| | "SymbolTable", |
---|
| | "TYPE_BOOL", |
---|
| | "TYPE_COMPLEX", |
---|
| | "TYPE_FLOAT", |
---|
| | "TYPE_INT", |
---|
| |
---|
| | |