gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, master, updated. 1387c9a6046ba3a3e9ce834


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, master, updated. 1387c9a6046ba3a3e9ce8343daac42e1086efa6b
Date: Wed, 04 May 2011 20:40:02 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, master has been updated
       via  1387c9a6046ba3a3e9ce8343daac42e1086efa6b (commit)
      from  f2b825c82aa6b0b2eabed734244148206f3c01a5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=1387c9a6046ba3a3e9ce8343daac42e1086efa6b

commit 1387c9a6046ba3a3e9ce8343daac42e1086efa6b
Author: Arnold D. Robbins <address@hidden>
Date:   Wed May 4 23:39:43 2011 +0300

    Revamp array sorting.

diff --git a/ChangeLog b/ChangeLog
index d9a27fa..5c439df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Wed May  4 23:31:14 2011  Arnold D. Robbins  <address@hidden>
+
+       Move array sorting to using predefined strings, add value sorting
+       by type of assignment.
+
+       * array.c (sort_up_value_type, sort_down_value_type): New routines.
+       (asort_actual): Pass string value to assoc_list, not NODE *.
+       Make sure indices of new arrays have numeric value set also.
+       (sort_up_value_number): Don't break the tie based on string value.
+       (sort_selection): Removed.
+       (assoc_list): Third arg is string constant. Add name to table of
+       functions. Linear search it.
+       * awk.h (assoc_list): Fix declaration.
+       * debug.c (print_array): And use of assoc_list.
+       * eval.c (r_interpret): Ditto.
+
 Wed May  4 23:06:17 2011  John Haque      <address@hidden>
 
        * eval.c (setup_frame): Handle a Node_var in stack. Fixes
diff --git a/array.c b/array.c
index 380d4f3..b6e72c8 100644
--- a/array.c
+++ b/array.c
@@ -63,6 +63,8 @@ static int sort_up_value_string(const void *, const void *);
 static int sort_down_value_string(const void *, const void *);
 static int sort_up_value_number(const void *, const void *);
 static int sort_down_value_number(const void *, const void *);
+static int sort_up_value_type(const void *, const void *);
+static int sort_down_value_type(const void *, const void *);
 
 /* array_init --- check relevant environment variables */
 
@@ -1030,16 +1032,27 @@ static NODE *
 asort_actual(int nargs, SORT_CTXT ctxt)
 {
        NODE *array, *dest = NULL, *result;
-       NODE *r, *subs, *sort_str;
+       NODE *r, *subs, *s;
        NODE **list, **ptr;
 #define TSIZE  100     /* an arbitrary amount */
        static char buf[TSIZE+2];
        unsigned long num_elems, i;
+       const char *sort_str;
 
        if (nargs == 3)  /* 3rd optional arg */
-               sort_str = POP_STRING();
+               s = POP_STRING();
        else
-               sort_str = Nnull_string;        /* "" => default sorting */
+               s = Nnull_string;       /* "" => default sorting */
+
+       s = force_string(s);
+       sort_str = s->stptr;
+       if (s->stlen == 0) {            /* default sorting */
+               if (ctxt == ASORT)
+                       sort_str = "@val_type_asc";
+               else
+                       sort_str = "@ind_str_asc";
+       }
+
 
        if (nargs >= 2) {  /* 2nd optional arg */
                dest = POP_PARAM();
@@ -1081,7 +1094,7 @@ asort_actual(int nargs, SORT_CTXT ctxt)
 
        /* sorting happens inside assoc_list */
        list = assoc_list(array, sort_str, ctxt);
-       DEREF(sort_str);
+       DEREF(s);
 
        /*
         * Must not assoc_clear() the source array before constructing
@@ -1106,12 +1119,15 @@ asort_actual(int nargs, SORT_CTXT ctxt)
        for (i = 1, ptr = list; i <= num_elems; i++) {
                sprintf(buf, "%lu", i);
                subs->stlen = strlen(buf);
+               /* make number valid in case this array gets sorted later */
+               subs->numbr = i;
+               subs->flags |= NUMCUR;
                r = *ptr++;
                if (ctxt == ASORTI) {
-                       /* We want the indices of the source array as values
+                       /*
+                        * We want the indices of the source array as values
                         * of the 'result' array.
                         */
-
                        *assoc_lookup(result, subs, FALSE) =
                                        make_string(r->ahname_str, 
r->ahname_len);
                } else {
@@ -1367,15 +1383,7 @@ sort_up_value_number(const void *p1, const void *p2)
        else
                ret = (n1->numbr > n2->numbr);
 
-       if (ret != 0)
-               return ret;
-
-       /* break a tie using string comparison. First, make sure both
-        * n1 and n2 have string values.
-        */
-       (void) force_string(n1);
-       (void) force_string(n2);
-       return cmp_string(n1, n2);
+       return ret;
 }
 
 /* sort_down_value_number --- descending value number */
@@ -1386,6 +1394,67 @@ sort_down_value_number(const void *p1, const void *p2)
        return -sort_up_value_number(p1, p2);
 }
 
+/* sort_up_value_type --- qsort comparison function; ascending value type */
+
+static int
+sort_up_value_type(const void *p1, const void *p2)
+{
+       const NODE *t1, *t2;
+       NODE *n1, *n2;
+       int ret;
+
+       /* we're passed a pair of index (array subscript) nodes */
+       t1 = *(const NODE *const *) p1;
+       t2 = *(const NODE *const *) p2;
+
+       /* and we want to compare the element values they refer to */
+       n1 = t1->ahvalue;
+       n2 = t2->ahvalue;
+
+       /* 1. Arrays vs. scalar, scalar is less than array */
+       if (n1->type == Node_var_array) {
+               /* return 0 if n2 is a sub-array too, else return 1 */
+               return (n2->type != Node_var_array);
+       }
+       if (n2->type == Node_var_array) {
+               return -1;              /* n1 (scalar) < n2 (sub-array) */
+       }
+
+       /* two scalars */
+       /* 2. Resolve MAYBE_NUM, so that have only NUMBER or STRING */
+       if ((n1->flags & MAYBE_NUM) != 0)
+               (void) force_number(n1);
+       if ((n2->flags & MAYBE_NUM) != 0)
+               (void) force_number(n2);
+
+       if ((n1->flags & NUMBER) != 0 && (n2->flags & NUMBER) != 0) {
+               if (n1->numbr < n2->numbr)
+                       return -1;
+               else if (n1->numbr > n2->numbr)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       /* 3. All numbers are less than all strings. This is aribitrary. */
+       if ((n1->flags & NUMBER) != 0 && (n2->flags & STRING) != 0) {
+               return -1;
+       } else if ((n1->flags & STRING) != 0 && (n2->flags & NUMBER) != 0) {
+               return 1;
+       }
+
+       /* 4. Two strings */
+       return cmp_string(n1, n2);
+}
+
+/* sort_down_value_type --- descending value type */
+
+static int
+sort_down_value_type(const void *p1, const void *p2)
+{
+       return -sort_up_value_type(p1, p2);
+}
+
 /* sort_user_func --- user defined qsort comparison function */
 
 static int
@@ -1429,134 +1498,6 @@ sort_user_func(const void *p1, const void *p2)
        return (ret < 0.0) ? -1 : (ret > 0.0);
 }
 
-
-/*
- * sort_selection --- parse user-specified sort specification;
- * returns an index into sort_funcs table located in assoc_list().
- */
-
-static int
-sort_selection(NODE *sort_str, SORT_CTXT sort_ctxt)
-{
-       /* first 4 bits used to calculate index into sort_funcs table in 
assoc_list(),
-        * next 4 bits for grouping individual components. Note that "Unsorted"
-        * belongs to all the groups.
-        */
-
-       enum sort_bits {
-               Unrecognized = 0xFF,    /* not part of a sort phrase */
-               Unsorted     = 0xF8,
-               Ascending    = 0x40,
-               Descending   = 0x44,
-               by_Index     = 0x20,
-               by_Value     = 0x22,
-               as_String    = 0x10,
-               as_Number    = 0x11
-       };
-
-#define INDEX_MASK     0x0F
-#define GROUP_MASK     0xF0
-
-       /*
-        * The documented values are singular, but it's trivial to accept
-        * "index numbers" and "descending values" since we're using a
-        * prefix match.  Latin plural of index is the only complication.
-        */
-       static const struct sort_keys {
-               const char *const keyword;
-               const size_t keyword_len;
-               enum  sort_bits keybit;
-       } sorts[] = {
-               { "unsorted",   8, Unsorted },
-               { "ascending",  9, Ascending }, /* ascending vs descending */
-               { "descending", 10, Descending  },
-               { "indexes", 7, by_Index  },    /* by_Index vs by_Value */
-               { "indices", 7, by_Index  },    /* synonym for plural match */
-               { "values", 6,  by_Value  },
-               { "strings", 7, as_String },    /* as_String vs as_Number */
-               { "numbers", 7, as_Number },
-               { "numeric", 7, as_Number },    /* synonym; singular only */
-       };
-       static int num_keys = sizeof(sorts) / sizeof(sorts[0]);
-       int num_words, i;
-       char *word, *s;
-       size_t word_len;
-       enum sort_bits allparts, bval;
-
-       if (sort_str == NULL) {
-               assert(sort_ctxt == SORTED_IN);
-               return (Unsorted & INDEX_MASK);         /* no sorting */
-       }
-
-       (void) force_string(sort_str);
-       sort_str->stptr[sort_str->stlen] = '\0';        /* safety */
-
-       /* Initialize with the context-sensitive defaults; Note that group-bits 
aren't
-        * copied, doing so will prevent the user from explicitely specifying 
the defaults.
-        */
- 
-       if (sort_ctxt == ASORT)
-               allparts = (Ascending|by_Value|as_String) & INDEX_MASK;
-       else
-               allparts = (Ascending|by_Index|as_String) & INDEX_MASK;
-
-       num_words = 0;
-
-       for (s = sort_str->stptr; *s != '\0'; ) {
-               /* skip leading spaces */
-               while (*s == ' ')
-                       s++;
-               if (*s == '\0')
-                       break;
-               word = s;
-               /* find the end of the word */
-               while (*s && *s != ' ')
-                       s++;
-               word_len = (size_t) (s - word);
-
-               if (++num_words > 3)    /* too many words in phrase */
-                       return -1;
-
-               bval = Unrecognized;
-               for (i = 0; i < num_keys; i++) {
-                       if (word_len <= sorts[i].keyword_len
-                                     && strncasecmp(sorts[i].keyword, word, 
word_len) == 0) {
-                               bval = sorts[i].keybit;
-                               break;
-                       }
-               }
-                               
-               if (bval == Unrecognized         /* invalid word in phrase */
-                       ||      (sort_ctxt == ASORT
-                                       && (bval == by_Index || bval == 
Unsorted)
-                               )                        /* "index" used in 
phrase for asort etc. */
-                       ||      (sort_ctxt == ASORTI
-                                       && (bval == by_Value || bval == 
Unsorted)
-                               )                        /* "value" used in 
phrase for asorti etc. */
-                       ||      ((allparts & bval) & GROUP_MASK
-                               )                        /* invalid grouping of 
words e.g. "str num" */
-               )
-                       return -1;
-
-               allparts |= bval;
-       }
-
-       if (allparts == Unsorted) {
-               NODE *f;
-               /* user-defined function overrides default */
-
-               if ((f = lookup(sort_str->stptr)) != NULL && f->type == 
Node_func)
-                       return -1;
-       }
-
-       /* num_words <= 3 */
-       return (allparts & INDEX_MASK);
-
-#undef INDEX_MASK
-#undef GROUP_MASK
-}
-
-
 /* sort_force_index_number -- pre-process list items for sorting indices as 
numbers */
 
 static void
@@ -1569,7 +1510,7 @@ sort_force_index_number(NODE **list, size_t num_elems)
        for (i = 0; i < num_elems; i++) {
                r = list[i];
 
-               if ((r->flags & NUMIND) != 0)   /* once in a lifetime is more 
than enough */
+               if ((r->flags & NUMIND) != 0)   /* once in a lifetime is plenty 
*/
                        continue;
                temp_node.type = Node_val;
                temp_node.stptr = r->ahname_str;
@@ -1615,24 +1556,27 @@ sort_force_value_string(NODE **list, size_t num_elems)
 /* assoc_list -- construct, and optionally sort, a list of array elements */  
 
 NODE **
-assoc_list(NODE *array, NODE *sort_str, SORT_CTXT sort_ctxt)
+assoc_list(NODE *array, const char *sort_str, SORT_CTXT sort_ctxt)
 {
        typedef void (*qsort_prefunc)(NODE **, size_t);
        typedef int (*qsort_compfunc)(const void *, const void *);
 
        static const struct qsort_funcs {
+               const char *name;
                qsort_compfunc comp_func;
                qsort_prefunc pre_func;         /* pre-processing of list items 
*/
        } sort_funcs[] = {
-               { sort_up_index_string,         0                       },      
/* ascending index string */
-               { sort_up_index_number,         sort_force_index_number },      
/* ascending index number */
-               { sort_up_value_string,         sort_force_value_string },      
/* ascending value string */
-               { sort_up_value_number,         sort_force_value_number },      
/* ascending value number */
-               { sort_down_index_string,       0                       },      
/* descending index string */ 
-               { sort_down_index_number,       sort_force_index_number },      
/* descending index number */   
-               { sort_down_value_string,       sort_force_value_string },      
/* descending value string */ 
-               { sort_down_value_number,       sort_force_value_number },      
/* descending value number */
-               { 0,    0 }                                             /* 
unsorted */
+               { "@ind_str_asc",       sort_up_index_string,   0 },
+               { "@ind_num_asc",       sort_up_index_number,   
sort_force_index_number },
+               { "@val_str_asc",       sort_up_value_string,   
sort_force_value_string },
+               { "@val_num_asc",       sort_up_value_number,   
sort_force_value_number },
+               { "@ind_str_desc",      sort_down_index_string, 0 },
+               { "@ind_num_desc",      sort_down_index_number, 
sort_force_index_number },
+               { "@val_str_desc",      sort_down_value_string, 
sort_force_value_string },
+               { "@val_num_desc",      sort_down_value_number, 
sort_force_value_number },
+               { "@val_type_asc",      sort_up_value_type,     0 },
+               { "@val_type_desc",     sort_down_value_type,   0 },
+               { "@unsorted",          0,      0 },
        };
        NODE **list;
        NODE *r;
@@ -1646,30 +1590,32 @@ assoc_list(NODE *array, NODE *sort_str, SORT_CTXT 
sort_ctxt)
        num_elems = array->table_size;
        assert(num_elems > 0);
 
-       qi = sort_selection(sort_str, sort_ctxt);
+       for (qi = 0, j = sizeof(sort_funcs)/sizeof(sort_funcs[0]); qi < j; 
qi++) {
+               if (strcmp(sort_funcs[qi].name, sort_str) == 0)
+                       break;
+       }
 
-       if (qi >= 0) {
+       if (qi >= 0 && qi < j) {
                cmp_func = sort_funcs[qi].comp_func;
                pre_func = sort_funcs[qi].pre_func;
 
        } else {                /* unrecognized */
                NODE *f;
-               char *sp;       
+               const char *sp; 
 
                assert(sort_str != NULL);
 
-               (void) force_string(sort_str);
-               for (sp = sort_str->stptr; *sp != '\0'
-                               && ! isspace((unsigned char) *sp); sp++)
-                       ;
+               for (sp = sort_str; *sp != '\0'
+                    && ! isspace((unsigned char) *sp); sp++)
+                       continue;
 
                /* empty string or string with space(s) not valid as function 
name */
-               if (sp == sort_str->stptr || *sp != '\0')
-                       fatal(_("`%s' is invalid as a function name"), 
sort_str->stptr);
+               if (sp == sort_str || *sp != '\0')
+                       fatal(_("`%s' is invalid as a function name"), 
sort_str);
 
-               f = lookup(sort_str->stptr);
+               f = lookup(sort_str);
                if (f == NULL || f->type != Node_func)
-                       fatal(_("sort comparison function `%s' is not 
defined"), sort_str->stptr);
+                       fatal(_("sort comparison function `%s' is not 
defined"), sort_str);
 
                cmp_func = sort_user_func;
                /* pre_func is still NULL */
diff --git a/awk.h b/awk.h
index fb56748..a14f20a 100644
--- a/awk.h
+++ b/awk.h
@@ -1110,7 +1110,7 @@ typedef int (*Func_print)(FILE *, const char *, ...);
 
 /* array.c */
 typedef enum sort_context { SORTED_IN = 1, ASORT, ASORTI } SORT_CTXT;
-extern NODE **assoc_list(NODE *array, NODE *sort_str, SORT_CTXT sort_ctxt);
+extern NODE **assoc_list(NODE *array, const char *sort_str, SORT_CTXT 
sort_ctxt);
 extern NODE *get_array(NODE *symbol, int canfatal);
 extern char *array_vname(const NODE *symbol);
 extern char *make_aname(NODE *array, NODE *subs);
diff --git a/debug.c b/debug.c
index ee1b311..1543a46 100644
--- a/debug.c
+++ b/debug.c
@@ -1074,7 +1074,7 @@ print_array(volatile NODE *arr, char *arr_name)
        num_elems = arr->table_size;
 
        /* sort indices, sub_arrays are also sorted! */
-       list = assoc_list((NODE *) arr, Nnull_string, SORTED_IN);
+       list = assoc_list((NODE *) arr, "@unsorted", SORTED_IN);
 
        PUSH_BINDING(pager_quit_tag_stack, pager_quit_tag, 
pager_quit_tag_valid);
        if (setjmp(pager_quit_tag) == 0) {
diff --git a/doc/ChangeLog b/doc/ChangeLog
index d658137..2ac2cce 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@
+Wed May  4 23:39:09 2011  Arnold D. Robbins  <address@hidden>
+
+       * gawk.texi: Start at revamping array sorting doc. Still
+       needs work.
+
 Wed Apr 27 21:49:23 2011  Arnold D. Robbins  <address@hidden>
 
        * gawk.1: Minor edit.
diff --git a/doc/gawk.info b/doc/gawk.info
index f5f3413..e34309c 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -109,394 +109,437 @@ texts being (a) (see below), and with the Back-Cover 
Texts being (b)
 * GNU Free Documentation License:: The license for this Info file.
 * Index::                          Concept and Variable Index.
 
-* History::                        The history of `gawk' and
-                                   `awk'.
-* Names::                          What name to use to find `awk'.
-* This Manual::                    Using this Info file. Includes
-                                   sample input files that you can use.
-* Conventions::                    Typographical Conventions.
-* Manual History::                 Brief history of the GNU project and this
-                                   Info file.
-* How To Contribute::              Helping to save the world.
-* Acknowledgments::                Acknowledgments.
-* Running gawk::                   How to run `gawk' programs;
-                                   includes command-line syntax.
-* One-shot::                       Running a short throwaway `awk'
-                                   program.
-* Read Terminal::                  Using no input files (input from terminal
-                                   instead).
-* Long::                           Putting permanent `awk' programs in
-                                   files.
-* Executable Scripts::             Making self-contained `awk'
-                                   programs.
-* Comments::                       Adding documentation to `gawk'
-                                   programs.
-* Quoting::                        More discussion of shell quoting issues.
-* DOS Quoting::                    Quoting in Windows Batch Files.
-* Sample Data Files::              Sample data files for use in the
-                                   `awk' programs illustrated in this
-                                   Info file.
-* Very Simple::                    A very simple example.
-* Two Rules::                      A less simple one-line example using two
-                                   rules.
-* More Complex::                   A more complex example.
-* Statements/Lines::               Subdividing or combining statements into
-                                   lines.
-* Other Features::                 Other Features of `awk'.
-* When::                           When to use `gawk' and when to use
-                                   other things.
-* Command Line::                   How to run `awk'.
-* Options::                        Command-line options and their meanings.
-* Other Arguments::                Input file names and variable assignments.
-* Naming Standard Input::          How to specify standard input with other
-                                   files.
-* Environment Variables::          The environment variables `gawk'
-                                   uses.
-* AWKPATH Variable::               Searching directories for `awk'
-                                   programs.
-* Other Environment Variables::    The environment variables.
-* Exit Status::                    `gawk''s exit status.
-* Include Files::                  Including other files into your program.
-* Obsolete::                       Obsolete Options and/or features.
-* Undocumented::                   Undocumented Options and Features.
-* Regexp Usage::                   How to Use Regular Expressions.
-* Escape Sequences::               How to write nonprinting characters.
-* Regexp Operators::               Regular Expression Operators.
-* Bracket Expressions::            What can go between `[...]'.
-* GNU Regexp Operators::           Operators specific to GNU software.
-* Case-sensitivity::               How to do case-insensitive matching.
-* Leftmost Longest::               How much text matches.
-* Computed Regexps::               Using Dynamic Regexps.
-* Locales::                        How the locale affects things.
-* Records::                        Controlling how data is split into records.
-* Fields::                         An introduction to fields.
-* Nonconstant Fields::             Nonconstant Field Numbers.
-* Changing Fields::                Changing the Contents of a Field.
-* Field Separators::               The field separator and how to change it.
-* Default Field Splitting::        How fields are normally separated.
-* Regexp Field Splitting::         Using regexps as the field separator.
-* Single Character Fields::        Making each character a separate field.
-* Command Line Field Separator::   Setting `FS' from the command-line.
-* Field Splitting Summary::        Some final points and a summary table.
-* Constant Size::                  Reading constant width data.
-* Splitting By Content::           Defining Fields By Content
-* Multiple Line::                  Reading multi-line records.
-* Getline::                        Reading files under explicit program
-                                   control using the `getline' function.
-* Plain Getline::                  Using `getline' with no arguments.
-* Getline/Variable::               Using `getline' into a variable.
-* Getline/File::                   Using `getline' from a file.
-* Getline/Variable/File::          Using `getline' into a variable from a
-                                   file.
-* Getline/Pipe::                   Using `getline' from a pipe.
-* Getline/Variable/Pipe::          Using `getline' into a variable from a
-                                   pipe.
-* Getline/Coprocess::              Using `getline' from a coprocess.
-* Getline/Variable/Coprocess::     Using `getline' into a variable from a
-                                   coprocess.
-* Getline Notes::                  Important things to know about
-                                   `getline'.
-* Getline Summary::                Summary of `getline' Variants.
-* Command line directories::       What happens if you put a directory on the
-                                   command line.
-* Print::                          The `print' statement.
-* Print Examples::                 Simple examples of `print' statements.
-* Output Separators::              The output separators and how to change
-                                   them.
-* OFMT::                           Controlling Numeric Output With
-                                   `print'.
-* Printf::                         The `printf' statement.
-* Basic Printf::                   Syntax of the `printf' statement.
-* Control Letters::                Format-control letters.
-* Format Modifiers::               Format-specification modifiers.
-* Printf Examples::                Several examples.
-* Redirection::                    How to redirect output to multiple files
-                                   and pipes.
-* Special Files::                  File name interpretation in `gawk'.
-                                   `gawk' allows access to inherited
-                                   file descriptors.
-* Special FD::                     Special files for I/O.
-* Special Network::                Special files for network communications.
-* Special Caveats::                Things to watch out for.
-* Close Files And Pipes::          Closing Input and Output Files and Pipes.
-* Values::                         Constants, Variables, and Regular
-                                   Expressions.
-* Constants::                      String, numeric and regexp constants.
-* Scalar Constants::               Numeric and string constants.
-* Nondecimal-numbers::             What are octal and hex numbers.
-* Regexp Constants::               Regular Expression constants.
-* Using Constant Regexps::         When and how to use a regexp constant.
-* Variables::                      Variables give names to values for later
-                                   use.
-* Using Variables::                Using variables in your programs.
-* Assignment Options::             Setting variables on the command-line and a
-                                   summary of command-line syntax. This is an
-                                   advanced method of input.
-* Conversion::                     The conversion of strings to numbers and
-                                   vice versa.
-* All Operators::                  `gawk''s operators.
-* Arithmetic Ops::                 Arithmetic operations (`+', `-',
-                                   etc.)
-* Concatenation::                  Concatenating strings.
-* Assignment Ops::                 Changing the value of a variable or a
-                                   field.
-* Increment Ops::                  Incrementing the numeric value of a
-                                   variable.
-* Truth Values and Conditions::    Testing for true and false.
-* Truth Values::                   What is ``true'' and what is ``false''.
-* Typing and Comparison::          How variables acquire types and how this
-                                   affects comparison of numbers and strings
-                                   with `<', etc.
-* Variable Typing::                String type versus numeric type.
-* Comparison Operators::           The comparison operators.
-* POSIX String Comparison::        String comparison with POSIX rules.
-* Boolean Ops::                    Combining comparison expressions using
-                                   boolean operators `||' (``or''),
-                                   `&&' (``and'') and `!' (``not'').
-* Conditional Exp::                Conditional expressions select between two
-                                   subexpressions under control of a third
-                                   subexpression.
-* Function Calls::                 A function call is an expression.
-* Precedence::                     How various operators nest.
-* Pattern Overview::               What goes into a pattern.
-* Regexp Patterns::                Using regexps as patterns.
-* Expression Patterns::            Any expression can be used as a pattern.
-* Ranges::                         Pairs of patterns specify record ranges.
-* BEGIN/END::                      Specifying initialization and cleanup
-                                   rules.
-* Using BEGIN/END::                How and why to use BEGIN/END rules.
-* I/O And BEGIN/END::              I/O issues in BEGIN/END rules.
-* Empty::                          The empty pattern, which matches every
-                                   record.
-* BEGINFILE/ENDFILE::              Two special patterns for advanced control.
-* Using Shell Variables::          How to use shell variables with
-                                   `awk'.
-* Action Overview::                What goes into an action.
-* Statements::                     Describes the various control statements in
-                                   detail.
-* If Statement::                   Conditionally execute some `awk'
-                                   statements.
-* While Statement::                Loop until some condition is satisfied.
-* Do Statement::                   Do specified action while looping until
-                                   some condition is satisfied.
-* For Statement::                  Another looping statement, that provides
-                                   initialization and increment clauses.
-* Switch Statement::               Switch/case evaluation for conditional
-                                   execution of statements based on a value.
-* Break Statement::                Immediately exit the innermost enclosing
-                                   loop.
-* Continue Statement::             Skip to the end of the innermost enclosing
-                                   loop.
-* Next Statement::                 Stop processing the current input record.
-* Nextfile Statement::             Stop processing the current file.
-* Exit Statement::                 Stop execution of `awk'.
-* Built-in Variables::             Summarizes the built-in variables.
-* User-modified::                  Built-in variables that you change to
-                                   control `awk'.
-* Auto-set::                       Built-in variables where `awk'
-                                   gives you information.
-* ARGC and ARGV::                  Ways to use `ARGC' and `ARGV'.
-* Array Basics::                   The basics of arrays.
-* Array Intro::                    Introduction to Arrays
-* Reference to Elements::          How to examine one element of an array.
-* Assigning Elements::             How to change an element of an array.
-* Array Example::                  Basic Example of an Array
-* Scanning an Array::              A variation of the `for' statement. It
-                                   loops through the indices of an array's
-                                   existing elements.
-* Controlling Scanning::           Controlling the order in which arrays
-                                   are scanned.
-* Delete::                         The `delete' statement removes an
-                                   element from an array.
-* Numeric Array Subscripts::       How to use numbers as subscripts in
-                                   `awk'.
-* Uninitialized Subscripts::       Using Uninitialized variables as
-                                   subscripts.
-* Multi-dimensional::              Emulating multidimensional arrays in
-                                   `awk'.
-* Multi-scanning::                 Scanning multidimensional arrays.
-* Array Sorting::                  Sorting array values and indices.
-* Arrays of Arrays::               True multidimensional arrays.
-* Built-in::                       Summarizes the built-in functions.
-* Calling Built-in::               How to call built-in functions.
-* Numeric Functions::              Functions that work with numbers, including
-                                   `int()', `sin()' and
-                                   `rand()'.
-* String Functions::               Functions for string manipulation, such as
-                                   `split()', `match()' and
-                                   `sprintf()'.
-* Gory Details::                   More than you want to know about `\'
-                                   and `&' with `sub()',
-                                   `gsub()', and `gensub()'.
-* I/O Functions::                  Functions for files and shell commands.
-* Time Functions::                 Functions for dealing with timestamps.
-* Bitwise Functions::              Functions for bitwise operations.
-* Type Functions::                 Functions for type information.
-* I18N Functions::                 Functions for string translation.
-* User-defined::                   Describes User-defined functions in detail.
-* Definition Syntax::              How to write definitions and what they
-                                   mean.
-* Function Example::               An example function definition and what it
-                                   does.
-* Function Caveats::               Things to watch out for.
-* Calling A Function::             Don't use spaces.
-* Variable Scope::                 Controlling variable scope.
-* Pass By Value/Reference::        Passing parameters.
-* Return Statement::               Specifying the value a function returns.
-* Dynamic Typing::                 How variable types can change at runtime.
-* Indirect Calls::                 Choosing the function to call at runtime.
-* I18N and L10N::                  Internationalization and Localization.
-* Explaining gettext::             How GNU `gettext' works.
-* Programmer i18n::                Features for the programmer.
-* Translator i18n::                Features for the translator.
-* String Extraction::              Extracting marked strings.
-* Printf Ordering::                Rearranging `printf' arguments.
-* I18N Portability::               `awk'-level portability issues.
-* I18N Example::                   A simple i18n example.
-* Gawk I18N::                      `gawk' is also internationalized.
-* Nondecimal Data::                Allowing nondecimal input data.
-* Two-way I/O::                    Two-way communications with another
-                                   process.
-* TCP/IP Networking::              Using `gawk' for network
-                                   programming.
-* Profiling::                      Profiling your `awk' programs.
-* Library Names::                  How to best name private global variables
-                                   in library functions.
-* General Functions::              Functions that are of general use.
-* Strtonum Function::              A replacement for the built-in
-                                   `strtonum()' function.
-* Assert Function::                A function for assertions in `awk'
-                                   programs.
-* Round Function::                 A function for rounding if `sprintf()'
-                                   does not do it correctly.
-* Cliff Random Function::          The Cliff Random Number Generator.
-* Ordinal Functions::              Functions for using characters as numbers
-                                   and vice versa.
-* Join Function::                  A function to join an array into a string.
-* Gettimeofday Function::          A function to get formatted times.
-* Data File Management::           Functions for managing command-line data
-                                   files.
-* Filetrans Function::             A function for handling data file
-                                   transitions.
-* Rewind Function::                A function for rereading the current file.
-* File Checking::                  Checking that data files are readable.
-* Empty Files::                    Checking for zero-length files.
-* Ignoring Assigns::               Treating assignments as file names.
-* Getopt Function::                A function for processing command-line
-                                   arguments.
-* Passwd Functions::               Functions for getting user information.
-* Group Functions::                Functions for getting group information.
-* Running Examples::               How to run these examples.
-* Clones::                         Clones of common utilities.
-* Cut Program::                    The `cut' utility.
-* Egrep Program::                  The `egrep' utility.
-* Id Program::                     The `id' utility.
-* Split Program::                  The `split' utility.
-* Tee Program::                    The `tee' utility.
-* Uniq Program::                   The `uniq' utility.
-* Wc Program::                     The `wc' utility.
-* Miscellaneous Programs::         Some interesting `awk' programs.
-* Dupword Program::                Finding duplicated words in a document.
-* Alarm Program::                  An alarm clock.
-* Translate Program::              A program similar to the `tr'
-                                   utility.
-* Labels Program::                 Printing mailing labels.
-* Word Sorting::                   A program to produce a word usage count.
-* History Sorting::                Eliminating duplicate entries from a
-                                   history file.
-* Extract Program::                Pulling out programs from Texinfo source
-                                   files.
-* Simple Sed::                     A Simple Stream Editor.
-* Igawk Program::                  A wrapper for `awk' that includes
-                                   files.
-* Anagram Program::                Finding anagrams from a dictionary.
-* Signature Program::              People do amazing things with too much time
-                                   on their hands.
-* Debugging::                      Introduction to `dgawk'.
-* Debugging Concepts::             Debugging In General.
-* Debugging Terms::                Additional Debugging Concepts.
-* Awk Debugging::                  Awk Debugging.
-* Sample dgawk session::           Sample `dgawk' session.
-* dgawk invocation::               `dgawk' Invocation.
-* Finding The Bug::                Finding The Bug.
-* List of Debugger Commands::      Main `dgawk' Commands.
-* Breakpoint Control::             Control of breakpoints.
-* Dgawk Execution Control::        Control of execution.
-* Viewing And Changing Data::      Viewing and changing data.
-* Dgawk Stack::                    Dealing with the stack.
-* Dgawk Info::                     Obtaining information about the program and
-                                   the debugger state.
-* Miscellaneous Dgawk Commands::   Miscellaneous Commands.
-* Readline Support::               Readline Support.
-* Dgawk Limitations::              Limitations and future plans.
-* V7/SVR3.1::                      The major changes between V7 and System V
-                                   Release 3.1.
-* SVR4::                           Minor changes between System V Releases 3.1
-                                   and 4.
-* POSIX::                          New features from the POSIX standard.
-* BTL::                            New features from Brian Kernighan's
-                                   version of `awk'.
-* POSIX/GNU::                      The extensions in `gawk' not in
-                                   POSIX `awk'.
-* Contributors::                   The major contributors to `gawk'.
-* Common Extensions::              Common Extensions Summary.
-* Gawk Distribution::              What is in the `gawk' distribution.
-* Getting::                        How to get the distribution.
-* Extracting::                     How to extract the distribution.
-* Distribution contents::          What is in the distribution.
-* Unix Installation::              Installing `gawk' under various
-                                   versions of Unix.
-* Quick Installation::             Compiling `gawk' under Unix.
-* Additional Configuration Options:: Other compile-time options.
-* Configuration Philosophy::       How it's all supposed to work.
-* Non-Unix Installation::          Installation on Other Operating Systems.
-* PC Installation::                Installing and Compiling `gawk' on
-                                   MS-DOS and OS/2.
-* PC Binary Installation::         Installing a prepared distribution.
-* PC Compiling::                   Compiling `gawk' for MS-DOS,
-                                   Windows32, and OS/2.
-* PC Testing::                     Testing `gawk' on PC
-                                   Operating Systems.
-* PC Using::                       Running `gawk' on MS-DOS, Windows32
-                                   and OS/2.
-* Cygwin::                         Building and running `gawk' for
-                                   Cygwin.
-* MSYS::                           Using `gawk' In The MSYS
-                                   Environment.
-* VMS Installation::               Installing `gawk' on VMS.
-* VMS Compilation::                How to compile `gawk' under VMS.
-* VMS Installation Details::       How to install `gawk' under VMS.
-* VMS Running::                    How to run `gawk' under VMS.
-* VMS Old Gawk::                   An old version comes with some VMS systems.
-* Bugs::                           Reporting Problems and Bugs.
-* Other Versions::                 Other freely available `awk'
-                                   implementations.
-* Compatibility Mode::             How to disable certain `gawk'
-                                   extensions.
-* Additions::                      Making Additions To `gawk'.
-* Accessing The Source::           Accessing the Git repository.
-* Adding Code::                    Adding code to the main body of
-                                   `gawk'.
-* New Ports::                      Porting `gawk' to a new operating
-                                   system.
-* Dynamic Extensions::             Adding new built-in functions to
-                                   `gawk'.
-* Internals::                      A brief look at some `gawk'
-                                   internals.
-* Plugin License::                 A note about licensing.
-* Sample Library::                 A example of new functions.
-* Internal File Description::      What the new functions will do.
-* Internal File Ops::              The code for internal file operations.
-* Using Internal File Ops::        How to use an external extension.
-* Future Extensions::              New features that may be implemented one
-                                   day.
-* Basic High Level::               The high level view.
-* Basic Data Typing::              A very quick intro to data types.
-* Floating Point Issues::          Stuff to know about floating-point numbers.
-* String Conversion Precision::    The String Value Can Lie.
-* Unexpected Results::             Floating Point Numbers Are Not Abstract
-                                   Numbers.
-* POSIX Floating Point Problems::  Standards Versus Existing Practice.
+* History::                            The history of `gawk' and
+                                       `awk'.
+* Names::                              What name to use to find `awk'.
+* This Manual::                        Using this Info file. Includes
+                                       sample input files that you can use.
+* Conventions::                        Typographical Conventions.
+* Manual History::                     Brief history of the GNU project and
+                                       this Info file.
+* How To Contribute::                  Helping to save the world.
+* Acknowledgments::                    Acknowledgments.
+* Running gawk::                       How to run `gawk' programs;
+                                       includes command-line syntax.
+* One-shot::                           Running a short throwaway `awk'
+                                       program.
+* Read Terminal::                      Using no input files (input from
+                                       terminal instead).
+* Long::                               Putting permanent `awk'
+                                       programs in files.
+* Executable Scripts::                 Making self-contained `awk'
+                                       programs.
+* Comments::                           Adding documentation to `gawk'
+                                       programs.
+* Quoting::                            More discussion of shell quoting
+                                       issues.
+* DOS Quoting::                        Quoting in Windows Batch Files.
+* Sample Data Files::                  Sample data files for use in the
+                                       `awk' programs illustrated in
+                                       this Info file.
+* Very Simple::                        A very simple example.
+* Two Rules::                          A less simple one-line example using
+                                       two rules.
+* More Complex::                       A more complex example.
+* Statements/Lines::                   Subdividing or combining statements
+                                       into lines.
+* Other Features::                     Other Features of `awk'.
+* When::                               When to use `gawk' and when to
+                                       use other things.
+* Command Line::                       How to run `awk'.
+* Options::                            Command-line options and their
+                                       meanings.
+* Other Arguments::                    Input file names and variable
+                                       assignments.
+* Naming Standard Input::              How to specify standard input with
+                                       other files.
+* Environment Variables::              The environment variables
+                                       `gawk' uses.
+* AWKPATH Variable::                   Searching directories for `awk'
+                                       programs.
+* Other Environment Variables::        The environment variables.
+* Exit Status::                        `gawk''s exit status.
+* Include Files::                      Including other files into your
+                                       program.
+* Obsolete::                           Obsolete Options and/or features.
+* Undocumented::                       Undocumented Options and Features.
+* Regexp Usage::                       How to Use Regular Expressions.
+* Escape Sequences::                   How to write nonprinting characters.
+* Regexp Operators::                   Regular Expression Operators.
+* Bracket Expressions::                What can go between `[...]'.
+* GNU Regexp Operators::               Operators specific to GNU software.
+* Case-sensitivity::                   How to do case-insensitive matching.
+* Leftmost Longest::                   How much text matches.
+* Computed Regexps::                   Using Dynamic Regexps.
+* Locales::                            How the locale affects things.
+* Records::                            Controlling how data is split into
+                                       records.
+* Fields::                             An introduction to fields.
+* Nonconstant Fields::                 Nonconstant Field Numbers.
+* Changing Fields::                    Changing the Contents of a Field.
+* Field Separators::                   The field separator and how to change
+                                       it.
+* Default Field Splitting::            How fields are normally separated.
+* Regexp Field Splitting::             Using regexps as the field separator.
+* Single Character Fields::            Making each character a separate field.
+* Command Line Field Separator::       Setting `FS' from the
+                                       command-line.
+* Field Splitting Summary::            Some final points and a summary table.
+* Constant Size::                      Reading constant width data.
+* Splitting By Content::               Defining Fields By Content
+* Multiple Line::                      Reading multi-line records.
+* Getline::                            Reading files under explicit program
+                                       control using the `getline'
+                                       function.
+* Plain Getline::                      Using `getline' with no arguments.
+* Getline/Variable::                   Using `getline' into a variable.
+* Getline/File::                       Using `getline' from a file.
+* Getline/Variable/File::              Using `getline' into a variable
+                                       from a file.
+* Getline/Pipe::                       Using `getline' from a pipe.
+* Getline/Variable/Pipe::              Using `getline' into a variable
+                                       from a pipe.
+* Getline/Coprocess::                  Using `getline' from a coprocess.
+* Getline/Variable/Coprocess::         Using `getline' into a variable
+                                       from a coprocess.
+* Getline Notes::                      Important things to know about
+                                       `getline'.
+* Getline Summary::                    Summary of `getline' Variants.
+* Command line directories::           What happens if you put a directory on
+                                       the command line.
+* Print::                              The `print' statement.
+* Print Examples::                     Simple examples of `print'
+                                       statements.
+* Output Separators::                  The output separators and how to change
+                                       them.
+* OFMT::                               Controlling Numeric Output With
+                                       `print'.
+* Printf::                             The `printf' statement.
+* Basic Printf::                       Syntax of the `printf' statement.
+* Control Letters::                    Format-control letters.
+* Format Modifiers::                   Format-specification modifiers.
+* Printf Examples::                    Several examples.
+* Redirection::                        How to redirect output to multiple
+                                       files and pipes.
+* Special Files::                      File name interpretation in
+                                       `gawk'. `gawk' allows
+                                       access to inherited file descriptors.
+* Special FD::                         Special files for I/O.
+* Special Network::                    Special files for network
+                                       communications.
+* Special Caveats::                    Things to watch out for.
+* Close Files And Pipes::              Closing Input and Output Files and
+                                       Pipes.
+* Values::                             Constants, Variables, and Regular
+                                       Expressions.
+* Constants::                          String, numeric and regexp constants.
+* Scalar Constants::                   Numeric and string constants.
+* Nondecimal-numbers::                 What are octal and hex numbers.
+* Regexp Constants::                   Regular Expression constants.
+* Using Constant Regexps::             When and how to use a regexp constant.
+* Variables::                          Variables give names to values for
+                                       later use.
+* Using Variables::                    Using variables in your programs.
+* Assignment Options::                 Setting variables on the command-line
+                                       and a summary of command-line syntax.
+                                       This is an advanced method of input.
+* Conversion::                         The conversion of strings to numbers
+                                       and vice versa.
+* All Operators::                      `gawk''s operators.
+* Arithmetic Ops::                     Arithmetic operations (`+',
+                                       `-', etc.)
+* Concatenation::                      Concatenating strings.
+* Assignment Ops::                     Changing the value of a variable or a
+                                       field.
+* Increment Ops::                      Incrementing the numeric value of a
+                                       variable.
+* Truth Values and Conditions::        Testing for true and false.
+* Truth Values::                       What is ``true'' and what is ``false''.
+* Typing and Comparison::              How variables acquire types and how
+                                       this affects comparison of numbers and
+                                       strings with `<', etc.
+* Variable Typing::                    String type versus numeric type.
+* Comparison Operators::               The comparison operators.
+* POSIX String Comparison::            String comparison with POSIX rules.
+* Boolean Ops::                        Combining comparison expressions using
+                                       boolean operators `||' (``or''),
+                                       `&&' (``and'') and `!'
+                                       (``not'').
+* Conditional Exp::                    Conditional expressions select between
+                                       two subexpressions under control of a
+                                       third subexpression.
+* Function Calls::                     A function call is an expression.
+* Precedence::                         How various operators nest.
+* Pattern Overview::                   What goes into a pattern.
+* Regexp Patterns::                    Using regexps as patterns.
+* Expression Patterns::                Any expression can be used as a
+                                       pattern.
+* Ranges::                             Pairs of patterns specify record
+                                       ranges.
+* BEGIN/END::                          Specifying initialization and cleanup
+                                       rules.
+* Using BEGIN/END::                    How and why to use BEGIN/END rules.
+* I/O And BEGIN/END::                  I/O issues in BEGIN/END rules.
+* BEGINFILE/ENDFILE::                  Two special patterns for advanced
+                                       control.
+* Empty::                              The empty pattern, which matches every
+                                       record.
+* Using Shell Variables::              How to use shell variables with
+                                       `awk'.
+* Action Overview::                    What goes into an action.
+* Statements::                         Describes the various control
+                                       statements in detail.
+* If Statement::                       Conditionally execute some
+                                       `awk' statements.
+* While Statement::                    Loop until some condition is satisfied.
+* Do Statement::                       Do specified action while looping until
+                                       some condition is satisfied.
+* For Statement::                      Another looping statement, that
+                                       provides initialization and increment
+                                       clauses.
+* Switch Statement::                   Switch/case evaluation for conditional
+                                       execution of statements based on a
+                                       value.
+* Break Statement::                    Immediately exit the innermost
+                                       enclosing loop.
+* Continue Statement::                 Skip to the end of the innermost
+                                       enclosing loop.
+* Next Statement::                     Stop processing the current input
+                                       record.
+* Nextfile Statement::                 Stop processing the current file.
+* Exit Statement::                     Stop execution of `awk'.
+* Built-in Variables::                 Summarizes the built-in variables.
+* User-modified::                      Built-in variables that you change to
+                                       control `awk'.
+* Auto-set::                           Built-in variables where `awk'
+                                       gives you information.
+* ARGC and ARGV::                      Ways to use `ARGC' and
+                                       `ARGV'.
+* Array Basics::                       The basics of arrays.
+* Array Intro::                        Introduction to Arrays
+* Reference to Elements::              How to examine one element of an array.
+* Assigning Elements::                 How to change an element of an array.
+* Array Example::                      Basic Example of an Array
+* Scanning an Array::                  A variation of the `for'
+                                       statement. It loops through the indices
+                                       of an array's existing elements.
+* Delete::                             The `delete' statement removes an
+                                       element from an array.
+* Numeric Array Subscripts::           How to use numbers as subscripts in
+                                       `awk'.
+* Uninitialized Subscripts::           Using Uninitialized variables as
+                                       subscripts.
+* Multi-dimensional::                  Emulating multidimensional arrays in
+                                       `awk'.
+* Multi-scanning::                     Scanning multidimensional arrays.
+* Arrays of Arrays::                   True multidimensional arrays.
+* Built-in::                           Summarizes the built-in functions.
+* Calling Built-in::                   How to call built-in functions.
+* Numeric Functions::                  Functions that work with numbers,
+                                       including `int()', `sin()'
+                                       and `rand()'.
+* String Functions::                   Functions for string manipulation, such
+                                       as `split()', `match()' and
+                                       `sprintf()'.
+* Gory Details::                       More than you want to know about
+                                       `\' and `&' with
+                                       `sub()', `gsub()', and
+                                       `gensub()'.
+* I/O Functions::                      Functions for files and shell commands.
+* Time Functions::                     Functions for dealing with timestamps.
+* Bitwise Functions::                  Functions for bitwise operations.
+* Type Functions::                     Functions for type information.
+* I18N Functions::                     Functions for string translation.
+* User-defined::                       Describes User-defined functions in
+                                       detail.
+* Definition Syntax::                  How to write definitions and what they
+                                       mean.
+* Function Example::                   An example function definition and what
+                                       it does.
+* Function Caveats::                   Things to watch out for.
+* Calling A Function::                 Don't use spaces.
+* Variable Scope::                     Controlling variable scope.
+* Pass By Value/Reference::            Passing parameters.
+* Return Statement::                   Specifying the value a function
+                                       returns.
+* Dynamic Typing::                     How variable types can change at
+                                       runtime.
+* Indirect Calls::                     Choosing the function to call at
+                                       runtime.
+* I18N and L10N::                      Internationalization and Localization.
+* Explaining gettext::                 How GNU `gettext' works.
+* Programmer i18n::                    Features for the programmer.
+* Translator i18n::                    Features for the translator.
+* String Extraction::                  Extracting marked strings.
+* Printf Ordering::                    Rearranging `printf' arguments.
+* I18N Portability::                   `awk'-level portability issues.
+* I18N Example::                       A simple i18n example.
+* Gawk I18N::                          `gawk' is also
+                                       internationalized.
+* Nondecimal Data::                    Allowing nondecimal input data.
+* Array Sorting::                      Facilities for controlling array
+                                       traversal and sorting arrays.
+* Controlling Array Traversal::        How to use PROCINFO["sorted_in"].
+* Controlling Scanning With A Function:: Using a function to control scanning.
+* Controlling Scanning::               Controlling the order in which arrays
+                                       are scanned.
+* Array Sorting Functions::            How to use `asort()' and
+                                       `asorti()'.
+* Two-way I/O::                        Two-way communications with another
+                                       process.
+* TCP/IP Networking::                  Using `gawk' for network
+                                       programming.
+* Profiling::                          Profiling your `awk' programs.
+* Library Names::                      How to best name private global
+                                       variables in library functions.
+* General Functions::                  Functions that are of general use.
+* Strtonum Function::                  A replacement for the built-in
+                                       `strtonum()' function.
+* Assert Function::                    A function for assertions in
+                                       `awk' programs.
+* Round Function::                     A function for rounding if
+                                       `sprintf()' does not do it
+                                       correctly.
+* Cliff Random Function::              The Cliff Random Number Generator.
+* Ordinal Functions::                  Functions for using characters as
+                                       numbers and vice versa.
+* Join Function::                      A function to join an array into a
+                                       string.
+* Gettimeofday Function::              A function to get formatted times.
+* Data File Management::               Functions for managing command-line
+                                       data files.
+* Filetrans Function::                 A function for handling data file
+                                       transitions.
+* Rewind Function::                    A function for rereading the current
+                                       file.
+* File Checking::                      Checking that data files are readable.
+* Empty Files::                        Checking for zero-length files.
+* Ignoring Assigns::                   Treating assignments as file names.
+* Getopt Function::                    A function for processing command-line
+                                       arguments.
+* Passwd Functions::                   Functions for getting user information.
+* Group Functions::                    Functions for getting group
+                                       information.
+* Walking Arrays::                     A function to walk arrays of arrays.
+* Running Examples::                   How to run these examples.
+* Clones::                             Clones of common utilities.
+* Cut Program::                        The `cut' utility.
+* Egrep Program::                      The `egrep' utility.
+* Id Program::                         The `id' utility.
+* Split Program::                      The `split' utility.
+* Tee Program::                        The `tee' utility.
+* Uniq Program::                       The `uniq' utility.
+* Wc Program::                         The `wc' utility.
+* Miscellaneous Programs::             Some interesting `awk'
+                                       programs.
+* Dupword Program::                    Finding duplicated words in a document.
+* Alarm Program::                      An alarm clock.
+* Translate Program::                  A program similar to the `tr'
+                                       utility.
+* Labels Program::                     Printing mailing labels.
+* Word Sorting::                       A program to produce a word usage
+                                       count.
+* History Sorting::                    Eliminating duplicate entries from a
+                                       history file.
+* Extract Program::                    Pulling out programs from Texinfo
+                                       source files.
+* Simple Sed::                         A Simple Stream Editor.
+* Igawk Program::                      A wrapper for `awk' that
+                                       includes files.
+* Anagram Program::                    Finding anagrams from a dictionary.
+* Signature Program::                  People do amazing things with too much
+                                       time on their hands.
+* Debugging::                          Introduction to `dgawk'.
+* Debugging Concepts::                 Debugging In General.
+* Debugging Terms::                    Additional Debugging Concepts.
+* Awk Debugging::                      Awk Debugging.
+* Sample dgawk session::               Sample `dgawk' session.
+* dgawk invocation::                   `dgawk' Invocation.
+* Finding The Bug::                    Finding The Bug.
+* List of Debugger Commands::          Main `dgawk' Commands.
+* Breakpoint Control::                 Control of breakpoints.
+* Dgawk Execution Control::            Control of execution.
+* Viewing And Changing Data::          Viewing and changing data.
+* Dgawk Stack::                        Dealing with the stack.
+* Dgawk Info::                         Obtaining information about the program
+                                       and the debugger state.
+* Miscellaneous Dgawk Commands::       Miscellaneous Commands.
+* Readline Support::                   Readline Support.
+* Dgawk Limitations::                  Limitations and future plans.
+* V7/SVR3.1::                          The major changes between V7 and System
+                                       V Release 3.1.
+* SVR4::                               Minor changes between System V Releases
+                                       3.1 and 4.
+* POSIX::                              New features from the POSIX standard.
+* BTL::                                New features from Brian Kernighan's
+                                       version of `awk'.
+* POSIX/GNU::                          The extensions in `gawk' not in
+                                       POSIX `awk'.
+* Common Extensions::                  Common Extensions Summary.
+* Contributors::                       The major contributors to
+                                       `gawk'.
+* Gawk Distribution::                  What is in the `gawk'
+                                       distribution.
+* Getting::                            How to get the distribution.
+* Extracting::                         How to extract the distribution.
+* Distribution contents::              What is in the distribution.
+* Unix Installation::                  Installing `gawk' under various
+                                       versions of Unix.
+* Quick Installation::                 Compiling `gawk' under Unix.
+* Additional Configuration Options::   Other compile-time options.
+* Configuration Philosophy::           How it's all supposed to work.
+* Non-Unix Installation::              Installation on Other Operating
+                                       Systems.
+* PC Installation::                    Installing and Compiling `gawk'
+                                       on MS-DOS and OS/2.
+* PC Binary Installation::             Installing a prepared distribution.
+* PC Compiling::                       Compiling `gawk' for MS-DOS,
+                                       Windows32, and OS/2.
+* PC Testing::                         Testing `gawk' on PC systems.
+* PC Using::                           Running `gawk' on MS-DOS,
+                                       Windows32 and OS/2.
+* Cygwin::                             Building and running `gawk' for
+                                       Cygwin.
+* MSYS::                               Using `gawk' In The MSYS
+                                       Environment.
+* VMS Installation::                   Installing `gawk' on VMS.
+* VMS Compilation::                    How to compile `gawk' under
+                                       VMS.
+* VMS Installation Details::           How to install `gawk' under
+                                       VMS.
+* VMS Running::                        How to run `gawk' under VMS.
+* VMS Old Gawk::                       An old version comes with some VMS
+                                       systems.
+* Bugs::                               Reporting Problems and Bugs.
+* Other Versions::                     Other freely available `awk'
+                                       implementations.
+* Compatibility Mode::                 How to disable certain `gawk'
+                                       extensions.
+* Additions::                          Making Additions To `gawk'.
+* Accessing The Source::               Accessing the Git repository.
+* Adding Code::                        Adding code to the main body of
+                                       `gawk'.
+* New Ports::                          Porting `gawk' to a new
+                                       operating system.
+* Dynamic Extensions::                 Adding new built-in functions to
+                                       `gawk'.
+* Internals::                          A brief look at some `gawk'
+                                       internals.
+* Plugin License::                     A note about licensing.
+* Sample Library::                     A example of new functions.
+* Internal File Description::          What the new functions will do.
+* Internal File Ops::                  The code for internal file operations.
+* Using Internal File Ops::            How to use an external extension.
+* Future Extensions::                  New features that may be implemented
+                                       one day.
+* Basic High Level::                   The high level view.
+* Basic Data Typing::                  A very quick intro to data types.
+* Floating Point Issues::              Stuff to know about floating-point
+                                       numbers.
+* String Conversion Precision::        The String Value Can Lie.
+* Unexpected Results::                 Floating Point Numbers Are Not Abstract
+                                       Numbers.
+* POSIX Floating Point Problems::      Standards Versus Existing Practice.
 
                   To Miriam, for making me complete.
 
@@ -9638,7 +9681,6 @@ cannot have a variable and an array with the same name in 
the same
 * Uninitialized Subscripts::    Using Uninitialized variables as subscripts.
 * Multi-dimensional::           Emulating multidimensional arrays in
                                 `awk'.
-* Array Sorting::               Sorting array values and indices.
 * Arrays of Arrays::            True multidimensional arrays.
 
 
@@ -9896,12 +9938,7 @@ File: gawk.info,  Node: Scanning an Array,  Prev: Array 
Example,  Up: Array Basi
 8.1.5 Scanning All Elements of an Array
 ---------------------------------------
 
-* Menu:
-
-* Controlling Scanning::   Controlling the order in which arrays are scanned.
-* Controlling Scanning With A Function::  Using a function to control scanning.
-
-   In programs that use arrays, it is often necessary to use a loop that
+In programs that use arrays, it is often necessary to use a loop that
 executes once for each element of an array.  In other languages, where
 arrays are contiguous and indices are limited to positive integers,
 this is easy: all the valid indices can be found by counting from the
@@ -9951,256 +9988,14 @@ statements in the loop body; it is not predictable 
whether the `for'
 loop will reach them.  Similarly, changing VAR inside the loop may
 produce strange results.  It is best to avoid such things.
 
-
-File: gawk.info,  Node: Controlling Scanning,  Next: Controlling Scanning With 
A Function,  Up: Scanning an Array
-
-8.1.5.1 Controlling Array Scanning Order
-........................................
-
-As an extension, `gawk' makes it possible for you to loop over the
+   As an extension, `gawk' makes it possible for you to loop over the
 elements of an array in order, based on the value of
-`PROCINFO["sorted_in"]' (*note Auto-set::).  Several sorting options
-are available:
-
-`ascending index string'
-     Order by indices compared as strings; this is the most basic sort.
-     (Internally, array indices are always strings, so with `a[2*5] = 1'
-     the index is actually `"10"' rather than numeric 10.)
-
-`ascending index number'
-     Order by indices but force them to be treated as numbers in the
-     process.  Any index with non-numeric value will end up positioned
-     as if it were zero.
-
-`ascending value string'
-     Order by element values rather than by indices.  Scalar values are
-     compared as strings.  Subarrays, if present, come out last.
-
-`ascending value number'
-     Order by values but force scalar values to be treated as numbers
-     for the purpose of comparison.  If there are subarrays, those
-     appear at the end of the sorted list.
-
-`descending index string'
-     Reverse order from the most basic sort.
-
-`descending index number'
-     Numeric indices ordered from high to low.
-
-`descending value string'
-     Element values, treated as strings, ordered from high to low.
-     Subarrays, if present, come out first.
-
-`descending value number'
-     Element values, treated as numbers, ordered from high to low.
-     Subarrays, if present, come out first.
-
-`unsorted'
-     Array elements are processed in arbitrary order, the normal `awk'
-     behavior. You can also get the normal behavior by just deleting
-     the `"sorted_in"' item from the `PROCINFO' array, if it previously
-     had a value assigned to it.
-
-   The array traversal order is determined before the `for' loop starts
-to run. Changing `PROCINFO["sorted_in"]' in the loop body will not
-affect the loop.
-
-   Portions of the sort specification string may be truncated or
-omitted.  The default is `ascending' for direction, `index' for sort
-key type, and `string' for comparison mode.  This implies that one can
-simply assign the empty string, "", instead of "ascending index string"
-to `PROCINFO["sorted_in"]' for the same effect.
-
-   For example:
-
-     $ gawk 'BEGIN {
-     >    a[4] = 4
-     >    a[3] = 3
-     >    for (i in a)
-     >        print i, a[i]
-     > }'
-     -| 4 4
-     -| 3 3
-     $ gawk 'BEGIN {
-     >    PROCINFO["sorted_in"] = "asc index"
-     >    a[4] = 4
-     >    a[3] = 3
-     >    for (i in a)
-     >        print i, a[i]
-     > }'
-     -| 3 3
-     -| 4 4
-
-   When sorting an array by element values, if a value happens to be a
-subarray then it is considered to be greater than any string or numeric
-value, regardless of what the subarray itself contains, and all
-subarrays are treated as being equal to each other.  Their order
-relative to each other is determined by their index strings.
-
-
-File: gawk.info,  Node: Controlling Scanning With A Function,  Prev: 
Controlling Scanning,  Up: Scanning an Array
-
-8.1.5.2 Controlling Array Scanning Order With a User-defined Function
-.....................................................................
-
-The value of `PROCINFO["sorted_in"]' can also be a function name.  This
-lets you traverse an array based on any custom criterion.  The array
-elements are ordered according to the return value of this function.
-This comparison function should be defined with at least four arguments:
-
-     function comp_func(i1, v1, i2, v2)
-     {
-         COMPARE ELEMENTS 1 AND 2 IN SOME FASHION
-         RETURN < 0; 0; OR > 0
-     }
-
-   Here, I1 and I2 are the indices, and V1 and V2 are the corresponding
-values of the two elements being compared.  Either V1 or V2, or both,
-can be arrays if the array being traversed contains subarrays as
-values.  The three possible return values are interpreted this way:
-
-   * If the return value of `comp_func(i1, v1, i2, v2)' is less than
-     zero, index I1 comes before index I2 during loop traversal.
-
-   * If `comp_func(i1, v1, i2, v2)' returns zero, I1 and I2 come
-     together but the relative order with respect to each other is
-     undefined.
-
-   * If the return value of `comp_func(i1, v1, i2, v2)' is greater than
-     zero, I1 comes after I2.
-
-   The following comparison function can be used to scan an array in
-numerical order of the indices:
-
-     function cmp_num_idx(i1, v1, i2, v2)
-     {
-         # numerical index comparison, ascending order
-         return (i1 - i2)
-     }
-
-   This function traverses an array based on an order by element values
-rather than by indices:
-
-     function cmp_str_val(i1, v1, i2, v2)
-     {
-         # string value comparison, ascending order
-         v1 = v1 ""
-         v2 = v2 ""
-         if (v1 < v2)
-             return -1
-         return (v1 != v2)
-     }
-
-   Here is a comparison function to make all numbers, and numeric
-strings without any leading or trailing spaces, come out first during
-loop traversal:
-
-     function cmp_num_str_val(i1, v1, i2, v2,   n1, n2)
-     {
-         # numbers before string value comparison, ascending order
-         n1 = v1 + 0
-         n2 = v2 + 0
-         if (n1 == v1)
-             return (n2 == v2) ? (n1 - n2) : -1
-         else if (n2 == v2)
-             return 1
-         return (v1 < v2) ? -1 : (v1 != v2)
-     }
-
-   Consider sorting the entries of a GNU/Linux system password file
-according to login names.  The following program which sorts records by
-a specific field position can be used for this purpose:
-
-     # sort.awk --- simple program to sort by field position
-     # field position is specified by the global variable POS
-
-     function cmp_field(i1, v1, i2, v2)
-     {
-         # comparison by value, as string, and ascending order
-         return v1[POS] < v2[POS] ? -1 : (v1[POS] != v2[POS])
-     }
-
-     {
-         for (i = 1; i <= NF; i++)
-             a[NR][i] = $i
-     }
-
-     END {
-         PROCINFO["sorted_in"] = "cmp_field"
-         if (POS < 1 || POS > NF)
-             POS = 1
-         for (i in a) {
-             for (j = 1; j <= NF; j++)
-                 printf("%s%c", a[i][j], j < NF ? ":" : "")
-             print ""
-         }
-     }
-
-   The first field in each entry of the password file is the user's
-login name, and the fields are seperated by colons.  Running the
-program produces the following output:
-
-     $ gawk -vPOS=1 -F: -f sort.awk /etc/passwd
-     -| adm:x:3:4:adm:/var/adm:/sbin/nologin
-     -| apache:x:48:48:Apache:/var/www:/sbin/nologin
-     -| avahi:x:70:70:Avahi daemon:/:/sbin/nologin
-     ...
-
-   The comparison normally should always return the same value when
-given a specific pair of array elements as its arguments.  If
-inconsistent results are returned then the order is undefined.  This
-behavior is sometimes exploited to introduce random order in otherwise
-seemingly ordered data:
-
-     function cmp_randomize(i1, v1, i2, v2)
-     {
-         # random order
-         return (2 - 4 * rand())
-     }
-
-   As mentioned above, the order of the indices is arbitrary if two
-elements compare equal.  This is usually not a problem, but letting the
-tied elements come out in arbitrary order can be an issue, especially
-when comparing item values.  The partial ordering of the equal elements
-may change during the next loop traversal, if other elements are added
-or removed from the array.  One way to resolve ties when comparing
-elements with otherwise equal values is to include the indices in the
-comparison rules.  Note that doing this may make the loop traversal
-less efficient, so consider it only if necessary.  The following
-comparison functions force a deterministic order, and are based on the
-fact that the indices of two elements are never equal:
+`PROCINFO["sorted_in"]' (*note Auto-set::).  This is an advanced
+feature, so discussion of it is delayed until *note Controlling Array
+Traversal::.
 
-     function cmp_numeric(i1, v1, i2, v2)
-     {
-         # numerical value (and index) comparison, descending order
-         return (v1 != v2) ? (v2 - v1) : (i2 - i1)
-     }
-
-     function cmp_string(i1, v1, i2, v2)
-     {
-         # string value (and index) comparison, descending order
-         v1 = v1 i1
-         v2 = v2 i2
-         return (v1 > v2) ? -1 : (v1 != v2)
-     }
-
-   A custom comparison function can often simplify ordered loop
-traversal, and the the sky is really the limit when it comes to
-designing such a function.
-
-   When string comparisons are made during a sort, either for element
-values where one or both aren't numbers, or for element indices handled
-as strings, the value of `IGNORECASE' (*note Built-in Variables::)
-controls whether the comparisons treat corresponding uppercase and
-lowercase letters as equivalent or distinct.
-
-   All sorting based on `PROCINFO["sorted_in"]' is disabled in POSIX
-mode, since the `PROCINFO' array is not special in that case.
-
-   As a side note, sorting the array indices before traversing the
-array has been reported to add 15% to 20% overhead to the execution
-time of `awk' programs. For this reason, sorted array traversal is not
-the default.
+   In addition, `gawk' provides built-in functions for sorting arrays;
+see *note Array Sorting Functions::.
 
 
 File: gawk.info,  Node: Delete,  Next: Numeric Array Subscripts,  Prev: Array 
Basics,  Up: Arrays
@@ -10376,7 +10171,7 @@ string as a subscript if `--lint' is provided on the 
command line
 (*note Options::).
 
 
-File: gawk.info,  Node: Multi-dimensional,  Next: Array Sorting,  Prev: 
Uninitialized Subscripts,  Up: Arrays
+File: gawk.info,  Node: Multi-dimensional,  Next: Arrays of Arrays,  Prev: 
Uninitialized Subscripts,  Up: Arrays
 
 8.5 Multidimensional Arrays
 ===========================
@@ -10502,123 +10297,27 @@ The result is to set `separate[1]' to `"1"' and 
`separate[2]' to
 recovered.
 
 
-File: gawk.info,  Node: Array Sorting,  Next: Arrays of Arrays,  Prev: 
Multi-dimensional,  Up: Arrays
+File: gawk.info,  Node: Arrays of Arrays,  Prev: Multi-dimensional,  Up: Arrays
 
-8.6 Sorting Array Values and Indices with `gawk'
-================================================
+8.6 Arrays of Arrays
+====================
 
-The order in which an array is scanned with a `for (i in array)' loop
-is essentially arbitrary.  In most `awk' implementations, sorting an
-array requires writing a `sort' function.  While this can be
-educational for exploring different sorting algorithms, usually that's
-not the point of the program.  `gawk' provides the built-in `asort()'
-and `asorti()' functions (*note String Functions::) for sorting arrays.
-For example:
+`gawk' supports arrays of arrays. Elements of a subarray are referred
+to by their own indices enclosed in square brackets, just like the
+elements of the main array.  For example, the following creates a
+two-element subarray at index `1' of the main array `a':
 
-     POPULATE THE ARRAY data
-     n = asort(data)
-     for (i = 1; i <= n; i++)
-         DO SOMETHING WITH data[i]
+     a[1][1] = 1
+     a[1][2] = 2
 
-   After the call to `asort()', the array `data' is indexed from 1 to
-some number N, the total number of elements in `data'.  (This count is
-`asort()''s return value.)  `data[1]' <= `data[2]' <= `data[3]', and so
-on.  The array elements are compared as strings.
+   This simulates a true two-dimensional array. Each subarray element
+can contain another subarray as a value, which in turn can hold other
+arrays as well. In this way, you can create arrays of three or more
+dimensions.  The indices can be any `awk' expression, including scalars
+separated by commas (that is, a regular `awk' simulated
+multidimensional subscript). So the following is valid in `gawk':
 
-   An important side effect of calling `asort()' is that _the array's
-original indices are irrevocably lost_.  As this isn't always
-desirable, `asort()' accepts a second argument:
-
-     POPULATE THE ARRAY source
-     n = asort(source, dest)
-     for (i = 1; i <= n; i++)
-         DO SOMETHING WITH dest[i]
-
-   In this case, `gawk' copies the `source' array into the `dest' array
-and then sorts `dest', destroying its indices.  However, the `source'
-array is not affected.
-
-   `asort()' and `asorti()' accept a third string argument to control
-the comparison rule for the array elements, and the direction of the
-sorted results.  The valid comparison modes are `string' and `number',
-and the direction can be either `ascending' or `descending'.  Either
-mode or direction, or both, can be omitted in which case the defaults,
-`string' or `ascending' is assumed for the comparison mode and the
-direction, respectively.  Seperate comparison mode from direction with
-a single space, and they can appear in any order.  To compare the
-elements as numbers, and to reverse the elements of the `dest' array,
-the call to asort in the above example can be replaced with:
-
-     asort(source, dest, "descending number")
-
-   The third argument to `asort()' can also be a user-defined function
-name which is used to order the array elements before constructing the
-result array.  *Note Scanning an Array::, for more information.
-
-   Often, what's needed is to sort on the values of the _indices_
-instead of the values of the elements.  To do that, use the `asorti()'
-function.  The interface is identical to that of `asort()', except that
-the index values are used for sorting, and become the values of the
-result array:
-
-     { source[$0] = some_func($0) }
-
-     END {
-         n = asorti(source, dest)
-         for (i = 1; i <= n; i++) {
-             Work with sorted indices directly:
-             DO SOMETHING WITH dest[i]
-             ...
-             Access original array via sorted indices:
-             DO SOMETHING WITH source[dest[i]]
-         }
-     }
-
-   Sorting the array by replacing the indices provides maximal
-flexibility.  To traverse the elements in decreasing order, use a loop
-that goes from N down to 1, either over the elements or over the
-indices.  This is an alternative to specifying `descending' for the
-sorting order using the optional third argument.
-
-   Copying array indices and elements isn't expensive in terms of
-memory.  Internally, `gawk' maintains "reference counts" to data.  For
-example, when `asort()' copies the first array to the second one, there
-is only one copy of the original array elements' data, even though both
-arrays use the values.
-
-   Because `IGNORECASE' affects string comparisons, the value of
-`IGNORECASE' also affects sorting for both `asort()' and `asorti()'.
-Note also that the locale's sorting order does _not_ come into play;
-comparisons are based on character values only.(1) Caveat Emptor.
-
-   ---------- Footnotes ----------
-
-   (1) This is true because locale-based comparison occurs only when in
-POSIX compatibility mode, and since `asort()' and `asorti()' are `gawk'
-extensions, they are not available in that case.
-
-
-File: gawk.info,  Node: Arrays of Arrays,  Prev: Array Sorting,  Up: Arrays
-
-8.7 Arrays of Arrays
-====================
-
-`gawk' supports arrays of arrays. Elements of a subarray are referred
-to by their own indices enclosed in square brackets, just like the
-elements of the main array.  For example, the following creates a
-two-element subarray at index `1' of the main array `a':
-
-     a[1][1] = 1
-     a[1][2] = 2
-
-   This simulates a true two-dimensional array. Each subarray element
-can contain another subarray as a value, which in turn can hold other
-arrays as well. In this way, you can create arrays of three or more
-dimensions.  The indices can be any `awk' expression, including scalars
-separated by commas (that is, a regular `awk' simulated
-multidimensional subscript). So the following is valid in `gawk':
-
-     a[1][3][1, "name"] = "barney"
+     a[1][3][1, "name"] = "barney"
 
    Each subarray and the main array can be of different length. In
 fact, the elements of an array or its subarray do not all have to have
@@ -10972,8 +10671,8 @@ pound sign (`#'):
      `IGNORECASE' affects the sorting.  The third argument can also be
      a user-defined function name in which case the value returned by
      the function is used to order the array elements before
-     constructing the result array.  *Note Scanning an Array::, for
-     more information.
+     constructing the result array.  *Note Array Sorting Functions::,
+     for more information.
 
      For example, if the contents of `a' are as follows:
 
@@ -10998,8 +10697,8 @@ pound sign (`#'):
           asort(a, a, "descending")
 
      The `asort()' function is described in more detail in *note Array
-     Sorting::.  `asort()' is a `gawk' extension; it is not available
-     in compatibility mode (*note Options::).
+     Sorting Functions::.  `asort()' is a `gawk' extension; it is not
+     available in compatibility mode (*note Options::).
 
 `asorti(SOURCE [, DEST [, HOW  ] ]) #'
      Return the number of elements in the array SOURCE.  It works
@@ -11007,8 +10706,8 @@ pound sign (`#'):
      of the values. (Here too, `IGNORECASE' affects the sorting.)
 
      The `asorti()' function is described in more detail in *note Array
-     Sorting::.  `asorti()' is a `gawk' extension; it is not available
-     in compatibility mode (*note Options::).
+     Sorting Functions::.  `asorti()' is a `gawk' extension; it is not
+     available in compatibility mode (*note Options::).
 
 `gensub(REGEXP, REPLACEMENT, HOW [, TARGET]) #'
      Search the target string TARGET for matches of the regular
@@ -13578,169 +13277,581 @@ source:
          print "Pardon me, Zaphod who?"
      }
 
-Run `gawk --gen-pot' to create the `.pot' file:
+Run `gawk --gen-pot' to create the `.pot' file:
+
+     $ gawk --gen-pot -f guide.awk > guide.pot
+
+This produces:
+
+     #: guide.awk:4
+     msgid "Don't Panic"
+     msgstr ""
+
+     #: guide.awk:5
+     msgid "The Answer Is"
+     msgstr ""
+
+   This original portable object template file is saved and reused for
+each language into which the application is translated.  The `msgid' is
+the original string and the `msgstr' is the translation.
+
+     NOTE: Strings not marked with a leading underscore do not appear
+     in the `guide.pot' file.
+
+   Next, the messages must be translated.  Here is a translation to a
+hypothetical dialect of English, called "Mellow":(1)
+
+     $ cp guide.pot guide-mellow.po
+     ADD TRANSLATIONS TO guide-mellow.po ...
+
+Following are the translations:
+
+     #: guide.awk:4
+     msgid "Don't Panic"
+     msgstr "Hey man, relax!"
+
+     #: guide.awk:5
+     msgid "The Answer Is"
+     msgstr "Like, the scoop is"
+
+   The next step is to make the directory to hold the binary message
+object file and then to create the `guide.mo' file.  The directory
+layout shown here is standard for GNU `gettext' on GNU/Linux systems.
+Other versions of `gettext' may use a different layout:
+
+     $ mkdir en_US en_US/LC_MESSAGES
+
+   The `msgfmt' utility does the conversion from human-readable `.po'
+file to machine-readable `.mo' file.  By default, `msgfmt' creates a
+file named `messages'.  This file must be renamed and placed in the
+proper directory so that `gawk' can find it:
+
+     $ msgfmt guide-mellow.po
+     $ mv messages en_US/LC_MESSAGES/guide.mo
+
+   Finally, we run the program to test it:
+
+     $ gawk -f guide.awk
+     -| Hey man, relax!
+     -| Like, the scoop is 42
+     -| Pardon me, Zaphod who?
+
+   If the three replacement functions for `dcgettext()', `dcngettext()'
+and `bindtextdomain()' (*note I18N Portability::) are in a file named
+`libintl.awk', then we can run `guide.awk' unchanged as follows:
+
+     $ gawk --posix -f guide.awk -f libintl.awk
+     -| Don't Panic
+     -| The Answer Is 42
+     -| Pardon me, Zaphod who?
+
+   ---------- Footnotes ----------
+
+   (1) Perhaps it would be better if it were called "Hippy." Ah, well.
+
+
+File: gawk.info,  Node: Gawk I18N,  Prev: I18N Example,  Up: 
Internationalization
+
+10.6 `gawk' Can Speak Your Language
+===================================
+
+`gawk' itself has been internationalized using the GNU `gettext'
+package.  (GNU `gettext' is described in complete detail in *note (GNU
+`gettext' utilities)Top:: gettext, GNU gettext tools.)  As of this
+writing, the latest version of GNU `gettext' is version 0.18.1
+(ftp://ftp.gnu.org/gnu/gettext/gettext-0.18.1.tar.gz).
+
+   If a translation of `gawk''s messages exists, then `gawk' produces
+usage messages, warnings, and fatal errors in the local language.
+
+
+File: gawk.info,  Node: Advanced Features,  Next: Library Functions,  Prev: 
Internationalization,  Up: Top
+
+11 Advanced Features of `gawk'
+******************************
+
+     Write documentation as if whoever reads it is a violent psychopath
+     who knows where you live.
+     Steve English, as quoted by Peter Langston
+
+   This major node discusses advanced features in `gawk'.  It's a bit
+of a "grab bag" of items that are otherwise unrelated to each other.
+First, a command-line option allows `gawk' to recognize nondecimal
+numbers in input data, not just in `awk' programs.  Then, `gawk''s
+special features for sorting arrays are presented.  Next, two-way I/O,
+discussed briefly in earlier parts of this Info file, is described in
+full detail, along with the basics of TCP/IP networking.  Finally,
+`gawk' can "profile" an `awk' program, making it possible to tune it
+for performance.
+
+   *note Dynamic Extensions::, discusses the ability to dynamically add
+new built-in functions to `gawk'.  As this feature is still immature
+and likely to change, its description is relegated to an appendix.
+
+* Menu:
+
+* Nondecimal Data::             Allowing nondecimal input data.
+* Array Sorting::               Facilities for controlling array traversal and
+                                sorting arrays.
+* Two-way I/O::                 Two-way communications with another process.
+* TCP/IP Networking::           Using `gawk' for network programming.
+* Profiling::                   Profiling your `awk' programs.
+
+
+File: gawk.info,  Node: Nondecimal Data,  Next: Array Sorting,  Up: Advanced 
Features
+
+11.1 Allowing Nondecimal Input Data
+===================================
+
+If you run `gawk' with the `--non-decimal-data' option, you can have
+nondecimal constants in your input data:
+
+     $ echo 0123 123 0x123 |
+     > gawk --non-decimal-data '{ printf "%d, %d, %d\n",
+     >                                         $1, $2, $3 }'
+     -| 83, 123, 291
+
+   For this feature to work, write your program so that `gawk' treats
+your data as numeric:
+
+     $ echo 0123 123 0x123 | gawk '{ print $1, $2, $3 }'
+     -| 0123 123 0x123
+
+The `print' statement treats its expressions as strings.  Although the
+fields can act as numbers when necessary, they are still strings, so
+`print' does not try to treat them numerically.  You may need to add
+zero to a field to force it to be treated as a number.  For example:
+
+     $ echo 0123 123 0x123 | gawk --non-decimal-data '
+     > { print $1, $2, $3
+     >   print $1 + 0, $2 + 0, $3 + 0 }'
+     -| 0123 123 0x123
+     -| 83 123 291
+
+   Because it is common to have decimal data with leading zeros, and
+because using this facility could lead to surprising results, the
+default is to leave it disabled.  If you want it, you must explicitly
+request it.
+
+     CAUTION: _Use of this option is not recommended._ It can break old
+     programs very badly.  Instead, use the `strtonum()' function to
+     convert your data (*note Nondecimal-numbers::).  This makes your
+     programs easier to write and easier to read, and leads to less
+     surprising results.
+
+
+File: gawk.info,  Node: Array Sorting,  Next: Two-way I/O,  Prev: Nondecimal 
Data,  Up: Advanced Features
+
+11.2 Controlling Array Traversal and Array Sorting
+==================================================
+
+`gawk' lets you control the order in which `for (i in array)' loops
+will traverse an array.
+
+   In addition, two built-in functions, `asort()' and `asorti()', let
+you sort arrays based on the array values and indices, respectively.
+These two functions also provide control over the sorting criteria used
+to order the elements during sorting.
+
+* Menu:
+
+* Controlling Array Traversal:: How to use PROCINFO["sorted_in"].
+* Array Sorting Functions::     How to use `asort()' and `asorti()'.
+
+
+File: gawk.info,  Node: Controlling Array Traversal,  Next: Array Sorting 
Functions,  Up: Array Sorting
+
+11.2.1 Controlling Array Traversal
+----------------------------------
+
+By default, the order in which a `for (i in array)' loop will scan an
+array is not defined; it is generally based upon the internal
+implementation of arrays inside `awk'.
+
+   Often, though, it is desirable to be able to loop over the elements
+in a particular order that you, the programmer, choose.  `gawk' lets
+you do this; this node describes how.
+
+* Menu:
+
+* Controlling Scanning With A Function:: Using a function to control scanning.
+* Controlling Scanning::                 Controlling the order in which arrays
+                                         are scanned.
+
+
+File: gawk.info,  Node: Controlling Scanning With A Function,  Next: 
Controlling Scanning,  Up: Controlling Array Traversal
+
+11.2.1.1 Controlling Array Scanning Order With a User-defined Function
+......................................................................
+
+The value of `PROCINFO["sorted_in"]' can be a function name.  This lets
+you traverse an array based on any custom criterion.  The array
+elements are ordered according to the return value of this function.
+This comparison function should be defined with at least four arguments:
+
+     function comp_func(i1, v1, i2, v2)
+     {
+         COMPARE ELEMENTS 1 AND 2 IN SOME FASHION
+         RETURN < 0; 0; OR > 0
+     }
+
+   Here, I1 and I2 are the indices, and V1 and V2 are the corresponding
+values of the two elements being compared.  Either V1 or V2, or both,
+can be arrays if the array being traversed contains subarrays as
+values.  The three possible return values are interpreted this way:
+
+   * If the return value of `comp_func(i1, v1, i2, v2)' is less than
+     zero, index I1 comes before index I2 during loop traversal.
+
+   * If `comp_func(i1, v1, i2, v2)' returns zero, I1 and I2 come
+     together but the relative order with respect to each other is
+     undefined.
+
+   * If the return value of `comp_func(i1, v1, i2, v2)' is greater than
+     zero, I1 comes after I2.
+
+   The following comparison function can be used to scan an array in
+numerical order of the indices:
+
+     function cmp_num_idx(i1, v1, i2, v2)
+     {
+         # numerical index comparison, ascending order
+         return (i1 - i2)
+     }
+
+   This function traverses an array based on the string order of the
+element values rather than by indices:
+
+     function cmp_str_val(i1, v1, i2, v2)
+     {
+         # string value comparison, ascending order
+         v1 = v1 ""
+         v2 = v2 ""
+         if (v1 < v2)
+             return -1
+         return (v1 != v2)
+     }
+
+   Here is a comparison function to make all numbers, and numeric
+strings without any leading or trailing spaces, come out first during
+loop traversal:
+
+     function cmp_num_str_val(i1, v1, i2, v2,   n1, n2)
+     {
+         # numbers before string value comparison, ascending order
+         n1 = v1 + 0
+         n2 = v2 + 0
+         if (n1 == v1)
+             return (n2 == v2) ? (n1 - n2) : -1
+         else if (n2 == v2)
+             return 1
+         return (v1 < v2) ? -1 : (v1 != v2)
+     }
+
+   *FIXME*: Put in a fuller example here of some data and show the
+different results when traversing.
+
+   Consider sorting the entries of a GNU/Linux system password file
+according to login names.  The following program which sorts records by
+a specific field position can be used for this purpose:
+
+     # sort.awk --- simple program to sort by field position
+     # field position is specified by the global variable POS
+
+     function cmp_field(i1, v1, i2, v2)
+     {
+         # comparison by value, as string, and ascending order
+         return v1[POS] < v2[POS] ? -1 : (v1[POS] != v2[POS])
+     }
+
+     {
+         for (i = 1; i <= NF; i++)
+             a[NR][i] = $i
+     }
+
+     END {
+         PROCINFO["sorted_in"] = "cmp_field"
+         if (POS < 1 || POS > NF)
+             POS = 1
+         for (i in a) {
+             for (j = 1; j <= NF; j++)
+                 printf("%s%c", a[i][j], j < NF ? ":" : "")
+             print ""
+         }
+     }
+
+   The first field in each entry of the password file is the user's
+login name, and the fields are seperated by colons.  Each record
+defines a subarray, which each field as an element in the subarray.
+Running the program produces the following output:
+
+     $ gawk -vPOS=1 -F: -f sort.awk /etc/passwd
+     -| adm:x:3:4:adm:/var/adm:/sbin/nologin
+     -| apache:x:48:48:Apache:/var/www:/sbin/nologin
+     -| avahi:x:70:70:Avahi daemon:/:/sbin/nologin
+     ...
+
+   The comparison normally should always return the same value when
+given a specific pair of array elements as its arguments.  If
+inconsistent results are returned then the order is undefined.  This
+behavior is sometimes exploited to introduce random order in otherwise
+seemingly ordered data:
+
+     function cmp_randomize(i1, v1, i2, v2)
+     {
+         # random order
+         return (2 - 4 * rand())
+     }
+
+   As mentioned above, the order of the indices is arbitrary if two
+elements compare equal.  This is usually not a problem, but letting the
+tied elements come out in arbitrary order can be an issue, especially
+when comparing item values.  The partial ordering of the equal elements
+may change during the next loop traversal, if other elements are added
+or removed from the array.  One way to resolve ties when comparing
+elements with otherwise equal values is to include the indices in the
+comparison rules.  Note that doing this may make the loop traversal
+less efficient, so consider it only if necessary.  The following
+comparison functions force a deterministic order, and are based on the
+fact that the indices of two elements are never equal:
+
+     function cmp_numeric(i1, v1, i2, v2)
+     {
+         # numerical value (and index) comparison, descending order
+         return (v1 != v2) ? (v2 - v1) : (i2 - i1)
+     }
+
+     function cmp_string(i1, v1, i2, v2)
+     {
+         # string value (and index) comparison, descending order
+         v1 = v1 i1
+         v2 = v2 i2
+         return (v1 > v2) ? -1 : (v1 != v2)
+     }
+
+   A custom comparison function can often simplify ordered loop
+traversal, and the the sky is really the limit when it comes to
+designing such a function.
+
+   When string comparisons are made during a sort, either for element
+values where one or both aren't numbers, or for element indices handled
+as strings, the value of `IGNORECASE' (*note Built-in Variables::)
+controls whether the comparisons treat corresponding uppercase and
+lowercase letters as equivalent or distinct.
 
-     $ gawk --gen-pot -f guide.awk > guide.pot
+   Another point to keep in mind is that in the case of subarrays the
+element values can themselves be arrays; a production comparison
+function should use the `isarray()' function (*note Type Functions::),
+to check for this, and choose a defined sorting order for subarrays.
 
-This produces:
+   All sorting based on `PROCINFO["sorted_in"]' is disabled in POSIX
+mode, since the `PROCINFO' array is not special in that case.
 
-     #: guide.awk:4
-     msgid "Don't Panic"
-     msgstr ""
+   As a side note, sorting the array indices before traversing the
+array has been reported to add 15% to 20% overhead to the execution
+time of `awk' programs. For this reason, sorted array traversal is not
+the default.
 
-     #: guide.awk:5
-     msgid "The Answer Is"
-     msgstr ""
+
+File: gawk.info,  Node: Controlling Scanning,  Prev: Controlling Scanning With 
A Function,  Up: Controlling Array Traversal
 
-   This original portable object template file is saved and reused for
-each language into which the application is translated.  The `msgid' is
-the original string and the `msgstr' is the translation.
+11.2.1.2 Controlling Array Scanning Order
+.........................................
 
-     NOTE: Strings not marked with a leading underscore do not appear
-     in the `guide.pot' file.
+As described in *note Controlling Scanning With A Function::, you can
+provide the name of a function as the value of `PROCINFO["sorted_in"]'
+to specify custom sorting criteria.
 
-   Next, the messages must be translated.  Here is a translation to a
-hypothetical dialect of English, called "Mellow":(1)
+   Often, though, you may wish to do something simple, such as "sort
+based on comparing the indices in ascending order," or "sort based on
+comparing the values in descending order."  Having to write a simple
+comparison function for this purpose for use in all of your programs
+becomes tedious.  For the most likely simple cases `gawk' provides the
+option of supplying special names that do the requested sorting for you.
+You can think of them as "predefined" sorting functions, if you like,
+although the names purposely include characters that are not valid in
+real `awk' function names.
 
-     $ cp guide.pot guide-mellow.po
-     ADD TRANSLATIONS TO guide-mellow.po ...
+   The following special values are available:
 
-Following are the translations:
+`"@ind_str_asc"'
+     Order by indices compared as strings; this is the most basic sort.
+     (Internally, array indices are always strings, so with `a[2*5] = 1'
+     the index is actually `"10"' rather than numeric 10.)
 
-     #: guide.awk:4
-     msgid "Don't Panic"
-     msgstr "Hey man, relax!"
+`"@ind_num_asc"'
+     Order by indices but force them to be treated as numbers in the
+     process.  Any index with non-numeric value will end up positioned
+     as if it were zero.
 
-     #: guide.awk:5
-     msgid "The Answer Is"
-     msgstr "Like, the scoop is"
+`"@val_type_asc"'
+     Order by element values rather than indices.  Ordering is by the
+     type assigned to the element (*note Typing and Comparison::).  All
+     numeric values come before all string values, which in turn come
+     before all subarrays.
 
-   The next step is to make the directory to hold the binary message
-object file and then to create the `guide.mo' file.  The directory
-layout shown here is standard for GNU `gettext' on GNU/Linux systems.
-Other versions of `gettext' may use a different layout:
+`"@val_str_asc"'
+     Order by element values rather than by indices.  Scalar values are
+     compared as strings.  Subarrays, if present, come out last.
 
-     $ mkdir en_US en_US/LC_MESSAGES
+`"@val_num_asc"'
+     Order by values but force scalar values to be treated as numbers
+     for the purpose of comparison.  If there are subarrays, those
+     appear at the end of the sorted list.
 
-   The `msgfmt' utility does the conversion from human-readable `.po'
-file to machine-readable `.mo' file.  By default, `msgfmt' creates a
-file named `messages'.  This file must be renamed and placed in the
-proper directory so that `gawk' can find it:
+`"@ind_str_desc"'
+     Reverse order from the most basic sort.
 
-     $ msgfmt guide-mellow.po
-     $ mv messages en_US/LC_MESSAGES/guide.mo
+`"@ind_num_desc"'
+     Numeric indices ordered from high to low.
 
-   Finally, we run the program to test it:
+`"@val_type_desc"'
+     Element values, based on type, in descending order.
 
-     $ gawk -f guide.awk
-     -| Hey man, relax!
-     -| Like, the scoop is 42
-     -| Pardon me, Zaphod who?
+`"@val_str_desc"'
+     Element values, treated as strings, ordered from high to low.
+     Subarrays, if present, come out first.
 
-   If the three replacement functions for `dcgettext()', `dcngettext()'
-and `bindtextdomain()' (*note I18N Portability::) are in a file named
-`libintl.awk', then we can run `guide.awk' unchanged as follows:
+`"@val_num_desc"'
+     Element values, treated as numbers, ordered from high to low.
+     Subarrays, if present, come out first.
 
-     $ gawk --posix -f guide.awk -f libintl.awk
-     -| Don't Panic
-     -| The Answer Is 42
-     -| Pardon me, Zaphod who?
+`"@unsorted"'
+     Array elements are processed in arbitrary order, which is the
+     normal `awk' behavior. You can also get the normal behavior by just
+     deleting the `"sorted_in"' element from the `PROCINFO' array, if
+     it previously had a value assigned to it.
 
-   ---------- Footnotes ----------
+   The array traversal order is determined before the `for' loop starts
+to run. Changing `PROCINFO["sorted_in"]' in the loop body will not
+affect the loop.
 
-   (1) Perhaps it would be better if it were called "Hippy." Ah, well.
+   For example:
 
-
-File: gawk.info,  Node: Gawk I18N,  Prev: I18N Example,  Up: 
Internationalization
+     $ gawk 'BEGIN {
+     >    a[4] = 4
+     >    a[3] = 3
+     >    for (i in a)
+     >        print i, a[i]
+     > }'
+     -| 4 4
+     -| 3 3
+     $ gawk 'BEGIN {
+     >    PROCINFO["sorted_in"] = "@str_ind_asc"
+     >    a[4] = 4
+     >    a[3] = 3
+     >    for (i in a)
+     >        print i, a[i]
+     > }'
+     -| 3 3
+     -| 4 4
 
-10.6 `gawk' Can Speak Your Language
-===================================
+   When sorting an array by element values, if a value happens to be a
+subarray then it is considered to be greater than any string or numeric
+value, regardless of what the subarray itself contains, and all
+subarrays are treated as being equal to each other.  Their order
+relative to each other is determined by their index strings.
 
-`gawk' itself has been internationalized using the GNU `gettext'
-package.  (GNU `gettext' is described in complete detail in *note (GNU
-`gettext' utilities)Top:: gettext, GNU gettext tools.)  As of this
-writing, the latest version of GNU `gettext' is version 0.18.1
-(ftp://ftp.gnu.org/gnu/gettext/gettext-0.18.1.tar.gz).
+
+File: gawk.info,  Node: Array Sorting Functions,  Prev: Controlling Array 
Traversal,  Up: Array Sorting
 
-   If a translation of `gawk''s messages exists, then `gawk' produces
-usage messages, warnings, and fatal errors in the local language.
+11.2.2 Sorting Array Values and Indices with `gawk'
+---------------------------------------------------
 
-
-File: gawk.info,  Node: Advanced Features,  Next: Library Functions,  Prev: 
Internationalization,  Up: Top
+The order in which an array is scanned with a `for (i in array)' loop
+is essentially arbitrary.  In most `awk' implementations, sorting an
+array requires writing a `sort' function.  While this can be
+educational for exploring different sorting algorithms, usually that's
+not the point of the program.  `gawk' provides the built-in `asort()'
+and `asorti()' functions (*note String Functions::) for sorting arrays.
+For example:
 
-11 Advanced Features of `gawk'
-******************************
+     POPULATE THE ARRAY data
+     n = asort(data)
+     for (i = 1; i <= n; i++)
+         DO SOMETHING WITH data[i]
 
-     Write documentation as if whoever reads it is a violent psychopath
-     who knows where you live.
-     Steve English, as quoted by Peter Langston
+   After the call to `asort()', the array `data' is indexed from 1 to
+some number N, the total number of elements in `data'.  (This count is
+`asort()''s return value.)  `data[1]' <= `data[2]' <= `data[3]', and so
+on.  The array elements are compared as strings.
 
-   This major node discusses advanced features in `gawk'.  It's a bit
-of a "grab bag" of items that are otherwise unrelated to each other.
-First, a command-line option allows `gawk' to recognize nondecimal
-numbers in input data, not just in `awk' programs.  Next, two-way I/O,
-discussed briefly in earlier parts of this Info file, is described in
-full detail, along with the basics of TCP/IP networking.  Finally,
-`gawk' can "profile" an `awk' program, making it possible to tune it
-for performance.
+   An important side effect of calling `asort()' is that _the array's
+original indices are irrevocably lost_.  As this isn't always
+desirable, `asort()' accepts a second argument:
 
-   *note Dynamic Extensions::, discusses the ability to dynamically add
-new built-in functions to `gawk'.  As this feature is still immature
-and likely to change, its description is relegated to an appendix.
+     POPULATE THE ARRAY source
+     n = asort(source, dest)
+     for (i = 1; i <= n; i++)
+         DO SOMETHING WITH dest[i]
 
-* Menu:
+   In this case, `gawk' copies the `source' array into the `dest' array
+and then sorts `dest', destroying its indices.  However, the `source'
+array is not affected.
 
-* Nondecimal Data::             Allowing nondecimal input data.
-* Two-way I/O::                 Two-way communications with another process.
-* TCP/IP Networking::           Using `gawk' for network programming.
-* Profiling::                   Profiling your `awk' programs.
+   `asort()' and `asorti()' accept a third string argument to control
+the comparison rule for the array elements, and the direction of the
+sorted results.  The valid comparison modes are `string' and `number',
+and the direction can be either `ascending' or `descending'.  Either
+mode or direction, or both, can be omitted in which case the defaults,
+`string' or `ascending' is assumed for the comparison mode and the
+direction, respectively.  Seperate comparison mode from direction with
+a single space, and they can appear in any order.  To compare the
+elements as numbers, and to reverse the elements of the `dest' array,
+the call to asort in the above example can be replaced with:
 
-
-File: gawk.info,  Node: Nondecimal Data,  Next: Two-way I/O,  Up: Advanced 
Features
+     asort(source, dest, "descending number")
 
-11.1 Allowing Nondecimal Input Data
-===================================
+   The third argument to `asort()' can also be a user-defined function
+name which is used to order the array elements before constructing the
+result array.  *Note Scanning an Array::, for more information.
 
-If you run `gawk' with the `--non-decimal-data' option, you can have
-nondecimal constants in your input data:
+   Often, what's needed is to sort on the values of the _indices_
+instead of the values of the elements.  To do that, use the `asorti()'
+function.  The interface is identical to that of `asort()', except that
+the index values are used for sorting, and become the values of the
+result array:
 
-     $ echo 0123 123 0x123 |
-     > gawk --non-decimal-data '{ printf "%d, %d, %d\n",
-     >                                         $1, $2, $3 }'
-     -| 83, 123, 291
+     { source[$0] = some_func($0) }
 
-   For this feature to work, write your program so that `gawk' treats
-your data as numeric:
+     END {
+         n = asorti(source, dest)
+         for (i = 1; i <= n; i++) {
+             Work with sorted indices directly:
+             DO SOMETHING WITH dest[i]
+             ...
+             Access original array via sorted indices:
+             DO SOMETHING WITH source[dest[i]]
+         }
+     }
 
-     $ echo 0123 123 0x123 | gawk '{ print $1, $2, $3 }'
-     -| 0123 123 0x123
+   Sorting the array by replacing the indices provides maximal
+flexibility.  To traverse the elements in decreasing order, use a loop
+that goes from N down to 1, either over the elements or over the
+indices.  This is an alternative to specifying `descending' for the
+sorting order using the optional third argument.
 
-The `print' statement treats its expressions as strings.  Although the
-fields can act as numbers when necessary, they are still strings, so
-`print' does not try to treat them numerically.  You may need to add
-zero to a field to force it to be treated as a number.  For example:
+   Copying array indices and elements isn't expensive in terms of
+memory.  Internally, `gawk' maintains "reference counts" to data.  For
+example, when `asort()' copies the first array to the second one, there
+is only one copy of the original array elements' data, even though both
+arrays use the values.
 
-     $ echo 0123 123 0x123 | gawk --non-decimal-data '
-     > { print $1, $2, $3
-     >   print $1 + 0, $2 + 0, $3 + 0 }'
-     -| 0123 123 0x123
-     -| 83 123 291
+   Because `IGNORECASE' affects string comparisons, the value of
+`IGNORECASE' also affects sorting for both `asort()' and `asorti()'.
+Note also that the locale's sorting order does _not_ come into play;
+comparisons are based on character values only.(1) Caveat Emptor.
 
-   Because it is common to have decimal data with leading zeros, and
-because using this facility could lead to surprising results, the
-default is to leave it disabled.  If you want it, you must explicitly
-request it.
+   ---------- Footnotes ----------
 
-     CAUTION: _Use of this option is not recommended._ It can break old
-     programs very badly.  Instead, use the `strtonum()' function to
-     convert your data (*note Nondecimal-numbers::).  This makes your
-     programs easier to write and easier to read, and leads to less
-     surprising results.
+   (1) This is true because locale-based comparison occurs only when in
+POSIX compatibility mode, and since `asort()' and `asorti()' are `gawk'
+extensions, they are not available in that case.
 
 
-File: gawk.info,  Node: Two-way I/O,  Next: TCP/IP Networking,  Prev: 
Nondecimal Data,  Up: Advanced Features
+File: gawk.info,  Node: Two-way I/O,  Next: TCP/IP Networking,  Prev: Array 
Sorting,  Up: Advanced Features
 
-11.2 Two-Way Communications with Another Process
+11.3 Two-Way Communications with Another Process
 ================================================
 
      From: address@hidden (Mike Brennan)
@@ -13875,7 +13986,7 @@ regular pipes.
 
 File: gawk.info,  Node: TCP/IP Networking,  Next: Profiling,  Prev: Two-way 
I/O,  Up: Advanced Features
 
-11.3 Using `gawk' for Network Programming
+11.4 Using `gawk' for Network Programming
 =========================================
 
      `EMISTERED':
@@ -13952,7 +14063,7 @@ examples.
 
 File: gawk.info,  Node: Profiling,  Prev: TCP/IP Networking,  Up: Advanced 
Features
 
-11.4 Profiling Your `awk' Programs
+11.5 Profiling Your `awk' Programs
 ==================================
 
 You may produce execution traces of your `awk' programs.  This is done
@@ -19603,8 +19714,8 @@ you can find more information.
 * SVR4::                        Minor changes between System V Releases 3.1
                                 and 4.
 * POSIX::                       New features from the POSIX standard.
-* BTL::                         New features from Brian Kernighan's
-                                version of `awk'.
+* BTL::                         New features from Brian Kernighan's version of
+                                `awk'.
 * POSIX/GNU::                   The extensions in `gawk' not in POSIX
                                 `awk'.
 * Common Extensions::           Common Extensions Summary.
@@ -19916,6 +20027,8 @@ the current version of `gawk'.
 
         - Tandem (non-POSIX)
 
+        - Prestandard VAX C compiler for VAX/VMS
+
 
 
 
@@ -19991,9 +20104,9 @@ Info file, in approximate chronological order:
      documentation.
 
    * Michal Jaegermann provided the port to Atari systems and its
-     documentation.  He continues to provide portability checking with
-     DEC Alpha systems, and has done a lot of work to make sure `gawk'
-     works on non-32-bit systems.
+     documentation.  (This port is no longer supported.)  He continues
+     to provide portability checking with DEC Alpha systems, and has
+     done a lot of work to make sure `gawk' works on non-32-bit systems.
 
    * Fred Fish provided the port to Amiga systems and its documentation.
      (With Fred's sad passing, this is no longer supported.)
@@ -24696,11 +24809,11 @@ Index
 * arrays, elements, assigning:           Assigning Elements.  (line   6)
 * arrays, elements, deleting:            Delete.              (line   6)
 * arrays, elements, installing:          Internals.           (line  79)
-* arrays, elements, order of:            Scanning an Array.   (line  53)
+* arrays, elements, order of:            Scanning an Array.   (line  48)
 * arrays, elements, referencing:         Reference to Elements.
                                                               (line   6)
 * arrays, elements, retrieving number of: String Functions.   (line  29)
-* arrays, for statement and:             Scanning an Array.   (line  25)
+* arrays, for statement and:             Scanning an Array.   (line  20)
 * arrays, IGNORECASE variable and:       Array Intro.         (line  92)
 * arrays, indexing:                      Array Intro.         (line  50)
 * arrays, merging into strings:          Join Function.       (line   6)
@@ -24708,8 +24821,10 @@ Index
 * arrays, multidimensional, scanning:    Multi-scanning.      (line  11)
 * arrays, names of:                      Arrays.              (line  18)
 * arrays, scanning:                      Scanning an Array.   (line   6)
-* arrays, sorting:                       Array Sorting.       (line   6)
-* arrays, sorting, IGNORECASE variable and: Array Sorting.    (line  85)
+* arrays, sorting:                       Array Sorting Functions.
+                                                              (line   6)
+* arrays, sorting, IGNORECASE variable and: Array Sorting Functions.
+                                                              (line  85)
 * arrays, sparse:                        Array Intro.         (line  71)
 * arrays, subscripts:                    Numeric Array Subscripts.
                                                               (line   6)
@@ -24719,9 +24834,11 @@ Index
                                                               (line  55)
 * ASCII <1>:                             Glossary.            (line 137)
 * ASCII:                                 Ordinal Functions.   (line  45)
-* asort() function (gawk) <1>:           String Functions.    (line  29)
-* asort() function (gawk):               Array Sorting.       (line   6)
-* asort() function (gawk), arrays, sorting: Array Sorting.    (line   6)
+* asort() function (gawk) <1>:           Array Sorting Functions.
+                                                              (line   6)
+* asort() function (gawk):               String Functions.    (line  29)
+* asort() function (gawk), arrays, sorting: Array Sorting Functions.
+                                                              (line   6)
 * asorti() function (gawk):              String Functions.    (line  77)
 * assert() function (C library):         Assert Function.     (line   6)
 * assert() user-defined function:        Assert Function.     (line  28)
@@ -25386,7 +25503,7 @@ Index
                                                               (line   6)
 * elements in arrays, assigning:         Assigning Elements.  (line   6)
 * elements in arrays, deleting:          Delete.              (line   6)
-* elements in arrays, order of:          Scanning an Array.   (line  53)
+* elements in arrays, order of:          Scanning an Array.   (line  48)
 * elements in arrays, scanning:          Scanning an Array.   (line   6)
 * email address for bug reports, address@hidden: Bugs.      (line  30)
 * EMISTERED:                             TCP/IP Networking.   (line   6)
@@ -25617,7 +25734,7 @@ Index
 * FNR variable:                          Records.             (line   6)
 * FNR variable, changing:                Auto-set.            (line 229)
 * for statement:                         For Statement.       (line   6)
-* for statement, in arrays:              Scanning an Array.   (line  25)
+* for statement, in arrays:              Scanning an Array.   (line  20)
 * force_number() internal function:      Internals.           (line  27)
 * force_string() internal function:      Internals.           (line  32)
 * force_wstring() internal function:     Internals.           (line  37)
@@ -25751,8 +25868,9 @@ Index
 * gawk, function arguments and:          Calling Built-in.    (line  16)
 * gawk, functions, adding:               Dynamic Extensions.  (line  10)
 * gawk, hexadecimal numbers and:         Nondecimal-numbers.  (line  42)
-* gawk, IGNORECASE variable in <1>:      String Functions.    (line  29)
-* gawk, IGNORECASE variable in <2>:      Array Sorting.       (line  85)
+* gawk, IGNORECASE variable in <1>:      Array Sorting Functions.
+                                                              (line  85)
+* gawk, IGNORECASE variable in <2>:      String Functions.    (line  29)
 * gawk, IGNORECASE variable in <3>:      Array Intro.         (line  92)
 * gawk, IGNORECASE variable in <4>:      User-modified.       (line  82)
 * gawk, IGNORECASE variable in:          Case-sensitivity.    (line  26)
@@ -25910,12 +26028,14 @@ Index
 * if statement, actions, changing:       Ranges.              (line  25)
 * igawk.sh program:                      Igawk Program.       (line 124)
 * ignore debugger command:               Breakpoint Control.  (line  86)
-* IGNORECASE variable <1>:               String Functions.    (line  29)
-* IGNORECASE variable <2>:               Array Sorting.       (line  85)
+* IGNORECASE variable <1>:               Array Sorting Functions.
+                                                              (line  85)
+* IGNORECASE variable <2>:               String Functions.    (line  29)
 * IGNORECASE variable <3>:               Array Intro.         (line  92)
 * IGNORECASE variable <4>:               User-modified.       (line  82)
 * IGNORECASE variable:                   Case-sensitivity.    (line  26)
-* IGNORECASE variable, array sorting and: Array Sorting.      (line  85)
+* IGNORECASE variable, array sorting and: Array Sorting Functions.
+                                                              (line  85)
 * IGNORECASE variable, array subscripts and: Array Intro.     (line  92)
 * IGNORECASE variable, in example programs: Library Functions.
                                                               (line  42)
@@ -25928,7 +26048,7 @@ Index
 * in operator <3>:                       Precedence.          (line  83)
 * in operator:                           Comparison Operators.
                                                               (line  11)
-* in operator, arrays and <1>:           Scanning an Array.   (line  22)
+* in operator, arrays and <1>:           Scanning an Array.   (line  17)
 * in operator, arrays and:               Reference to Elements.
                                                               (line  37)
 * increment operators:                   Increment Ops.       (line   6)
@@ -26593,7 +26713,8 @@ Index
 * recursive functions:                   Definition Syntax.   (line  73)
 * redirection of input:                  Getline/File.        (line   6)
 * redirection of output:                 Redirection.         (line   6)
-* reference counting, sorting arrays:    Array Sorting.       (line  79)
+* reference counting, sorting arrays:    Array Sorting Functions.
+                                                              (line  79)
 * regexp constants <1>:                  Comparison Operators.
                                                               (line 103)
 * regexp constants <2>:                  Regexp Constants.    (line   6)
@@ -26751,7 +26872,8 @@ Index
 * side effects:                          Concatenation.       (line  42)
 * side effects, array indexing:          Reference to Elements.
                                                               (line  42)
-* side effects, asort() function:        Array Sorting.       (line  24)
+* side effects, asort() function:        Array Sorting Functions.
+                                                              (line  24)
 * side effects, assignment expressions:  Assignment Ops.      (line  23)
 * side effects, Boolean operators:       Boolean Ops.         (line  30)
 * side effects, conditional expressions: Conditional Exp.     (line  22)
@@ -26781,7 +26903,8 @@ Index
 * Skywalker, Luke:                       Undocumented.        (line   6)
 * sleep utility:                         Alarm Program.       (line 109)
 * Solaris, POSIX-compliant awk:          Other Versions.      (line  86)
-* sort function, arrays, sorting:        Array Sorting.       (line   6)
+* sort function, arrays, sorting:        Array Sorting Functions.
+                                                              (line   6)
 * sort utility:                          Word Sorting.        (line  50)
 * sort utility, coprocesses and:         Two-way I/O.         (line  83)
 * sorting characters in different languages: Explaining gettext.
@@ -27132,407 +27255,409 @@ Index
 
 Tag Table:
 Node: Top1346
-Node: Foreword29926
-Node: Preface34271
-Ref: Preface-Footnote-137238
-Ref: Preface-Footnote-237344
-Node: History37576
-Node: Names39967
-Ref: Names-Footnote-141444
-Node: This Manual41516
-Ref: This Manual-Footnote-146464
-Node: Conventions46564
-Node: Manual History48698
-Ref: Manual History-Footnote-151968
-Ref: Manual History-Footnote-252009
-Node: How To Contribute52083
-Node: Acknowledgments53227
-Node: Getting Started57558
-Node: Running gawk59937
-Node: One-shot61123
-Node: Read Terminal62348
-Ref: Read Terminal-Footnote-163998
-Ref: Read Terminal-Footnote-264274
-Node: Long64445
-Node: Executable Scripts65821
-Ref: Executable Scripts-Footnote-167690
-Ref: Executable Scripts-Footnote-267792
-Node: Comments68243
-Node: Quoting70710
-Node: DOS Quoting75333
-Node: Sample Data Files76008
-Node: Very Simple79040
-Node: Two Rules83639
-Node: More Complex85786
-Ref: More Complex-Footnote-188716
-Node: Statements/Lines88801
-Ref: Statements/Lines-Footnote-193263
-Node: Other Features93528
-Node: When94456
-Node: Invoking Gawk96603
-Node: Command Line97988
-Node: Options98771
-Ref: Options-Footnote-1111903
-Node: Other Arguments111928
-Node: Naming Standard Input114586
-Node: Environment Variables115680
-Node: AWKPATH Variable116124
-Ref: AWKPATH Variable-Footnote-1118721
-Node: Other Environment Variables118981
-Node: Exit Status121321
-Node: Include Files121996
-Node: Obsolete125481
-Node: Undocumented126167
-Node: Regexp126408
-Node: Regexp Usage127860
-Node: Escape Sequences129886
-Node: Regexp Operators135649
-Ref: Regexp Operators-Footnote-1142846
-Ref: Regexp Operators-Footnote-2142993
-Node: Bracket Expressions143091
-Ref: table-char-classes144894
-Node: GNU Regexp Operators147538
-Node: Case-sensitivity151261
-Ref: Case-sensitivity-Footnote-1154229
-Ref: Case-sensitivity-Footnote-2154464
-Node: Leftmost Longest154572
-Node: Computed Regexps155773
-Node: Locales159199
-Node: Reading Files162906
-Node: Records164847
-Ref: Records-Footnote-1173521
-Node: Fields173558
-Ref: Fields-Footnote-1176591
-Node: Nonconstant Fields176677
-Node: Changing Fields178879
-Node: Field Separators184857
-Node: Default Field Splitting187486
-Node: Regexp Field Splitting188603
-Node: Single Character Fields191945
-Node: Command Line Field Separator193004
-Node: Field Splitting Summary196445
-Ref: Field Splitting Summary-Footnote-1199637
-Node: Constant Size199738
-Node: Splitting By Content204322
-Ref: Splitting By Content-Footnote-1208048
-Node: Multiple Line208088
-Ref: Multiple Line-Footnote-1213935
-Node: Getline214114
-Node: Plain Getline216342
-Node: Getline/Variable218431
-Node: Getline/File219572
-Node: Getline/Variable/File220894
-Ref: Getline/Variable/File-Footnote-1222493
-Node: Getline/Pipe222580
-Node: Getline/Variable/Pipe225140
-Node: Getline/Coprocess226247
-Node: Getline/Variable/Coprocess227490
-Node: Getline Notes228204
-Node: Getline Summary230146
-Ref: table-getline-variants230489
-Node: Command line directories231345
-Node: Printing231970
-Node: Print233601
-Node: Print Examples234938
-Node: Output Separators237722
-Node: OFMT239482
-Node: Printf240840
-Node: Basic Printf241746
-Node: Control Letters243285
-Node: Format Modifiers247097
-Node: Printf Examples253106
-Node: Redirection255821
-Node: Special Files262805
-Node: Special FD263338
-Ref: Special FD-Footnote-1266962
-Node: Special Network267036
-Node: Special Caveats267886
-Node: Close Files And Pipes268682
-Ref: Close Files And Pipes-Footnote-1275705
-Ref: Close Files And Pipes-Footnote-2275853
-Node: Expressions276003
-Node: Values277072
-Node: Constants277748
-Node: Scalar Constants278428
-Ref: Scalar Constants-Footnote-1279287
-Node: Nondecimal-numbers279469
-Node: Regexp Constants282528
-Node: Using Constant Regexps283003
-Node: Variables286058
-Node: Using Variables286713
-Node: Assignment Options288437
-Node: Conversion290309
-Ref: table-locale-affects295685
-Ref: Conversion-Footnote-1296309
-Node: All Operators296418
-Node: Arithmetic Ops297048
-Node: Concatenation299553
-Ref: Concatenation-Footnote-1302346
-Node: Assignment Ops302466
-Ref: table-assign-ops307454
-Node: Increment Ops308862
-Node: Truth Values and Conditions312332
-Node: Truth Values313415
-Node: Typing and Comparison314464
-Node: Variable Typing315253
-Ref: Variable Typing-Footnote-1319150
-Node: Comparison Operators319272
-Ref: table-relational-ops319682
-Node: POSIX String Comparison323231
-Ref: POSIX String Comparison-Footnote-1324187
-Node: Boolean Ops324325
-Ref: Boolean Ops-Footnote-1328403
-Node: Conditional Exp328494
-Node: Function Calls330226
-Node: Precedence333820
-Node: Patterns and Actions337473
-Node: Pattern Overview338527
-Node: Regexp Patterns340193
-Node: Expression Patterns340736
-Node: Ranges344310
-Node: BEGIN/END347276
-Node: Using BEGIN/END348038
-Ref: Using BEGIN/END-Footnote-1350769
-Node: I/O And BEGIN/END350875
-Node: BEGINFILE/ENDFILE353157
-Node: Empty355988
-Node: Using Shell Variables356304
-Node: Action Overview358589
-Node: Statements360946
-Node: If Statement362800
-Node: While Statement364299
-Node: Do Statement366343
-Node: For Statement367499
-Node: Switch Statement370651
-Node: Break Statement372748
-Node: Continue Statement374738
-Node: Next Statement376525
-Node: Nextfile Statement378915
-Node: Exit Statement381212
-Node: Built-in Variables383628
-Node: User-modified384723
-Ref: User-modified-Footnote-1392749
-Node: Auto-set392811
-Ref: Auto-set-Footnote-1403524
-Node: ARGC and ARGV403729
-Node: Arrays407580
-Node: Array Basics409151
-Node: Array Intro409862
-Node: Reference to Elements414180
-Node: Assigning Elements416450
-Node: Array Example416941
-Node: Scanning an Array418673
-Node: Controlling Scanning421129
-Node: Controlling Scanning With A Function424172
-Node: Delete430174
-Ref: Delete-Footnote-1432609
-Node: Numeric Array Subscripts432666
-Node: Uninitialized Subscripts434849
-Node: Multi-dimensional436477
-Node: Multi-scanning439568
-Node: Array Sorting441152
-Ref: Array Sorting-Footnote-1445138
-Node: Arrays of Arrays445332
-Node: Functions449905
-Node: Built-in450727
-Node: Calling Built-in451805
-Node: Numeric Functions453793
-Ref: Numeric Functions-Footnote-1457558
-Ref: Numeric Functions-Footnote-2457915
-Ref: Numeric Functions-Footnote-3457963
-Node: String Functions458232
-Ref: String Functions-Footnote-1481703
-Ref: String Functions-Footnote-2481832
-Ref: String Functions-Footnote-3482080
-Node: Gory Details482167
-Ref: table-sub-escapes483846
-Ref: table-posix-sub485160
-Ref: table-gensub-escapes486073
-Node: I/O Functions487244
-Ref: I/O Functions-Footnote-1493899
-Node: Time Functions494046
-Ref: Time Functions-Footnote-1504938
-Ref: Time Functions-Footnote-2505006
-Ref: Time Functions-Footnote-3505164
-Ref: Time Functions-Footnote-4505275
-Ref: Time Functions-Footnote-5505387
-Ref: Time Functions-Footnote-6505614
-Node: Bitwise Functions505880
-Ref: table-bitwise-ops506438
-Ref: Bitwise Functions-Footnote-1510598
-Node: Type Functions510782
-Node: I18N Functions511252
-Node: User-defined512879
-Node: Definition Syntax513683
-Ref: Definition Syntax-Footnote-1518593
-Node: Function Example518662
-Node: Function Caveats521256
-Node: Calling A Function521677
-Node: Variable Scope522792
-Node: Pass By Value/Reference524767
-Node: Return Statement528207
-Node: Dynamic Typing531188
-Node: Indirect Calls531923
-Node: Internationalization541608
-Node: I18N and L10N543034
-Node: Explaining gettext543720
-Ref: Explaining gettext-Footnote-1548786
-Ref: Explaining gettext-Footnote-2548970
-Node: Programmer i18n549135
-Node: Translator i18n553335
-Node: String Extraction554128
-Ref: String Extraction-Footnote-1555089
-Node: Printf Ordering555175
-Ref: Printf Ordering-Footnote-1557959
-Node: I18N Portability558023
-Ref: I18N Portability-Footnote-1560472
-Node: I18N Example560535
-Ref: I18N Example-Footnote-1563170
-Node: Gawk I18N563242
-Node: Advanced Features563859
-Node: Nondecimal Data565178
-Node: Two-way I/O566759
-Ref: Two-way I/O-Footnote-1572193
-Node: TCP/IP Networking572263
-Node: Profiling575107
-Node: Library Functions582581
-Ref: Library Functions-Footnote-1585588
-Node: Library Names585759
-Ref: Library Names-Footnote-1589230
-Ref: Library Names-Footnote-2589450
-Node: General Functions589536
-Node: Strtonum Function590489
-Node: Assert Function593419
-Node: Round Function596745
-Node: Cliff Random Function598288
-Node: Ordinal Functions599304
-Ref: Ordinal Functions-Footnote-1602374
-Ref: Ordinal Functions-Footnote-2602626
-Node: Join Function602835
-Ref: Join Function-Footnote-1604606
-Node: Gettimeofday Function604806
-Node: Data File Management608521
-Node: Filetrans Function609153
-Node: Rewind Function613292
-Node: File Checking614679
-Node: Empty Files615773
-Node: Ignoring Assigns618003
-Node: Getopt Function619556
-Ref: Getopt Function-Footnote-1630860
-Node: Passwd Functions631063
-Ref: Passwd Functions-Footnote-1640038
-Node: Group Functions640126
-Node: Walking Arrays648210
-Node: Sample Programs649779
-Node: Running Examples650444
-Node: Clones651172
-Node: Cut Program652396
-Node: Egrep Program662241
-Ref: Egrep Program-Footnote-1670014
-Node: Id Program670124
-Node: Split Program673740
-Ref: Split Program-Footnote-1677259
-Node: Tee Program677387
-Node: Uniq Program680190
-Node: Wc Program687619
-Ref: Wc Program-Footnote-1691885
-Ref: Wc Program-Footnote-2692085
-Node: Miscellaneous Programs692177
-Node: Dupword Program693365
-Node: Alarm Program695396
-Node: Translate Program700145
-Ref: Translate Program-Footnote-1704532
-Ref: Translate Program-Footnote-2704760
-Node: Labels Program704894
-Ref: Labels Program-Footnote-1708265
-Node: Word Sorting708349
-Node: History Sorting712233
-Node: Extract Program714072
-Ref: Extract Program-Footnote-1721555
-Node: Simple Sed721683
-Node: Igawk Program724745
-Ref: Igawk Program-Footnote-1739778
-Ref: Igawk Program-Footnote-2739979
-Node: Anagram Program740117
-Node: Signature Program743185
-Node: Debugger744285
-Node: Debugging745196
-Node: Debugging Concepts745609
-Node: Debugging Terms747465
-Node: Awk Debugging750087
-Node: Sample dgawk session750979
-Node: dgawk invocation751471
-Node: Finding The Bug752653
-Node: List of Debugger Commands759139
-Node: Breakpoint Control760450
-Node: Dgawk Execution Control764086
-Node: Viewing And Changing Data767437
-Node: Dgawk Stack770774
-Node: Dgawk Info772234
-Node: Miscellaneous Dgawk Commands776182
-Node: Readline Support781610
-Node: Dgawk Limitations782448
-Node: Language History784637
-Node: V7/SVR3.1786075
-Node: SVR4788396
-Node: POSIX789838
-Node: BTL790846
-Node: POSIX/GNU791580
-Node: Common Extensions796681
-Node: Contributors797782
-Node: Installation801921
-Node: Gawk Distribution802815
-Node: Getting803299
-Node: Extracting804125
-Node: Distribution contents805817
-Node: Unix Installation811039
-Node: Quick Installation811656
-Node: Additional Configuration Options813618
-Node: Configuration Philosophy815095
-Node: Non-Unix Installation817437
-Node: PC Installation817895
-Node: PC Binary Installation819194
-Node: PC Compiling821042
-Node: PC Testing823986
-Node: PC Using825162
-Node: Cygwin829347
-Node: MSYS830347
-Node: VMS Installation830861
-Node: VMS Compilation831464
-Ref: VMS Compilation-Footnote-1832471
-Node: VMS Installation Details832529
-Node: VMS Running834164
-Node: VMS Old Gawk835771
-Node: Bugs836245
-Node: Other Versions840155
-Node: Notes845434
-Node: Compatibility Mode846126
-Node: Additions846909
-Node: Accessing The Source847721
-Node: Adding Code849146
-Node: New Ports855113
-Node: Dynamic Extensions859226
-Node: Internals860602
-Node: Plugin License869705
-Node: Sample Library870339
-Node: Internal File Description871025
-Node: Internal File Ops874740
-Ref: Internal File Ops-Footnote-1879521
-Node: Using Internal File Ops879661
-Node: Future Extensions882038
-Node: Basic Concepts884542
-Node: Basic High Level885299
-Ref: Basic High Level-Footnote-1889334
-Node: Basic Data Typing889519
-Node: Floating Point Issues894044
-Node: String Conversion Precision895127
-Ref: String Conversion Precision-Footnote-1896821
-Node: Unexpected Results896930
-Node: POSIX Floating Point Problems898756
-Ref: POSIX Floating Point Problems-Footnote-1902458
-Node: Glossary902496
-Node: Copying926639
-Node: GNU Free Documentation License964196
-Node: Index989333
+Node: Foreword33320
+Node: Preface37665
+Ref: Preface-Footnote-140632
+Ref: Preface-Footnote-240738
+Node: History40970
+Node: Names43361
+Ref: Names-Footnote-144838
+Node: This Manual44910
+Ref: This Manual-Footnote-149858
+Node: Conventions49958
+Node: Manual History52092
+Ref: Manual History-Footnote-155362
+Ref: Manual History-Footnote-255403
+Node: How To Contribute55477
+Node: Acknowledgments56621
+Node: Getting Started60952
+Node: Running gawk63331
+Node: One-shot64517
+Node: Read Terminal65742
+Ref: Read Terminal-Footnote-167392
+Ref: Read Terminal-Footnote-267668
+Node: Long67839
+Node: Executable Scripts69215
+Ref: Executable Scripts-Footnote-171084
+Ref: Executable Scripts-Footnote-271186
+Node: Comments71637
+Node: Quoting74104
+Node: DOS Quoting78727
+Node: Sample Data Files79402
+Node: Very Simple82434
+Node: Two Rules87033
+Node: More Complex89180
+Ref: More Complex-Footnote-192110
+Node: Statements/Lines92195
+Ref: Statements/Lines-Footnote-196657
+Node: Other Features96922
+Node: When97850
+Node: Invoking Gawk99997
+Node: Command Line101382
+Node: Options102165
+Ref: Options-Footnote-1115297
+Node: Other Arguments115322
+Node: Naming Standard Input117980
+Node: Environment Variables119074
+Node: AWKPATH Variable119518
+Ref: AWKPATH Variable-Footnote-1122115
+Node: Other Environment Variables122375
+Node: Exit Status124715
+Node: Include Files125390
+Node: Obsolete128875
+Node: Undocumented129561
+Node: Regexp129802
+Node: Regexp Usage131254
+Node: Escape Sequences133280
+Node: Regexp Operators139043
+Ref: Regexp Operators-Footnote-1146240
+Ref: Regexp Operators-Footnote-2146387
+Node: Bracket Expressions146485
+Ref: table-char-classes148288
+Node: GNU Regexp Operators150932
+Node: Case-sensitivity154655
+Ref: Case-sensitivity-Footnote-1157623
+Ref: Case-sensitivity-Footnote-2157858
+Node: Leftmost Longest157966
+Node: Computed Regexps159167
+Node: Locales162593
+Node: Reading Files166300
+Node: Records168241
+Ref: Records-Footnote-1176915
+Node: Fields176952
+Ref: Fields-Footnote-1179985
+Node: Nonconstant Fields180071
+Node: Changing Fields182273
+Node: Field Separators188251
+Node: Default Field Splitting190880
+Node: Regexp Field Splitting191997
+Node: Single Character Fields195339
+Node: Command Line Field Separator196398
+Node: Field Splitting Summary199839
+Ref: Field Splitting Summary-Footnote-1203031
+Node: Constant Size203132
+Node: Splitting By Content207716
+Ref: Splitting By Content-Footnote-1211442
+Node: Multiple Line211482
+Ref: Multiple Line-Footnote-1217329
+Node: Getline217508
+Node: Plain Getline219736
+Node: Getline/Variable221825
+Node: Getline/File222966
+Node: Getline/Variable/File224288
+Ref: Getline/Variable/File-Footnote-1225887
+Node: Getline/Pipe225974
+Node: Getline/Variable/Pipe228534
+Node: Getline/Coprocess229641
+Node: Getline/Variable/Coprocess230884
+Node: Getline Notes231598
+Node: Getline Summary233540
+Ref: table-getline-variants233883
+Node: Command line directories234739
+Node: Printing235364
+Node: Print236995
+Node: Print Examples238332
+Node: Output Separators241116
+Node: OFMT242876
+Node: Printf244234
+Node: Basic Printf245140
+Node: Control Letters246679
+Node: Format Modifiers250491
+Node: Printf Examples256500
+Node: Redirection259215
+Node: Special Files266199
+Node: Special FD266732
+Ref: Special FD-Footnote-1270356
+Node: Special Network270430
+Node: Special Caveats271280
+Node: Close Files And Pipes272076
+Ref: Close Files And Pipes-Footnote-1279099
+Ref: Close Files And Pipes-Footnote-2279247
+Node: Expressions279397
+Node: Values280466
+Node: Constants281142
+Node: Scalar Constants281822
+Ref: Scalar Constants-Footnote-1282681
+Node: Nondecimal-numbers282863
+Node: Regexp Constants285922
+Node: Using Constant Regexps286397
+Node: Variables289452
+Node: Using Variables290107
+Node: Assignment Options291831
+Node: Conversion293703
+Ref: table-locale-affects299079
+Ref: Conversion-Footnote-1299703
+Node: All Operators299812
+Node: Arithmetic Ops300442
+Node: Concatenation302947
+Ref: Concatenation-Footnote-1305740
+Node: Assignment Ops305860
+Ref: table-assign-ops310848
+Node: Increment Ops312256
+Node: Truth Values and Conditions315726
+Node: Truth Values316809
+Node: Typing and Comparison317858
+Node: Variable Typing318647
+Ref: Variable Typing-Footnote-1322544
+Node: Comparison Operators322666
+Ref: table-relational-ops323076
+Node: POSIX String Comparison326625
+Ref: POSIX String Comparison-Footnote-1327581
+Node: Boolean Ops327719
+Ref: Boolean Ops-Footnote-1331797
+Node: Conditional Exp331888
+Node: Function Calls333620
+Node: Precedence337214
+Node: Patterns and Actions340867
+Node: Pattern Overview341921
+Node: Regexp Patterns343587
+Node: Expression Patterns344130
+Node: Ranges347704
+Node: BEGIN/END350670
+Node: Using BEGIN/END351432
+Ref: Using BEGIN/END-Footnote-1354163
+Node: I/O And BEGIN/END354269
+Node: BEGINFILE/ENDFILE356551
+Node: Empty359382
+Node: Using Shell Variables359698
+Node: Action Overview361983
+Node: Statements364340
+Node: If Statement366194
+Node: While Statement367693
+Node: Do Statement369737
+Node: For Statement370893
+Node: Switch Statement374045
+Node: Break Statement376142
+Node: Continue Statement378132
+Node: Next Statement379919
+Node: Nextfile Statement382309
+Node: Exit Statement384606
+Node: Built-in Variables387022
+Node: User-modified388117
+Ref: User-modified-Footnote-1396143
+Node: Auto-set396205
+Ref: Auto-set-Footnote-1406918
+Node: ARGC and ARGV407123
+Node: Arrays410974
+Node: Array Basics412479
+Node: Array Intro413190
+Node: Reference to Elements417508
+Node: Assigning Elements419778
+Node: Array Example420269
+Node: Scanning an Array422001
+Node: Delete424667
+Ref: Delete-Footnote-1427102
+Node: Numeric Array Subscripts427159
+Node: Uninitialized Subscripts429342
+Node: Multi-dimensional430970
+Node: Multi-scanning434064
+Node: Arrays of Arrays435648
+Node: Functions440225
+Node: Built-in441047
+Node: Calling Built-in442125
+Node: Numeric Functions444113
+Ref: Numeric Functions-Footnote-1447878
+Ref: Numeric Functions-Footnote-2448235
+Ref: Numeric Functions-Footnote-3448283
+Node: String Functions448552
+Ref: String Functions-Footnote-1472049
+Ref: String Functions-Footnote-2472178
+Ref: String Functions-Footnote-3472426
+Node: Gory Details472513
+Ref: table-sub-escapes474192
+Ref: table-posix-sub475506
+Ref: table-gensub-escapes476419
+Node: I/O Functions477590
+Ref: I/O Functions-Footnote-1484245
+Node: Time Functions484392
+Ref: Time Functions-Footnote-1495284
+Ref: Time Functions-Footnote-2495352
+Ref: Time Functions-Footnote-3495510
+Ref: Time Functions-Footnote-4495621
+Ref: Time Functions-Footnote-5495733
+Ref: Time Functions-Footnote-6495960
+Node: Bitwise Functions496226
+Ref: table-bitwise-ops496784
+Ref: Bitwise Functions-Footnote-1500944
+Node: Type Functions501128
+Node: I18N Functions501598
+Node: User-defined503225
+Node: Definition Syntax504029
+Ref: Definition Syntax-Footnote-1508939
+Node: Function Example509008
+Node: Function Caveats511602
+Node: Calling A Function512023
+Node: Variable Scope513138
+Node: Pass By Value/Reference515113
+Node: Return Statement518553
+Node: Dynamic Typing521534
+Node: Indirect Calls522269
+Node: Internationalization531954
+Node: I18N and L10N533380
+Node: Explaining gettext534066
+Ref: Explaining gettext-Footnote-1539132
+Ref: Explaining gettext-Footnote-2539316
+Node: Programmer i18n539481
+Node: Translator i18n543681
+Node: String Extraction544474
+Ref: String Extraction-Footnote-1545435
+Node: Printf Ordering545521
+Ref: Printf Ordering-Footnote-1548305
+Node: I18N Portability548369
+Ref: I18N Portability-Footnote-1550818
+Node: I18N Example550881
+Ref: I18N Example-Footnote-1553516
+Node: Gawk I18N553588
+Node: Advanced Features554205
+Node: Nondecimal Data555718
+Node: Array Sorting557301
+Node: Controlling Array Traversal558001
+Node: Controlling Scanning With A Function558752
+Node: Controlling Scanning565232
+Node: Array Sorting Functions568860
+Ref: Array Sorting Functions-Footnote-1572854
+Node: Two-way I/O573048
+Ref: Two-way I/O-Footnote-1578480
+Node: TCP/IP Networking578550
+Node: Profiling581394
+Node: Library Functions588868
+Ref: Library Functions-Footnote-1591875
+Node: Library Names592046
+Ref: Library Names-Footnote-1595517
+Ref: Library Names-Footnote-2595737
+Node: General Functions595823
+Node: Strtonum Function596776
+Node: Assert Function599706
+Node: Round Function603032
+Node: Cliff Random Function604575
+Node: Ordinal Functions605591
+Ref: Ordinal Functions-Footnote-1608661
+Ref: Ordinal Functions-Footnote-2608913
+Node: Join Function609122
+Ref: Join Function-Footnote-1610893
+Node: Gettimeofday Function611093
+Node: Data File Management614808
+Node: Filetrans Function615440
+Node: Rewind Function619579
+Node: File Checking620966
+Node: Empty Files622060
+Node: Ignoring Assigns624290
+Node: Getopt Function625843
+Ref: Getopt Function-Footnote-1637147
+Node: Passwd Functions637350
+Ref: Passwd Functions-Footnote-1646325
+Node: Group Functions646413
+Node: Walking Arrays654497
+Node: Sample Programs656066
+Node: Running Examples656731
+Node: Clones657459
+Node: Cut Program658683
+Node: Egrep Program668528
+Ref: Egrep Program-Footnote-1676301
+Node: Id Program676411
+Node: Split Program680027
+Ref: Split Program-Footnote-1683546
+Node: Tee Program683674
+Node: Uniq Program686477
+Node: Wc Program693906
+Ref: Wc Program-Footnote-1698172
+Ref: Wc Program-Footnote-2698372
+Node: Miscellaneous Programs698464
+Node: Dupword Program699652
+Node: Alarm Program701683
+Node: Translate Program706432
+Ref: Translate Program-Footnote-1710819
+Ref: Translate Program-Footnote-2711047
+Node: Labels Program711181
+Ref: Labels Program-Footnote-1714552
+Node: Word Sorting714636
+Node: History Sorting718520
+Node: Extract Program720359
+Ref: Extract Program-Footnote-1727842
+Node: Simple Sed727970
+Node: Igawk Program731032
+Ref: Igawk Program-Footnote-1746065
+Ref: Igawk Program-Footnote-2746266
+Node: Anagram Program746404
+Node: Signature Program749472
+Node: Debugger750572
+Node: Debugging751483
+Node: Debugging Concepts751896
+Node: Debugging Terms753752
+Node: Awk Debugging756374
+Node: Sample dgawk session757266
+Node: dgawk invocation757758
+Node: Finding The Bug758940
+Node: List of Debugger Commands765426
+Node: Breakpoint Control766737
+Node: Dgawk Execution Control770373
+Node: Viewing And Changing Data773724
+Node: Dgawk Stack777061
+Node: Dgawk Info778521
+Node: Miscellaneous Dgawk Commands782469
+Node: Readline Support787897
+Node: Dgawk Limitations788735
+Node: Language History790924
+Node: V7/SVR3.1792362
+Node: SVR4794683
+Node: POSIX796125
+Node: BTL797133
+Node: POSIX/GNU797867
+Node: Common Extensions803018
+Node: Contributors804119
+Node: Installation808295
+Node: Gawk Distribution809189
+Node: Getting809673
+Node: Extracting810499
+Node: Distribution contents812191
+Node: Unix Installation817413
+Node: Quick Installation818030
+Node: Additional Configuration Options819992
+Node: Configuration Philosophy821469
+Node: Non-Unix Installation823811
+Node: PC Installation824269
+Node: PC Binary Installation825568
+Node: PC Compiling827416
+Node: PC Testing830360
+Node: PC Using831536
+Node: Cygwin835721
+Node: MSYS836721
+Node: VMS Installation837235
+Node: VMS Compilation837838
+Ref: VMS Compilation-Footnote-1838845
+Node: VMS Installation Details838903
+Node: VMS Running840538
+Node: VMS Old Gawk842145
+Node: Bugs842619
+Node: Other Versions846529
+Node: Notes851808
+Node: Compatibility Mode852500
+Node: Additions853283
+Node: Accessing The Source854095
+Node: Adding Code855520
+Node: New Ports861487
+Node: Dynamic Extensions865600
+Node: Internals866976
+Node: Plugin License876079
+Node: Sample Library876713
+Node: Internal File Description877399
+Node: Internal File Ops881114
+Ref: Internal File Ops-Footnote-1885895
+Node: Using Internal File Ops886035
+Node: Future Extensions888412
+Node: Basic Concepts890916
+Node: Basic High Level891673
+Ref: Basic High Level-Footnote-1895708
+Node: Basic Data Typing895893
+Node: Floating Point Issues900418
+Node: String Conversion Precision901501
+Ref: String Conversion Precision-Footnote-1903195
+Node: Unexpected Results903304
+Node: POSIX Floating Point Problems905130
+Ref: POSIX Floating Point Problems-Footnote-1908832
+Node: Glossary908870
+Node: Copying933013
+Node: GNU Free Documentation License970570
+Node: Index995707
 
 End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 60cfd1d..49229d1 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -306,394 +306,437 @@ particular records in a file and perform operations 
upon them.
 * Index::                          Concept and Variable Index.
 
 @detailmenu
-* History::                        The history of @command{gawk} and
-                                   @command{awk}.
-* Names::                          What name to use to find @command{awk}.
-* This Manual::                    Using this @value{DOCUMENT}. Includes
-                                   sample input files that you can use.
-* Conventions::                    Typographical Conventions.
-* Manual History::                 Brief history of the GNU project and this
-                                   @value{DOCUMENT}.
-* How To Contribute::              Helping to save the world.
-* Acknowledgments::                Acknowledgments.
-* Running gawk::                   How to run @command{gawk} programs;
-                                   includes command-line syntax.
-* One-shot::                       Running a short throwaway @command{awk}
-                                   program.
-* Read Terminal::                  Using no input files (input from terminal
-                                   instead).
-* Long::                           Putting permanent @command{awk} programs in
-                                   files.
-* Executable Scripts::             Making self-contained @command{awk}
-                                   programs.
-* Comments::                       Adding documentation to @command{gawk}
-                                   programs.
-* Quoting::                        More discussion of shell quoting issues.
-* DOS Quoting::                    Quoting in Windows Batch Files.
-* Sample Data Files::              Sample data files for use in the
-                                   @command{awk} programs illustrated in this
-                                   @value{DOCUMENT}.
-* Very Simple::                    A very simple example.
-* Two Rules::                      A less simple one-line example using two
-                                   rules.
-* More Complex::                   A more complex example.
-* Statements/Lines::               Subdividing or combining statements into
-                                   lines.
-* Other Features::                 Other Features of @command{awk}.
-* When::                           When to use @command{gawk} and when to use
-                                   other things.
-* Command Line::                   How to run @command{awk}.
-* Options::                        Command-line options and their meanings.
-* Other Arguments::                Input file names and variable assignments.
-* Naming Standard Input::          How to specify standard input with other
-                                   files.
-* Environment Variables::          The environment variables @command{gawk}
-                                   uses.
-* AWKPATH Variable::               Searching directories for @command{awk}
-                                   programs.
-* Other Environment Variables::    The environment variables.
-* Exit Status::                    @command{gawk}'s exit status.
-* Include Files::                  Including other files into your program.
-* Obsolete::                       Obsolete Options and/or features.
-* Undocumented::                   Undocumented Options and Features.
-* Regexp Usage::                   How to Use Regular Expressions.
-* Escape Sequences::               How to write nonprinting characters.
-* Regexp Operators::               Regular Expression Operators.
-* Bracket Expressions::            What can go between @samp{[...]}.
-* GNU Regexp Operators::           Operators specific to GNU software.
-* Case-sensitivity::               How to do case-insensitive matching.
-* Leftmost Longest::               How much text matches.
-* Computed Regexps::               Using Dynamic Regexps.
-* Locales::                        How the locale affects things.
-* Records::                        Controlling how data is split into records.
-* Fields::                         An introduction to fields.
-* Nonconstant Fields::             Nonconstant Field Numbers.
-* Changing Fields::                Changing the Contents of a Field.
-* Field Separators::               The field separator and how to change it.
-* Default Field Splitting::        How fields are normally separated.
-* Regexp Field Splitting::         Using regexps as the field separator.
-* Single Character Fields::        Making each character a separate field.
-* Command Line Field Separator::   Setting @code{FS} from the command-line.
-* Field Splitting Summary::        Some final points and a summary table.
-* Constant Size::                  Reading constant width data.
-* Splitting By Content::           Defining Fields By Content
-* Multiple Line::                  Reading multi-line records.
-* Getline::                        Reading files under explicit program
-                                   control using the @code{getline} function.
-* Plain Getline::                  Using @code{getline} with no arguments.
-* Getline/Variable::               Using @code{getline} into a variable.
-* Getline/File::                   Using @code{getline} from a file.
-* Getline/Variable/File::          Using @code{getline} into a variable from a
-                                   file.
-* Getline/Pipe::                   Using @code{getline} from a pipe.
-* Getline/Variable/Pipe::          Using @code{getline} into a variable from a
-                                   pipe.
-* Getline/Coprocess::              Using @code{getline} from a coprocess.
-* Getline/Variable/Coprocess::     Using @code{getline} into a variable from a
-                                   coprocess.
-* Getline Notes::                  Important things to know about
-                                   @code{getline}.
-* Getline Summary::                Summary of @code{getline} Variants.
-* Command line directories::       What happens if you put a directory on the
-                                   command line.
-* Print::                          The @code{print} statement.
-* Print Examples::                 Simple examples of @code{print} statements.
-* Output Separators::              The output separators and how to change
-                                   them.
-* OFMT::                           Controlling Numeric Output With
-                                   @code{print}.
-* Printf::                         The @code{printf} statement.
-* Basic Printf::                   Syntax of the @code{printf} statement.
-* Control Letters::                Format-control letters.
-* Format Modifiers::               Format-specification modifiers.
-* Printf Examples::                Several examples.
-* Redirection::                    How to redirect output to multiple files
-                                   and pipes.
-* Special Files::                  File name interpretation in @command{gawk}.
-                                   @command{gawk} allows access to inherited
-                                   file descriptors.
-* Special FD::                     Special files for I/O.
-* Special Network::                Special files for network communications.
-* Special Caveats::                Things to watch out for.
-* Close Files And Pipes::          Closing Input and Output Files and Pipes.
-* Values::                         Constants, Variables, and Regular
-                                   Expressions.
-* Constants::                      String, numeric and regexp constants.
-* Scalar Constants::               Numeric and string constants.
-* Nondecimal-numbers::             What are octal and hex numbers.
-* Regexp Constants::               Regular Expression constants.
-* Using Constant Regexps::         When and how to use a regexp constant.
-* Variables::                      Variables give names to values for later
-                                   use.
-* Using Variables::                Using variables in your programs.
-* Assignment Options::             Setting variables on the command-line and a
-                                   summary of command-line syntax. This is an
-                                   advanced method of input.
-* Conversion::                     The conversion of strings to numbers and
-                                   vice versa.
-* All Operators::                  @command{gawk}'s operators.
-* Arithmetic Ops::                 Arithmetic operations (@samp{+}, @samp{-},
-                                   etc.)
-* Concatenation::                  Concatenating strings.
-* Assignment Ops::                 Changing the value of a variable or a
-                                   field.
-* Increment Ops::                  Incrementing the numeric value of a
-                                   variable.
-* Truth Values and Conditions::    Testing for true and false.
-* Truth Values::                   What is ``true'' and what is ``false''.
-* Typing and Comparison::          How variables acquire types and how this
-                                   affects comparison of numbers and strings
-                                   with @samp{<}, etc.
-* Variable Typing::                String type versus numeric type.
-* Comparison Operators::           The comparison operators.
-* POSIX String Comparison::        String comparison with POSIX rules.
-* Boolean Ops::                    Combining comparison expressions using
-                                   boolean operators @samp{||} (``or''),
-                                   @samp{&&} (``and'') and @samp{!} (``not'').
-* Conditional Exp::                Conditional expressions select between two
-                                   subexpressions under control of a third
-                                   subexpression.
-* Function Calls::                 A function call is an expression.
-* Precedence::                     How various operators nest.
-* Pattern Overview::               What goes into a pattern.
-* Regexp Patterns::                Using regexps as patterns.
-* Expression Patterns::            Any expression can be used as a pattern.
-* Ranges::                         Pairs of patterns specify record ranges.
-* BEGIN/END::                      Specifying initialization and cleanup
-                                   rules.
-* Using BEGIN/END::                How and why to use BEGIN/END rules.
-* I/O And BEGIN/END::              I/O issues in BEGIN/END rules.
-* Empty::                          The empty pattern, which matches every
-                                   record.
-* BEGINFILE/ENDFILE::              Two special patterns for advanced control.
-* Using Shell Variables::          How to use shell variables with
-                                   @command{awk}.
-* Action Overview::                What goes into an action.
-* Statements::                     Describes the various control statements in
-                                   detail.
-* If Statement::                   Conditionally execute some @command{awk}
-                                   statements.
-* While Statement::                Loop until some condition is satisfied.
-* Do Statement::                   Do specified action while looping until
-                                   some condition is satisfied.
-* For Statement::                  Another looping statement, that provides
-                                   initialization and increment clauses.
-* Switch Statement::               Switch/case evaluation for conditional
-                                   execution of statements based on a value.
-* Break Statement::                Immediately exit the innermost enclosing
-                                   loop.
-* Continue Statement::             Skip to the end of the innermost enclosing
-                                   loop.
-* Next Statement::                 Stop processing the current input record.
-* Nextfile Statement::             Stop processing the current file.
-* Exit Statement::                 Stop execution of @command{awk}.
-* Built-in Variables::             Summarizes the built-in variables.
-* User-modified::                  Built-in variables that you change to
-                                   control @command{awk}.
-* Auto-set::                       Built-in variables where @command{awk}
-                                   gives you information.
-* ARGC and ARGV::                  Ways to use @code{ARGC} and @code{ARGV}.
-* Array Basics::                   The basics of arrays.
-* Array Intro::                    Introduction to Arrays
-* Reference to Elements::          How to examine one element of an array.
-* Assigning Elements::             How to change an element of an array.
-* Array Example::                  Basic Example of an Array
-* Scanning an Array::              A variation of the @code{for} statement. It
-                                   loops through the indices of an array's
-                                   existing elements.
-* Controlling Scanning::           Controlling the order in which arrays
-                                   are scanned.
-* Delete::                         The @code{delete} statement removes an
-                                   element from an array.
-* Numeric Array Subscripts::       How to use numbers as subscripts in
-                                   @command{awk}.
-* Uninitialized Subscripts::       Using Uninitialized variables as
-                                   subscripts.
-* Multi-dimensional::              Emulating multidimensional arrays in
-                                   @command{awk}.
-* Multi-scanning::                 Scanning multidimensional arrays.
-* Array Sorting::                  Sorting array values and indices.
-* Arrays of Arrays::               True multidimensional arrays.
-* Built-in::                       Summarizes the built-in functions.
-* Calling Built-in::               How to call built-in functions.
-* Numeric Functions::              Functions that work with numbers, including
-                                   @code{int()}, @code{sin()} and
-                                   @code{rand()}.
-* String Functions::               Functions for string manipulation, such as
-                                   @code{split()}, @code{match()} and
-                                   @code{sprintf()}.
-* Gory Details::                   More than you want to know about @samp{\}
-                                   and @samp{&} with @code{sub()},
-                                   @code{gsub()}, and @code{gensub()}.
-* I/O Functions::                  Functions for files and shell commands.
-* Time Functions::                 Functions for dealing with timestamps.
-* Bitwise Functions::              Functions for bitwise operations.
-* Type Functions::                 Functions for type information.
-* I18N Functions::                 Functions for string translation.
-* User-defined::                   Describes User-defined functions in detail.
-* Definition Syntax::              How to write definitions and what they
-                                   mean.
-* Function Example::               An example function definition and what it
-                                   does.
-* Function Caveats::               Things to watch out for.
-* Calling A Function::             Don't use spaces.
-* Variable Scope::                 Controlling variable scope.
-* Pass By Value/Reference::        Passing parameters.
-* Return Statement::               Specifying the value a function returns.
-* Dynamic Typing::                 How variable types can change at runtime.
-* Indirect Calls::                 Choosing the function to call at runtime.
-* I18N and L10N::                  Internationalization and Localization.
-* Explaining gettext::             How GNU @code{gettext} works.
-* Programmer i18n::                Features for the programmer.
-* Translator i18n::                Features for the translator.
-* String Extraction::              Extracting marked strings.
-* Printf Ordering::                Rearranging @code{printf} arguments.
-* I18N Portability::               @command{awk}-level portability issues.
-* I18N Example::                   A simple i18n example.
-* Gawk I18N::                      @command{gawk} is also internationalized.
-* Nondecimal Data::                Allowing nondecimal input data.
-* Two-way I/O::                    Two-way communications with another
-                                   process.
-* TCP/IP Networking::              Using @command{gawk} for network
-                                   programming.
-* Profiling::                      Profiling your @command{awk} programs.
-* Library Names::                  How to best name private global variables
-                                   in library functions.
-* General Functions::              Functions that are of general use.
-* Strtonum Function::              A replacement for the built-in
-                                   @code{strtonum()} function.
-* Assert Function::                A function for assertions in @command{awk}
-                                   programs.
-* Round Function::                 A function for rounding if @code{sprintf()}
-                                   does not do it correctly.
-* Cliff Random Function::          The Cliff Random Number Generator.
-* Ordinal Functions::              Functions for using characters as numbers
-                                   and vice versa.
-* Join Function::                  A function to join an array into a string.
-* Gettimeofday Function::          A function to get formatted times.
-* Data File Management::           Functions for managing command-line data
-                                   files.
-* Filetrans Function::             A function for handling data file
-                                   transitions.
-* Rewind Function::                A function for rereading the current file.
-* File Checking::                  Checking that data files are readable.
-* Empty Files::                    Checking for zero-length files.
-* Ignoring Assigns::               Treating assignments as file names.
-* Getopt Function::                A function for processing command-line
-                                   arguments.
-* Passwd Functions::               Functions for getting user information.
-* Group Functions::                Functions for getting group information.
-* Running Examples::               How to run these examples.
-* Clones::                         Clones of common utilities.
-* Cut Program::                    The @command{cut} utility.
-* Egrep Program::                  The @command{egrep} utility.
-* Id Program::                     The @command{id} utility.
-* Split Program::                  The @command{split} utility.
-* Tee Program::                    The @command{tee} utility.
-* Uniq Program::                   The @command{uniq} utility.
-* Wc Program::                     The @command{wc} utility.
-* Miscellaneous Programs::         Some interesting @command{awk} programs.
-* Dupword Program::                Finding duplicated words in a document.
-* Alarm Program::                  An alarm clock.
-* Translate Program::              A program similar to the @command{tr}
-                                   utility.
-* Labels Program::                 Printing mailing labels.
-* Word Sorting::                   A program to produce a word usage count.
-* History Sorting::                Eliminating duplicate entries from a
-                                   history file.
-* Extract Program::                Pulling out programs from Texinfo source
-                                   files.
-* Simple Sed::                     A Simple Stream Editor.
-* Igawk Program::                  A wrapper for @command{awk} that includes
-                                   files.
-* Anagram Program::                Finding anagrams from a dictionary.
-* Signature Program::              People do amazing things with too much time
-                                   on their hands.
-* Debugging::                      Introduction to @command{dgawk}.
-* Debugging Concepts::             Debugging In General.
-* Debugging Terms::                Additional Debugging Concepts.
-* Awk Debugging::                  Awk Debugging.
-* Sample dgawk session::           Sample @command{dgawk} session.
-* dgawk invocation::               @command{dgawk} Invocation.
-* Finding The Bug::                Finding The Bug.
-* List of Debugger Commands::      Main @command{dgawk} Commands.
-* Breakpoint Control::             Control of breakpoints.
-* Dgawk Execution Control::        Control of execution.
-* Viewing And Changing Data::      Viewing and changing data.
-* Dgawk Stack::                    Dealing with the stack.
-* Dgawk Info::                     Obtaining information about the program and
-                                   the debugger state.
-* Miscellaneous Dgawk Commands::   Miscellaneous Commands.
-* Readline Support::               Readline Support.
-* Dgawk Limitations::              Limitations and future plans.
-* V7/SVR3.1::                      The major changes between V7 and System V
-                                   Release 3.1.
-* SVR4::                           Minor changes between System V Releases 3.1
-                                   and 4.
-* POSIX::                          New features from the POSIX standard.
-* BTL::                            New features from Brian Kernighan's
-                                   version of @command{awk}.
-* POSIX/GNU::                      The extensions in @command{gawk} not in
-                                   POSIX @command{awk}.
-* Contributors::                   The major contributors to @command{gawk}.
-* Common Extensions::              Common Extensions Summary.
-* Gawk Distribution::              What is in the @command{gawk} distribution.
-* Getting::                        How to get the distribution.
-* Extracting::                     How to extract the distribution.
-* Distribution contents::          What is in the distribution.
-* Unix Installation::              Installing @command{gawk} under various
-                                   versions of Unix.
-* Quick Installation::             Compiling @command{gawk} under Unix.
-* Additional Configuration Options:: Other compile-time options.
-* Configuration Philosophy::       How it's all supposed to work.
-* Non-Unix Installation::          Installation on Other Operating Systems.
-* PC Installation::                Installing and Compiling @command{gawk} on
-                                   MS-DOS and OS/2.
-* PC Binary Installation::         Installing a prepared distribution.
-* PC Compiling::                   Compiling @command{gawk} for MS-DOS,
-                                   Windows32, and OS/2.
-* PC Testing::                     Testing @command{gawk} on PC
-                                   Operating Systems.
-* PC Using::                       Running @command{gawk} on MS-DOS, Windows32
-                                   and OS/2.
-* Cygwin::                         Building and running @command{gawk} for
-                                   Cygwin.
-* MSYS::                           Using @command{gawk} In The MSYS
-                                   Environment.
-* VMS Installation::               Installing @command{gawk} on VMS.
-* VMS Compilation::                How to compile @command{gawk} under VMS.
-* VMS Installation Details::       How to install @command{gawk} under VMS.
-* VMS Running::                    How to run @command{gawk} under VMS.
-* VMS Old Gawk::                   An old version comes with some VMS systems.
-* Bugs::                           Reporting Problems and Bugs.
-* Other Versions::                 Other freely available @command{awk}
-                                   implementations.
-* Compatibility Mode::             How to disable certain @command{gawk}
-                                   extensions.
-* Additions::                      Making Additions To @command{gawk}.
-* Accessing The Source::           Accessing the Git repository.
-* Adding Code::                    Adding code to the main body of
-                                   @command{gawk}.
-* New Ports::                      Porting @command{gawk} to a new operating
-                                   system.
-* Dynamic Extensions::             Adding new built-in functions to
-                                   @command{gawk}.
-* Internals::                      A brief look at some @command{gawk}
-                                   internals.
-* Plugin License::                 A note about licensing.
-* Sample Library::                 A example of new functions.
-* Internal File Description::      What the new functions will do.
-* Internal File Ops::              The code for internal file operations.
-* Using Internal File Ops::        How to use an external extension.
-* Future Extensions::              New features that may be implemented one
-                                   day.
-* Basic High Level::               The high level view.
-* Basic Data Typing::              A very quick intro to data types.
-* Floating Point Issues::          Stuff to know about floating-point numbers.
-* String Conversion Precision::    The String Value Can Lie.
-* Unexpected Results::             Floating Point Numbers Are Not Abstract
-                                   Numbers.
-* POSIX Floating Point Problems::  Standards Versus Existing Practice.
+* History::                            The history of @command{gawk} and
+                                       @command{awk}.
+* Names::                              What name to use to find @command{awk}.
+* This Manual::                        Using this @value{DOCUMENT}. Includes
+                                       sample input files that you can use.
+* Conventions::                        Typographical Conventions.
+* Manual History::                     Brief history of the GNU project and
+                                       this @value{DOCUMENT}.
+* How To Contribute::                  Helping to save the world.
+* Acknowledgments::                    Acknowledgments.
+* Running gawk::                       How to run @command{gawk} programs;
+                                       includes command-line syntax.
+* One-shot::                           Running a short throwaway @command{awk}
+                                       program.
+* Read Terminal::                      Using no input files (input from
+                                       terminal instead).
+* Long::                               Putting permanent @command{awk}
+                                       programs in files.
+* Executable Scripts::                 Making self-contained @command{awk}
+                                       programs.
+* Comments::                           Adding documentation to @command{gawk}
+                                       programs.
+* Quoting::                            More discussion of shell quoting
+                                       issues.
+* DOS Quoting::                        Quoting in Windows Batch Files.
+* Sample Data Files::                  Sample data files for use in the
+                                       @command{awk} programs illustrated in
+                                       this @value{DOCUMENT}.
+* Very Simple::                        A very simple example.
+* Two Rules::                          A less simple one-line example using
+                                       two rules.
+* More Complex::                       A more complex example.
+* Statements/Lines::                   Subdividing or combining statements
+                                       into lines.
+* Other Features::                     Other Features of @command{awk}.
+* When::                               When to use @command{gawk} and when to
+                                       use other things.
+* Command Line::                       How to run @command{awk}.
+* Options::                            Command-line options and their
+                                       meanings.
+* Other Arguments::                    Input file names and variable
+                                       assignments.
+* Naming Standard Input::              How to specify standard input with
+                                       other files.
+* Environment Variables::              The environment variables
+                                       @command{gawk} uses.
+* AWKPATH Variable::                   Searching directories for @command{awk}
+                                       programs.
+* Other Environment Variables::        The environment variables.
+* Exit Status::                        @command{gawk}'s exit status.
+* Include Files::                      Including other files into your
+                                       program.
+* Obsolete::                           Obsolete Options and/or features.
+* Undocumented::                       Undocumented Options and Features.
+* Regexp Usage::                       How to Use Regular Expressions.
+* Escape Sequences::                   How to write nonprinting characters.
+* Regexp Operators::                   Regular Expression Operators.
+* Bracket Expressions::                What can go between @samp{[...]}.
+* GNU Regexp Operators::               Operators specific to GNU software.
+* Case-sensitivity::                   How to do case-insensitive matching.
+* Leftmost Longest::                   How much text matches.
+* Computed Regexps::                   Using Dynamic Regexps.
+* Locales::                            How the locale affects things.
+* Records::                            Controlling how data is split into
+                                       records.
+* Fields::                             An introduction to fields.
+* Nonconstant Fields::                 Nonconstant Field Numbers.
+* Changing Fields::                    Changing the Contents of a Field.
+* Field Separators::                   The field separator and how to change
+                                       it.
+* Default Field Splitting::            How fields are normally separated.
+* Regexp Field Splitting::             Using regexps as the field separator.
+* Single Character Fields::            Making each character a separate field.
+* Command Line Field Separator::       Setting @code{FS} from the
+                                       command-line.
+* Field Splitting Summary::            Some final points and a summary table.
+* Constant Size::                      Reading constant width data.
+* Splitting By Content::               Defining Fields By Content
+* Multiple Line::                      Reading multi-line records.
+* Getline::                            Reading files under explicit program
+                                       control using the @code{getline}
+                                       function.
+* Plain Getline::                      Using @code{getline} with no arguments.
+* Getline/Variable::                   Using @code{getline} into a variable.
+* Getline/File::                       Using @code{getline} from a file.
+* Getline/Variable/File::              Using @code{getline} into a variable
+                                       from a file.
+* Getline/Pipe::                       Using @code{getline} from a pipe.
+* Getline/Variable/Pipe::              Using @code{getline} into a variable
+                                       from a pipe.
+* Getline/Coprocess::                  Using @code{getline} from a coprocess.
+* Getline/Variable/Coprocess::         Using @code{getline} into a variable
+                                       from a coprocess.
+* Getline Notes::                      Important things to know about
+                                       @code{getline}.
+* Getline Summary::                    Summary of @code{getline} Variants.
+* Command line directories::           What happens if you put a directory on
+                                       the command line.
+* Print::                              The @code{print} statement.
+* Print Examples::                     Simple examples of @code{print}
+                                       statements.
+* Output Separators::                  The output separators and how to change
+                                       them.
+* OFMT::                               Controlling Numeric Output With
+                                       @code{print}.
+* Printf::                             The @code{printf} statement.
+* Basic Printf::                       Syntax of the @code{printf} statement.
+* Control Letters::                    Format-control letters.
+* Format Modifiers::                   Format-specification modifiers.
+* Printf Examples::                    Several examples.
+* Redirection::                        How to redirect output to multiple
+                                       files and pipes.
+* Special Files::                      File name interpretation in
+                                       @command{gawk}. @command{gawk} allows
+                                       access to inherited file descriptors.
+* Special FD::                         Special files for I/O.
+* Special Network::                    Special files for network
+                                       communications.
+* Special Caveats::                    Things to watch out for.
+* Close Files And Pipes::              Closing Input and Output Files and
+                                       Pipes.
+* Values::                             Constants, Variables, and Regular
+                                       Expressions.
+* Constants::                          String, numeric and regexp constants.
+* Scalar Constants::                   Numeric and string constants.
+* Nondecimal-numbers::                 What are octal and hex numbers.
+* Regexp Constants::                   Regular Expression constants.
+* Using Constant Regexps::             When and how to use a regexp constant.
+* Variables::                          Variables give names to values for
+                                       later use.
+* Using Variables::                    Using variables in your programs.
+* Assignment Options::                 Setting variables on the command-line
+                                       and a summary of command-line syntax.
+                                       This is an advanced method of input.
+* Conversion::                         The conversion of strings to numbers
+                                       and vice versa.
+* All Operators::                      @command{gawk}'s operators.
+* Arithmetic Ops::                     Arithmetic operations (@samp{+},
+                                       @samp{-}, etc.)
+* Concatenation::                      Concatenating strings.
+* Assignment Ops::                     Changing the value of a variable or a
+                                       field.
+* Increment Ops::                      Incrementing the numeric value of a
+                                       variable.
+* Truth Values and Conditions::        Testing for true and false.
+* Truth Values::                       What is ``true'' and what is ``false''.
+* Typing and Comparison::              How variables acquire types and how
+                                       this affects comparison of numbers and
+                                       strings with @samp{<}, etc.
+* Variable Typing::                    String type versus numeric type.
+* Comparison Operators::               The comparison operators.
+* POSIX String Comparison::            String comparison with POSIX rules.
+* Boolean Ops::                        Combining comparison expressions using
+                                       boolean operators @samp{||} (``or''),
+                                       @samp{&&} (``and'') and @samp{!}
+                                       (``not'').
+* Conditional Exp::                    Conditional expressions select between
+                                       two subexpressions under control of a
+                                       third subexpression.
+* Function Calls::                     A function call is an expression.
+* Precedence::                         How various operators nest.
+* Pattern Overview::                   What goes into a pattern.
+* Regexp Patterns::                    Using regexps as patterns.
+* Expression Patterns::                Any expression can be used as a
+                                       pattern.
+* Ranges::                             Pairs of patterns specify record
+                                       ranges.
+* BEGIN/END::                          Specifying initialization and cleanup
+                                       rules.
+* Using BEGIN/END::                    How and why to use BEGIN/END rules.
+* I/O And BEGIN/END::                  I/O issues in BEGIN/END rules.
+* BEGINFILE/ENDFILE::                  Two special patterns for advanced
+                                       control.
+* Empty::                              The empty pattern, which matches every
+                                       record.
+* Using Shell Variables::              How to use shell variables with
+                                       @command{awk}.
+* Action Overview::                    What goes into an action.
+* Statements::                         Describes the various control
+                                       statements in detail.
+* If Statement::                       Conditionally execute some
+                                       @command{awk} statements.
+* While Statement::                    Loop until some condition is satisfied.
+* Do Statement::                       Do specified action while looping until
+                                       some condition is satisfied.
+* For Statement::                      Another looping statement, that
+                                       provides initialization and increment
+                                       clauses.
+* Switch Statement::                   Switch/case evaluation for conditional
+                                       execution of statements based on a
+                                       value.
+* Break Statement::                    Immediately exit the innermost
+                                       enclosing loop.
+* Continue Statement::                 Skip to the end of the innermost
+                                       enclosing loop.
+* Next Statement::                     Stop processing the current input
+                                       record.
+* Nextfile Statement::                 Stop processing the current file.
+* Exit Statement::                     Stop execution of @command{awk}.
+* Built-in Variables::                 Summarizes the built-in variables.
+* User-modified::                      Built-in variables that you change to
+                                       control @command{awk}.
+* Auto-set::                           Built-in variables where @command{awk}
+                                       gives you information.
+* ARGC and ARGV::                      Ways to use @code{ARGC} and
+                                       @code{ARGV}.
+* Array Basics::                       The basics of arrays.
+* Array Intro::                        Introduction to Arrays
+* Reference to Elements::              How to examine one element of an array.
+* Assigning Elements::                 How to change an element of an array.
+* Array Example::                      Basic Example of an Array
+* Scanning an Array::                  A variation of the @code{for}
+                                       statement. It loops through the indices
+                                       of an array's existing elements.
+* Delete::                             The @code{delete} statement removes an
+                                       element from an array.
+* Numeric Array Subscripts::           How to use numbers as subscripts in
+                                       @command{awk}.
+* Uninitialized Subscripts::           Using Uninitialized variables as
+                                       subscripts.
+* Multi-dimensional::                  Emulating multidimensional arrays in
+                                       @command{awk}.
+* Multi-scanning::                     Scanning multidimensional arrays.
+* Arrays of Arrays::                   True multidimensional arrays.
+* Built-in::                           Summarizes the built-in functions.
+* Calling Built-in::                   How to call built-in functions.
+* Numeric Functions::                  Functions that work with numbers,
+                                       including @code{int()}, @code{sin()}
+                                       and @code{rand()}.
+* String Functions::                   Functions for string manipulation, such
+                                       as @code{split()}, @code{match()} and
+                                       @code{sprintf()}.
+* Gory Details::                       More than you want to know about
+                                       @samp{\} and @samp{&} with
+                                       @code{sub()}, @code{gsub()}, and
+                                       @code{gensub()}.
+* I/O Functions::                      Functions for files and shell commands.
+* Time Functions::                     Functions for dealing with timestamps.
+* Bitwise Functions::                  Functions for bitwise operations.
+* Type Functions::                     Functions for type information.
+* I18N Functions::                     Functions for string translation.
+* User-defined::                       Describes User-defined functions in
+                                       detail.
+* Definition Syntax::                  How to write definitions and what they
+                                       mean.
+* Function Example::                   An example function definition and what
+                                       it does.
+* Function Caveats::                   Things to watch out for.
+* Calling A Function::                 Don't use spaces.
+* Variable Scope::                     Controlling variable scope.
+* Pass By Value/Reference::            Passing parameters.
+* Return Statement::                   Specifying the value a function
+                                       returns.
+* Dynamic Typing::                     How variable types can change at
+                                       runtime.
+* Indirect Calls::                     Choosing the function to call at
+                                       runtime.
+* I18N and L10N::                      Internationalization and Localization.
+* Explaining gettext::                 How GNU @code{gettext} works.
+* Programmer i18n::                    Features for the programmer.
+* Translator i18n::                    Features for the translator.
+* String Extraction::                  Extracting marked strings.
+* Printf Ordering::                    Rearranging @code{printf} arguments.
+* I18N Portability::                   @command{awk}-level portability issues.
+* I18N Example::                       A simple i18n example.
+* Gawk I18N::                          @command{gawk} is also
+                                       internationalized.
+* Nondecimal Data::                    Allowing nondecimal input data.
+* Array Sorting::                      Facilities for controlling array
+                                       traversal and sorting arrays.
+* Controlling Array Traversal::        How to use PROCINFO["sorted_in"].
+* Controlling Scanning With A Function:: Using a function to control scanning.
+* Controlling Scanning::               Controlling the order in which arrays
+                                       are scanned.
+* Array Sorting Functions::            How to use @code{asort()} and
+                                       @code{asorti()}.
+* Two-way I/O::                        Two-way communications with another
+                                       process.
+* TCP/IP Networking::                  Using @command{gawk} for network
+                                       programming.
+* Profiling::                          Profiling your @command{awk} programs.
+* Library Names::                      How to best name private global
+                                       variables in library functions.
+* General Functions::                  Functions that are of general use.
+* Strtonum Function::                  A replacement for the built-in
+                                       @code{strtonum()} function.
+* Assert Function::                    A function for assertions in
+                                       @command{awk} programs.
+* Round Function::                     A function for rounding if
+                                       @code{sprintf()} does not do it
+                                       correctly.
+* Cliff Random Function::              The Cliff Random Number Generator.
+* Ordinal Functions::                  Functions for using characters as
+                                       numbers and vice versa.
+* Join Function::                      A function to join an array into a
+                                       string.
+* Gettimeofday Function::              A function to get formatted times.
+* Data File Management::               Functions for managing command-line
+                                       data files.
+* Filetrans Function::                 A function for handling data file
+                                       transitions.
+* Rewind Function::                    A function for rereading the current
+                                       file.
+* File Checking::                      Checking that data files are readable.
+* Empty Files::                        Checking for zero-length files.
+* Ignoring Assigns::                   Treating assignments as file names.
+* Getopt Function::                    A function for processing command-line
+                                       arguments.
+* Passwd Functions::                   Functions for getting user information.
+* Group Functions::                    Functions for getting group
+                                       information.
+* Walking Arrays::                     A function to walk arrays of arrays.
+* Running Examples::                   How to run these examples.
+* Clones::                             Clones of common utilities.
+* Cut Program::                        The @command{cut} utility.
+* Egrep Program::                      The @command{egrep} utility.
+* Id Program::                         The @command{id} utility.
+* Split Program::                      The @command{split} utility.
+* Tee Program::                        The @command{tee} utility.
+* Uniq Program::                       The @command{uniq} utility.
+* Wc Program::                         The @command{wc} utility.
+* Miscellaneous Programs::             Some interesting @command{awk}
+                                       programs.
+* Dupword Program::                    Finding duplicated words in a document.
+* Alarm Program::                      An alarm clock.
+* Translate Program::                  A program similar to the @command{tr}
+                                       utility.
+* Labels Program::                     Printing mailing labels.
+* Word Sorting::                       A program to produce a word usage
+                                       count.
+* History Sorting::                    Eliminating duplicate entries from a
+                                       history file.
+* Extract Program::                    Pulling out programs from Texinfo
+                                       source files.
+* Simple Sed::                         A Simple Stream Editor.
+* Igawk Program::                      A wrapper for @command{awk} that
+                                       includes files.
+* Anagram Program::                    Finding anagrams from a dictionary.
+* Signature Program::                  People do amazing things with too much
+                                       time on their hands.
+* Debugging::                          Introduction to @command{dgawk}.
+* Debugging Concepts::                 Debugging In General.
+* Debugging Terms::                    Additional Debugging Concepts.
+* Awk Debugging::                      Awk Debugging.
+* Sample dgawk session::               Sample @command{dgawk} session.
+* dgawk invocation::                   @command{dgawk} Invocation.
+* Finding The Bug::                    Finding The Bug.
+* List of Debugger Commands::          Main @command{dgawk} Commands.
+* Breakpoint Control::                 Control of breakpoints.
+* Dgawk Execution Control::            Control of execution.
+* Viewing And Changing Data::          Viewing and changing data.
+* Dgawk Stack::                        Dealing with the stack.
+* Dgawk Info::                         Obtaining information about the program
+                                       and the debugger state.
+* Miscellaneous Dgawk Commands::       Miscellaneous Commands.
+* Readline Support::                   Readline Support.
+* Dgawk Limitations::                  Limitations and future plans.
+* V7/SVR3.1::                          The major changes between V7 and System
+                                       V Release 3.1.
+* SVR4::                               Minor changes between System V Releases
+                                       3.1 and 4.
+* POSIX::                              New features from the POSIX standard.
+* BTL::                                New features from Brian Kernighan's
+                                       version of @command{awk}.
+* POSIX/GNU::                          The extensions in @command{gawk} not in
+                                       POSIX @command{awk}.
+* Common Extensions::                  Common Extensions Summary.
+* Contributors::                       The major contributors to
+                                       @command{gawk}.
+* Gawk Distribution::                  What is in the @command{gawk}
+                                       distribution.
+* Getting::                            How to get the distribution.
+* Extracting::                         How to extract the distribution.
+* Distribution contents::              What is in the distribution.
+* Unix Installation::                  Installing @command{gawk} under various
+                                       versions of Unix.
+* Quick Installation::                 Compiling @command{gawk} under Unix.
+* Additional Configuration Options::   Other compile-time options.
+* Configuration Philosophy::           How it's all supposed to work.
+* Non-Unix Installation::              Installation on Other Operating
+                                       Systems.
+* PC Installation::                    Installing and Compiling @command{gawk}
+                                       on MS-DOS and OS/2.
+* PC Binary Installation::             Installing a prepared distribution.
+* PC Compiling::                       Compiling @command{gawk} for MS-DOS,
+                                       Windows32, and OS/2.
+* PC Testing::                         Testing @command{gawk} on PC systems.
+* PC Using::                           Running @command{gawk} on MS-DOS,
+                                       Windows32 and OS/2.
+* Cygwin::                             Building and running @command{gawk} for
+                                       Cygwin.
+* MSYS::                               Using @command{gawk} In The MSYS
+                                       Environment.
+* VMS Installation::                   Installing @command{gawk} on VMS.
+* VMS Compilation::                    How to compile @command{gawk} under
+                                       VMS.
+* VMS Installation Details::           How to install @command{gawk} under
+                                       VMS.
+* VMS Running::                        How to run @command{gawk} under VMS.
+* VMS Old Gawk::                       An old version comes with some VMS
+                                       systems.
+* Bugs::                               Reporting Problems and Bugs.
+* Other Versions::                     Other freely available @command{awk}
+                                       implementations.
+* Compatibility Mode::                 How to disable certain @command{gawk}
+                                       extensions.
+* Additions::                          Making Additions To @command{gawk}.
+* Accessing The Source::               Accessing the Git repository.
+* Adding Code::                        Adding code to the main body of
+                                       @command{gawk}.
+* New Ports::                          Porting @command{gawk} to a new
+                                       operating system.
+* Dynamic Extensions::                 Adding new built-in functions to
+                                       @command{gawk}.
+* Internals::                          A brief look at some @command{gawk}
+                                       internals.
+* Plugin License::                     A note about licensing.
+* Sample Library::                     A example of new functions.
+* Internal File Description::          What the new functions will do.
+* Internal File Ops::                  The code for internal file operations.
+* Using Internal File Ops::            How to use an external extension.
+* Future Extensions::                  New features that may be implemented
+                                       one day.
+* Basic High Level::                   The high level view.
+* Basic Data Typing::                  A very quick intro to data types.
+* Floating Point Issues::              Stuff to know about floating-point
+                                       numbers.
+* String Conversion Precision::        The String Value Can Lie.
+* Unexpected Results::                 Floating Point Numbers Are Not Abstract
+                                       Numbers.
+* POSIX Floating Point Problems::      Standards Versus Existing Practice.
 @end detailmenu
 @end menu
 
@@ -13036,7 +13079,6 @@ same @command{awk} program.
 * Uninitialized Subscripts::    Using Uninitialized variables as subscripts.
 * Multi-dimensional::           Emulating multidimensional arrays in
                                 @command{awk}.
-* Array Sorting::               Sorting array values and indices.
 * Arrays of Arrays::            True multidimensional arrays.
 @end menu
 
@@ -13378,11 +13420,6 @@ END @{
 @cindex elements in arrays, scanning
 @cindex arrays, scanning
 
address@hidden
-* Controlling Scanning::   Controlling the order in which arrays are scanned.
-* Controlling Scanning With A Function::  Using a function to control scanning.
address@hidden menu
-
 In programs that use arrays, it is often necessary to use a loop that
 executes once for each element of an array.  In other languages, where
 arrays are contiguous and indices are limited to positive integers,
@@ -13447,1245 +13484,1225 @@ the loop body; it is not predictable whether the 
@code{for} loop will
 reach them.  Similarly, changing @var{var} inside the loop may produce
 strange results.  It is best to avoid such things.
 
address@hidden Controlling Scanning
address@hidden Controlling Array Scanning Order
-
 As an extension, @command{gawk} makes it possible for you to
 loop over the elements of an array in order, based on the value of
 @code{PROCINFO["sorted_in"]} (@pxref{Auto-set}).
-Several sorting options are available:
-
address@hidden @samp
address@hidden ascending index string
-Order by indices compared as strings; this is the most basic sort.
-(Internally, array indices are always strings, so with @samp{a[2*5] = 1}
-the index is actually @code{"10"} rather than numeric 10.)
-
address@hidden ascending index number
-Order by indices but force them to be treated as numbers in the process.
-Any index with non-numeric value will end up positioned as if it were zero. 
-
address@hidden ascending value string
-Order by element values rather than by indices.  Scalar values are 
-compared as strings.  Subarrays, if present, come out last.
+This is an advanced feature, so discussion of it is delayed
+until @ref{Controlling Array Traversal}.
 
address@hidden ascending value number
-Order by values but force scalar values to be treated as numbers
-for the purpose of comparison.  If there are subarrays, those appear
-at the end of the sorted list.
+In addition, @command{gawk} provides built-in functions for
+sorting arrays; see @ref{Array Sorting Functions}.
 
address@hidden descending index string
-Reverse order from the most basic sort.
address@hidden Delete
address@hidden The @code{delete} Statement
address@hidden @code{delete} statement
address@hidden deleting elements in arrays
address@hidden arrays, elements, deleting
address@hidden elements in arrays, deleting
 
address@hidden descending index number
-Numeric indices ordered from high to low.
+To remove an individual element of an array, use the @code{delete}
+statement:
 
address@hidden descending value string
-Element values, treated as strings, ordered from high to low.  Subarrays, if 
present,
-come out first.
address@hidden
+delete @address@hidden
address@hidden example
 
address@hidden descending value number
-Element values, treated as numbers, ordered from high to low.  Subarrays, if 
present,
-come out first.
+Once an array element has been deleted, any value the element once
+had is no longer available. It is as if the element had never
+been referred to or been given a value.
+The following is an example of deleting elements in an array:
 
address@hidden unsorted
-Array elements are processed in arbitrary order, the normal @command{awk}
-behavior. You can also get the normal behavior by just
-deleting the @code{"sorted_in"} item from the @code{PROCINFO} array, if
-it previously had a value assigned to it.
address@hidden table
address@hidden
+for (i in frequencies)
+  delete frequencies[i]
address@hidden example
 
-The array traversal order is determined before the @code{for} loop
-starts to run. Changing @code{PROCINFO["sorted_in"]} in the loop body
-will not affect the loop.
address@hidden
+This example removes all the elements from the array @code{frequencies}.
+Once an element is deleted, a subsequent @code{for} statement to scan the array
+does not report that element and the @code{in} operator to check for
+the presence of that element returns zero (i.e., false):
 
-Portions of the sort specification string may be truncated or omitted.
-The default is @samp{ascending} for direction, @samp{index} for sort key type,
-and @samp{string} for comparison mode.  This implies that one can
-simply assign the empty string, "", instead of "ascending index string" to
address@hidden"sorted_in"]} for the same effect.
address@hidden
+delete foo[4]
+if (4 in foo)
+    print "This will never be printed"
address@hidden example
 
address@hidden null strings, array elements and
+It is important to note that deleting an element is @emph{not} the
+same as assigning it a null value (the empty string, @code{""}).
 For example:
 
 @example
-$ @kbd{gawk 'BEGIN @{}
-> @kbd{   a[4] = 4}
-> @kbd{   a[3] = 3}
-> @kbd{   for (i in a)}
-> @kbd{       print i, a[i]}
-> @address@hidden'}
address@hidden 4 4
address@hidden 3 3
-$ @kbd{gawk 'BEGIN @{}
-> @kbd{   PROCINFO["sorted_in"] = "asc index"}
-> @kbd{   a[4] = 4}
-> @kbd{   a[3] = 3}
-> @kbd{   for (i in a)}
-> @kbd{       print i, a[i]}
-> @address@hidden'}
address@hidden 3 3
address@hidden 4 4
+foo[4] = ""
+if (4 in foo)
+  print "This is printed, even though foo[4] is empty"
 @end example
 
-When sorting an array by element values, if a value happens to be
-a subarray then it is considered to be greater than any string or
-numeric value, regardless of what the subarray itself contains,
-and all subarrays are treated as being equal to each other.  Their 
-order relative to each other is determined by their index strings.
-
address@hidden Controlling Scanning With A Function
address@hidden Controlling Array Scanning Order With a User-defined Function
address@hidden lint checking, array elements
+It is not an error to delete an element that does not exist.
+However, if @option{--lint} is provided on the command line
+(@pxref{Options}),
address@hidden issues a warning message when an element that
+is not in the array is deleted.
 
-The value of @code{PROCINFO["sorted_in"]} can also be a function name.
-This lets you traverse an array based on any custom criterion.
-The array elements are ordered according to the return value of this
-function.  This comparison function should be defined with at least
-four arguments:
address@hidden common extensions, @code{delete} to delete entire arrays
address@hidden extensions, address@hidden @code{delete} to delete entire arrays
address@hidden arrays, deleting entire contents
address@hidden deleting entire arrays
address@hidden differences in @command{awk} and @command{gawk}, array elements, 
deleting
+All the elements of an array may be deleted with a single statement
address@hidden
+by leaving off the subscript in the @code{delete} statement,
+as follows:
 
 @example
-function comp_func(i1, v1, i2, v2)
address@hidden
-    @var{compare elements 1 and 2 in some fashion}
-    @var{return < 0; 0; or > 0}
address@hidden
+delete @var{array}
 @end example
 
-Here, @var{i1} and @var{i2} are the indices, and @var{v1} and @var{v2}
-are the corresponding values of the two elements being compared.
-Either @var{v1} or @var{v2}, or both, can be arrays if the array being
-traversed contains subarrays as values.  The three possible return values
-are interpreted this way:
+This ability is a @command{gawk} extension; it is not available in
+compatibility mode (@pxref{Options}).
 
address@hidden @bullet
address@hidden
-If the return value of @code{comp_func(i1, v1, i2, v2)} is less than zero,
-index @var{i1} comes before index @var{i2} during loop traversal.
+Using this version of the @code{delete} statement is about three times
+more efficient than the equivalent loop that deletes each element one
+at a time.
 
address@hidden
-If @code{comp_func(i1, v1, i2, v2)} returns zero, @var{i1} and @var{i2}
-come together but the relative order with respect to each other is undefined.
address@hidden portability, deleting array elements
address@hidden Brennan, Michael
+The following statement provides a portable but nonobvious way to clear
+out an array:@footnote{Thanks to Michael Brennan for pointing this out.}
 
address@hidden
-If the return value of @code{comp_func(i1, v1, i2, v2)} is greater than zero,
address@hidden comes after @var{i2}.
address@hidden itemize
address@hidden
+split("", array)
address@hidden example
 
-The following comparison function can be used to scan an array in
-numerical order of the indices:
address@hidden @code{split()} function, array address@hidden deleting
+The @code{split()} function
+(@pxref{String Functions})
+clears out the target array first. This call asks it to split
+apart the null string. Because there is no data to split out, the
+function simply clears the array and then returns.
+
address@hidden CAUTION
+Deleting an array does not change its type; you cannot
+delete an array and then use the array's name as a scalar
+(i.e., a regular variable). For example, the following does not work:
 
 @example
-function cmp_num_idx(i1, v1, i2, v2)
address@hidden
-    # numerical index comparison, ascending order
-    return (i1 - i2)
address@hidden
+a[1] = 3
+delete a
+a = 3
 @end example
address@hidden quotation
 
-This function traverses an array based on an order by element values
-rather than by indices:
address@hidden Numeric Array Subscripts
address@hidden Using Numbers to Subscript Arrays
+
address@hidden numbers, as array subscripts
address@hidden arrays, subscripts
address@hidden subscripts in arrays, numbers as
address@hidden @code{CONVFMT} variable, array subscripts and
+An important aspect to remember about arrays is that @emph{array subscripts
+are always strings}.  When a numeric value is used as a subscript,
+it is converted to a string value before being used for subscripting
+(@pxref{Conversion}).
+This means that the value of the built-in variable @code{CONVFMT} can
+affect how your program accesses elements of an array.  For example:
 
 @example
-function cmp_str_val(i1, v1, i2, v2)
address@hidden
-    # string value comparison, ascending order
-    v1 = v1 ""
-    v2 = v2 ""
-    if (v1 < v2)
-        return -1
-    return (v1 != v2)
address@hidden
+xyz = 12.153
+data[xyz] = 1
+CONVFMT = "%2.2f"
+if (xyz in data)
+    printf "%s is in data\n", xyz
+else
+    printf "%s is not in data\n", xyz
 @end example
 
-Here is a
-comparison function to make all numbers, and numeric strings without
-any leading or trailing spaces, come out first during loop traversal:  
address@hidden
+This prints @samp{12.15 is not in data}.  The first statement gives
address@hidden a numeric value.  Assigning to
address@hidden subscripts @code{data} with the string value @code{"12.153"}
+(using the default conversion value of @code{CONVFMT}, @code{"%.6g"}).
+Thus, the array element @code{data["12.153"]} is assigned the value one.
+The program then changes
+the value of @code{CONVFMT}.  The test @samp{(xyz in data)} generates a new
+string value from @code{xyz}---this time @code{"12.15"}---because the value of
address@hidden only allows two significant digits.  This test fails,
+since @code{"12.15"} is different from @code{"12.153"}.
+
address@hidden converting, during subscripting
+According to the rules for conversions
+(@pxref{Conversion}), integer
+values are always converted to strings as integers, no matter what the
+value of @code{CONVFMT} may happen to be.  So the usual case of
+the following works:
 
 @example
-function cmp_num_str_val(i1, v1, i2, v2,   n1, n2)
address@hidden
-    # numbers before string value comparison, ascending order
-    n1 = v1 + 0
-    n2 = v2 + 0
-    if (n1 == v1) 
-        return (n2 == v2) ? (n1 - n2) : -1
-    else if (n2 == v2)
-        return 1 
-    return (v1 < v2) ? -1 : (v1 != v2)
address@hidden
+for (i = 1; i <= maxsub; i++)
+    @ii{do something with} array[i]
 @end example
 
-Consider sorting the entries of a GNU/Linux system password file
-according to login names.  The following program which sorts records
-by a specific field position can be used for this purpose:   
+The ``integer values always convert to strings as integers'' rule
+has an additional consequence for array indexing.
+Octal and hexadecimal constants
+(@pxref{Nondecimal-numbers})
+are converted internally into numbers, and their original form
+is forgotten.
+This means, for example, that
address@hidden,
address@hidden,
+and
address@hidden
+all refer to the same element!
 
address@hidden
-# sort.awk --- simple program to sort by field position
-# field position is specified by the global variable POS
+As with many things in @command{awk}, the majority of the time
+things work as one would expect them to.  But it is useful to have a precise
+knowledge of the actual rules since they can sometimes have a subtle
+effect on your programs.
 
-function cmp_field(i1, v1, i2, v2)
address@hidden
-    # comparison by value, as string, and ascending order
-    return v1[POS] < v2[POS] ? -1 : (v1[POS] != v2[POS])
address@hidden
address@hidden Uninitialized Subscripts
address@hidden Using Uninitialized Variables as Subscripts
 
address@hidden
-    for (i = 1; i <= NF; i++)
-        a[NR][i] = $i
address@hidden
address@hidden variables, address@hidden as array subscripts
address@hidden uninitialized variables, as array subscripts
address@hidden subscripts in arrays, uninitialized variables as
address@hidden arrays, subscripts, uninitialized variables as
+Suppose it's necessary to write a program
+to print the input data in reverse order.
+A reasonable attempt to do so (with some test
+data) might look like this:
 
-END @{
-    PROCINFO["sorted_in"] = "cmp_field"
-    if (POS < 1 || POS > NF)
-        POS = 1
-    for (i in a) @{
-        for (j = 1; j <= NF; j++)
-            printf("%s%c", a[i][j], j < NF ? ":" : "")
-        print ""
-    @}
address@hidden
address@hidden
+$ @kbd{echo 'line 1}
+> @kbd{line 2}
+> @kbd{line 3' | awk '@{ l[lines] = $0; ++lines @}}
+> @kbd{END @{}
+>     @kbd{for (i = lines-1; i >= 0; --i)}
+>        @kbd{print l[i]}
+> @address@hidden'}
address@hidden line 3
address@hidden line 2
 @end example
 
-The first field in each entry of the password file is the user's login name,
-and the fields are seperated by colons.  Running the program produces the
-following output:
+Unfortunately, the very first line of input data did not come out in the
+output!
 
address@hidden
-$ @kbd{gawk -vPOS=1 -F: -f sort.awk /etc/passwd}
address@hidden adm:x:3:4:adm:/var/adm:/sbin/nologin
address@hidden apache:x:48:48:Apache:/var/www:/sbin/nologin
address@hidden avahi:x:70:70:Avahi daemon:/:/sbin/nologin
address@hidden
address@hidden example
+Upon first glance, we would think that this program should have worked.
+The variable @code{lines}
+is uninitialized, and uninitialized variables have the numeric value zero.
+So, @command{awk} should have printed the value of @code{l[0]}.
 
-The comparison normally should always return the same value when given a
-specific pair of array elements as its arguments.  If inconsistent
-results are returned then the order is undefined.  This behavior is
-sometimes exploited to introduce random order in otherwise seemingly
-ordered data:
+The issue here is that subscripts for @command{awk} arrays are @emph{always}
+strings. Uninitialized variables, when used as strings, have the
+value @code{""}, not zero.  Thus, @samp{line 1} ends up stored in
address@hidden""]}.
+The following version of the program works correctly:
 
 @example
-function cmp_randomize(i1, v1, i2, v2)
address@hidden
-    # random order
-    return (2 - 4 * rand())
address@hidden l[lines++] = $0 @}
+END @{
+    for (i = lines - 1; i >= 0; --i)
+       print l[i]
 @}
 @end example
 
-As mentioned above, the order of the indices is arbitrary if two
-elements compare equal.  This is usually not a problem, but letting
-the tied elements come out in arbitrary order can be an issue, especially
-when comparing item values.  The partial ordering of the equal elements
-may change during the next loop traversal, if other elements are added or
-removed from the array.  One way to resolve ties when comparing elements
-with otherwise equal values is to include the indices in the comparison
-rules.  Note that doing this may make the loop traversal less efficient,
-so consider it only if necessary.  The following comparison functions
-force a deterministic order, and are based on the fact that the
-indices of two elements are never equal:
-
address@hidden
-function cmp_numeric(i1, v1, i2, v2)
address@hidden
-    # numerical value (and index) comparison, descending order
-    return (v1 != v2) ? (v2 - v1) : (i2 - i1)
address@hidden
+Here, the @samp{++} forces @code{lines} to be numeric, thus making
+the ``old value'' numeric zero. This is then converted to @code{"0"}
+as the array subscript.
 
-function cmp_string(i1, v1, i2, v2)
address@hidden
-    # string value (and index) comparison, descending order
-    v1 = v1 i1
-    v2 = v2 i2
-    return (v1 > v2) ? -1 : (v1 != v2)
address@hidden
address@hidden example
address@hidden null strings, as array subscripts
address@hidden dark corner, array subscripts
address@hidden lint checking, array subscripts
+Even though it is somewhat unusual, the null string
+(@code{""}) is a valid array subscript.
address@hidden
address@hidden warns about the use of the null string as a subscript
+if @option{--lint} is provided
+on the command line (@pxref{Options}).
 
address@hidden Avoid using the term ``stable'' when describing the 
unpredictable behavior
address@hidden if two items compare equal.  Usually, the goal of a "stable 
algorithm"
address@hidden is to maintain the original order of the items, which is a 
meaningless
address@hidden concept for a list constructed from a hash.
address@hidden Multi-dimensional
address@hidden Multidimensional Arrays
 
-A custom comparison function can often simplify ordered loop
-traversal, and the the sky is really the limit when it comes to
-designing such a function.
address@hidden
+* Multi-scanning::              Scanning multidimensional arrays.
address@hidden menu
 
-When string comparisons are made during a sort, either for element
-values where one or both aren't numbers, or for element indices
-handled as strings, the value of @code{IGNORECASE}
-(@pxref{Built-in Variables}) controls whether
-the comparisons treat corresponding uppercase and lowercase letters as
-equivalent or distinct.
address@hidden subscripts in arrays, multidimensional
address@hidden arrays, multidimensional
+A multidimensional array is an array in which an element is identified
+by a sequence of indices instead of a single index.  For example, a
+two-dimensional array requires two indices.  The usual way (in most
+languages, including @command{awk}) to refer to an element of a
+two-dimensional array named @code{grid} is with
address@hidden@var{x},@var{y}]}.
 
-All sorting based on @code{PROCINFO["sorted_in"]}
-is disabled in POSIX mode,
-since the @code{PROCINFO} array is not special in that case.
address@hidden @code{SUBSEP} variable, multidimensional arrays
+Multidimensional arrays are supported in @command{awk} through
+concatenation of indices into one string.
address@hidden converts the indices into strings
+(@pxref{Conversion}) and
+concatenates them together, with a separator between them.  This creates
+a single string that describes the values of the separate indices.  The
+combined string is used as a single index into an ordinary,
+one-dimensional array.  The separator used is the value of the built-in
+variable @code{SUBSEP}.
 
-As a side note, sorting the array indices before traversing
-the array has been reported to add 15% to 20% overhead to the
-execution time of @command{awk} programs. For this reason,
-sorted array traversal is not the default.
+For example, suppose we evaluate the expression @samp{foo[5,12] = "value"}
+when the value of @code{SUBSEP} is @code{"@@"}.  The numbers 5 and 12 are
+converted to strings and
+concatenated with an @samp{@@} between them, yielding @code{"5@@12"}; thus,
+the array element @code{foo["5@@12"]} is set to @code{"value"}.
 
address@hidden The @command{gawk}
address@hidden maintainers believe that only the people who wish to use a
address@hidden feature should have to pay for it.
+Once the element's value is stored, @command{awk} has no record of whether
+it was stored with a single index or a sequence of indices.  The two
+expressions @samp{foo[5,12]} and @address@hidden SUBSEP 12]}} are always
+equivalent.
 
address@hidden Delete
address@hidden The @code{delete} Statement
address@hidden @code{delete} statement
address@hidden deleting elements in arrays
address@hidden arrays, elements, deleting
address@hidden elements in arrays, deleting
+The default value of @code{SUBSEP} is the string @code{"\034"},
+which contains a nonprinting character that is unlikely to appear in an
address@hidden program or in most input data.
+The usefulness of choosing an unlikely character comes from the fact
+that index values that contain a string matching @code{SUBSEP} can lead to
+combined strings that are ambiguous.  Suppose that @code{SUBSEP} is
address@hidden"@@"}; then @address@hidden"a@@b", "c"]}} and @address@hidden"a",
+"b@@c"]}} are indistinguishable because both are actually
+stored as @samp{foo["a@@b@@c"]}.
 
-To remove an individual element of an array, use the @code{delete}
-statement:
+To test whether a particular index sequence exists in a
+multidimensional array, use the same operator (@code{in}) that is
+used for single dimensional arrays.  Write the whole sequence of indices
+in parentheses, separated by commas, as the left operand:
 
 @example
-delete @address@hidden
+(@var{subscript1}, @var{subscript2}, @dots{}) in @var{array}
 @end example
 
-Once an array element has been deleted, any value the element once
-had is no longer available. It is as if the element had never
-been referred to or been given a value.
-The following is an example of deleting elements in an array:
+The following example treats its input as a two-dimensional array of
+fields; it rotates this array 90 degrees clockwise and prints the
+result.  It assumes that all lines have the same number of
+elements:
 
 @example
-for (i in frequencies)
-  delete frequencies[i]
address@hidden
+     if (max_nf < NF)
+          max_nf = NF
+     max_nr = NR
+     for (x = 1; x <= NF; x++)
+          vector[x, NR] = $x
address@hidden
+
+END @{
+     for (x = 1; x <= max_nf; x++) @{
+          for (y = max_nr; y >= 1; --y)
+               printf("%s ", vector[x, y])
+          printf("\n")
+     @}
address@hidden
 @end example
 
 @noindent
-This example removes all the elements from the array @code{frequencies}.
-Once an element is deleted, a subsequent @code{for} statement to scan the array
-does not report that element and the @code{in} operator to check for
-the presence of that element returns zero (i.e., false):
+When given the input:
 
 @example
-delete foo[4]
-if (4 in foo)
-    print "This will never be printed"
+1 2 3 4 5 6
+2 3 4 5 6 1
+3 4 5 6 1 2
+4 5 6 1 2 3
 @end example
 
address@hidden null strings, array elements and
-It is important to note that deleting an element is @emph{not} the
-same as assigning it a null value (the empty string, @code{""}).
-For example:
address@hidden
+the program produces the following output:
 
 @example
-foo[4] = ""
-if (4 in foo)
-  print "This is printed, even though foo[4] is empty"
+4 3 2 1
+5 4 3 2
+6 5 4 3
+1 6 5 4
+2 1 6 5
+3 2 1 6
 @end example
 
address@hidden lint checking, array elements
-It is not an error to delete an element that does not exist.
-However, if @option{--lint} is provided on the command line
-(@pxref{Options}),
address@hidden issues a warning message when an element that
-is not in the array is deleted.
address@hidden Multi-scanning
address@hidden Scanning Multidimensional Arrays
 
address@hidden common extensions, @code{delete} to delete entire arrays
address@hidden extensions, address@hidden @code{delete} to delete entire arrays
address@hidden arrays, deleting entire contents
address@hidden deleting entire arrays
address@hidden differences in @command{awk} and @command{gawk}, array elements, 
deleting
-All the elements of an array may be deleted with a single statement
address@hidden
-by leaving off the subscript in the @code{delete} statement,
-as follows:
+There is no special @code{for} statement for scanning a
+``multidimensional'' array. There cannot be one, because, in truth, there
+are no multidimensional arrays or elements---there is only a
+multidimensional @emph{way of accessing} an array.
+
address@hidden subscripts in arrays, multidimensional, scanning
address@hidden arrays, multidimensional, scanning
+However, if your program has an array that is always accessed as
+multidimensional, you can get the effect of scanning it by combining
+the scanning @code{for} statement
+(@pxref{Scanning an Array}) with the
+built-in @code{split()} function
+(@pxref{String Functions}).
+It works in the following manner:
 
 @example
-delete @var{array}
+for (combined in array) @{
+    split(combined, separate, SUBSEP)
+    @dots{}
address@hidden
 @end example
 
-This ability is a @command{gawk} extension; it is not available in
-compatibility mode (@pxref{Options}).
-
-Using this version of the @code{delete} statement is about three times
-more efficient than the equivalent loop that deletes each element one
-at a time.
address@hidden
+This sets the variable @code{combined} to
+each concatenated combined index in the array, and splits it
+into the individual indices by breaking it apart where the value of
address@hidden appears.  The individual indices then become the elements of
+the array @code{separate}.
 
address@hidden portability, deleting array elements
address@hidden Brennan, Michael
-The following statement provides a portable but nonobvious way to clear
-out an array:@footnote{Thanks to Michael Brennan for pointing this out.}
+Thus, if a value is previously stored in @code{array[1, "foo"]}; then
+an element with index @code{"1\034foo"} exists in @code{array}.  (Recall
+that the default value of @code{SUBSEP} is the character with code 034.)
+Sooner or later, the @code{for} statement finds that index and does an
+iteration with the variable @code{combined} set to @code{"1\034foo"}.
+Then the @code{split()} function is called as follows:
 
 @example
-split("", array)
+split("1\034foo", separate, "\034")
 @end example
 
address@hidden @code{split()} function, array address@hidden deleting
-The @code{split()} function
-(@pxref{String Functions})
-clears out the target array first. This call asks it to split
-apart the null string. Because there is no data to split out, the
-function simply clears the array and then returns.
address@hidden
+The result is to set @code{separate[1]} to @code{"1"} and
address@hidden to @code{"foo"}.  Presto! The original sequence of
+separate indices is recovered.
 
address@hidden CAUTION
-Deleting an array does not change its type; you cannot
-delete an array and then use the array's name as a scalar
-(i.e., a regular variable). For example, the following does not work:
+
address@hidden Arrays of Arrays
address@hidden Arrays of Arrays
+
address@hidden supports arrays of
+arrays. Elements of a subarray are referred to by their own indices
+enclosed in square brackets, just like the elements of the main array.
+For example, the following creates a two-element subarray at index @samp{1}
+of the main array @code{a}:
 
 @example
-a[1] = 3
-delete a
-a = 3
+a[1][1] = 1
+a[1][2] = 2
 @end example
address@hidden quotation
 
address@hidden Numeric Array Subscripts
address@hidden Using Numbers to Subscript Arrays
+This simulates a true two-dimensional array. Each subarray element can
+contain another subarray as a value, which in turn can hold other arrays
+as well. In this way, you can create arrays of three or more dimensions.
+The indices can be any @command{awk} expression, including scalars
+separated by commas (that is, a regular @command{awk} simulated
+multidimensional subscript). So the following is valid in
address@hidden:
 
address@hidden numbers, as array subscripts
address@hidden arrays, subscripts
address@hidden subscripts in arrays, numbers as
address@hidden @code{CONVFMT} variable, array subscripts and
-An important aspect to remember about arrays is that @emph{array subscripts
-are always strings}.  When a numeric value is used as a subscript,
-it is converted to a string value before being used for subscripting
-(@pxref{Conversion}).
-This means that the value of the built-in variable @code{CONVFMT} can
-affect how your program accesses elements of an array.  For example:
address@hidden
+a[1][3][1, "name"] = "barney"
address@hidden example
+
+Each subarray and the main array can be of different length. In fact, the
+elements of an array or its subarray do not all have to have the same
+type. This means that the main array and any of its subarrays can be
+non-rectangular, or jagged in structure. One can assign a scalar value to
+the index @samp{4} of the main array @code{a}:
 
 @example
-xyz = 12.153
-data[xyz] = 1
-CONVFMT = "%2.2f"
-if (xyz in data)
-    printf "%s is in data\n", xyz
-else
-    printf "%s is not in data\n", xyz
+a[4] = "An element in a jagged array"
 @end example
+  
+The terms @dfn{dimension}, @dfn{row} and @dfn{column} are
+meaningless when applied
+to such an array, but we will use ``dimension'' henceforth to imply the
+maximum number of indices needed to refer to an existing element. The
+type of any element that has already been assigned cannot be changed
+by assigning a value of a different type. You have to first delete the
+current element, which effectively makes @command{gawk} forget about
+the element at that index:
 
address@hidden
-This prints @samp{12.15 is not in data}.  The first statement gives
address@hidden a numeric value.  Assigning to
address@hidden subscripts @code{data} with the string value @code{"12.153"}
-(using the default conversion value of @code{CONVFMT}, @code{"%.6g"}).
-Thus, the array element @code{data["12.153"]} is assigned the value one.
-The program then changes
-the value of @code{CONVFMT}.  The test @samp{(xyz in data)} generates a new
-string value from @code{xyz}---this time @code{"12.15"}---because the value of
address@hidden only allows two significant digits.  This test fails,
-since @code{"12.15"} is different from @code{"12.153"}.
address@hidden
+delete a[4]
+a[4][5][6][7] = "An element in a four-dimensional array"
address@hidden example
 
address@hidden converting, during subscripting
-According to the rules for conversions
-(@pxref{Conversion}), integer
-values are always converted to strings as integers, no matter what the
-value of @code{CONVFMT} may happen to be.  So the usual case of
-the following works:
address@hidden
+This removes the scalar value from index @samp{4} and then inserts a
+subarray of subarray of subarray containing a scalar. You can also
+delete an entire subarray or subarray of subarrays:
 
 @example
-for (i = 1; i <= maxsub; i++)
-    @ii{do something with} array[i]
+delete a[4][5]
+a[4][5] = "An element in subarray a[4]"
 @end example
 
-The ``integer values always convert to strings as integers'' rule
-has an additional consequence for array indexing.
-Octal and hexadecimal constants
-(@pxref{Nondecimal-numbers})
-are converted internally into numbers, and their original form
-is forgotten.
-This means, for example, that
address@hidden,
address@hidden,
-and
address@hidden
-all refer to the same element!
+But recall that you can not delete the main array @code{a} and then use it
+as a scalar.
 
-As with many things in @command{awk}, the majority of the time
-things work as one would expect them to.  But it is useful to have a precise
-knowledge of the actual rules since they can sometimes have a subtle
-effect on your programs.
+The built-in functions which take array arguments can also be used
+with subarrays. For example, the following code fragment uses @code{length()}
+(@pxref{String Functions})
+to determine the number of elements in the main array @code{a} and
+its subarrays:
 
address@hidden Uninitialized Subscripts
address@hidden Using Uninitialized Variables as Subscripts
address@hidden
+print length(a), length(a[1]), length(a[1][3])
address@hidden example
 
address@hidden variables, address@hidden as array subscripts
address@hidden uninitialized variables, as array subscripts
address@hidden subscripts in arrays, uninitialized variables as
address@hidden arrays, subscripts, uninitialized variables as
-Suppose it's necessary to write a program
-to print the input data in reverse order.
-A reasonable attempt to do so (with some test
-data) might look like this:
address@hidden
+This results in the following output for our main array @code{a}:
 
 @example
-$ @kbd{echo 'line 1}
-> @kbd{line 2}
-> @kbd{line 3' | awk '@{ l[lines] = $0; ++lines @}}
-> @kbd{END @{}
->     @kbd{for (i = lines-1; i >= 0; --i)}
->        @kbd{print l[i]}
-> @address@hidden'}
address@hidden line 3
address@hidden line 2
+2, 3, 1
 @end example
 
-Unfortunately, the very first line of input data did not come out in the
-output!
address@hidden
+The @address@hidden in @var{array}} expression
+(@pxref{Reference to Elements}) works similarly for both
+regular @command{awk}-style
+arrays and arrays of arrays. For example, the tests @samp{1 in a},
address@hidden in a[1]}, and @samp{(1, "name") in a[1][3]} all evaluate to
+one (true) for our array @code{a}.
 
-Upon first glance, we would think that this program should have worked.
-The variable @code{lines}
-is uninitialized, and uninitialized variables have the numeric value zero.
-So, @command{awk} should have printed the value of @code{l[0]}.
+The @samp{for (item in array)} statement (@pxref{Scanning an Array})
+can be nested to scan all the
+elements of an array of arrays if it is rectangular in structure. In order
+to print the contents (scalar values) of a two-dimensional array of arrays
+(i.e., in which each first-level element is itself an 
+array, not necessarily of the same length) 
+you could use the following code:
 
-The issue here is that subscripts for @command{awk} arrays are @emph{always}
-strings. Uninitialized variables, when used as strings, have the
-value @code{""}, not zero.  Thus, @samp{line 1} ends up stored in
address@hidden""]}.
-The following version of the program works correctly:
address@hidden
+for (i in array)
+    for (j in array[i])
+        print array[i][j] 
address@hidden example
+
+The @code{isarray()} function (@pxref{Type Functions})
+lets you test if an array element is itself an array:
 
 @example
address@hidden l[lines++] = $0 @}
-END @{
-    for (i = lines - 1; i >= 0; --i)
-       print l[i]
+for (i in array) @{
+    if (isarray(array[i]) @{
+        for (j in array[i]) @{
+            print array[i][j] 
+        @}
+    @}
 @}
 @end example
 
-Here, the @samp{++} forces @code{lines} to be numeric, thus making
-the ``old value'' numeric zero. This is then converted to @code{"0"}
-as the array subscript.
-
address@hidden null strings, as array subscripts
address@hidden dark corner, array subscripts
address@hidden lint checking, array subscripts
-Even though it is somewhat unusual, the null string
-(@code{""}) is a valid array subscript.
address@hidden
address@hidden warns about the use of the null string as a subscript
-if @option{--lint} is provided
-on the command line (@pxref{Options}).
+If the structure of a jagged array of arrays is known in advance,
+you can often devise workarounds using control statements. For example,
+the following code prints the elements of our main array @code{a}: 
 
address@hidden Multi-dimensional
address@hidden Multidimensional Arrays
-
address@hidden
-* Multi-scanning::              Scanning multidimensional arrays.
address@hidden menu
-
address@hidden subscripts in arrays, multidimensional
address@hidden arrays, multidimensional
-A multidimensional array is an array in which an element is identified
-by a sequence of indices instead of a single index.  For example, a
-two-dimensional array requires two indices.  The usual way (in most
-languages, including @command{awk}) to refer to an element of a
-two-dimensional array named @code{grid} is with
address@hidden@var{x},@var{y}]}.
-
address@hidden @code{SUBSEP} variable, multidimensional arrays
-Multidimensional arrays are supported in @command{awk} through
-concatenation of indices into one string.
address@hidden converts the indices into strings
-(@pxref{Conversion}) and
-concatenates them together, with a separator between them.  This creates
-a single string that describes the values of the separate indices.  The
-combined string is used as a single index into an ordinary,
-one-dimensional array.  The separator used is the value of the built-in
-variable @code{SUBSEP}.
address@hidden
+for (i in a) @{
+    for (j in a[i]) @{
+        if (j == 3) @{
+            for (k in a[i][j])
+                print a[i][j][k]
+        @} else
+            print a[i][j]
+    @} 
address@hidden
address@hidden example
 
-For example, suppose we evaluate the expression @samp{foo[5,12] = "value"}
-when the value of @code{SUBSEP} is @code{"@@"}.  The numbers 5 and 12 are
-converted to strings and
-concatenated with an @samp{@@} between them, yielding @code{"5@@12"}; thus,
-the array element @code{foo["5@@12"]} is set to @code{"value"}.
address@hidden
address@hidden Arrays}, for a user-defined function that will ``walk'' an
+arbitrarily-dimensioned array of arrays.
 
-Once the element's value is stored, @command{awk} has no record of whether
-it was stored with a single index or a sequence of indices.  The two
-expressions @samp{foo[5,12]} and @address@hidden SUBSEP 12]}} are always
-equivalent.
+Recall that a reference to an uninitialized array element yields a value
+of @code{""}, the null string. This has one important implication when you
+intend to use a subarray as an argument to a function, as illustrated by
+the following example:
 
-The default value of @code{SUBSEP} is the string @code{"\034"},
-which contains a nonprinting character that is unlikely to appear in an
address@hidden program or in most input data.
-The usefulness of choosing an unlikely character comes from the fact
-that index values that contain a string matching @code{SUBSEP} can lead to
-combined strings that are ambiguous.  Suppose that @code{SUBSEP} is
address@hidden"@@"}; then @address@hidden"a@@b", "c"]}} and @address@hidden"a",
-"b@@c"]}} are indistinguishable because both are actually
-stored as @samp{foo["a@@b@@c"]}.
address@hidden
+$ @kbd{gawk 'BEGIN @{ split("a b c d", b[1]); print b[1][1] @}'}
address@hidden gawk: cmd. line:1: fatal: split: second argument is not an array
address@hidden example
 
-To test whether a particular index sequence exists in a
-multidimensional array, use the same operator (@code{in}) that is
-used for single dimensional arrays.  Write the whole sequence of indices
-in parentheses, separated by commas, as the left operand:
+The way to work around this is to first force @code{b[1]} to be an array by
+creating an arbitrary index:
 
 @example
-(@var{subscript1}, @var{subscript2}, @dots{}) in @var{array}
+$ @kbd{gawk 'BEGIN @{ b[1][1] = ""; split("a b c d", b[1]); print b[1][1] @}'}
address@hidden a
 @end example
address@hidden ENDOFRANGE arrs
 
-The following example treats its input as a two-dimensional array of
-fields; it rotates this array 90 degrees clockwise and prints the
-result.  It assumes that all lines have the same number of
-elements:
address@hidden Functions
address@hidden Functions
 
address@hidden
address@hidden
-     if (max_nf < NF)
-          max_nf = NF
-     max_nr = NR
-     for (x = 1; x <= NF; x++)
-          vector[x, NR] = $x
address@hidden
address@hidden STARTOFRANGE funcbi
address@hidden functions, built-in
address@hidden STARTOFRANGE bifunc
address@hidden built-in functions
+This @value{CHAPTER} describes @command{awk}'s built-in functions,
+which fall into three categories: numeric, string, and I/O.
address@hidden provides additional groups of functions
+to work with values that represent time, do
+bit manipulation, sort arrays, and internationalize and localize programs.
 
-END @{
-     for (x = 1; x <= max_nf; x++) @{
-          for (y = max_nr; y >= 1; --y)
-               printf("%s ", vector[x, y])
-          printf("\n")
-     @}
address@hidden
address@hidden example
+Besides the built-in functions, @command{awk} has provisions for
+writing new functions that the rest of a program can use.
+The second half of this @value{CHAPTER} describes these
address@hidden functions.
 
address@hidden
-When given the input:
address@hidden
+* Built-in::                    Summarizes the built-in functions.
+* User-defined::                Describes User-defined functions in detail.
+* Indirect Calls::              Choosing the function to call at runtime.
address@hidden menu
 
address@hidden
-1 2 3 4 5 6
-2 3 4 5 6 1
-3 4 5 6 1 2
-4 5 6 1 2 3
address@hidden example
address@hidden Built-in
address@hidden Built-in Functions
 
address@hidden
-the program produces the following output:
address@hidden functions are always available for
+your @command{awk} program to call.  This @value{SECTION} defines all
+the built-in
+functions in @command{awk}; some of these are mentioned in other sections
+but are summarized here for your convenience.
 
address@hidden
-4 3 2 1
-5 4 3 2
-6 5 4 3
-1 6 5 4
-2 1 6 5
-3 2 1 6
address@hidden example
address@hidden
+* Calling Built-in::            How to call built-in functions.
+* Numeric Functions::           Functions that work with numbers, including
+                                @code{int()}, @code{sin()} and @code{rand()}.
+* String Functions::            Functions for string manipulation, such as
+                                @code{split()}, @code{match()} and
+                                @code{sprintf()}.
+* I/O Functions::               Functions for files and shell commands.
+* Time Functions::              Functions for dealing with timestamps.
+* Bitwise Functions::           Functions for bitwise operations.
+* Type Functions::              Functions for type information.
+* I18N Functions::              Functions for string translation.
address@hidden menu
 
address@hidden Multi-scanning
address@hidden Scanning Multidimensional Arrays
address@hidden Calling Built-in
address@hidden Calling Built-in Functions
 
-There is no special @code{for} statement for scanning a
-``multidimensional'' array. There cannot be one, because, in truth, there
-are no multidimensional arrays or elements---there is only a
-multidimensional @emph{way of accessing} an array.
+To call one of @command{awk}'s built-in functions, write the name of
+the function followed
+by arguments in parentheses.  For example, @samp{atan2(y + z, 1)}
+is a call to the function @code{atan2()} and has two arguments.
 
address@hidden subscripts in arrays, multidimensional, scanning
address@hidden arrays, multidimensional, scanning
-However, if your program has an array that is always accessed as
-multidimensional, you can get the effect of scanning it by combining
-the scanning @code{for} statement
-(@pxref{Scanning an Array}) with the
-built-in @code{split()} function
-(@pxref{String Functions}).
-It works in the following manner:
address@hidden programming conventions, functions, calling
address@hidden whitespace, address@hidden calling
+Whitespace is ignored between the built-in function name and the
+open parenthesis, but nonetheless it is good practice to avoid using whitespace
+there.  User-defined functions do not permit whitespace in this way, and
+it is easier to avoid mistakes by following a simple
+convention that always works---no whitespace after a function name.
+
address@hidden troubleshooting, @command{gawk}, fatal address@hidden function 
arguments
address@hidden @command{gawk}, function arguments and
address@hidden differences in @command{awk} and @command{gawk}, function 
arguments (@command{gawk})
+Each built-in function accepts a certain number of arguments.
+In some cases, arguments can be omitted. The defaults for omitted
+arguments vary from function to function and are described under the
+individual functions.  In some @command{awk} implementations, extra
+arguments given to built-in functions are ignored.  However, in @command{gawk},
+it is a fatal error to give extra arguments to a built-in function.
+
+When a function is called, expressions that create the function's actual
+parameters are evaluated completely before the call is performed.
+For example, in the following code fragment:
 
 @example
-for (combined in array) @{
-    split(combined, separate, SUBSEP)
-    @dots{}
address@hidden
+i = 4
+j = sqrt(i++)
 @end example
 
address@hidden evaluation order, functions
address@hidden functions, built-in, evaluation order
address@hidden built-in functions, evaluation order
 @noindent
-This sets the variable @code{combined} to
-each concatenated combined index in the array, and splits it
-into the individual indices by breaking it apart where the value of
address@hidden appears.  The individual indices then become the elements of
-the array @code{separate}.
-
-Thus, if a value is previously stored in @code{array[1, "foo"]}; then
-an element with index @code{"1\034foo"} exists in @code{array}.  (Recall
-that the default value of @code{SUBSEP} is the character with code 034.)
-Sooner or later, the @code{for} statement finds that index and does an
-iteration with the variable @code{combined} set to @code{"1\034foo"}.
-Then the @code{split()} function is called as follows:
+the variable @code{i} is incremented to the value five before @code{sqrt()}
+is called with a value of four for its actual parameter.
+The order of evaluation of the expressions used for the function's
+parameters is undefined.  Thus, avoid writing programs that
+assume that parameters are evaluated from left to right or from
+right to left.  For example:
 
 @example
-split("1\034foo", separate, "\034")
+i = 5
+j = atan2(i++, i *= 2)
 @end example
 
address@hidden
-The result is to set @code{separate[1]} to @code{"1"} and
address@hidden to @code{"foo"}.  Presto! The original sequence of
-separate indices is recovered.
+If the order of evaluation is left to right, then @code{i} first becomes
+6, and then 12, and @code{atan2()} is called with the two arguments 6
+and 12.  But if the order of evaluation is right to left, @code{i}
+first becomes 10, then 11, and @code{atan2()} is called with the
+two arguments 11 and 10.
 
address@hidden Array Sorting
address@hidden Sorting Array Values and Indices with @command{gawk}
address@hidden Numeric Functions
address@hidden Numeric Functions
 
address@hidden arrays, sorting
address@hidden @code{asort()} function (@command{gawk})
address@hidden @code{asort()} function (@command{gawk}), address@hidden sorting
address@hidden sort function, arrays, sorting
-The order in which an array is scanned with a @samp{for (i in array)}
-loop is essentially arbitrary.
-In most @command{awk} implementations, sorting an array requires
-writing a @code{sort} function.
-While this can be educational for exploring different sorting algorithms,
-usually that's not the point of the program.
address@hidden provides the built-in @code{asort()}
-and @code{asorti()} functions
-(@pxref{String Functions})
-for sorting arrays.  For example:
+The following list describes all of
+the built-in functions that work with numbers.
+Optional parameters are enclosed in square address@hidden ([ ]):}
 
address@hidden
address@hidden the array} data
-n = asort(data)
-for (i = 1; i <= n; i++)
-    @var{do something with} data[i]
address@hidden example
address@hidden @code
address@hidden atan2(@var{y}, @var{x})
address@hidden @code{atan2()} function
+Return the arctangent of @address@hidden / @var{x}} in radians.
 
-After the call to @code{asort()}, the array @code{data} is indexed from 1
-to some number @var{n}, the total number of elements in @code{data}.
-(This count is @code{asort()}'s return value.)
address@hidden @value{LEQ} @code{data[2]} @value{LEQ} @code{data[3]}, and so on.
-The array elements are compared as strings.
address@hidden cos(@var{x})
address@hidden @code{cos()} function
+Return the cosine of @var{x}, with @var{x} in radians.
 
address@hidden side effects, @code{asort()} function
-An important side effect of calling @code{asort()} is that
address@hidden array's original indices are irrevocably lost}.
-As this isn't always desirable, @code{asort()} accepts a
-second argument:
address@hidden exp(@var{x})
address@hidden @code{exp()} function
+Return the exponential of @var{x} (@code{e ^ @var{x}}) or report
+an error if @var{x} is out of range.  The range of values @var{x} can have
+depends on your machine's floating-point representation.
 
address@hidden
address@hidden the array} source
-n = asort(source, dest)
-for (i = 1; i <= n; i++)
-    @var{do something with} dest[i]
address@hidden example
address@hidden int(@var{x})
address@hidden @code{int()} function
+Return the nearest integer to @var{x}, located between @var{x} and zero and
+truncated toward zero.
 
-In this case, @command{gawk} copies the @code{source} array into the
address@hidden array and then sorts @code{dest}, destroying its indices.
-However, the @code{source} array is not affected.
+For example, @code{int(3)} is 3, @code{int(3.9)} is 3, @code{int(-3.9)}
+is @minus{}3, and @code{int(-3)} is @minus{}3 as well.
 
address@hidden()} and @code{asorti()} accept a third string argument
-to control the comparison rule for the array elements, and the direction
-of the sorted results.  The valid comparison modes are @samp{string} and 
@samp{number},
-and the direction can be either @samp{ascending} or @samp{descending}.   
-Either mode or direction, or both, can be omitted in which
-case the defaults, @samp{string} or @samp{ascending} is assumed
-for the comparison mode and the direction, respectively.  Seperate comparison
-mode from direction with a single space, and they can appear in any
-order.  To compare the elements as numbers, and to reverse the elements
-of the @code{dest} array, the call to asort in the above example can be
-replaced with:
address@hidden log(@var{x})
address@hidden @code{log()} function
+Return the natural logarithm of @var{x}, if @var{x} is positive;
+otherwise, report an error.
+
address@hidden rand()
address@hidden @code{rand()} function
address@hidden random numbers, @code{rand()}/@code{srand()} functions
+Return a random number.  The values of @code{rand()} are
+uniformly distributed between zero and one.
+The value could be zero but is never address@hidden C version of @code{rand()}
+on many Unix systems
+is known to produce fairly poor sequences of random numbers.
+However, nothing requires that an @command{awk} implementation use the C
address@hidden()} to implement the @command{awk} version of @code{rand()}.
+In fact, @command{gawk} uses the BSD @code{random()} function, which is
+considerably better than @code{rand()}, to produce random numbers.}
+
+Often random integers are needed instead.  Following is a user-defined function
+that can be used to obtain a random non-negative integer less than @var{n}:
 
 @example
-asort(source, dest, "descending number")
+function randint(n) @{
+     return int(n * rand())
address@hidden
 @end example
 
-The third argument to @code{asort()} can also be a user-defined
-function name which is used to order the array elements before
-constructing the result array.
address@hidden an Array}, for more information.
- 
address@hidden
+The multiplication produces a random number greater than zero and less
+than @code{n}.  Using @code{int()}, this result is made into
+an integer between zero and @code{n} @minus{} 1, inclusive.
 
-Often, what's needed is to sort on the values of the @emph{indices}
-instead of the values of the elements.
-To do that, use the
address@hidden()} function.  The interface is identical to that of
address@hidden()}, except that the index values are used for sorting, and
-become the values of the result array:
+The following example uses a similar function to produce random integers
+between one and @var{n}.  This program prints a new random number for
+each input record:
 
 @example
address@hidden source[$0] = some_func($0) @}
+# Function to roll a simulated die.
+function roll(n) @{ return 1 + int(rand() * n) @}
 
-END @{
-    n = asorti(source, dest)
-    for (i = 1; i <= n; i++) @{
-        @ii{Work with sorted indices directly:}
-        @var{do something with} dest[i]
-        @dots{}
-        @ii{Access original array via sorted indices:}
-        @var{do something with} source[dest[i]]
-    @}
+# Roll 3 six-sided dice and
+# print total number of points.
address@hidden
+      printf("%d points\n",
+             roll(6)+roll(6)+roll(6))
 @}
 @end example
 
-Sorting the array by replacing the indices provides maximal flexibility.
-To traverse the elements in decreasing order, use a loop that goes from
address@hidden down to 1, either over the elements or over the indices.  This
-is an alternative to specifying @samp{descending} for the sorting order
-using the optional third argument.
-
address@hidden reference counting, sorting arrays
-Copying array indices and elements isn't expensive in terms of memory.
-Internally, @command{gawk} maintains @dfn{reference counts} to data.
-For example, when @code{asort()} copies the first array to the second one,
-there is only one copy of the original array elements' data, even though
-both arrays use the values.
-
address@hidden Document It And Call It A Feature. Sigh.
address@hidden @command{gawk}, @code{IGNORECASE} variable in
address@hidden @code{IGNORECASE} variable
address@hidden arrays, sorting, @code{IGNORECASE} variable and
address@hidden @code{IGNORECASE} variable, array sorting and
-Because @code{IGNORECASE} affects string comparisons, the value
-of @code{IGNORECASE} also affects sorting for both @code{asort()} and 
@code{asorti()}.
-Note also that the locale's sorting order does @emph{not}
-come into play; comparisons are based on character values address@hidden
-is true because locale-based comparison occurs only when in POSIX
-compatibility mode, and since @code{asort()} and @code{asorti()} are
address@hidden extensions, they are not available in that case.}
-Caveat Emptor.
address@hidden numbers, random
address@hidden random numbers, seed of
address@hidden CAUTION
+In most @command{awk} implementations, including @command{gawk},
address@hidden()} starts generating numbers from the same
+starting number, or @dfn{seed}, each time you run @address@hidden@command{mawk}
+uses a different seed each time.}  Thus,
+a program generates the same results each time you run it.
+The numbers are random within one @command{awk} run but predictable
+from run to run.  This is convenient for debugging, but if you want
+a program to do different things each time it is used, you must change
+the seed to a value that is different in each run.  To do this,
+use @code{srand()}.
address@hidden quotation
 
address@hidden Arrays of Arrays
address@hidden Arrays of Arrays
address@hidden sin(@var{x})
address@hidden @code{sin()} function
+Return the sine of @var{x}, with @var{x} in radians.
 
address@hidden supports arrays of
-arrays. Elements of a subarray are referred to by their own indices
-enclosed in square brackets, just like the elements of the main array.
-For example, the following creates a two-element subarray at index @samp{1}
-of the main array @code{a}:
address@hidden sqrt(@var{x})
address@hidden @code{sqrt()} function
+Return the positive square root of @var{x}.
address@hidden prints a warning message
+if @var{x} is negative.  Thus, @code{sqrt(4)} is 2.
 
address@hidden
-a[1][1] = 1
-a[1][2] = 2
address@hidden example
address@hidden srand(@address@hidden@r{]})
address@hidden @code{srand()} function
+Set the starting point, or seed,
+for generating random numbers to the value @var{x}.
 
-This simulates a true two-dimensional array. Each subarray element can
-contain another subarray as a value, which in turn can hold other arrays
-as well. In this way, you can create arrays of three or more dimensions.
-The indices can be any @command{awk} expression, including scalars
-separated by commas (that is, a regular @command{awk} simulated
-multidimensional subscript). So the following is valid in
address@hidden:
+Each seed value leads to a particular sequence of random
address@hidden random numbers really are not truly
+random.  They are technically known as ``pseudorandom.''  This means
+that while the numbers in a sequence appear to be random, you can in
+fact generate the same sequence of random numbers over and over again.}
+Thus, if the seed is set to the same value a second time,
+the same sequence of random numbers is produced again.
 
address@hidden
-a[1][3][1, "name"] = "barney"
address@hidden example
address@hidden CAUTION
+Different @command{awk} implementations use different random-number
+generators internally.  Don't expect the same @command{awk} program
+to produce the same series of random numbers when executed by
+different versions of @command{awk}.
address@hidden quotation
 
-Each subarray and the main array can be of different length. In fact, the
-elements of an array or its subarray do not all have to have the same
-type. This means that the main array and any of its subarrays can be
-non-rectangular, or jagged in structure. One can assign a scalar value to
-the index @samp{4} of the main array @code{a}:
+If the argument @var{x} is omitted, as in @samp{srand()}, then the current
+date and time of day are used for a seed.  This is the way to get random
+numbers that are truly unpredictable.
 
address@hidden
-a[4] = "An element in a jagged array"
address@hidden example
-  
-The terms @dfn{dimension}, @dfn{row} and @dfn{column} are
-meaningless when applied
-to such an array, but we will use ``dimension'' henceforth to imply the
-maximum number of indices needed to refer to an existing element. The
-type of any element that has already been assigned cannot be changed
-by assigning a value of a different type. You have to first delete the
-current element, which effectively makes @command{gawk} forget about
-the element at that index:
+The return value of @code{srand()} is the previous seed.  This makes it
+easy to keep track of the seeds in case you need to consistently reproduce
+sequences of random numbers.
address@hidden table
 
address@hidden
-delete a[4]
-a[4][5][6][7] = "An element in a four-dimensional array"
address@hidden example
address@hidden String Functions
address@hidden String-Manipulation Functions
 
address@hidden
-This removes the scalar value from index @samp{4} and then inserts a
-subarray of subarray of subarray containing a scalar. You can also
-delete an entire subarray or subarray of subarrays:
+The functions in this @value{SECTION} look at or change the text of one or more
+strings.
address@hidden understands locales (@pxref{Locales}), and does all string 
processing in terms of
address@hidden, not @emph{bytes}.  This distinction is particularly important
+to understand for locales where one character
+may be represented by multiple bytes.  Thus, for example, @code{length()}
+returns the number of characters in a string, and not the number of bytes
+used to represent those characters, Similarly, @code{index()} works with
+character indices, and not byte indices.
 
address@hidden
-delete a[4][5]
-a[4][5] = "An element in subarray a[4]"
address@hidden example
+In the following list, optional parameters are enclosed in square 
address@hidden ([ ]).}
+Several functions perform string substitution; the full discussion is
+provided in the description of the @code{sub()} function, which comes
+towards the end since the list is presented in alphabetic order.
+Those functions that are specific to @command{gawk} are marked with a
+pound address@hidden (@samp{#}):}
 
-But recall that you can not delete the main array @code{a} and then use it
-as a scalar.
address@hidden
+* Gory Details::                More than you want to know about @samp{\} and
+                                @samp{&} with @code{sub()}, @code{gsub()}, and
+                                @code{gensub()}.
address@hidden menu
 
-The built-in functions which take array arguments can also be used
-with subarrays. For example, the following code fragment uses @code{length()}
-(@pxref{String Functions})
-to determine the number of elements in the main array @code{a} and
-its subarrays:
address@hidden @code
address@hidden asort(@var{source} @r{[}, @var{dest} @r{[}, @var{how}  @r{]} 
@r{]}) #
address@hidden arrays, elements, retrieving number of
address@hidden @code{asort()} function (@command{gawk})
address@hidden @command{gawk}, @code{IGNORECASE} variable in
address@hidden @code{IGNORECASE} variable
+Return the number of elements in the array @var{source}.
address@hidden sorts the contents of @var{source}
+and replaces the indices
+of the sorted values of @var{source} with sequential
+integers starting with one.  If the optional array @var{dest} is specified,
+then @var{source} is duplicated into @var{dest}.  @var{dest} is then
+sorted, leaving the indices of @var{source} unchanged.  The optional third
+argument @var{how} is a string which controls the rule for comparing values,
+and the sort direction.  A single space is required between the
+comparison mode, @samp{string} or @samp{number}, and the direction 
specification,
address@hidden or @samp{descending}.  You can omit direction and/or mode
+in which case it will default to @samp{ascending} and @samp{string}, 
respectively. 
+An empty string "" is the same as the default @code{"ascending string"}
+for the value of @var{how}.  If the @samp{source} array contains subarrays as 
values,
+they will come out last(first) in the @samp{dest} array for 
@samp{ascending}(@samp{descending})
+order specification.  The value of @code{IGNORECASE} affects the sorting.
+The third argument can also be a user-defined function name in which case
+the value returned by the function is used to order the array elements
+before constructing the result array.
address@hidden Sorting Functions}, for more information.
+
+For example, if the contents of @code{a} are as follows:
 
 @example
-print length(a), length(a[1]), length(a[1][3])
+a["last"] = "de"
+a["first"] = "sac"
+a["middle"] = "cul"
 @end example
 
 @noindent
-This results in the following output for our main array @code{a}:
+A call to @code{asort()}:
 
 @example
-2, 3, 1
+asort(a)
 @end example
 
 @noindent
-The @address@hidden in @var{array}} expression
-(@pxref{Reference to Elements}) works similarly for both
-regular @command{awk}-style
-arrays and arrays of arrays. For example, the tests @samp{1 in a},
address@hidden in a[1]}, and @samp{(1, "name") in a[1][3]} all evaluate to
-one (true) for our array @code{a}.
-
-The @samp{for (item in array)} statement (@pxref{Scanning an Array})
-can be nested to scan all the
-elements of an array of arrays if it is rectangular in structure. In order
-to print the contents (scalar values) of a two-dimensional array of arrays
-(i.e., in which each first-level element is itself an 
-array, not necessarily of the same length) 
-you could use the following code:
+results in the following contents of @code{a}:
 
 @example
-for (i in array)
-    for (j in array[i])
-        print array[i][j] 
+a[1] = "cul"
+a[2] = "de"
+a[3] = "sac"
 @end example
 
-The @code{isarray()} function (@pxref{Type Functions})
-lets you test if an array element is itself an array:
+In order to reverse the direction of the sorted results in the above example,
address@hidden()} can be called with three arguments as follows:
 
 @example
-for (i in array) @{
-    if (isarray(array[i]) @{
-        for (j in array[i]) @{
-            print array[i][j] 
-        @}
-    @}
address@hidden
+asort(a, a, "descending")
 @end example
 
-If the structure of a jagged array of arrays is known in advance,
-you can often devise workarounds using control statements. For example,
-the following code prints the elements of our main array @code{a}: 
+The @code{asort()} function is described in more detail in
address@hidden Sorting Functions}.
address@hidden()} is a @command{gawk} extension; it is not available
+in compatibility mode (@pxref{Options}).
 
address@hidden
-for (i in a) @{
-    for (j in a[i]) @{
-        if (j == 3) @{
-            for (k in a[i][j])
-                print a[i][j][k]
-        @} else
-            print a[i][j]
-    @} 
address@hidden
address@hidden example
address@hidden asorti(@var{source} @r{[}, @var{dest} @r{[}, @var{how}  @r{]} 
@r{]}) #
address@hidden @code{asorti()} function (@command{gawk})
+Return the number of elements in the array @var{source}.
+It works similarly to @code{asort()}, however, the @emph{indices}
+are sorted, instead of the values. (Here too,
address@hidden affects the sorting.)
 
address@hidden
address@hidden Arrays}, for a user-defined function that will ``walk'' an
-arbitrarily-dimensioned array of arrays.
+The @code{asorti()} function is described in more detail in
address@hidden Sorting Functions}.
address@hidden()} is a @command{gawk} extension; it is not available
+in compatibility mode (@pxref{Options}).
 
-Recall that a reference to an uninitialized array element yields a value
-of @code{""}, the null string. This has one important implication when you
-intend to use a subarray as an argument to a function, as illustrated by
-the following example:
address@hidden gensub(@var{regexp}, @var{replacement}, @var{how} @r{[}, 
@address@hidden) #
address@hidden @code{gensub()} function (@command{gawk})
+Search the target string @var{target} for matches of the regular
+expression @var{regexp}.  If @var{how} is a string beginning with
address@hidden or @samp{G} (short for ``global''), then replace all matches of 
@var{regexp} with
address@hidden  Otherwise, @var{how} is treated as a number indicating
+which match of @var{regexp} to replace. If no @var{target} is supplied,
+use @code{$0}.  It returns the modified string as the result
+of the function and the original target string is @emph{not} changed.
 
address@hidden
-$ @kbd{gawk 'BEGIN @{ split("a b c d", b[1]); print b[1][1] @}'}
address@hidden gawk: cmd. line:1: fatal: split: second argument is not an array
address@hidden example
address@hidden()} is a general substitution function.  It's purpose is
+to provide more features than the standard @code{sub()} and @code{gsub()}
+functions.
 
-The way to work around this is to first force @code{b[1]} to be an array by
-creating an arbitrary index:
address@hidden()} provides an additional feature that is not available
+in @code{sub()} or @code{gsub()}: the ability to specify components of a
+regexp in the replacement text.  This is done by using parentheses in
+the regexp to mark the components and then specifying @address@hidden
+in the replacement text, where @var{N} is a digit from 1 to 9.
+For example:
 
 @example
-$ @kbd{gawk 'BEGIN @{ b[1][1] = ""; split("a b c d", b[1]); print b[1][1] @}'}
address@hidden a
+$ @kbd{gawk '}
+> @kbd{BEGIN @{}
+>      @kbd{a = "abc def"}
+>      @kbd{b = gensub(/(.+) (.+)/, "\\2 \\1", "g", a)}
+>      @kbd{print b}
+> @address@hidden'}
address@hidden def abc
 @end example
address@hidden ENDOFRANGE arrs
-
address@hidden Functions
address@hidden Functions
-
address@hidden STARTOFRANGE funcbi
address@hidden functions, built-in
address@hidden STARTOFRANGE bifunc
address@hidden built-in functions
-This @value{CHAPTER} describes @command{awk}'s built-in functions,
-which fall into three categories: numeric, string, and I/O.
address@hidden provides additional groups of functions
-to work with values that represent time, do
-bit manipulation, sort arrays, and internationalize and localize programs.
-
-Besides the built-in functions, @command{awk} has provisions for
-writing new functions that the rest of a program can use.
-The second half of this @value{CHAPTER} describes these
address@hidden functions.
-
address@hidden
-* Built-in::                    Summarizes the built-in functions.
-* User-defined::                Describes User-defined functions in detail.
-* Indirect Calls::              Choosing the function to call at runtime.
address@hidden menu
 
address@hidden Built-in
address@hidden Built-in Functions
address@hidden
+As with @code{sub()}, you must type two backslashes in order
+to get one into the string.
+In the replacement text, the sequence @samp{\0} represents the entire
+matched text, as does the character @samp{&}.
 
address@hidden functions are always available for
-your @command{awk} program to call.  This @value{SECTION} defines all
-the built-in
-functions in @command{awk}; some of these are mentioned in other sections
-but are summarized here for your convenience.
+The following example shows how you can use the third argument to control
+which match of the regexp should be changed:
 
address@hidden
-* Calling Built-in::            How to call built-in functions.
-* Numeric Functions::           Functions that work with numbers, including
-                                @code{int()}, @code{sin()} and @code{rand()}.
-* String Functions::            Functions for string manipulation, such as
-                                @code{split()}, @code{match()} and
-                                @code{sprintf()}.
-* I/O Functions::               Functions for files and shell commands.
-* Time Functions::              Functions for dealing with timestamps.
-* Bitwise Functions::           Functions for bitwise operations.
-* Type Functions::              Functions for type information.
-* I18N Functions::              Functions for string translation.
address@hidden menu
address@hidden
+$ @kbd{echo a b c a b c |}
+> @kbd{gawk '@{ print gensub(/a/, "AA", 2) @}'}
address@hidden a b c AA b c
address@hidden example
 
address@hidden Calling Built-in
address@hidden Calling Built-in Functions
+In this case, @code{$0} is the default target string.
address@hidden()} returns the new string as its result, which is
+passed directly to @code{print} for printing.
 
-To call one of @command{awk}'s built-in functions, write the name of
-the function followed
-by arguments in parentheses.  For example, @samp{atan2(y + z, 1)}
-is a call to the function @code{atan2()} and has two arguments.
address@hidden @cindex automatic warnings
address@hidden @cindex warnings, automatic
+If the @var{how} argument is a string that does not begin with @samp{g} or
address@hidden, or if it is a number that is less than or equal to zero, only 
one
+substitution is performed.  If @var{how} is zero, @command{gawk} issues
+a warning message.
 
address@hidden programming conventions, functions, calling
address@hidden whitespace, address@hidden calling
-Whitespace is ignored between the built-in function name and the
-open parenthesis, but nonetheless it is good practice to avoid using whitespace
-there.  User-defined functions do not permit whitespace in this way, and
-it is easier to avoid mistakes by following a simple
-convention that always works---no whitespace after a function name.
+If @var{regexp} does not match @var{target}, @code{gensub()}'s return value
+is the original unchanged value of @var{target}.
 
address@hidden troubleshooting, @command{gawk}, fatal address@hidden function 
arguments
address@hidden @command{gawk}, function arguments and
address@hidden differences in @command{awk} and @command{gawk}, function 
arguments (@command{gawk})
-Each built-in function accepts a certain number of arguments.
-In some cases, arguments can be omitted. The defaults for omitted
-arguments vary from function to function and are described under the
-individual functions.  In some @command{awk} implementations, extra
-arguments given to built-in functions are ignored.  However, in @command{gawk},
-it is a fatal error to give extra arguments to a built-in function.
address@hidden()} is a @command{gawk} extension; it is not available
+in compatibility mode (@pxref{Options}).
 
-When a function is called, expressions that create the function's actual
-parameters are evaluated completely before the call is performed.
-For example, in the following code fragment:
address@hidden gsub(@var{regexp}, @var{replacement} @r{[}, @address@hidden)
address@hidden @code{gsub()} function
+Search @var{target} for
address@hidden of the longest, leftmost, @emph{nonoverlapping} matching
+substrings it can find and replace them with @var{replacement}.
+The @samp{g} in @code{gsub()} stands for
+``global,'' which means replace everywhere.  For example:
 
 @example
-i = 4
-j = sqrt(i++)
address@hidden gsub(/Britain/, "United Kingdom"); print @}
 @end example
 
address@hidden evaluation order, functions
address@hidden functions, built-in, evaluation order
address@hidden built-in functions, evaluation order
 @noindent
-the variable @code{i} is incremented to the value five before @code{sqrt()}
-is called with a value of four for its actual parameter.
-The order of evaluation of the expressions used for the function's
-parameters is undefined.  Thus, avoid writing programs that
-assume that parameters are evaluated from left to right or from
-right to left.  For example:
+replaces all occurrences of the string @samp{Britain} with @samp{United
+Kingdom} for all input records.
 
address@hidden
-i = 5
-j = atan2(i++, i *= 2)
+The @code{gsub()} function returns the number of substitutions made.  If
+the variable to search and alter (@var{target}) is
+omitted, then the entire input record (@code{$0}) is used.
+As in @code{sub()}, the characters @samp{&} and @samp{\} are special,
+and the third argument must be assignable.
+
address@hidden index(@var{in}, @var{find})
address@hidden @code{index()} function
address@hidden searching
+Search the string @var{in} for the first occurrence of the string
address@hidden, and return the position in characters where that occurrence
+begins in the string @var{in}.  Consider the following example:
+
address@hidden
+$ @kbd{awk 'BEGIN @{ print index("peanut", "an") @}'}
address@hidden 3
 @end example
 
-If the order of evaluation is left to right, then @code{i} first becomes
-6, and then 12, and @code{atan2()} is called with the two arguments 6
-and 12.  But if the order of evaluation is right to left, @code{i}
-first becomes 10, then 11, and @code{atan2()} is called with the
-two arguments 11 and 10.
address@hidden
+If @var{find} is not found, @code{index()} returns zero.
+(Remember that string indices in @command{awk} start at one.)
 
address@hidden Numeric Functions
address@hidden Numeric Functions
address@hidden length(@address@hidden@r{]})
address@hidden @code{length()} function
+Return the number of characters in @var{string}.  If
address@hidden is a number, the length of the digit string representing
+that number is returned.  For example, @code{length("abcde")} is five.  By
+contrast, @code{length(15 * 35)} works out to three. In this example, 15 * 35 =
+525, and 525 is then converted to the string @code{"525"}, which has
+three characters.
 
-The following list describes all of
-the built-in functions that work with numbers.
-Optional parameters are enclosed in square address@hidden ([ ]):}
+If no argument is supplied, @code{length()} returns the length of @code{$0}.
 
address@hidden @code
address@hidden atan2(@var{y}, @var{x})
address@hidden @code{atan2()} function
-Return the arctangent of @address@hidden / @var{x}} in radians.
address@hidden @cindex historical features
address@hidden portability, @code{length()} function
address@hidden POSIX @command{awk}, functions and, @code{length()}
address@hidden NOTE
+In older versions of @command{awk}, the @code{length()} function could
+be called
+without any parentheses.  Doing so is considered poor practice,
+although the 2008 POSIX standard explicitly allows it, to
+support historical practice.  For programs to be maximally portable,
+always supply the parentheses.
address@hidden quotation
 
address@hidden cos(@var{x})
address@hidden @code{cos()} function
-Return the cosine of @var{x}, with @var{x} in radians.
address@hidden dark corner, @code{length()} function
+If @code{length()} is called with a variable that has not been used,
address@hidden forces the variable to be a scalar.  Other
+implementations of @command{awk} leave the variable without a type.
address@hidden
+Consider:
 
address@hidden exp(@var{x})
address@hidden @code{exp()} function
-Return the exponential of @var{x} (@code{e ^ @var{x}}) or report
-an error if @var{x} is out of range.  The range of values @var{x} can have
-depends on your machine's floating-point representation.
address@hidden
+$ @kbd{gawk 'BEGIN @{ print length(x) ; x[1] = 1 @}'}
address@hidden 0
address@hidden gawk: fatal: attempt to use scalar `x' as array
 
address@hidden int(@var{x})
address@hidden @code{int()} function
-Return the nearest integer to @var{x}, located between @var{x} and zero and
-truncated toward zero.
+$ @kbd{nawk 'BEGIN @{ print length(x) ; x[1] = 1 @}'}
address@hidden 0
address@hidden example
 
-For example, @code{int(3)} is 3, @code{int(3.9)} is 3, @code{int(-3.9)}
-is @minus{}3, and @code{int(-3)} is @minus{}3 as well.
address@hidden
+If @option{--lint} has
+been specified on the command line, @command{gawk} issues a
+warning about this.
 
address@hidden log(@var{x})
address@hidden @code{log()} function
-Return the natural logarithm of @var{x}, if @var{x} is positive;
-otherwise, report an error.
address@hidden common extensions, @code{length()} applied to an array
address@hidden extensions, address@hidden @code{length()} applied to an array
address@hidden differences between @command{gawk} and @command{awk}
+With @command{gawk} and several other @command{awk} implementations, when 
given an
+array argument, the @code{length()} function returns the number of elements
+in the array. @value{COMMONEXT}
+This is less useful than it might seem at first, as the
+array is not guaranteed to be indexed from one to the number of elements
+in it.
+If @option{--lint} is provided on the command line
+(@pxref{Options}),
address@hidden warns that passing an array argument is not portable.
+If @option{--posix} is supplied, using an array argument is a fatal error
+(@pxref{Arrays}).
 
address@hidden rand()
address@hidden @code{rand()} function
address@hidden random numbers, @code{rand()}/@code{srand()} functions
-Return a random number.  The values of @code{rand()} are
-uniformly distributed between zero and one.
-The value could be zero but is never address@hidden C version of @code{rand()}
-on many Unix systems
-is known to produce fairly poor sequences of random numbers.
-However, nothing requires that an @command{awk} implementation use the C
address@hidden()} to implement the @command{awk} version of @code{rand()}.
-In fact, @command{gawk} uses the BSD @code{random()} function, which is
-considerably better than @code{rand()}, to produce random numbers.}
address@hidden match(@var{string}, @var{regexp} @r{[}, @address@hidden)
address@hidden @code{match()} function
+Search @var{string} for the
+longest, leftmost substring matched by the regular expression,
address@hidden and return the character position, or @dfn{index},
+at which that substring begins (one, if it starts at the beginning of
address@hidden).  If no match is found, return zero.
 
-Often random integers are needed instead.  Following is a user-defined function
-that can be used to obtain a random non-negative integer less than @var{n}:
+The @var{regexp} argument may be either a regexp constant
+(@code{/@dots{}/}) or a string constant (@code{"@dots{}"}).
+In the latter case, the string is treated as a regexp to be matched.
address@hidden Regexps}, for a
+discussion of the difference between the two forms, and the
+implications for writing your program correctly.
 
address@hidden
-function randint(n) @{
-     return int(n * rand())
address@hidden
address@hidden example
+The order of the first two arguments is backwards from most other string
+functions that work with regular expressions, such as
address@hidden()} and @code{gsub()}.  It might help to remember that
+for @code{match()}, the order is the same as for the @samp{~} operator:
address@hidden@var{string} ~ @var{regexp}}.
 
address@hidden
-The multiplication produces a random number greater than zero and less
-than @code{n}.  Using @code{int()}, this result is made into
-an integer between zero and @code{n} @minus{} 1, inclusive.
address@hidden @code{RSTART} variable, @code{match()} function and
address@hidden @code{RLENGTH} variable, @code{match()} function and
address@hidden @code{match()} function, @code{RSTART}/@code{RLENGTH} variables
+The @code{match()} function sets the built-in variable @code{RSTART} to
+the index.  It also sets the built-in variable @code{RLENGTH} to the
+length in characters of the matched substring.  If no match is found,
address@hidden is set to zero, and @code{RLENGTH} to @minus{}1.
 
-The following example uses a similar function to produce random integers
-between one and @var{n}.  This program prints a new random number for
-each input record:
+For example:
 
 @example
-# Function to roll a simulated die.
-function roll(n) @{ return 1 + int(rand() * n) @}
-
-# Roll 3 six-sided dice and
-# print total number of points.
address@hidden file eg/misc/findpat.awk
 @{
-      printf("%d points\n",
-             roll(6)+roll(6)+roll(6))
+       if ($1 == "FIND")
+         regex = $2
+       else @{
+         where = match($0, regex)
+         if (where != 0)
+           print "Match of", regex, "found at",
+                     where, "in", $0
+       @}
 @}
address@hidden endfile
 @end example
 
address@hidden numbers, random
address@hidden random numbers, seed of
address@hidden CAUTION
-In most @command{awk} implementations, including @command{gawk},
address@hidden()} starts generating numbers from the same
-starting number, or @dfn{seed}, each time you run @address@hidden@command{mawk}
-uses a different seed each time.}  Thus,
-a program generates the same results each time you run it.
-The numbers are random within one @command{awk} run but predictable
-from run to run.  This is convenient for debugging, but if you want
-a program to do different things each time it is used, you must change
-the seed to a value that is different in each run.  To do this,
-use @code{srand()}.
address@hidden quotation
address@hidden
+This program looks for lines that match the regular expression stored in
+the variable @code{regex}.  This regular expression can be changed.  If the
+first word on a line is @samp{FIND}, @code{regex} is changed to be the
+second word on that line.  Therefore, if given:
 
address@hidden sin(@var{x})
address@hidden @code{sin()} function
-Return the sine of @var{x}, with @var{x} in radians.
address@hidden
address@hidden file eg/misc/findpat.data
+FIND ru+n
+My program runs
+but not very quickly
+FIND Melvin
+JF+KM
+This line is property of Reality Engineering Co.
+Melvin was here.
address@hidden endfile
address@hidden example
 
address@hidden sqrt(@var{x})
address@hidden @code{sqrt()} function
-Return the positive square root of @var{x}.
address@hidden prints a warning message
-if @var{x} is negative.  Thus, @code{sqrt(4)} is 2.
address@hidden
address@hidden prints:
 
address@hidden srand(@address@hidden@r{]})
address@hidden @code{srand()} function
-Set the starting point, or seed,
-for generating random numbers to the value @var{x}.
address@hidden
+Match of ru+n found at 12 in My program runs
+Match of Melvin found at 1 in Melvin was here.
address@hidden example
 
-Each seed value leads to a particular sequence of random
address@hidden random numbers really are not truly
-random.  They are technically known as ``pseudorandom.''  This means
-that while the numbers in a sequence appear to be random, you can in
-fact generate the same sequence of random numbers over and over again.}
-Thus, if the seed is set to the same value a second time,
-the same sequence of random numbers is produced again.
address@hidden differences in @command{awk} and @command{gawk}, @code{match()} 
function
+If @var{array} is present, it is cleared, and then the zeroth element
+of @var{array} is set to the entire portion of @var{string}
+matched by @var{regexp}.  If @var{regexp} contains parentheses,
+the integer-indexed elements of @var{array} are set to contain the
+portion of @var{string} matching the corresponding parenthesized
+subexpression.
+For example:
 
address@hidden CAUTION
-Different @command{awk} implementations use different random-number
-generators internally.  Don't expect the same @command{awk} program
-to produce the same series of random numbers when executed by
-different versions of @command{awk}.
address@hidden quotation
address@hidden
+$ @kbd{echo foooobazbarrrrr |}
+> @kbd{gawk '@{ match($0, /(fo+).+(bar*)/, arr)}
+>         @kbd{print arr[1], arr[2] @}'}
address@hidden foooo barrrrr
address@hidden example
 
-If the argument @var{x} is omitted, as in @samp{srand()}, then the current
-date and time of day are used for a seed.  This is the way to get random
-numbers that are truly unpredictable.
+In addition,
+multidimensional subscripts are available providing
+the start index and length of each matched subexpression:
 
-The return value of @code{srand()} is the previous seed.  This makes it
-easy to keep track of the seeds in case you need to consistently reproduce
-sequences of random numbers.
address@hidden table
address@hidden
+$ @kbd{echo foooobazbarrrrr |}
+> @kbd{gawk '@{ match($0, /(fo+).+(bar*)/, arr)}
+>           @kbd{print arr[1], arr[2]}
+>           @kbd{print arr[1, "start"], arr[1, "length"]}
+>           @kbd{print arr[2, "start"], arr[2, "length"]}
+> @address@hidden'}
address@hidden foooo barrrrr
address@hidden 1 5
address@hidden 9 7
address@hidden example
 
address@hidden String Functions
address@hidden String-Manipulation Functions
+There may not be subscripts for the start and index for every parenthesized
+subexpression, since they may not all have matched text; thus they
+should be tested for with the @code{in} operator
+(@pxref{Reference to Elements}).
 
-The functions in this @value{SECTION} look at or change the text of one or more
-strings.
address@hidden understands locales (@pxref{Locales}), and does all string 
processing in terms of
address@hidden, not @emph{bytes}.  This distinction is particularly important
-to understand for locales where one character
-may be represented by multiple bytes.  Thus, for example, @code{length()}
-returns the number of characters in a string, and not the number of bytes
-used to represent those characters, Similarly, @code{index()} works with
-character indices, and not byte indices.
address@hidden troubleshooting, @code{match()} function
+The @var{array} argument to @code{match()} is a
address@hidden extension.  In compatibility mode
+(@pxref{Options}),
+using a third argument is a fatal error.
 
-In the following list, optional parameters are enclosed in square 
address@hidden ([ ]).}
-Several functions perform string substitution; the full discussion is
-provided in the description of the @code{sub()} function, which comes
-towards the end since the list is presented in alphabetic order.
-Those functions that are specific to @command{gawk} are marked with a
-pound address@hidden (@samp{#}):}
address@hidden patsplit(@var{string}, @var{array} @r{[}, @var{fieldpat} @r{[}, 
@var{seps} @r{]} @r{]}) #
address@hidden @code{patsplit()} function
+Divide
address@hidden into pieces defined by @var{fieldpat}
+and store the pieces in @var{array} and the separator strings in the
address@hidden array.  The first piece is stored in
address@hidden@var{array}[1]}, the second piece in @address@hidden, and so
+forth.  The third argument, @var{fieldpat}, is
+a regexp describing the fields in @var{string} (just as @code{FPAT} is
+a regexp describing the fields in input records).
+It may be either a regexp constant or a string.
+If @var{fieldpat} is omitted, the value of @code{FPAT} is used.
address@hidden()} returns the number of elements created.
address@hidden@address@hidden is
+the separator string
+between @address@hidden@var{i}]} and @address@hidden@var{i}+1]}.
+Any leading separator will be in @address@hidden
 
address@hidden
-* Gory Details::                More than you want to know about @samp{\} and
-                                @samp{&} with @code{sub()}, @code{gsub()}, and
-                                @code{gensub()}.
address@hidden menu
+The @code{patsplit()} function splits strings into pieces in a
+manner similar to the way input lines are split into fields using @code{FPAT}
+(@pxref{Splitting By Content}.
 
address@hidden @code
address@hidden asort(@var{source} @r{[}, @var{dest} @r{[}, @var{how}  @r{]} 
@r{]}) #
address@hidden arrays, elements, retrieving number of
address@hidden @code{asort()} function (@command{gawk})
address@hidden @command{gawk}, @code{IGNORECASE} variable in
address@hidden @code{IGNORECASE} variable
-Return the number of elements in the array @var{source}.
address@hidden sorts the contents of @var{source}
-and replaces the indices
-of the sorted values of @var{source} with sequential
-integers starting with one.  If the optional array @var{dest} is specified,
-then @var{source} is duplicated into @var{dest}.  @var{dest} is then
-sorted, leaving the indices of @var{source} unchanged.  The optional third
-argument @var{how} is a string which controls the rule for comparing values,
-and the sort direction.  A single space is required between the
-comparison mode, @samp{string} or @samp{number}, and the direction 
specification,
address@hidden or @samp{descending}.  You can omit direction and/or mode
-in which case it will default to @samp{ascending} and @samp{string}, 
respectively. 
-An empty string "" is the same as the default @code{"ascending string"}
-for the value of @var{how}.  If the @samp{source} array contains subarrays as 
values,
-they will come out last(first) in the @samp{dest} array for 
@samp{ascending}(@samp{descending})
-order specification.  The value of @code{IGNORECASE} affects the sorting.
-The third argument can also be a user-defined function name in which case
-the value returned by the function is used to order the array elements
-before constructing the result array.
address@hidden an Array}, for more information.
+Before splitting the string, @code{patsplit()} deletes any previously existing
+elements in the arrays @var{array} and @var{seps}.
 
-For example, if the contents of @code{a} are as follows:
address@hidden troubleshooting, @code{patsplit()} function
+The @code{patsplit()} function is a
address@hidden extension.  In compatibility mode
+(@pxref{Options}),
+it is not available.
 
address@hidden
-a["last"] = "de"
-a["first"] = "sac"
-a["middle"] = "cul"
address@hidden example
address@hidden split(@var{string}, @var{array} @r{[}, @var{fieldsep} @r{[}, 
@var{seps} @r{]} @r{]})
address@hidden @code{split()} function
+Divide @var{string} into pieces separated by @var{fieldsep}
+and store the pieces in @var{array} and the separator strings in the
address@hidden array.  The first piece is stored in
address@hidden@var{array}[1]}, the second piece in @address@hidden, and so
+forth.  The string value of the third argument, @var{fieldsep}, is
+a regexp describing where to split @var{string} (much as @code{FS} can
+be a regexp describing where to split input records;
address@hidden Field Splitting}).
+If @var{fieldsep} is omitted, the value of @code{FS} is used.
address@hidden()} returns the number of elements created.
address@hidden is a @command{gawk} extension with @address@hidden@var{i}]} 
+being the separator string
+between @address@hidden@var{i}]} and @address@hidden@var{i}+1]}. 
+If @var{fieldsep} is a single
+space then any leading whitespace goes into @address@hidden and 
+any trailing
+whitespace goes into @address@hidden@var{n}]} where @var{n} is the 
+return value of 
address@hidden()} (that is, the number of elements in @var{array}).
 
address@hidden
-A call to @code{asort()}:
+The @code{split()} function splits strings into pieces in a
+manner similar to the way input lines are split into fields.  For example:
 
 @example
-asort(a)
+split("cul-de-sac", a, "-", seps)
 @end example
 
 @noindent
-results in the following contents of @code{a}:
address@hidden strings, splitting
+splits the string @samp{cul-de-sac} into three fields using @samp{-} as the
+separator.  It sets the contents of the array @code{a} as follows:
 
 @example
 a[1] = "cul"
@@ -14693,616 +14710,246 @@ a[2] = "de"
 a[3] = "sac"
 @end example
 
-In order to reverse the direction of the sorted results in the above example,
address@hidden()} can be called with three arguments as follows:
+and sets the contents of the array @code{seps} as follows:
 
 @example
-asort(a, a, "descending")
+seps[1] = "-"
+seps[2] = "-"
 @end example
 
-The @code{asort()} function is described in more detail in
address@hidden Sorting}.
address@hidden()} is a @command{gawk} extension; it is not available
-in compatibility mode (@pxref{Options}).
address@hidden
+The value returned by this call to @code{split()} is three.
 
address@hidden asorti(@var{source} @r{[}, @var{dest} @r{[}, @var{how}  @r{]} 
@r{]}) #
address@hidden @code{asorti()} function (@command{gawk})
-Return the number of elements in the array @var{source}.
-It works similarly to @code{asort()}, however, the @emph{indices}
-are sorted, instead of the values. (Here too,
address@hidden affects the sorting.)
address@hidden differences in @command{awk} and @command{gawk}, @code{split()} 
function
+As with input field-splitting, when the value of @var{fieldsep} is
address@hidden@code{" "}}, leading and trailing whitespace is ignored in values 
assigned to
+the elements of
address@hidden but not in @var{seps}, and the elements
+are separated by runs of whitespace.
+Also as with input field-splitting, if @var{fieldsep} is the null string, each
+individual character in the string is split into its own array element.
address@hidden
 
-The @code{asorti()} function is described in more detail in
address@hidden Sorting}.
address@hidden()} is a @command{gawk} extension; it is not available
-in compatibility mode (@pxref{Options}).
+Note, however, that @code{RS} has no effect on the way @code{split()}
+works. Even though @samp{RS = ""} causes newline to also be an input
+field separator, this does not affect how @code{split()} splits strings.
 
address@hidden gensub(@var{regexp}, @var{replacement}, @var{how} @r{[}, 
@address@hidden) #
address@hidden @code{gensub()} function (@command{gawk})
-Search the target string @var{target} for matches of the regular
-expression @var{regexp}.  If @var{how} is a string beginning with
address@hidden or @samp{G} (short for ``global''), then replace all matches of 
@var{regexp} with
address@hidden  Otherwise, @var{how} is treated as a number indicating
-which match of @var{regexp} to replace. If no @var{target} is supplied,
-use @code{$0}.  It returns the modified string as the result
-of the function and the original target string is @emph{not} changed.
address@hidden dark corner, @code{split()} function
+Modern implementations of @command{awk}, including @command{gawk}, allow
+the third argument to be a regexp constant (@code{/abc/}) as well as a
+string.
address@hidden
+The POSIX standard allows this as well.
address@hidden Regexps}, for a
+discussion of the difference between using a string constant or a regexp 
constant,
+and the implications for writing your program correctly.
 
address@hidden()} is a general substitution function.  It's purpose is
-to provide more features than the standard @code{sub()} and @code{gsub()}
-functions.
+Before splitting the string, @code{split()} deletes any previously existing
+elements in the arrays @var{array} and @var{seps}.
 
address@hidden()} provides an additional feature that is not available
-in @code{sub()} or @code{gsub()}: the ability to specify components of a
-regexp in the replacement text.  This is done by using parentheses in
-the regexp to mark the components and then specifying @address@hidden
-in the replacement text, where @var{N} is a digit from 1 to 9.
+If @var{string} is null, the array has no elements. (So this is a portable
+way to delete an entire array with one statement.
address@hidden)
+
+If @var{string} does not match @var{fieldsep} at all (but is not null),
address@hidden has one element only. The value of that element is the original
address@hidden
+
address@hidden sprintf(@var{format}, @var{expression1}, @dots{})
address@hidden @code{sprintf()} function
+Return (without printing) the string that @code{printf} would
+have printed out with the same arguments
+(@pxref{Printf}).
 For example:
 
 @example
-$ @kbd{gawk '}
-> @kbd{BEGIN @{}
->      @kbd{a = "abc def"}
->      @kbd{b = gensub(/(.+) (.+)/, "\\2 \\1", "g", a)}
->      @kbd{print b}
-> @address@hidden'}
address@hidden def abc
+pival = sprintf("pi = %.2f (approx.)", 22/7)
 @end example
 
 @noindent
-As with @code{sub()}, you must type two backslashes in order
-to get one into the string.
-In the replacement text, the sequence @samp{\0} represents the entire
-matched text, as does the character @samp{&}.
+assigns the string @address@hidden = 3.14 (approx.)}} to the variable 
@code{pival}.
 
-The following example shows how you can use the third argument to control
-which match of the regexp should be changed:
address@hidden @code{strtonum()} function (@command{gawk})
address@hidden strtonum(@var{str}) #
+Examine @var{str} and return its numeric value.  If @var{str}
+begins with a leading @samp{0}, @code{strtonum()} assumes that @var{str}
+is an octal number.  If @var{str} begins with a leading @samp{0x} or
address@hidden, @code{strtonum()} assumes that @var{str} is a hexadecimal 
number.
+For example:
 
 @example
-$ @kbd{echo a b c a b c |}
-> @kbd{gawk '@{ print gensub(/a/, "AA", 2) @}'}
address@hidden a b c AA b c
+$ @kbd{echo 0x11 |}
+> @kbd{gawk '@{ printf "%d\n", strtonum($1) @}'}
address@hidden 17
 @end example
 
-In this case, @code{$0} is the default target string.
address@hidden()} returns the new string as its result, which is
-passed directly to @code{print} for printing.
+Using the @code{strtonum()} function is @emph{not} the same as adding zero
+to a string value; the automatic coercion of strings to numbers
+works only for decimal data, not for octal or address@hidden
+you use the @option{--non-decimal-data} option, which isn't recommended.
address@hidden Data}, for more information.}
 
address@hidden @cindex automatic warnings
address@hidden @cindex warnings, automatic
-If the @var{how} argument is a string that does not begin with @samp{g} or
address@hidden, or if it is a number that is less than or equal to zero, only 
one
-substitution is performed.  If @var{how} is zero, @command{gawk} issues
-a warning message.
+Note also that @code{strtonum()} uses the current locale's decimal point
+for recognizing numbers (@pxref{Locales}).
 
-If @var{regexp} does not match @var{target}, @code{gensub()}'s return value
-is the original unchanged value of @var{target}.
address@hidden differences in @command{awk} and @command{gawk}, 
@code{strtonum()} function (@command{gawk})
address@hidden()} is a @command{gawk} extension; it is not available
+in compatibility mode (@pxref{Options}).
 
address@hidden()} is a @command{gawk} extension; it is not available
-in compatibility mode (@pxref{Options}).
address@hidden sub(@var{regexp}, @var{replacement} @r{[}, @address@hidden)
address@hidden @code{sub()} function
+Search @var{target}, which is treated as a string, for the
+leftmost, longest substring matched by the regular expression @var{regexp}.
+Modify the entire string
+by replacing the matched text with @var{replacement}.
+The modified string becomes the new value of @var{target}.
+Return the number of substitutions made (zero or one).
 
address@hidden gsub(@var{regexp}, @var{replacement} @r{[}, @address@hidden)
address@hidden @code{gsub()} function
-Search @var{target} for
address@hidden of the longest, leftmost, @emph{nonoverlapping} matching
-substrings it can find and replace them with @var{replacement}.
-The @samp{g} in @code{gsub()} stands for
-``global,'' which means replace everywhere.  For example:
+The @var{regexp} argument may be either a regexp constant
+(@code{/@dots{}/}) or a string constant (@code{"@dots{}"}).
+In the latter case, the string is treated as a regexp to be matched.
address@hidden Regexps}, for a
+discussion of the difference between the two forms, and the
+implications for writing your program correctly.
+
+This function is peculiar because @var{target} is not simply
+used to compute a value, and not just any expression will do---it
+must be a variable, field, or array element so that @code{sub()} can
+store a modified value there.  If this argument is omitted, then the
+default is to use and alter @address@hidden that this means
+that the record will first be regenerated using the value of @code{OFS} if
+any fields have been changed, and that the fields will be updated
+after the substitution, even if the operation is a ``no-op'' such
+as @samp{sub(/^/, "")}.}
+For example:
 
 @example
address@hidden gsub(/Britain/, "United Kingdom"); print @}
+str = "water, water, everywhere"
+sub(/at/, "ith", str)
 @end example
 
 @noindent
-replaces all occurrences of the string @samp{Britain} with @samp{United
-Kingdom} for all input records.
-
-The @code{gsub()} function returns the number of substitutions made.  If
-the variable to search and alter (@var{target}) is
-omitted, then the entire input record (@code{$0}) is used.
-As in @code{sub()}, the characters @samp{&} and @samp{\} are special,
-and the third argument must be assignable.
+sets @code{str} to @address@hidden, water, everywhere}}, by replacing the
+leftmost longest occurrence of @samp{at} with @samp{ith}.
 
address@hidden index(@var{in}, @var{find})
address@hidden @code{index()} function
address@hidden searching
-Search the string @var{in} for the first occurrence of the string
address@hidden, and return the position in characters where that occurrence
-begins in the string @var{in}.  Consider the following example:
+If the special character @samp{&} appears in @var{replacement}, it
+stands for the precise substring that was matched by @var{regexp}.  (If
+the regexp can match more than one string, then this precise substring
+may vary.)  For example:
 
 @example
-$ @kbd{awk 'BEGIN @{ print index("peanut", "an") @}'}
address@hidden 3
address@hidden sub(/candidate/, "& and his wife"); print @}
 @end example
 
 @noindent
-If @var{find} is not found, @code{index()} returns zero.
-(Remember that string indices in @command{awk} start at one.)
-
address@hidden length(@address@hidden@r{]})
address@hidden @code{length()} function
-Return the number of characters in @var{string}.  If
address@hidden is a number, the length of the digit string representing
-that number is returned.  For example, @code{length("abcde")} is five.  By
-contrast, @code{length(15 * 35)} works out to three. In this example, 15 * 35 =
-525, and 525 is then converted to the string @code{"525"}, which has
-three characters.
+changes the first occurrence of @samp{candidate} to @samp{candidate
+and his wife} on each input line.
+Here is another example:
 
-If no argument is supplied, @code{length()} returns the length of @code{$0}.
address@hidden
+$ @kbd{awk 'BEGIN @{}
+>         @kbd{str = "daabaaa"}
+>         @kbd{sub(/a+/, "C&C", str)}
+>         @kbd{print str}
+> @address@hidden'}
address@hidden dCaaCbaaa
address@hidden example
 
address@hidden @cindex historical features
address@hidden portability, @code{length()} function
address@hidden POSIX @command{awk}, functions and, @code{length()}
address@hidden NOTE
-In older versions of @command{awk}, the @code{length()} function could
-be called
-without any parentheses.  Doing so is considered poor practice,
-although the 2008 POSIX standard explicitly allows it, to
-support historical practice.  For programs to be maximally portable,
-always supply the parentheses.
address@hidden quotation
address@hidden
+This shows how @samp{&} can represent a nonconstant string and also
+illustrates the ``leftmost, longest'' rule in regexp matching
+(@pxref{Leftmost Longest}).
 
address@hidden dark corner, @code{length()} function
-If @code{length()} is called with a variable that has not been used,
address@hidden forces the variable to be a scalar.  Other
-implementations of @command{awk} leave the variable without a type.
address@hidden
-Consider:
+The effect of this special character (@samp{&}) can be turned off by putting a
+backslash before it in the string.  As usual, to insert one backslash in
+the string, you must write two backslashes.  Therefore, write @samp{\\&}
+in a string constant to include a literal @samp{&} in the replacement.
+For example, the following shows how to replace the first @samp{|} on each 
line with
+an @samp{&}:
 
 @example
-$ @kbd{gawk 'BEGIN @{ print length(x) ; x[1] = 1 @}'}
address@hidden 0
address@hidden gawk: fatal: attempt to use scalar `x' as array
address@hidden sub(/\|/, "\\&"); print @}
address@hidden example
 
-$ @kbd{nawk 'BEGIN @{ print length(x) ; x[1] = 1 @}'}
address@hidden 0
address@hidden @code{sub()} function, arguments of
address@hidden @code{gsub()} function, arguments of
+As mentioned, the third argument to @code{sub()} must
+be a variable, field or array element.
+Some versions of @command{awk} allow the third argument to
+be an expression that is not an lvalue.  In such a case, @code{sub()}
+still searches for the pattern and returns zero or one, but the result of
+the substitution (if any) is thrown away because there is no place
+to put it.  Such versions of @command{awk} accept expressions
+like the following:
+
address@hidden
+sub(/USA/, "United States", "the USA and Canada")
 @end example
 
 @noindent
-If @option{--lint} has
-been specified on the command line, @command{gawk} issues a
-warning about this.
-
address@hidden common extensions, @code{length()} applied to an array
address@hidden extensions, address@hidden @code{length()} applied to an array
address@hidden differences between @command{gawk} and @command{awk}
-With @command{gawk} and several other @command{awk} implementations, when 
given an
-array argument, the @code{length()} function returns the number of elements
-in the array. @value{COMMONEXT}
-This is less useful than it might seem at first, as the
-array is not guaranteed to be indexed from one to the number of elements
-in it.
-If @option{--lint} is provided on the command line
-(@pxref{Options}),
address@hidden warns that passing an array argument is not portable.
-If @option{--posix} is supplied, using an array argument is a fatal error
-(@pxref{Arrays}).
address@hidden troubleshooting, @code{gsub()}/@code{sub()} functions
+For historical compatibility, @command{gawk} accepts such erroneous code.
+However, using any other nonchangeable
+object as the third parameter causes a fatal error and your program
+will not run.
 
address@hidden match(@var{string}, @var{regexp} @r{[}, @address@hidden)
address@hidden @code{match()} function
-Search @var{string} for the
-longest, leftmost substring matched by the regular expression,
address@hidden and return the character position, or @dfn{index},
-at which that substring begins (one, if it starts at the beginning of
address@hidden).  If no match is found, return zero.
+Finally, if the @var{regexp} is not a regexp constant, it is converted into a
+string, and then the value of that string is treated as the regexp to match.
 
-The @var{regexp} argument may be either a regexp constant
-(@code{/@dots{}/}) or a string constant (@code{"@dots{}"}).
-In the latter case, the string is treated as a regexp to be matched.
address@hidden Regexps}, for a
-discussion of the difference between the two forms, and the
-implications for writing your program correctly.
address@hidden substr(@var{string}, @var{start} @r{[}, @address@hidden)
address@hidden @code{substr()} function
+Return a @var{length}-character-long substring of @var{string},
+starting at character number @var{start}.  The first character of a
+string is character number address@hidden is different from
+C and C++, in which the first character is number zero.}
+For example, @code{substr("washington", 5, 3)} returns @code{"ing"}.
 
-The order of the first two arguments is backwards from most other string
-functions that work with regular expressions, such as
address@hidden()} and @code{gsub()}.  It might help to remember that
-for @code{match()}, the order is the same as for the @samp{~} operator:
address@hidden@var{string} ~ @var{regexp}}.
+If @var{length} is not present, @code{substr()} returns the whole suffix of
address@hidden that begins at character number @var{start}.  For example,
address@hidden("washington", 5)} returns @code{"ington"}.  The whole
+suffix is also returned
+if @var{length} is greater than the number of characters remaining
+in the string, counting from character @var{start}.
 
address@hidden @code{RSTART} variable, @code{match()} function and
address@hidden @code{RLENGTH} variable, @code{match()} function and
address@hidden @code{match()} function, @code{RSTART}/@code{RLENGTH} variables
-The @code{match()} function sets the built-in variable @code{RSTART} to
-the index.  It also sets the built-in variable @code{RLENGTH} to the
-length in characters of the matched substring.  If no match is found,
address@hidden is set to zero, and @code{RLENGTH} to @minus{}1.
+If @var{start} is less than one, @code{substr()} treats it as
+if it was one. (POSIX doesn't specify what to do in this case:
+Brian Kernighan's @command{awk} acts this way, and therefore @command{gawk}
+does too.)
+If @var{start} is greater than the number of characters
+in the string, @code{substr()} returns the null string.
+Similarly, if @var{length} is present but less than or equal to zero,
+the null string is returned.
 
-For example:
address@hidden troubleshooting, @code{substr()} function
+The string returned by @code{substr()} @emph{cannot} be
+assigned.  Thus, it is a mistake to attempt to change a portion of
+a string, as shown in the following example:
 
 @example
address@hidden file eg/misc/findpat.awk
address@hidden
-       if ($1 == "FIND")
-         regex = $2
-       else @{
-         where = match($0, regex)
-         if (where != 0)
-           print "Match of", regex, "found at",
-                     where, "in", $0
-       @}
address@hidden
address@hidden endfile
+string = "abcdef"
+# try to get "abCDEf", won't work
+substr(string, 3, 3) = "CDE"
 @end example
 
 @noindent
-This program looks for lines that match the regular expression stored in
-the variable @code{regex}.  This regular expression can be changed.  If the
-first word on a line is @samp{FIND}, @code{regex} is changed to be the
-second word on that line.  Therefore, if given:
+It is also a mistake to use @code{substr()} as the third argument
+of @code{sub()} or @code{gsub()}:
 
 @example
address@hidden file eg/misc/findpat.data
-FIND ru+n
-My program runs
-but not very quickly
-FIND Melvin
-JF+KM
-This line is property of Reality Engineering Co.
-Melvin was here.
address@hidden endfile
+gsub(/xyz/, "pdq", substr($0, 5, 20))  # WRONG
 @end example
 
address@hidden
address@hidden prints:
address@hidden portability, @code{substr()} function
+(Some commercial versions of @command{awk} treat
address@hidden()} as assignable, but doing so is not portable.)
+
+If you need to replace bits and pieces of a string, combine @code{substr()}
+with string concatenation, in the following manner:
 
 @example
-Match of ru+n found at 12 in My program runs
-Match of Melvin found at 1 in Melvin was here.
address@hidden example
-
address@hidden differences in @command{awk} and @command{gawk}, @code{match()} 
function
-If @var{array} is present, it is cleared, and then the zeroth element
-of @var{array} is set to the entire portion of @var{string}
-matched by @var{regexp}.  If @var{regexp} contains parentheses,
-the integer-indexed elements of @var{array} are set to contain the
-portion of @var{string} matching the corresponding parenthesized
-subexpression.
-For example:
-
address@hidden
-$ @kbd{echo foooobazbarrrrr |}
-> @kbd{gawk '@{ match($0, /(fo+).+(bar*)/, arr)}
->         @kbd{print arr[1], arr[2] @}'}
address@hidden foooo barrrrr
address@hidden example
-
-In addition,
-multidimensional subscripts are available providing
-the start index and length of each matched subexpression:
-
address@hidden
-$ @kbd{echo foooobazbarrrrr |}
-> @kbd{gawk '@{ match($0, /(fo+).+(bar*)/, arr)}
->           @kbd{print arr[1], arr[2]}
->           @kbd{print arr[1, "start"], arr[1, "length"]}
->           @kbd{print arr[2, "start"], arr[2, "length"]}
-> @address@hidden'}
address@hidden foooo barrrrr
address@hidden 1 5
address@hidden 9 7
address@hidden example
-
-There may not be subscripts for the start and index for every parenthesized
-subexpression, since they may not all have matched text; thus they
-should be tested for with the @code{in} operator
-(@pxref{Reference to Elements}).
-
address@hidden troubleshooting, @code{match()} function
-The @var{array} argument to @code{match()} is a
address@hidden extension.  In compatibility mode
-(@pxref{Options}),
-using a third argument is a fatal error.
-
address@hidden patsplit(@var{string}, @var{array} @r{[}, @var{fieldpat} @r{[}, 
@var{seps} @r{]} @r{]}) #
address@hidden @code{patsplit()} function
-Divide
address@hidden into pieces defined by @var{fieldpat}
-and store the pieces in @var{array} and the separator strings in the
address@hidden array.  The first piece is stored in
address@hidden@var{array}[1]}, the second piece in @address@hidden, and so
-forth.  The third argument, @var{fieldpat}, is
-a regexp describing the fields in @var{string} (just as @code{FPAT} is
-a regexp describing the fields in input records).
-It may be either a regexp constant or a string.
-If @var{fieldpat} is omitted, the value of @code{FPAT} is used.
address@hidden()} returns the number of elements created.
address@hidden@address@hidden is
-the separator string
-between @address@hidden@var{i}]} and @address@hidden@var{i}+1]}.
-Any leading separator will be in @address@hidden
-
-The @code{patsplit()} function splits strings into pieces in a
-manner similar to the way input lines are split into fields using @code{FPAT}
-(@pxref{Splitting By Content}.
-
-Before splitting the string, @code{patsplit()} deletes any previously existing
-elements in the arrays @var{array} and @var{seps}.
-
address@hidden troubleshooting, @code{patsplit()} function
-The @code{patsplit()} function is a
address@hidden extension.  In compatibility mode
-(@pxref{Options}),
-it is not available.
-
address@hidden split(@var{string}, @var{array} @r{[}, @var{fieldsep} @r{[}, 
@var{seps} @r{]} @r{]})
address@hidden @code{split()} function
-Divide @var{string} into pieces separated by @var{fieldsep}
-and store the pieces in @var{array} and the separator strings in the
address@hidden array.  The first piece is stored in
address@hidden@var{array}[1]}, the second piece in @address@hidden, and so
-forth.  The string value of the third argument, @var{fieldsep}, is
-a regexp describing where to split @var{string} (much as @code{FS} can
-be a regexp describing where to split input records;
address@hidden Field Splitting}).
-If @var{fieldsep} is omitted, the value of @code{FS} is used.
address@hidden()} returns the number of elements created.
address@hidden is a @command{gawk} extension with @address@hidden@var{i}]} 
-being the separator string
-between @address@hidden@var{i}]} and @address@hidden@var{i}+1]}. 
-If @var{fieldsep} is a single
-space then any leading whitespace goes into @address@hidden and 
-any trailing
-whitespace goes into @address@hidden@var{n}]} where @var{n} is the 
-return value of 
address@hidden()} (that is, the number of elements in @var{array}).
-
-The @code{split()} function splits strings into pieces in a
-manner similar to the way input lines are split into fields.  For example:
-
address@hidden
-split("cul-de-sac", a, "-", seps)
address@hidden example
-
address@hidden
address@hidden strings, splitting
-splits the string @samp{cul-de-sac} into three fields using @samp{-} as the
-separator.  It sets the contents of the array @code{a} as follows:
-
address@hidden
-a[1] = "cul"
-a[2] = "de"
-a[3] = "sac"
address@hidden example
-
-and sets the contents of the array @code{seps} as follows:
-
address@hidden
-seps[1] = "-"
-seps[2] = "-"
address@hidden example
-
address@hidden
-The value returned by this call to @code{split()} is three.
-
address@hidden differences in @command{awk} and @command{gawk}, @code{split()} 
function
-As with input field-splitting, when the value of @var{fieldsep} is
address@hidden@code{" "}}, leading and trailing whitespace is ignored in values 
assigned to
-the elements of
address@hidden but not in @var{seps}, and the elements
-are separated by runs of whitespace.
-Also as with input field-splitting, if @var{fieldsep} is the null string, each
-individual character in the string is split into its own array element.
address@hidden
-
-Note, however, that @code{RS} has no effect on the way @code{split()}
-works. Even though @samp{RS = ""} causes newline to also be an input
-field separator, this does not affect how @code{split()} splits strings.
-
address@hidden dark corner, @code{split()} function
-Modern implementations of @command{awk}, including @command{gawk}, allow
-the third argument to be a regexp constant (@code{/abc/}) as well as a
-string.
address@hidden
-The POSIX standard allows this as well.
address@hidden Regexps}, for a
-discussion of the difference between using a string constant or a regexp 
constant,
-and the implications for writing your program correctly.
-
-Before splitting the string, @code{split()} deletes any previously existing
-elements in the arrays @var{array} and @var{seps}.
-
-If @var{string} is null, the array has no elements. (So this is a portable
-way to delete an entire array with one statement.
address@hidden)
-
-If @var{string} does not match @var{fieldsep} at all (but is not null),
address@hidden has one element only. The value of that element is the original
address@hidden
-
address@hidden sprintf(@var{format}, @var{expression1}, @dots{})
address@hidden @code{sprintf()} function
-Return (without printing) the string that @code{printf} would
-have printed out with the same arguments
-(@pxref{Printf}).
-For example:
-
address@hidden
-pival = sprintf("pi = %.2f (approx.)", 22/7)
address@hidden example
-
address@hidden
-assigns the string @address@hidden = 3.14 (approx.)}} to the variable 
@code{pival}.
-
address@hidden @code{strtonum()} function (@command{gawk})
address@hidden strtonum(@var{str}) #
-Examine @var{str} and return its numeric value.  If @var{str}
-begins with a leading @samp{0}, @code{strtonum()} assumes that @var{str}
-is an octal number.  If @var{str} begins with a leading @samp{0x} or
address@hidden, @code{strtonum()} assumes that @var{str} is a hexadecimal 
number.
-For example:
-
address@hidden
-$ @kbd{echo 0x11 |}
-> @kbd{gawk '@{ printf "%d\n", strtonum($1) @}'}
address@hidden 17
address@hidden example
-
-Using the @code{strtonum()} function is @emph{not} the same as adding zero
-to a string value; the automatic coercion of strings to numbers
-works only for decimal data, not for octal or address@hidden
-you use the @option{--non-decimal-data} option, which isn't recommended.
address@hidden Data}, for more information.}
-
-Note also that @code{strtonum()} uses the current locale's decimal point
-for recognizing numbers (@pxref{Locales}).
-
address@hidden differences in @command{awk} and @command{gawk}, 
@code{strtonum()} function (@command{gawk})
address@hidden()} is a @command{gawk} extension; it is not available
-in compatibility mode (@pxref{Options}).
-
address@hidden sub(@var{regexp}, @var{replacement} @r{[}, @address@hidden)
address@hidden @code{sub()} function
-Search @var{target}, which is treated as a string, for the
-leftmost, longest substring matched by the regular expression @var{regexp}.
-Modify the entire string
-by replacing the matched text with @var{replacement}.
-The modified string becomes the new value of @var{target}.
-Return the number of substitutions made (zero or one).
-
-The @var{regexp} argument may be either a regexp constant
-(@code{/@dots{}/}) or a string constant (@code{"@dots{}"}).
-In the latter case, the string is treated as a regexp to be matched.
address@hidden Regexps}, for a
-discussion of the difference between the two forms, and the
-implications for writing your program correctly.
-
-This function is peculiar because @var{target} is not simply
-used to compute a value, and not just any expression will do---it
-must be a variable, field, or array element so that @code{sub()} can
-store a modified value there.  If this argument is omitted, then the
-default is to use and alter @address@hidden that this means
-that the record will first be regenerated using the value of @code{OFS} if
-any fields have been changed, and that the fields will be updated
-after the substitution, even if the operation is a ``no-op'' such
-as @samp{sub(/^/, "")}.}
-For example:
-
address@hidden
-str = "water, water, everywhere"
-sub(/at/, "ith", str)
address@hidden example
-
address@hidden
-sets @code{str} to @address@hidden, water, everywhere}}, by replacing the
-leftmost longest occurrence of @samp{at} with @samp{ith}.
-
-If the special character @samp{&} appears in @var{replacement}, it
-stands for the precise substring that was matched by @var{regexp}.  (If
-the regexp can match more than one string, then this precise substring
-may vary.)  For example:
-
address@hidden
address@hidden sub(/candidate/, "& and his wife"); print @}
address@hidden example
-
address@hidden
-changes the first occurrence of @samp{candidate} to @samp{candidate
-and his wife} on each input line.
-Here is another example:
-
address@hidden
-$ @kbd{awk 'BEGIN @{}
->         @kbd{str = "daabaaa"}
->         @kbd{sub(/a+/, "C&C", str)}
->         @kbd{print str}
-> @address@hidden'}
address@hidden dCaaCbaaa
address@hidden example
-
address@hidden
-This shows how @samp{&} can represent a nonconstant string and also
-illustrates the ``leftmost, longest'' rule in regexp matching
-(@pxref{Leftmost Longest}).
-
-The effect of this special character (@samp{&}) can be turned off by putting a
-backslash before it in the string.  As usual, to insert one backslash in
-the string, you must write two backslashes.  Therefore, write @samp{\\&}
-in a string constant to include a literal @samp{&} in the replacement.
-For example, the following shows how to replace the first @samp{|} on each 
line with
-an @samp{&}:
-
address@hidden
address@hidden sub(/\|/, "\\&"); print @}
address@hidden example
-
address@hidden @code{sub()} function, arguments of
address@hidden @code{gsub()} function, arguments of
-As mentioned, the third argument to @code{sub()} must
-be a variable, field or array element.
-Some versions of @command{awk} allow the third argument to
-be an expression that is not an lvalue.  In such a case, @code{sub()}
-still searches for the pattern and returns zero or one, but the result of
-the substitution (if any) is thrown away because there is no place
-to put it.  Such versions of @command{awk} accept expressions
-like the following:
-
address@hidden
-sub(/USA/, "United States", "the USA and Canada")
address@hidden example
-
address@hidden
address@hidden troubleshooting, @code{gsub()}/@code{sub()} functions
-For historical compatibility, @command{gawk} accepts such erroneous code.
-However, using any other nonchangeable
-object as the third parameter causes a fatal error and your program
-will not run.
-
-Finally, if the @var{regexp} is not a regexp constant, it is converted into a
-string, and then the value of that string is treated as the regexp to match.
-
address@hidden substr(@var{string}, @var{start} @r{[}, @address@hidden)
address@hidden @code{substr()} function
-Return a @var{length}-character-long substring of @var{string},
-starting at character number @var{start}.  The first character of a
-string is character number address@hidden is different from
-C and C++, in which the first character is number zero.}
-For example, @code{substr("washington", 5, 3)} returns @code{"ing"}.
-
-If @var{length} is not present, @code{substr()} returns the whole suffix of
address@hidden that begins at character number @var{start}.  For example,
address@hidden("washington", 5)} returns @code{"ington"}.  The whole
-suffix is also returned
-if @var{length} is greater than the number of characters remaining
-in the string, counting from character @var{start}.
-
-If @var{start} is less than one, @code{substr()} treats it as
-if it was one. (POSIX doesn't specify what to do in this case:
-Brian Kernighan's @command{awk} acts this way, and therefore @command{gawk}
-does too.)
-If @var{start} is greater than the number of characters
-in the string, @code{substr()} returns the null string.
-Similarly, if @var{length} is present but less than or equal to zero,
-the null string is returned.
-
address@hidden troubleshooting, @code{substr()} function
-The string returned by @code{substr()} @emph{cannot} be
-assigned.  Thus, it is a mistake to attempt to change a portion of
-a string, as shown in the following example:
-
address@hidden
-string = "abcdef"
-# try to get "abCDEf", won't work
-substr(string, 3, 3) = "CDE"
address@hidden example
-
address@hidden
-It is also a mistake to use @code{substr()} as the third argument
-of @code{sub()} or @code{gsub()}:
-
address@hidden
-gsub(/xyz/, "pdq", substr($0, 5, 20))  # WRONG
address@hidden example
-
address@hidden portability, @code{substr()} function
-(Some commercial versions of @command{awk} treat
address@hidden()} as assignable, but doing so is not portable.)
-
-If you need to replace bits and pieces of a string, combine @code{substr()}
-with string concatenation, in the following manner:
-
address@hidden
-string = "abcdef"
address@hidden
-string = substr(string, 1, 2) "CDE" substr(string, 6)
+string = "abcdef"
address@hidden
+string = substr(string, 1, 2) "CDE" substr(string, 6)
 @end example
 
 @cindex case sensitivity, converting case
@@ -17002,1552 +16649,2023 @@ BEGIN @{
 @}
 @end example
 
-Running this script produces the following, because the @code{i} in
-functions @code{foo()} and @code{bar()} and at the top level refer to the same
-variable instance:
+Running this script produces the following, because the @code{i} in
+functions @code{foo()} and @code{bar()} and at the top level refer to the same
+variable instance:
+
address@hidden
+top's i=10
+foo's i=1
+bar's i=0
+bar's i=1
+bar's i=2
+foo's i=3
+top's i=3
address@hidden example
+
+If you want @code{i} to be local to both @code{foo()} and @code{bar()} do as
+follows (the extra-space before @code{i} is a coding convention to
+indicate that @code{i} is a local variable, not an argument):
+
address@hidden
+function bar(    i)
address@hidden
+    for (i = 0; i < 3; i++) 
+        print "bar's i=" i
address@hidden
+
+function foo(j,    i)
address@hidden
+    i = j + 1
+    print "foo's i=" i
+    bar()
+    print "foo's i=" i
address@hidden
+
+BEGIN @{ 
+      i = 10
+      print "top's i=" i
+      foo(0) 
+      print "top's i=" i
address@hidden
address@hidden example
+
+Running the corrected script produces the following:
+
address@hidden
+top's i=10
+foo's i=1
+bar's i=0
+bar's i=1
+bar's i=2
+foo's i=1
+top's i=10
address@hidden example
+
address@hidden Pass By Value/Reference
address@hidden Passing Function Arguments By Value Or By Reference
+
+In @command{awk}, when you declare a function, there is no way to
+declare explicitly whether the arguments are passed @dfn{by value} or
address@hidden reference}.
+
+Instead the passing convention is determined at runtime when
+the function is called according to the following rule:
+
address@hidden
address@hidden
+If the argument is an array variable, then it is passed by reference,
address@hidden
+Otherwise the argument is passed by value.
address@hidden itemize
+
address@hidden call by value
+Passing an argument by value means that when a function is called, it
+is given a @emph{copy} of the value of this argument.
+The caller may use a variable as the expression for the argument, but
+the called function does not know this---it only knows what value the
+argument had.  For example, if you write the following code:
+
address@hidden
+foo = "bar"
+z = myfunc(foo)
address@hidden example
+
address@hidden
+then you should not think of the argument to @code{myfunc()} as being
+``the variable @code{foo}.''  Instead, think of the argument as the
+string value @code{"bar"}.
+If the function @code{myfunc()} alters the values of its local variables,
+this has no effect on any other variables.  Thus, if @code{myfunc()}
+does this:
+
address@hidden
+function myfunc(str)
address@hidden
+   print str
+   str = "zzz"
+   print str
address@hidden
address@hidden example
+
address@hidden
+to change its first argument variable @code{str}, it does @emph{not}
+change the value of @code{foo} in the caller.  The role of @code{foo} in
+calling @code{myfunc()} ended when its value (@code{"bar"}) was computed.
+If @code{str} also exists outside of @code{myfunc()}, the function body
+cannot alter this outer value, because it is shadowed during the
+execution of @code{myfunc()} and cannot be seen or changed from there.
+
address@hidden call by reference
address@hidden arrays, as parameters to functions
address@hidden functions, arrays as parameters to
+However, when arrays are the parameters to functions, they are @emph{not}
+copied.  Instead, the array itself is made available for direct manipulation
+by the function.  This is usually termed @dfn{call by reference}.
+Changes made to an array parameter inside the body of a function @emph{are}
+visible outside that function.
+
address@hidden NOTE
+Changing an array parameter inside a function
+can be very dangerous if you do not watch what you are doing.
+For example:
+
address@hidden
+function changeit(array, ind, nvalue)
address@hidden
+     array[ind] = nvalue
address@hidden
+
+BEGIN @{
+    a[1] = 1; a[2] = 2; a[3] = 3
+    changeit(a, 2, "two")
+    printf "a[1] = %s, a[2] = %s, a[3] = %s\n",
+            a[1], a[2], a[3]
address@hidden
address@hidden example
+
address@hidden
+prints @samp{a[1] = 1, a[2] = two, a[3] = 3}, because
address@hidden stores @code{"two"} in the second element of @code{a}.
address@hidden quotation
+
address@hidden undefined functions
address@hidden functions, undefined
+Some @command{awk} implementations allow you to call a function that
+has not been defined. They only report a problem at runtime when the
+program actually tries to call the function. For example:
+
address@hidden
+BEGIN @{
+    if (0)
+        foo()
+    else
+        bar()
address@hidden
+function bar() @{ @dots{} @}
+# note that `foo' is not defined
address@hidden example
+
address@hidden
+Because the @samp{if} statement will never be true, it is not really a
+problem that @code{foo()} has not been defined.  Usually, though, it is a
+problem if a program calls an undefined function.
+
address@hidden lint checking, undefined functions
+If @option{--lint} is specified
+(@pxref{Options}),
address@hidden reports calls to undefined functions.
+
address@hidden portability, @code{next} statement in user-defined functions
+Some @command{awk} implementations generate a runtime
+error if you use the @code{next} statement
+(@pxref{Next Statement})
+inside a user-defined function.
address@hidden does not have this limitation.
address@hidden ENDOFRANGE fudc
+
address@hidden Return Statement
address@hidden The @code{return} Statement
address@hidden @code{return} address@hidden user-defined functions
+
+As seen in several earlier examples,
+the body of a user-defined function can contain a @code{return} statement.
+This statement returns control to the calling part of the @command{awk} 
program.  It
+can also be used to return a value for use in the rest of the @command{awk}
+program.  It looks like this:
+
address@hidden
+return @address@hidden@r{]}
address@hidden example
+
+The @var{expression} part is optional.
+Due most likely to an oversight, POSIX does not define what the return
+value is if you omit the @var{expression}.  Technically speaking, this
+make the returned value undefined, and therefore, unpredictable.
+In practice, though, all versions of @command{awk} simply return the
+null string, which acts like zero if used in a numeric context.
+
+A @code{return} statement with no value expression is assumed at the end of
+every function definition.  So if control reaches the end of the function
+body, then technically, the function returns an unpredictable value.
+In practice, it returns the empty string.  @command{awk}
+does @emph{not} warn you if you use the return value of such a function.
+
+Sometimes, you want to write a function for what it does, not for
+what it returns.  Such a function corresponds to a @code{void} function
+in C, C++ or Java, or to a @code{procedure} in Ada.  Thus, it may be 
appropriate to not
+return any value; simply bear in mind that you should not be using the
+return value of such a function.
+
+The following is an example of a user-defined function that returns a value
+for the largest number among the elements of an array:
+
address@hidden
+function maxelt(vec,   i, ret)
address@hidden
+     for (i in vec) @{
+          if (ret == "" || vec[i] > ret)
+               ret = vec[i]
+     @}
+     return ret
address@hidden
address@hidden example
+
address@hidden programming conventions, function parameters
address@hidden
+You call @code{maxelt()} with one argument, which is an array name.  The local
+variables @code{i} and @code{ret} are not intended to be arguments;
+while there is nothing to stop you from passing more than one argument
+to @code{maxelt()}, the results would be strange.  The extra space before
address@hidden in the function parameter list indicates that @code{i} and
address@hidden are local variables.
+You should follow this convention when defining functions.
+
+The following program uses the @code{maxelt()} function.  It loads an
+array, calls @code{maxelt()}, and then reports the maximum number in that
+array:
+
address@hidden
+function maxelt(vec,   i, ret)
address@hidden
+     for (i in vec) @{
+          if (ret == "" || vec[i] > ret)
+               ret = vec[i]
+     @}
+     return ret
address@hidden
+
+# Load all fields of each record into nums.
address@hidden
+     for(i = 1; i <= NF; i++)
+          nums[NR, i] = $i
address@hidden
+
+END @{
+     print maxelt(nums)
address@hidden
address@hidden example
+
+Given the following input:
 
 @example
-top's i=10
-foo's i=1
-bar's i=0
-bar's i=1
-bar's i=2
-foo's i=3
-top's i=3
+ 1 5 23 8 16
+44 3 5 2 8 26
+256 291 1396 2962 100
+-6 467 998 1101
+99385 11 0 225
 @end example
 
-If you want @code{i} to be local to both @code{foo()} and @code{bar()} do as
-follows (the extra-space before @code{i} is a coding convention to
-indicate that @code{i} is a local variable, not an argument):
address@hidden
+the program reports (predictably) that 99,385 is the largest value
+in the array.
+
address@hidden Dynamic Typing
address@hidden Functions and Their Effects on Variable Typing
+
address@hidden is a very fluid language.
+It is possible that @command{awk} can't tell if an identifier
+represents a scalar variable or an array until runtime.
+Here is an annotated sample program:
 
 @example
-function bar(    i)
+function foo(a)
 @{
-    for (i = 0; i < 3; i++) 
-        print "bar's i=" i
+    a[1] = 1   # parameter is an array
 @}
 
-function foo(j,    i)
address@hidden
-    i = j + 1
-    print "foo's i=" i
-    bar()
-    print "foo's i=" i
address@hidden
+BEGIN @{
+    b = 1
+    foo(b)  # invalid: fatal type mismatch
 
-BEGIN @{ 
-      i = 10
-      print "top's i=" i
-      foo(0) 
-      print "top's i=" i
+    foo(x)  # x uninitialized, becomes an array dynamically
+    x = 1   # now not allowed, runtime error
 @}
 @end example
 
-Running the corrected script produces the following:
+Usually, such things aren't a big issue, but it's worth
+being aware of them.
address@hidden ENDOFRANGE udfunc
 
address@hidden
-top's i=10
-foo's i=1
-bar's i=0
-bar's i=1
-bar's i=2
-foo's i=1
-top's i=10
address@hidden example
address@hidden Indirect Calls
address@hidden Indirect Function Calls
 
address@hidden Pass By Value/Reference
address@hidden Passing Function Arguments By Value Or By Reference
address@hidden indirect function calls
address@hidden function calls, indirect
address@hidden function pointers
address@hidden pointers to functions
address@hidden differences in @command{awk} and @command{gawk}, indirect 
function calls
 
-In @command{awk}, when you declare a function, there is no way to
-declare explicitly whether the arguments are passed @dfn{by value} or
address@hidden reference}.
+This section describes a @command{gawk}-specific extension.
 
-Instead the passing convention is determined at runtime when
-the function is called according to the following rule:
+Often, you may wish to defer the choice of function to call until runtime.
+For example, you may have different kinds of records, each of which
+should be processed differently.
 
address@hidden
address@hidden
-If the argument is an array variable, then it is passed by reference,
address@hidden
-Otherwise the argument is passed by value.
address@hidden itemize
+Normally, you would have to use a series of @address@hidden
+statements to decide which function to call.  By using @dfn{indirect}
+function calls, you can specify the name of the function to call as a
+string variable, and then call the function.  Let's look at an example.
 
address@hidden call by value
-Passing an argument by value means that when a function is called, it
-is given a @emph{copy} of the value of this argument.
-The caller may use a variable as the expression for the argument, but
-the called function does not know this---it only knows what value the
-argument had.  For example, if you write the following code:
+Suppose you have a file with your test scores for the classes you
+are taking.  The first field is the class name. The following fields
+are the functions to call to process the data, up to a ``marker''
+field @samp{data:}.  Following the marker, to the end of the record,
+are the various numeric test scores.
+
+Here is the initial file; you wish to get the sum and the average of
+your test scores:
 
 @example
-foo = "bar"
-z = myfunc(foo)
address@hidden file eg/data/class_data1
+Biology_101 sum average data: 87.0 92.4 78.5 94.9
+Chemistry_305 sum average data: 75.2 98.3 94.7 88.2
+English_401 sum average data: 100.0 95.6 87.1 93.4
address@hidden endfile
 @end example
 
address@hidden
-then you should not think of the argument to @code{myfunc()} as being
-``the variable @code{foo}.''  Instead, think of the argument as the
-string value @code{"bar"}.
-If the function @code{myfunc()} alters the values of its local variables,
-this has no effect on any other variables.  Thus, if @code{myfunc()}
-does this:
+To process the data, you might write initially:
 
 @example
-function myfunc(str)
 @{
-   print str
-   str = "zzz"
-   print str
+    class = $1
+    for (i = 2; $i != "data:"; i++) @{
+        if ($i == "sum")
+            sum()   # processes the whole record
+        else if ($i == "average")
+            average()
+        @dots{}           # and so on
+    @}
 @}
 @end example
 
 @noindent
-to change its first argument variable @code{str}, it does @emph{not}
-change the value of @code{foo} in the caller.  The role of @code{foo} in
-calling @code{myfunc()} ended when its value (@code{"bar"}) was computed.
-If @code{str} also exists outside of @code{myfunc()}, the function body
-cannot alter this outer value, because it is shadowed during the
-execution of @code{myfunc()} and cannot be seen or changed from there.
+This style of programming works, but can be awkward.  With @dfn{indirect}
+function calls, you tell @command{gawk} to use the @emph{value} of a
+variable as the name of the function to call.
 
address@hidden call by reference
address@hidden arrays, as parameters to functions
address@hidden functions, arrays as parameters to
-However, when arrays are the parameters to functions, they are @emph{not}
-copied.  Instead, the array itself is made available for direct manipulation
-by the function.  This is usually termed @dfn{call by reference}.
-Changes made to an array parameter inside the body of a function @emph{are}
-visible outside that function.
+The syntax is similar to that of a regular function call: an identifier
+immediately followed by a left parenthesis, any arguments, and then
+a closing right parenthesis, with the addition of a leading @samp{@@}
+character:
 
address@hidden NOTE
-Changing an array parameter inside a function
-can be very dangerous if you do not watch what you are doing.
-For example:
address@hidden
+the_func = "sum"
+result = @@the_func()   # calls the `sum' function
address@hidden example
+
+Here is a full program that processes the previously shown data,
+using indirect function calls.
 
 @example
-function changeit(array, ind, nvalue)
address@hidden file eg/prog/indirectcall.awk
+# indirectcall.awk --- Demonstrate indirect function calls
address@hidden endfile
address@hidden
address@hidden file eg/prog/indirectcall.awk
+#
+# Arnold Robbins, address@hidden, Public Domain
+# January 2009
address@hidden endfile
address@hidden ignore
+
address@hidden file eg/prog/indirectcall.awk
+# average --- return the average of the values in fields $first - $last
+
+function average(first, last,   sum, i)
 @{
-     array[ind] = nvalue
+    sum = 0;
+    for (i = first; i <= last; i++)
+        sum += $i
+
+    return sum / (last - first + 1)
 @}
 
-BEGIN @{
-    a[1] = 1; a[2] = 2; a[3] = 3
-    changeit(a, 2, "two")
-    printf "a[1] = %s, a[2] = %s, a[3] = %s\n",
-            a[1], a[2], a[3]
+# sum --- return the sum of the values in fields $first - $last
+
+function sum(first, last,   ret, i)
address@hidden
+    ret = 0;
+    for (i = first; i <= last; i++)
+        ret += $i
+
+    return ret
 @}
address@hidden endfile
 @end example
 
address@hidden
-prints @samp{a[1] = 1, a[2] = two, a[3] = 3}, because
address@hidden stores @code{"two"} in the second element of @code{a}.
address@hidden quotation
-
address@hidden undefined functions
address@hidden functions, undefined
-Some @command{awk} implementations allow you to call a function that
-has not been defined. They only report a problem at runtime when the
-program actually tries to call the function. For example:
+These two functions expect to work on fields; thus the parameters
address@hidden and @code{last} indicate where in the fields to start and end.
+Otherwise they perform the expected computations and are not unusual.
 
 @example
-BEGIN @{
-    if (0)
-        foo()
-    else
-        bar()
address@hidden file eg/prog/indirectcall.awk
+# For each record, print the class name and the requested statistics
+
address@hidden
+    class_name = $1
+    gsub(/_/, " ", class_name)  # Replace _ with spaces
+
+    # find start
+    for (i = 1; i <= NF; i++) @{
+        if ($i == "data:") @{
+            start = i + 1
+            break
+        @}
+    @}
+
+    printf("%s:\n", class_name)
+    for (i = 2; $i != "data:"; i++) @{
+        the_function = $i
+        printf("\t%s: <%s>\n", $i, @@the_function(start, NF) "")
+    @}
+    print ""
 @}
-function bar() @{ @dots{} @}
-# note that `foo' is not defined
address@hidden endfile
 @end example
 
address@hidden
-Because the @samp{if} statement will never be true, it is not really a
-problem that @code{foo()} has not been defined.  Usually, though, it is a
-problem if a program calls an undefined function.
+This is the main processing for each record. It prints the class name (with
+underscores replaced with spaces). It then finds the start of the actual data,
+saving it in @code{start}.
+The last part of the code loops through each function name (from @code{$2} up 
to
+the marker, @samp{data:}), calling the function named by the field. The 
indirect
+function call itself occurs as a parameter in the call to @code{printf}.
+(The @code{printf} format string uses @samp{%s} as the format specifier so 
that we
+can use functions that return strings, as well as numbers. Note that the result
+from the indirect call is concatenated with the empty string, in order to force
+it to be a string value.)
 
address@hidden lint checking, undefined functions
-If @option{--lint} is specified
-(@pxref{Options}),
address@hidden reports calls to undefined functions.
+Here is the result of running the program:
 
address@hidden portability, @code{next} statement in user-defined functions
-Some @command{awk} implementations generate a runtime
-error if you use the @code{next} statement
-(@pxref{Next Statement})
-inside a user-defined function.
address@hidden does not have this limitation.
address@hidden ENDOFRANGE fudc
address@hidden
+$ @kbd{gawk -f indirectcall.awk class_data1}
address@hidden Biology 101:
address@hidden     sum: <352.8>
address@hidden     average: <88.2>
address@hidden 
address@hidden Chemistry 305:
address@hidden     sum: <356.4>
address@hidden     average: <89.1>
address@hidden 
address@hidden English 401:
address@hidden     sum: <376.1>
address@hidden     average: <94.025>
address@hidden example
 
address@hidden Return Statement
address@hidden The @code{return} Statement
address@hidden @code{return} address@hidden user-defined functions
+The ability to use indirect function calls is more powerful than you may
+think at first.  The C and C++ languages provide ``function pointers,'' which
+are a mechanism for calling a function chosen at runtime.  One of the most
+well-known uses of this ability is the C @code{qsort()} function, which sorts
+an array using the famous ``quick sort'' algorithm
+(see @uref{http://en.wikipedia.org/wiki/Quick_sort, the Wikipedia article}
+for more information).  To use this function, you supply a pointer to a 
comparison
+function.  This mechanism allows you to sort arbitrary data in an arbitrary
+fashion.
 
-As seen in several earlier examples,
-the body of a user-defined function can contain a @code{return} statement.
-This statement returns control to the calling part of the @command{awk} 
program.  It
-can also be used to return a value for use in the rest of the @command{awk}
-program.  It looks like this:
+We can do something similar using @command{gawk}, like this:
 
 @example
-return @address@hidden@r{]}
address@hidden example
address@hidden file eg/lib/quicksort.awk
+# quicksort.awk --- Quicksort algorithm, with user-supplied
+#                   comparison function
address@hidden endfile
address@hidden
address@hidden file eg/lib/quicksort.awk
+#
+# Arnold Robbins, address@hidden, Public Domain
+# January 2009
address@hidden endfile
 
-The @var{expression} part is optional.
-Due most likely to an oversight, POSIX does not define what the return
-value is if you omit the @var{expression}.  Technically speaking, this
-make the returned value undefined, and therefore, unpredictable.
-In practice, though, all versions of @command{awk} simply return the
-null string, which acts like zero if used in a numeric context.
address@hidden ignore
address@hidden file eg/lib/quicksort.awk
+# quicksort --- C.A.R. Hoare's quick sort algorithm. See Wikipedia
+#               or almost any algorithms or computer science text
address@hidden endfile
address@hidden
address@hidden file eg/lib/quicksort.awk
+#
+# Adapted from K&R-II, page 110
address@hidden ignore
address@hidden file eg/lib/quicksort.awk
 
-A @code{return} statement with no value expression is assumed at the end of
-every function definition.  So if control reaches the end of the function
-body, then technically, the function returns an unpredictable value.
-In practice, it returns the empty string.  @command{awk}
-does @emph{not} warn you if you use the return value of such a function.
+function quicksort(data, left, right, less_than,    i, last)
address@hidden
+    if (left >= right)  # do nothing if array contains fewer
+        return          # than two elements
 
-Sometimes, you want to write a function for what it does, not for
-what it returns.  Such a function corresponds to a @code{void} function
-in C, C++ or Java, or to a @code{procedure} in Ada.  Thus, it may be 
appropriate to not
-return any value; simply bear in mind that you should not be using the
-return value of such a function.
+    quicksort_swap(data, left, int((left + right) / 2))
+    last = left
+    for (i = left + 1; i <= right; i++)
+        if (@@less_than(data[i], data[left]))
+            quicksort_swap(data, ++last, i)
+    quicksort_swap(data, left, last)
+    quicksort(data, left, last - 1, less_than)
+    quicksort(data, last + 1, right, less_than)
address@hidden
 
-The following is an example of a user-defined function that returns a value
-for the largest number among the elements of an array:
+# quicksort_swap --- helper function for quicksort, should really be inline
 
address@hidden
-function maxelt(vec,   i, ret)
+function quicksort_swap(data, i, j, temp)
 @{
-     for (i in vec) @{
-          if (ret == "" || vec[i] > ret)
-               ret = vec[i]
-     @}
-     return ret
+    temp = data[i]
+    data[i] = data[j]
+    data[j] = temp
 @}
address@hidden endfile
 @end example
 
address@hidden programming conventions, function parameters
address@hidden
-You call @code{maxelt()} with one argument, which is an array name.  The local
-variables @code{i} and @code{ret} are not intended to be arguments;
-while there is nothing to stop you from passing more than one argument
-to @code{maxelt()}, the results would be strange.  The extra space before
address@hidden in the function parameter list indicates that @code{i} and
address@hidden are local variables.
-You should follow this convention when defining functions.
+The @code{quicksort()} function receives the @code{data} array, the starting 
and ending
+indices to sort (@code{left} and @code{right}), and the name of a function that
+performs a ``less than'' comparison.  It then implements the quick sort 
algorithm.
 
-The following program uses the @code{maxelt()} function.  It loads an
-array, calls @code{maxelt()}, and then reports the maximum number in that
-array:
+To make use of the sorting function, we return to our previous example. The
+first thing to do is write some comparison functions:
 
 @example
-function maxelt(vec,   i, ret)
address@hidden
-     for (i in vec) @{
-          if (ret == "" || vec[i] > ret)
-               ret = vec[i]
-     @}
-     return ret
address@hidden
address@hidden file eg/prog/indirectcall.awk
+# num_lt --- do a numeric less than comparison
 
-# Load all fields of each record into nums.
+function num_lt(left, right)
 @{
-     for(i = 1; i <= NF; i++)
-          nums[NR, i] = $i
address@hidden
-
-END @{
-     print maxelt(nums)
+    return ((left + 0) < (right + 0))
 @}
address@hidden example
 
-Given the following input:
+# num_ge --- do a numeric greater than or equal to comparison
 
address@hidden
- 1 5 23 8 16
-44 3 5 2 8 26
-256 291 1396 2962 100
--6 467 998 1101
-99385 11 0 225
+function num_ge(left, right)
address@hidden
+    return ((left + 0) >= (right + 0))
address@hidden
address@hidden endfile
 @end example
 
address@hidden
-the program reports (predictably) that 99,385 is the largest value
-in the array.
-
address@hidden Dynamic Typing
address@hidden Functions and Their Effects on Variable Typing
+The @code{num_ge()} function is needed to perform a descending sort; when used
+to perform a ``less than'' test, it actually does the opposite (greater than
+or equal to), which yields data sorted in descending order.
 
address@hidden is a very fluid language.
-It is possible that @command{awk} can't tell if an identifier
-represents a scalar variable or an array until runtime.
-Here is an annotated sample program:
+Next comes a sorting function.  It is parameterized with the starting and
+ending field numbers and the comparison function. It builds an array with
+the data and calls @code{quicksort} appropriately, and then formats the
+results as a single string:
 
 @example
-function foo(a)
address@hidden file eg/prog/indirectcall.awk
+# do_sort --- sort the data according to `compare'
+#             and return it as a string
+
+function do_sort(first, last, compare,      data, i, retval)
 @{
-    a[1] = 1   # parameter is an array
address@hidden
+    delete data
+    for (i = 1; first <= last; first++) @{
+        data[i] = $first
+        i++
+    @}
 
-BEGIN @{
-    b = 1
-    foo(b)  # invalid: fatal type mismatch
+    quicksort(data, 1, i-1, compare)
 
-    foo(x)  # x uninitialized, becomes an array dynamically
-    x = 1   # now not allowed, runtime error
+    retval = data[1]
+    for (i = 2; i in data; i++)
+        retval = retval " " data[i]
+    
+    return retval
 @}
address@hidden endfile
 @end example
 
-Usually, such things aren't a big issue, but it's worth
-being aware of them.
address@hidden ENDOFRANGE udfunc
+Finally, the two sorting functions call @code{do_sort()}, passing in the
+names of the two comparison functions:
 
address@hidden Indirect Calls
address@hidden Indirect Function Calls
address@hidden
address@hidden file eg/prog/indirectcall.awk
+# sort --- sort the data in ascending order and return it as a string
 
address@hidden indirect function calls
address@hidden function calls, indirect
address@hidden function pointers
address@hidden pointers to functions
address@hidden differences in @command{awk} and @command{gawk}, indirect 
function calls
+function sort(first, last)
address@hidden
+    return do_sort(first, last, "num_lt")
address@hidden
 
-This section describes a @command{gawk}-specific extension.
+# rsort --- sort the data in descending order and return it as a string
 
-Often, you may wish to defer the choice of function to call until runtime.
-For example, you may have different kinds of records, each of which
-should be processed differently.
+function rsort(first, last)
address@hidden
+    return do_sort(first, last, "num_ge")
address@hidden
address@hidden endfile
address@hidden example
 
-Normally, you would have to use a series of @address@hidden
-statements to decide which function to call.  By using @dfn{indirect}
-function calls, you can specify the name of the function to call as a
-string variable, and then call the function.  Let's look at an example.
+Here is an extended version of the data file:
 
-Suppose you have a file with your test scores for the classes you
-are taking.  The first field is the class name. The following fields
-are the functions to call to process the data, up to a ``marker''
-field @samp{data:}.  Following the marker, to the end of the record,
-are the various numeric test scores.
address@hidden
address@hidden file eg/data/class_data2
+Biology_101 sum average sort rsort data: 87.0 92.4 78.5 94.9
+Chemistry_305 sum average sort rsort data: 75.2 98.3 94.7 88.2
+English_401 sum average sort rsort data: 100.0 95.6 87.1 93.4
address@hidden endfile
address@hidden example
 
-Here is the initial file; you wish to get the sum and the average of
-your test scores:
+Finally, here are the results when the enhanced program is run:
 
 @example
address@hidden file eg/data/class_data1
-Biology_101 sum average data: 87.0 92.4 78.5 94.9
-Chemistry_305 sum average data: 75.2 98.3 94.7 88.2
-English_401 sum average data: 100.0 95.6 87.1 93.4
address@hidden endfile
+$ @kbd{gawk -f quicksort.awk -f indirectcall.awk class_data2}
address@hidden Biology 101:
address@hidden     sum: <352.8>
address@hidden     average: <88.2>
address@hidden     sort: <78.5 87.0 92.4 94.9>
address@hidden     rsort: <94.9 92.4 87.0 78.5>
address@hidden 
address@hidden Chemistry 305:
address@hidden     sum: <356.4>
address@hidden     average: <89.1>
address@hidden     sort: <75.2 88.2 94.7 98.3>
address@hidden     rsort: <98.3 94.7 88.2 75.2>
address@hidden 
address@hidden English 401:
address@hidden     sum: <376.1>
address@hidden     average: <94.025>
address@hidden     sort: <87.1 93.4 95.6 100.0>
address@hidden     rsort: <100.0 95.6 93.4 87.1>
 @end example
 
-To process the data, you might write initially:
+Remember that you must supply a leading @samp{@@} in front of an indirect 
function call.
+
+Unfortunately, indirect function calls cannot be used with the built-in 
functions.  However,
+you can generally write ``wrapper'' functions which call the built-in ones, 
and those can
+be called indirectly. (Other than, perhaps, the mathematical functions, there 
is not a lot
+of reason to try to call the built-in functions indirectly.)
+
address@hidden does its best to make indirect function calls efficient.
+For example, in the following case:
 
 @example
address@hidden
-    class = $1
-    for (i = 2; $i != "data:"; i++) @{
-        if ($i == "sum")
-            sum()   # processes the whole record
-        else if ($i == "average")
-            average()
-        @dots{}           # and so on
-    @}
address@hidden
+for (i = 1; i <= n; i++)
+    @@the_func()
 @end example
 
 @noindent
-This style of programming works, but can be awkward.  With @dfn{indirect}
-function calls, you tell @command{gawk} to use the @emph{value} of a
-variable as the name of the function to call.
address@hidden will look up the actual function to call only once.
 
-The syntax is similar to that of a regular function call: an identifier
-immediately followed by a left parenthesis, any arguments, and then
-a closing right parenthesis, with the addition of a leading @samp{@@}
-character:
address@hidden ENDOFRANGE funcud
 
address@hidden
-the_func = "sum"
-result = @@the_func()   # calls the `sum' function
address@hidden example
address@hidden Internationalization
address@hidden Internationalization with @command{gawk}
 
-Here is a full program that processes the previously shown data,
-using indirect function calls.
+Once upon a time, computer makers
+wrote software that worked only in English.
+Eventually, hardware and software vendors noticed that if their
+systems worked in the native languages of non-English-speaking
+countries, they were able to sell more systems.
+As a result, internationalization and localization
+of programs and software systems became a common practice.
 
address@hidden
address@hidden file eg/prog/indirectcall.awk
-# indirectcall.awk --- Demonstrate indirect function calls
address@hidden endfile
address@hidden
address@hidden file eg/prog/indirectcall.awk
-#
-# Arnold Robbins, address@hidden, Public Domain
-# January 2009
address@hidden endfile
address@hidden ignore
address@hidden STARTOFRANGE inloc
address@hidden internationalization, localization
address@hidden @command{gawk}, internationalization and, See 
internationalization
address@hidden internationalization, localization, @command{gawk} and
+For many years, the ability to provide internationalization
+was largely restricted to programs written in C and C++.
+This @value{CHAPTER} describes the underlying library @command{gawk}
+uses for internationalization, as well as how
address@hidden makes internationalization
+features available at the @command{awk} program level.
+Having internationalization available at the @command{awk} level
+gives software developers additional flexibility---they are no
+longer forced to write in C or C++ when internationalization is
+a requirement.
 
address@hidden file eg/prog/indirectcall.awk
-# average --- return the average of the values in fields $first - $last
address@hidden
+* I18N and L10N::               Internationalization and Localization.
+* Explaining gettext::          How GNU @code{gettext} works.
+* Programmer i18n::             Features for the programmer.
+* Translator i18n::             Features for the translator.
+* I18N Example::                A simple i18n example.
+* Gawk I18N::                   @command{gawk} is also internationalized.
address@hidden menu
 
-function average(first, last,   sum, i)
address@hidden
-    sum = 0;
-    for (i = first; i <= last; i++)
-        sum += $i
address@hidden I18N and L10N
address@hidden Internationalization and Localization
 
-    return sum / (last - first + 1)
address@hidden
address@hidden internationalization
address@hidden localization, See address@hidden localization
address@hidden localization
address@hidden means writing (or modifying) a program once,
+in such a way that it can use multiple languages without requiring
+further source-code changes.
address@hidden means providing the data necessary for an
+internationalized program to work in a particular language.
+Most typically, these terms refer to features such as the language
+used for printing error messages, the language used to read
+responses, and information related to how numerical and
+monetary values are printed and read.
 
-# sum --- return the sum of the values in fields $first - $last
address@hidden Explaining gettext
address@hidden GNU @code{gettext}
 
-function sum(first, last,   ret, i)
address@hidden
-    ret = 0;
-    for (i = first; i <= last; i++)
-        ret += $i
address@hidden internationalizing a program
address@hidden STARTOFRANGE gettex
address@hidden @code{gettext} library
+The facilities in GNU @code{gettext} focus on messages; strings printed
+by a program, either directly or via formatting with @code{printf} or
address@hidden()address@hidden some operating systems, the @command{gawk}
+port doesn't support GNU @code{gettext}.
+Therefore, these features are not available
+if you are using one of those operating systems. Sorry.}
 
-    return ret
address@hidden
address@hidden endfile
address@hidden example
address@hidden portability, @code{gettext} library and
+When using GNU @code{gettext}, each application has its own
address@hidden domain}.  This is a unique name, such as @samp{kpilot} or 
@samp{gawk},
+that identifies the application.
+A complete application may have multiple components---programs written
+in C or C++, as well as scripts written in @command{sh} or @command{awk}.
+All of the components use the same text domain.
 
-These two functions expect to work on fields; thus the parameters
address@hidden and @code{last} indicate where in the fields to start and end.
-Otherwise they perform the expected computations and are not unusual.
+To make the discussion concrete, assume we're writing an application
+named @command{guide}.  Internationalization consists of the
+following steps, in this order:
 
address@hidden
address@hidden file eg/prog/indirectcall.awk
-# For each record, print the class name and the requested statistics
address@hidden
address@hidden
+The programmer goes
+through the source for all of @command{guide}'s components
+and marks each string that is a candidate for translation.
+For example, @code{"`-F': option required"} is a good candidate for 
translation.
+A table with strings of option names is not (e.g., @command{gawk}'s
address@hidden option should remain the same, no matter what the local
+language).
 
address@hidden
-    class_name = $1
-    gsub(/_/, " ", class_name)  # Replace _ with spaces
address@hidden @code{textdomain()} function (C library)
address@hidden
+The programmer indicates the application's text domain
+(@code{"guide"}) to the @code{gettext} library,
+by calling the @code{textdomain()} function.
 
-    # find start
-    for (i = 1; i <= NF; i++) @{
-        if ($i == "data:") @{
-            start = i + 1
-            break
-        @}
-    @}
address@hidden @code{.pot} files
address@hidden files, @code{.pot}
address@hidden portable object template files
address@hidden files, portable object template
address@hidden
+Messages from the application are extracted from the source code and
+collected into a portable object template file (@file{guide.pot}),
+which lists the strings and their translations.
+The translations are initially empty.
+The original (usually English) messages serve as the key for
+lookup of the translations.
 
-    printf("%s:\n", class_name)
-    for (i = 2; $i != "data:"; i++) @{
-        the_function = $i
-        printf("\t%s: <%s>\n", $i, @@the_function(start, NF) "")
-    @}
-    print ""
address@hidden
address@hidden endfile
address@hidden example
address@hidden @code{.po} files
address@hidden files, @code{.po}
address@hidden portable object files
address@hidden files, portable object
address@hidden
+For each language with a translator, @file{guide.pot}
+is copied to a portable object file (@code{.po})
+and translations are created and shipped with the application.
+For example, there might be a @file{fr.po} for a French translation.
 
-This is the main processing for each record. It prints the class name (with
-underscores replaced with spaces). It then finds the start of the actual data,
-saving it in @code{start}.
-The last part of the code loops through each function name (from @code{$2} up 
to
-the marker, @samp{data:}), calling the function named by the field. The 
indirect
-function call itself occurs as a parameter in the call to @code{printf}.
-(The @code{printf} format string uses @samp{%s} as the format specifier so 
that we
-can use functions that return strings, as well as numbers. Note that the result
-from the indirect call is concatenated with the empty string, in order to force
-it to be a string value.)
address@hidden @code{.mo} files
address@hidden files, @code{.mo}
address@hidden message object files
address@hidden files, message object
address@hidden
+Each language's @file{.po} file is converted into a binary
+message object (@file{.mo}) file.
+A message object file contains the original messages and their
+translations in a binary format that allows fast lookup of translations
+at runtime.
+
address@hidden
+When @command{guide} is built and installed, the binary translation files
+are installed in a standard place.
+
address@hidden @code{bindtextdomain()} function (C library)
address@hidden
+For testing and development, it is possible to tell @code{gettext}
+to use @file{.mo} files in a different directory than the standard
+one by using the @code{bindtextdomain()} function.
+
address@hidden @code{.mo} files, specifying directory of
address@hidden files, @code{.mo}, specifying directory of
address@hidden message object files, specifying directory of
address@hidden files, message object, specifying directory of
address@hidden
+At runtime, @command{guide} looks up each string via a call
+to @code{gettext()}.  The returned string is the translated string
+if available, or the original string if not.
 
-Here is the result of running the program:
address@hidden
+If necessary, it is possible to access messages from a different
+text domain than the one belonging to the application, without
+having to switch the application's default text domain back
+and forth.
address@hidden enumerate
+
address@hidden @code{gettext()} function (C library)
+In C (or C++), the string marking and dynamic translation lookup
+are accomplished by wrapping each string in a call to @code{gettext()}:
 
 @example
-$ @kbd{gawk -f indirectcall.awk class_data1}
address@hidden Biology 101:
address@hidden     sum: <352.8>
address@hidden     average: <88.2>
address@hidden 
address@hidden Chemistry 305:
address@hidden     sum: <356.4>
address@hidden     average: <89.1>
address@hidden 
address@hidden English 401:
address@hidden     sum: <376.1>
address@hidden     average: <94.025>
+printf("%s", gettext("Don't Panic!\n"));
 @end example
 
-The ability to use indirect function calls is more powerful than you may
-think at first.  The C and C++ languages provide ``function pointers,'' which
-are a mechanism for calling a function chosen at runtime.  One of the most
-well-known uses of this ability is the C @code{qsort()} function, which sorts
-an array using the famous ``quick sort'' algorithm
-(see @uref{http://en.wikipedia.org/wiki/Quick_sort, the Wikipedia article}
-for more information).  To use this function, you supply a pointer to a 
comparison
-function.  This mechanism allows you to sort arbitrary data in an arbitrary
-fashion.
+The tools that extract messages from source code pull out all
+strings enclosed in calls to @code{gettext()}.
 
-We can do something similar using @command{gawk}, like this:
address@hidden @code{_} (underscore), @code{_} C macro
address@hidden underscore (@code{_}), @code{_} C macro
+The GNU @code{gettext} developers, recognizing that typing
address@hidden(@dots{})} over and over again is both painful and ugly to look
+at, use the macro @samp{_} (an underscore) to make things easier:
 
 @example
address@hidden file eg/lib/quicksort.awk
-# quicksort.awk --- Quicksort algorithm, with user-supplied
-#                   comparison function
address@hidden endfile
address@hidden
address@hidden file eg/lib/quicksort.awk
-#
-# Arnold Robbins, address@hidden, Public Domain
-# January 2009
address@hidden endfile
+/* In the standard header file: */
+#define _(str) gettext(str)
 
address@hidden ignore
address@hidden file eg/lib/quicksort.awk
-# quicksort --- C.A.R. Hoare's quick sort algorithm. See Wikipedia
-#               or almost any algorithms or computer science text
address@hidden endfile
address@hidden
address@hidden file eg/lib/quicksort.awk
-#
-# Adapted from K&R-II, page 110
address@hidden ignore
address@hidden file eg/lib/quicksort.awk
+/* In the program text: */
+printf("%s", _("Don't Panic!\n"));
address@hidden example
 
-function quicksort(data, left, right, less_than,    i, last)
address@hidden
-    if (left >= right)  # do nothing if array contains fewer
-        return          # than two elements
address@hidden internationalization, localization, locale categories
address@hidden @code{gettext} library, locale categories
address@hidden locale categories
address@hidden
+This reduces the typing overhead to just three extra characters per string
+and is considerably easier to read as well.
 
-    quicksort_swap(data, left, int((left + right) / 2))
-    last = left
-    for (i = left + 1; i <= right; i++)
-        if (@@less_than(data[i], data[left]))
-            quicksort_swap(data, ++last, i)
-    quicksort_swap(data, left, last)
-    quicksort(data, left, last - 1, less_than)
-    quicksort(data, last + 1, right, less_than)
address@hidden
+There are locale @dfn{categories}
+for different types of locale-related information.
+The defined locale categories that @code{gettext} knows about are:
 
-# quicksort_swap --- helper function for quicksort, should really be inline
address@hidden @code
address@hidden @code{LC_MESSAGES} locale category
address@hidden LC_MESSAGES
+Text messages.  This is the default category for @code{gettext}
+operations, but it is possible to supply a different one explicitly,
+if necessary.  (It is almost never necessary to supply a different category.)
 
-function quicksort_swap(data, i, j, temp)
address@hidden
-    temp = data[i]
-    data[i] = data[j]
-    data[j] = temp
address@hidden
address@hidden endfile
address@hidden example
address@hidden sorting characters in different languages
address@hidden @code{LC_COLLATE} locale category
address@hidden LC_COLLATE
+Text-collation information; i.e., how different characters
+and/or groups of characters sort in a given language.
 
-The @code{quicksort()} function receives the @code{data} array, the starting 
and ending
-indices to sort (@code{left} and @code{right}), and the name of a function that
-performs a ``less than'' comparison.  It then implements the quick sort 
algorithm.
address@hidden @code{LC_CTYPE} locale category
address@hidden LC_CTYPE
+Character-type information (alphabetic, digit, upper- or lowercase, and
+so on).
+This information is accessed via the
+POSIX character classes in regular expressions,
+such as @code{/[[:alnum:]]/}
+(@pxref{Regexp Operators}).
 
-To make use of the sorting function, we return to our previous example. The
-first thing to do is write some comparison functions:
address@hidden monetary information, localization
address@hidden currency symbols, localization
address@hidden @code{LC_MONETARY} locale category
address@hidden LC_MONETARY
+Monetary information, such as the currency symbol, and whether the
+symbol goes before or after a number.
 
address@hidden
address@hidden file eg/prog/indirectcall.awk
-# num_lt --- do a numeric less than comparison
address@hidden @code{LC_NUMERIC} locale category
address@hidden LC_NUMERIC
+Numeric information, such as which characters to use for the decimal
+point and the thousands address@hidden
+use a comma every three decimal places and a period for the decimal
+point, while many Europeans do exactly the opposite:
+1,234.56 versus 1.234,56.}
 
-function num_lt(left, right)
address@hidden
-    return ((left + 0) < (right + 0))
address@hidden
address@hidden @code{LC_RESPONSE} locale category
address@hidden LC_RESPONSE
+Response information, such as how ``yes'' and ``no'' appear in the
+local language, and possibly other information as well.
 
-# num_ge --- do a numeric greater than or equal to comparison
address@hidden time, localization and
address@hidden dates, information related address@hidden localization
address@hidden @code{LC_TIME} locale category
address@hidden LC_TIME
+Time- and date-related information, such as 12- or 24-hour clock, month printed
+before or after the day in a date, local month abbreviations, and so on.
 
-function num_ge(left, right)
address@hidden
-    return ((left + 0) >= (right + 0))
address@hidden
address@hidden endfile
address@hidden example
address@hidden @code{LC_ALL} locale category
address@hidden LC_ALL
+All of the above.  (Not too useful in the context of @code{gettext}.)
address@hidden table
address@hidden ENDOFRANGE gettex
 
-The @code{num_ge()} function is needed to perform a descending sort; when used
-to perform a ``less than'' test, it actually does the opposite (greater than
-or equal to), which yields data sorted in descending order.
address@hidden Programmer i18n
address@hidden Internationalizing @command{awk} Programs
address@hidden STARTOFRANGE inap
address@hidden @command{awk} programs, internationalizing
 
-Next comes a sorting function.  It is parameterized with the starting and
-ending field numbers and the comparison function. It builds an array with
-the data and calls @code{quicksort} appropriately, and then formats the
-results as a single string:
address@hidden provides the following variables and functions for
+internationalization:
 
address@hidden
address@hidden file eg/prog/indirectcall.awk
-# do_sort --- sort the data according to `compare'
-#             and return it as a string
address@hidden @code
address@hidden @code{TEXTDOMAIN} variable
address@hidden TEXTDOMAIN
+This variable indicates the application's text domain.
+For compatibility with GNU @code{gettext}, the default
+value is @code{"messages"}.
 
-function do_sort(first, last, compare,      data, i, retval)
address@hidden
-    delete data
-    for (i = 1; first <= last; first++) @{
-        data[i] = $first
-        i++
-    @}
address@hidden internationalization, localization, marked strings
address@hidden strings, for localization
address@hidden _"your message here"
+String constants marked with a leading underscore
+are candidates for translation at runtime.
+String constants without a leading underscore are not translated.
 
-    quicksort(data, 1, i-1, compare)
address@hidden @code{dcgettext()} function (@command{gawk})
address@hidden dcgettext(@var{string} @r{[}, @var{domain} @r{[}, 
@address@hidden)
+Return the translation of @var{string} in
+text domain @var{domain} for locale category @var{category}.
+The default value for @var{domain} is the current value of @code{TEXTDOMAIN}.
+The default value for @var{category} is @code{"LC_MESSAGES"}.
 
-    retval = data[1]
-    for (i = 2; i in data; i++)
-        retval = retval " " data[i]
-    
-    return retval
address@hidden
address@hidden endfile
address@hidden example
+If you supply a value for @var{category}, it must be a string equal to
+one of the known locale categories described in
address@hidden
+the previous @value{SECTION}.
address@hidden ifnotinfo
address@hidden
address@hidden gettext}.
address@hidden ifinfo
+You must also supply a text domain.  Use @code{TEXTDOMAIN} if
+you want to use the current domain.
 
-Finally, the two sorting functions call @code{do_sort()}, passing in the
-names of the two comparison functions:
address@hidden CAUTION
+The order of arguments to the @command{awk} version
+of the @code{dcgettext()} function is purposely different from the order for
+the C version.  The @command{awk} version's order was
+chosen to be simple and to allow for reasonable @command{awk}-style
+default arguments.
address@hidden quotation
+
address@hidden @code{dcngettext()} function (@command{gawk})
address@hidden dcngettext(@var{string1}, @var{string2}, @var{number} @r{[}, 
@var{domain} @r{[}, @address@hidden)
+Return the plural form used for @var{number} of the
+translation of @var{string1} and @var{string2} in text domain
address@hidden for locale category @var{category}. @var{string1} is the
+English singular variant of a message, and @var{string2} the English plural
+variant of the same message.
+The default value for @var{domain} is the current value of @code{TEXTDOMAIN}.
+The default value for @var{category} is @code{"LC_MESSAGES"}.
+
+The same remarks about argument order as for the @code{dcgettext()} function 
apply.
+
address@hidden @code{.mo} files, specifying directory of
address@hidden files, @code{.mo}, specifying directory of
address@hidden message object files, specifying directory of
address@hidden files, message object, specifying directory of
address@hidden @code{bindtextdomain()} function (@command{gawk})
address@hidden bindtextdomain(@var{directory} @r{[}, @address@hidden)
+Change the directory in which
address@hidden looks for @file{.mo} files, in case they
+will not or cannot be placed in the standard locations
+(e.g., during testing).
+Return the directory in which @var{domain} is ``bound.''
 
address@hidden
address@hidden file eg/prog/indirectcall.awk
-# sort --- sort the data in ascending order and return it as a string
+The default @var{domain} is the value of @code{TEXTDOMAIN}.
+If @var{directory} is the null string (@code{""}), then
address@hidden()} returns the current binding for the
+given @var{domain}.
address@hidden table
 
-function sort(first, last)
address@hidden
-    return do_sort(first, last, "num_lt")
address@hidden
+To use these facilities in your @command{awk} program, follow the steps
+outlined in
address@hidden
+the previous @value{SECTION},
address@hidden ifnotinfo
address@hidden
address@hidden gettext},
address@hidden ifinfo
+like so:
 
-# rsort --- sort the data in descending order and return it as a string
address@hidden
address@hidden @code{BEGIN} pattern, @code{TEXTDOMAIN} variable and
address@hidden @code{TEXTDOMAIN} variable, @code{BEGIN} pattern and
address@hidden
+Set the variable @code{TEXTDOMAIN} to the text domain of
+your program.  This is best done in a @code{BEGIN} rule
+(@pxref{BEGIN/END}),
+or it can also be done via the @option{-v} command-line
+option (@pxref{Options}):
 
-function rsort(first, last)
address@hidden
-    return do_sort(first, last, "num_ge")
address@hidden
+BEGIN @{
+    TEXTDOMAIN = "guide"
+    @dots{}
 @}
address@hidden endfile
 @end example
 
-Here is an extended version of the data file:
address@hidden @code{_} (underscore), translatable string
address@hidden underscore (@code{_}), translatable string
address@hidden
+Mark all translatable strings with a leading underscore (@samp{_})
+character.  It @emph{must} be adjacent to the opening
+quote of the string.  For example:
 
 @example
address@hidden file eg/data/class_data2
-Biology_101 sum average sort rsort data: 87.0 92.4 78.5 94.9
-Chemistry_305 sum average sort rsort data: 75.2 98.3 94.7 88.2
-English_401 sum average sort rsort data: 100.0 95.6 87.1 93.4
address@hidden endfile
+print _"hello, world"
+x = _"you goofed"
+printf(_"Number of users is %d\n", nusers)
 @end example
 
-Finally, here are the results when the enhanced program is run:
address@hidden
+If you are creating strings dynamically, you can
+still translate them, using the @code{dcgettext()}
+built-in function:
 
 @example
-$ @kbd{gawk -f quicksort.awk -f indirectcall.awk class_data2}
address@hidden Biology 101:
address@hidden     sum: <352.8>
address@hidden     average: <88.2>
address@hidden     sort: <78.5 87.0 92.4 94.9>
address@hidden     rsort: <94.9 92.4 87.0 78.5>
address@hidden 
address@hidden Chemistry 305:
address@hidden     sum: <356.4>
address@hidden     average: <89.1>
address@hidden     sort: <75.2 88.2 94.7 98.3>
address@hidden     rsort: <98.3 94.7 88.2 75.2>
address@hidden 
address@hidden English 401:
address@hidden     sum: <376.1>
address@hidden     average: <94.025>
address@hidden     sort: <87.1 93.4 95.6 100.0>
address@hidden     rsort: <100.0 95.6 93.4 87.1>
+message = nusers " users logged in"
+message = dcgettext(message, "adminprog")
+print message
 @end example
 
-Remember that you must supply a leading @samp{@@} in front of an indirect 
function call.
-
-Unfortunately, indirect function calls cannot be used with the built-in 
functions.  However,
-you can generally write ``wrapper'' functions which call the built-in ones, 
and those can
-be called indirectly. (Other than, perhaps, the mathematical functions, there 
is not a lot
-of reason to try to call the built-in functions indirectly.)
+Here, the call to @code{dcgettext()} supplies a different
+text domain (@code{"adminprog"}) in which to find the
+message, but it uses the default @code{"LC_MESSAGES"} category.
 
address@hidden does its best to make indirect function calls efficient.
-For example, in the following case:
address@hidden @code{LC_MESSAGES} locale category, @code{bindtextdomain()} 
function (@command{gawk})
address@hidden
+During development, you might want to put the @file{.mo}
+file in a private directory for testing.  This is done
+with the @code{bindtextdomain()} built-in function:
 
 @example
-for (i = 1; i <= n; i++)
-    @@the_func()
+BEGIN @{
+   TEXTDOMAIN = "guide"   # our text domain
+   if (Testing) @{
+       # where to find our files
+       bindtextdomain("testdir")
+       # joe is in charge of adminprog
+       bindtextdomain("../joe/testdir", "adminprog")
+   @}
+   @dots{}
address@hidden
 @end example
 
address@hidden
address@hidden will look up the actual function to call only once.
address@hidden enumerate
 
address@hidden ENDOFRANGE funcud
address@hidden Example},
+for an example program showing the steps to create
+and use translations from @command{awk}.
 
address@hidden Internationalization
address@hidden Internationalization with @command{gawk}
address@hidden Translator i18n
address@hidden Translating @command{awk} Programs
 
-Once upon a time, computer makers
-wrote software that worked only in English.
-Eventually, hardware and software vendors noticed that if their
-systems worked in the native languages of non-English-speaking
-countries, they were able to sell more systems.
-As a result, internationalization and localization
-of programs and software systems became a common practice.
address@hidden @code{.po} files
address@hidden files, @code{.po}
address@hidden portable object files
address@hidden files, portable object
+Once a program's translatable strings have been marked, they must
+be extracted to create the initial @file{.po} file.
+As part of translation, it is often helpful to rearrange the order
+in which arguments to @code{printf} are output.
 
address@hidden STARTOFRANGE inloc
address@hidden internationalization, localization
address@hidden @command{gawk}, internationalization and, See 
internationalization
address@hidden internationalization, localization, @command{gawk} and
-For many years, the ability to provide internationalization
-was largely restricted to programs written in C and C++.
-This @value{CHAPTER} describes the underlying library @command{gawk}
-uses for internationalization, as well as how
address@hidden makes internationalization
-features available at the @command{awk} program level.
-Having internationalization available at the @command{awk} level
-gives software developers additional flexibility---they are no
-longer forced to write in C or C++ when internationalization is
-a requirement.
address@hidden's @option{--gen-pot} command-line option extracts
+the messages and is discussed next.
+After that, @code{printf}'s ability to
+rearrange the order for @code{printf} arguments at runtime
+is covered.
 
 @menu
-* I18N and L10N::               Internationalization and Localization.
-* Explaining gettext::          How GNU @code{gettext} works.
-* Programmer i18n::             Features for the programmer.
-* Translator i18n::             Features for the translator.
-* I18N Example::                A simple i18n example.
-* Gawk I18N::                   @command{gawk} is also internationalized.
+* String Extraction::           Extracting marked strings.
+* Printf Ordering::             Rearranging @code{printf} arguments.
+* I18N Portability::            @command{awk}-level portability issues.
 @end menu
 
address@hidden I18N and L10N
address@hidden Internationalization and Localization
-
address@hidden internationalization
address@hidden localization, See address@hidden localization
address@hidden localization
address@hidden means writing (or modifying) a program once,
-in such a way that it can use multiple languages without requiring
-further source-code changes.
address@hidden means providing the data necessary for an
-internationalized program to work in a particular language.
-Most typically, these terms refer to features such as the language
-used for printing error messages, the language used to read
-responses, and information related to how numerical and
-monetary values are printed and read.
address@hidden String Extraction
address@hidden Extracting Marked Strings
address@hidden strings, extracting
address@hidden marked address@hidden extracting
address@hidden @code{--gen-pot} option
address@hidden command-line options, string extraction
address@hidden string extraction (internationalization)
address@hidden marked string extraction (internationalization)
address@hidden extraction, of marked strings (internationalization)
 
address@hidden Explaining gettext
address@hidden GNU @code{gettext}
address@hidden @code{--gen-pot} option
+Once your @command{awk} program is working, and all the strings have
+been marked and you've set (and perhaps bound) the text domain,
+it is time to produce translations.
+First, use the @option{--gen-pot} command-line option to create
+the initial @file{.pot} file:
 
address@hidden internationalizing a program
address@hidden STARTOFRANGE gettex
address@hidden @code{gettext} library
-The facilities in GNU @code{gettext} focus on messages; strings printed
-by a program, either directly or via formatting with @code{printf} or
address@hidden()address@hidden some operating systems, the @command{gawk}
-port doesn't support GNU @code{gettext}.
-Therefore, these features are not available
-if you are using one of those operating systems. Sorry.}
address@hidden
+$ @kbd{gawk --gen-pot -f guide.awk > guide.pot}
address@hidden example
 
address@hidden portability, @code{gettext} library and
-When using GNU @code{gettext}, each application has its own
address@hidden domain}.  This is a unique name, such as @samp{kpilot} or 
@samp{gawk},
-that identifies the application.
-A complete application may have multiple components---programs written
-in C or C++, as well as scripts written in @command{sh} or @command{awk}.
-All of the components use the same text domain.
address@hidden @code{xgettext} utility
+When run with @option{--gen-pot}, @command{gawk} does not execute your
+program.  Instead, it parses it as usual and prints all marked strings
+to standard output in the format of a GNU @code{gettext} Portable Object
+file.  Also included in the output are any constant strings that
+appear as the first argument to @code{dcgettext()} or as the first and
+second argument to @code{dcngettext()address@hidden
address@hidden utility that comes with GNU
address@hidden can handle @file{.awk} files.}
address@hidden Example},
+for the full list of steps to go through to create and test
+translations for @command{guide}.
 
-To make the discussion concrete, assume we're writing an application
-named @command{guide}.  Internationalization consists of the
-following steps, in this order:
address@hidden Printf Ordering
address@hidden Rearranging @code{printf} Arguments
 
address@hidden
address@hidden
-The programmer goes
-through the source for all of @command{guide}'s components
-and marks each string that is a candidate for translation.
-For example, @code{"`-F': option required"} is a good candidate for 
translation.
-A table with strings of option names is not (e.g., @command{gawk}'s
address@hidden option should remain the same, no matter what the local
-language).
address@hidden @code{printf} statement, positional specifiers
address@hidden positional specifiers, @code{printf} statement
+Format strings for @code{printf} and @code{sprintf()}
+(@pxref{Printf})
+present a special problem for translation.
+Consider the following:@footnote{This example is borrowed
+from the GNU @code{gettext} manual.}
 
address@hidden @code{textdomain()} function (C library)
address@hidden
-The programmer indicates the application's text domain
-(@code{"guide"}) to the @code{gettext} library,
-by calling the @code{textdomain()} function.
address@hidden line broken here only for smallbook format
address@hidden
+printf(_"String `%s' has %d characters\n",
+          string, length(string)))
address@hidden example
 
address@hidden @code{.pot} files
address@hidden files, @code{.pot}
address@hidden portable object template files
address@hidden files, portable object template
address@hidden
-Messages from the application are extracted from the source code and
-collected into a portable object template file (@file{guide.pot}),
-which lists the strings and their translations.
-The translations are initially empty.
-The original (usually English) messages serve as the key for
-lookup of the translations.
+A possible German translation for this might be:
 
address@hidden @code{.po} files
address@hidden files, @code{.po}
address@hidden portable object files
address@hidden files, portable object
address@hidden
-For each language with a translator, @file{guide.pot}
-is copied to a portable object file (@code{.po})
-and translations are created and shipped with the application.
-For example, there might be a @file{fr.po} for a French translation.
address@hidden
+"%d Zeichen lang ist die Zeichenkette `%s'\n"
address@hidden example
 
address@hidden @code{.mo} files
address@hidden files, @code{.mo}
address@hidden message object files
address@hidden files, message object
address@hidden
-Each language's @file{.po} file is converted into a binary
-message object (@file{.mo}) file.
-A message object file contains the original messages and their
-translations in a binary format that allows fast lookup of translations
-at runtime.
+The problem should be obvious: the order of the format
+specifications is different from the original!
+Even though @code{gettext()} can return the translated string
+at runtime,
+it cannot change the argument order in the call to @code{printf}.
 
address@hidden
-When @command{guide} is built and installed, the binary translation files
-are installed in a standard place.
+To solve this problem, @code{printf} format specifiers may have
+an additional optional element, which we call a @dfn{positional specifier}.
+For example:
 
address@hidden @code{bindtextdomain()} function (C library)
address@hidden
-For testing and development, it is possible to tell @code{gettext}
-to use @file{.mo} files in a different directory than the standard
-one by using the @code{bindtextdomain()} function.
address@hidden
+"%2$d Zeichen lang ist die Zeichenkette `%1$s'\n"
address@hidden example
 
address@hidden @code{.mo} files, specifying directory of
address@hidden files, @code{.mo}, specifying directory of
address@hidden message object files, specifying directory of
address@hidden files, message object, specifying directory of
address@hidden
-At runtime, @command{guide} looks up each string via a call
-to @code{gettext()}.  The returned string is the translated string
-if available, or the original string if not.
+Here, the positional specifier consists of an integer count, which indicates 
which
+argument to use, and a @samp{$}. Counts are one-based, and the
+format string itself is @emph{not} included.  Thus, in the following
+example, @samp{string} is the first argument and @samp{length(string)} is the 
second:
 
address@hidden
-If necessary, it is possible to access messages from a different
-text domain than the one belonging to the application, without
-having to switch the application's default text domain back
-and forth.
address@hidden enumerate
address@hidden
+$ @kbd{gawk 'BEGIN @{}
+>     @kbd{string = "Dont Panic"}
+>     @kbd{printf _"%2$d characters live in \"%1$s\"\n",}
+>                         @kbd{string, length(string)}
+> @address@hidden'}
address@hidden 10 characters live in "Dont Panic"
address@hidden example
 
address@hidden @code{gettext()} function (C library)
-In C (or C++), the string marking and dynamic translation lookup
-are accomplished by wrapping each string in a call to @code{gettext()}:
+If present, positional specifiers come first in the format specification,
+before the flags, the field width, and/or the precision.
+
+Positional specifiers can be used with the dynamic field width and
+precision capability:
 
 @example
-printf("%s", gettext("Don't Panic!\n"));
+$ @kbd{gawk 'BEGIN @{}
+>    @kbd{printf("%*.*s\n", 10, 20, "hello")}
+>    @kbd{printf("%3$*2$.*1$s\n", 20, 10, "hello")}
+> @address@hidden'}
address@hidden      hello
address@hidden      hello
 @end example
 
-The tools that extract messages from source code pull out all
-strings enclosed in calls to @code{gettext()}.
address@hidden NOTE
+When using @samp{*} with a positional specifier, the @samp{*}
+comes first, then the integer position, and then the @samp{$}.
+This is somewhat counterintuitive.
address@hidden quotation
 
address@hidden @code{_} (underscore), @code{_} C macro
address@hidden underscore (@code{_}), @code{_} C macro
-The GNU @code{gettext} developers, recognizing that typing
address@hidden(@dots{})} over and over again is both painful and ugly to look
-at, use the macro @samp{_} (an underscore) to make things easier:
address@hidden @code{printf} statement, positional specifiers, mixing with 
regular formats
address@hidden positional specifiers, @code{printf} statement, mixing with 
regular formats
address@hidden format specifiers, mixing regular with positional specifiers
address@hidden does not allow you to mix regular format specifiers
+and those with positional specifiers in the same string:
 
 @example
-/* In the standard header file: */
-#define _(str) gettext(str)
+$ @kbd{gawk 'BEGIN @{ printf _"%d %3$s\n", 1, 2, "hi" @}'}
address@hidden gawk: cmd. line:1: fatal: must use `count$' on all formats or 
none
address@hidden example
 
-/* In the program text: */
-printf("%s", _("Don't Panic!\n"));
address@hidden NOTE
+There are some pathological cases that @command{gawk} may fail to
+diagnose.  In such cases, the output may not be what you expect.
+It's still a bad idea to try mixing them, even if @command{gawk}
+doesn't detect it.
address@hidden quotation
+
+Although positional specifiers can be used directly in @command{awk} programs,
+their primary purpose is to help in producing correct translations of
+format strings into languages different from the one in which the program
+is first written.
+
address@hidden I18N Portability
address@hidden @command{awk} Portability Issues
+
address@hidden portability, internationalization and
address@hidden internationalization, localization, portability and
address@hidden's internationalization features were purposely chosen to
+have as little impact as possible on the portability of @command{awk}
+programs that use them to other versions of @command{awk}.
+Consider this program:
+
address@hidden
+BEGIN @{
+    TEXTDOMAIN = "guide"
+    if (Test_Guide)   # set with -v
+        bindtextdomain("/test/guide/messages")
+    print _"don't panic!"
address@hidden
 @end example
 
address@hidden internationalization, localization, locale categories
address@hidden @code{gettext} library, locale categories
address@hidden locale categories
 @noindent
-This reduces the typing overhead to just three extra characters per string
-and is considerably easier to read as well.
+As written, it won't work on other versions of @command{awk}.
+However, it is actually almost portable, requiring very little
+change:
 
-There are locale @dfn{categories}
-for different types of locale-related information.
-The defined locale categories that @code{gettext} knows about are:
address@hidden @bullet
address@hidden @code{TEXTDOMAIN} variable, portability and
address@hidden
+Assignments to @code{TEXTDOMAIN} won't have any effect,
+since @code{TEXTDOMAIN} is not special in other @command{awk} implementations.
 
address@hidden @code
address@hidden @code{LC_MESSAGES} locale category
address@hidden LC_MESSAGES
-Text messages.  This is the default category for @code{gettext}
-operations, but it is possible to supply a different one explicitly,
-if necessary.  (It is almost never necessary to supply a different category.)
address@hidden
+Non-GNU versions of @command{awk} treat marked strings
+as the concatenation of a variable named @code{_} with the string
+following address@hidden is good fodder for an ``Obfuscated
address@hidden'' contest.} Typically, the variable @code{_} has
+the null string (@code{""}) as its value, leaving the original string constant 
as
+the result.
 
address@hidden sorting characters in different languages
address@hidden @code{LC_COLLATE} locale category
address@hidden LC_COLLATE
-Text-collation information; i.e., how different characters
-and/or groups of characters sort in a given language.
address@hidden
+By defining ``dummy'' functions to replace @code{dcgettext()}, 
@code{dcngettext()}
+and @code{bindtextdomain()}, the @command{awk} program can be made to run, but
+all the messages are output in the original language.
+For example:
 
address@hidden @code{LC_CTYPE} locale category
address@hidden LC_CTYPE
-Character-type information (alphabetic, digit, upper- or lowercase, and
-so on).
-This information is accessed via the
-POSIX character classes in regular expressions,
-such as @code{/[[:alnum:]]/}
-(@pxref{Regexp Operators}).
address@hidden @code{bindtextdomain()} function (@command{gawk}), portability 
and
address@hidden @code{dcgettext()} function (@command{gawk}), portability and
address@hidden @code{dcngettext()} function (@command{gawk}), portability and
address@hidden
address@hidden file eg/lib/libintl.awk
+function bindtextdomain(dir, domain)
address@hidden
+    return dir
address@hidden
 
address@hidden monetary information, localization
address@hidden currency symbols, localization
address@hidden @code{LC_MONETARY} locale category
address@hidden LC_MONETARY
-Monetary information, such as the currency symbol, and whether the
-symbol goes before or after a number.
+function dcgettext(string, domain, category)
address@hidden
+    return string
address@hidden
 
address@hidden @code{LC_NUMERIC} locale category
address@hidden LC_NUMERIC
-Numeric information, such as which characters to use for the decimal
-point and the thousands address@hidden
-use a comma every three decimal places and a period for the decimal
-point, while many Europeans do exactly the opposite:
-1,234.56 versus 1.234,56.}
+function dcngettext(string1, string2, number, domain, category)
address@hidden
+    return (number == 1 ? string1 : string2)
address@hidden
address@hidden endfile
address@hidden example
 
address@hidden @code{LC_RESPONSE} locale category
address@hidden LC_RESPONSE
-Response information, such as how ``yes'' and ``no'' appear in the
-local language, and possibly other information as well.
address@hidden
+The use of positional specifications in @code{printf} or
address@hidden()} is @emph{not} portable.
+To support @code{gettext()} at the C level, many systems' C versions of
address@hidden()} do support positional specifiers.  But it works only if
+enough arguments are supplied in the function call.  Many versions of
address@hidden pass @code{printf} formats and arguments unchanged to the
+underlying C library version of @code{sprintf()}, but only one format and
+argument at a time.  What happens if a positional specification is
+used is anybody's guess.
+However, since the positional specifications are primarily for use in
address@hidden format strings, and since non-GNU @command{awk}s never
+retrieve the translated string, this should not be a problem in practice.
address@hidden itemize
address@hidden ENDOFRANGE inap
 
address@hidden time, localization and
address@hidden dates, information related address@hidden localization
address@hidden @code{LC_TIME} locale category
address@hidden LC_TIME
-Time- and date-related information, such as 12- or 24-hour clock, month printed
-before or after the day in a date, local month abbreviations, and so on.
address@hidden I18N Example
address@hidden A Simple Internationalization Example
 
address@hidden @code{LC_ALL} locale category
address@hidden LC_ALL
-All of the above.  (Not too useful in the context of @code{gettext}.)
address@hidden table
address@hidden ENDOFRANGE gettex
+Now let's look at a step-by-step example of how to internationalize and
+localize a simple @command{awk} program, using @file{guide.awk} as our
+original source:
 
address@hidden Programmer i18n
address@hidden Internationalizing @command{awk} Programs
address@hidden STARTOFRANGE inap
address@hidden @command{awk} programs, internationalizing
address@hidden
address@hidden file eg/prog/guide.awk
+BEGIN @{
+    TEXTDOMAIN = "guide"
+    bindtextdomain(".")  # for testing
+    print _"Don't Panic"
+    print _"The Answer Is", 42
+    print "Pardon me, Zaphod who?"
address@hidden
address@hidden endfile
address@hidden example
 
address@hidden provides the following variables and functions for
-internationalization:
address@hidden
+Run @samp{gawk --gen-pot} to create the @file{.pot} file:
 
address@hidden @code
address@hidden @code{TEXTDOMAIN} variable
address@hidden TEXTDOMAIN
-This variable indicates the application's text domain.
-For compatibility with GNU @code{gettext}, the default
-value is @code{"messages"}.
address@hidden
+$ @kbd{gawk --gen-pot -f guide.awk > guide.pot}
address@hidden example
 
address@hidden internationalization, localization, marked strings
address@hidden strings, for localization
address@hidden _"your message here"
-String constants marked with a leading underscore
-are candidates for translation at runtime.
-String constants without a leading underscore are not translated.
address@hidden
+This produces:
 
address@hidden @code{dcgettext()} function (@command{gawk})
address@hidden dcgettext(@var{string} @r{[}, @var{domain} @r{[}, 
@address@hidden)
-Return the translation of @var{string} in
-text domain @var{domain} for locale category @var{category}.
-The default value for @var{domain} is the current value of @code{TEXTDOMAIN}.
-The default value for @var{category} is @code{"LC_MESSAGES"}.
address@hidden
address@hidden file eg/data/guide.po
+#: guide.awk:4
+msgid "Don't Panic"
+msgstr ""
 
-If you supply a value for @var{category}, it must be a string equal to
-one of the known locale categories described in
address@hidden
-the previous @value{SECTION}.
address@hidden ifnotinfo
address@hidden
address@hidden gettext}.
address@hidden ifinfo
-You must also supply a text domain.  Use @code{TEXTDOMAIN} if
-you want to use the current domain.
+#: guide.awk:5
+msgid "The Answer Is"
+msgstr ""
 
address@hidden CAUTION
-The order of arguments to the @command{awk} version
-of the @code{dcgettext()} function is purposely different from the order for
-the C version.  The @command{awk} version's order was
-chosen to be simple and to allow for reasonable @command{awk}-style
-default arguments.
address@hidden endfile
address@hidden example
+
+This original portable object template file is saved and reused for each 
language
+into which the application is translated.  The @code{msgid}
+is the original string and the @code{msgstr} is the translation.
+
address@hidden NOTE
+Strings not marked with a leading underscore do not
+appear in the @file{guide.pot} file.
 @end quotation
 
address@hidden @code{dcngettext()} function (@command{gawk})
address@hidden dcngettext(@var{string1}, @var{string2}, @var{number} @r{[}, 
@var{domain} @r{[}, @address@hidden)
-Return the plural form used for @var{number} of the
-translation of @var{string1} and @var{string2} in text domain
address@hidden for locale category @var{category}. @var{string1} is the
-English singular variant of a message, and @var{string2} the English plural
-variant of the same message.
-The default value for @var{domain} is the current value of @code{TEXTDOMAIN}.
-The default value for @var{category} is @code{"LC_MESSAGES"}.
+Next, the messages must be translated.
+Here is a translation to a hypothetical dialect of English,
+called ``Mellow'':@footnote{Perhaps it would be better if it were
+called ``Hippy.'' Ah, well.}
 
-The same remarks about argument order as for the @code{dcgettext()} function 
apply.
address@hidden
address@hidden
+$ cp guide.pot guide-mellow.po
address@hidden translations to} guide-mellow.po @dots{}
address@hidden group
address@hidden example
 
address@hidden @code{.mo} files, specifying directory of
address@hidden files, @code{.mo}, specifying directory of
address@hidden message object files, specifying directory of
address@hidden files, message object, specifying directory of
address@hidden @code{bindtextdomain()} function (@command{gawk})
address@hidden bindtextdomain(@var{directory} @r{[}, @address@hidden)
-Change the directory in which
address@hidden looks for @file{.mo} files, in case they
-will not or cannot be placed in the standard locations
-(e.g., during testing).
-Return the directory in which @var{domain} is ``bound.''
address@hidden
+Following are the translations:
 
-The default @var{domain} is the value of @code{TEXTDOMAIN}.
-If @var{directory} is the null string (@code{""}), then
address@hidden()} returns the current binding for the
-given @var{domain}.
address@hidden table
address@hidden
address@hidden file eg/data/guide-mellow.po
+#: guide.awk:4
+msgid "Don't Panic"
+msgstr "Hey man, relax!"
 
-To use these facilities in your @command{awk} program, follow the steps
-outlined in
address@hidden
-the previous @value{SECTION},
address@hidden ifnotinfo
address@hidden
address@hidden gettext},
address@hidden ifinfo
-like so:
+#: guide.awk:5
+msgid "The Answer Is"
+msgstr "Like, the scoop is"
 
address@hidden
address@hidden @code{BEGIN} pattern, @code{TEXTDOMAIN} variable and
address@hidden @code{TEXTDOMAIN} variable, @code{BEGIN} pattern and
address@hidden
-Set the variable @code{TEXTDOMAIN} to the text domain of
-your program.  This is best done in a @code{BEGIN} rule
-(@pxref{BEGIN/END}),
-or it can also be done via the @option{-v} command-line
-option (@pxref{Options}):
address@hidden endfile
address@hidden example
+
address@hidden Linux
address@hidden GNU/Linux
+The next step is to make the directory to hold the binary message object
+file and then to create the @file{guide.mo} file.
+The directory layout shown here is standard for GNU @code{gettext} on
+GNU/Linux systems.  Other versions of @code{gettext} may use a different
+layout:
 
 @example
-BEGIN @{
-    TEXTDOMAIN = "guide"
-    @dots{}
address@hidden
+$ @kbd{mkdir en_US en_US/LC_MESSAGES}
 @end example
 
address@hidden @code{_} (underscore), translatable string
address@hidden underscore (@code{_}), translatable string
address@hidden
-Mark all translatable strings with a leading underscore (@samp{_})
-character.  It @emph{must} be adjacent to the opening
-quote of the string.  For example:
address@hidden @code{.po} files, converting to @code{.mo}
address@hidden files, @code{.po}, converting to @code{.mo}
address@hidden @code{.mo} files, converting from @code{.po}
address@hidden files, @code{.mo}, converting from @code{.po}
address@hidden portable object files, converting to message object files
address@hidden files, portable object, converting to message object files
address@hidden message object files, converting from portable object files
address@hidden files, message object, converting from portable object files
address@hidden @command{msgfmt} utility
+The @command{msgfmt} utility does the conversion from human-readable
address@hidden file to machine-readable @file{.mo} file.
+By default, @command{msgfmt} creates a file named @file{messages}.
+This file must be renamed and placed in the proper directory so that
address@hidden can find it:
 
 @example
-print _"hello, world"
-x = _"you goofed"
-printf(_"Number of users is %d\n", nusers)
+$ @kbd{msgfmt guide-mellow.po}
+$ @kbd{mv messages en_US/LC_MESSAGES/guide.mo}
 @end example
 
address@hidden
-If you are creating strings dynamically, you can
-still translate them, using the @code{dcgettext()}
-built-in function:
+Finally, we run the program to test it:
 
 @example
-message = nusers " users logged in"
-message = dcgettext(message, "adminprog")
-print message
+$ @kbd{gawk -f guide.awk}
address@hidden Hey man, relax!
address@hidden Like, the scoop is 42
address@hidden Pardon me, Zaphod who?
 @end example
 
-Here, the call to @code{dcgettext()} supplies a different
-text domain (@code{"adminprog"}) in which to find the
-message, but it uses the default @code{"LC_MESSAGES"} category.
-
address@hidden @code{LC_MESSAGES} locale category, @code{bindtextdomain()} 
function (@command{gawk})
address@hidden
-During development, you might want to put the @file{.mo}
-file in a private directory for testing.  This is done
-with the @code{bindtextdomain()} built-in function:
+If the three replacement functions for @code{dcgettext()}, @code{dcngettext()}
+and @code{bindtextdomain()}
+(@pxref{I18N Portability})
+are in a file named @file{libintl.awk},
+then we can run @file{guide.awk} unchanged as follows:
 
 @example
-BEGIN @{
-   TEXTDOMAIN = "guide"   # our text domain
-   if (Testing) @{
-       # where to find our files
-       bindtextdomain("testdir")
-       # joe is in charge of adminprog
-       bindtextdomain("../joe/testdir", "adminprog")
-   @}
-   @dots{}
address@hidden
+$ @kbd{gawk --posix -f guide.awk -f libintl.awk}
address@hidden Don't Panic
address@hidden The Answer Is 42
address@hidden Pardon me, Zaphod who?
 @end example
 
address@hidden enumerate
address@hidden Gawk I18N
address@hidden @command{gawk} Can Speak Your Language
+
address@hidden itself has been internationalized
+using the GNU @code{gettext} package.
+(GNU @code{gettext} is described in
+complete detail in
address@hidden
address@hidden, , GNU @code{gettext} utilities, gettext, GNU gettext tools}.)
address@hidden ifinfo
address@hidden
address@hidden gettext tools}.)
address@hidden ifnotinfo
+As of this writing, the latest version of GNU @code{gettext} is
address@hidden://ftp.gnu.org/gnu/gettext/gettext-0.18.1.tar.gz, 
@value{PVERSION} 0.18.1}.
+
+If a translation of @command{gawk}'s messages exists,
+then @command{gawk} produces usage messages, warnings,
+and fatal errors in the local language.
address@hidden ENDOFRANGE inloc
+
address@hidden Advanced Features
address@hidden Advanced Features of @command{gawk}
address@hidden advanced features, network connections, See Also networks, 
connections
address@hidden STARTOFRANGE gawadv
address@hidden @command{gawk}, features, advanced
address@hidden STARTOFRANGE advgaw
address@hidden advanced features, @command{gawk}
address@hidden
+Contributed by: Peter Langston <address@hidden>
 
address@hidden Example},
-for an example program showing the steps to create
-and use translations from @command{awk}.
+    Found in Steve English's "signature" line:
 
address@hidden Translator i18n
address@hidden Translating @command{awk} Programs
+"Write documentation as if whoever reads it is a violent psychopath
+who knows where you live."
address@hidden ignore
address@hidden
address@hidden documentation as if whoever reads it is
+a violent psychopath who knows where you address@hidden
+Steve English, as quoted by Peter Langston
address@hidden quotation
 
address@hidden @code{.po} files
address@hidden files, @code{.po}
address@hidden portable object files
address@hidden files, portable object
-Once a program's translatable strings have been marked, they must
-be extracted to create the initial @file{.po} file.
-As part of translation, it is often helpful to rearrange the order
-in which arguments to @code{printf} are output.
+This @value{CHAPTER} discusses advanced features in @command{gawk}.
+It's a bit of a ``grab bag'' of items that are otherwise unrelated
+to each other.
+First, a command-line option allows @command{gawk} to recognize
+nondecimal numbers in input data, not just in @command{awk}
+programs.
+Then, @command{gawk}'s special features for sorting arrays are presented.
+Next, two-way I/O, discussed briefly in earlier parts of this
address@hidden, is described in full detail, along with the basics
+of TCP/IP networking.  Finally, @command{gawk}
+can @dfn{profile} an @command{awk} program, making it possible to tune
+it for performance.
 
address@hidden's @option{--gen-pot} command-line option extracts
-the messages and is discussed next.
-After that, @code{printf}'s ability to
-rearrange the order for @code{printf} arguments at runtime
-is covered.
address@hidden Extensions},
+discusses the ability to dynamically add new built-in functions to
address@hidden  As this feature is still immature and likely to change,
+its description is relegated to an appendix.
 
 @menu
-* String Extraction::           Extracting marked strings.
-* Printf Ordering::             Rearranging @code{printf} arguments.
-* I18N Portability::            @command{awk}-level portability issues.
+* Nondecimal Data::             Allowing nondecimal input data.
+* Array Sorting::               Facilities for controlling array traversal and
+                                sorting arrays.
+* Two-way I/O::                 Two-way communications with another process.
+* TCP/IP Networking::           Using @command{gawk} for network programming.
+* Profiling::                   Profiling your @command{awk} programs.
 @end menu
 
address@hidden String Extraction
address@hidden Extracting Marked Strings
address@hidden strings, extracting
address@hidden marked address@hidden extracting
address@hidden @code{--gen-pot} option
address@hidden command-line options, string extraction
address@hidden string extraction (internationalization)
address@hidden marked string extraction (internationalization)
address@hidden extraction, of marked strings (internationalization)
address@hidden Nondecimal Data
address@hidden Allowing Nondecimal Input Data
address@hidden @code{--non-decimal-data} option
address@hidden advanced features, @command{gawk}, nondecimal input data
address@hidden input, address@hidden nondecimal
address@hidden constants, nondecimal
 
address@hidden @code{--gen-pot} option
-Once your @command{awk} program is working, and all the strings have
-been marked and you've set (and perhaps bound) the text domain,
-it is time to produce translations.
-First, use the @option{--gen-pot} command-line option to create
-the initial @file{.pot} file:
+If you run @command{gawk} with the @option{--non-decimal-data} option,
+you can have nondecimal constants in your input data:
 
address@hidden line break here for small book format
 @example
-$ @kbd{gawk --gen-pot -f guide.awk > guide.pot}
+$ @kbd{echo 0123 123 0x123 |}
+> @kbd{gawk --non-decimal-data '@{ printf "%d, %d, %d\n",}
+>                                         @kbd{$1, $2, $3 @}'}
address@hidden 83, 123, 291
 @end example
 
address@hidden @code{xgettext} utility
-When run with @option{--gen-pot}, @command{gawk} does not execute your
-program.  Instead, it parses it as usual and prints all marked strings
-to standard output in the format of a GNU @code{gettext} Portable Object
-file.  Also included in the output are any constant strings that
-appear as the first argument to @code{dcgettext()} or as the first and
-second argument to @code{dcngettext()address@hidden
address@hidden utility that comes with GNU
address@hidden can handle @file{.awk} files.}
address@hidden Example},
-for the full list of steps to go through to create and test
-translations for @command{guide}.
-
address@hidden Printf Ordering
address@hidden Rearranging @code{printf} Arguments
-
address@hidden @code{printf} statement, positional specifiers
address@hidden positional specifiers, @code{printf} statement
-Format strings for @code{printf} and @code{sprintf()}
-(@pxref{Printf})
-present a special problem for translation.
-Consider the following:@footnote{This example is borrowed
-from the GNU @code{gettext} manual.}
+For this feature to work, write your program so that
address@hidden treats your data as numeric:
 
address@hidden line broken here only for smallbook format
 @example
-printf(_"String `%s' has %d characters\n",
-          string, length(string)))
+$ @kbd{echo 0123 123 0x123 | gawk '@{ print $1, $2, $3 @}'}
address@hidden 0123 123 0x123
 @end example
 
-A possible German translation for this might be:
address@hidden
+The @code{print} statement treats its expressions as strings.
+Although the fields can act as numbers when necessary,
+they are still strings, so @code{print} does not try to treat them
+numerically.  You may need to add zero to a field to force it to
+be treated as a number.  For example:
 
 @example
-"%d Zeichen lang ist die Zeichenkette `%s'\n"
+$ @kbd{echo 0123 123 0x123 | gawk --non-decimal-data '}
+> @address@hidden print $1, $2, $3}
+>   @kbd{print $1 + 0, $2 + 0, $3 + 0 @}'}
address@hidden 0123 123 0x123
address@hidden 83 123 291
 @end example
 
-The problem should be obvious: the order of the format
-specifications is different from the original!
-Even though @code{gettext()} can return the translated string
-at runtime,
-it cannot change the argument order in the call to @code{printf}.
+Because it is common to have decimal data with leading zeros, and because
+using this facility could lead to surprising results, the default is to leave 
it
+disabled.  If you want it, you must explicitly request it.
 
-To solve this problem, @code{printf} format specifiers may have
-an additional optional element, which we call a @dfn{positional specifier}.
-For example:
address@hidden programming conventions, @code{--non-decimal-data} option
address@hidden @code{--non-decimal-data} option, @code{strtonum()} function and
address@hidden @code{strtonum()} function (@command{gawk}), 
@code{--non-decimal-data} option and
address@hidden CAUTION
address@hidden of this option is not recommended.}
+It can break old programs very badly.
+Instead, use the @code{strtonum()} function to convert your data
+(@pxref{Nondecimal-numbers}).
+This makes your programs easier to write and easier to read, and
+leads to less surprising results.
address@hidden quotation
 
address@hidden
-"%2$d Zeichen lang ist die Zeichenkette `%1$s'\n"
address@hidden example
address@hidden Array Sorting
address@hidden Controlling Array Traversal and Array Sorting
 
-Here, the positional specifier consists of an integer count, which indicates 
which
-argument to use, and a @samp{$}. Counts are one-based, and the
-format string itself is @emph{not} included.  Thus, in the following
-example, @samp{string} is the first argument and @samp{length(string)} is the 
second:
address@hidden lets you control the order in which @samp{for (i in array)} loops
+will traverse an array.
 
address@hidden
-$ @kbd{gawk 'BEGIN @{}
->     @kbd{string = "Dont Panic"}
->     @kbd{printf _"%2$d characters live in \"%1$s\"\n",}
->                         @kbd{string, length(string)}
-> @address@hidden'}
address@hidden 10 characters live in "Dont Panic"
address@hidden example
+In addition, two built-in functions, @code{asort()} and @code{asorti()},
+let you sort arrays based on the array values and indices, respectively.
+These two functions also provide control over the sorting criteria used
+to order the elements during sorting.
 
-If present, positional specifiers come first in the format specification,
-before the flags, the field width, and/or the precision.
address@hidden
+* Controlling Array Traversal:: How to use PROCINFO["sorted_in"].
+* Array Sorting Functions::     How to use @code{asort()} and @code{asorti()}.
address@hidden menu
 
-Positional specifiers can be used with the dynamic field width and
-precision capability:
address@hidden Controlling Array Traversal
address@hidden Controlling Array Traversal
 
address@hidden
-$ @kbd{gawk 'BEGIN @{}
->    @kbd{printf("%*.*s\n", 10, 20, "hello")}
->    @kbd{printf("%3$*2$.*1$s\n", 20, 10, "hello")}
-> @address@hidden'}
address@hidden      hello
address@hidden      hello
address@hidden example
+By default, the order in which a @samp{for (i in array)} loop
+will scan an array is not defined; it is generally based upon
+the internal implementation of arrays inside @command{awk}.
 
address@hidden NOTE
-When using @samp{*} with a positional specifier, the @samp{*}
-comes first, then the integer position, and then the @samp{$}.
-This is somewhat counterintuitive.
address@hidden quotation
+Often, though, it is desirable to be able to loop over the elements
+in a particular order that you, the programmer, choose.  @command{gawk}
+lets you do this; this @value{SUBSECTION} describes how.
 
address@hidden @code{printf} statement, positional specifiers, mixing with 
regular formats
address@hidden positional specifiers, @code{printf} statement, mixing with 
regular formats
address@hidden format specifiers, mixing regular with positional specifiers
address@hidden does not allow you to mix regular format specifiers
-and those with positional specifiers in the same string:
address@hidden
+* Controlling Scanning With A Function:: Using a function to control scanning.
+* Controlling Scanning::                 Controlling the order in which arrays
+                                         are scanned.
address@hidden menu
+
address@hidden Controlling Scanning With A Function
address@hidden Controlling Array Scanning Order With a User-defined Function
+
+The value of @code{PROCINFO["sorted_in"]} can be a function name.
+This lets you traverse an array based on any custom criterion.
+The array elements are ordered according to the return value of this
+function.  This comparison function should be defined with at least
+four arguments:
 
 @example
-$ @kbd{gawk 'BEGIN @{ printf _"%d %3$s\n", 1, 2, "hi" @}'}
address@hidden gawk: cmd. line:1: fatal: must use `count$' on all formats or 
none
+function comp_func(i1, v1, i2, v2)
address@hidden
+    @var{compare elements 1 and 2 in some fashion}
+    @var{return < 0; 0; or > 0}
address@hidden
 @end example
 
address@hidden NOTE
-There are some pathological cases that @command{gawk} may fail to
-diagnose.  In such cases, the output may not be what you expect.
-It's still a bad idea to try mixing them, even if @command{gawk}
-doesn't detect it.
address@hidden quotation
+Here, @var{i1} and @var{i2} are the indices, and @var{v1} and @var{v2}
+are the corresponding values of the two elements being compared.
+Either @var{v1} or @var{v2}, or both, can be arrays if the array being
+traversed contains subarrays as values.  The three possible return values
+are interpreted this way:
 
-Although positional specifiers can be used directly in @command{awk} programs,
-their primary purpose is to help in producing correct translations of
-format strings into languages different from the one in which the program
-is first written.
address@hidden @bullet
address@hidden
+If the return value of @code{comp_func(i1, v1, i2, v2)} is less than zero,
+index @var{i1} comes before index @var{i2} during loop traversal.
 
address@hidden I18N Portability
address@hidden @command{awk} Portability Issues
address@hidden
+If @code{comp_func(i1, v1, i2, v2)} returns zero, @var{i1} and @var{i2}
+come together but the relative order with respect to each other is undefined.
 
address@hidden portability, internationalization and
address@hidden internationalization, localization, portability and
address@hidden's internationalization features were purposely chosen to
-have as little impact as possible on the portability of @command{awk}
-programs that use them to other versions of @command{awk}.
-Consider this program:
address@hidden
+If the return value of @code{comp_func(i1, v1, i2, v2)} is greater than zero,
address@hidden comes after @var{i2}.
address@hidden itemize
+
+The following comparison function can be used to scan an array in
+numerical order of the indices:
 
 @example
-BEGIN @{
-    TEXTDOMAIN = "guide"
-    if (Test_Guide)   # set with -v
-        bindtextdomain("/test/guide/messages")
-    print _"don't panic!"
+function cmp_num_idx(i1, v1, i2, v2)
address@hidden
+    # numerical index comparison, ascending order
+    return (i1 - i2)
address@hidden
address@hidden example
+
+This function traverses an array based on the string order of the element 
values
+rather than by indices:
+
address@hidden
+function cmp_str_val(i1, v1, i2, v2)
address@hidden
+    # string value comparison, ascending order
+    v1 = v1 ""
+    v2 = v2 ""
+    if (v1 < v2)
+        return -1
+    return (v1 != v2)
 @}
 @end example
 
address@hidden
-As written, it won't work on other versions of @command{awk}.
-However, it is actually almost portable, requiring very little
-change:
+Here is a
+comparison function to make all numbers, and numeric strings without
+any leading or trailing spaces, come out first during loop traversal:  
 
address@hidden @bullet
address@hidden @code{TEXTDOMAIN} variable, portability and
address@hidden
-Assignments to @code{TEXTDOMAIN} won't have any effect,
-since @code{TEXTDOMAIN} is not special in other @command{awk} implementations.
address@hidden
+function cmp_num_str_val(i1, v1, i2, v2,   n1, n2)
address@hidden
+    # numbers before string value comparison, ascending order
+    n1 = v1 + 0
+    n2 = v2 + 0
+    if (n1 == v1) 
+        return (n2 == v2) ? (n1 - n2) : -1
+    else if (n2 == v2)
+        return 1 
+    return (v1 < v2) ? -1 : (v1 != v2)
address@hidden
address@hidden example
 
address@hidden
-Non-GNU versions of @command{awk} treat marked strings
-as the concatenation of a variable named @code{_} with the string
-following address@hidden is good fodder for an ``Obfuscated
address@hidden'' contest.} Typically, the variable @code{_} has
-the null string (@code{""}) as its value, leaving the original string constant 
as
-the result.
address@hidden: Put in a fuller example here of some data
+and show the different results when traversing.
 
address@hidden
-By defining ``dummy'' functions to replace @code{dcgettext()}, 
@code{dcngettext()}
-and @code{bindtextdomain()}, the @command{awk} program can be made to run, but
-all the messages are output in the original language.
-For example:
+Consider sorting the entries of a GNU/Linux system password file
+according to login names.  The following program which sorts records
+by a specific field position can be used for this purpose:   
 
address@hidden @code{bindtextdomain()} function (@command{gawk}), portability 
and
address@hidden @code{dcgettext()} function (@command{gawk}), portability and
address@hidden @code{dcngettext()} function (@command{gawk}), portability and
 @example
address@hidden file eg/lib/libintl.awk
-function bindtextdomain(dir, domain)
+# sort.awk --- simple program to sort by field position
+# field position is specified by the global variable POS
+
+function cmp_field(i1, v1, i2, v2)
 @{
-    return dir
+    # comparison by value, as string, and ascending order
+    return v1[POS] < v2[POS] ? -1 : (v1[POS] != v2[POS])
 @}
 
-function dcgettext(string, domain, category)
 @{
-    return string
+    for (i = 1; i <= NF; i++)
+        a[NR][i] = $i
 @}
 
-function dcngettext(string1, string2, number, domain, category)
address@hidden
-    return (number == 1 ? string1 : string2)
+END @{
+    PROCINFO["sorted_in"] = "cmp_field"
+    if (POS < 1 || POS > NF)
+        POS = 1
+    for (i in a) @{
+        for (j = 1; j <= NF; j++)
+            printf("%s%c", a[i][j], j < NF ? ":" : "")
+        print ""
+    @}
 @}
address@hidden endfile
 @end example
 
address@hidden
-The use of positional specifications in @code{printf} or
address@hidden()} is @emph{not} portable.
-To support @code{gettext()} at the C level, many systems' C versions of
address@hidden()} do support positional specifiers.  But it works only if
-enough arguments are supplied in the function call.  Many versions of
address@hidden pass @code{printf} formats and arguments unchanged to the
-underlying C library version of @code{sprintf()}, but only one format and
-argument at a time.  What happens if a positional specification is
-used is anybody's guess.
-However, since the positional specifications are primarily for use in
address@hidden format strings, and since non-GNU @command{awk}s never
-retrieve the translated string, this should not be a problem in practice.
address@hidden itemize
address@hidden ENDOFRANGE inap
-
address@hidden I18N Example
address@hidden A Simple Internationalization Example
-
-Now let's look at a step-by-step example of how to internationalize and
-localize a simple @command{awk} program, using @file{guide.awk} as our
-original source:
+The first field in each entry of the password file is the user's login name,
+and the fields are seperated by colons.
+Each record defines a subarray, which each field as an element in the subarray.
+Running the program produces the
+following output:
 
 @example
address@hidden file eg/prog/guide.awk
-BEGIN @{
-    TEXTDOMAIN = "guide"
-    bindtextdomain(".")  # for testing
-    print _"Don't Panic"
-    print _"The Answer Is", 42
-    print "Pardon me, Zaphod who?"
address@hidden
address@hidden endfile
+$ @kbd{gawk -vPOS=1 -F: -f sort.awk /etc/passwd}
address@hidden adm:x:3:4:adm:/var/adm:/sbin/nologin
address@hidden apache:x:48:48:Apache:/var/www:/sbin/nologin
address@hidden avahi:x:70:70:Avahi daemon:/:/sbin/nologin
address@hidden
 @end example
 
address@hidden
-Run @samp{gawk --gen-pot} to create the @file{.pot} file:
+The comparison normally should always return the same value when given a
+specific pair of array elements as its arguments.  If inconsistent
+results are returned then the order is undefined.  This behavior is
+sometimes exploited to introduce random order in otherwise seemingly
+ordered data:
 
 @example
-$ @kbd{gawk --gen-pot -f guide.awk > guide.pot}
+function cmp_randomize(i1, v1, i2, v2)
address@hidden
+    # random order
+    return (2 - 4 * rand())
address@hidden
 @end example
 
address@hidden
-This produces:
+As mentioned above, the order of the indices is arbitrary if two
+elements compare equal.  This is usually not a problem, but letting
+the tied elements come out in arbitrary order can be an issue, especially
+when comparing item values.  The partial ordering of the equal elements
+may change during the next loop traversal, if other elements are added or
+removed from the array.  One way to resolve ties when comparing elements
+with otherwise equal values is to include the indices in the comparison
+rules.  Note that doing this may make the loop traversal less efficient,
+so consider it only if necessary.  The following comparison functions
+force a deterministic order, and are based on the fact that the
+indices of two elements are never equal:
 
 @example
address@hidden file eg/data/guide.po
-#: guide.awk:4
-msgid "Don't Panic"
-msgstr ""
-
-#: guide.awk:5
-msgid "The Answer Is"
-msgstr ""
+function cmp_numeric(i1, v1, i2, v2)
address@hidden
+    # numerical value (and index) comparison, descending order
+    return (v1 != v2) ? (v2 - v1) : (i2 - i1)
address@hidden
 
address@hidden endfile
+function cmp_string(i1, v1, i2, v2)
address@hidden
+    # string value (and index) comparison, descending order
+    v1 = v1 i1
+    v2 = v2 i2
+    return (v1 > v2) ? -1 : (v1 != v2)
address@hidden
 @end example
 
-This original portable object template file is saved and reused for each 
language
-into which the application is translated.  The @code{msgid}
-is the original string and the @code{msgstr} is the translation.
address@hidden Avoid using the term ``stable'' when describing the 
unpredictable behavior
address@hidden if two items compare equal.  Usually, the goal of a "stable 
algorithm"
address@hidden is to maintain the original order of the items, which is a 
meaningless
address@hidden concept for a list constructed from a hash.
 
address@hidden NOTE
-Strings not marked with a leading underscore do not
-appear in the @file{guide.pot} file.
address@hidden quotation
+A custom comparison function can often simplify ordered loop
+traversal, and the the sky is really the limit when it comes to
+designing such a function.
 
-Next, the messages must be translated.
-Here is a translation to a hypothetical dialect of English,
-called ``Mellow'':@footnote{Perhaps it would be better if it were
-called ``Hippy.'' Ah, well.}
+When string comparisons are made during a sort, either for element
+values where one or both aren't numbers, or for element indices
+handled as strings, the value of @code{IGNORECASE}
+(@pxref{Built-in Variables}) controls whether
+the comparisons treat corresponding uppercase and lowercase letters as
+equivalent or distinct.
 
address@hidden
address@hidden
-$ cp guide.pot guide-mellow.po
address@hidden translations to} guide-mellow.po @dots{}
address@hidden group
address@hidden example
+Another point to keep in mind is that in the case of subarrays
+the element values can themselves be arrays; a production comparison
+function should use the @code{isarray()} function
+(@pxref{Type Functions}),
+to check for this, and choose a defined sorting order for subarrays.
 
address@hidden
-Following are the translations:
+All sorting based on @code{PROCINFO["sorted_in"]}
+is disabled in POSIX mode,
+since the @code{PROCINFO} array is not special in that case.
 
address@hidden
address@hidden file eg/data/guide-mellow.po
-#: guide.awk:4
-msgid "Don't Panic"
-msgstr "Hey man, relax!"
+As a side note, sorting the array indices before traversing
+the array has been reported to add 15% to 20% overhead to the
+execution time of @command{awk} programs. For this reason,
+sorted array traversal is not the default.
 
-#: guide.awk:5
-msgid "The Answer Is"
-msgstr "Like, the scoop is"
address@hidden The @command{gawk}
address@hidden maintainers believe that only the people who wish to use a
address@hidden feature should have to pay for it.
 
address@hidden endfile
address@hidden example
address@hidden Controlling Scanning
address@hidden Controlling Array Scanning Order
 
address@hidden Linux
address@hidden GNU/Linux
-The next step is to make the directory to hold the binary message object
-file and then to create the @file{guide.mo} file.
-The directory layout shown here is standard for GNU @code{gettext} on
-GNU/Linux systems.  Other versions of @code{gettext} may use a different
-layout:
+As described in
address@hidden
+the previous subsubsection,
address@hidden iftex
address@hidden Scanning With A Function},
address@hidden
address@hidden ifnottex
+you can provide the name of a function as the value of
address@hidden"sorted_in"]} to specify custom sorting criteria.
+
+Often, though, you may wish to do something simple, such as
+``sort based on comparing the indices in ascending order,''
+or ``sort based on comparing the values in descending order.''
+Having to write a simple comparison function for this purpose
+for use in all of your programs becomes tedious.
+For the most likely simple cases @command{gawk} provides
+the option of supplying special names that do the requested
+sorting for you.
+You can think of them as ``predefined'' sorting functions,
+if you like, although the names purposely include characters
+that are not valid in real @command{awk} function names.
+
+The following special values are available:
 
address@hidden
-$ @kbd{mkdir en_US en_US/LC_MESSAGES}
address@hidden example
address@hidden @code
address@hidden "@@ind_str_asc"
+Order by indices compared as strings; this is the most basic sort.
+(Internally, array indices are always strings, so with @samp{a[2*5] = 1}
+the index is actually @code{"10"} rather than numeric 10.)
 
address@hidden @code{.po} files, converting to @code{.mo}
address@hidden files, @code{.po}, converting to @code{.mo}
address@hidden @code{.mo} files, converting from @code{.po}
address@hidden files, @code{.mo}, converting from @code{.po}
address@hidden portable object files, converting to message object files
address@hidden files, portable object, converting to message object files
address@hidden message object files, converting from portable object files
address@hidden files, message object, converting from portable object files
address@hidden @command{msgfmt} utility
-The @command{msgfmt} utility does the conversion from human-readable
address@hidden file to machine-readable @file{.mo} file.
-By default, @command{msgfmt} creates a file named @file{messages}.
-This file must be renamed and placed in the proper directory so that
address@hidden can find it:
address@hidden "@@ind_num_asc"
+Order by indices but force them to be treated as numbers in the process.
+Any index with non-numeric value will end up positioned as if it were zero. 
 
address@hidden
-$ @kbd{msgfmt guide-mellow.po}
-$ @kbd{mv messages en_US/LC_MESSAGES/guide.mo}
address@hidden example
address@hidden "@@val_type_asc"
+Order by element values rather than indices.
+Ordering is by the type assigned to the element
+(@pxref{Typing and Comparison}).
+All numeric values come before all string values,
+which in turn come before all subarrays.
+
address@hidden "@@val_str_asc"
+Order by element values rather than by indices.  Scalar values are 
+compared as strings.  Subarrays, if present, come out last.
+
address@hidden "@@val_num_asc"
+Order by values but force scalar values to be treated as numbers
+for the purpose of comparison.  If there are subarrays, those appear
+at the end of the sorted list.
 
-Finally, we run the program to test it:
address@hidden "@@ind_str_desc"
+Reverse order from the most basic sort.
 
address@hidden
-$ @kbd{gawk -f guide.awk}
address@hidden Hey man, relax!
address@hidden Like, the scoop is 42
address@hidden Pardon me, Zaphod who?
address@hidden example
address@hidden "@@ind_num_desc"
+Numeric indices ordered from high to low.
 
-If the three replacement functions for @code{dcgettext()}, @code{dcngettext()}
-and @code{bindtextdomain()}
-(@pxref{I18N Portability})
-are in a file named @file{libintl.awk},
-then we can run @file{guide.awk} unchanged as follows:
address@hidden "@@val_type_desc"
+Element values, based on type, in descending order.
 
address@hidden
-$ @kbd{gawk --posix -f guide.awk -f libintl.awk}
address@hidden Don't Panic
address@hidden The Answer Is 42
address@hidden Pardon me, Zaphod who?
address@hidden example
address@hidden "@@val_str_desc"
+Element values, treated as strings, ordered from high to low.  Subarrays, if 
present,
+come out first.
 
address@hidden Gawk I18N
address@hidden @command{gawk} Can Speak Your Language
address@hidden "@@val_num_desc"
+Element values, treated as numbers, ordered from high to low.  Subarrays, if 
present,
+come out first.
 
address@hidden itself has been internationalized
-using the GNU @code{gettext} package.
-(GNU @code{gettext} is described in
-complete detail in
address@hidden
address@hidden, , GNU @code{gettext} utilities, gettext, GNU gettext tools}.)
address@hidden ifinfo
address@hidden
address@hidden gettext tools}.)
address@hidden ifnotinfo
-As of this writing, the latest version of GNU @code{gettext} is
address@hidden://ftp.gnu.org/gnu/gettext/gettext-0.18.1.tar.gz, 
@value{PVERSION} 0.18.1}.
address@hidden "@@unsorted"
+Array elements are processed in arbitrary order, which is the normal 
@command{awk}
+behavior. You can also get the normal behavior by just
+deleting the @code{"sorted_in"} element from the @code{PROCINFO} array, if
+it previously had a value assigned to it.
address@hidden table
 
-If a translation of @command{gawk}'s messages exists,
-then @command{gawk} produces usage messages, warnings,
-and fatal errors in the local language.
address@hidden ENDOFRANGE inloc
+The array traversal order is determined before the @code{for} loop
+starts to run. Changing @code{PROCINFO["sorted_in"]} in the loop body
+will not affect the loop.
 
address@hidden Advanced Features
address@hidden Advanced Features of @command{gawk}
address@hidden advanced features, network connections, See Also networks, 
connections
address@hidden STARTOFRANGE gawadv
address@hidden @command{gawk}, features, advanced
address@hidden STARTOFRANGE advgaw
address@hidden advanced features, @command{gawk}
address@hidden
-Contributed by: Peter Langston <address@hidden>
+For example:
 
-    Found in Steve English's "signature" line:
address@hidden
+$ @kbd{gawk 'BEGIN @{}
+> @kbd{   a[4] = 4}
+> @kbd{   a[3] = 3}
+> @kbd{   for (i in a)}
+> @kbd{       print i, a[i]}
+> @address@hidden'}
address@hidden 4 4
address@hidden 3 3
+$ @kbd{gawk 'BEGIN @{}
+> @kbd{   PROCINFO["sorted_in"] = "@@str_ind_asc"}
+> @kbd{   a[4] = 4}
+> @kbd{   a[3] = 3}
+> @kbd{   for (i in a)}
+> @kbd{       print i, a[i]}
+> @address@hidden'}
address@hidden 3 3
address@hidden 4 4
address@hidden example
 
-"Write documentation as if whoever reads it is a violent psychopath
-who knows where you live."
address@hidden ignore
address@hidden
address@hidden documentation as if whoever reads it is
-a violent psychopath who knows where you address@hidden
-Steve English, as quoted by Peter Langston
address@hidden quotation
+When sorting an array by element values, if a value happens to be
+a subarray then it is considered to be greater than any string or
+numeric value, regardless of what the subarray itself contains,
+and all subarrays are treated as being equal to each other.  Their 
+order relative to each other is determined by their index strings.
 
-This @value{CHAPTER} discusses advanced features in @command{gawk}.
-It's a bit of a ``grab bag'' of items that are otherwise unrelated
-to each other.
-First, a command-line option allows @command{gawk} to recognize
-nondecimal numbers in input data, not just in @command{awk}
-programs.  Next, two-way I/O, discussed briefly in earlier parts of this
address@hidden, is described in full detail, along with the basics
-of TCP/IP networking.  Finally, @command{gawk}
-can @dfn{profile} an @command{awk} program, making it possible to tune
-it for performance.
address@hidden Array Sorting Functions
address@hidden Sorting Array Values and Indices with @command{gawk}
 
address@hidden Extensions},
-discusses the ability to dynamically add new built-in functions to
address@hidden  As this feature is still immature and likely to change,
-its description is relegated to an appendix.
address@hidden arrays, sorting
address@hidden @code{asort()} function (@command{gawk})
address@hidden @code{asort()} function (@command{gawk}), address@hidden sorting
address@hidden sort function, arrays, sorting
+The order in which an array is scanned with a @samp{for (i in array)}
+loop is essentially arbitrary.
+In most @command{awk} implementations, sorting an array requires
+writing a @code{sort} function.
+While this can be educational for exploring different sorting algorithms,
+usually that's not the point of the program.
address@hidden provides the built-in @code{asort()}
+and @code{asorti()} functions
+(@pxref{String Functions})
+for sorting arrays.  For example:
 
address@hidden
-* Nondecimal Data::             Allowing nondecimal input data.
-* Two-way I/O::                 Two-way communications with another process.
-* TCP/IP Networking::           Using @command{gawk} for network programming.
-* Profiling::                   Profiling your @command{awk} programs.
address@hidden menu
address@hidden
address@hidden the array} data
+n = asort(data)
+for (i = 1; i <= n; i++)
+    @var{do something with} data[i]
address@hidden example
 
address@hidden Nondecimal Data
address@hidden Allowing Nondecimal Input Data
address@hidden @code{--non-decimal-data} option
address@hidden advanced features, @command{gawk}, nondecimal input data
address@hidden input, address@hidden nondecimal
address@hidden constants, nondecimal
+After the call to @code{asort()}, the array @code{data} is indexed from 1
+to some number @var{n}, the total number of elements in @code{data}.
+(This count is @code{asort()}'s return value.)
address@hidden @value{LEQ} @code{data[2]} @value{LEQ} @code{data[3]}, and so on.
+The array elements are compared as strings.
 
-If you run @command{gawk} with the @option{--non-decimal-data} option,
-you can have nondecimal constants in your input data:
address@hidden side effects, @code{asort()} function
+An important side effect of calling @code{asort()} is that
address@hidden array's original indices are irrevocably lost}.
+As this isn't always desirable, @code{asort()} accepts a
+second argument:
 
address@hidden line break here for small book format
 @example
-$ @kbd{echo 0123 123 0x123 |}
-> @kbd{gawk --non-decimal-data '@{ printf "%d, %d, %d\n",}
->                                         @kbd{$1, $2, $3 @}'}
address@hidden 83, 123, 291
address@hidden the array} source
+n = asort(source, dest)
+for (i = 1; i <= n; i++)
+    @var{do something with} dest[i]
 @end example
 
-For this feature to work, write your program so that
address@hidden treats your data as numeric:
+In this case, @command{gawk} copies the @code{source} array into the
address@hidden array and then sorts @code{dest}, destroying its indices.
+However, the @code{source} array is not affected.
+
address@hidden()} and @code{asorti()} accept a third string argument
+to control the comparison rule for the array elements, and the direction
+of the sorted results.  The valid comparison modes are @samp{string} and 
@samp{number},
+and the direction can be either @samp{ascending} or @samp{descending}.   
+Either mode or direction, or both, can be omitted in which
+case the defaults, @samp{string} or @samp{ascending} is assumed
+for the comparison mode and the direction, respectively.  Seperate comparison
+mode from direction with a single space, and they can appear in any
+order.  To compare the elements as numbers, and to reverse the elements
+of the @code{dest} array, the call to asort in the above example can be
+replaced with:
 
 @example
-$ @kbd{echo 0123 123 0x123 | gawk '@{ print $1, $2, $3 @}'}
address@hidden 0123 123 0x123
+asort(source, dest, "descending number")
 @end example
 
address@hidden
-The @code{print} statement treats its expressions as strings.
-Although the fields can act as numbers when necessary,
-they are still strings, so @code{print} does not try to treat them
-numerically.  You may need to add zero to a field to force it to
-be treated as a number.  For example:
+The third argument to @code{asort()} can also be a user-defined
+function name which is used to order the array elements before
+constructing the result array.
address@hidden an Array}, for more information.
+ 
+
+Often, what's needed is to sort on the values of the @emph{indices}
+instead of the values of the elements.
+To do that, use the
address@hidden()} function.  The interface is identical to that of
address@hidden()}, except that the index values are used for sorting, and
+become the values of the result array:
 
 @example
-$ @kbd{echo 0123 123 0x123 | gawk --non-decimal-data '}
-> @address@hidden print $1, $2, $3}
->   @kbd{print $1 + 0, $2 + 0, $3 + 0 @}'}
address@hidden 0123 123 0x123
address@hidden 83 123 291
address@hidden source[$0] = some_func($0) @}
+
+END @{
+    n = asorti(source, dest)
+    for (i = 1; i <= n; i++) @{
+        @ii{Work with sorted indices directly:}
+        @var{do something with} dest[i]
+        @dots{}
+        @ii{Access original array via sorted indices:}
+        @var{do something with} source[dest[i]]
+    @}
address@hidden
 @end example
 
-Because it is common to have decimal data with leading zeros, and because
-using this facility could lead to surprising results, the default is to leave 
it
-disabled.  If you want it, you must explicitly request it.
+Sorting the array by replacing the indices provides maximal flexibility.
+To traverse the elements in decreasing order, use a loop that goes from
address@hidden down to 1, either over the elements or over the indices.  This
+is an alternative to specifying @samp{descending} for the sorting order
+using the optional third argument.
 
address@hidden programming conventions, @code{--non-decimal-data} option
address@hidden @code{--non-decimal-data} option, @code{strtonum()} function and
address@hidden @code{strtonum()} function (@command{gawk}), 
@code{--non-decimal-data} option and
address@hidden CAUTION
address@hidden of this option is not recommended.}
-It can break old programs very badly.
-Instead, use the @code{strtonum()} function to convert your data
-(@pxref{Nondecimal-numbers}).
-This makes your programs easier to write and easier to read, and
-leads to less surprising results.
address@hidden quotation
address@hidden reference counting, sorting arrays
+Copying array indices and elements isn't expensive in terms of memory.
+Internally, @command{gawk} maintains @dfn{reference counts} to data.
+For example, when @code{asort()} copies the first array to the second one,
+there is only one copy of the original array elements' data, even though
+both arrays use the values.
+
address@hidden Document It And Call It A Feature. Sigh.
address@hidden @command{gawk}, @code{IGNORECASE} variable in
address@hidden @code{IGNORECASE} variable
address@hidden arrays, sorting, @code{IGNORECASE} variable and
address@hidden @code{IGNORECASE} variable, array sorting and
+Because @code{IGNORECASE} affects string comparisons, the value
+of @code{IGNORECASE} also affects sorting for both @code{asort()} and 
@code{asorti()}.
+Note also that the locale's sorting order does @emph{not}
+come into play; comparisons are based on character values address@hidden
+is true because locale-based comparison occurs only when in POSIX
+compatibility mode, and since @code{asort()} and @code{asorti()} are
address@hidden extensions, they are not available in that case.}
+Caveat Emptor.
 
 @node Two-way I/O
 @section Two-Way Communications with Another Process
@@ -26252,8 +26370,8 @@ of the @value{DOCUMENT} where you can find more 
information.
 * SVR4::                        Minor changes between System V Releases 3.1
                                 and 4.
 * POSIX::                       New features from the POSIX standard.
-* BTL::                         New features from Brian Kernighan's
-                                version of @command{awk}.
+* BTL::                         New features from Brian Kernighan's version of
+                                @command{awk}.
 * POSIX/GNU::                   The extensions in @command{gawk} not in POSIX
                                 @command{awk}.
 * Common Extensions::           Common Extensions Summary.
@@ -26762,6 +26880,9 @@ SunOS 3.x, Sun 386 (Road Runner)
 @item
 Tandem (non-POSIX)
 
address@hidden
+Prestandard VAX C compiler for VAX/VMS
+
 @end itemize
 
 @end itemize
@@ -26887,6 +27008,7 @@ provided the initial port to OS/2 and its documentation.
 @cindex Jaegermann, Michal
 Michal Jaegermann
 provided the port to Atari systems and its documentation.
+(This port is no longer supported.)
 He continues to provide portability checking with DEC Alpha
 systems, and has done a lot of work to make sure @command{gawk}
 works on non-32-bit systems.
diff --git a/eval.c b/eval.c
index dbd1c9f..8e0eff9 100644
--- a/eval.c
+++ b/eval.c
@@ -2182,6 +2182,7 @@ post:
                        NODE *array, *sort_str;
                        size_t num_elems = 0;
                        static NODE *sorted_in = NULL;
+                       const char *how_to_sort = "@unsorted";
 
                        /* get the array */
                        array = POP_ARRAY();
@@ -2200,7 +2201,13 @@ post:
                        if (PROCINFO_node != NULL)
                                sort_str = in_array(PROCINFO_node, sorted_in);
 
-                       list = assoc_list(array, sort_str, SORTED_IN);
+                       if (sort_str != NULL) {
+                               sort_str = force_string(sort_str);
+                               if (sort_str->stlen > 0)
+                                       how_to_sort = sort_str->stptr;
+                       }
+
+                       list = assoc_list(array, how_to_sort, SORTED_IN);
 
                        list[num_elems] = array;      /* actual array for use in
                                                       * lint warning in 
Op_arrayfor_incr
diff --git a/test/ChangeLog b/test/ChangeLog
index b3e99c2..03c9359 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,10 @@
+Wed May  4 23:37:27 2011  Arnold D. Robbins  <address@hidden>
+
+       Revise tests for array sorting.
+
+       * arraysort.awk, arraysort.ok, sort1.awk, sort1.ok,
+       sortfor.awk: Revised.
+
 Wed May  4 23:07:39 2011  Arnold D. Robbins  <address@hidden>
 
        * nastyparm.awk, nastyparm.ok: New files from John Haque.
diff --git a/test/arraysort.awk b/test/arraysort.awk
index 0992204..b053a1d 100644
--- a/test/arraysort.awk
+++ b/test/arraysort.awk
@@ -18,7 +18,7 @@ BEGIN {
 BEGIN {
        print "--- test2 ---"
        a[100] = a[1] = a["x"] = a["y"] = 1
-       PROCINFO["sorted_in"] = "num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a)
                print i, a[i]
        delete a
@@ -27,7 +27,7 @@ BEGIN {
 BEGIN {
        print "--- test3 ---"
        a[100] = a[1] = a["x"] = 1
-       PROCINFO["sorted_in"] = "num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a)
                print i, a[i]
        delete a
@@ -36,7 +36,7 @@ BEGIN {
 BEGIN {
        print "--- test4 ---"
        a[0] = a[100] = a[1] = a["x"] = 1
-       PROCINFO["sorted_in"] = "num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a)
                print i, a[i]
        delete a
@@ -45,7 +45,7 @@ BEGIN {
 BEGIN {
        print "--- test5 ---"
        a[""] = a["y"] = a[0] = 1
-       PROCINFO["sorted_in"] = "num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a)
                print i, a[i]
        delete a
@@ -54,7 +54,7 @@ BEGIN {
 BEGIN {
        print "--- test6 ---"
        a[2] = a[1] = a[4] = a["3 "] = 1
-       PROCINFO["sorted_in"] = "num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a)
                print "\""i"\""
        delete a
@@ -67,24 +67,24 @@ BEGIN {
        for (i = 1; i <= n; i++)
                b[a[i]] = a[i]
        print "--unsorted--"
-       PROCINFO["sorted_in"] = "unsorted"
+       PROCINFO["sorted_in"] = "@unsorted"
        for (i in b)
                print "|"i"|"b[i]"|"
 
        print "--asc ind str--"
-       PROCINFO["sorted_in"] = "asc ind str"
+       PROCINFO["sorted_in"] = "@ind_str_asc"
        for (i in b)
                print "|"i"|"b[i]"|"
        print "--asc val str--"
-       PROCINFO["sorted_in"] = "asc val str"
+       PROCINFO["sorted_in"] = "@val_str_asc"
        for (i in b)
                print "|"i"|"b[i]"|"
        print "--asc ind num--"
-       PROCINFO["sorted_in"] = "asc ind num"
+       PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in b)
                print "|"i"|"b[i]"|"
        print "--asc val num--"
-       PROCINFO["sorted_in"] = "asc val num"
+       PROCINFO["sorted_in"] = "@val_num_asc"
        for (i in b)
                print "|"i"|"b[i]"|"
 }
diff --git a/test/arraysort.ok b/test/arraysort.ok
index 70af0e0..454badf 100644
--- a/test/arraysort.ok
+++ b/test/arraysort.ok
@@ -1,7 +1,7 @@
 --- test1 ---
+   5  5 
   10  10
   3D  3D
-   5  5 
 --- test2 ---
 x 1
 y 1
@@ -71,13 +71,13 @@ y 1
 |4|4|
 |5|5|
 --asc val num--
-|0|0|
 |D3|D3|
+|0|0|
 |1|1|
 |2|2|
+|3D|3D|
 | 3| 3|
 |3|3|
-|3D|3D|
-| 4 | 4 |
 |4|4|
+| 4 | 4 |
 |5|5|
diff --git a/test/sort1.awk b/test/sort1.awk
index 44af59f..ef28e9c 100644
--- a/test/sort1.awk
+++ b/test/sort1.awk
@@ -16,38 +16,52 @@ BEGIN{
        printf("---end asort(a, a), IGNORECASE = %d---\n", IGNORECASE)
 
        makea(a)
-       SORT_STR = "num"
+       SORT_STR = "@ind_num_asc"
        asort2(a, "")
-       printf("---end asort(a, b, \"num\"), IGNORECASE = %d---\n", IGNORECASE)
+       printf("---end asort(a, b, \"%s\"), IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
 
        makea(a)
-       SORT_STR = "desc str"
+       SORT_STR = "@ind_str_desc"
        asort1(a, "")
-       printf("---end asort(a, a, \"desc str\"), IGNORECASE = %d---\n", 
IGNORECASE)
+       printf("---end asort(a, a, \"%s\"), IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
 
        makea(a)
-       SORT_STR = "val str"
+       SORT_STR = "@val_str_asc"
        proc_sort(a, "")
-       printf("---end PROCINFO[\"sorted_in\"] = \"val str\", IGNORECASE = 
%d---\n",
-               IGNORECASE)
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
 
        makea(a)
-       SORT_STR = "val num"
+       SORT_STR = "@val_num_asc"
        proc_sort(a, "")
-       printf("---end PROCINFO[\"sorted_in\"] = \"val num\", IGNORECASE = 
%d---\n",
-               IGNORECASE)
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
 
        makea(a)
-       SORT_STR = "desc val str"
+       SORT_STR = "@val_str_desc"
        proc_sort(a, "")
-       printf("---end PROCINFO[\"sorted_in\"] = \"desc val str\", IGNORECASE = 
%d---\n",
-               IGNORECASE)
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
 
        makea(a)
-       SORT_STR = "desc val num"
+       SORT_STR = "@val_num_desc"
        proc_sort(a, "")
-       printf("---end PROCINFO[\"sorted_in\"] = \"desc val num\", IGNORECASE = 
%d---\n",
-               IGNORECASE)
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
+
+       makea(a)
+       SORT_STR = "@val_type_asc"
+       proc_sort(a, "")
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
+
+       makea(a)
+       SORT_STR = "@val_type_desc"
+       proc_sort(a, "")
+       printf("---end PROCINFO[\"sorted_in\"] = \"%s\", IGNORECASE = %d---\n",
+               SORT_STR, IGNORECASE)
   }
 }
 
diff --git a/test/sort1.ok b/test/sort1.ok
index 8ba2bcd..2d43e31 100644
--- a/test/sort1.ok
+++ b/test/sort1.ok
@@ -1,5 +1,5 @@
-       [1]:      1234
-       [2]:       234
+       [1]:       234
+       [2]:      1234
        [3]:     Zebra
        [4]:      barz
        [5]:    blattt
@@ -8,8 +8,8 @@
     [6][3]:    tttalb
     [6][4]:      zrab
 ---end asort(a), IGNORECASE = 0---
-       [1]:      barz      1234
-       [2]:    blattt       234
+       [1]:      barz       234
+       [2]:    blattt      1234
        [3]:     Zebra     Zebra
        [4]:      1234      barz
        [5]:       234    blattt
@@ -18,8 +18,8 @@
     [6][3]:    tttalb    tttalb
     [6][4]:      zrab      zrab
 ---end asort(a, b), IGNORECASE = 0---
-       [1]:      1234
-       [2]:       234
+       [1]:       234
+       [2]:      1234
        [3]:     Zebra
        [4]:      barz
        [5]:    blattt
@@ -28,26 +28,26 @@
     [6][3]:    tttalb
     [6][4]:      zrab
 ---end asort(a, a), IGNORECASE = 0---
-       [1]:      barz     Zebra
-       [2]:    blattt      barz
-       [3]:     Zebra    blattt
-       [4]:      1234       234
-       [5]:       234      1234
-    [6][1]:      4321     arbeZ
-    [6][2]:     arbeZ    tttalb
-    [6][3]:    tttalb      zrab
-    [6][4]:      zrab      4321
----end asort(a, b, "num"), IGNORECASE = 0---
+       [1]:      barz      barz
+       [2]:    blattt    blattt
+       [3]:     Zebra     Zebra
+       [4]:      1234      1234
+       [5]:       234       234
+    [6][1]:      4321      4321
+    [6][2]:     arbeZ     arbeZ
+    [6][3]:    tttalb    tttalb
+    [6][4]:      zrab      zrab
+---end asort(a, b, "@ind_num_asc"), IGNORECASE = 0---
     [1][1]:      zrab
     [1][2]:    tttalb
     [1][3]:     arbeZ
     [1][4]:      4321
-       [2]:    blattt
-       [3]:      barz
+       [2]:       234
+       [3]:      1234
        [4]:     Zebra
-       [5]:       234
-       [6]:      1234
----end asort(a, a, "desc str"), IGNORECASE = 0---
+       [5]:    blattt
+       [6]:      barz
+---end asort(a, a, "@ind_str_desc"), IGNORECASE = 0---
        [4]:      1234
        [5]:       234
        [3]:     Zebra
@@ -57,17 +57,17 @@
     [6][2]:     arbeZ
     [6][3]:    tttalb
     [6][4]:      zrab
----end PROCINFO["sorted_in"] = "val str", IGNORECASE = 0---
-       [3]:     Zebra
+---end PROCINFO["sorted_in"] = "@val_str_asc", IGNORECASE = 0---
        [1]:      barz
        [2]:    blattt
+       [3]:     Zebra
        [5]:       234
        [4]:      1234
+    [6][4]:      zrab
     [6][2]:     arbeZ
     [6][3]:    tttalb
-    [6][4]:      zrab
     [6][1]:      4321
----end PROCINFO["sorted_in"] = "val num", IGNORECASE = 0---
+---end PROCINFO["sorted_in"] = "@val_num_asc", IGNORECASE = 0---
     [6][4]:      zrab
     [6][3]:    tttalb
     [6][2]:     arbeZ
@@ -77,19 +77,39 @@
        [3]:     Zebra
        [5]:       234
        [4]:      1234
----end PROCINFO["sorted_in"] = "desc val str", IGNORECASE = 0---
+---end PROCINFO["sorted_in"] = "@val_str_desc", IGNORECASE = 0---
     [6][1]:      4321
     [6][4]:      zrab
-    [6][3]:    tttalb
     [6][2]:     arbeZ
+    [6][3]:    tttalb
        [4]:      1234
        [5]:       234
+       [1]:      barz
+       [2]:    blattt
+       [3]:     Zebra
+---end PROCINFO["sorted_in"] = "@val_num_desc", IGNORECASE = 0---
+       [5]:       234
+       [4]:      1234
+       [3]:     Zebra
+       [1]:      barz
+       [2]:    blattt
+    [6][1]:      4321
+    [6][2]:     arbeZ
+    [6][3]:    tttalb
+    [6][4]:      zrab
+---end PROCINFO["sorted_in"] = "@val_type_asc", IGNORECASE = 0---
+    [6][4]:      zrab
+    [6][3]:    tttalb
+    [6][2]:     arbeZ
+    [6][1]:      4321
        [2]:    blattt
        [1]:      barz
        [3]:     Zebra
----end PROCINFO["sorted_in"] = "desc val num", IGNORECASE = 0---
-       [1]:      1234
-       [2]:       234
+       [4]:      1234
+       [5]:       234
+---end PROCINFO["sorted_in"] = "@val_type_desc", IGNORECASE = 0---
+       [1]:       234
+       [2]:      1234
        [3]:      barz
        [4]:    blattt
        [5]:     Zebra
@@ -98,8 +118,8 @@
     [6][3]:    tttalb
     [6][4]:      zrab
 ---end asort(a), IGNORECASE = 1---
-       [1]:      barz      1234
-       [2]:    blattt       234
+       [1]:      barz       234
+       [2]:    blattt      1234
        [3]:     Zebra      barz
        [4]:      1234    blattt
        [5]:       234     Zebra
@@ -108,8 +128,8 @@
     [6][3]:    tttalb    tttalb
     [6][4]:      zrab      zrab
 ---end asort(a, b), IGNORECASE = 1---
-       [1]:      1234
-       [2]:       234
+       [1]:       234
+       [2]:      1234
        [3]:      barz
        [4]:    blattt
        [5]:     Zebra
@@ -121,23 +141,23 @@
        [1]:      barz      barz
        [2]:    blattt    blattt
        [3]:     Zebra     Zebra
-       [4]:      1234       234
-       [5]:       234      1234
-    [6][1]:      4321     arbeZ
-    [6][2]:     arbeZ    tttalb
-    [6][3]:    tttalb      zrab
-    [6][4]:      zrab      4321
----end asort(a, b, "num"), IGNORECASE = 1---
+       [4]:      1234      1234
+       [5]:       234       234
+    [6][1]:      4321      4321
+    [6][2]:     arbeZ     arbeZ
+    [6][3]:    tttalb    tttalb
+    [6][4]:      zrab      zrab
+---end asort(a, b, "@ind_num_asc"), IGNORECASE = 1---
     [1][1]:      zrab
     [1][2]:    tttalb
     [1][3]:     arbeZ
     [1][4]:      4321
-       [2]:     Zebra
-       [3]:    blattt
-       [4]:      barz
-       [5]:       234
-       [6]:      1234
----end asort(a, a, "desc str"), IGNORECASE = 1---
+       [2]:       234
+       [3]:      1234
+       [4]:     Zebra
+       [5]:    blattt
+       [6]:      barz
+---end asort(a, a, "@ind_str_desc"), IGNORECASE = 1---
        [4]:      1234
        [5]:       234
        [1]:      barz
@@ -147,17 +167,17 @@
     [6][2]:     arbeZ
     [6][3]:    tttalb
     [6][4]:      zrab
----end PROCINFO["sorted_in"] = "val str", IGNORECASE = 1---
+---end PROCINFO["sorted_in"] = "@val_str_asc", IGNORECASE = 1---
        [1]:      barz
        [2]:    blattt
        [3]:     Zebra
        [5]:       234
        [4]:      1234
+    [6][4]:      zrab
     [6][2]:     arbeZ
     [6][3]:    tttalb
-    [6][4]:      zrab
     [6][1]:      4321
----end PROCINFO["sorted_in"] = "val num", IGNORECASE = 1---
+---end PROCINFO["sorted_in"] = "@val_num_asc", IGNORECASE = 1---
     [6][4]:      zrab
     [6][3]:    tttalb
     [6][2]:     arbeZ
@@ -167,14 +187,34 @@
        [1]:      barz
        [5]:       234
        [4]:      1234
----end PROCINFO["sorted_in"] = "desc val str", IGNORECASE = 1---
+---end PROCINFO["sorted_in"] = "@val_str_desc", IGNORECASE = 1---
     [6][1]:      4321
     [6][4]:      zrab
-    [6][3]:    tttalb
     [6][2]:     arbeZ
+    [6][3]:    tttalb
        [4]:      1234
        [5]:       234
+       [1]:      barz
+       [2]:    blattt
+       [3]:     Zebra
+---end PROCINFO["sorted_in"] = "@val_num_desc", IGNORECASE = 1---
+       [5]:       234
+       [4]:      1234
+       [1]:      barz
+       [2]:    blattt
+       [3]:     Zebra
+    [6][1]:      4321
+    [6][2]:     arbeZ
+    [6][3]:    tttalb
+    [6][4]:      zrab
+---end PROCINFO["sorted_in"] = "@val_type_asc", IGNORECASE = 1---
+    [6][4]:      zrab
+    [6][3]:    tttalb
+    [6][2]:     arbeZ
+    [6][1]:      4321
        [3]:     Zebra
        [2]:    blattt
        [1]:      barz
----end PROCINFO["sorted_in"] = "desc val num", IGNORECASE = 1---
+       [4]:      1234
+       [5]:       234
+---end PROCINFO["sorted_in"] = "@val_type_desc", IGNORECASE = 1---
diff --git a/test/sortfor.awk b/test/sortfor.awk
index 611eca6..922b5e8 100644
--- a/test/sortfor.awk
+++ b/test/sortfor.awk
@@ -1,9 +1,9 @@
 { a[$0]++ }
 END {
-       PROCINFO["sorted_in"] = "ascending"
+       PROCINFO["sorted_in"] = "@ind_str_asc"
        for (i in a)
                print i
-       PROCINFO["sorted_in"] = "descending"
+       PROCINFO["sorted_in"] = "@ind_str_desc"
        for (i in a)
                print i
 }

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog          |   16 +
 array.c            |  276 +--
 awk.h              |    2 +-
 debug.c            |    2 +-
 doc/ChangeLog      |    5 +
 doc/gawk.info      | 2739 ++++++++++++-----------
 doc/gawk.texi      | 6400 ++++++++++++++++++++++++++--------------------------
 eval.c             |    9 +-
 test/ChangeLog     |    7 +
 test/arraysort.awk |   20 +-
 test/arraysort.ok  |    8 +-
 test/sort1.awk     |   46 +-
 test/sort1.ok      |  146 +-
 test/sortfor.awk   |    4 +-
 14 files changed, 4981 insertions(+), 4699 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]