Annotation of embedaddon/readline/doc/hstech.texi, revision 1.1.1.2

1.1       misho       1: @ignore
                      2: This file documents the user interface to the GNU History library.
                      3: 
1.1.1.2 ! misho       4: Copyright (C) 1988-2020 Free Software Foundation, Inc.
1.1       misho       5: Authored by Brian Fox and Chet Ramey.
                      6: 
                      7: Permission is granted to make and distribute verbatim copies of this manual
                      8: provided the copyright notice and this permission notice are preserved on
                      9: all copies.
                     10: 
                     11: Permission is granted to process this file through Tex and print the
                     12: results, provided the printed document carries copying permission notice
                     13: identical to this one except for the removal of this paragraph (this
                     14: paragraph not being relevant to the printed manual).
                     15: 
                     16: Permission is granted to copy and distribute modified versions of this
                     17: manual under the conditions for verbatim copying, provided also that the
                     18: GNU Copyright statement is available to the distributee, and provided that
                     19: the entire resulting derived work is distributed under the terms of a
                     20: permission notice identical to this one.
                     21: 
                     22: Permission is granted to copy and distribute translations of this manual
                     23: into another language, under the above conditions for modified versions.
                     24: @end ignore
                     25: 
                     26: @node Programming with GNU History
                     27: @chapter Programming with GNU History
                     28: 
                     29: This chapter describes how to interface programs that you write
                     30: with the @sc{gnu} History Library.
                     31: It should be considered a technical guide.
                     32: For information on the interactive use of @sc{gnu} History, @pxref{Using
                     33: History Interactively}.
                     34: 
                     35: @menu
                     36: * Introduction to History::    What is the GNU History library for?
                     37: * History Storage::            How information is stored.
                     38: * History Functions::          Functions that you can use.
                     39: * History Variables::          Variables that control behaviour.
                     40: * History Programming Example::        Example of using the GNU History Library.
                     41: @end menu
                     42: 
                     43: @node Introduction to History
                     44: @section Introduction to History
                     45: 
                     46: Many programs read input from the user a line at a time.  The @sc{gnu}
                     47: History library is able to keep track of those lines, associate arbitrary
                     48: data with each line, and utilize information from previous lines in
                     49: composing new ones. 
                     50: 
1.1.1.2 ! misho      51: A programmer using the History library has available functions
1.1       misho      52: for remembering lines on a history list, associating arbitrary data
                     53: with a line, removing lines from the list, searching through the list
                     54: for a line containing an arbitrary text string, and referencing any line
                     55: in the list directly.  In addition, a history @dfn{expansion} function
                     56: is available which provides for a consistent user interface across
                     57: different programs.
                     58: 
                     59: The user using programs written with the History library has the
                     60: benefit of a consistent user interface with a set of well-known
                     61: commands for manipulating the text of previous lines and using that text
                     62: in new commands.  The basic history manipulation commands are similar to
                     63: the history substitution provided by @code{csh}.
                     64: 
