diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/ChangeLog | 4 | ||||
-rw-r--r-- | doc/api.texi | 612 | ||||
-rw-r--r-- | doc/gawk.info | 549 | ||||
-rw-r--r-- | doc/gawk.texi | 25 |
4 files changed, 924 insertions, 266 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog index e0f8c2f9..7613e26d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2012-10-19 Arnold D. Robbins <arnold@skeeve.com> + + * gawk.texi: More doc on SYMTAB. + 2012-10-05 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (LN, install-data-hook, uninstall-hook): Removed. No diff --git a/doc/api.texi b/doc/api.texi index 9e3c288d..ab4ea632 100644 --- a/doc/api.texi +++ b/doc/api.texi @@ -221,15 +221,41 @@ ISBN 1-882114-28-0 @* @node Extension API @chapter Writing Extensions for @command{gawk} -This @value{CHAPTER} describes how to extend @command{gawk} using +It is possible to add new built-in +functions to @command{gawk} using dynamically loaded libraries. This +facility is available on systems (such as GNU/Linux) that support +the C @code{dlopen()} and @code{dlsym()} functions. +This @value{CHAPTER} describes how to do so using code written in C or C++. If you don't know anything about C programming, you can safely skip this @value{CHAPTER}, although you may wish to review the documentation on the extensions that come with @command{gawk} (@pxref{Extension Samples}). +@quotation NOTE +When @option{--sandbox} is specified, extensions are disabled +(@pxref{Options}. +@end quotation + @menu +* Plugin License:: A note about licensing. @end menu +@node Plugin License +@section Extension Licensing + +Every dynamic extension should define the global symbol +@code{plugin_is_GPL_compatible} to assert that it has been licensed under +a GPL-compatible license. If this symbol does not exist, @command{gawk} +will emit a fatal error and exit. + +The declared type of the symbol should be @code{int}. It does not need +to be in any allocated section, though. The code merely asserts that +the symbol exists in the global scope. Something like this is enough: + +@example +int plugin_is_GPL_compatible; +@end example + @node Extension Intro @section Introduction @@ -1599,11 +1625,593 @@ The others should not change during execution. @c It's enough to show chdir and stat, no need for fts @node Extension Samples -@section Sample Extensions +@section Example: Directory and File Operation Built-ins + +Two useful functions that are not in @command{awk} are @code{chdir()} +(so that an @command{awk} program can change its directory) and +@code{stat()} (so that an @command{awk} program can gather information about +a file). +This @value{SECTION} implements these functions for @command{gawk} in an +external extension. @menu +* 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. @end menu +@node Internal File Description +@subsection Using @code{chdir()} and @code{stat()} + +This @value{SECTION} shows how to use the new functions at +the @command{awk} level once they've been integrated into the +running @command{gawk} interpreter. Using @code{chdir()} is very +straightforward. It takes one argument, the new directory to change to: + +@example +@@load "filefuncs" +@dots{} +newdir = "/home/arnold/funstuff" +ret = chdir(newdir) +if (ret < 0) @{ + printf("could not change to %s: %s\n", + newdir, ERRNO) > "/dev/stderr" + exit 1 +@} +@dots{} +@end example + +The return value is negative if the @code{chdir()} failed, and +@code{ERRNO} (@pxref{Built-in Variables}) is set to a string indicating +the error. + +Using @code{stat()} is a bit more complicated. The C @code{stat()} +function fills in a structure that has a fair amount of information. +The right way to model this in @command{awk} is to fill in an associative +array with the appropriate information: + +@c broke printf for page breaking +@example +file = "/home/arnold/.profile" +# fdata[1] = "x" # force `fdata' to be an array FIXME: IS THIS NEEDED +ret = stat(file, fdata) +if (ret < 0) @{ + printf("could not stat %s: %s\n", + file, ERRNO) > "/dev/stderr" + exit 1 +@} +printf("size of %s is %d bytes\n", file, fdata["size"]) +@end example + +The @code{stat()} function always clears the data array, even if +the @code{stat()} fails. It fills in the following elements: + +@table @code +@item "name" +The name of the file that was @code{stat()}'ed. + +@item "dev" +@itemx "ino" +The file's device and inode numbers, respectively. + +@item "mode" +The file's mode, as a numeric value. This includes both the file's +type and its permissions. + +@item "nlink" +The number of hard links (directory entries) the file has. + +@item "uid" +@itemx "gid" +The numeric user and group ID numbers of the file's owner. + +@item "size" +The size in bytes of the file. + +@item "blocks" +The number of disk blocks the file actually occupies. This may not +be a function of the file's size if the file has holes. + +@item "atime" +@itemx "mtime" +@itemx "ctime" +The file's last access, modification, and inode update times, +respectively. These are numeric timestamps, suitable for formatting +with @code{strftime()} +(@pxref{Built-in}). + +@item "pmode" +The file's ``printable mode.'' This is a string representation of +the file's type and permissions, such as what is produced by +@samp{ls -l}---for example, @code{"drwxr-xr-x"}. + +@item "type" +A printable string representation of the file's type. The value +is one of the following: + +@table @code +@item "blockdev" +@itemx "chardev" +The file is a block or character device (``special file''). + +@ignore +@item "door" +The file is a Solaris ``door'' (special file used for +interprocess communications). +@end ignore + +@item "directory" +The file is a directory. + +@item "fifo" +The file is a named-pipe (also known as a FIFO). + +@item "file" +The file is just a regular file. + +@item "socket" +The file is an @code{AF_UNIX} (``Unix domain'') socket in the +filesystem. + +@item "symlink" +The file is a symbolic link. +@end table +@end table + +Several additional elements may be present depending upon the operating +system and the type of the file. You can test for them in your @command{awk} +program by using the @code{in} operator +(@pxref{Reference to Elements}): + +@table @code +@item "blksize" +The preferred block size for I/O to the file. This field is not +present on all POSIX-like systems in the C @code{stat} structure. + +@item "linkval" +If the file is a symbolic link, this element is the name of the +file the link points to (i.e., the value of the link). + +@item "rdev" +@itemx "major" +@itemx "minor" +If the file is a block or character device file, then these values +represent the numeric device number and the major and minor components +of that number, respectively. +@end table + +@node Internal File Ops +@subsection C Code for @code{chdir()} and @code{stat()} + +Here is the C code for these extensions.@footnote{This version is +edited slightly for presentation. See @file{extension/filefuncs.c} +in the @command{gawk} distribution for the complete version.} + +@c break line for page breaking +@example +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include "gawkapi.h" + +#include "gettext.h" +#define _(msgid) gettext(msgid) +#define N_(msgid) msgid + +#include "gawkfts.h" +#include "stack.h" + +static const gawk_api_t *api; /* for convenience macros to work */ +static awk_ext_id_t *ext_id; +static awk_bool_t init_filefuncs(void); +static awk_bool_t (*init_func)(void) = init_filefuncs; +static const char *ext_version = "filefuncs extension: version 1.0"; + +int plugin_is_GPL_compatible; + +/* do_chdir --- provide dynamically loaded chdir() builtin for gawk */ + +static awk_value_t * +do_chdir(int nargs, awk_value_t *result) +@{ + awk_value_t newdir; + int ret = -1; + + assert(result != NULL); + + if (do_lint && nargs != 1) + lintwarn(ext_id, _("chdir: called with incorrect number of arguments, expecting 1")); +@end example + +The file includes +a number of standard header files, and then includes the +@code{"gawkapi.h"} header file which provides the API definitions. + +@cindex programming conventions, @command{gawk} internals +By convention, for an @command{awk} function @code{foo()}, the function that +implements it is called @samp{do_foo()}. The function should have two +arguments: the first is an +@samp{int} usually called @code{nargs}, that +represents the number of defined arguments for the function. +The second is a pointer to an @code{awk_result_t}, usally named +@code{result}. +The @code{newdir} +variable represents the new directory to change to, retrieved +with @code{get_argument()}. Note that the first argument is +numbered zero. + +This code actually accomplishes the @code{chdir()}. It first forces +the argument to be a string and passes the string value to the +@code{chdir()} system call. If the @code{chdir()} fails, @code{ERRNO} +is updated. + +@example + if (get_argument(0, AWK_STRING, & newdir)) @{ + ret = chdir(newdir.str_value.str); + if (ret < 0) + update_ERRNO_int(errno); + @} +@end example + +Finally, the function returns the return value to the @command{awk} level: + +@example + return make_number(ret, result); +@} +@end example + +The @code{stat()} built-in is more involved. First comes a function +that turns a numeric mode into a printable representation +(e.g., 644 becomes @samp{-rw-r--r--}). This is omitted here for brevity: + +@c break line for page breaking +@example +/* format_mode --- turn a stat mode field into something readable */ + +static char * +format_mode(unsigned long fmode) +@{ + @dots{} +@} +@end example + +Next comes a function for reading symbolic links, which is also +omitted here for brevity: + +@example +/* read_symlink -- read a symbolic link into an allocated buffer. + @dots{} */ + +static char * +read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) +@{ + @dots{} +@} +@end example + +Two helper functions simplify entering values in the +array that will contain the result of the @code{stat()}: + +@example +/* array_set --- set an array element */ + +static void +array_set(awk_array_t array, const char *sub, awk_value_t *value) +@{ + awk_value_t index; + + set_array_element(array, + make_const_string(sub, strlen(sub), & index), + value); + +@} + +/* array_set_numeric --- set an array element with a number */ + +static void +array_set_numeric(awk_array_t array, const char *sub, double num) +@{ + awk_value_t tmp; + + array_set(array, sub, make_number(num, & tmp)); +@} +@end example + +The following function does most of the work to fill in +the @code{awk_array_t} result array with values obtained +from a valid @code{struct stat}. It is done in a separate function +to support the @code{stat()} function for @command{gawk} and also +to support the @code{fts()} extension which is included in +the same file but whose code is not shown here. (FIXME: XREF to section +with documentation.) + +@example +/* fill_stat_array --- do the work to fill an array with stat info */ + +static int +fill_stat_array(const char *name, awk_array_t array, struct stat *sbuf) +@{ + char *pmode; /* printable mode */ + const char *type = "unknown"; + awk_value_t tmp; + static struct ftype_map @{ + unsigned int mask; + const char *type; + @} ftype_map[] = @{ + @{ S_IFREG, "file" @}, + @{ S_IFBLK, "blockdev" @}, + @{ S_IFCHR, "chardev" @}, + @{ S_IFDIR, "directory" @}, +#ifdef S_IFSOCK + @{ S_IFSOCK, "socket" @}, +#endif +#ifdef S_IFIFO + @{ S_IFIFO, "fifo" @}, +#endif +#ifdef S_IFLNK + @{ S_IFLNK, "symlink" @}, +#endif +#ifdef S_IFDOOR /* Solaris weirdness */ + @{ S_IFDOOR, "door" @}, +#endif /* S_IFDOOR */ + @}; + int j, k; + + /* empty out the array */ + clear_array(array); + + /* fill in the array */ + array_set(array, "name", make_const_string(name, strlen(name), & tmp)); + array_set_numeric(array, "dev", sbuf->st_dev); + array_set_numeric(array, "ino", sbuf->st_ino); + array_set_numeric(array, "mode", sbuf->st_mode); + array_set_numeric(array, "nlink", sbuf->st_nlink); + array_set_numeric(array, "uid", sbuf->st_uid); + array_set_numeric(array, "gid", sbuf->st_gid); + array_set_numeric(array, "size", sbuf->st_size); + array_set_numeric(array, "blocks", sbuf->st_blocks); + array_set_numeric(array, "atime", sbuf->st_atime); + array_set_numeric(array, "mtime", sbuf->st_mtime); + array_set_numeric(array, "ctime", sbuf->st_ctime); + + /* for block and character devices, add rdev, major and minor numbers */ + if (S_ISBLK(sbuf->st_mode) || S_ISCHR(sbuf->st_mode)) @{ + array_set_numeric(array, "rdev", sbuf->st_rdev); + array_set_numeric(array, "major", major(sbuf->st_rdev)); + array_set_numeric(array, "minor", minor(sbuf->st_rdev)); + @} + +#ifdef HAVE_ST_BLKSIZE + array_set_numeric(array, "blksize", sbuf->st_blksize); +#endif /* HAVE_ST_BLKSIZE */ + + pmode = format_mode(sbuf->st_mode); + array_set(array, "pmode", make_const_string(pmode, strlen(pmode), & tmp)); + + /* for symbolic links, add a linkval field */ + if (S_ISLNK(sbuf->st_mode)) @{ + char *buf; + ssize_t linksize; + + if ((buf = read_symlink(name, sbuf->st_size, + & linksize)) != NULL) + array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp)); + else + warning(ext_id, "stat: unable to read symbolic link `%s'", name); + @} + + /* add a type field */ + type = "unknown"; /* shouldn't happen */ + for (j = 0, k = sizeof(ftype_map)/sizeof(ftype_map[0]); j < k; j++) @{ + if ((sbuf->st_mode & S_IFMT) == ftype_map[j].mask) @{ + type = ftype_map[j].type; + break; + @} + @} + + array_set(array, "type", make_const_string(type, strlen(type), &tmp)); + + return 0; +@} +@end example + +Finall, here is the @code{do_stat()} function. It starts with +variable declarations and argument checking: + +@ignore +Changed message for page breaking. Used to be: + "stat: called with incorrect number of arguments (%d), should be 2", +@end ignore +@example +/* do_stat --- provide a stat() function for gawk */ + +static awk_value_t * +do_stat(int nargs, awk_value_t *result) +@{ + awk_value_t file_param, array_param; + char *name; + awk_array_t array; + int ret; + struct stat sbuf; + + assert(result != NULL); + + if (do_lint && nargs != 2) @{ + lintwarn(ext_id, _("stat: called with wrong number of arguments")); + return make_number(-1, result); + @} +@end example + +Then comes the actual work. First, the function gets the arguments. +Next, it gets the information for the file. +The code use @code{lstat()} (instead of @code{stat()}) +to get the file information, +in case the file is a symbolic link. +If there's an error, it sets @code{ERRNO} and returns: + +@example + /* file is first arg, array to hold results is second */ + if ( ! get_argument(0, AWK_STRING, & file_param) + || ! get_argument(1, AWK_ARRAY, & array_param)) @{ + warning(ext_id, _("stat: bad parameters")); + return make_number(-1, result); + @} + + name = file_param.str_value.str; + array = array_param.array_cookie; + + /* lstat the file, if error, set ERRNO and return */ + ret = lstat(name, & sbuf); + if (ret < 0) @{ + update_ERRNO_int(errno); + return make_number(ret, result); + @} +@end example + +The tedious work is done by @code{fill_stat_array()}, shown +earlier. +When done, return the result from @code{fill_stat_array()}: + +@example + ret = fill_stat_array(name, array, & sbuf); + + return make_number(ret, result); +@} +@end example + +@cindex programming conventions, @command{gawk} internals +Finally, it's necessary to provide the ``glue'' that loads the +new function(s) into @command{gawk}. + +The @samp{filefuncs} extension also provides an @code{fts()} +function, which we omit here. For its sake there is an initialization +function: + +@example +/* init_filefuncs --- initialization routine */ + +static awk_bool_t +init_filefuncs(void) +@{ + @dots{} +@} +@end example + +Almost done. We need an array of @code{awk_ext_func_t} +structures for loading each function into @command{gawk}: + +@example +static awk_ext_func_t func_table[] = @{ + @{ "chdir", do_chdir, 1 @}, + @{ "stat", do_stat, 2 @}, + @{ "fts", do_fts, 3 @}, +@}; +@end example + +Each extension must have a routine named @code{dl_load()} to load +everything that needs to be loaded. The simplest way is to use the +@code{dl_load_func} macro in @code{gawkapi.h}: + +@example +/* define the dl_load function using the boilerplate macro */ + +dl_load_func(func_table, filefuncs, "") +@end example + +And that's it! As an exercise, consider adding functions to +implement system calls such as @code{chown()}, @code{chmod()}, +and @code{umask()}. + +@node Using Internal File Ops +@subsection Integrating the Extensions + +@cindex @command{gawk}, interpreter@comma{} adding code to +Now that the code is written, it must be possible to add it at +runtime to the running @command{gawk} interpreter. First, the +code must be compiled. Assuming that the functions are in +a file named @file{filefuncs.c}, and @var{idir} is the location +of the @command{gawk} include files, +the following steps create +a GNU/Linux shared library: + +@example +$ @kbd{gcc -fPIC -shared -DHAVE_CONFIG_H -c -O -g -I@var{idir} filefuncs.c} +$ @kbd{ld -o filefuncs.so -shared filefuncs.o} +@end example + +@cindex @code{extension()} function (@command{gawk}) +Once the library exists, it is loaded by calling the @code{extension()} +built-in function. +This function takes two arguments: the name of the +library to load and the name of a function to call when the library +is first loaded. This function adds the new functions to @command{gawk}. +It returns the value returned by the initialization function +within the shared library: + +@example +# file testff.awk +BEGIN @{ + extension("./filefuncs.so", "dl_load") + + chdir(".") # no-op + + data[1] = 1 # force `data' to be an array + print "Info for testff.awk" + ret = stat("testff.awk", data) + print "ret =", ret + for (i in data) + printf "data[\"%s\"] = %s\n", i, data[i] + print "testff.awk modified:", + strftime("%m %d %y %H:%M:%S", data["mtime"]) + + print "\nInfo for JUNK" + ret = stat("JUNK", data) + print "ret =", ret + for (i in data) + printf "data[\"%s\"] = %s\n", i, data[i] + print "JUNK modified:", strftime("%m %d %y %H:%M:%S", data["mtime"]) +@} +@end example + +Here are the results of running the program: + +@example +$ @kbd{gawk -f testff.awk} +@print{} Info for testff.awk +@print{} ret = 0 +@print{} data["size"] = 607 +@print{} data["ino"] = 14945891 +@print{} data["name"] = testff.awk +@print{} data["pmode"] = -rw-rw-r-- +@print{} data["nlink"] = 1 +@print{} data["atime"] = 1293993369 +@print{} data["mtime"] = 1288520752 +@print{} data["mode"] = 33204 +@print{} data["blksize"] = 4096 +@print{} data["dev"] = 2054 +@print{} data["type"] = file +@print{} data["gid"] = 500 +@print{} data["uid"] = 500 +@print{} data["blocks"] = 8 +@print{} data["ctime"] = 1290113572 +@print{} testff.awk modified: 10 31 10 12:25:52 +@print{} +@print{} Info for JUNK +@print{} ret = -1 +@print{} JUNK modified: 01 01 70 02:00:00 +@end example + @node Extension Sample File Functions @subsection File Related Functions diff --git a/doc/gawk.info b/doc/gawk.info index 08fbc297..b97acf46 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -9750,6 +9750,27 @@ with a pound sign (`#'). test if an element in `SYMTAB' is an array. Also, you may not use the `delete' statement with the `SYMTAB' array. + You may use an index for `SYMTAB' that is not a predefined + identifer: + + SYMTAB["xxx"] = 5 + print SYMTAB["xxx"] + + This works as expected: in this case `SYMTAB' acts just like a + regular array. The only difference is that you can't then delete + `SYMTAB["xxx"]'. + + The `SYMTAB' array is more interesting than it looks. Andrew Schorr + points out that it effectively gives `awk' data pointers. Consider + his example: + + # Indirect multiply of any variable by amount, return result + + function multiply(variable, amount) + { + return SYMTAB[variable] *= amount + } + NOTE: In order to avoid severe time-travel paradoxes(2), neither `FUNCTAB' nor `SYMTAB' are available as elements within the `SYMTAB' array. @@ -26022,7 +26043,7 @@ Index (line 67) * advanced features, data files as single record: Records. (line 180) * advanced features, fixed-width data: Constant Size. (line 9) -* advanced features, FNR/NR variables: Auto-set. (line 274) +* advanced features, FNR/NR variables: Auto-set. (line 295) * advanced features, gawk: Advanced Features. (line 6) * advanced features, gawk, network programming: TCP/IP Networking. (line 6) @@ -26527,7 +26548,7 @@ Index (line 47) * dark corner, FILENAME variable <1>: Auto-set. (line 93) * dark corner, FILENAME variable: Getline Notes. (line 19) -* dark corner, FNR/NR variables: Auto-set. (line 274) +* dark corner, FNR/NR variables: Auto-set. (line 295) * dark corner, format-control characters: Control Letters. (line 18) * dark corner, FS as null string: Single Character Fields. (line 20) @@ -27009,7 +27030,7 @@ Index * floating-point, numbers: General Arithmetic. (line 6) * FNR variable <1>: Auto-set. (line 103) * FNR variable: Records. (line 6) -* FNR variable, changing: Auto-set. (line 274) +* FNR variable, changing: Auto-set. (line 295) * for statement: For Statement. (line 6) * for statement, in arrays: Scanning an Array. (line 20) * format specifiers, mixing regular with positional specifiers: Printf Ordering. @@ -27594,7 +27615,7 @@ Index * not Boolean-logic operator: Boolean Ops. (line 6) * NR variable <1>: Auto-set. (line 125) * NR variable: Records. (line 6) -* NR variable, changing: Auto-set. (line 274) +* NR variable, changing: Auto-set. (line 295) * null strings <1>: Basic Data Typing. (line 26) * null strings <2>: Truth Values. (line 6) * null strings <3>: Regexp Field Splitting. @@ -28674,265 +28695,265 @@ Node: Built-in Variables393879 Node: User-modified394974 Ref: User-modified-Footnote-1403329 Node: Auto-set403391 -Ref: Auto-set-Footnote-1415085 -Ref: Auto-set-Footnote-2415290 -Node: ARGC and ARGV415346 -Node: Arrays419197 -Node: Array Basics420702 -Node: Array Intro421528 -Node: Reference to Elements425846 -Node: Assigning Elements428116 -Node: Array Example428607 -Node: Scanning an Array430339 -Node: Controlling Scanning432653 -Ref: Controlling Scanning-Footnote-1437586 -Node: Delete437902 -Ref: Delete-Footnote-1440667 -Node: Numeric Array Subscripts440724 -Node: Uninitialized Subscripts442907 -Node: Multi-dimensional444535 -Node: Multi-scanning447629 -Node: Arrays of Arrays449220 -Node: Functions453865 -Node: Built-in454687 -Node: Calling Built-in455765 -Node: Numeric Functions457753 -Ref: Numeric Functions-Footnote-1461585 -Ref: Numeric Functions-Footnote-2461942 -Ref: Numeric Functions-Footnote-3461990 -Node: String Functions462259 -Ref: String Functions-Footnote-1485756 -Ref: String Functions-Footnote-2485885 -Ref: String Functions-Footnote-3486133 -Node: Gory Details486220 -Ref: table-sub-escapes487899 -Ref: table-sub-posix-92489253 -Ref: table-sub-proposed490596 -Ref: table-posix-sub491946 -Ref: table-gensub-escapes493492 -Ref: Gory Details-Footnote-1494699 -Ref: Gory Details-Footnote-2494750 -Node: I/O Functions494901 -Ref: I/O Functions-Footnote-1501556 -Node: Time Functions501703 -Ref: Time Functions-Footnote-1512595 -Ref: Time Functions-Footnote-2512663 -Ref: Time Functions-Footnote-3512821 -Ref: Time Functions-Footnote-4512932 -Ref: Time Functions-Footnote-5513044 -Ref: Time Functions-Footnote-6513271 -Node: Bitwise Functions513537 -Ref: table-bitwise-ops514095 -Ref: Bitwise Functions-Footnote-1518316 -Node: Type Functions518500 -Node: I18N Functions518970 -Node: User-defined520597 -Node: Definition Syntax521401 -Ref: Definition Syntax-Footnote-1526311 -Node: Function Example526380 -Node: Function Caveats528974 -Node: Calling A Function529395 -Node: Variable Scope530510 -Node: Pass By Value/Reference532485 -Node: Return Statement535925 -Node: Dynamic Typing538906 -Node: Indirect Calls539641 -Node: Internationalization549326 -Node: I18N and L10N550752 -Node: Explaining gettext551438 -Ref: Explaining gettext-Footnote-1556504 -Ref: Explaining gettext-Footnote-2556688 -Node: Programmer i18n556853 -Node: Translator i18n561053 -Node: String Extraction561846 -Ref: String Extraction-Footnote-1562807 -Node: Printf Ordering562893 -Ref: Printf Ordering-Footnote-1565677 -Node: I18N Portability565741 -Ref: I18N Portability-Footnote-1568190 -Node: I18N Example568253 -Ref: I18N Example-Footnote-1570888 -Node: Gawk I18N570960 -Node: Advanced Features571577 -Node: Nondecimal Data573090 -Node: Array Sorting574673 -Node: Controlling Array Traversal575370 -Node: Array Sorting Functions583608 -Ref: Array Sorting Functions-Footnote-1587282 -Ref: Array Sorting Functions-Footnote-2587375 -Node: Two-way I/O587569 -Ref: Two-way I/O-Footnote-1593001 -Node: TCP/IP Networking593071 -Node: Profiling595915 -Node: Library Functions603369 -Ref: Library Functions-Footnote-1606376 -Node: Library Names606547 -Ref: Library Names-Footnote-1610018 -Ref: Library Names-Footnote-2610238 -Node: General Functions610324 -Node: Strtonum Function611277 -Node: Assert Function614207 -Node: Round Function617533 -Node: Cliff Random Function619076 -Node: Ordinal Functions620092 -Ref: Ordinal Functions-Footnote-1623162 -Ref: Ordinal Functions-Footnote-2623414 -Node: Join Function623623 -Ref: Join Function-Footnote-1625394 -Node: Getlocaltime Function625594 -Node: Data File Management629309 -Node: Filetrans Function629941 -Node: Rewind Function634080 -Node: File Checking635467 -Node: Empty Files636561 -Node: Ignoring Assigns638791 -Node: Getopt Function640344 -Ref: Getopt Function-Footnote-1651648 -Node: Passwd Functions651851 -Ref: Passwd Functions-Footnote-1660826 -Node: Group Functions660914 -Node: Walking Arrays668998 -Node: Sample Programs670567 -Node: Running Examples671232 -Node: Clones671960 -Node: Cut Program673184 -Node: Egrep Program683029 -Ref: Egrep Program-Footnote-1690802 -Node: Id Program690912 -Node: Split Program694528 -Ref: Split Program-Footnote-1698047 -Node: Tee Program698175 -Node: Uniq Program700978 -Node: Wc Program708407 -Ref: Wc Program-Footnote-1712673 -Ref: Wc Program-Footnote-2712873 -Node: Miscellaneous Programs712965 -Node: Dupword Program714153 -Node: Alarm Program716184 -Node: Translate Program720933 -Ref: Translate Program-Footnote-1725320 -Ref: Translate Program-Footnote-2725548 -Node: Labels Program725682 -Ref: Labels Program-Footnote-1729053 -Node: Word Sorting729137 -Node: History Sorting733021 -Node: Extract Program734860 -Ref: Extract Program-Footnote-1742343 -Node: Simple Sed742471 -Node: Igawk Program745533 -Ref: Igawk Program-Footnote-1760690 -Ref: Igawk Program-Footnote-2760891 -Node: Anagram Program761029 -Node: Signature Program764097 -Node: Debugger765197 -Node: Debugging766163 -Node: Debugging Concepts766596 -Node: Debugging Terms768452 -Node: Awk Debugging771049 -Node: Sample Debugging Session771941 -Node: Debugger Invocation772461 -Node: Finding The Bug773790 -Node: List of Debugger Commands780278 -Node: Breakpoint Control781612 -Node: Debugger Execution Control785276 -Node: Viewing And Changing Data788636 -Node: Execution Stack791992 -Node: Debugger Info793459 -Node: Miscellaneous Debugger Commands797440 -Node: Readline Support802885 -Node: Limitations803716 -Node: Arbitrary Precision Arithmetic805968 -Ref: Arbitrary Precision Arithmetic-Footnote-1807610 -Node: General Arithmetic807758 -Node: Floating Point Issues809478 -Node: String Conversion Precision810359 -Ref: String Conversion Precision-Footnote-1812065 -Node: Unexpected Results812174 -Node: POSIX Floating Point Problems814327 -Ref: POSIX Floating Point Problems-Footnote-1818152 -Node: Integer Programming818190 -Node: Floating-point Programming819943 -Ref: Floating-point Programming-Footnote-1826252 -Node: Floating-point Representation826516 -Node: Floating-point Context827681 -Ref: table-ieee-formats828523 -Node: Rounding Mode829907 -Ref: table-rounding-modes830386 -Ref: Rounding Mode-Footnote-1833390 -Node: Gawk and MPFR833571 -Node: Arbitrary Precision Floats834813 -Ref: Arbitrary Precision Floats-Footnote-1837242 -Node: Setting Precision837553 -Node: Setting Rounding Mode840286 -Ref: table-gawk-rounding-modes840690 -Node: Floating-point Constants841870 -Node: Changing Precision843294 -Ref: Changing Precision-Footnote-1844694 -Node: Exact Arithmetic844868 -Node: Arbitrary Precision Integers847976 -Ref: Arbitrary Precision Integers-Footnote-1850976 -Node: Dynamic Extensions851123 -Node: Plugin License852041 -Node: Sample Library852655 -Node: Internal File Description853339 -Node: Internal File Ops857052 -Ref: Internal File Ops-Footnote-1861615 -Node: Using Internal File Ops861755 -Node: Language History864131 -Node: V7/SVR3.1865653 -Node: SVR4867974 -Node: POSIX869416 -Node: BTL870424 -Node: POSIX/GNU871158 -Node: Common Extensions876693 -Node: Ranges and Locales877800 -Ref: Ranges and Locales-Footnote-1882418 -Ref: Ranges and Locales-Footnote-2882445 -Ref: Ranges and Locales-Footnote-3882705 -Node: Contributors882926 -Node: Installation887222 -Node: Gawk Distribution888116 -Node: Getting888600 -Node: Extracting889426 -Node: Distribution contents891118 -Node: Unix Installation896340 -Node: Quick Installation896957 -Node: Additional Configuration Options898919 -Node: Configuration Philosophy900396 -Node: Non-Unix Installation902738 -Node: PC Installation903196 -Node: PC Binary Installation904495 -Node: PC Compiling906343 -Node: PC Testing909287 -Node: PC Using910463 -Node: Cygwin914648 -Node: MSYS915648 -Node: VMS Installation916162 -Node: VMS Compilation916765 -Ref: VMS Compilation-Footnote-1917772 -Node: VMS Installation Details917830 -Node: VMS Running919465 -Node: VMS Old Gawk921072 -Node: Bugs921546 -Node: Other Versions925398 -Node: Notes930713 -Node: Compatibility Mode931300 -Node: Additions932083 -Node: Accessing The Source933010 -Node: Adding Code934436 -Node: New Ports940478 -Node: Derived Files944613 -Ref: Derived Files-Footnote-1949918 -Ref: Derived Files-Footnote-2949952 -Ref: Derived Files-Footnote-3950552 -Node: Future Extensions950650 -Node: Basic Concepts952137 -Node: Basic High Level952818 -Ref: Basic High Level-Footnote-1956853 -Node: Basic Data Typing957038 -Node: Glossary960393 -Node: Copying985568 -Node: GNU Free Documentation License1023125 -Node: Index1048262 +Ref: Auto-set-Footnote-1415742 +Ref: Auto-set-Footnote-2415947 +Node: ARGC and ARGV416003 +Node: Arrays419854 +Node: Array Basics421359 +Node: Array Intro422185 +Node: Reference to Elements426503 +Node: Assigning Elements428773 +Node: Array Example429264 +Node: Scanning an Array430996 +Node: Controlling Scanning433310 +Ref: Controlling Scanning-Footnote-1438243 +Node: Delete438559 +Ref: Delete-Footnote-1441324 +Node: Numeric Array Subscripts441381 +Node: Uninitialized Subscripts443564 +Node: Multi-dimensional445192 +Node: Multi-scanning448286 +Node: Arrays of Arrays449877 +Node: Functions454522 +Node: Built-in455344 +Node: Calling Built-in456422 +Node: Numeric Functions458410 +Ref: Numeric Functions-Footnote-1462242 +Ref: Numeric Functions-Footnote-2462599 +Ref: Numeric Functions-Footnote-3462647 +Node: String Functions462916 +Ref: String Functions-Footnote-1486413 +Ref: String Functions-Footnote-2486542 +Ref: String Functions-Footnote-3486790 +Node: Gory Details486877 +Ref: table-sub-escapes488556 +Ref: table-sub-posix-92489910 +Ref: table-sub-proposed491253 +Ref: table-posix-sub492603 +Ref: table-gensub-escapes494149 +Ref: Gory Details-Footnote-1495356 +Ref: Gory Details-Footnote-2495407 +Node: I/O Functions495558 +Ref: I/O Functions-Footnote-1502213 +Node: Time Functions502360 +Ref: Time Functions-Footnote-1513252 +Ref: Time Functions-Footnote-2513320 +Ref: Time Functions-Footnote-3513478 +Ref: Time Functions-Footnote-4513589 +Ref: Time Functions-Footnote-5513701 +Ref: Time Functions-Footnote-6513928 +Node: Bitwise Functions514194 +Ref: table-bitwise-ops514752 +Ref: Bitwise Functions-Footnote-1518973 +Node: Type Functions519157 +Node: I18N Functions519627 +Node: User-defined521254 +Node: Definition Syntax522058 +Ref: Definition Syntax-Footnote-1526968 +Node: Function Example527037 +Node: Function Caveats529631 +Node: Calling A Function530052 +Node: Variable Scope531167 +Node: Pass By Value/Reference533142 +Node: Return Statement536582 +Node: Dynamic Typing539563 +Node: Indirect Calls540298 +Node: Internationalization549983 +Node: I18N and L10N551409 +Node: Explaining gettext552095 +Ref: Explaining gettext-Footnote-1557161 +Ref: Explaining gettext-Footnote-2557345 +Node: Programmer i18n557510 +Node: Translator i18n561710 +Node: String Extraction562503 +Ref: String Extraction-Footnote-1563464 +Node: Printf Ordering563550 +Ref: Printf Ordering-Footnote-1566334 +Node: I18N Portability566398 +Ref: I18N Portability-Footnote-1568847 +Node: I18N Example568910 +Ref: I18N Example-Footnote-1571545 +Node: Gawk I18N571617 +Node: Advanced Features572234 +Node: Nondecimal Data573747 +Node: Array Sorting575330 +Node: Controlling Array Traversal576027 +Node: Array Sorting Functions584265 +Ref: Array Sorting Functions-Footnote-1587939 +Ref: Array Sorting Functions-Footnote-2588032 +Node: Two-way I/O588226 +Ref: Two-way I/O-Footnote-1593658 +Node: TCP/IP Networking593728 +Node: Profiling596572 +Node: Library Functions604026 +Ref: Library Functions-Footnote-1607033 +Node: Library Names607204 +Ref: Library Names-Footnote-1610675 +Ref: Library Names-Footnote-2610895 +Node: General Functions610981 +Node: Strtonum Function611934 +Node: Assert Function614864 +Node: Round Function618190 +Node: Cliff Random Function619733 +Node: Ordinal Functions620749 +Ref: Ordinal Functions-Footnote-1623819 +Ref: Ordinal Functions-Footnote-2624071 +Node: Join Function624280 +Ref: Join Function-Footnote-1626051 +Node: Getlocaltime Function626251 +Node: Data File Management629966 +Node: Filetrans Function630598 +Node: Rewind Function634737 +Node: File Checking636124 +Node: Empty Files637218 +Node: Ignoring Assigns639448 +Node: Getopt Function641001 +Ref: Getopt Function-Footnote-1652305 +Node: Passwd Functions652508 +Ref: Passwd Functions-Footnote-1661483 +Node: Group Functions661571 +Node: Walking Arrays669655 +Node: Sample Programs671224 +Node: Running Examples671889 +Node: Clones672617 +Node: Cut Program673841 +Node: Egrep Program683686 +Ref: Egrep Program-Footnote-1691459 +Node: Id Program691569 +Node: Split Program695185 +Ref: Split Program-Footnote-1698704 +Node: Tee Program698832 +Node: Uniq Program701635 +Node: Wc Program709064 +Ref: Wc Program-Footnote-1713330 +Ref: Wc Program-Footnote-2713530 +Node: Miscellaneous Programs713622 +Node: Dupword Program714810 +Node: Alarm Program716841 +Node: Translate Program721590 +Ref: Translate Program-Footnote-1725977 +Ref: Translate Program-Footnote-2726205 +Node: Labels Program726339 +Ref: Labels Program-Footnote-1729710 +Node: Word Sorting729794 +Node: History Sorting733678 +Node: Extract Program735517 +Ref: Extract Program-Footnote-1743000 +Node: Simple Sed743128 +Node: Igawk Program746190 +Ref: Igawk Program-Footnote-1761347 +Ref: Igawk Program-Footnote-2761548 +Node: Anagram Program761686 +Node: Signature Program764754 +Node: Debugger765854 +Node: Debugging766820 +Node: Debugging Concepts767253 +Node: Debugging Terms769109 +Node: Awk Debugging771706 +Node: Sample Debugging Session772598 +Node: Debugger Invocation773118 +Node: Finding The Bug774447 +Node: List of Debugger Commands780935 +Node: Breakpoint Control782269 +Node: Debugger Execution Control785933 +Node: Viewing And Changing Data789293 +Node: Execution Stack792649 +Node: Debugger Info794116 +Node: Miscellaneous Debugger Commands798097 +Node: Readline Support803542 +Node: Limitations804373 +Node: Arbitrary Precision Arithmetic806625 +Ref: Arbitrary Precision Arithmetic-Footnote-1808267 +Node: General Arithmetic808415 +Node: Floating Point Issues810135 +Node: String Conversion Precision811016 +Ref: String Conversion Precision-Footnote-1812722 +Node: Unexpected Results812831 +Node: POSIX Floating Point Problems814984 +Ref: POSIX Floating Point Problems-Footnote-1818809 +Node: Integer Programming818847 +Node: Floating-point Programming820600 +Ref: Floating-point Programming-Footnote-1826909 +Node: Floating-point Representation827173 +Node: Floating-point Context828338 +Ref: table-ieee-formats829180 +Node: Rounding Mode830564 +Ref: table-rounding-modes831043 +Ref: Rounding Mode-Footnote-1834047 +Node: Gawk and MPFR834228 +Node: Arbitrary Precision Floats835470 +Ref: Arbitrary Precision Floats-Footnote-1837899 +Node: Setting Precision838210 +Node: Setting Rounding Mode840943 +Ref: table-gawk-rounding-modes841347 +Node: Floating-point Constants842527 +Node: Changing Precision843951 +Ref: Changing Precision-Footnote-1845351 +Node: Exact Arithmetic845525 +Node: Arbitrary Precision Integers848633 +Ref: Arbitrary Precision Integers-Footnote-1851633 +Node: Dynamic Extensions851780 +Node: Plugin License852698 +Node: Sample Library853312 +Node: Internal File Description853996 +Node: Internal File Ops857709 +Ref: Internal File Ops-Footnote-1862272 +Node: Using Internal File Ops862412 +Node: Language History864788 +Node: V7/SVR3.1866310 +Node: SVR4868631 +Node: POSIX870073 +Node: BTL871081 +Node: POSIX/GNU871815 +Node: Common Extensions877350 +Node: Ranges and Locales878457 +Ref: Ranges and Locales-Footnote-1883075 +Ref: Ranges and Locales-Footnote-2883102 +Ref: Ranges and Locales-Footnote-3883362 +Node: Contributors883583 +Node: Installation887879 +Node: Gawk Distribution888773 +Node: Getting889257 +Node: Extracting890083 +Node: Distribution contents891775 +Node: Unix Installation896997 +Node: Quick Installation897614 +Node: Additional Configuration Options899576 +Node: Configuration Philosophy901053 +Node: Non-Unix Installation903395 +Node: PC Installation903853 +Node: PC Binary Installation905152 +Node: PC Compiling907000 +Node: PC Testing909944 +Node: PC Using911120 +Node: Cygwin915305 +Node: MSYS916305 +Node: VMS Installation916819 +Node: VMS Compilation917422 +Ref: VMS Compilation-Footnote-1918429 +Node: VMS Installation Details918487 +Node: VMS Running920122 +Node: VMS Old Gawk921729 +Node: Bugs922203 +Node: Other Versions926055 +Node: Notes931370 +Node: Compatibility Mode931957 +Node: Additions932740 +Node: Accessing The Source933667 +Node: Adding Code935093 +Node: New Ports941135 +Node: Derived Files945270 +Ref: Derived Files-Footnote-1950575 +Ref: Derived Files-Footnote-2950609 +Ref: Derived Files-Footnote-3951209 +Node: Future Extensions951307 +Node: Basic Concepts952794 +Node: Basic High Level953475 +Ref: Basic High Level-Footnote-1957510 +Node: Basic Data Typing957695 +Node: Glossary961050 +Node: Copying986225 +Node: GNU Free Documentation License1023782 +Node: Index1048919 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index f0378b30..bc41fb24 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -13201,6 +13201,31 @@ if an element in @code{SYMTAB} is an array. Also, you may not use the @code{delete} statement with the @code{SYMTAB} array. +You may use an index for @code{SYMTAB} that is not a predefined identifer: + +@example +SYMTAB["xxx"] = 5 +print SYMTAB["xxx"] +@end example + +@noindent +This works as expected: in this case @code{SYMTAB} acts just like +a regular array. The only difference is that you can't then delete +@code{SYMTAB["xxx"]}. + +The @code{SYMTAB} array is more interesting than it looks. Andrew Schorr +points out that it effectively gives @command{awk} data pointers. Consider his +example: + +@example +# Indirect multiply of any variable by amount, return result + +function multiply(variable, amount) +@{ + return SYMTAB[variable] *= amount +@} +@end example + @quotation NOTE In order to avoid severe time-travel paradoxes@footnote{Not to mention difficult implementation issues.}, neither @code{FUNCTAB} nor @code{SYMTAB} |