OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| 2 |
| 3 <html> |
| 4 <head> |
| 5 <title>How To Use Google Commandline Flags</title> |
| 6 |
| 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| 8 <link href="http://www.google.com/favicon.ico" type="image/x-icon" |
| 9 rel="shortcut icon"> |
| 10 <link href="designstyle.css" type="text/css" rel="stylesheet"> |
| 11 <style type="text/css"> |
| 12 <!-- |
| 13 ol.bluelist li { |
| 14 color: #3366ff; |
| 15 font-family: sans-serif; |
| 16 } |
| 17 ol.bluelist li p { |
| 18 color: #000; |
| 19 font-family: "Times Roman", times, serif; |
| 20 } |
| 21 ul.blacklist li { |
| 22 color: #000; |
| 23 font-family: "Times Roman", times, serif; |
| 24 } |
| 25 //--> |
| 26 </style> |
| 27 </head> |
| 28 |
| 29 <body> |
| 30 |
| 31 <h1>How To Use Google Commandline Flags (gflags)</h1> |
| 32 <small>(as of |
| 33 <script type=text/javascript> |
| 34 var lm = new Date(document.lastModified); |
| 35 document.write(lm.toDateString()); |
| 36 </script>) |
| 37 </small> |
| 38 <br> |
| 39 |
| 40 |
| 41 <h2> <A NAME=intro>Introduction, and Comparison to Other Commandline |
| 42 Flags Libraries</A> </h2> |
| 43 |
| 44 <p><b>Commandline flags</b> are flags that users specify on the |
| 45 command line when they run an executable. In the command</p> |
| 46 <pre> |
| 47 fgrep -l -f /var/tmp/foo johannes brahms |
| 48 </pre> |
| 49 <p><code>-l</code> and <code>-f /var/tmp/foo</code> are the two |
| 50 commandline flags. (<code>johannes</code> and <code>brahms</code>, |
| 51 which don't start with a dash, are <b>commandline arguments</b>.)</p> |
| 52 |
| 53 <p>Typically, an application lists what flags the user is allowed to |
| 54 pass in, and what arguments they take -- in this example, |
| 55 <code>-l</code> takes no argument, and <code>-f</code> takes a |
| 56 string (in particular, a filename) as an argument. Users can use a |
| 57 library to help parse the commandline and store the flags in some data |
| 58 structure.</p> |
| 59 |
| 60 <p>Google's commandline flags library differs from other libraries, |
| 61 such as <code>getopt()</code>, in that flag definitions can be |
| 62 scattered around the source code, and not just listed in one place |
| 63 such as <code>main()</code>. In practice, this means that a single |
| 64 source-code file will define and use flags that are meaningful to that |
| 65 file. Any application that links in that file will get the flags, and |
| 66 the google commandline flags library will automatically handle that |
| 67 flag appropriately.</p> |
| 68 |
| 69 <p>There's significant gain in flexibility, and ease of code reuse, |
| 70 due to this technique. However, there is a danger that two files will |
| 71 define the same flag, and then give an error when they're linked |
| 72 together.</p> |
| 73 |
| 74 <p>The rest of this document describes how to use the commandlineflag |
| 75 library. It's a C++ library, so examples are in C++. However, there |
| 76 is a Python port with the same functionality, and this discussion |
| 77 translates directly to Python.</p> |
| 78 |
| 79 |
| 80 <h2> <A name=define>DEFINE: Defining Flags In Program</A> </h2> |
| 81 |
| 82 <p> Defining a flag is easy: just use the appropriate macro for the |
| 83 type you want the flag to be, as defined at the bottom of |
| 84 <code>gflags/gflags.h</code>. Here's an example file, |
| 85 <code>foo.cc</code>:</p> |
| 86 |
| 87 <pre> |
| 88 #include <gflags/gflags.h> |
| 89 |
| 90 DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing")
; |
| 91 DEFINE_string(languages, "english,french,german", |
| 92 "comma-separated list of languages to offer in the 'lang' menu"
); |
| 93 </pre> |
| 94 |
| 95 <p><code>DEFINE_bool</code> defines a boolean flag. Here are the |
| 96 types supported:</p> |
| 97 <ul> |
| 98 <li> <code>DEFINE_bool</code>: boolean |
| 99 <li> <code>DEFINE_int32</code>: 32-bit integer |
| 100 <li> <code>DEFINE_int64</code>: 64-bit integer |
| 101 <li> <code>DEFINE_uint64</code>: unsigned 64-bit integer |
| 102 <li> <code>DEFINE_double</code>: double |
| 103 <li> <code>DEFINE_string</code>: C++ string |
| 104 </ul> |
| 105 |
| 106 <p>Note that there are no 'complex' types like lists: the "languages" |
| 107 flag in our example is a list of strings, but is defined of type |
| 108 "string", not "list_of_string" or similar. This is by design. We'd |
| 109 rather use only simple types for the flags, and allow for complex, |
| 110 arbitrary parsing routines to parse them, then to try to put the logic |
| 111 inside the flags library proper.</p> |
| 112 |
| 113 <p>All DEFINE macros take the same three arguments: the name of the |
| 114 flag, its default value, and a 'help' string that describes its use. |
| 115 The 'help' string is displayed when the user runs the application with |
| 116 the <A HREF="#special"><code>--help</code> flag</A>.</p> |
| 117 |
| 118 <p>You can define a flag in any source-code file in your executable. |
| 119 Only define a flag once! If you want to access a flag in more than |
| 120 one source file, DEFINE it in one file, and <A |
| 121 HREF="#declare">DECLARE</A> it in the others. Even better, DEFINE it |
| 122 in <code>foo.cc</code> and DECLARE it in <code>foo.h</code>; then |
| 123 everyone who <code>#includes foo.h</code> can use the flag.</p> |
| 124 |
| 125 <p>Note that while most functions in this library are defined in the |
| 126 <code>google</code> namespace, <code>DEFINE_foo</code> (and |
| 127 <code>DECLARE_foo</code>, <A HREF="#declare">below</A>), should always |
| 128 be in the global namespace.</p> |
| 129 |
| 130 |
| 131 <h2> <A name=using>Accessing the Flag</A> </h2> |
| 132 |
| 133 <p>All defined flags are available to the program as just a normal |
| 134 variable, with the prefix <code>FLAGS_</code> prepended. In the above |
| 135 example, the macros define two variables, <code>FLAGS_big_menu</code> |
| 136 (a bool), and <code>FLAGS_languages</code> (a C++ string).</p> |
| 137 |
| 138 <p>You can read and write to the flag just like any other |
| 139 variable:</p> |
| 140 <pre> |
| 141 if (FLAGS_consider_made_up_languages) |
| 142 FLAGS_languages += ",klingon"; // implied by --consider_made_up_languages |
| 143 if (FLAGS_languages.find("finnish") != string::npos) |
| 144 HandleFinnish(); |
| 145 </pre> |
| 146 |
| 147 <p>You can also get and set flag values via special functions in |
| 148 <code>gflags.h</code>. That's a rarer use case, though.</p> |
| 149 |
| 150 |
| 151 <h2> <A name=declare>DECLARE: Using the Flag in a Different File</A> </h2> |
| 152 |
| 153 <p>Accessing a flag in the manner of the previous section only works |
| 154 if the flag was <code>DEFINE</code>-ed at the top of the file. If it |
| 155 wasn't, you'll get an 'unknown variable' error.</p> |
| 156 |
| 157 <p>The <code>DECLARE_type</code> macro is available when you want to |
| 158 use a flag that's defined in another file. For instance, if I were |
| 159 writing <code>bar.cc</code> but wanted to access the big_menu, flag, I |
| 160 would put this near the top of <code>bar.cc</code>:</p> |
| 161 <pre> |
| 162 DECLARE_bool(big_menu); |
| 163 </pre> |
| 164 |
| 165 <p>This is functionally equivalent to saying <code>extern |
| 166 FLAGS_big_menu</code>.</p> |
| 167 |
| 168 <p>Note that such an extern declaration introduces a dependency |
| 169 between your file and the file that defines the <code>big_menu</code> |
| 170 flag: <code>foo.cc</code>, in this case. Such implicit dependencies |
| 171 can be difficult to manage in large projects. For that reason we |
| 172 recommend the following guideline:</p> |
| 173 |
| 174 <blockquote> |
| 175 If you DEFINE a flag in <code>foo.cc</code>, either don't DECLARE it |
| 176 at all, only DECLARE it in tightly related tests, or only DECLARE |
| 177 it in <code>foo.h</code>. |
| 178 </blockquote> |
| 179 |
| 180 <p>You should go the do-not-DECLARE route when the flag is only needed |
| 181 by <code>foo.cc</code>, and not in any other file. If you want to |
| 182 modify the value of the flag in the related test file to see if it is |
| 183 functioning as expected, DECLARE it in the <code>foo_test.cc</code> |
| 184 file. |
| 185 |
| 186 <p>If the flag does span multiple files, DECLARE it in the associated |
| 187 <code>.h</code> file, and make others <code>#include</code> that |
| 188 <code>.h</code> file if they want to access the flag. The |
| 189 <code>#include</code> will make explicit the dependency between the |
| 190 two files. This causes the flag to be a global variable.</p> |
| 191 |
| 192 |
| 193 <h2> <A name=validate>RegisterFlagValidator: Sanity-checking Flag Values</A> </h
2> |
| 194 |
| 195 <p>After DEFINE-ing a flag, you may optionally register a validator |
| 196 function with the flag. If you do this, after the flag is parsed from |
| 197 the commandline, and whenever its value is changes via a call to |
| 198 <code>SetCommandLineOption()</code>, the validator function is called |
| 199 with the new value as an argument. The validator function should |
| 200 return 'true' if the flag value is valid, and false otherwise. |
| 201 |
| 202 <p>Here is an example use of this functionality:</p> |
| 203 <pre> |
| 204 static bool ValidatePort(const char* flagname, int32 value) { |
| 205 if (value > 0 && value < 32768) // value is ok |
| 206 return true; |
| 207 printf("Invalid value for --%s: %d\n", flagname, (int)value); |
| 208 return false; |
| 209 } |
| 210 DEFINE_int32(port, 0, "What port to listen on"); |
| 211 static const bool port_dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort)
; |
| 212 </pre> |
| 213 |
| 214 <p>By doing the registration at global initialization time (right |
| 215 after the DEFINE), we ensure that the registration happens before |
| 216 the commandline is parsed at the beginning of <code>main()</code>.</p> |
| 217 |
| 218 <p><code>RegisterFlagValidator()</code> returns true if the |
| 219 registration is successful. It return false if the registration fails |
| 220 because a) the first argument does not refer to a commandline flag, or |
| 221 b) a different validator has already been registered for this flag.</p> |
| 222 |
| 223 |
| 224 <h2> <A name=together>Putting It Together: How to Set Up Flags</A> </h2> |
| 225 |
| 226 <p>The final piece is the one that tells the executable to process the |
| 227 commandline flags, and set the <code>FLAGS_*</code> variables to the |
| 228 appropriate, non-default value based on what is seen on the |
| 229 commandline. This is equivalent to the <code>getopt()</code> call in |
| 230 the getopt library, but has much less overhead to use. In fact, it's |
| 231 just a single function call:</p> |
| 232 |
| 233 <pre> |
| 234 google::ParseCommandLineFlags(&argc, &argv, true); |
| 235 </pre> |
| 236 |
| 237 <p>Usually, this code is at the beginning of <code>main()</code>. |
| 238 <code>argc</code> and <code>argv</code> are exactly as passed in to |
| 239 <code>main()</code>. This routine might modify them, which is why |
| 240 pointers to them are passed in.</p> |
| 241 |
| 242 <p>The last argument is called "remove_flags". If true, then |
| 243 <code>ParseCommandLineFlags</code> removes the flags and their |
| 244 arguments from <code>argv</code>, and modifies <code>argc</code> |
| 245 appropriately. In this case, after the function call, |
| 246 <code>argv</code> will hold only commandline arguments, and not |
| 247 commandline flags.</p> |
| 248 |
| 249 <p>If, on the other hand, <code>remove_flags</code> is false, then |
| 250 <code>ParseCommandLineFlags</code> will leave argc unchanged, but will |
| 251 rearrange the arguments in argv so that the flags are all at the |
| 252 beginning. For example, if the input is <code>"/bin/foo" "arg1" "-q" |
| 253 "arg2"</code> (which is legal but weird), the function will rearrange |
| 254 <code>argv</code> so it reads <code>"/bin/foo", "-q", "arg1", |
| 255 "arg2"</code>. In this case, <code>ParseCommandLineFlags</code> |
| 256 returns the index into argv that holds the first commandline argument: |
| 257 that is, the index past the last flag. (In this example, it would |
| 258 return 2, since <code>argv[2]</code> points to <code>arg1</code>.)</p> |
| 259 |
| 260 <p>In either case, the <code>FLAGS_*</code> variables are modified |
| 261 based on what was <A HREF="#commandline">passed in on the |
| 262 commandline</A>.</p> |
| 263 |
| 264 |
| 265 <h2> <A name=commandline>Setting Flags on the Command Line</A> </h2> |
| 266 |
| 267 <p>The reason you make something a flag instead of a compile-time |
| 268 constant, is so users can specify a non-default value on the |
| 269 commandline. Here's how they might do it for an application that |
| 270 links in <code>foo.cc</code>:</p> |
| 271 <pre> |
| 272 app_containing_foo --nobig_menu -languages="chinese,japanese,korean" ... |
| 273 </pre> |
| 274 |
| 275 <p>This sets <code>FLAGS_big_menu = false;</code> and |
| 276 <code>FLAGS_languages = "chinese,japanese,korean"</code>, when |
| 277 <code>ParseCommandLineFlags</code> is run.</p> |
| 278 |
| 279 <p>Note the atypical syntax for setting a boolean flag to false: |
| 280 putting "no" in front of its name. There's a fair bit of flexibility |
| 281 to how flags may be specified. Here's an example of all the ways to |
| 282 specify the "languages" flag:</p> |
| 283 <ul> |
| 284 <li> <code>app_containing_foo --languages="chinese,japanese,korean"</code> |
| 285 <li> <code>app_containing_foo -languages="chinese,japanese,korean"</code> |
| 286 <li> <code>app_containing_foo --languages "chinese,japanese,korean"</code> |
| 287 <li> <code>app_containing_foo -languages "chinese,japanese,korean"</code> |
| 288 </ul> |
| 289 |
| 290 <p>For boolean flags, the possibilities are slightly different:</p> |
| 291 <ul> |
| 292 <li> <code>app_containing_foo --big_menu</code> |
| 293 <li> <code>app_containing_foo --nobig_menu</code> |
| 294 <li> <code>app_containing_foo --big_menu=true</code> |
| 295 <li> <code>app_containing_foo --big_menu=false</code> |
| 296 </ul> |
| 297 <p>(as well as the single-dash variant on all of these).</p> |
| 298 |
| 299 <p>Despite this flexibility, we recommend using only a single form: |
| 300 <code>--variable=value</code> for non-boolean flags, and |
| 301 <code>--variable/--novariable</code> for boolean flags. This |
| 302 consistency will make your code more readable, and is also the format |
| 303 required for certain special-use cases like <A |
| 304 HREF="#flagfiles">flagfiles</A>.</p> |
| 305 |
| 306 <p>It is a fatal error to specify a flag on the commandline that has |
| 307 not been DEFINED somewhere in the executable. If you need that |
| 308 functionality for some reason -- say you want to use the same set of |
| 309 flags for several executables, but not all of them DEFINE every flag |
| 310 in your list -- you can specify <A |
| 311 HREF="#special"><code>--undefok</code></A> to suppress the error.</p> |
| 312 |
| 313 <p>As in getopt(), <code>--</code> by itself will terminate flags |
| 314 processing. So in <code>foo -f1 1 -- -f2 2</code>, <code>f1</code> is |
| 315 considered a flag, but <code>-f2</code> is not.</p> |
| 316 |
| 317 <p>Note that flags do not have single-letter synonyms, like they do in |
| 318 the getopt library, nor do we allow "combining" flags behind a |
| 319 single dash, as in <code>ls -la</code>.</p> |
| 320 |
| 321 |
| 322 <h2> <A name="special">Special Flags</code> </h2> |
| 323 |
| 324 <p>There are a few flags defined by the commandlineflags module |
| 325 itself, and are available to all applications. These fall into three |
| 326 categories. First are the 'reporting' flags that, when found, cause |
| 327 the application to print some information about itself and exit.</p> |
| 328 |
| 329 <table><tr valign=top> |
| 330 <td><code>--help</code></td> |
| 331 <td>shows all flags from all files, sorted by file and then by name; |
| 332 shows the flagname, its default value, and its help string</td> |
| 333 </tr><tr valign=top> |
| 334 <td><code>--helpfull</code></td> |
| 335 <td>same as -help, but unambiguously asks for all flags |
| 336 (in case -help changes in the future)</td> |
| 337 </tr><tr valign=top> |
| 338 <td><code>--helpshort</code></td> |
| 339 <td>shows only flags for the file that includes <code>main()</code></td> |
| 340 </tr><tr valign=top> |
| 341 <td><code>--helpxml</code></td> |
| 342 <td>like --help, but output is in xml for easier parsing</td> |
| 343 </tr><tr valign=top> |
| 344 <td><code>--helpon=FILE </code></td> |
| 345 <td>shows only flags defined in FILE.*</td> |
| 346 </tr><tr valign=top> |
| 347 <td><code>--helpmatch=S</code></td> |
| 348 <td>shows only flags defined in *S*.*</td> |
| 349 </tr><tr valign=top> |
| 350 <td><code>--helppackage</code></td> |
| 351 <td>shows flags defined in files in same directory as <code>main()</code></td> |
| 352 </tr><tr valign=top> |
| 353 <td><code>--version</code></td> |
| 354 <td>prints version info for the executable</td> |
| 355 </tr></table> |
| 356 |
| 357 <p>Second are the flags that affect how other flags are parsed.</p> |
| 358 |
| 359 <table><tr valign=top> |
| 360 <td><code>--undefok=flagname,flagname,...</code></td> |
| 361 <td>for those names listed as the argument to <code>--undefok</code>, |
| 362 suppress the normal error-exit that occurs when |
| 363 <code>--name</code> is seen on the commandline, but |
| 364 <code>name</code> has not been DEFINED anywhere in the |
| 365 application |
| 366 </table> |
| 367 |
| 368 <p>Third are the 'recursive' flags, that cause other flag values to be |
| 369 set: <code>--fromenv</code>, <code>--tryfromenv</code>, |
| 370 <code>--flagfile</code>. These are described below in more |
| 371 detail.</p> |
| 372 |
| 373 <h3> <code>--fromenv</code> </h3> |
| 374 |
| 375 <p><code>--fromenv=foo,bar</code> says to read the values for the |
| 376 <code>foo</code> and <code>bar</code> flags from the environment. |
| 377 In concert with this flag, you must actually set the values in the |
| 378 environment, via a line like one of the two below:</p> |
| 379 <pre> |
| 380 export FLAGS_foo=xxx; export FLAGS_bar=yyy # sh |
| 381 setenv FLAGS_foo xxx; setenv FLAGS_bar yyy # tcsh |
| 382 </pre> |
| 383 <p>This is equivalent to specifying <code>--foo=xxx</code>, |
| 384 <code>--bar=yyy</code> on the commandline.</p> |
| 385 |
| 386 <p>Note it is a fatal error to say <code>--fromenv=foo</code> if |
| 387 <code>foo</code> is not DEFINED somewhere in the application. (Though |
| 388 you can suppress this error via <code>--undefok=foo</code>, just like |
| 389 for any other flag.)</p> |
| 390 |
| 391 <p>It is also a fatal error to say <code>--fromenv=foo</code> if |
| 392 <code>FLAGS_foo</code> is not actually defined in the environment.</p> |
| 393 |
| 394 <h3> <code>--tryfromenv</code> </h3> |
| 395 |
| 396 <p><code>--tryfromenv</code> is exactly like <code>--fromenv</code>, |
| 397 except it is <b>not</b> a fatal error to say |
| 398 <code>--tryfromenv=foo</code> if <code>FLAGS_foo</code> is not |
| 399 actually defined in the environment. Instead, in such cases, |
| 400 <code>FLAGS_foo</code> just keeps its default value as specified in |
| 401 the application.</p> |
| 402 |
| 403 <p>Note it is still an error to say <code>--tryfromenv=foo</code> if |
| 404 <code>foo</code> is not DEFINED somewhere in the application.</p> |
| 405 |
| 406 <h3> <code>--flagfile</code> </h3> |
| 407 |
| 408 <p><code>--flagfile=f</code> tells the commandlineflags module to read |
| 409 the file <code>f</code>, and to run all the flag-assignments found in |
| 410 that file as if these flags had been specified on the commandline.</p> |
| 411 |
| 412 <p>In its simplest form, <code>f</code> should just be a list of flag |
| 413 assignments, one per line. Unlike on the commandline, the equals sign |
| 414 separating a flagname from its argument is <i>required</i> for |
| 415 flagfiles. An example flagfile, <code>/tmp/myflags</code>:</p> |
| 416 <pre> |
| 417 --nobig_menus |
| 418 --languages=english,french |
| 419 </pre> |
| 420 |
| 421 <p>With this flagfile, the following two lines are equivalent:<p> |
| 422 <pre> |
| 423 ./myapp --foo --nobig_menus --languages=english,french --bar |
| 424 ./myapp --foo --flagfile=/tmp/myflags --bar |
| 425 </pre> |
| 426 |
| 427 <p>Note that many errors are silently suppressed in flagfiles. In |
| 428 particular, unrecognized flagnames are silently ignored, as are flags |
| 429 that are missing a required value (e.g., a flagfile that just says |
| 430 <code>--languages</code>).</p> |
| 431 |
| 432 <p>The general format of a flagfile is a bit more complicated than the |
| 433 simple, common case above. It is: a sequence of filenames, one per |
| 434 line, followed by a sequence of flags, one per line, repeated as many |
| 435 times as desired. Filenames in a flagfile can use wildcards |
| 436 (<code>*</code> and <code>?</code>), and the sequence of flags located |
| 437 after a sequence of filenames is processed only if the current |
| 438 executable's name matches one of the filenames. It is possible to |
| 439 start the flagfile with a sequence of flags instead of a sequence of |
| 440 filenames; if such a sequence of flags is present, these flags are |
| 441 applied to the current executable no matter what it is.</p> |
| 442 |
| 443 <p>Lines that start with a <code>#</code> are ignored as comments. |
| 444 Leading whitespace is also ignored in flagfiles, as are blank |
| 445 lines.</p> |
| 446 |
| 447 <p>It is possible for a flagfile to use the <code>--flagfile</code> |
| 448 flag to include another flagfile.</p> |
| 449 |
| 450 <p>Flags are always processed in the expected order. That is, |
| 451 processing begins by examining the flags specified directly on the |
| 452 command line. If a flagfile is specified, its contents are processed, |
| 453 and then processing continues with remaining flags from the command |
| 454 line.</p> |
| 455 |
| 456 |
| 457 <h2> <A name="api">The API</code> </h2> |
| 458 |
| 459 <p>In addition to accessing <code>FLAGS_foo</code> directly, it is |
| 460 possible to access the flags programmatically, through an API. It is |
| 461 also possible to access information about a flag, such as its default |
| 462 value and help-string. A <code>FlagSaver</code> makes it easy to |
| 463 modify flags and then automatically undo the modifications later. |
| 464 Finally, there are somewhat unrelated, but useful, routines to easily |
| 465 access parts of <code>argv</code> outside main, including the program |
| 466 name (<code>argv[0]</code>).</p> |
| 467 |
| 468 <p>For more information about these routines, and other useful helper |
| 469 methods such as <code>google::SetUsageMessage</code>, see |
| 470 <code>gflags.h</code>.</p> |
| 471 |
| 472 |
| 473 <h2> <A name="misc">Miscellaneous Notes</code> </h2> |
| 474 |
| 475 <p>If your application has code like this:</p> |
| 476 <pre> |
| 477 #define STRIP_FLAG_HELP 1 // this must go before the #include! |
| 478 #include <gflags/gflags.h> |
| 479 </pre> |
| 480 <p>we will remove the help messages from the compiled source. This can |
| 481 reduce the size of the resulting binary somewhat, and may also be |
| 482 useful for security reasons.</p> |
| 483 |
| 484 |
| 485 <hr> |
| 486 <address> |
| 487 Craig Silverstein<br> |
| 488 <script type=text/javascript> |
| 489 var lm = new Date(document.lastModified); |
| 490 document.write(lm.toDateString()); |
| 491 </script> |
| 492 </address> |
| 493 |
| 494 </body> |
| 495 </html> |
OLD | NEW |