1.1.1.2 ! misho      65: The programmer can also use the Readline library, which
1.1       misho      66: includes some history manipulation by default, and has the added
                     67: advantage of command line editing.
                     68: 
                     69: Before declaring any functions using any functionality the History
                     70: library provides in other code, an application writer should include
                     71: the file @code{<readline/history.h>} in any file that uses the
                     72: History library's features.  It supplies extern declarations for all
                     73: of the library's public functions and variables, and declares all of
                     74: the public data structures.
                     75: 
                     76: @node History Storage
                     77: @section History Storage
                     78: 
                     79: The history list is an array of history entries.  A history entry is
                     80: declared as follows:
                     81: 
                     82: @example
                     83: typedef void *histdata_t;
                     84: 
                     85: typedef struct _hist_entry @{
                     86:   char *line;
                     87:   char *timestamp;
                     88:   histdata_t data;
                     89: @} HIST_ENTRY;
                     90: @end example
                     91: 
                     92: The history list itself might therefore be declared as
                     93: 
                     94: @example
                     95: HIST_ENTRY **the_history_list;
                     96: @end example
                     97: 
                     98: The state of the History library is encapsulated into a single structure:
                     99: 
                    100: @example
                    101: /*
                    102:  * A structure used to pass around the current state of the history.
                    103:  */
                    104: typedef struct _hist_state @{
                    105:   HIST_ENTRY **entries; /* Pointer to the entries themselves. */
                    106:   int offset;           /* The location pointer within this array. */
                    107:   int length;           /* Number of elements within this array. */
                    108:   int size;             /* Number of slots allocated to this array. */
                    109:   int flags;
                    110: @} HISTORY_STATE;
                    111: @end example
                    112: 
                    113: If the flags member includes @code{HS_STIFLED}, the history has been
                    114: stifled.
                    115: 
                    116: @node History Functions
                    117: @section History Functions
                    118: 
                    119: This section describes the calling sequence for the various functions
                    120: exported by the @sc{gnu} History library.
                    121: 
                    122: @menu
                    123: * Initializing History and State Management::  Functions to call when you
                    124:                                                want to use history in a
                    125:                                                program.
                    126: * History List Management::            Functions used to manage the list
                    127:                                        of history entries.
                    128: * Information About the History List:: Functions returning information about
                    129:                                        the history list.
                    130: * Moving Around the History List::     Functions used to change the position
                    131:                                        in the history list.
                    132: * Searching the History List::         Functions to search the history list
                    133:                                        for entries containing a string.
                    134: * Managing the History File::          Functions that read and write a file
                    135:                                        containing the history list.
                    136: * History Expansion::                  Functions to perform csh-like history
                    137:                                        expansion.
                    138: @end menu
                    139: 
                    140: @node Initializing History and State Management
                    141: @subsection Initializing History and State Management
                    142: 
                    143: This section describes functions used to initialize and manage
                    144: the state of the History library when you want to use the history
                    145: functions in your program.
                    146: 
                    147: @deftypefun void using_history (void)
                    148: Begin a session in which the history functions might be used.  This
                    149: initializes the interactive variables.
                    150: @end deftypefun
                    151: 
                    152: @deftypefun {HISTORY_STATE *} history_get_history_state (void)
                    153: Return a structure describing the current state of the input history.
                    154: @end deftypefun
                    155: 
                    156: @deftypefun void history_set_history_state (HISTORY_STATE *state)
                    157: Set the state of the history list according to @var{state}.
                    158: @end deftypefun
                    159: 
                    160: @node History List Management
                    161: @subsection History List Management
                    162: 
                    163: These functions manage individual entries on the history list, or set
                    164: parameters managing the list itself.
                    165: 
                    166: @deftypefun void add_history (const char *string)
                    167: Place @var{string} at the end of the history list.  The associated data
                    168: field (if any) is set to @code{NULL}.
1.1.1.2 ! misho     169: If the maximum number of history entries has been set using
        !           170: @code{stifle_history()}, and the new number of history entries would exceed
        !           171: that maximum, the oldest history entry is removed.
1.1       misho     172: @end deftypefun
                    173: 
                    174: @deftypefun void add_history_time (const char *string)
                    175: Change the time stamp associated with the most recent history entry to
                    176: @var{string}.
                    177: @end deftypefun
                    178: 
                    179: @deftypefun {HIST_ENTRY *} remove_history (int which)
                    180: Remove history entry at offset @var{which} from the history.  The
                    181: removed element is returned so you can free the line, data,
                    182: and containing structure.
                    183: @end deftypefun
                    184: 
                    185: @deftypefun {histdata_t} free_history_entry (HIST_ENTRY *histent)
                    186: Free the history entry @var{histent} and any history library private
                    187: data associated with it.  Returns the application-specific data
                    188: so the caller can dispose of it.
                    189: @end deftypefun
                    190: 
                    191: @deftypefun {HIST_ENTRY *} replace_history_entry (int which, const char *line, histdata_t data)
                    192: Make the history entry at offset @var{which} have @var{line} and @var{data}.
                    193: This returns the old entry so the caller can dispose of any
                    194: application-specific data.  In the case
                    195: of an invalid @var{which}, a @code{NULL} pointer is returned.
                    196: @end deftypefun
                    197: 
                    198: @deftypefun void clear_history (void)
                    199: Clear the history list by deleting all the entries.
                    200: @end deftypefun
                    201: 
                    202: @deftypefun void stifle_history (int max)
                    203: Stifle the history list, remembering only the last @var{max} entries.
