| |
---|
| | recognized by \*(TC. This is the "User's View" of the package, but |
---|
| | 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. |
---|
| | |
---|
| | .B INSTALLATION |
---|
| |
---|
| | preceding \'.literal\' will also generate a warning message, and the |
---|
| | 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 |
---|
| | |
---|
| |
---|
| | |