diff --git a/tconfpy.3 b/tconfpy.3 index 522e505..e1c3299 100644 --- a/tconfpy.3 +++ b/tconfpy.3 @@ -47,7 +47,7 @@ both programmers and people writing configuration files will find this helpful. -.B ADVANCED TOPICS +.B ADVANCED TOPICS FOR PROGRAMMERS describes some ways to combine the various \*(TC features to do some fairly nifty things. @@ -2089,14 +2089,119 @@ statement will be ignored. -.SH ADVANCED TOPICS +.SH ADVANCED TOPICS FOR PROGRAMMERS + +Here are some ideas on how you might combine \*(TC features +to enhance your own applications. .SS Guaranteeing A Correct Base Configuration +While it is always nice to give users lots of "knobs" to turn, the +problem is that the more options you give them, the more they can +misconfigure a program. This is especially a problem when you are +doing technical support. You'd really like to get them to a +"standard" configuration and then work from there to help solve their +problem. If your write your program with this in mind, \*(TC gives +you several ways to easily do this: + +.IP \(bu 4 +Provide a "standard" system-, or even, enterprise-wide configuration +file for your application. This file presumably has all the program +options set to "sane" values. All the user has to do is create +a configuration file with one line in it: + +.nf + .include /wherever/the/standard/config/file/is +.fi + +.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 +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 +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 +attribute to an empty string. However, you can change both type and +default value under program control.) If you predefine a variable in the +initial symbol table passed to the parser, \*(TC will leave this +attribute alone. However, variables that are created for the first +time in the configuration file will have this attribute set to the +first value assigned to the variable. Now provide a "reset" feature +in your application. All it has to do is scan through the symbol +table and set each option to its default value. + + .SS Enforcing Mandatory Configurations +The \*(TC type and value validation features give you a handy way to +enforce what the legal values for a particular option may be. +However, you may want to go further than this. For instance, you may +only want to give certain classes of users the ability to change +certain options. This is easily done. First, predefine all the +options of interest in the symbol table prior to calling the \*(TC +parser. Next, have your program decide which options the current user +is permitted to change. Finally, mark all the options they may not +change as "Read Only", by setting the "Writeable" attribute for those +options to "False". Now call the parser. + + This general approach allows you to write programs that support a +wide range of options which are enablde/disabled on a per-user, +per-machine, per-domain, per-ip, per-company... basis. + .SS Iterative Parsing +There may be situations where one "pass" through a configuration +file may not be enough. For example, your program may need to +read an initial configuration to decide how to further process +the remainder of a configuration file. Although it sounds +complicated, it is actually pretty easy to do. The idea +is to have the program set some variable that selects +which part of the configuration file to process, and then call +the parser. When the parser returns the symbol table, the program +examines the results, makes whatever adjustments to the symbol +table it needs to, and passes it back to the parser for another +"go". You can keep doing this as often as needed. For instance: + +.nf + + # Program calls the parser with PASS set to 1 + + .if PASS == 1 + # Do 1st Pass Stuff + .endif + + + + # Program examines the results of the first pass, does + # what is has to, and sets PASS to 2 + + .if PASS == 2 + # Do 2nd Pass Stuff + .endif + + # And so on +.if + +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\'). +The goal might be that a variable is set to a particular value +(like, \'SYSTEMS=3\'). + +It might even be tempting to keep parsing iteratively until \*(TC no +longer returns any errors. This is not recommended, though. A +well-formed configuration file should have no errors on any pass. +Iterating until \*(TC no longer detects errors makes it hard to +debug complex configuration files. It is tough to distinguish +actual configuration errors from errors would be resolved in a +future parsing pass. + .SH INSTALLATION