1.1.1.2 ! misho     204: The history list will contain only @var{max} entries at a time.
1.1       misho     205: @end deftypefun
                    206: 
                    207: @deftypefun int unstifle_history (void)
                    208: Stop stifling the history.  This returns the previously-set
                    209: maximum number of history entries (as set by @code{stifle_history()}).
                    210: The value is positive if the history was
                    211: stifled, negative if it wasn't.
                    212: @end deftypefun
                    213: 
                    214: @deftypefun int history_is_stifled (void)
                    215: Returns non-zero if the history is stifled, zero if it is not.
                    216: @end deftypefun
                    217: 
                    218: @node Information About the History List
                    219: @subsection Information About the History List
                    220: 
                    221: These functions return information about the entire history list or
                    222: individual list entries.
                    223: 
                    224: @deftypefun {HIST_ENTRY **} history_list (void)
                    225: Return a @code{NULL} terminated array of @code{HIST_ENTRY *} which is the
                    226: current input history.  Element 0 of this list is the beginning of time.
                    227: If there is no history, return @code{NULL}.
                    228: @end deftypefun
                    229: 
                    230: @deftypefun int where_history (void)
                    231: Returns the offset of the current history element.
                    232: @end deftypefun
                    233: 
                    234: @deftypefun {HIST_ENTRY *} current_history (void)
                    235: Return the history entry at the current position, as determined by
                    236: @code{where_history()}.  If there is no entry there, return a @code{NULL}
                    237: pointer.
                    238: @end deftypefun
                    239: 
                    240: @deftypefun {HIST_ENTRY *} history_get (int offset)
1.1.1.2 ! misho     241: Return the history entry at position @var{offset}.
        !           242: The range of valid
        !           243: values of @var{offset} starts at @code{history_base} and ends at
        !           244: @var{history_length} - 1 (@pxref{History Variables}).
        !           245: If there is no entry there, or if @var{offset} is outside the valid
        !           246: range, return a @code{NULL} pointer.
1.1       misho     247: @end deftypefun
                    248: 
                    249: @deftypefun time_t history_get_time (HIST_ENTRY *entry)
                    250: Return the time stamp associated with the history entry @var{entry}.
1.1.1.2 ! misho     251: If the timestamp is missing or invalid, return 0.
1.1       misho     252: @end deftypefun
                    253: 
                    254: @deftypefun int history_total_bytes (void)
                    255: Return the number of bytes that the primary history entries are using.
                    256: This function returns the sum of the lengths of all the lines in the
                    257: history.
                    258: @end deftypefun
                    259: 
                    260: @node Moving Around the History List
                    261: @subsection Moving Around the History List
                    262: 
                    263: These functions allow the current index into the history list to be
                    264: set or changed.
                    265: 
                    266: @deftypefun int history_set_pos (int pos)
                    267: Set the current history offset to @var{pos}, an absolute index
                    268: into the list.
                    269: Returns 1 on success, 0 if @var{pos} is less than zero or greater
                    270: than the number of history entries.
                    271: @end deftypefun
                    272: 
                    273: @deftypefun {HIST_ENTRY *} previous_history (void)
                    274: Back up the current history offset to the previous history entry, and
                    275: return a pointer to that entry.  If there is no previous entry, return
                    276: a @code{NULL} pointer.
                    277: @end deftypefun
                    278: 
                    279: @deftypefun {HIST_ENTRY *} next_history (void)
1.1.1.2 ! misho     280: If the current history offset refers to a valid history entry,
        !           281: increment the current history offset.
        !           282: If the possibly-incremented history offset refers to a valid history
        !           283: entry, return a pointer to that entry;
        !           284: otherwise, return a @code{BNULL} pointer.
