diff --git a/tconfpy.3 b/tconfpy.3 index c6c5395..57c0468 100644 --- a/tconfpy.3 +++ b/tconfpy.3 @@ -1,5 +1,5 @@ .ds CP 2003-2004 -.ds TC \'tconfpy\' +.ds TC \fCtconfpy\fP .TH TCONFPY 3 "TundraWare Inc." .SH NAME tconfpy.py @@ -54,7 +54,7 @@ .B INSTALLATION explains how to install this package on various platforms. This -information can also be found in the \'READ-1ST.txt\' file distributed +information can also be found in the \fCREAD-1ST.txt\fP file distributed with the package. @@ -84,11 +84,11 @@ .ft \" revert you will have to prepend all references to a \*(TC object with -\'tconfpy.\'. So \'retval=ParseConfig(...\' becomes -\'retval = tconfpy.ParseConfig(...\' and so on. +\fCtconfpy.\fP. So \fCretval=ParseConfig(...\fP becomes +\fCretval = tconfpy.ParseConfig(...\fP and so on. You will also find the test driver code provided in the \*(TC package -helpful as you read through the following sections. \'test-tc.py\' is +helpful as you read through the following sections. \fCtest-tc.py\fP is a utility to help you learn and exercise the \*(TC API. Perusing the code therein is helpful as an example of the topics discussed below. @@ -125,7 +125,7 @@ A prepopulated symbol table (a Python dictionary). As described -below, this must contain valid \'VarDescriptor\' entries for each +below, this must contain valid \fCVarDescriptor\fP entries for each symbol in the table. .TP @@ -139,8 +139,8 @@ If set to \fCTrue\fP this option enables variable substitutions within -\'.literal\' blocks of a configuration file. See the section in the -language reference below on \'.literal\' usage for details. +\fC.literal\fP blocks of a configuration file. See the section in the +language reference below on \fC.literal\fP usage for details. .TP .B Debug (Default: \fCFalse\fP) @@ -153,7 +153,7 @@ .B retval -An object of type \'tconfpy.RetObj\' used to return parsing results. +An object of type \fCtconfpy.RetObj\fP used to return parsing results. .SS The Initial Symbol Table API Option @@ -168,7 +168,7 @@ .fi .ft \" revert -Assuming your configuration file is valid, \'ParseConfig()\' will +Assuming your configuration file is valid, \fCParseConfig()\fP will return a symbol table populated with all the variables defined in the file and their associated values. This symbol table will have .B only @@ -197,7 +197,7 @@ In this example, only the calling application can know its own version, so it sets the variable APPVERSION in a symbol table -which is passed to \'ParseConfig()\'. +which is passed to \fCParseConfig()\fP. .IP \(bu 4 You may wish to "protect" certain variable names be creating @@ -255,7 +255,7 @@ .ft \" revert -The heart of this whole business the \'VarDescriptor\' object. It +The heart of this whole business the \fCVarDescriptor\fP object. It "describes" the value and properties of a variable. These descriptor objects have the following attributes and defaults: @@ -309,7 +309,7 @@ checks to see if that variable already exists in the symbol table. If it does, the parser checks the value being assigned and makes sure it matches the type declared for that variable. For example, -suppose you did this when defining the variable, \'foo\': +suppose you did this when defining the variable, \fCfoo\fP: .ft C \" Courier .nf @@ -325,7 +325,7 @@ .fi .ft \" revert -This will cause a type mismatch error because \'bar\' cannot be coerced +This will cause a type mismatch error because \fCbar\fP cannot be coerced into an integer type - it is a string. @@ -333,7 +333,7 @@ the right-hand-side of an assignment to the type declared for that variable. The least fussy operation here is when the variable is defined as TYPE_STRING because pretty much everything can be coerced -into a string. For example, here is how \'foo = 3+8j\' is treated for +into a string. For example, here is how \fCfoo = 3+8j\fP is treated for different type declarations: @@ -347,7 +347,7 @@ TYPE_COMPLEX 3+8j (A complex number) TYPE_FLOAT Type Error TYPE_INT Type Error -TYPE_STRING \'3+8j\' (A string) +TYPE_STRING "3+8j" (A string) .fi .ft \" revert @@ -372,7 +372,7 @@ .B VarDescriptor.LegalVals (Default: \fC[]\fP) Sometimes you want to limit a variable to a specific set of values. -That's what this attribute is for. \'LegalVals\' explictly lists +That's what this attribute is for. \fCLegalVals\fP explictly lists every legal value for the variable in question. If the list is empty,then this validation check is skipped. @@ -405,7 +405,7 @@ The general semantic here is "If Legal Vals is not an empty list, the user must assign a value that matches one of the items in LegalVals." -One special note applies to \'LegalVals\' for string variables. \*(TC +One special note applies to \fCLegalVals\fP for string variables. \*(TC always assumes that this list contains Python regular expressions. For validation, it grabs each entry in the list, attempts to compile it as a regex, and checks to see if the value the user wants to set @@ -415,8 +415,8 @@ You may also want to specify a set of legal strings that are .B exact matches not open-ended regular expressions. For example, suppose you have -a variable, \'COLOR\' and you only want the user to be able to only set it -to one of, \'Red\', \'White\', or \'Blue\'. In that case, use the Python +a variable, \fCCOLOR\fP and you only want the user to be able to only set it +to one of, \fCRed\fP, \fCWhite\fP, or \fCBlue\fP. In that case, use the Python regular expression metacharacters that indicate "Start Of String" and "End Of String" do do this: @@ -431,9 +431,9 @@ .ft \" revert .B NOTE: -If you want this test to be skipped, then set \'LegalVals\' to an +If you want this test to be skipped, then set \fCLegalVals\fP to an empty list, []. (This is the default when you first create an -instance of \'tconfpy.VarDescriptor\'.) Do not set it to a Python +instance of \fCtconfpy.VarDescriptor\fP.) Do not set it to a Python None or anything else. \*(TC expects this attribute to be a list in every case. @@ -460,8 +460,8 @@ .fi .ft \" revert -In all cases, if you want either of these tests skipped, set \'Min\' -or \'Max\' to the Python None. +In all cases, if you want either of these tests skipped, set \fCMin\fP +or \fCMax\fP to the Python None. .P All these various validations are logically "ANDed" together. @@ -471,10 +471,10 @@ \*(TC makes no attempt to harmonize these validation conditions with each other. If you specify a value in -\'LegalVals\' that is, say, lower than allowed by -\'Min\' you will always get an error when the user sets -the variable to that value: It passed the \'LegalVals\' -validation but failed it for \'Min\'. +\fCLegalVals\fP that is, say, lower than allowed by +\fCMin\fP you will always get an error when the user sets +the variable to that value: It passed the \fCLegalVals\fP +validation but failed it for \fCMin\fP. .SS The Initial Symbol Table And Lexical Namespaces @@ -485,42 +485,42 @@ user's point-of-view. However, it is useful for the programmer to understand how they are implemented. -\*(TC is written to use a predefined variable named \'NAMESPACE\' as +\*(TC is written to use a predefined variable named \fCNAMESPACE\fP as the place where the current namespace is kept. If you do not define this variable in the initial symbol table passed to the parser, \*(TC will create it automatically with an initial value of "". From a programmer's perspective, there are are few important things -to know about namespaces and the \'NAMESPACE\' variable: +to know about namespaces and the \fCNAMESPACE\fP variable: .IP \(bu 4 You can manually set the initial namespace to something other than "". -You do this by creating the \'NAMESPACE\' variable in the initial -symbol table passed to the parser, and setting the \'Value\' attribute +You do this by creating the \fCNAMESPACE\fP variable in the initial +symbol table passed to the parser, and setting the \fCValue\fP attribute of its descriptor to whatever you want as the initial namespace. At startup \*(TC will check this initial value to make sure it conforms to the rules for properly formed names - i.e., It it will check for -blank space, a leading \'$\, the presence of square brackets, and so +blank space, a leading \fC$\fP, the presence of square brackets, and so on. If the initial namespace value you provide is illegal, \*(TC will produce an error and reset the initial namespace to "". .IP \(bu 4 -Because lexical namespaces are implemented by treating \'NAMESPACE\' +Because lexical namespaces are implemented by treating \fCNAMESPACE\fP as just another variable, all the type and value validations available -for string variables can be applied to \'NAMESPACE\'. As discussed above, +for string variables can be applied to \fCNAMESPACE\fP. As discussed above, this means you can limit the length and content of what the user assigns -to \'NAMESPACE\'. In effect, this means you can limit the number and +to \fCNAMESPACE\fP. In effect, this means you can limit the number and name of namespaces available for use by the user. There is one slight difference here than for other variables. .B The root namespace is always legal, regardless of what other limitations you may impose via -the \'LegalVals\', \'Min\', and \'Max\' attributes of the \'NAMESPACE\' +the \fCLegalVals\fP, \fCMin\fP, and \fCMax\fP attributes of the \fCNAMESPACE\fP variable descriptor. .IP \(bu 4 -When the call to \'ParseConfig()\' completes, the \'Value\' -attribute of the \'NAMESPACE\' variable descriptor will contain +When the call to \fCParseConfig()\fP completes, the \fCValue\fP +attribute of the \fCNAMESPACE\fP variable descriptor will contain the namespace that was in effect when the parse completed. i.e., It will contain the last namespace used. @@ -529,7 +529,7 @@ When you pass an initial symbol table to the parser, \*(TC does some basic validation that the table contents properly conform to the -\'VarDescriptor\' format and generates error messages if it finds +\fCVarDescriptor\fP format and generates error messages if it finds problems. However, the program does .B not check your specifications to see if they make sense. For instance @@ -537,11 +537,11 @@ value of 50, \*(TC cheerfully accepts these limits even they they are impossible. You'll just be unable to do anything with that variable - any attempt to change its value will cause an error -to be recorded. Similarly, if you put a value in \'LegalVals\' that -is outside the range of \'Min\' to \'Max\', \*(TC will accept +to be recorded. Similarly, if you put a value in \fCLegalVals\fP that +is outside the range of \fCMin\fP to \fCMax\fP, \*(TC will accept it quietly. -.SS The \'AllowNewVars\' API Option +.SS The \fCAllowNewVars\fP API Option By default, \*(TC lets the user define any new variables they wish in a configuration file, merely by placing a line in the @@ -583,8 +583,8 @@ .IP \(bu 4 You want to insulate your user from silent errors caused by misspellings. Say your program looks for a configuration -variable called \'MyEmail\' but the user enters something -like \'myemail = foo@bar.com\'. \'MyEmail\' and \'myemail\' +variable called \fCMyEmail\fP but the user enters something +like \fCmyemail = foo@bar.com\fP. \fCMyEmail\fP and \fCmyemail\fP are entirely different variables and only the former is recognized by your calling program. By turning off new variable creation, the user's inadvertent misspelling of @@ -609,18 +609,18 @@ .ft \" revert If you disable new variable creation you can't do this -anymore unless all the variables \'inter1\', \'inter2\', -and \'realvar\' are predefined in the initial symbol +anymore unless all the variables \fCinter1\fP, \fCinter2\fP, +and \fCrealvar\fP are predefined in the initial symbol table passed to the parser. -.SS The \'LiteralVars\' API Option +.SS The \fCLiteralVars\fP API Option \*(TC supports the inclusion of literal text anywhere in a -configuration file via the \'.literal\' directive. This +configuration file via the \fC.literal\fP directive. This directive effectively tells the \*(TC parser to pass every line it encounters "literally" until it sees a -corresponding \'.endlinteral\' directive. By default, +corresponding \fC.endlinteral\fP directive. By default, \*(TC does .B exactly this. However, \*(TC has very powerful variable substitution @@ -639,8 +639,8 @@ .fi .ft \" revert -By default, \'ParseConfig()\' will leave everything within -the \'.literal\'/\'.endliteral\' block unchanged. In our +By default, \fCParseConfig()\fP will leave everything within +the \fC.literal\fP/\fC.endliteral\fP block unchanged. In our example, the string: .ft C \" Courier @@ -649,12 +649,12 @@ .fi .ft \" revert -would be in the list of literals returned by \'ParseConfig()\'. +would be in the list of literals returned by \fCParseConfig()\fP. However, we can ask \*(TC to do variable replacement .B within -literal blocks by setting \'LiteralVars=True\' in the -\'ParseConfig()\' call: +literal blocks by setting \fCLiteralVars=True\fP in the +\fCParseConfig()\fP call: .ft C \" Courier .nf @@ -682,12 +682,12 @@ other language or text. -.SS The \'Debug\' API Option +.SS The \fCDebug\fP API Option \*(TC has a fairly rich set of debugging features built into its parser. It can provide some detail about each line parsed as well as overall information about the parse. Be default, debugging is -turned off. To enable debugging, merely set \'Debug=True' in the +turned off. To enable debugging, merely set \fCDebug=True\fP in the API call: .ft C \" Courier @@ -718,7 +718,7 @@ (if you requested this via the API), and any "literal" lines encountred in the configuration. -The return object is an instance of the class \'twander.RetObj\' which is +The return object is an instance of the class \fCtwander.RetObj\fP which is nothing more than a container to hold return data. In the simplest case, we can parse and extract results like this: @@ -730,7 +730,7 @@ .fi .ft \" revert -\'retval\' now contains the results of the parse: +\fCretval\fP now contains the results of the parse: .TP .B retval.Errors @@ -756,7 +756,7 @@ .B retval.Literals As described below, the \*(TC configuration language supports a -\'.literal\' directive. This directive allows the user to embed +\fC.literal\fP directive. This directive allows the user to embed literal text anywhere in the configuration file. This effectively makes \*(TC useful as a preprocessor for any other language or text. retval.Literals is a Python list containing all literal text @@ -768,7 +768,7 @@ A Python list containing detailed debug information for each line parsed as well as some brief summary information about the parse. retval.Debug defaults to an empty list and is only populated if you -set \'Debug=True\' in the API call that initiated the parse (as in the +set \fCDebug=True\fP in the API call that initiated the parse (as in the example above). @@ -792,9 +792,9 @@ "continuation". .IP \(bu 4 -The \'#'\ can begin a comment anywhere on a line. This is done +The \fC#\fP can begin a comment anywhere on a line. This is done blindly. If you need to embed this symbol somewhere within a variable -value, use the \'[HASH]\' variable reference. +value, use the \fC[HASH]\fP variable reference. .IP \(bu 4 Whitespace is (mostly) insignificant. Leading and trailing @@ -814,7 +814,7 @@ - Whitespace within both the left- and right-hand-side arguments of a conditional comparison - (\'.if ... == / != ...\') is significant for purposes + (\fC.if ... == / != ...\fP) is significant for purposes of the comparison. @@ -859,11 +859,11 @@ .fi .ft \" revert -If \'MyVariable\' is a new variable, \*(TC will create it on the spot. -If it already exists, \*(TC will first check and make sure that \'Some -string of text\' is a legal value for this variable. If not, it will +If \fCMyVariable\fP is a new variable, \*(TC will create it on the spot. +If it already exists, \*(TC will first check and make sure that \fCSome +string of text\fP is a legal value for this variable. If not, it will produce an error and refuse to change the current value of -\'MyVariable\'. +\fCMyVariable\fP. Anytime you create a new variable, the first value assigned to it is also considered its "default" value. This may (or may @@ -895,31 +895,31 @@ Variable names may not contain whitespace. .IP \(bu 4 -Variable names may not begin with the \'$\' character. The one exception +Variable names may not begin with the \fC$\fP character. The one exception to this is when you are referencing the value of an environment -variable. References to environment variables begin with \'$\': +variable. References to environment variables begin with \fC$\fP: .ft C \" Courier .nf # A reference to an environment variable is legal x = [$TERM] - # Attempting to create a new variable starting with \'$\' is illegal + # Attempting to create a new variable starting with $ is illegal $MYVAR = something .fi .ft \" revert .IP \(bu 4 -Variable names cannot have the \'#\' character anywhere in them +Variable names cannot have the \fC#\fP character anywhere in them because \*(TC sees that character as the beginning a comment. .IP \(bu 4 -Variable names cannot begin with \'.\' character. \*(TC understands +Variable names cannot begin with \fC.\fP character. \*(TC understands a leading period in a variable name to be a "namespace escape". This is discussed in a later section on lexical namespaces. .IP \(bu 4 -Variable names cannot contain the \'[\' or \']\' characters. These +Variable names cannot contain the \fC[\fP or \fC]\fP characters. These are reserved symbols used to indicate a variable .B reference. @@ -934,7 +934,7 @@ .ft \" revert .IP \(bu 4 -The variable named \'NAMESPACE\' is not available for your own +The variable named \fCNAMESPACE\fP is not available for your own use. \*(TC understands this variable to hold the current lexical namespace as described later in this document. If you set it to a new value, it will change the namespace, so be sure this is @@ -956,7 +956,7 @@ variable's value. You can also get the value of any Environment Variable on your -system by naming the variable with a leading \'$\': +system by naming the variable with a leading \fC$\fP: .ft C \" Courier .nf @@ -992,16 +992,16 @@ .IP \(bu 4 The substitution of variables takes place as soon as the parser -processes the line \'Greeting = ...\'. That is, variable substitution +processes the line \fCGreeting = ...\fP. That is, variable substitution happens as it is encountered in the configuration file. The only exception to this is if an attempt is made to refer to an undefined/non-existent variable. This generates an error. .IP \(bu 4 -The variable \'Greeting\' now contains the +The variable \fCGreeting\fP now contains the .B string "Hello Mr. Tconfpy, you look great for someone 101!" This is true even -if variable \'MYAGE\' has been defined by the calling program to be +if variable \fCMYAGE\fP has been defined by the calling program to be an integer type. To repeat a previously-made point: All variable substitution and comparison operations in a configuration file are done with .B strings @@ -1012,7 +1012,7 @@ Unless a variable as been marked as "Read Only" by the application program, you can continue to change its value as you go. Simply adding another line at the end of our example above will change the -value of \'Greeting\' to something new: +value of \fCGreeting\fP to something new: .ft C \" Courier .nf @@ -1022,7 +1022,7 @@ In other words, the last assignment statement for a given variable "wins". This may seem sort of pointless, but it actually has great -utility. You can use the \'.include\' directive to get, say, a +utility. You can use the \fC.include\fP directive to get, say, a "standard" configuration provided by the system administrator for a particular application. You can then selectively override the variables you want to change in your own configuration file. @@ -1054,8 +1054,8 @@ .fi .ft \" revert -i.e., The value \'Dad\' is assigned to a (new) variable called -\'HouseCleaning\'. In other words, putting a variable reference +i.e., The value \fCDad\fP is assigned to a (new) variable called +\fCHouseCleaning\fP. In other words, putting a variable reference on the left-hand-side of an assignment like this allows you to access another variable which is named "indirectly". @@ -1082,7 +1082,7 @@ \*(TC will produce an error if it sees such a construct. As a general matter, any variable you construct through this indirection method must still conform to all the rules of variable naming: It cannot -contain whitespace, begin with \'$\', contain \'#\', \'[\', or \']\' and +contain whitespace, begin with \fC$\fP, contain \fC#\fP, \fC[\fP, or \fC]\fP and so on. Another example of how indirection can "bite" you is when the @@ -1095,8 +1095,8 @@ .ft C \" Courier .nf NAMESPACE = NS1 - foo = .bar # Creates variable NS1.foo with value \'.bar\' - [foo] = baz # Means \'[NS1.foo] = baz\' + foo = .bar # Creates variable NS1.foo with value .bar + [foo] = baz # Means [NS1.foo] = baz .fi .ft \" revert @@ -1112,16 +1112,16 @@ .ft \" revert As you'll see in the section on Lexical Namespaces below, this actually -means, "Set the variable \'bar\' in the root namespace to the value -\'baz\'." In other words, if you do indirect variable assignment, and +means, "Set the variable \fCbar\fP in the root namespace to the value +\fCbaz\fP." In other words, if you do indirect variable assignment, and the content of that variable begins with a period, you will be creating/setting a variable in .B the root namespace. Be sure this is what you intended to do. -Get into the habit of reading \'[something]\' as, "The current value -of \'something\'". See if you understand what the following does (if -you don't, try it out with \'test-tc.py\'): +Get into the habit of reading \fC[something]\fP as, "The current value +of \fCsomething\fP". See if you understand what the following does (if +you don't, try it out with \fCtest-tc.py\fP): .ft C \" Courier .nf @@ -1172,7 +1172,7 @@ .ft \" revert You'll notice that every variable start with the "thing" that -each item has in common - they are features of \'MyCar\'. +each item has in common - they are features of \fCMyCar\fP. We can simplify this considerably by introducing a lexical namespace: .ft C \" Courier @@ -1187,18 +1187,18 @@ The first statement looks like a variable reference, but it is not. .B A string inside square brackets by itself on a line introduces a namespace. -The first statement in this example sets the namespace to \'MyCar\'. +The first statement in this example sets the namespace to \fCMyCar\fP. From that point forward until the namespace is changed again, every variable assignment .B and reference is "relative" to the namespace. What this really means is -that \*(TC sticks the namspace plus a \'.\' in front of every +that \*(TC sticks the namspace plus a \fC.\fP in front of every variable assigned or referenced. It does this automatically and -invisibly, so \'Brand\' is turned into \'MyCar.Brand\' and so on. You +invisibly, so \fCBrand\fP is turned into \fCMyCar.Brand\fP and so on. You can actually check this by loading the example above into a test -configuration file and running the \'test-tc\' program on it. You will +configuration file and running the \fCtest-tc\fP program on it. You will see the "fully qualified" variable names that actually were loaded -into the symbol table, each beginning with \'MyCar.\' and ending with +into the symbol table, each beginning with \fCMyCar.\fP and ending with the variable name you specified. Realize that this is entirely a naming "trick". \*(TC has no clue @@ -1228,10 +1228,10 @@ program that extracts all the information about your car from the configuration file, but I don't know ahead of time how many things you will describe. All I really have to know is that you are using -\'MyCar\' as the namespace for this information. My program can then +\fCMyCar\fP as the namespace for this information. My program can then just scan the symbol table after the configuration file has been parsed, -looking for variables whose name begins with \'MyCar.\'. So if you -want to add other details about your auto like, say, \'Age\', \'Price\', +looking for variables whose name begins with \fCMyCar.\fP. So if you +want to add other details about your auto like, say, \fCAge\fP, \fCPrice\fP, and so on, you can do so later .B and the program does not have to be rewritten. @@ -1240,7 +1240,7 @@ introduce new namespaces into the configuration file any time you like. However, as described in the previous section on the \*(TC API, the application programmer can limit you to a predefined set of legal -namespaces (via the \'LegalVals\' attribute of the \'NAMESPACE\' +namespaces (via the \fCLegalVals\fP attribute of the \fCNAMESPACE\fP variable descriptor). By doing this, the programmer is helping you avoid incorrect configuration file entries by limiting just which namespaces you can enter to reference or create variables. @@ -1312,8 +1312,8 @@ .fi .ft \" revert -This just set the value of the variable \'Namespace\' to -\'something\' and has nothing whatsoever to do with lexical +This just set the value of the variable \fCNamespace\fP to +\fCsomething\fP and has nothing whatsoever to do with lexical namespaces. .IP \(bu 4 @@ -1341,8 +1341,8 @@ .nf [MyNameSpace] - foo = 123 # Creates a variable called \'MyNameSpace.foo\' - x = bar # Means: \'MyNameSpace.x = MyNameSpace.bar\' + foo = 123 # Creates a variable called MyNameSpace.foo + x = bar # Means: MyNameSpace.x = MyNameSpace.bar .fi .ft \" revert @@ -1350,18 +1350,18 @@ If you want to set or reference a variable in a namespace different than the current namespace, you must use a so-called "absolute" variable name. You do this by "escaping" the variable name. To escape the -name, begin it with a \'.\' and then use the +name, begin it with a \fC.\fP and then use the .B full name (including namespace) of that variable. (This is called the "fully qualified variable name".) For example: .ft C \" Courier .nf - [NS1] # Switch to the namespace \'NS1\' - foo = 14 # Creates \'NS1.foo\' + [NS1] # Switch to the namespace NS1 + foo = 14 # Creates NS1.foo - [NS2] # Switch to the \'NS2\' namespace - foo = [.NS1.foo] # Sets \'NS2.foo = 14\' + [NS2] # Switch to the NS2 namespace + foo = [.NS1.foo] # Sets NS2.foo = 14 .fi .ft \" revert @@ -1378,11 +1378,11 @@ .ft C \" Courier .nf - [NS1] # Switch to the namespace \'NS1\' - foo = 14 # Creates \'NS1.foo\' + [NS1] # Switch to the namespace NS1 + foo = 14 # Creates NS1.foo [] # Switch to the root namespace - foo = [NS1.foo] # Sets \'foo = 14\' - no escape needed + foo = [NS1.foo] # Sets foo = 14 - no escape needed .fi .ft \" revert @@ -1394,7 +1394,7 @@ for details.) .IP \(bu 4 -Lexical namspaces are implemented by having \'NAMESPACE\' just be +Lexical namspaces are implemented by having \fCNAMESPACE\fP just be nothing more than (yet) another variable in the symbol table. \*(TC just understands that variable to be special - it treats it as the repository of the current lexical namespace. This means you can use @@ -1417,12 +1417,12 @@ .ft \" revert One final, but very important point is worth noting here. The -\'NAMESPACE\' variable itself is always understood to be +\fCNAMESPACE\fP variable itself is always understood to be .B relative to the root namespace. -No matter what the current namespace actually is, \'[NAMESPACE]\' or -\'NAMESPACE = ...\' always set a variable by that name in the +No matter what the current namespace actually is, \fC[NAMESPACE]\fP or +\fCNAMESPACE = ...\fP always set a variable by that name in the root namespace. Similarly, when we use a variable reference to get -the current namespace value (as we did in the example above), \'NAMESPACE\' +the current namespace value (as we did in the example above), \fCNAMESPACE\fP is understood to be relative to the root namespace. That's why things like this work: @@ -1439,11 +1439,11 @@ .SS Predefined Variables -\*(TC predefines a number of variables. The \'NAMESPACE\' variable we +\*(TC predefines a number of variables. The \fCNAMESPACE\fP variable we discussed in the previous section is one of them, but there are a number of others of which you should be aware. Note that all predefined variables .B are relative to the root namespace. -Except for the \'NAMESPACE\' variable, they are all Read Only and +Except for the \fCNAMESPACE\fP variable, they are all Read Only and cannot be modified in your configuration file. The first group of predefined variables are called "System Variables". @@ -1497,7 +1497,7 @@ The other kind of predefined variables are called "Reserved Variables". \*(TC understands a number of symbols as part of its own language. -For example, the string \'#\' tells \*(TC to begin a comment until +For example, the string \fC#\fP tells \*(TC to begin a comment until end-of-line. There may be times, however, when .B you need these strings for your own use. In other words, you would like @@ -1530,7 +1530,7 @@ .fi -For instance, suppose you wanted to include the \'#\' symbol +For instance, suppose you wanted to include the \fC#\fP symbol in the value of one of your variables. This will not work, because \*(TC interprets it as the beginning of a comment, which is not what you want: @@ -1618,14 +1618,14 @@ The programmer may specify .B the set of all legal values that can be assigned to a variable. For instance, the programmer -might specify that the floating point variable \'Transcend\' can only +might specify that the floating point variable \fCTranscend\fP can only be set to either 3.14 or 2.73. Similarly, the programmer might -specify that the string variable \'Color\' can only ever be set to -\'Red\', \'Green\', or \'Blue\'. In fact, in the case of string +specify that the string variable \fCColor\fP can only ever be set to +\fCRed\fP, \fCGreen\fP, or \fCBlue\fP. In fact, in the case of string variables, the programmer can actually specify a set of patterns (regular expressions) the value has to match. For instance, they can demand that you only set a particular string variable to strings that -begin with \'a'\ and end with \'bob\'. +begin with \fCa\fP and end with \fCbob\fP. .IP \(bu 4 For integer and floating point variables, the programmer can specify @@ -1655,7 +1655,7 @@ .IP \(bu 4 The programmer can enable or prevent .B the substitution of variable references in literal blocks -(see below). If they disable this option, something like \'[Foo]\' +(see below). If they disable this option, something like \fC[Foo]\fP is left unchanged within the literal block. i.e., It too, is treated "literally". @@ -1672,7 +1672,7 @@ .B stored in the symbol table in their actual type.) -For instance, suppose the programmer defines variable \'Foo\' to be +For instance, suppose the programmer defines variable \fCFoo\fP to be floating point. Then: .ft C \" Courier @@ -1688,7 +1688,7 @@ configuration file. This is primarily an issue with the conditional comparisons below. For example, the following conditional is \fCFalse\fP because the string representations of the -two numbers are different. Assume \'f1\' and \'f2\' have been +two numbers are different. Assume \fCf1\fP and \fCf2\fP have been defined as floating point variables by the calling program: .ft C \" Courier @@ -1747,7 +1747,7 @@ .ft \" revert This is the one case where \*(TC is insensitive to case - -"tRUE", "TRUE", and "true" are all accepted, for example. +\fCtRUE\fP, \fCTRUE\fP, and \fCtrue\fP are all accepted, for example. .B NOTE HOWEVER: If the user wants to do a conditional test on the value of @@ -1769,7 +1769,7 @@ .ft \" revert -.SS The \'.include\' Directive +.SS The \fC.include\fP Directive At any point in a configuration file, you can "include" another configuration file like this: @@ -1792,8 +1792,8 @@ .fi .ft \" revert -The whitespace after the \'.include\' directive is mandatory to separate it from -the file name. You can have as many \'.include\' statements in your configuration file +The whitespace after the \fC.include\fP directive is mandatory to separate it from +the file name. You can have as many \fC.include\fP statements in your configuration file as you wish, and they may appear anywhere. The only restriction is that they must appear on a line by themselves (with an optional comment). @@ -1808,12 +1808,12 @@ files which can then be used by different programs as needed. .IP \(bu 4 -The most common use for \'.include\' is to load a "standard" configuration for +The most common use for \fC.include\fP is to load a "standard" configuration for your program. Recall that the last assignment of a variable's value "wins". Suppose you want all the standard settings for a program, but you just want to change one or two options. Instead of requiring each user to have the whole set of standard settings in their own configuration file, the system administrator -can make them available as a common configuration. You then \'.include\' +can make them available as a common configuration. You then \fC.include\fP that file and override any options you like: .ft C \" Courier @@ -1835,8 +1835,8 @@ .P One last thing needs to be noted here. \*(TC does not detect -so-called "circular" inclusions. If file \'a\' \'.include\'s file -\'b\' and file \'b\' \'.include\'s file \'a\', you will have an +so-called "circular" inclusions. If file \fCa\fP \fC.include\fPs file +\fCb\fP and file \fCb\fP \fC.include\fPs file \fCa\fP, you will have an infinite loop of inclusion, which, uh ..., is a Bad Thing... .SS Conditional Directives @@ -1889,7 +1889,7 @@ significant. You may indent as you wish. Conditionals may also be "nested". You can have a conditional within another conditional -or \'.else\' block: +or \fC.else\fP block: .ft C \" Courier .nf @@ -1915,8 +1915,8 @@ .ft \" revert There are no explicit limits to how deeply you can nest a configuration. However, -you must have an \'.endif\' that terminates each conditional test. Bear in mind that -\*(TC pays no attention to your indentation. It associates an \'.endif\' +you must have an \fC.endif\fP that terminates each conditional test. Bear in mind that +\*(TC pays no attention to your indentation. It associates an \fC.endif\fP .B with the last conditional it encountered. That's why it's a really good idea to use some consistent indentation style so .B you @@ -1936,17 +1936,17 @@ conditional blocks. .IP \(bu 4 -Each conditional directive must have a corresponding \'.endif\'. If -you have more conditionals than \'.endif\'s or vice-versa, \*(TC will +Each conditional directive must have a corresponding \fC.endif\fP. If +you have more conditionals than \fC.endif\fPs or vice-versa, \*(TC will produce an error message to that effect. It can get complicated to keep track of this, especially with deeply nested conditionals. It is therefore recommended that you always begin and end conditional blocks within the same file. i.e., Don't start a conditional in one file and -then \'.include\' another file that has the terminating \'.endif\' in +then \fC.include\fP another file that has the terminating \fC.endif\fP in it. .IP \(bu 4 -The \'.else\' clause is optional. However, it can only appear after +The \fC.else\fP clause is optional. However, it can only appear after some preceding conditional directive. .IP \(bu 4 @@ -1960,7 +1960,7 @@ .SS Existential Conditional Directives -There are three Existential Conditionals: \'.ifall\', \'.ifany\', and \'.ifnone\'. +There are three Existential Conditionals: \fC.ifall\fP, \fC.ifany\fP, and \fC.ifnone\fP. Each has the same syntax: .ft C \" Courier @@ -1990,18 +1990,18 @@ .nf .ifall var1 var2 ... - This is a logical "AND" operation. ALL of the variables, \'var1\', \'var2\' ... + This is a logical "AND" operation. ALL of the variables, var1, var2 ... must exist for this test to be True. .ifany var1 var2 ... This is a logical "OR" operation. It is True of ANY of the variables, - \'var1\', \'var2\' ... exist. + var1, var2 ... exist. - .ifall var1 var2 ... + .ifnone var1 var2 ... This is a logical "NOR" operation. It is True only if NONE of the variables, - \'var1\', \'var2\' ... exist. + var1, var2 ... exist. .fi .ft \" revert @@ -2061,13 +2061,13 @@ .fi .ft \" revert -This will test to see if either the variable \'MyVarName\' exists. +This will test to see if either the variable \fCMyVarName\fP exists. You can also do indirection through an environment variable, but this is .B really not recommended because of the obscurity it introduces into a -configuration file. Say the \'TERM\' environment variable is set to -\'vt100\': +configuration file. Say the \fCTERM\fP environment variable is set to +\fCvt100\fP: .ft C \" Courier .nf @@ -2077,7 +2077,7 @@ .fi .ft \" revert -This will test to see if a variable called \'vt100\' exists in the +This will test to see if a variable called \fCvt100\fP exists in the symbol table. This is, perhaps, not the clearest possible construct! @@ -2137,13 +2137,13 @@ .ft \" revert -.SS The \'.literal\. Directive +.SS The \fC.literal\fP Directive By default, \*(TC only permits statements it "recognizes" in the configuration file. Anything else is flagged as an unrecognized statement or "syntax error". However, it is possible to "embed" arbitrary text in a configuration file and have \*(TC pass it back -to the calling program without comment by using the \'.literal\' +to the calling program without comment by using the \fC.literal\fP directive. It works like this: .ft C \" Courier @@ -2154,8 +2154,8 @@ .fi .ft \" revert -This tells \*(TC to ignore everything between \'.literal\' and \'.endliteral\' -and just pass it back to the calling program (in \'retval.Literals\' - see +This tells \*(TC to ignore everything between \fC.literal\fP and \fC.endliteral\fP +and just pass it back to the calling program (in \fCretval.Literals\fP - see previous section on the \*(TC API). What good is this? It is a nifty way to embedd plain text or even @@ -2186,7 +2186,7 @@ By default, \*(TC leaves text within the literal block completely untouched. It simply returns it as it finds it in the literal block. However, the -programmer can invoke \*(TC with an option (\'LiteralVars=True\') that +programmer can invoke \*(TC with an option (\fCLiteralVars=True\fP) that allows .B variable substitution within literal blocks. This allows you to combine the results of your configuration into the @@ -2216,11 +2216,11 @@ .fi .ft \" revert -If the calling program sets \'LiteralVars=True\', the literal block +If the calling program sets \fCLiteralVars=True\fP, the literal block will return a C program that prints the greeting defined at the top of -this example. If they use the default \'LiteralVars=False\', the C -program would print "[Greeting]". (Well ... it should do that, but if -variable substitution is not enabled, the \'[HASH]\' reference will +this example. If they use the default \fCLiteralVars=False\fP, the C +program would print \fC[Greeting]\fP. (Well ... it should do that, but if +variable substitution is not enabled, the \fC[HASH]\fP reference will not be resolved and the C program returned will be incorrect.) In other words, it is possible to have your literal blocks make @@ -2231,16 +2231,16 @@ other, arbitrary textual information that the program may need, all in a single configuration file. -If you fail to provide a terminating \'.endliteral\', the program will +If you fail to provide a terminating \fC.endliteral\fP, the program will treat everthing as literal until it reaches the end of the configuration file. This will generate an appropriate warning, but -will work as you might expect. Everything from the \'.literal\' +will work as you might expect. Everything from the \fC.literal\fP directive forward will be treated literally. As a matter of good -style, you should always insert an explicit \'.endliteral\', even if +style, you should always insert an explicit \fC.endliteral\fP, even if it is at the end of file. -Placing an \'.endliteral\' in the configuration file without a -preceding \'.literal\' will also generate a warning message, and the +Placing an \fC.endliteral\fP in the configuration file without a +preceding \fC.literal\fP will also generate a warning message, and the statement will be ignored. @@ -2271,10 +2271,10 @@ and .B variable references. -The example above checks to see if the string "foo" equals -the string "bar" - which, of course, it never does. +The example above checks to see if the string \fCfoo\fP equals +the string \fCbar\fP - which, of course, it never does. -What you probably want is to compare the value of variable \'foo\' with +What you probably want is to compare the value of variable \fCfoo\fP with some string: .ft C \" Courier @@ -2289,7 +2289,7 @@ Now you're comparing the .B value -of the variable \'foo\' with the string "bar". +of the variable \fCfoo\fP with the string \fCbar\fP. By the way, this was done for a very good reason. By requiring the user explicitly note whether they want the name or value of a variable (instead of @@ -2338,14 +2338,14 @@ .fi .ft \" revert -At the end of all this, \'myvar\' will be set to 200. This can be -especially annoying if you \'.include\' a configuration file after +At the end of all this, \fCmyvar\fP will be set to 200. This can be +especially annoying if you \fC.include\fP a configuration file after you've set a value and the included file resets it. As a matter of -style, it's best to do all the \'.include\'s at the top of the master +style, it's best to do all the \fC.include\fPs at the top of the master configuration file so you won't get bitten by this one. .IP \(bu 4 -Remember that case matters. \'Foo\', \'foo\', and \'foO\' are all +Remember that case matters. \fCFoo\fP, \fCfoo\fP, and \fCfoO\fP are all different variable names. .IP \(bu 4 @@ -2388,13 +2388,13 @@ .IP \(bu 4 Predefine every option variable the program will support. Populate the -initial symbol table passed to \'ParseConfig()\' with these definitions. -By properly setting the \'Type\', \'LegalVals\', and \'Min/Max\' for +initial symbol table passed to \fCParseConfig()\fP with these definitions. +By properly setting the \fCType\fP, \fCLegalVals\fP, and \fCMin/Max\fP for each of these variables ahead of time, you can prevent the user from ever entering option values that make no sense or are dangerous. .IP \(bu 4 -Make sure ever program option has a reasonable \'Default\' value in +Make sure ever program option has a reasonable \fCDefault\fP value in its variable descriptor. Recall that this attribute is provided for the programmer's convenience. (When a variable descriptor is first instantiated, it defaults to a string type and sets the default @@ -2464,9 +2464,9 @@ In fact, you can even make this iterative parsing "goal driven". The program can keep calling the parser, modifing the results, and calling the parser again until some "goal" is met. The goal -could be that a particular variable gets defined (like \'CONFIGDONE\'). +could be that a particular variable gets defined (like \fCCONFIGDONE\fP). The goal might be that a variable is set to a particular value -(like, \'SYSTEMS=3\'). +(like, \fCSYSTEMS=3\fP). It might even be tempting to keep parsing iteratively until \*(TC no longer returns any errors. This is not recommended, though. A