Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 2 | <html><head><title>CommandLine 2.0 Library Manual</title></head> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 3 | <body bgcolor=white> |
| 4 | |
| 5 | <table width="100%" bgcolor="#330077" border=0 cellpadding=4 cellspacing=0> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 6 | <tr><td> <font size=+4 color="#EEEEFF" face="Georgia,Palatino,Times,Roman"><b>CommandLine 2.0 Library Manual</b></font></td> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 7 | </tr></table> |
| 8 | |
| 9 | <ol> |
| 10 | <li><a href="#introduction">Introduction</a> |
| 11 | <li><a href="#quickstart">Quick Start Guide</a> |
| 12 | <ol> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 13 | <li><a href="#bool">Boolean Arguments</a> |
| 14 | <li><a href="#alias">Argument Aliases</a> |
| 15 | <li><a href="#onealternative">Selecting an alternative from a set of possibilities</a> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 16 | <li><a href="#namedalternatives">Named alternatives</a> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 17 | <li><a href="#list">Parsing a list of options</a> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 18 | </ol> |
| 19 | <li><a href="#referenceguide">Reference Guide</a> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 20 | <ol> |
| 21 | <li>Option Modifiers: |
| 22 | <ul> |
| 23 | <li>Controlling whether or not the option is shown by <tt>--help</tt> |
| 24 | <li>Controlling the number of occurances required and allowed |
| 25 | <li>Controlling whether or not a value must be specified |
| 26 | <li>Controlling other formatting options |
| 27 | </ul> |
| 28 | <li>Positional Arguments |
| 29 | <li>Internal vs External Storage |
| 30 | <li>The option classes |
| 31 | <ul> |
| 32 | <li>The <tt>opt<></tt> class |
| 33 | <li>The <tt>list<></tt> class |
| 34 | <li>The <tt>alias</tt> class |
| 35 | </ul> |
| 36 | </ol> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 37 | <li><a href="#extensionguide">Extension Guide</a> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 38 | <ol> |
| 39 | <li>Writing a custom parser |
| 40 | <li>Exploiting external storage |
| 41 | <li>Dynamically adding command line options |
| 42 | </ol> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 43 | </ol><p> |
| 44 | |
| 45 | |
| 46 | <!-- *********************************************************************** --> |
| 47 | </ul><table width="100%" bgcolor="#330077" border=0 cellpadding=4 cellspacing=0> |
| 48 | <tr><td align=center><font color="#EEEEFF" size=+2 face="Georgia,Palatino"><b> |
| 49 | <a name="introduction">Introduction |
| 50 | </b></font></td></tr></table><ul> |
| 51 | <!-- *********************************************************************** --> |
| 52 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 53 | This document describes the CommandLine argument processing library. It will |
| 54 | show you how to use it, and what it can do.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 55 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 56 | Although there are a <b>lot</b> of command line argument parsing libraries out |
| 57 | there in many different languages, none of them fit well with what I needed. By |
| 58 | looking at the features and problems of other libraries, I designed the |
| 59 | CommandLine library to have the following features:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 60 | |
| 61 | <ol> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 62 | <li>Speed: The CommandLine library is very quick and uses little resources. The |
| 63 | parsing time of the library is directly proportional to the number of arguments |
| 64 | parsed, not the the number of options recognized. Additionally, command line |
| 65 | argument values are captured transparently into user defined variables, which |
| 66 | can be accessed like any other variable (and with the same performance).<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 67 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 68 | <li>Type Safe: As a user of CommandLine, you don't have to worry about |
| 69 | remembering the type of arguments that you want (is it an int? a string? a |
| 70 | bool? an enum?) and keep casting it around. Not only does this help prevent |
| 71 | error prone constructs, it also leads to dramatically cleaner source code.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 72 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 73 | <li>No subclasses required: To use CommandLine, you instantiate variables that |
| 74 | correspond to the arguments that you would like to capture, you don't subclass a |
| 75 | parser. This leads to much less boilerplate code.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 76 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 77 | <li>Globally accessible: Libraries can specify command line arguments that are |
| 78 | automatically enabled in any tool that links to the library. This is possible |
| 79 | because the application doesn't have to keep a "list" of arguments to pass to |
| 80 | the parser.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 81 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 82 | <li>More Clean: CommandLine supports enum types directly, meaning that there is |
| 83 | less error and more security built into the library. You don't have to worry |
| 84 | about whether your integral command line argument accidentally got assigned a |
| 85 | value that is not valid for your enum type.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 86 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 87 | <li>Powerful: The CommandLine library supports many different types of |
| 88 | arguments, from simple boolean flags to scalars arguments (strings, integers, |
| 89 | enums, doubles), to lists of arguments. This is possible because CommandLine |
| 90 | is...<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 91 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 92 | <li>Extensible: It is very simple to add a new argument type to CommandLine. |
| 93 | Simply specify the parser that you want to use with the command line option when |
| 94 | you declare it. Custom parsers are no problem.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 95 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 96 | <li>Labor Saving: The CommandLine library cuts down on the amount of grunt work |
| 97 | that you, the user, have to do. For example, it automatically provides a --help |
| 98 | option that shows the available command line options for your tool.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 99 | </ol> |
| 100 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 101 | This document will hopefully let you jump in and start using CommandLine in your |
| 102 | utility quickly and painlessly. Additionally it should be a simple reference |
| 103 | manual to figure out how stuff works. If it is failing in some area, nag the |
| 104 | author, <a href="mailto:sabre@nondot.org">Chris Lattner</a>.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 105 | |
| 106 | |
| 107 | <!-- *********************************************************************** --> |
| 108 | </ul><table width="100%" bgcolor="#330077" border=0 cellpadding=4 cellspacing=0><tr><td align=center><font color="#EEEEFF" size=+2 face="Georgia,Palatino"><b> |
| 109 | <a name="quickstart">Quick Start Guide |
| 110 | </b></font></td></tr></table><ul> |
| 111 | <!-- *********************************************************************** --> |
| 112 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 113 | This section of the manual runs through a simple CommandLine'ification of a |
| 114 | basic compiler tool. This is intended to show you how to jump into using the |
| 115 | CommandLine library in your own program, and show you some of the cool things it |
| 116 | can do.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 117 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 118 | To start out, you need to include the CommandLine header file into your |
| 119 | program:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 120 | |
| 121 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 122 | #include "Support/CommandLine.h" |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 123 | </pre><p> |
| 124 | |
| 125 | Additionally, you need to add this as the first line of your main program:<p> |
| 126 | |
| 127 | <pre> |
| 128 | int main(int argc, char **argv) { |
| 129 | cl::ParseCommandLineOptions(argc, argv); |
| 130 | ... |
| 131 | } |
| 132 | </pre><p> |
| 133 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 134 | ... which actually parses the arguments and fills in the variable |
| 135 | declarations.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 136 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 137 | Now that you are ready to support command line arguments, we need to tell the |
| 138 | system which ones we want, and what type of argument they are. The CommandLine |
| 139 | library uses a declarative syntax to model cammand line arguments with the |
| 140 | variable declarations that capture the parsed values. This means that for every |
| 141 | command line option that you would like to support, there should be a variable |
| 142 | declaration to capture the result. For example, in a compiler, we would like to |
| 143 | support the unix standard '<tt>-o <filename></tt>' option to specify where |
| 144 | to put the output. With the CommandLine library, this is represented like |
| 145 | this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 146 | |
| 147 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 148 | cl::opt<string> OutputFilename("<i>o</i>", cl::desc("<i>Specify output filename</i>"), cl::value_desc("<i>filename</i>")); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 149 | </pre><p> |
| 150 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 151 | This declares a variable "<tt>OutputFilename</tt>" that is used to capture the |
| 152 | result of the "<tt>o</tt>" argument (first parameter). We specify that this is |
| 153 | a simple scalar option by using the "<tt>opt<></tt>" template (as opposed |
| 154 | to the <a href="#list">"<tt>list<></tt> template</a>), and tell the |
| 155 | CommandLine library that the data type that we are parsing is a string.<p> |
| 156 | |
| 157 | The second and third parameters (which are optional) are used to specify what to |
| 158 | output for the "<tt>--help</tt>" option. In this case, we get a line that looks |
| 159 | like this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 160 | |
| 161 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 162 | USAGE: compiler [options] |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 163 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 164 | OPTIONS: |
| 165 | -help - display available options (--help-hidden for more) |
| 166 | -o <filename> - Specify output filename |
| 167 | </pre> |
| 168 | |
| 169 | Because we specified that the command line option should parse using the |
| 170 | <tt>string</tt> data type, the variable declared is automatically usable as a |
| 171 | real string in all contexts that a normal C++ string object may be used. For |
| 172 | example:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 173 | |
| 174 | <pre> |
| 175 | ... |
| 176 | ofstream Output(OutputFilename.c_str()); |
| 177 | if (Out.good()) ... |
| 178 | ... |
| 179 | </pre><p> |
| 180 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 181 | There are many different options that you can use to customize the command line |
| 182 | option handling library, but the above example shows the general interface to |
| 183 | these options. The options can be specified in any order, and are specified |
| 184 | with helper functions like <tt>cl::desc(...)</tt>, so there are no positional |
| 185 | dependencies to have to remember. We will discuss the options you can use later |
| 186 | in this document. Also note that if your compiler supports Koenig lookup (gcc |
| 187 | 2.95.x doesn't), that you don't have to specify as many <tt>cl::</tt> namespace |
| 188 | qualifiers to use the library.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 189 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 190 | Continuing the example, we would like to have our compiler take an input |
| 191 | filename as well as an output filename, but we do not want the input filename to |
| 192 | be specified with a hyphen (ie, not <tt>-filename.c</tt>). To support this |
| 193 | style of argument, the CommandLine library allows for positional arguments to be |
| 194 | specified for the program. These positional arguments are filled with command |
| 195 | line parameters that are not in option form. We use this feature like this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 196 | |
| 197 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 198 | cl::opt<string> InputFilename(cl::Positional, cl::desc("<i><input file></i>"), cl::init("<i>-</i>")); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 199 | </pre> |
| 200 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 201 | This declaration indicates that the first positional argument should be treated |
| 202 | as the input filename. Here we use the <tt>cl::init</tt> option to specify an |
| 203 | initial value for the command line option, which is used if the option is not |
| 204 | specified (if you do not specify a <tt>cl::init</tt> modifier for an option, |
| 205 | then the default constructor for the data type is used to initialize the value). |
| 206 | Command line options default to being optional, so if we would like to require |
| 207 | that the user always specify an input filename, we would add the |
| 208 | <tt>cl::Required</tt> flag, and we could eliminate the <tt>cl::init</tt> |
| 209 | modifier, like this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 210 | |
| 211 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 212 | cl::opt<string> InputFilename(cl::Positional, cl::desc("<i><input file></i>"), <b>cl::Required</b>); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 213 | </pre> |
| 214 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 215 | Again, the CommandLine library does not require the options to be specified in |
| 216 | any particular order, so the above declaration is equivalent to:<p> |
| 217 | |
| 218 | <pre> |
| 219 | cl::opt<string> InputFilename(cl::Positional, cl::Required, cl::desc("<i><input file></i>")); |
| 220 | </pre> |
| 221 | |
| 222 | By simply adding the <tt>cl::Required</tt> flag, the CommandLine library will |
| 223 | automatically issue an error if the argument is not specified, which shifts all |
| 224 | of the command line option verification code out of your application into the |
| 225 | library. This is just one example of how using flags can alter the default |
| 226 | behaviour of the library, on a per-option basis. By adding one of the |
| 227 | declarations above, the <tt>--help</tt> option synopsis is now extended to:<p> |
| 228 | |
| 229 | <pre> |
| 230 | USAGE: compiler [options] <input file> |
| 231 | |
| 232 | OPTIONS: |
| 233 | -help - display available options (--help-hidden for more) |
| 234 | -o <filename> - Specify output filename |
| 235 | </pre> |
| 236 | |
| 237 | ... indicating that an input filename is expected.<p> |
| 238 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 239 | |
| 240 | <!-- ======================================================================= --> |
| 241 | </ul><table width="100%" bgcolor="#441188" border=0 cellpadding=4 cellspacing=0><tr><td> </td><td width="100%"> <font color="#EEEEFF" face="Georgia,Palatino"><b> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 242 | <a name="bool">Boolean Arguments |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 243 | </b></font></td></tr></table><ul> |
| 244 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 245 | In addition to input and output filenames, we would like the compiler example to |
| 246 | support three boolean flags: "<tt>-f</tt>" to force overwriting of the output |
| 247 | file, "<tt>--quiet</tt>" to enable quiet mode, and "<tt>-q</tt>" for backwards |
| 248 | compatibility with some of our users. We can support these by declaring options |
| 249 | of boolean type like this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 250 | |
| 251 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 252 | cl::opt<bool> Force ("<i>f</i>", cl::desc("<i>Overwrite output files</i>")); |
| 253 | cl::opt<bool> Quiet ("<i>quiet</i>", cl::desc("<i>Don't print informational messages</i>")); |
| 254 | cl::opt<bool> Quiet2("<i>q</i>", cl::desc("<i>Don't print informational messages</i>"), cl::Hidden); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 255 | </pre><p> |
| 256 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 257 | This does what you would expect: it declares three boolean variables |
| 258 | ("<tt>Force</tt>", "<tt>Quiet</tt>", and "<tt>Quiet2</tt>") to recognize these |
| 259 | options. Note that the "<tt>-q</tt>" option is specified with the |
| 260 | "<tt>cl::Hidden</tt>" flag. This modifier prevents it from being shown by the |
| 261 | standard "<tt>--help</tt>" output (note that it is still shown in the |
| 262 | "<tt>--help-hidden</tt>" output).<p> |
| 263 | |
| 264 | The CommandLine library uses a different parser for different data types. For |
| 265 | example, in the string case, the argument passed to the option is copied |
| 266 | literally into the content of the string variable... we obviously cannot do that |
| 267 | in the boolean case, however, so we must use a smarter parser. In the case of |
| 268 | the boolean parser, it allows no options (in which case it assigns the value of |
| 269 | true to the variable), or it allows the values "<tt>true</tt>" or |
| 270 | "<tt>false</tt>" to be specified, allowing any of the following inputs:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 271 | |
| 272 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 273 | compiler -f # No value, 'Force' == true |
| 274 | compiler -f=true # Value specified, 'Force' == true |
| 275 | compiler -f=TRUE # Value specified, 'Force' == true |
| 276 | compiler -f=FALSE # Value specified, 'Force' == false |
| 277 | </pre> |
| 278 | |
| 279 | ... you get the idea. The bool parser just turns the string values into boolean |
| 280 | values, and rejects things like '<tt>compiler -f=foo</tt>'. Similarly, the |
| 281 | float, double, and int parsers work like you would expect, using the |
| 282 | '<tt>strtol</tt>' and '<tt>strtod</tt>' C library calls to parse the string |
| 283 | value into the specified data type.<p> |
| 284 | |
| 285 | With the declarations above, "<tt>compiler --help</tt>" emits this:<p> |
| 286 | |
| 287 | <pre> |
| 288 | USAGE: compiler [options] <input file> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 289 | |
| 290 | OPTIONS: |
| 291 | -f - Overwrite output files |
| 292 | -o - Override output filename |
| 293 | -quiet - Don't print informational messages |
| 294 | -help - display available options (--help-hidden for more) |
| 295 | </pre><p> |
| 296 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 297 | and "<tt>opt --help-hidden</tt>" prints this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 298 | |
| 299 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 300 | USAGE: opt [options] <input file> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 301 | |
| 302 | OPTIONS: |
| 303 | -f - Overwrite output files |
| 304 | -o - Override output filename |
| 305 | -q - Don't print informational messages |
| 306 | -quiet - Don't print informational messages |
| 307 | -help - display available options (--help-hidden for more) |
| 308 | </pre><p> |
| 309 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 310 | This brief example has shown you how to use the '<tt>opt<></tt>' class to |
| 311 | parse simple scalar command line arguments. In addition to simple scalar |
| 312 | arguments, the CommandLine library also provides primitives to support |
| 313 | CommandLine option <a href="#alias">aliases</a>, and <a href="#list">lists</a> |
| 314 | of options.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 315 | |
| 316 | |
| 317 | <!-- ======================================================================= --> |
| 318 | </ul><table width="100%" bgcolor="#441188" border=0 cellpadding=4 cellspacing=0><tr><td> </td><td width="100%"> <font color="#EEEEFF" face="Georgia,Palatino"><b> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 319 | <a name="alias">Argument Aliases |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 320 | </b></font></td></tr></table><ul> |
| 321 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 322 | So far, the example works well, except for the fact that we need to check the |
| 323 | quiet condition like this now:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 324 | |
| 325 | <pre> |
| 326 | ... |
| 327 | if (!Quiet && !Quiet2) printInformationalMessage(...); |
| 328 | ... |
| 329 | </pre><p> |
| 330 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 331 | ... which is a real pain! Instead of defining two values for the same |
| 332 | condition, we can use the "<tt>cl::alias</tt>" class to make the "<tt>-q</tt>" |
| 333 | option an <b>alias</b> for the "<tt>-quiet</tt>" option, instead of providing |
| 334 | a value itself:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 335 | |
| 336 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 337 | cl::opt<bool> Force ("<i>f</i>", cl::desc("<i>Overwrite output files</i>")); |
| 338 | cl::opt<bool> Quiet ("<i>quiet</i>", cl::desc("<i>Don't print informational messages</i>")); |
| 339 | cl::alias QuietA("<i>q</i>", cl::desc("<i>Alias for -quiet</i>"), cl::aliasopt(Quiet)); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 340 | </pre><p> |
| 341 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 342 | The third line (which is the only one we modified from above) defines a |
| 343 | "<tt>-q</tt> alias that updates the "<tt>Quiet</tt>" variable (as specified by |
| 344 | the <tt>cl::aliasopt</tt> modifier) whenever it is specified. Because aliases |
| 345 | do not hold state, the only thing the program has to query is the <tt>Quiet</tt> |
| 346 | variable now. Another nice feature of aliases is that they automatically hide |
| 347 | themselves from the <tt>-help</tt> output (although, again, they are still |
| 348 | visible in the <tt>--help-hidden output</tt>).<p> |
| 349 | |
| 350 | Now the application code can simply use:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 351 | |
| 352 | <pre> |
| 353 | ... |
| 354 | if (!Quiet) printInformationalMessage(...); |
| 355 | ... |
| 356 | </pre><p> |
| 357 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 358 | ... which is much nicer! The "<tt>cl::alias</tt>" can be used to specify an |
| 359 | alternative name for any variable type, and has many uses.<p> |
| 360 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 361 | |
| 362 | |
| 363 | <!-- ======================================================================= --> |
| 364 | </ul><table width="100%" bgcolor="#441188" border=0 cellpadding=4 cellspacing=0><tr><td> </td><td width="100%"> <font color="#EEEEFF" face="Georgia,Palatino"><b> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 365 | <a name="onealternative">Selecting an alternative from a set of possibilities |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 366 | </b></font></td></tr></table><ul> |
| 367 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 368 | So far, we have seen how the CommandLine library handles builtin types like |
| 369 | <tt>std::string</tt>, <tt>bool</tt> and <tt>int</tt>, but how does it handle |
| 370 | things it doesn't know about, like enums or '<tt>int*</tt>'s?<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 371 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 372 | The answer is that it uses a table driven generic parser (unless you specify |
| 373 | your own parser, as described in the <a href="#extensionguide">Extension |
| 374 | Guide</a>). This parser maps literal strings to whatever type is required, are |
| 375 | requires you to tell it what this mapping should be.<p> |
| 376 | |
| 377 | Lets say that we would like to add four optimizations levels to our optimizer, |
| 378 | using the standard flags "<tt>-g</tt>", "<tt>-O0</tt>", "<tt>-O1</tt>", and |
| 379 | "<tt>-O2</tt>". We could easily implement this with boolean options like above, |
| 380 | but there are several problems with this strategy:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 381 | |
| 382 | <ol> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 383 | <li>A user could specify more than one of the options at a time, for example, |
| 384 | "<tt>opt -O3 -O2</tt>". The CommandLine library would not be able to catch this |
| 385 | erroneous input for us. |
| 386 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 387 | <li>We would have to test 4 different variables to see which ones are set. |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 388 | |
| 389 | <li>This doesn't map to the numeric levels that we want... so we cannot easily |
| 390 | see if some level >= "<tt>-O1</tt>" is enabled. |
| 391 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 392 | </ol><p> |
| 393 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 394 | To cope with these problems, we can use an enum value, and have the CommandLine |
| 395 | library fill it in with the appropriate level directly, which is used like |
| 396 | this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 397 | |
| 398 | <pre> |
| 399 | enum OptLevel { |
| 400 | g, O1, O2, O3 |
| 401 | }; |
| 402 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 403 | cl::opt<OptLevel> OptimizationLevel(cl::desc("<i>Choose optimization level:</i>"), |
| 404 | cl::values( |
| 405 | clEnumVal(g , "<i>No optimizations, enable debugging</i>"), |
| 406 | clEnumVal(O1, "<i>Enable trivial optimizations</i>"), |
| 407 | clEnumVal(O2, "<i>Enable default optimizations</i>"), |
| 408 | clEnumVal(O3, "<i>Enable expensive optimizations</i>"), |
| 409 | 0)); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 410 | |
| 411 | ... |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 412 | if (OptimizationLevel >= O2) doPartialRedundancyElimination(...); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 413 | ... |
| 414 | </pre><p> |
| 415 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 416 | This declaration defines a variable "<tt>OptimizationLevel</tt>" of the |
| 417 | "<tt>OptLevel</tt>" enum type. This variable can be assigned any of the values |
| 418 | that are listed in the declaration (Note that the declaration list must be |
| 419 | terminated with the "<tt>0</tt>" argument!). The CommandLine library enforces |
| 420 | that the user can only specify one of the options, and it ensure that only valid |
| 421 | enum values can be specified. The "<tt>clEnumVal</tt>" macros ensure that the |
| 422 | command line arguments matche the enum values. With this option added, our help |
| 423 | output now is:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 424 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 425 | <pre> |
| 426 | USAGE: compiler [options] <input file> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 427 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 428 | OPTIONS: |
| 429 | Choose optimization level: |
| 430 | -g - No optimizations, enable debugging |
| 431 | -O1 - Enable trivial optimizations |
| 432 | -O2 - Enable default optimizations |
| 433 | -O3 - Enable expensive optimizations |
| 434 | -f - Overwrite output files |
| 435 | -help - display available options (--help-hidden for more) |
| 436 | -o <filename> - Specify output filename |
| 437 | -quiet - Don't print informational messages |
| 438 | </pre> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 439 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 440 | In this case, it is sort of awkward that flag names correspond directly to enum |
| 441 | names, because we probably don't want a enum definition named "<tt>g</tt>" in |
| 442 | our program. Because of this, we can alternatively write this example like |
| 443 | this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 444 | |
| 445 | <pre> |
| 446 | enum OptLevel { |
| 447 | Debug, O1, O2, O3 |
| 448 | }; |
| 449 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 450 | cl::opt<OptLevel> OptimizationLevel(cl::desc("<i>Choose optimization level:</i>"), |
| 451 | cl::values( |
| 452 | clEnumValN(Debug, "g", "<i>No optimizations, enable debugging</i>"), |
| 453 | clEnumVal(O1 , "<i>Enable trivial optimizations</i>"), |
| 454 | clEnumVal(O2 , "<i>Enable default optimizations</i>"), |
| 455 | clEnumVal(O3 , "<i>Enable expensive optimizations</i>"), |
| 456 | 0)); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 457 | |
| 458 | ... |
| 459 | if (OptimizationLevel == Debug) outputDebugInfo(...); |
| 460 | ... |
| 461 | </pre><p> |
| 462 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 463 | By using the "<tt>clEnumValN</tt>" macro instead of "<tt>clEnumVal</tt>", we can |
| 464 | directly specify the name that the flag should get. In general a direct mapping |
| 465 | is nice, but sometimes you can't or don't want to preserve the mapping, which is |
| 466 | when you would use it.<p> |
| 467 | |
| 468 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 469 | |
| 470 | <!-- ======================================================================= --> |
| 471 | </ul><table width="100%" bgcolor="#441188" border=0 cellpadding=4 cellspacing=0><tr><td> </td><td width="100%"> <font color="#EEEEFF" face="Georgia,Palatino"><b> |
| 472 | <a name="namedalternatives">Named Alternatives |
| 473 | </b></font></td></tr></table><ul> |
| 474 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 475 | Another useful argument form is a named alternative style. We shall use this |
| 476 | style in our compiler to specify different debug levels that can be used. |
| 477 | Instead of each debug level being its own switch, we want to support the |
| 478 | following options, of which only one can be specified at a time: |
| 479 | "<tt>--debug-level=none</tt>", "<tt>--debug-level=quick</tt>", |
| 480 | "<tt>--debug-level=detailed</tt>". To do this, we use the exact same format as |
| 481 | our optimization level flags, but we also specify an option name. For this |
| 482 | case, the code looks like this:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 483 | |
| 484 | <pre> |
| 485 | enum DebugLev { |
| 486 | nodebuginfo, quick, detailed |
| 487 | }; |
| 488 | |
| 489 | // Enable Debug Options to be specified on the command line |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 490 | cl::opt<DebugLev> DebugLevel("<i>debug_level</i>", cl::desc("<i>Set the debugging level:</i>"), |
| 491 | cl::values( |
| 492 | clEnumValN(nodebuginfo, "none", "<i>disable debug information</i>"), |
| 493 | clEnumVal(quick, "<i>enable quick debug information</i>"), |
| 494 | clEnumVal(detailed, "<i>enable detailed debug information</i>"), |
| 495 | 0)); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 496 | </pre> |
| 497 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 498 | This definition defines an enumerated command line variable of type "<tt>enum |
| 499 | DebugLev</tt>", which works exactly the same way as before. The difference here |
| 500 | is just the interface exposed to the user of your program and the help output by |
| 501 | the "<tt>--help</tt>" option:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 502 | |
| 503 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 504 | USAGE: compiler [options] <input file> |
| 505 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 506 | OPTIONS: |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 507 | Choose optimization level: |
| 508 | -g - No optimizations, enable debugging |
| 509 | -O1 - Enable trivial optimizations |
| 510 | -O2 - Enable default optimizations |
| 511 | -O3 - Enable expensive optimizations |
| 512 | -debug_level - Set the debugging level: |
| 513 | =none - disable debug information |
| 514 | =quick - enable quick debug information |
| 515 | =detailed - enable detailed debug information |
| 516 | -f - Overwrite output files |
| 517 | -help - display available options (--help-hidden for more) |
| 518 | -o <filename> - Specify output filename |
| 519 | -quiet - Don't print informational messages |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 520 | </pre><p> |
| 521 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 522 | Again, the only structural difference between the debug level declaration and |
| 523 | the optimiation level declaration is that the debug level declaration includes |
| 524 | an option name (<tt>"debug_level"</tt>), which automatically changes how the |
| 525 | library processes the argument. The CommandLine library supports both forms so |
| 526 | that you can choose the form most appropriate for your application.<p> |
| 527 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 528 | |
| 529 | |
| 530 | <!-- ======================================================================= --> |
| 531 | </ul><table width="100%" bgcolor="#441188" border=0 cellpadding=4 cellspacing=0><tr><td> </td><td width="100%"> <font color="#EEEEFF" face="Georgia,Palatino"><b> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 532 | <a name="list">Parsing a list of options |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 533 | </b></font></td></tr></table><ul> |
| 534 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 535 | Now that we have the standard run of the mill argument types out of the way, |
| 536 | lets get a little wild and crazy. Lets say that we want our optimizer to accept |
| 537 | a <b>list</b> of optimizations to perform, allowing duplicates. For example, we |
| 538 | might want to run: "<tt>compiler -dce -constprop -inline -dce -strip</tt>". In |
| 539 | this case, the order of the arguments and the number of appearances is very |
| 540 | important. This is what the "<tt>cl::list</tt>" template is for. First, |
| 541 | start by defining an enum of the optimizations that you would like to |
| 542 | perform:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 543 | |
| 544 | <pre> |
| 545 | enum Opts { |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 546 | // 'inline' is a C++ keyword, so name it 'inlining' |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 547 | dce, constprop, inlining, strip |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 548 | }; |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 549 | </pre><p> |
| 550 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 551 | Then define your "<tt>cl::list</tt>" variable:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 552 | |
| 553 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 554 | cl::list<Opts> OptimizationList(cl::desc("<i>Available Optimizations:</i>"), |
| 555 | cl::values( |
| 556 | clEnumVal(dce , "<i>Dead Code Elimination</i>"), |
| 557 | clEnumVal(constprop , "<i>Constant Propogation</i>"), |
| 558 | clEnumValN(inlining, "<i>inline</i>", "<i>Procedure Integration</i>"), |
| 559 | clEnumVal(strip , "<i>Strip Symbols</i>"), |
| 560 | 0)); |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 561 | </pre><p> |
| 562 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 563 | This defines a variable that is conceptually of the type |
| 564 | "<tt>std::vector<enum Opts></tt>". Thus, you can access it with standard |
| 565 | vector methods:<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 566 | |
| 567 | <pre> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 568 | for (unsigned i = 0; i != OptimizationList.size(); ++i) |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 569 | switch (OptimizationList[i]) |
| 570 | ... |
| 571 | </pre> |
| 572 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 573 | ... to iterate through the list of options specified.<p> |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 574 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 575 | Note that the "<tt>cl::list</tt>" template is completely general and may be used |
| 576 | with any data types or other arguments that you can use with the |
| 577 | "<tt>cl::opt</tt>" template. One especially useful way to use a list is to |
| 578 | capture all of the positional arguments together if there may be more than one |
| 579 | specified. In the case of a linker, for example, the linker takes several |
| 580 | '<tt>.o</tt>' files, and needs to capture them into a list. This is naturally |
| 581 | specified as:<p> |
Chris Lattner | 3e5fe17 | 2002-04-13 18:35:59 +0000 | [diff] [blame] | 582 | |
| 583 | <pre> |
| 584 | ... |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 585 | cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore); |
Chris Lattner | 3e5fe17 | 2002-04-13 18:35:59 +0000 | [diff] [blame] | 586 | ... |
| 587 | </pre><p> |
| 588 | |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 589 | This variable works just like a "<tt>vector<string></tt>" object. As |
| 590 | such, accessing the list is simple, just like above. In this example, we used |
| 591 | the <tt>cl::OneOrMore</tt> modifier to inform the CommandLine library that it is |
| 592 | an error if the user does not specify any <tt>.o</tt> files on our command line. |
| 593 | Again, this just reduces the amount of checking we have to do.<p> |
Chris Lattner | 3e5fe17 | 2002-04-13 18:35:59 +0000 | [diff] [blame] | 594 | |
Chris Lattner | 3e5fe17 | 2002-04-13 18:35:59 +0000 | [diff] [blame] | 595 | |
| 596 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 597 | <!-- *********************************************************************** --> |
| 598 | </ul><table width="100%" bgcolor="#330077" border=0 cellpadding=4 cellspacing=0><tr><td align=center><font color="#EEEEFF" size=+2 face="Georgia,Palatino"><b> |
| 599 | <a name="referenceguide">Reference Guide |
| 600 | </b></font></td></tr></table><ul> |
| 601 | <!-- *********************************************************************** --> |
| 602 | |
| 603 | Reference Guide: TODO |
| 604 | |
| 605 | |
| 606 | <!-- *********************************************************************** --> |
| 607 | </ul><table width="100%" bgcolor="#330077" border=0 cellpadding=4 cellspacing=0><tr><td align=center><font color="#EEEEFF" size=+2 face="Georgia,Palatino"><b> |
| 608 | <a name="extensionguide">Extension Guide |
| 609 | </b></font></td></tr></table><ul> |
| 610 | <!-- *********************************************************************** --> |
| 611 | |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 612 | |
Chris Lattner | 3e5fe17 | 2002-04-13 18:35:59 +0000 | [diff] [blame] | 613 | Look at the examples classes provided. This section is a TODO. |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 614 | |
| 615 | |
| 616 | |
| 617 | <!-- *********************************************************************** --> |
| 618 | </ul> |
| 619 | <!-- *********************************************************************** --> |
| 620 | |
| 621 | <hr> |
| 622 | <font size=-1> |
| 623 | <address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address> |
| 624 | <!-- Created: Tue Jan 23 15:19:28 CST 2001 --> |
| 625 | <!-- hhmts start --> |
Chris Lattner | ae85363 | 2002-07-25 19:27:01 +0000 | [diff] [blame] | 626 | Last modified: Thu Jul 25 14:25:50 CDT 2002 |
Chris Lattner | 209c7f4 | 2001-07-23 23:03:12 +0000 | [diff] [blame] | 627 | <!-- hhmts end --> |
| 628 | </font> |
| 629 | </body></html> |