1.1       misho     285: @end deftypefun
                    286: 
                    287: @node Searching the History List
                    288: @subsection Searching the History List
                    289: @cindex History Searching
                    290: 
                    291: These functions allow searching of the history list for entries containing
                    292: a specific string.  Searching may be performed both forward and backward
                    293: from the current history position.  The search may be @dfn{anchored},
                    294: meaning that the string must match at the beginning of the history entry.
                    295: @cindex anchored search
                    296: 
                    297: @deftypefun int history_search (const char *string, int direction)
                    298: Search the history for @var{string}, starting at the current history offset.
                    299: If @var{direction} is less than 0, then the search is through
                    300: previous entries, otherwise through subsequent entries.
                    301: If @var{string} is found, then
                    302: the current history index is set to that history entry, and the value
                    303: returned is the offset in the line of the entry where
                    304: @var{string} was found.  Otherwise, nothing is changed, and a -1 is
                    305: returned.
                    306: @end deftypefun
                    307: 
                    308: @deftypefun int history_search_prefix (const char *string, int direction)
                    309: Search the history for @var{string}, starting at the current history
                    310: offset.  The search is anchored: matching lines must begin with
                    311: @var{string}.  If @var{direction} is less than 0, then the search is
                    312: through previous entries, otherwise through subsequent entries.
                    313: If @var{string} is found, then the
                    314: current history index is set to that entry, and the return value is 0. 
                    315: Otherwise, nothing is changed, and a -1 is returned. 
                    316: @end deftypefun
                    317: 
                    318: @deftypefun int history_search_pos (const char *string, int direction, int pos)
                    319: Search for @var{string} in the history list, starting at @var{pos}, an
                    320: absolute index into the list.  If @var{direction} is negative, the search
                    321: proceeds backward from @var{pos}, otherwise forward.  Returns the absolute
                    322: index of the history element where @var{string} was found, or -1 otherwise.
                    323: @end deftypefun
                    324: 
                    325: @node Managing the History File
                    326: @subsection Managing the History File
                    327: 
                    328: The History library can read the history from and write it to a file.
                    329: This section documents the functions for managing a history file.
                    330: 
                    331: @deftypefun int read_history (const char *filename)
                    332: Add the contents of @var{filename} to the history list, a line at a time.
                    333: If @var{filename} is @code{NULL}, then read from @file{~/.history}.
                    334: Returns 0 if successful, or @code{errno} if not.
                    335: @end deftypefun
                    336: 
                    337: @deftypefun int read_history_range (const char *filename, int from, int to)
                    338: Read a range of lines from @var{filename}, adding them to the history list.
                    339: Start reading at line @var{from} and end at @var{to}.
                    340: If @var{from} is zero, start at the beginning.  If @var{to} is less than
                    341: @var{from}, then read until the end of the file.  If @var{filename} is
                    342: @code{NULL}, then read from @file{~/.history}.  Returns 0 if successful,
                    343: or @code{errno} if not.
                    344: @end deftypefun
                    345: 
                    346: @deftypefun int write_history (const char *filename)
                    347: Write the current history to @var{filename}, overwriting @var{filename}
                    348: if necessary.
                    349: If @var{filename} is @code{NULL}, then write the history list to
                    350: @file{~/.history}.
                    351: Returns 0 on success, or @code{errno} on a read or write error.
                    352: @end deftypefun
                    353: 
                    354: @deftypefun int append_history (int nelements, const char *filename)
                    355: Append the last @var{nelements} of the history list to @var{filename}.
                    356: If @var{filename} is @code{NULL}, then append to @file{~/.history}.
                    357: Returns 0 on success, or @code{errno} on a read or write error.
                    358: @end deftypefun
                    359: 
                    360: @deftypefun int history_truncate_file (const char *filename, int nlines)
                    361: Truncate the history file @var{filename}, leaving only the last
                    362: @var{nlines} lines.
                    363: If @var{filename} is @code{NULL}, then @file{~/.history} is truncated.
                    364: Returns 0 on success, or @code{errno} on failure.
                    365: @end deftypefun
                    366: 
                    367: @node History Expansion
                    368: @subsection History Expansion
                    369: 
                    370: These functions implement history expansion.
                    371: 
                    372: @deftypefun int history_expand (char *string, char **output)
                    373: Expand @var{string}, placing the result into @var{output}, a pointer
                    374: to a string (@pxref{History Interaction}).  Returns:
                    375: @table @code
                    376: @item 0
                    377: If no expansions took place (or, if the only change in
                    378: the text was the removal of escape characters preceding the history expansion
                    379: character);
                    380: @item 1
                    381: if expansions did take place;
                    382: @item -1
                    383: if there was an error in expansion;
                    384: @item 2
                    385: if the returned line should be displayed, but not executed,
                    386: as with the @code{:p} modifier (@pxref{Modifiers}).
                    387: @end table
                    388: 
                    389: If an error occurred in expansion, then @var{output} contains a descriptive
                    390: error message.
                    391: @end deftypefun
                    392: 
                    393: @deftypefun {char *} get_history_event (const char *string, int *cindex, int qchar)
                    394: Returns the text of the history event beginning at @var{string} +
                    395: @var{*cindex}.  @var{*cindex} is modified to point to after the event
                    396: specifier.  At function entry, @var{cindex} points to the index into
                    397: @var{string} where the history event specification begins.  @var{qchar}
                    398: is a character that is allowed to end the event specification in addition
                    399: to the ``normal'' terminating characters.
                    400: @end deftypefun
                    401: 
                    402: @deftypefun {char **} history_tokenize (const char *string)
                    403: Return an array of tokens parsed out of @var{string}, much as the
                    404: shell might.  The tokens are split on the characters in the
                    405: @var{history_word_delimiters} variable,
1.1.1.2 ! misho     406: and shell quoting conventions are obeyed as described below.
1.1       misho     407: @end deftypefun
                    408: 
                    409: @deftypefun {char *} history_arg_extract (int first, int last, const char *string)
                    410: Extract a string segment consisting of the @var{first} through @var{last}
                    411: arguments present in @var{string}.  Arguments are split using
                    412: @code{history_tokenize}.
                    413: @end deftypefun
                    414: 
                    415: @node History Variables
                    416: @section History Variables
                    417: 
                    418: This section describes the externally-visible variables exported by
                    419: the @sc{gnu} History Library.
                    420: 
                    421: @deftypevar int history_base
                    422: The logical offset of the first entry in the history list.
                    423: @end deftypevar
                    424: 
                    425: @deftypevar int history_length
                    426: The number of entries currently stored in the history list.
                    427: @end deftypevar
                    428: 
                    429: @deftypevar int history_max_entries
                    430: The maximum number of history entries.  This must be changed using
                    431: @code{stifle_history()}.
                    432: @end deftypevar
                    433: 
                    434: @deftypevar int history_write_timestamps
                    435: If non-zero, timestamps are written to the history file, so they can be
                    436: preserved between sessions.  The default value is 0, meaning that
                    437: timestamps are not saved.
                    438: 
                    439: The current timestamp format uses the value of @var{history_comment_char}
                    440: to delimit timestamp entries in the history file.  If that variable does
                    441: not have a value (the default), timestamps will not be written.
                    442: @end deftypevar
                    443: 
                    444: @deftypevar char history_expansion_char
                    445: The character that introduces a history event.  The default is @samp{!}.
                    446: Setting this to 0 inhibits history expansion.
                    447: @end deftypevar
                    448: 
                    449: @deftypevar char history_subst_char
                    450: The character that invokes word substitution if found at the start of
                    451: a line.  The default is @samp{^}.
                    452: @end deftypevar
                    453: 
                    454: @deftypevar char history_comment_char
                    455: During tokenization, if this character is seen as the first character
                    456: of a word, then it and all subsequent characters up to a newline are
                    457: ignored, suppressing history expansion for the remainder of the line.
                    458: This is disabled by default.
                    459: @end deftypevar
                    460: 
                    461: @deftypevar {char *} history_word_delimiters
                    462: The characters that separate tokens for @code{history_tokenize()}.
                    463: The default value is @code{" \t\n()<>;&|"}.
                    464: @end deftypevar
                    465: 
                    466: @deftypevar {char *} history_search_delimiter_chars
                    467: The list of additional characters which can delimit a history search
                    468: string, in addition to space, TAB, @samp{:} and @samp{?} in the case of
                    469: a substring search.  The default is empty.
                    470: @end deftypevar
                    471: 
                    472: @deftypevar {char *} history_no_expand_chars
                    473: The list of characters which inhibit history expansion if found immediately
                    474: following @var{history_expansion_char}.  The default is space, tab, newline,
                    475: carriage return, and @samp{=}.
                    476: @end deftypevar
                    477: 
                    478: @deftypevar int history_quotes_inhibit_expansion
1.1.1.2 ! misho     479: If non-zero, the history expansion code implements shell-like quoting:
        !           480: single-quoted words are not scanned for the history expansion
        !           481: character or the history comment character, and double-quoted words may
        !           482: have history expansion performed, since single quotes are not special
        !           483: within double quotes.
        !           484: The default value is 0.
        !           485: @end deftypevar
        !           486: 
        !           487: @deftypevar int history_quoting_state
        !           488: An application may set this variable to indicate that the current line
        !           489: being expanded is subject to existing quoting. If set to @samp{'}, the
        !           490: history expansion function will assume that the line is single-quoted and
        !           491: inhibit expansion until it reads an unquoted closing single quote; if set
        !           492: to @samp{"}, history expansion will assume the line is double quoted until
        !           493: it reads an unquoted closing double quote. If set to zero, the default,
        !           494: the history expansion function will assume the line is not quoted and
        !           495: treat quote characters within the line as described above.
        !           496: This is only effective if @var{history_quotes_inhibit_expansion} is set.
1.1       misho     497: @end deftypevar
                    498: 
                    499: @deftypevar {rl_linebuf_func_t *} history_inhibit_expansion_function
                    500: This should be set to the address of a function that takes two arguments:
                    501: a @code{char *} (@var{string})
                    502: and an @code{int} index into that string (@var{i}).
                    503: It should return a non-zero value if the history expansion starting at
                    504: @var{string[i]} should not be performed; zero if the expansion should
                    505: be done.
                    506: It is intended for use by applications like Bash that use the history
                    507: expansion character for additional purposes.
                    508: By default, this variable is set to @code{NULL}.
                    509: @end deftypevar
                    510: 
                    511: @node History Programming Example
                    512: @section History Programming Example
                    513: 
                    514: The following program demonstrates simple use of the @sc{gnu} History Library.
                    515: 
                    516: @smallexample
                    517: #include <stdio.h>
                    518: #include <readline/history.h>
                    519: 
                    520: main (argc, argv)
                    521:      int argc;
                    522:      char **argv;
                    523: @{
                    524:   char line[1024], *t;
                    525:   int len, done = 0;
                    526: 
                    527:   line[0] = 0;
                    528: 
                    529:   using_history ();
                    530:   while (!done)
                    531:     @{
                    532:       printf ("history$ ");
                    533:       fflush (stdout);
                    534:       t = fgets (line, sizeof (line) - 1, stdin);
                    535:       if (t && *t)
                    536:         @{
                    537:           len = strlen (t);
                    538:           if (t[len - 1] == '\n')
                    539:             t[len - 1] = '\0';
                    540:         @}
                    541: 
                    542:       if (!t)
                    543:         strcpy (line, "quit");
                    544: 
                    545:       if (line[0])
                    546:         @{
                    547:           char *expansion;
                    548:           int result;
                    549: 
                    550:           result = history_expand (line, &expansion);
                    551:           if (result)
                    552:             fprintf (stderr, "%s\n", expansion);
                    553: 
                    554:           if (result < 0 || result == 2)
                    555:             @{
                    556:               free (expansion);
                    557:               continue;
                    558:             @}
                    559: 
                    560:           add_history (expansion);
                    561:           strncpy (line, expansion, sizeof (line) - 1);
                    562:           free (expansion);
                    563:         @}
                    564: 
                    565:       if (strcmp (line, "quit") == 0)
                    566:         done = 1;
                    567:       else if (strcmp (line, "save") == 0)
                    568:         write_history ("history_file");
                    569:       else if (strcmp (line, "read") == 0)
                    570:         read_history ("history_file");
                    571:       else if (strcmp (line, "list") == 0)
                    572:         @{
                    573:           register HIST_ENTRY **the_list;
                    574:           register int i;
                    575: 
                    576:           the_list = history_list ();
                    577:           if (the_list)
                    578:             for (i = 0; the_list[i]; i++)
                    579:               printf ("%d: %s\n", i + history_base, the_list[i]->line);
                    580:         @}
                    581:       else if (strncmp (line, "delete", 6) == 0)
                    582:         @{
                    583:           int which;
                    584:           if ((sscanf (line + 6, "%d", &which)) == 1)
                    585:             @{
                    586:               HIST_ENTRY *entry = remove_history (which);
                    587:               if (!entry)
                    588:                 fprintf (stderr, "No such entry %d\n", which);
                    589:               else
                    590:                 @{
                    591:                   free (entry->line);
                    592:                   free (entry);
                    593:                 @}
                    594:             @}
                    595:           else
                    596:             @{
                    597:               fprintf (stderr, "non-numeric arg given to `delete'\n");
                    598:             @}
                    599:         @}
                    600:     @}
                    601: @}
                    602: @end smallexample

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>