summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2017-04-12 11:35:08 +0300
committerArnold D. Robbins <arnold@skeeve.com>2017-04-12 11:35:08 +0300
commitc080fd4c72fffb78d4c06d97a4876a826b24fe56 (patch)
treef6a0132db9450eb454fa07d08a818deb6c0981c2
parent7151f1a0e366345adf052b9b2fb1dbf6dcb04837 (diff)
parentc9c9fe5bb2d5c6b07a67f4cf6861aeb6d9bbfcfd (diff)
downloadgawk-c080fd4c72fffb78d4c06d97a4876a826b24fe56.tar.gz
Merge branch 'master' into feature/memleak
-rw-r--r--ChangeLog148
-rw-r--r--NEWS7
-rw-r--r--awk.h6
-rw-r--r--doc/ChangeLog21
-rw-r--r--doc/awkcard.in8
-rw-r--r--doc/gawk.115
-rw-r--r--doc/gawk.info1200
-rw-r--r--doc/gawk.texi100
-rw-r--r--doc/gawktexi.in100
-rw-r--r--extension/ChangeLog38
-rw-r--r--extension/Makefile.am8
-rw-r--r--extension/Makefile.in33
-rw-r--r--extension/readdir.c8
-rw-r--r--extension/readdir_test.c343
-rw-r--r--extension/readfile.c3
-rw-r--r--extension/revtwoway.c3
-rw-r--r--field.c219
-rw-r--r--gawkapi.h38
-rw-r--r--io.c24
-rw-r--r--main.c17
-rw-r--r--test/ChangeLog18
-rw-r--r--test/Makefile.am19
-rw-r--r--test/Makefile.in23
-rw-r--r--test/Maketests2
-rw-r--r--test/fwtest3.awk7
-rw-r--r--test/fwtest3.ok13
-rw-r--r--test/fwtest4.awk1
-rw-r--r--test/fwtest4.in (renamed from test/fwtest3.in)0
-rw-r--r--test/fwtest4.ok1
29 files changed, 1728 insertions, 695 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b370518..035db955 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,10 +7,18 @@
(free_bc_mempool): Improve clarity by comparing opcode to Op_illegal
instead of to 0.
+ * field.c (set_FIELDWIDTHS): Set use_chars to awk_true, since its
+ type is awk_bool_t.
+
2017-04-10 Arnold D. Robbins <arnold@skeeve.com>
* symbol.c (free_bc_mempool): Change `first' from int to bool.
+2017-04-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * field.c (fw_parse_field): Edit comment about resetting shift state.
+ * gawkapi.h (awk_fieldwidth_info_t): Make white space more uniform.
+
2017-04-08 Eli Zaretskii <eliz@gnu.org>
* main.c (usage, copyleft) [__MINGW32__]:
@@ -51,6 +59,14 @@
2017-03-27 Arnold D. Robbins <arnold@skeeve.com>
+ * field.c (parse_field_func_t): New typedef. Used as needed.
+ (fw_parse_field): Edit comment about resetting shift state.
+ (set_parser): Fix leading comment's style and type of argument.
+ (set_FIELDWIDTHS): Improve the fatal error message.
+ * gawkapi.h: Minor edits in some comments.
+
+2017-03-27 Arnold D. Robbins <arnold@skeeve.com>
+
Cause EPIPE errors to stdout to generate a real SIGPIPE.
* awk.h (die_via_sigpipe): New macro.
@@ -77,6 +93,60 @@
* config.sub: Updated again.
+2017-03-22 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * NEWS: Document new PROCINFO["FS"] value of "API".
+
+2017-03-22 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * NEWS: Document new FIELDWIDTHS skip capability and API input parser
+ field parsing enhancement.
+
+2017-03-22 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (awk_input_buf_t): Update get_record comment regarding the
+ new field_width argument.
+
+2017-03-21 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (awk_fieldwidth_info_t): Define new structure to contain
+ API field parsing info, replacing the previous awk_input_field_info_t
+ array.
+ (awk_fieldwidth_info_size): Define macro to calculate size of the
+ variable-length awk_fieldwidth_info_t structure.
+ (awk_input_buf_t): Update get_record prototype to update the type
+ of the final field_width argument from 'const awk_input_field_info_t **'
+ to 'const awk_fieldwidth_info_t **'.
+ * awk.h (set_record): Change 3rd argument from
+ 'const awk_input_field_info_t *' to 'const awk_fieldwidth_info_t *'.
+ * io.c (inrec, do_getline_redir, do_getline): Change field_width type
+ from 'const awk_input_field_info_t *' to
+ 'const awk_fieldwidth_info_t *'.
+ (get_a_record): Change field_width argument type from
+ 'const awk_input_field_info_t **' to 'const awk_fieldwidth_info_t **'.
+ * field.c (api_parser_override): Define new boolean to track whether
+ API parsing is currently overriding default parsing behavior.
+ (api_fw): Change type from 'const awk_input_field_info_t *'
+ to 'const awk_fieldwidth_info_t *'.
+ (FIELDWIDTHS): Change type from 'int *' to 'awk_fieldwidth_info_t *'.
+ (set_record): Use new boolean api_parser_override to track whether
+ API parsing override is in effect, since we can no longer discern
+ this from the value of parse_field -- FIELDWIDTHS parsing uses the
+ same function.
+ (calc_mbslen): New function to calculate the length of a multi-byte
+ string.
+ (fw_parse_field): Enhance to support the awk_fieldwidth_info_t
+ structure instead of simply using an array of integer field widths.
+ (api_parse_field): Remove function no longer needed since fw_parse_field
+ now supports both FIELDWIDTHS and API parsing.
+ (set_parser): Use api_parser_override instead of comparing parse_field
+ to api_parse_field.
+ (set_FIELDWIDTHS): Enhance to use new awk_fieldwidth_info_t structure
+ and parse new skip prefix for each field.
+ (current_field_sep): Use api_parser_override flag instead of comparing
+ to api_parse_field.
+ (current_field_sep_str): Ditto.
+
2017-03-20 Arnold D. Robbins <arnold@skeeve.com>
Improve handling of EPIPE. Problems reported by
@@ -106,6 +176,84 @@
* configure.ac: Some cleanups.
+2017-03-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (awk_input_field_info_t): Define new structure to contain
+ API field parsing info.
+ (awk_input_buf_t): Update get_record prototype to use an array of
+ awk_input_field_info_t instead of integers.
+ * awk.h (set_record): Change 3rd argument from 'const int *' to
+ 'const awk_input_field_info_t *'.
+ * field.c (api_fw): Now points to an array of awk_input_field_info_t
+ instead of integers.
+ (set_record): Change 3rd argument to point to an array of
+ awk_input_field_info_t.
+ (api_parse_field): Update parsing logic to use awk_input_field_info_t
+ structures instead of an array of integers.
+ * io.c (inrec, do_getline_redir, do_getline): Change field_width type
+ from 'const int *' to 'const awk_input_field_info_t *'.
+ (get_a_record): Change field_width argument type from 'const int **'
+ to 'const awk_input_field_info_t **'.
+
+2017-03-09 Arnold D. Robbins <arnold@skeeve.com>
+
+ * field.c: Minor style edits.
+
+2017-03-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * field.c (normal_parse_field): Renamed from save_parse_field to reflect
+ better its purpose. Added a comment to explain more clearly what's
+ going on.
+ (set_record, set_parser): Rename save_parse_field to normal_parse_field.
+
+2017-03-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (awk_input_buf_t): Remove field_width array and instead
+ add it as a 6th argument to the get_record function. This should
+ not break existing code, since it's fine to ignore the additional
+ argument. Document the behavior of the field_width argument.
+ * io.c (inrec): Pass pointer to field_width array to get_a_record,
+ and then hand it off to set_record.
+ (do_getline_redir): If not reading into a variable, pass pointer to
+ field_width array to get_a_record and then hand it off to set_record.
+ (do_getline): Ditto.
+ (get_a_record): Add a 4th field_width argument to pass through to
+ the API get_record method.
+
+2017-03-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awk.h (set_record): Add a new argument containing a field-width
+ array returned by an API parser.
+ (field_sep_type): Add new enum value Using_API.
+ (current_field_sep_str): Declare new function.
+ * field.c (save_parse_field): New static variable to save the
+ parse_field value in cases where it's overridden by API parsing.
+ (api_fw): New static variable to hold pointer to API parser fieldwidth
+ array.
+ (set_record): Add new field-width array argument. If present, API
+ parsing will override the default parsing mechanism.
+ (api_parse_field): New field parser using field widths supplied by the
+ API. This is very similar to the existing fw_parse_field function.
+ (get_field): Fix typo in comment.
+ (set_parser): New function to set default parser and check whether
+ there's an API parser override in effect. Update PROCINFO["FS"] if
+ something has changed.
+ (set_FIELDWIDTHS): Use set_parser and stop updating PROCINFO["FS"].
+ (set_FS): Ditto.
+ (set_FPAT): Ditto.
+ (current_field_sep): Return Using_API when using the API field parsing
+ widths.
+ (current_field_sep_str): New function to return the proper string
+ value for PROCINFO["FS"].
+ * gawkapi.h (awk_input_buf_t): Add field_width array to enable the
+ parser get_record function to supply field widths to override the
+ default gawk field parsing mechanism.
+ * io.c (inrec): Pass iop->public.field_width to set_record as the
+ 3rd argument to enable API field parsing overrides.
+ (do_getline_redir, do_getline): Ditto.
+ * main.c (load_procinfo): Use new current_field_sep_str function
+ instead of switching on the return value from current_field_sep.
+
2017-02-23 Arnold D. Robbins <arnold@skeeve.com>
* awk.h (boolval): Return bool instead of int.
diff --git a/NEWS b/NEWS
index 3ddc96e9..2503f5f8 100644
--- a/NEWS
+++ b/NEWS
@@ -104,6 +104,13 @@ Changes from 4.1.x to 4.2.0
argument is present and is non-zero or non-null, the time will be converted
from UTC instead of from the local timezone.
+26. The FIELDWIDTHS parsing syntax has been enhanced to allow specifying
+ how many characters to skip before a field starts.
+
+27. An API input parser now has the ability to override the default field
+ parsing mechanism by specifying the locations of each field in the input
+ record. When this is in effect, PROCINFO["FS"] will be set to "API".
+
Changes from 4.1.3 to 4.1.4
---------------------------
diff --git a/awk.h b/awk.h
index 3a9f826f..2f82ba0f 100644
--- a/awk.h
+++ b/awk.h
@@ -1520,7 +1520,7 @@ extern NODE *get_actual_argument(NODE *, int, bool);
#endif
/* field.c */
extern void init_fields(void);
-extern void set_record(const char *buf, int cnt);
+extern void set_record(const char *buf, int cnt, const awk_fieldwidth_info_t *);
extern void reset_record(void);
extern void rebuild_record(void);
extern void set_NF(void);
@@ -1537,9 +1537,11 @@ extern void update_PROCINFO_num(const char *subscript, AWKNUM val);
typedef enum {
Using_FS,
Using_FIELDWIDTHS,
- Using_FPAT
+ Using_FPAT,
+ Using_API
} field_sep_type;
extern field_sep_type current_field_sep(void);
+extern const char *current_field_sep_str(void);
/* gawkapi.c: */
extern gawk_api_t api_impl;
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 0a04a64b..82ae2ce3 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,14 @@
+2017-04-11 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Minor style edits.
+
+2017-04-10 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawktexi.in: Document FIELDWIDTHS enhancement to support an optional
+ field skip prefix. Document new PROCINFO["FS"] value "API".
+ Document new get_record field_width argument that enables the API
+ parser to override the default field parsing mechanism.
+
2017-04-07 Arnold D. Robbins <arnold@skeeve.com>
* using-git.texi: Removed.
@@ -9,6 +20,16 @@
* wordlist2: Updated.
* Makefile.am: Fix spell checking. :-(
+2017-03-22 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawk.1: Document new PROCINFO["FS"] value "API".
+
+2017-03-22 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awkcard.in: Document FIELDWIDTHS enhancement to support an optional
+ field skip prefix.
+ * gawk.1: Ditto.
+
2017-03-17 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Improve the discussion of quoting on
diff --git a/doc/awkcard.in b/doc/awkcard.in
index 418cc8d9..86aeee2e 100644
--- a/doc/awkcard.in
+++ b/doc/awkcard.in
@@ -556,8 +556,10 @@ fails, or if
\*(FCclose()\*(FR fails.
T}
\*(FCFIELDWIDTHS\fP T{
-Whitespace separated list of field widths. Used
-to parse the input into fields of fixed width,
+Whitespace-separated list of field widths.
+Each field width may optionally be preceded by a colon-separated
+value specifying the number of characters to skip before the field starts.
+Used to parse the input into fields of fixed width,
instead of the value of \*(FCFS\fP.\*(CD
T}
\*(FCFILENAME\fP T{
@@ -1017,6 +1019,8 @@ also affects how fields are split when
variable is set to a space-separated list of numbers, each field is
expected to have a fixed width, and \*(GK
splits up the record using the specified widths.
+Each field width may optionally be preceded by a colon-separated
+value specifying the number of characters to skip before the field starts.
The value of \*(FCFS\fP is ignored.
Assigning a new value to \*(FCFS\fP or \*(FCFPAT\fP
overrides the use of \*(FCFIELDWIDTHS\*(FR.
diff --git a/doc/gawk.1 b/doc/gawk.1
index 2460a686..a4f691d6 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -805,10 +805,13 @@ is a regular expression.
.PP
If the
.B FIELDWIDTHS
-variable is set to a space separated list of numbers, each field is
+variable is set to a space-separated list of numbers, each field is
expected to have fixed width, and
.I gawk
-splits up the record using the specified widths. The value of
+splits up the record using the specified widths.
+Each field width may optionally be preceded by a colon-separated
+value specifying the number of characters to skip before the field starts.
+The value of
.B FS
is ignored.
Assigning a new value to
@@ -959,12 +962,14 @@ For non-system errors,
will be zero.
.TP
.B FIELDWIDTHS
-A whitespace separated list of field widths. When set,
+A whitespace-separated list of field widths. When set,
.I gawk
parses the input into fields of fixed width, instead of using the
value of the
.B FS
variable as the field separator.
+Each field width may optionally be preceded by a colon-separated
+value specifying the number of characters to skip before the field starts.
See
.BR Fields ,
above.
@@ -1133,8 +1138,10 @@ is in effect,
\fB"FPAT"\fP if field splitting with
.B FPAT
is in effect,
-or \fB"FIELDWIDTHS"\fP if field splitting with
+\fB"FIELDWIDTHS"\fP if field splitting with
.B FIELDWIDTHS
+is in effect,
+or \fB"API"\fP if API input parser field splitting
is in effect.
.TP
\fBPROCINFO["gid"]\fP
diff --git a/doc/gawk.info b/doc/gawk.info
index 197dc2f7..42c3c197 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -5127,9 +5127,12 @@ by assigning a string containing space-separated numbers to the built-in
variable 'FIELDWIDTHS'. Each number specifies the width of the field,
_including_ columns between fields. If you want to ignore the columns
between fields, you can specify the width as a separate field that is
-subsequently ignored. It is a fatal error to supply a field width that
-has a negative value. The following data is the output of the Unix 'w'
-utility. It is useful to illustrate the use of 'FIELDWIDTHS':
+subsequently ignored. Or, starting in version 4.2, each field width may
+optionally be preceded by a colon-separated value specifying the number
+of characters to skip before the field starts. It is a fatal error to
+supply a field width that has a negative value. The following data is
+the output of the Unix 'w' utility. It is useful to illustrate the use
+of 'FIELDWIDTHS':
10:06pm up 21 days, 14:04, 23 users
User tty login idle JCPU PCPU what
@@ -5176,6 +5179,20 @@ calculated idle time:
brent ttyp0 286
dave ttyq4 1296000
+ Starting in version 4.2, this program could be rewritten to specify
+'FIELDWIDTHS' like so:
+ BEGIN { FIELDWIDTHS = "8 1:5 4:7 6 1:6 1:6 2:33" }
+ This strips away some of the white space separating the fields. With
+such a change, the program would produce the following results:
+
+ hzang ttyV3 50
+ eklye ttyV5 0
+ dportein ttyV6 107
+ gierd ttyD3 1
+ dave ttyD4 0
+ brent ttyp0 286
+ dave ttyq4 1296000
+
Another (possibly more practical) example of fixed-width input data
is the input from a deck of balloting cards. In some parts of the
United States, voters mark their choices by punching holes in computer
@@ -5197,8 +5214,10 @@ value is '"FS"' if regular field splitting is being used, or
REGULAR FIELD SPLITTING ...
else if (PROCINFO["FS"] == "FIELDWIDTHS")
FIXED-WIDTH FIELD SPLITTING ...
- else
+ else if (PROCINFO["FS"] == "FPAT")
CONTENT-BASED FIELD SPLITTING ... (see next minor node)
+ else
+ API INPUT PARSER FIELD SPLITTING ... (advanced feature)
This information is useful when writing a function that needs to
temporarily change 'FS' or 'FIELDWIDTHS', read some records, and then
@@ -5304,7 +5323,10 @@ available for splitting regular strings (*note String Functions::).
To recap, 'gawk' provides three independent methods to split input
records into fields. The mechanism used is based on which of the three
-variables--'FS', 'FIELDWIDTHS', or 'FPAT'--was last assigned to.
+variables--'FS', 'FIELDWIDTHS', or 'FPAT'--was last assigned to. In
+addition, an API input parser may choose to override the record parsing
+mechanism; please refer to *note Input Parsers:: for further information
+about this feature.
---------- Footnotes ----------
@@ -10441,9 +10463,12 @@ each variable.)
'FIELDWIDTHS #'
A space-separated list of columns that tells 'gawk' how to split
- input with fixed columnar boundaries. Assigning a value to
- 'FIELDWIDTHS' overrides the use of 'FS' and 'FPAT' for field
- splitting. *Note Constant Size:: for more information.
+ input with fixed columnar boundaries. Starting in version 4.2,
+ each field width may optionally be preceded by a colon-separated
+ value specifying the number of characters to skip before the field
+ starts. Assigning a value to 'FIELDWIDTHS' overrides the use of
+ 'FS' and 'FPAT' for field splitting. *Note Constant Size:: for
+ more information.
'FPAT #'
A regular expression (as a string) that tells 'gawk' to create the
@@ -10727,8 +10752,9 @@ they are not special:
'PROCINFO["FS"]'
This is '"FS"' if field splitting with 'FS' is in effect,
'"FIELDWIDTHS"' if field splitting with 'FIELDWIDTHS' is in
- effect, or '"FPAT"' if field matching with 'FPAT' is in
- effect.
+ effect, '"FPAT"' if field matching with 'FPAT' is in effect,
+ or '"API"' if field splitting is controlled by an API input
+ parser.
'PROCINFO["gid"]'
The value of the 'getgid()' system call.
@@ -24167,7 +24193,8 @@ for 'RT', if any.
#define INVALID_HANDLE (-1)
void *opaque; /* private data for input parsers */
int (*get_record)(char **out, struct awk_input *iobuf,
- int *errcode, char **rt_start, size_t *rt_len);
+ int *errcode, char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **field_width);
ssize_t (*read_func)();
void (*close_func)(struct awk_input *iobuf);
struct stat sbuf; /* stat buf */
@@ -24213,7 +24240,8 @@ may be filled by 'XXX_take_control_of()':
' struct awk_input *iobuf,'
' int *errcode,'
' char **rt_start,'
-' size_t *rt_len);'
+' size_t *rt_len,'
+' const awk_fieldwidth_info_t **field_width);'
This function pointer should point to a function that creates the
input records. Said function is the core of the input parser. Its
behavior is described in the text following this list.
@@ -24263,6 +24291,20 @@ records. The parameters are as follows:
'*rt_len' should be set to zero. 'gawk' makes its own copy of this
data, so the extension must manage this storage.
+'const awk_fieldwidth_info_t **field_width'
+ If 'field_width' is not 'NULL', then '*field_width' will be
+ initialized to 'NULL', and the function may set it to point to a
+ structure supplying field width information to override the default
+ field parsing mechanism. Note that this structure will not be
+ copied by 'gawk'; it must persist at least until the next call to
+ 'get_record' or 'close_func'. Note also that 'field_width' is
+ 'NULL' when 'getline' is assigning the results to a variable, thus
+ field parsing is not needed. If the parser does set
+ '*field_width', then 'gawk' uses this layout to parse the input
+ record, and the 'PROCINFO["FS"]' value will be '"API"' while this
+ record is active in '$0'. The 'awk_fieldwidth_info_t' data
+ structure is described below.
+
The return value is the length of the buffer pointed to by '*out', or
'EOF' if end-of-file was reached or an error occurred.
@@ -24312,6 +24354,46 @@ activate an input parser (*note BEGINFILE/ENDFILE::).
'void register_input_parser(awk_input_parser_t *input_parser);'
Register the input parser pointed to by 'input_parser' with 'gawk'.
+ If you would like to override the default field parsing mechanism for
+a given record, then you must populate an 'awk_fieldwidth_info_t'
+structure, which looks like this:
+
+ typedef struct {
+ awk_bool_t use_chars; /* false ==> use bytes */
+ size_t nf; /* number of fields in record (NF) */
+ struct awk_field_info {
+ size_t skip; /* amount to skip before field starts */
+ size_t len; /* length of field */
+ } fields[1]; /* actual dimension should be nf */
+ } awk_fieldwidth_info_t;
+
+ The fields are:
+
+'awk_bool_t use_chars;'
+ Set this to 'awk_true' if the field lengths are specified in terms
+ of potentially multi-byte characters, and set it to 'awk_false' if
+ the lengths are in terms of bytes. Performance will be better if
+ the values are supplied in terms of bytes.
+
+'size_t nf;'
+ Set this to the number of fields in the input record, i.e. 'NF'.
+
+'struct awk_field_info fields[nf];'
+ This is a variable-length array whose actual dimension should be
+ 'nf'. For each field, the 'skip' element should be set to the
+ number of characters or bytes, as controlled by the 'use_chars'
+ flag, to skip before the start of this field. The 'len' element
+ provides the length of the field. The values in 'fields[0]'
+ provide the information for '$1', and so on through the
+ 'fields[nf-1]' element containing the information for '$NF'.
+
+ A convenience macro 'awk_fieldwidth_info_size(NF)' is provided to
+calculate the appropriate size of a variable-length
+'awk_fieldwidth_info_t' structure containing 'NF' fields. This can be
+used as an argument to 'malloc()' or in a union to allocate space
+statically. Please refer to the 'readdir_test' sample extension for an
+example.
+

File: gawk.info, Node: Output Wrappers, Next: Two-way processors, Prev: Input Parsers, Up: Registration Functions
@@ -33052,8 +33134,8 @@ Index
* caret (^), ^= operator: Assignment Ops. (line 129)
* caret (^), ^= operator <1>: Precedence. (line 94)
* case keyword: Switch Statement. (line 6)
-* case sensitivity, and regexps: User-modified. (line 76)
-* case sensitivity, and string comparisons: User-modified. (line 76)
+* case sensitivity, and regexps: User-modified. (line 79)
+* case sensitivity, and string comparisons: User-modified. (line 79)
* case sensitivity, array indices and: Array Intro. (line 100)
* case sensitivity, converting case: String Functions. (line 523)
* case sensitivity, example programs: Library Functions. (line 53)
@@ -33242,7 +33324,7 @@ Index
* dark corner, field separators: Full Line Fields. (line 22)
* dark corner, FILENAME variable: Getline Notes. (line 19)
* dark corner, FILENAME variable <1>: Auto-set. (line 108)
-* dark corner, FNR/NR variables: Auto-set. (line 357)
+* dark corner, FNR/NR variables: Auto-set. (line 358)
* dark corner, format-control characters: Control Letters. (line 18)
* dark corner, format-control characters <1>: Control Letters.
(line 93)
@@ -33441,13 +33523,13 @@ Index
* differences in awk and gawk, error messages: Special FD. (line 19)
* differences in awk and gawk, FIELDWIDTHS variable: User-modified.
(line 37)
-* differences in awk and gawk, FPAT variable: User-modified. (line 43)
+* differences in awk and gawk, FPAT variable: User-modified. (line 46)
* differences in awk and gawk, FUNCTAB variable: Auto-set. (line 134)
* differences in awk and gawk, function arguments (gawk): Calling Built-in.
(line 16)
* differences in awk and gawk, getline command: Getline. (line 19)
* differences in awk and gawk, IGNORECASE variable: User-modified.
- (line 76)
+ (line 79)
* differences in awk and gawk, implementation limitations: Getline Notes.
(line 14)
* differences in awk and gawk, implementation limitations <1>: Redirection.
@@ -33460,7 +33542,7 @@ Index
(line 96)
* differences in awk and gawk, line continuations: Conditional Exp.
(line 34)
-* differences in awk and gawk, LINT variable: User-modified. (line 87)
+* differences in awk and gawk, LINT variable: User-modified. (line 90)
* differences in awk and gawk, match() function: String Functions.
(line 262)
* differences in awk and gawk, print/printf statements: Format Modifiers.
@@ -33477,7 +33559,7 @@ Index
(line 6)
* differences in awk and gawk, RS/RT variables: gawk split records.
(line 58)
-* differences in awk and gawk, RT variable: Auto-set. (line 295)
+* differences in awk and gawk, RT variable: Auto-set. (line 296)
* differences in awk and gawk, single-character fields: Single Character Fields.
(line 6)
* differences in awk and gawk, split() function: String Functions.
@@ -33485,9 +33567,9 @@ Index
* differences in awk and gawk, strings: Scalar Constants. (line 20)
* differences in awk and gawk, strings, storing: gawk split records.
(line 76)
-* differences in awk and gawk, SYMTAB variable: Auto-set. (line 299)
+* differences in awk and gawk, SYMTAB variable: Auto-set. (line 300)
* differences in awk and gawk, TEXTDOMAIN variable: User-modified.
- (line 152)
+ (line 155)
* differences in awk and gawk, trunc-mod operation: Arithmetic Ops.
(line 66)
* directories, command-line: Command-line directories.
@@ -33648,7 +33730,7 @@ Index
(line 6)
* extension API version: Extension Versioning.
(line 6)
-* extension API, version number: Auto-set. (line 246)
+* extension API, version number: Auto-set. (line 247)
* extension example: Extension Example. (line 6)
* extension registration: Registration Functions.
(line 6)
@@ -33699,11 +33781,11 @@ Index
(line 6)
* field separator, POSIX and: Full Line Fields. (line 16)
* field separators: Field Separators. (line 15)
-* field separators <1>: User-modified. (line 50)
-* field separators <2>: User-modified. (line 113)
+* field separators <1>: User-modified. (line 53)
+* field separators <2>: User-modified. (line 116)
* field separators, choice of: Field Separators. (line 50)
* field separators, FIELDWIDTHS variable and: User-modified. (line 37)
-* field separators, FPAT variable and: User-modified. (line 43)
+* field separators, FPAT variable and: User-modified. (line 46)
* field separators, regular expressions as: Field Separators. (line 50)
* field separators, regular expressions as <1>: Regexp Field Splitting.
(line 6)
@@ -33800,7 +33882,7 @@ Index
(line 12)
* FNR variable: Records. (line 6)
* FNR variable <1>: Auto-set. (line 118)
-* FNR variable, changing: Auto-set. (line 357)
+* FNR variable, changing: Auto-set. (line 358)
* for statement: For Statement. (line 6)
* for statement, looping over arrays: Scanning an Array. (line 20)
* fork() extension function: Extension Sample Fork.
@@ -33824,7 +33906,7 @@ Index
* forward slash (/), patterns and: Expression Patterns. (line 24)
* FPAT variable: Splitting By Content.
(line 25)
-* FPAT variable <1>: User-modified. (line 43)
+* FPAT variable <1>: User-modified. (line 46)
* frame debugger command: Execution Stack. (line 27)
* Free Documentation License (FDL): GNU Free Documentation License.
(line 8)
@@ -33834,7 +33916,7 @@ Index
* Free Software Foundation (FSF) <3>: Glossary. (line 405)
* FreeBSD: Glossary. (line 748)
* FS variable: Field Separators. (line 15)
-* FS variable <1>: User-modified. (line 50)
+* FS variable <1>: User-modified. (line 53)
* FS variable, --field-separator option and: Options. (line 21)
* FS variable, as null string: Single Character Fields.
(line 20)
@@ -33904,7 +33986,7 @@ Index
* G., Daniel Richard <1>: Maintainers. (line 14)
* Garfinkle, Scott: Contributors. (line 35)
* gawk program, dynamic profiling: Profiling. (line 177)
-* gawk version: Auto-set. (line 221)
+* gawk version: Auto-set. (line 222)
* gawk, ARGIND variable in: Other Arguments. (line 15)
* gawk, awk and: Preface. (line 21)
* gawk, awk and <1>: This Manual. (line 14)
@@ -33931,7 +34013,7 @@ Index
* gawk, extensions, disabling: Options. (line 257)
* gawk, features, adding: Adding Code. (line 6)
* gawk, features, advanced: Advanced Features. (line 6)
-* gawk, field separators and: User-modified. (line 71)
+* gawk, field separators and: User-modified. (line 74)
* gawk, FIELDWIDTHS variable in: Constant Size. (line 22)
* gawk, FIELDWIDTHS variable in <1>: User-modified. (line 37)
* gawk, file names in: Special Files. (line 6)
@@ -33939,12 +34021,12 @@ Index
* gawk, format-control characters <1>: Control Letters. (line 93)
* gawk, FPAT variable in: Splitting By Content.
(line 25)
-* gawk, FPAT variable in <1>: User-modified. (line 43)
+* gawk, FPAT variable in <1>: User-modified. (line 46)
* gawk, FUNCTAB array in: Auto-set. (line 134)
* gawk, function arguments and: Calling Built-in. (line 16)
* gawk, hexadecimal numbers and: Nondecimal-numbers. (line 41)
* gawk, IGNORECASE variable in: Case-sensitivity. (line 26)
-* gawk, IGNORECASE variable in <1>: User-modified. (line 76)
+* gawk, IGNORECASE variable in <1>: User-modified. (line 79)
* gawk, IGNORECASE variable in <2>: Array Intro. (line 100)
* gawk, IGNORECASE variable in <3>: String Functions. (line 58)
* gawk, IGNORECASE variable in <4>: Array Sorting Functions.
@@ -33962,7 +34044,7 @@ Index
(line 6)
* gawk, interval expressions and: Regexp Operators. (line 139)
* gawk, line continuation in: Conditional Exp. (line 34)
-* gawk, LINT variable in: User-modified. (line 87)
+* gawk, LINT variable in: User-modified. (line 90)
* gawk, list of contributors to: Contributors. (line 6)
* gawk, MS-Windows version of: PC Using. (line 9)
* gawk, newlines in: Statements/Lines. (line 12)
@@ -33980,13 +34062,13 @@ Index
* gawk, regular expressions, precedence: Regexp Operators. (line 161)
* gawk, RT variable in: awk split records. (line 124)
* gawk, RT variable in <1>: Multiple Line. (line 130)
-* gawk, RT variable in <2>: Auto-set. (line 295)
+* gawk, RT variable in <2>: Auto-set. (line 296)
* gawk, See Also awk: Preface. (line 34)
* gawk, source code, obtaining: Getting. (line 6)
-* gawk, splitting fields and: Constant Size. (line 86)
+* gawk, splitting fields and: Constant Size. (line 103)
* gawk, string-translation functions: I18N Functions. (line 6)
-* gawk, SYMTAB array in: Auto-set. (line 299)
-* gawk, TEXTDOMAIN variable in: User-modified. (line 152)
+* gawk, SYMTAB array in: Auto-set. (line 300)
+* gawk, TEXTDOMAIN variable in: User-modified. (line 155)
* gawk, timestamps: Time Functions. (line 6)
* gawk, uses for: Preface. (line 34)
* gawk, versions of, information about, printing: Options. (line 304)
@@ -34082,7 +34164,7 @@ Index
* Grigera, Juan: Contributors. (line 58)
* group database, reading: Group Functions. (line 6)
* group file: Group Functions. (line 6)
-* group ID of gawk user: Auto-set. (line 170)
+* group ID of gawk user: Auto-set. (line 171)
* groups, information about: Group Functions. (line 6)
* gsub: Standard Regexp Constants.
(line 43)
@@ -34122,7 +34204,7 @@ Index
* igawk.sh program: Igawk Program. (line 124)
* ignore breakpoint: Breakpoint Control. (line 87)
* ignore debugger command: Breakpoint Control. (line 87)
-* IGNORECASE variable: User-modified. (line 76)
+* IGNORECASE variable: User-modified. (line 79)
* IGNORECASE variable, and array indices: Array Intro. (line 100)
* IGNORECASE variable, and array sorting functions: Array Sorting Functions.
(line 83)
@@ -34197,7 +34279,7 @@ Index
* interacting with other programs: I/O Functions. (line 107)
* internationalization: I18N Functions. (line 6)
* internationalization <1>: I18N and L10N. (line 6)
-* internationalization, localization: User-modified. (line 152)
+* internationalization, localization: User-modified. (line 155)
* internationalization, localization <1>: Internationalization.
(line 13)
* internationalization, localization, character classes: Bracket Expressions.
@@ -34310,7 +34392,7 @@ Index
* lines, duplicate, removing: History Sorting. (line 6)
* lines, matching ranges of: Ranges. (line 6)
* lines, skipping between markers: Ranges. (line 43)
-* lint checking: User-modified. (line 87)
+* lint checking: User-modified. (line 90)
* lint checking, array elements: Delete. (line 34)
* lint checking, array subscripts: Uninitialized Subscripts.
(line 43)
@@ -34320,7 +34402,7 @@ Index
(line 343)
* lint checking, undefined functions: Pass By Value/Reference.
(line 85)
-* LINT variable: User-modified. (line 87)
+* LINT variable: User-modified. (line 90)
* Linux: Manual History. (line 28)
* Linux <1>: I18N Example. (line 57)
* Linux <2>: Glossary. (line 748)
@@ -34382,7 +34464,7 @@ Index
* mawk utility <2>: Concatenation. (line 36)
* mawk utility <3>: Nextfile Statement. (line 47)
* mawk utility <4>: Other Versions. (line 48)
-* maximum precision supported by MPFR library: Auto-set. (line 235)
+* maximum precision supported by MPFR library: Auto-set. (line 236)
* McIlroy, Doug: Glossary. (line 257)
* McPhee, Patrick: Contributors. (line 101)
* message object files: Explaining gettext. (line 42)
@@ -34395,7 +34477,7 @@ Index
* messages from extensions: Printing Messages. (line 6)
* metacharacters in regular expressions: Regexp Operators. (line 6)
* metacharacters, escape sequences for: Escape Sequences. (line 140)
-* minimum precision required by MPFR library: Auto-set. (line 238)
+* minimum precision required by MPFR library: Auto-set. (line 239)
* mktime: Time Functions. (line 25)
* modifiers, in format specifiers: Format Modifiers. (line 6)
* monetary information, localization: Explaining gettext. (line 104)
@@ -34453,7 +34535,7 @@ Index
* not Boolean-logic operator: Boolean Ops. (line 6)
* NR variable: Records. (line 6)
* NR variable <1>: Auto-set. (line 143)
-* NR variable, changing: Auto-set. (line 357)
+* NR variable, changing: Auto-set. (line 358)
* null strings: awk split records. (line 114)
* null strings <1>: Regexp Field Splitting.
(line 43)
@@ -34479,7 +34561,7 @@ Index
* numbers, converting: Strings And Numbers. (line 6)
* numbers, converting <1>: Bitwise Functions. (line 108)
* numbers, converting, to strings: User-modified. (line 30)
-* numbers, converting, to strings <1>: User-modified. (line 104)
+* numbers, converting, to strings <1>: User-modified. (line 107)
* numbers, hexadecimal: Nondecimal-numbers. (line 6)
* numbers, octal: Nondecimal-numbers. (line 6)
* numbers, rounding: Round Function. (line 6)
@@ -34493,11 +34575,11 @@ Index
* octal values, enabling interpretation of: Options. (line 209)
* OFMT variable: OFMT. (line 15)
* OFMT variable <1>: Strings And Numbers. (line 56)
-* OFMT variable <2>: User-modified. (line 104)
+* OFMT variable <2>: User-modified. (line 107)
* OFMT variable, POSIX awk and: OFMT. (line 27)
* OFS variable: Changing Fields. (line 64)
* OFS variable <1>: Output Separators. (line 6)
-* OFS variable <2>: User-modified. (line 113)
+* OFS variable <2>: User-modified. (line 116)
* OpenBSD: Glossary. (line 748)
* OpenSolaris: Other Versions. (line 100)
* operating systems, BSD-based: Manual History. (line 28)
@@ -34553,7 +34635,7 @@ Index
* ord() user-defined function: Ordinal Functions. (line 16)
* order of evaluation, concatenation: Concatenation. (line 41)
* ORS variable: Output Separators. (line 20)
-* ORS variable <1>: User-modified. (line 119)
+* ORS variable <1>: User-modified. (line 122)
* output field separator, See OFS variable: Changing Fields. (line 64)
* output record separator, See ORS variable: Output Separators.
(line 20)
@@ -34573,7 +34655,7 @@ Index
* p debugger command (alias for print): Viewing And Changing Data.
(line 35)
* Papadopoulos, Panos: Contributors. (line 129)
-* parent process ID of gawk process: Auto-set. (line 210)
+* parent process ID of gawk process: Auto-set. (line 211)
* parentheses (), in a profile: Profiling. (line 146)
* parentheses (), regexp operator: Regexp Operators. (line 81)
* password file: Passwd Functions. (line 16)
@@ -34696,7 +34778,7 @@ Index
* POSIX, gawk extensions not included in: POSIX/GNU. (line 6)
* POSIX, programs, implementing in awk: Clones. (line 6)
* POSIXLY_CORRECT environment variable: Options. (line 343)
-* PREC variable: User-modified. (line 124)
+* PREC variable: User-modified. (line 127)
* precedence: Increment Ops. (line 60)
* precedence <1>: Precedence. (line 6)
* precedence, regexp operators: Regexp Operators. (line 156)
@@ -34711,7 +34793,7 @@ Index
* print statement, commas, omitting: Print Examples. (line 30)
* print statement, I/O operators in: Precedence. (line 70)
* print statement, line continuations and: Print Examples. (line 75)
-* print statement, OFMT variable and: User-modified. (line 113)
+* print statement, OFMT variable and: User-modified. (line 116)
* print statement, See Also redirection, of output: Redirection.
(line 17)
* print statement, sprintf() function and: Round Function. (line 6)
@@ -34742,8 +34824,8 @@ Index
* printing, unduplicated lines of text: Uniq Program. (line 6)
* printing, user information: Id Program. (line 6)
* private variables: Library Names. (line 11)
-* process group ID of gawk process: Auto-set. (line 204)
-* process ID of gawk process: Auto-set. (line 207)
+* process group ID of gawk process: Auto-set. (line 205)
+* process ID of gawk process: Auto-set. (line 208)
* processes, two-way communications with: Two-way I/O. (line 6)
* processing data: Basic High Level. (line 6)
* PROCINFO array: Auto-set. (line 148)
@@ -34758,7 +34840,7 @@ Index
(line 26)
* profiling awk programs: Profiling. (line 6)
* profiling awk programs, dynamically: Profiling. (line 177)
-* program identifiers: Auto-set. (line 173)
+* program identifiers: Auto-set. (line 174)
* program, definition of: Getting Started. (line 21)
* programming conventions, --non-decimal-data option: Nondecimal Data.
(line 35)
@@ -34827,7 +34909,7 @@ Index
* reading input files: Reading Files. (line 6)
* recipe for a programming language: History. (line 6)
* record separators: awk split records. (line 6)
-* record separators <1>: User-modified. (line 133)
+* record separators <1>: User-modified. (line 136)
* record separators, changing: awk split records. (line 85)
* record separators, regular expressions as: awk split records.
(line 124)
@@ -34869,7 +34951,7 @@ Index
* regular expressions, as record separators: awk split records.
(line 124)
* regular expressions, case sensitivity: Case-sensitivity. (line 6)
-* regular expressions, case sensitivity <1>: User-modified. (line 76)
+* regular expressions, case sensitivity <1>: User-modified. (line 79)
* regular expressions, computed: Computed Regexps. (line 6)
* regular expressions, constants, See regexp constants: Regexp Usage.
(line 57)
@@ -34919,7 +35001,7 @@ Index
* right shift: Bitwise Functions. (line 54)
* right shift, bitwise: Bitwise Functions. (line 32)
* Ritchie, Dennis: Basic Data Typing. (line 54)
-* RLENGTH variable: Auto-set. (line 282)
+* RLENGTH variable: Auto-set. (line 283)
* RLENGTH variable, match() function and: String Functions. (line 227)
* Robbins, Arnold: Command Line Field Separator.
(line 71)
@@ -34940,16 +35022,16 @@ Index
* round to nearest integer: Numeric Functions. (line 24)
* round() user-defined function: Round Function. (line 16)
* rounding numbers: Round Function. (line 6)
-* ROUNDMODE variable: User-modified. (line 128)
+* ROUNDMODE variable: User-modified. (line 131)
* RS variable: awk split records. (line 12)
-* RS variable <1>: User-modified. (line 133)
+* RS variable <1>: User-modified. (line 136)
* RS variable, multiline records and: Multiple Line. (line 17)
* rshift: Bitwise Functions. (line 54)
-* RSTART variable: Auto-set. (line 288)
+* RSTART variable: Auto-set. (line 289)
* RSTART variable, match() function and: String Functions. (line 227)
* RT variable: awk split records. (line 124)
* RT variable <1>: Multiple Line. (line 130)
-* RT variable <2>: Auto-set. (line 295)
+* RT variable <2>: Auto-set. (line 296)
* Rubin, Paul: History. (line 30)
* Rubin, Paul <1>: Contributors. (line 16)
* rule, definition of: Getting Started. (line 21)
@@ -34967,7 +35049,7 @@ Index
* scanning arrays: Scanning an Array. (line 6)
* scanning multidimensional arrays: Multiscanning. (line 11)
* Schorr, Andrew: Acknowledgments. (line 60)
-* Schorr, Andrew <1>: Auto-set. (line 327)
+* Schorr, Andrew <1>: Auto-set. (line 328)
* Schorr, Andrew <2>: Contributors. (line 134)
* Schreiber, Bert: Acknowledgments. (line 38)
* Schreiber, Rita: Acknowledgments. (line 38)
@@ -34994,17 +35076,17 @@ Index
(line 19)
* semicolon (;), separating statements in actions <2>: Statements.
(line 10)
-* separators, field: User-modified. (line 50)
-* separators, field <1>: User-modified. (line 113)
+* separators, field: User-modified. (line 53)
+* separators, field <1>: User-modified. (line 116)
* separators, field, FIELDWIDTHS variable and: User-modified. (line 37)
-* separators, field, FPAT variable and: User-modified. (line 43)
+* separators, field, FPAT variable and: User-modified. (line 46)
* separators, for records: awk split records. (line 6)
* separators, for records <1>: awk split records. (line 85)
-* separators, for records <2>: User-modified. (line 133)
+* separators, for records <2>: User-modified. (line 136)
* separators, for records, regular expressions as: awk split records.
(line 124)
* separators, for statements in actions: Action Overview. (line 19)
-* separators, subscript: User-modified. (line 146)
+* separators, subscript: User-modified. (line 149)
* set breakpoint: Breakpoint Control. (line 11)
* set debugger command: Viewing And Changing Data.
(line 58)
@@ -35053,7 +35135,7 @@ Index
* sidebar, Beware The Smoke and Mirrors!: Bitwise Functions. (line 126)
* sidebar, Changing FS Does Not Affect the Fields: Full Line Fields.
(line 14)
-* sidebar, Changing NR and FNR: Auto-set. (line 355)
+* sidebar, Changing NR and FNR: Auto-set. (line 356)
* sidebar, Controlling Output Buffering with system(): I/O Functions.
(line 164)
* sidebar, Escape Sequences for Metacharacters: Escape Sequences.
@@ -35138,7 +35220,7 @@ Index
* split.awk program: Split Program. (line 30)
* sprintf: OFMT. (line 15)
* sprintf <1>: String Functions. (line 384)
-* sprintf() function, OFMT variable and: User-modified. (line 113)
+* sprintf() function, OFMT variable and: User-modified. (line 116)
* sprintf() function, print/printf statements and: Round Function.
(line 6)
* sqrt: Numeric Functions. (line 93)
@@ -35184,7 +35266,7 @@ Index
* strings, converting <1>: Bitwise Functions. (line 108)
* strings, converting letter case: String Functions. (line 523)
* strings, converting, numbers to: User-modified. (line 30)
-* strings, converting, numbers to <1>: User-modified. (line 104)
+* strings, converting, numbers to <1>: User-modified. (line 107)
* strings, empty, See null strings: awk split records. (line 114)
* strings, extracting: String Extraction. (line 6)
* strings, for localization: Programmer i18n. (line 13)
@@ -35201,7 +35283,7 @@ Index
* sub <1>: String Functions. (line 409)
* sub() function, arguments of: String Functions. (line 463)
* sub() function, escape processing: Gory Details. (line 6)
-* subscript separators: User-modified. (line 146)
+* subscript separators: User-modified. (line 149)
* subscripts in arrays, multidimensional: Multidimensional. (line 10)
* subscripts in arrays, multidimensional, scanning: Multiscanning.
(line 11)
@@ -35209,16 +35291,16 @@ Index
(line 6)
* subscripts in arrays, uninitialized variables as: Uninitialized Subscripts.
(line 6)
-* SUBSEP variable: User-modified. (line 146)
+* SUBSEP variable: User-modified. (line 149)
* SUBSEP variable, and multidimensional arrays: Multidimensional.
(line 16)
* substitute in string: String Functions. (line 89)
* substr: String Functions. (line 482)
* substring: String Functions. (line 482)
* Sumner, Andrew: Other Versions. (line 68)
-* supplementary groups of gawk process: Auto-set. (line 251)
+* supplementary groups of gawk process: Auto-set. (line 252)
* switch statement: Switch Statement. (line 6)
-* SYMTAB array: Auto-set. (line 299)
+* SYMTAB array: Auto-set. (line 300)
* syntactic ambiguity: /= operator vs. /=.../ regexp constant: Assignment Ops.
(line 149)
* system: I/O Functions. (line 107)
@@ -35247,7 +35329,7 @@ Index
(line 6)
* text, printing: Print. (line 22)
* text, printing, unduplicated lines of: Uniq Program. (line 6)
-* TEXTDOMAIN variable: User-modified. (line 152)
+* TEXTDOMAIN variable: User-modified. (line 155)
* TEXTDOMAIN variable <1>: Programmer i18n. (line 8)
* TEXTDOMAIN variable, BEGIN pattern and: Programmer i18n. (line 60)
* TEXTDOMAIN variable, portability and: I18N Portability. (line 20)
@@ -35400,10 +35482,10 @@ Index
* variables, uninitialized, as array subscripts: Uninitialized Subscripts.
(line 6)
* variables, user-defined: Variables. (line 6)
-* version of gawk: Auto-set. (line 221)
-* version of gawk extension API: Auto-set. (line 246)
-* version of GNU MP library: Auto-set. (line 229)
-* version of GNU MPFR library: Auto-set. (line 231)
+* version of gawk: Auto-set. (line 222)
+* version of gawk extension API: Auto-set. (line 247)
+* version of GNU MP library: Auto-set. (line 230)
+* version of GNU MPFR library: Auto-set. (line 232)
* vertical bar (|): Regexp Operators. (line 70)
* vertical bar (|), | operator (I/O): Getline/Pipe. (line 10)
* vertical bar (|), | operator (I/O) <1>: Precedence. (line 64)
@@ -35560,484 +35642,484 @@ Ref: Full Line Fields-Footnote-1228233
Ref: Full Line Fields-Footnote-2228279
Node: Field Splitting Summary228380
Node: Constant Size230454
-Node: Splitting By Content235032
-Ref: Splitting By Content-Footnote-1239003
-Node: Multiple Line239166
-Ref: Multiple Line-Footnote-1245048
-Node: Getline245227
-Node: Plain Getline247694
-Node: Getline/Variable250333
-Node: Getline/File251482
-Node: Getline/Variable/File252868
-Ref: Getline/Variable/File-Footnote-1254471
-Node: Getline/Pipe254559
-Node: Getline/Variable/Pipe257264
-Node: Getline/Coprocess258397
-Node: Getline/Variable/Coprocess259662
-Node: Getline Notes260402
-Node: Getline Summary263197
-Ref: table-getline-variants263619
-Node: Read Timeout264367
-Ref: Read Timeout-Footnote-1268273
-Node: Retrying Input268331
-Node: Command-line directories269530
-Node: Input Summary270436
-Node: Input Exercises273608
-Node: Printing274336
-Node: Print276170
-Node: Print Examples277627
-Node: Output Separators280407
-Node: OFMT282424
-Node: Printf283780
-Node: Basic Printf284565
-Node: Control Letters286139
-Node: Format Modifiers290127
-Node: Printf Examples296142
-Node: Redirection298628
-Node: Special FD305469
-Ref: Special FD-Footnote-1308637
-Node: Special Files308711
-Node: Other Inherited Files309328
-Node: Special Network310329
-Node: Special Caveats311189
-Node: Close Files And Pipes312138
-Ref: table-close-pipe-return-values319045
-Ref: Close Files And Pipes-Footnote-1319828
-Ref: Close Files And Pipes-Footnote-2319976
-Node: Nonfatal320128
-Node: Output Summary322453
-Node: Output Exercises323675
-Node: Expressions324354
-Node: Values325542
-Node: Constants326220
-Node: Scalar Constants326911
-Ref: Scalar Constants-Footnote-1327775
-Node: Nondecimal-numbers328025
-Node: Regexp Constants331026
-Node: Using Constant Regexps331552
-Node: Standard Regexp Constants332174
-Node: Strong Regexp Constants335362
-Node: Variables338320
-Node: Using Variables338977
-Node: Assignment Options340887
-Node: Conversion342760
-Node: Strings And Numbers343284
-Ref: Strings And Numbers-Footnote-1346347
-Node: Locale influences conversions346456
-Ref: table-locale-affects349214
-Node: All Operators349832
-Node: Arithmetic Ops350461
-Node: Concatenation352967
-Ref: Concatenation-Footnote-1355814
-Node: Assignment Ops355921
-Ref: table-assign-ops360912
-Node: Increment Ops362225
-Node: Truth Values and Conditions365685
-Node: Truth Values366759
-Node: Typing and Comparison367807
-Node: Variable Typing368627
-Ref: Variable Typing-Footnote-1375090
-Ref: Variable Typing-Footnote-2375162
-Node: Comparison Operators375239
-Ref: table-relational-ops375658
-Node: POSIX String Comparison379153
-Ref: POSIX String Comparison-Footnote-1380848
-Ref: POSIX String Comparison-Footnote-2380987
-Node: Boolean Ops381071
-Ref: Boolean Ops-Footnote-1385553
-Node: Conditional Exp385645
-Node: Function Calls387381
-Node: Precedence391258
-Node: Locales394917
-Node: Expressions Summary396549
-Node: Patterns and Actions399122
-Node: Pattern Overview400242
-Node: Regexp Patterns401919
-Node: Expression Patterns402461
-Node: Ranges406242
-Node: BEGIN/END409350
-Node: Using BEGIN/END410111
-Ref: Using BEGIN/END-Footnote-1412847
-Node: I/O And BEGIN/END412953
-Node: BEGINFILE/ENDFILE415267
-Node: Empty418174
-Node: Using Shell Variables418491
-Node: Action Overview420765
-Node: Statements423090
-Node: If Statement424938
-Node: While Statement426433
-Node: Do Statement428461
-Node: For Statement429609
-Node: Switch Statement432767
-Node: Break Statement435153
-Node: Continue Statement437245
-Node: Next Statement439072
-Node: Nextfile Statement441455
-Node: Exit Statement444107
-Node: Built-in Variables446510
-Node: User-modified447643
-Node: Auto-set455229
-Ref: Auto-set-Footnote-1469882
-Ref: Auto-set-Footnote-2470088
-Node: ARGC and ARGV470144
-Node: Pattern Action Summary474357
-Node: Arrays476787
-Node: Array Basics478116
-Node: Array Intro478960
-Ref: figure-array-elements480935
-Ref: Array Intro-Footnote-1483639
-Node: Reference to Elements483767
-Node: Assigning Elements486231
-Node: Array Example486722
-Node: Scanning an Array488481
-Node: Controlling Scanning491503
-Ref: Controlling Scanning-Footnote-1496902
-Node: Numeric Array Subscripts497218
-Node: Uninitialized Subscripts499402
-Node: Delete501021
-Ref: Delete-Footnote-1503773
-Node: Multidimensional503830
-Node: Multiscanning506925
-Node: Arrays of Arrays508516
-Node: Arrays Summary513283
-Node: Functions515376
-Node: Built-in516414
-Node: Calling Built-in517495
-Node: Numeric Functions519491
-Ref: Numeric Functions-Footnote-1524324
-Ref: Numeric Functions-Footnote-2524681
-Ref: Numeric Functions-Footnote-3524729
-Node: String Functions525001
-Ref: String Functions-Footnote-1548505
-Ref: String Functions-Footnote-2548633
-Ref: String Functions-Footnote-3548881
-Node: Gory Details548968
-Ref: table-sub-escapes550759
-Ref: table-sub-proposed552278
-Ref: table-posix-sub553641
-Ref: table-gensub-escapes555182
-Ref: Gory Details-Footnote-1556005
-Node: I/O Functions556159
-Ref: table-system-return-values562741
-Ref: I/O Functions-Footnote-1564721
-Ref: I/O Functions-Footnote-2564869
-Node: Time Functions564989
-Ref: Time Functions-Footnote-1575656
-Ref: Time Functions-Footnote-2575724
-Ref: Time Functions-Footnote-3575882
-Ref: Time Functions-Footnote-4575993
-Ref: Time Functions-Footnote-5576105
-Ref: Time Functions-Footnote-6576332
-Node: Bitwise Functions576598
-Ref: table-bitwise-ops577192
-Ref: Bitwise Functions-Footnote-1583225
-Ref: Bitwise Functions-Footnote-2583398
-Node: Type Functions583589
-Node: I18N Functions586264
-Node: User-defined587915
-Node: Definition Syntax588720
-Ref: Definition Syntax-Footnote-1594407
-Node: Function Example594478
-Ref: Function Example-Footnote-1597400
-Node: Function Caveats597422
-Node: Calling A Function597940
-Node: Variable Scope598898
-Node: Pass By Value/Reference601892
-Node: Return Statement605391
-Node: Dynamic Typing608370
-Node: Indirect Calls609300
-Ref: Indirect Calls-Footnote-1619551
-Node: Functions Summary619679
-Node: Library Functions622384
-Ref: Library Functions-Footnote-1625991
-Ref: Library Functions-Footnote-2626134
-Node: Library Names626305
-Ref: Library Names-Footnote-1629765
-Ref: Library Names-Footnote-2629988
-Node: General Functions630074
-Node: Strtonum Function631177
-Node: Assert Function634199
-Node: Round Function637525
-Node: Cliff Random Function639066
-Node: Ordinal Functions640082
-Ref: Ordinal Functions-Footnote-1643145
-Ref: Ordinal Functions-Footnote-2643397
-Node: Join Function643607
-Ref: Join Function-Footnote-1645377
-Node: Getlocaltime Function645577
-Node: Readfile Function649319
-Node: Shell Quoting651291
-Node: Data File Management652692
-Node: Filetrans Function653324
-Node: Rewind Function657420
-Node: File Checking659326
-Ref: File Checking-Footnote-1660660
-Node: Empty Files660861
-Node: Ignoring Assigns662840
-Node: Getopt Function664390
-Ref: Getopt Function-Footnote-1675859
-Node: Passwd Functions676059
-Ref: Passwd Functions-Footnote-1684898
-Node: Group Functions684986
-Ref: Group Functions-Footnote-1692884
-Node: Walking Arrays693091
-Node: Library Functions Summary696099
-Node: Library Exercises697505
-Node: Sample Programs697970
-Node: Running Examples698740
-Node: Clones699468
-Node: Cut Program700692
-Node: Egrep Program710621
-Ref: Egrep Program-Footnote-1718133
-Node: Id Program718243
-Node: Split Program721923
-Ref: Split Program-Footnote-1725382
-Node: Tee Program725511
-Node: Uniq Program728301
-Node: Wc Program735727
-Ref: Wc Program-Footnote-1739982
-Node: Miscellaneous Programs740076
-Node: Dupword Program741289
-Node: Alarm Program743319
-Node: Translate Program748174
-Ref: Translate Program-Footnote-1752739
-Node: Labels Program753009
-Ref: Labels Program-Footnote-1756360
-Node: Word Sorting756444
-Node: History Sorting760516
-Node: Extract Program762351
-Node: Simple Sed769880
-Node: Igawk Program772954
-Ref: Igawk Program-Footnote-1787285
-Ref: Igawk Program-Footnote-2787487
-Ref: Igawk Program-Footnote-3787609
-Node: Anagram Program787724
-Node: Signature Program790786
-Node: Programs Summary792033
-Node: Programs Exercises793247
-Ref: Programs Exercises-Footnote-1797376
-Node: Advanced Features797467
-Node: Nondecimal Data799457
-Node: Array Sorting801048
-Node: Controlling Array Traversal801748
-Ref: Controlling Array Traversal-Footnote-1810115
-Node: Array Sorting Functions810233
-Ref: Array Sorting Functions-Footnote-1815324
-Node: Two-way I/O815520
-Ref: Two-way I/O-Footnote-1822071
-Ref: Two-way I/O-Footnote-2822258
-Node: TCP/IP Networking822340
-Node: Profiling825458
-Ref: Profiling-Footnote-1834130
-Node: Advanced Features Summary834453
-Node: Internationalization836297
-Node: I18N and L10N837777
-Node: Explaining gettext838464
-Ref: Explaining gettext-Footnote-1844356
-Ref: Explaining gettext-Footnote-2844541
-Node: Programmer i18n844706
-Ref: Programmer i18n-Footnote-1849655
-Node: Translator i18n849704
-Node: String Extraction850498
-Ref: String Extraction-Footnote-1851630
-Node: Printf Ordering851716
-Ref: Printf Ordering-Footnote-1854502
-Node: I18N Portability854566
-Ref: I18N Portability-Footnote-1857022
-Node: I18N Example857085
-Ref: I18N Example-Footnote-1859891
-Node: Gawk I18N859964
-Node: I18N Summary860609
-Node: Debugger861950
-Node: Debugging862972
-Node: Debugging Concepts863413
-Node: Debugging Terms865222
-Node: Awk Debugging867797
-Node: Sample Debugging Session868703
-Node: Debugger Invocation869237
-Node: Finding The Bug870623
-Node: List of Debugger Commands877101
-Node: Breakpoint Control878434
-Node: Debugger Execution Control882128
-Node: Viewing And Changing Data885490
-Node: Execution Stack888864
-Node: Debugger Info890501
-Node: Miscellaneous Debugger Commands894572
-Node: Readline Support899660
-Node: Limitations900556
-Node: Debugging Summary902665
-Node: Arbitrary Precision Arithmetic903944
-Node: Computer Arithmetic905360
-Ref: table-numeric-ranges908951
-Ref: Computer Arithmetic-Footnote-1909673
-Node: Math Definitions909730
-Ref: table-ieee-formats913044
-Ref: Math Definitions-Footnote-1913647
-Node: MPFR features913752
-Node: FP Math Caution915469
-Ref: FP Math Caution-Footnote-1916541
-Node: Inexactness of computations916910
-Node: Inexact representation917870
-Node: Comparing FP Values919230
-Node: Errors accumulate920312
-Node: Getting Accuracy921745
-Node: Try To Round924455
-Node: Setting precision925354
-Ref: table-predefined-precision-strings926051
-Node: Setting the rounding mode927881
-Ref: table-gawk-rounding-modes928255
-Ref: Setting the rounding mode-Footnote-1931663
-Node: Arbitrary Precision Integers931842
-Ref: Arbitrary Precision Integers-Footnote-1936759
-Node: POSIX Floating Point Problems936908
-Ref: POSIX Floating Point Problems-Footnote-1940790
-Node: Floating point summary940828
-Node: Dynamic Extensions943018
-Node: Extension Intro944571
-Node: Plugin License945837
-Node: Extension Mechanism Outline946634
-Ref: figure-load-extension947073
-Ref: figure-register-new-function948638
-Ref: figure-call-new-function949730
-Node: Extension API Description951792
-Node: Extension API Functions Introduction953434
-Node: General Data Types958768
-Ref: General Data Types-Footnote-1965973
-Node: Memory Allocation Functions966272
-Ref: Memory Allocation Functions-Footnote-1969117
-Node: Constructor Functions969216
-Node: Registration Functions972215
-Node: Extension Functions972900
-Node: Exit Callback Functions978113
-Node: Extension Version String979363
-Node: Input Parsers980026
-Node: Output Wrappers989908
-Node: Two-way processors994420
-Node: Printing Messages996685
-Ref: Printing Messages-Footnote-1997856
-Node: Updating ERRNO998009
-Node: Requesting Values998748
-Ref: table-value-types-returned999485
-Node: Accessing Parameters1000421
-Node: Symbol Table Access1001656
-Node: Symbol table by name1002168
-Node: Symbol table by cookie1003957
-Ref: Symbol table by cookie-Footnote-11008142
-Node: Cached values1008206
-Ref: Cached values-Footnote-11011742
-Node: Array Manipulation1011833
-Ref: Array Manipulation-Footnote-11012924
-Node: Array Data Types1012961
-Ref: Array Data Types-Footnote-11015619
-Node: Array Functions1015711
-Node: Flattening Arrays1020110
-Node: Creating Arrays1027051
-Node: Redirection API1031820
-Node: Extension API Variables1034662
-Node: Extension Versioning1035295
-Ref: gawk-api-version1035732
-Node: Extension API Informational Variables1037460
-Node: Extension API Boilerplate1038524
-Node: Changes from API V11042386
-Node: Finding Extensions1043046
-Node: Extension Example1043605
-Node: Internal File Description1044403
-Node: Internal File Ops1048483
-Ref: Internal File Ops-Footnote-11059883
-Node: Using Internal File Ops1060023
-Ref: Using Internal File Ops-Footnote-11062406
-Node: Extension Samples1062680
-Node: Extension Sample File Functions1064209
-Node: Extension Sample Fnmatch1071858
-Node: Extension Sample Fork1073345
-Node: Extension Sample Inplace1074563
-Node: Extension Sample Ord1077773
-Node: Extension Sample Readdir1078609
-Ref: table-readdir-file-types1079498
-Node: Extension Sample Revout1080303
-Node: Extension Sample Rev2way1080892
-Node: Extension Sample Read write array1081632
-Node: Extension Sample Readfile1083574
-Node: Extension Sample Time1084669
-Node: Extension Sample API Tests1086017
-Node: gawkextlib1086509
-Node: Extension summary1088956
-Node: Extension Exercises1092658
-Node: Language History1094156
-Node: V7/SVR3.11095812
-Node: SVR41097964
-Node: POSIX1099398
-Node: BTL1100777
-Node: POSIX/GNU1101506
-Node: Feature History1107398
-Node: Common Extensions1121768
-Node: Ranges and Locales1123051
-Ref: Ranges and Locales-Footnote-11127667
-Ref: Ranges and Locales-Footnote-21127694
-Ref: Ranges and Locales-Footnote-31127929
-Node: Contributors1128150
-Node: History summary1133710
-Node: Installation1135090
-Node: Gawk Distribution1136034
-Node: Getting1136518
-Node: Extracting1137479
-Node: Distribution contents1139117
-Node: Unix Installation1145459
-Node: Quick Installation1146141
-Node: Shell Startup Files1148555
-Node: Additional Configuration Options1149644
-Node: Configuration Philosophy1151449
-Node: Non-Unix Installation1153818
-Node: PC Installation1154278
-Node: PC Binary Installation1155116
-Node: PC Compiling1155551
-Node: PC Using1156668
-Node: Cygwin1159713
-Node: MSYS1160483
-Node: VMS Installation1160984
-Node: VMS Compilation1161775
-Ref: VMS Compilation-Footnote-11163004
-Node: VMS Dynamic Extensions1163062
-Node: VMS Installation Details1164747
-Node: VMS Running1167000
-Node: VMS GNV1171279
-Node: VMS Old Gawk1172014
-Node: Bugs1172485
-Node: Bug address1173148
-Node: Usenet1175545
-Node: Maintainers1176322
-Node: Other Versions1177698
-Node: Installation summary1184282
-Node: Notes1185317
-Node: Compatibility Mode1186182
-Node: Additions1186964
-Node: Accessing The Source1187889
-Node: Adding Code1189324
-Node: New Ports1195542
-Node: Derived Files1200030
-Ref: Derived Files-Footnote-11205515
-Ref: Derived Files-Footnote-21205550
-Ref: Derived Files-Footnote-31206148
-Node: Future Extensions1206262
-Node: Implementation Limitations1206920
-Node: Extension Design1208103
-Node: Old Extension Problems1209257
-Ref: Old Extension Problems-Footnote-11210775
-Node: Extension New Mechanism Goals1210832
-Ref: Extension New Mechanism Goals-Footnote-11214196
-Node: Extension Other Design Decisions1214385
-Node: Extension Future Growth1216498
-Node: Old Extension Mechanism1217334
-Node: Notes summary1219097
-Node: Basic Concepts1220279
-Node: Basic High Level1220960
-Ref: figure-general-flow1221242
-Ref: figure-process-flow1221927
-Ref: Basic High Level-Footnote-11225228
-Node: Basic Data Typing1225413
-Node: Glossary1228741
-Node: Copying1260688
-Node: GNU Free Documentation License1298227
-Node: Index1323345
+Node: Splitting By Content235763
+Ref: Splitting By Content-Footnote-1239903
+Node: Multiple Line240066
+Ref: Multiple Line-Footnote-1245948
+Node: Getline246127
+Node: Plain Getline248594
+Node: Getline/Variable251233
+Node: Getline/File252382
+Node: Getline/Variable/File253768
+Ref: Getline/Variable/File-Footnote-1255371
+Node: Getline/Pipe255459
+Node: Getline/Variable/Pipe258164
+Node: Getline/Coprocess259297
+Node: Getline/Variable/Coprocess260562
+Node: Getline Notes261302
+Node: Getline Summary264097
+Ref: table-getline-variants264519
+Node: Read Timeout265267
+Ref: Read Timeout-Footnote-1269173
+Node: Retrying Input269231
+Node: Command-line directories270430
+Node: Input Summary271336
+Node: Input Exercises274508
+Node: Printing275236
+Node: Print277070
+Node: Print Examples278527
+Node: Output Separators281307
+Node: OFMT283324
+Node: Printf284680
+Node: Basic Printf285465
+Node: Control Letters287039
+Node: Format Modifiers291027
+Node: Printf Examples297042
+Node: Redirection299528
+Node: Special FD306369
+Ref: Special FD-Footnote-1309537
+Node: Special Files309611
+Node: Other Inherited Files310228
+Node: Special Network311229
+Node: Special Caveats312089
+Node: Close Files And Pipes313038
+Ref: table-close-pipe-return-values319945
+Ref: Close Files And Pipes-Footnote-1320728
+Ref: Close Files And Pipes-Footnote-2320876
+Node: Nonfatal321028
+Node: Output Summary323353
+Node: Output Exercises324575
+Node: Expressions325254
+Node: Values326442
+Node: Constants327120
+Node: Scalar Constants327811
+Ref: Scalar Constants-Footnote-1328675
+Node: Nondecimal-numbers328925
+Node: Regexp Constants331926
+Node: Using Constant Regexps332452
+Node: Standard Regexp Constants333074
+Node: Strong Regexp Constants336262
+Node: Variables339220
+Node: Using Variables339877
+Node: Assignment Options341787
+Node: Conversion343660
+Node: Strings And Numbers344184
+Ref: Strings And Numbers-Footnote-1347247
+Node: Locale influences conversions347356
+Ref: table-locale-affects350114
+Node: All Operators350732
+Node: Arithmetic Ops351361
+Node: Concatenation353867
+Ref: Concatenation-Footnote-1356714
+Node: Assignment Ops356821
+Ref: table-assign-ops361812
+Node: Increment Ops363125
+Node: Truth Values and Conditions366585
+Node: Truth Values367659
+Node: Typing and Comparison368707
+Node: Variable Typing369527
+Ref: Variable Typing-Footnote-1375990
+Ref: Variable Typing-Footnote-2376062
+Node: Comparison Operators376139
+Ref: table-relational-ops376558
+Node: POSIX String Comparison380053
+Ref: POSIX String Comparison-Footnote-1381748
+Ref: POSIX String Comparison-Footnote-2381887
+Node: Boolean Ops381971
+Ref: Boolean Ops-Footnote-1386453
+Node: Conditional Exp386545
+Node: Function Calls388281
+Node: Precedence392158
+Node: Locales395817
+Node: Expressions Summary397449
+Node: Patterns and Actions400022
+Node: Pattern Overview401142
+Node: Regexp Patterns402819
+Node: Expression Patterns403361
+Node: Ranges407142
+Node: BEGIN/END410250
+Node: Using BEGIN/END411011
+Ref: Using BEGIN/END-Footnote-1413747
+Node: I/O And BEGIN/END413853
+Node: BEGINFILE/ENDFILE416167
+Node: Empty419074
+Node: Using Shell Variables419391
+Node: Action Overview421665
+Node: Statements423990
+Node: If Statement425838
+Node: While Statement427333
+Node: Do Statement429361
+Node: For Statement430509
+Node: Switch Statement433667
+Node: Break Statement436053
+Node: Continue Statement438145
+Node: Next Statement439972
+Node: Nextfile Statement442355
+Node: Exit Statement445007
+Node: Built-in Variables447410
+Node: User-modified448543
+Node: Auto-set456310
+Ref: Auto-set-Footnote-1471038
+Ref: Auto-set-Footnote-2471244
+Node: ARGC and ARGV471300
+Node: Pattern Action Summary475513
+Node: Arrays477943
+Node: Array Basics479272
+Node: Array Intro480116
+Ref: figure-array-elements482091
+Ref: Array Intro-Footnote-1484795
+Node: Reference to Elements484923
+Node: Assigning Elements487387
+Node: Array Example487878
+Node: Scanning an Array489637
+Node: Controlling Scanning492659
+Ref: Controlling Scanning-Footnote-1498058
+Node: Numeric Array Subscripts498374
+Node: Uninitialized Subscripts500558
+Node: Delete502177
+Ref: Delete-Footnote-1504929
+Node: Multidimensional504986
+Node: Multiscanning508081
+Node: Arrays of Arrays509672
+Node: Arrays Summary514439
+Node: Functions516532
+Node: Built-in517570
+Node: Calling Built-in518651
+Node: Numeric Functions520647
+Ref: Numeric Functions-Footnote-1525480
+Ref: Numeric Functions-Footnote-2525837
+Ref: Numeric Functions-Footnote-3525885
+Node: String Functions526157
+Ref: String Functions-Footnote-1549661
+Ref: String Functions-Footnote-2549789
+Ref: String Functions-Footnote-3550037
+Node: Gory Details550124
+Ref: table-sub-escapes551915
+Ref: table-sub-proposed553434
+Ref: table-posix-sub554797
+Ref: table-gensub-escapes556338
+Ref: Gory Details-Footnote-1557161
+Node: I/O Functions557315
+Ref: table-system-return-values563897
+Ref: I/O Functions-Footnote-1565877
+Ref: I/O Functions-Footnote-2566025
+Node: Time Functions566145
+Ref: Time Functions-Footnote-1576812
+Ref: Time Functions-Footnote-2576880
+Ref: Time Functions-Footnote-3577038
+Ref: Time Functions-Footnote-4577149
+Ref: Time Functions-Footnote-5577261
+Ref: Time Functions-Footnote-6577488
+Node: Bitwise Functions577754
+Ref: table-bitwise-ops578348
+Ref: Bitwise Functions-Footnote-1584381
+Ref: Bitwise Functions-Footnote-2584554
+Node: Type Functions584745
+Node: I18N Functions587420
+Node: User-defined589071
+Node: Definition Syntax589876
+Ref: Definition Syntax-Footnote-1595563
+Node: Function Example595634
+Ref: Function Example-Footnote-1598556
+Node: Function Caveats598578
+Node: Calling A Function599096
+Node: Variable Scope600054
+Node: Pass By Value/Reference603048
+Node: Return Statement606547
+Node: Dynamic Typing609526
+Node: Indirect Calls610456
+Ref: Indirect Calls-Footnote-1620707
+Node: Functions Summary620835
+Node: Library Functions623540
+Ref: Library Functions-Footnote-1627147
+Ref: Library Functions-Footnote-2627290
+Node: Library Names627461
+Ref: Library Names-Footnote-1630921
+Ref: Library Names-Footnote-2631144
+Node: General Functions631230
+Node: Strtonum Function632333
+Node: Assert Function635355
+Node: Round Function638681
+Node: Cliff Random Function640222
+Node: Ordinal Functions641238
+Ref: Ordinal Functions-Footnote-1644301
+Ref: Ordinal Functions-Footnote-2644553
+Node: Join Function644763
+Ref: Join Function-Footnote-1646533
+Node: Getlocaltime Function646733
+Node: Readfile Function650475
+Node: Shell Quoting652447
+Node: Data File Management653848
+Node: Filetrans Function654480
+Node: Rewind Function658576
+Node: File Checking660482
+Ref: File Checking-Footnote-1661816
+Node: Empty Files662017
+Node: Ignoring Assigns663996
+Node: Getopt Function665546
+Ref: Getopt Function-Footnote-1677015
+Node: Passwd Functions677215
+Ref: Passwd Functions-Footnote-1686054
+Node: Group Functions686142
+Ref: Group Functions-Footnote-1694040
+Node: Walking Arrays694247
+Node: Library Functions Summary697255
+Node: Library Exercises698661
+Node: Sample Programs699126
+Node: Running Examples699896
+Node: Clones700624
+Node: Cut Program701848
+Node: Egrep Program711777
+Ref: Egrep Program-Footnote-1719289
+Node: Id Program719399
+Node: Split Program723079
+Ref: Split Program-Footnote-1726538
+Node: Tee Program726667
+Node: Uniq Program729457
+Node: Wc Program736883
+Ref: Wc Program-Footnote-1741138
+Node: Miscellaneous Programs741232
+Node: Dupword Program742445
+Node: Alarm Program744475
+Node: Translate Program749330
+Ref: Translate Program-Footnote-1753895
+Node: Labels Program754165
+Ref: Labels Program-Footnote-1757516
+Node: Word Sorting757600
+Node: History Sorting761672
+Node: Extract Program763507
+Node: Simple Sed771036
+Node: Igawk Program774110
+Ref: Igawk Program-Footnote-1788441
+Ref: Igawk Program-Footnote-2788643
+Ref: Igawk Program-Footnote-3788765
+Node: Anagram Program788880
+Node: Signature Program791942
+Node: Programs Summary793189
+Node: Programs Exercises794403
+Ref: Programs Exercises-Footnote-1798532
+Node: Advanced Features798623
+Node: Nondecimal Data800613
+Node: Array Sorting802204
+Node: Controlling Array Traversal802904
+Ref: Controlling Array Traversal-Footnote-1811271
+Node: Array Sorting Functions811389
+Ref: Array Sorting Functions-Footnote-1816480
+Node: Two-way I/O816676
+Ref: Two-way I/O-Footnote-1823227
+Ref: Two-way I/O-Footnote-2823414
+Node: TCP/IP Networking823496
+Node: Profiling826614
+Ref: Profiling-Footnote-1835286
+Node: Advanced Features Summary835609
+Node: Internationalization837453
+Node: I18N and L10N838933
+Node: Explaining gettext839620
+Ref: Explaining gettext-Footnote-1845512
+Ref: Explaining gettext-Footnote-2845697
+Node: Programmer i18n845862
+Ref: Programmer i18n-Footnote-1850811
+Node: Translator i18n850860
+Node: String Extraction851654
+Ref: String Extraction-Footnote-1852786
+Node: Printf Ordering852872
+Ref: Printf Ordering-Footnote-1855658
+Node: I18N Portability855722
+Ref: I18N Portability-Footnote-1858178
+Node: I18N Example858241
+Ref: I18N Example-Footnote-1861047
+Node: Gawk I18N861120
+Node: I18N Summary861765
+Node: Debugger863106
+Node: Debugging864128
+Node: Debugging Concepts864569
+Node: Debugging Terms866378
+Node: Awk Debugging868953
+Node: Sample Debugging Session869859
+Node: Debugger Invocation870393
+Node: Finding The Bug871779
+Node: List of Debugger Commands878257
+Node: Breakpoint Control879590
+Node: Debugger Execution Control883284
+Node: Viewing And Changing Data886646
+Node: Execution Stack890020
+Node: Debugger Info891657
+Node: Miscellaneous Debugger Commands895728
+Node: Readline Support900816
+Node: Limitations901712
+Node: Debugging Summary903821
+Node: Arbitrary Precision Arithmetic905100
+Node: Computer Arithmetic906516
+Ref: table-numeric-ranges910107
+Ref: Computer Arithmetic-Footnote-1910829
+Node: Math Definitions910886
+Ref: table-ieee-formats914200
+Ref: Math Definitions-Footnote-1914803
+Node: MPFR features914908
+Node: FP Math Caution916625
+Ref: FP Math Caution-Footnote-1917697
+Node: Inexactness of computations918066
+Node: Inexact representation919026
+Node: Comparing FP Values920386
+Node: Errors accumulate921468
+Node: Getting Accuracy922901
+Node: Try To Round925611
+Node: Setting precision926510
+Ref: table-predefined-precision-strings927207
+Node: Setting the rounding mode929037
+Ref: table-gawk-rounding-modes929411
+Ref: Setting the rounding mode-Footnote-1932819
+Node: Arbitrary Precision Integers932998
+Ref: Arbitrary Precision Integers-Footnote-1937915
+Node: POSIX Floating Point Problems938064
+Ref: POSIX Floating Point Problems-Footnote-1941946
+Node: Floating point summary941984
+Node: Dynamic Extensions944174
+Node: Extension Intro945727
+Node: Plugin License946993
+Node: Extension Mechanism Outline947790
+Ref: figure-load-extension948229
+Ref: figure-register-new-function949794
+Ref: figure-call-new-function950886
+Node: Extension API Description952948
+Node: Extension API Functions Introduction954590
+Node: General Data Types959924
+Ref: General Data Types-Footnote-1967129
+Node: Memory Allocation Functions967428
+Ref: Memory Allocation Functions-Footnote-1970273
+Node: Constructor Functions970372
+Node: Registration Functions973371
+Node: Extension Functions974056
+Node: Exit Callback Functions979269
+Node: Extension Version String980519
+Node: Input Parsers981182
+Node: Output Wrappers993889
+Node: Two-way processors998401
+Node: Printing Messages1000666
+Ref: Printing Messages-Footnote-11001837
+Node: Updating ERRNO1001990
+Node: Requesting Values1002729
+Ref: table-value-types-returned1003466
+Node: Accessing Parameters1004402
+Node: Symbol Table Access1005637
+Node: Symbol table by name1006149
+Node: Symbol table by cookie1007938
+Ref: Symbol table by cookie-Footnote-11012123
+Node: Cached values1012187
+Ref: Cached values-Footnote-11015723
+Node: Array Manipulation1015814
+Ref: Array Manipulation-Footnote-11016905
+Node: Array Data Types1016942
+Ref: Array Data Types-Footnote-11019600
+Node: Array Functions1019692
+Node: Flattening Arrays1024091
+Node: Creating Arrays1031032
+Node: Redirection API1035801
+Node: Extension API Variables1038643
+Node: Extension Versioning1039276
+Ref: gawk-api-version1039713
+Node: Extension API Informational Variables1041441
+Node: Extension API Boilerplate1042505
+Node: Changes from API V11046367
+Node: Finding Extensions1047027
+Node: Extension Example1047586
+Node: Internal File Description1048384
+Node: Internal File Ops1052464
+Ref: Internal File Ops-Footnote-11063864
+Node: Using Internal File Ops1064004
+Ref: Using Internal File Ops-Footnote-11066387
+Node: Extension Samples1066661
+Node: Extension Sample File Functions1068190
+Node: Extension Sample Fnmatch1075839
+Node: Extension Sample Fork1077326
+Node: Extension Sample Inplace1078544
+Node: Extension Sample Ord1081754
+Node: Extension Sample Readdir1082590
+Ref: table-readdir-file-types1083479
+Node: Extension Sample Revout1084284
+Node: Extension Sample Rev2way1084873
+Node: Extension Sample Read write array1085613
+Node: Extension Sample Readfile1087555
+Node: Extension Sample Time1088650
+Node: Extension Sample API Tests1089998
+Node: gawkextlib1090490
+Node: Extension summary1092937
+Node: Extension Exercises1096639
+Node: Language History1098137
+Node: V7/SVR3.11099793
+Node: SVR41101945
+Node: POSIX1103379
+Node: BTL1104758
+Node: POSIX/GNU1105487
+Node: Feature History1111379
+Node: Common Extensions1125749
+Node: Ranges and Locales1127032
+Ref: Ranges and Locales-Footnote-11131648
+Ref: Ranges and Locales-Footnote-21131675
+Ref: Ranges and Locales-Footnote-31131910
+Node: Contributors1132131
+Node: History summary1137691
+Node: Installation1139071
+Node: Gawk Distribution1140015
+Node: Getting1140499
+Node: Extracting1141460
+Node: Distribution contents1143098
+Node: Unix Installation1149440
+Node: Quick Installation1150122
+Node: Shell Startup Files1152536
+Node: Additional Configuration Options1153625
+Node: Configuration Philosophy1155430
+Node: Non-Unix Installation1157799
+Node: PC Installation1158259
+Node: PC Binary Installation1159097
+Node: PC Compiling1159532
+Node: PC Using1160649
+Node: Cygwin1163694
+Node: MSYS1164464
+Node: VMS Installation1164965
+Node: VMS Compilation1165756
+Ref: VMS Compilation-Footnote-11166985
+Node: VMS Dynamic Extensions1167043
+Node: VMS Installation Details1168728
+Node: VMS Running1170981
+Node: VMS GNV1175260
+Node: VMS Old Gawk1175995
+Node: Bugs1176466
+Node: Bug address1177129
+Node: Usenet1179526
+Node: Maintainers1180303
+Node: Other Versions1181679
+Node: Installation summary1188263
+Node: Notes1189298
+Node: Compatibility Mode1190163
+Node: Additions1190945
+Node: Accessing The Source1191870
+Node: Adding Code1193305
+Node: New Ports1199523
+Node: Derived Files1204011
+Ref: Derived Files-Footnote-11209496
+Ref: Derived Files-Footnote-21209531
+Ref: Derived Files-Footnote-31210129
+Node: Future Extensions1210243
+Node: Implementation Limitations1210901
+Node: Extension Design1212084
+Node: Old Extension Problems1213238
+Ref: Old Extension Problems-Footnote-11214756
+Node: Extension New Mechanism Goals1214813
+Ref: Extension New Mechanism Goals-Footnote-11218177
+Node: Extension Other Design Decisions1218366
+Node: Extension Future Growth1220479
+Node: Old Extension Mechanism1221315
+Node: Notes summary1223078
+Node: Basic Concepts1224260
+Node: Basic High Level1224941
+Ref: figure-general-flow1225223
+Ref: figure-process-flow1225908
+Ref: Basic High Level-Footnote-11229209
+Node: Basic Data Typing1229394
+Node: Glossary1232722
+Node: Copying1264669
+Node: GNU Free Documentation License1302208
+Node: Index1327326

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 658ac17e..0e376104 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -7761,6 +7761,9 @@ variable @code{FIELDWIDTHS}. Each number specifies the width of the field,
@emph{including} columns between fields. If you want to ignore the columns
between fields, you can specify the width as a separate field that is
subsequently ignored.
+Or, starting in @value{PVERSION} 4.2, each field width may optionally be
+preceded by a colon-separated value specifying the number of characters to skip
+before the field starts.
It is a fatal error to supply a field width that has a negative value.
The following data is the output of the Unix @command{w} utility. It is useful
to illustrate the use of @code{FIELDWIDTHS}:
@@ -7820,6 +7823,24 @@ brent ttyp0 286
dave ttyq4 1296000
@end example
+Starting in @value{PVERSION} 4.2, this program could be rewritten to
+specify @code{FIELDWIDTHS} like so:
+@example
+BEGIN @{ FIELDWIDTHS = "8 1:5 4:7 6 1:6 1:6 2:33" @}
+@end example
+This strips away some of the white space separating the fields. With such
+a change, the program would produce the following results:
+
+@example
+hzang ttyV3 50
+eklye ttyV5 0
+dportein ttyV6 107
+gierd ttyD3 1
+dave ttyD4 0
+brent ttyp0 286
+dave ttyq4 1296000
+@end example
+
Another (possibly more practical) example of fixed-width input data
is the input from a deck of balloting cards. In some parts of
the United States, voters mark their choices by punching holes in computer
@@ -7845,8 +7866,10 @@ if (PROCINFO["FS"] == "FS")
@var{regular field splitting} @dots{}
else if (PROCINFO["FS"] == "FIELDWIDTHS")
@var{fixed-width field splitting} @dots{}
-else
+else if (PROCINFO["FS"] == "FPAT")
@var{content-based field splitting} @dots{} @ii{(see next @value{SECTION})}
+else
+ @var{API input parser field splitting} @dots{} @ii{(advanced feature)}
@end example
This information is useful when writing a function
@@ -7986,7 +8009,9 @@ To recap, @command{gawk} provides three independent methods
to split input records into fields.
The mechanism used is based on which of the three
variables---@code{FS}, @code{FIELDWIDTHS}, or @code{FPAT}---was
-last assigned to.
+last assigned to. In addition, an API input parser may choose to
+override the record parsing mechanism; please refer to @ref{Input Parsers}
+for further information about this feature.
@node Multiple Line
@section Multiple-Line Records
@@ -14972,6 +14997,9 @@ Its default value is @code{"%.6g"}.
@item FIELDWIDTHS #
A space-separated list of columns that tells @command{gawk}
how to split input with fixed columnar boundaries.
+Starting in @value{PVERSION} 4.2, each field width may optionally be
+preceded by a colon-separated value specifying the number of characters to skip
+before the field starts.
Assigning a value to @code{FIELDWIDTHS}
overrides the use of @code{FS} and @code{FPAT} for field splitting.
@xref{Constant Size} for more information.
@@ -15366,7 +15394,8 @@ The value of the @code{geteuid()} system call.
This is
@code{"FS"} if field splitting with @code{FS} is in effect,
@code{"FIELDWIDTHS"} if field splitting with @code{FIELDWIDTHS} is in effect,
-or @code{"FPAT"} if field matching with @code{FPAT} is in effect.
+@code{"FPAT"} if field matching with @code{FPAT} is in effect,
+or @code{"API"} if field splitting is controlled by an API input parser.
@item PROCINFO["gid"]
@cindex group ID of @command{gawk} user
@@ -33165,7 +33194,8 @@ typedef struct awk_input @{
#define INVALID_HANDLE (-1)
void *opaque; /* private data for input parsers */
int (*get_record)(char **out, struct awk_input *iobuf,
- int *errcode, char **rt_start, size_t *rt_len);
+ int *errcode, char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **field_width);
ssize_t (*read_func)();
void (*close_func)(struct awk_input *iobuf);
struct stat sbuf; /* stat buf */
@@ -33217,7 +33247,8 @@ is not required to use this pointer.
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ struct@ awk_input *iobuf,
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ int *errcode,
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ char **rt_start,
-@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t *rt_len);
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t *rt_len,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_fieldwidth_info_t **field_width);
This function pointer should point to a function that creates the input
records. Said function is the core of the input parser. Its behavior
is described in the text following this list.
@@ -33269,6 +33300,21 @@ If the concept of a ``record terminator'' makes sense, then
data. Otherwise, @code{*rt_len} should be set to zero.
@command{gawk} makes its own copy of this data, so the
extension must manage this storage.
+
+@item const awk_fieldwidth_info_t **field_width
+If @code{field_width} is not @code{NULL}, then @code{*field_width} will be initialized
+to @code{NULL}, and the function may set it to point to a structure
+supplying field width information to override the default
+field parsing mechanism. Note that this structure will not
+be copied by @command{gawk}; it must persist at least until the next call
+to @code{get_record} or @code{close_func}. Note also that @code{field_width} is
+@code{NULL} when @code{getline} is assigning the results to a variable, thus
+field parsing is not needed. If the parser does set @code{*field_width},
+then @command{gawk} uses this layout to parse the input record,
+and the @code{PROCINFO["FS"]} value will be @code{"API"} while this record
+is active in @code{$0}.
+The @code{awk_fieldwidth_info_t} data structure
+is described below.
@end table
The return value is the length of the buffer pointed to by
@@ -33327,6 +33373,50 @@ Register the input parser pointed to by @code{input_parser} with
@command{gawk}.
@end table
+If you would like to override the default field parsing mechanism for a given
+record, then you must populate an @code{awk_fieldwidth_info_t} structure,
+which looks like this:
+
+@example
+typedef struct @{
+ awk_bool_t use_chars; /* false ==> use bytes */
+ size_t nf; /* number of fields in record (NF) */
+ struct awk_field_info @{
+ size_t skip; /* amount to skip before field starts */
+ size_t len; /* length of field */
+ @} fields[1]; /* actual dimension should be nf */
+@} awk_fieldwidth_info_t;
+@end example
+
+The fields are:
+
+@table @code
+@item awk_bool_t use_chars;
+Set this to @code{awk_true} if the field lengths are specified in terms
+of potentially multi-byte characters, and set it to @code{awk_false} if
+the lengths are in terms of bytes.
+Performance will be better if the values are supplied in
+terms of bytes.
+
+@item size_t nf;
+Set this to the number of fields in the input record, i.e. @code{NF}.
+
+@item struct awk_field_info fields[nf];
+This is a variable-length array whose actual dimension should be @code{nf}.
+For each field, the @code{skip} element should be set to the number
+of characters or bytes, as controlled by the @code{use_chars} flag,
+to skip before the start of this field. The @code{len} element provides
+the length of the field. The values in @code{fields[0]} provide the information
+for @code{$1}, and so on through the @code{fields[nf-1]} element containing the information for @code{$NF}.
+@end table
+
+A convenience macro @code{awk_fieldwidth_info_size(NF)} is provided to
+calculate the appropriate size of a variable-length
+@code{awk_fieldwidth_info_t} structure containing @code{NF} fields. This can
+be used as an argument to @code{malloc()} or in a union to allocate space
+statically. Please refer to the @code{readdir_test} sample extension for an
+example.
+
@node Output Wrappers
@subsubsection Customized Output Wrappers
@cindex customized output wrapper
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index d8e9654f..f4fe2596 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -7361,6 +7361,9 @@ variable @code{FIELDWIDTHS}. Each number specifies the width of the field,
@emph{including} columns between fields. If you want to ignore the columns
between fields, you can specify the width as a separate field that is
subsequently ignored.
+Or, starting in @value{PVERSION} 4.2, each field width may optionally be
+preceded by a colon-separated value specifying the number of characters to skip
+before the field starts.
It is a fatal error to supply a field width that has a negative value.
The following data is the output of the Unix @command{w} utility. It is useful
to illustrate the use of @code{FIELDWIDTHS}:
@@ -7420,6 +7423,24 @@ brent ttyp0 286
dave ttyq4 1296000
@end example
+Starting in @value{PVERSION} 4.2, this program could be rewritten to
+specify @code{FIELDWIDTHS} like so:
+@example
+BEGIN @{ FIELDWIDTHS = "8 1:5 4:7 6 1:6 1:6 2:33" @}
+@end example
+This strips away some of the white space separating the fields. With such
+a change, the program would produce the following results:
+
+@example
+hzang ttyV3 50
+eklye ttyV5 0
+dportein ttyV6 107
+gierd ttyD3 1
+dave ttyD4 0
+brent ttyp0 286
+dave ttyq4 1296000
+@end example
+
Another (possibly more practical) example of fixed-width input data
is the input from a deck of balloting cards. In some parts of
the United States, voters mark their choices by punching holes in computer
@@ -7445,8 +7466,10 @@ if (PROCINFO["FS"] == "FS")
@var{regular field splitting} @dots{}
else if (PROCINFO["FS"] == "FIELDWIDTHS")
@var{fixed-width field splitting} @dots{}
-else
+else if (PROCINFO["FS"] == "FPAT")
@var{content-based field splitting} @dots{} @ii{(see next @value{SECTION})}
+else
+ @var{API input parser field splitting} @dots{} @ii{(advanced feature)}
@end example
This information is useful when writing a function
@@ -7586,7 +7609,9 @@ To recap, @command{gawk} provides three independent methods
to split input records into fields.
The mechanism used is based on which of the three
variables---@code{FS}, @code{FIELDWIDTHS}, or @code{FPAT}---was
-last assigned to.
+last assigned to. In addition, an API input parser may choose to
+override the record parsing mechanism; please refer to @ref{Input Parsers}
+for further information about this feature.
@node Multiple Line
@section Multiple-Line Records
@@ -14291,6 +14316,9 @@ Its default value is @code{"%.6g"}.
@item FIELDWIDTHS #
A space-separated list of columns that tells @command{gawk}
how to split input with fixed columnar boundaries.
+Starting in @value{PVERSION} 4.2, each field width may optionally be
+preceded by a colon-separated value specifying the number of characters to skip
+before the field starts.
Assigning a value to @code{FIELDWIDTHS}
overrides the use of @code{FS} and @code{FPAT} for field splitting.
@xref{Constant Size} for more information.
@@ -14685,7 +14713,8 @@ The value of the @code{geteuid()} system call.
This is
@code{"FS"} if field splitting with @code{FS} is in effect,
@code{"FIELDWIDTHS"} if field splitting with @code{FIELDWIDTHS} is in effect,
-or @code{"FPAT"} if field matching with @code{FPAT} is in effect.
+@code{"FPAT"} if field matching with @code{FPAT} is in effect,
+or @code{"API"} if field splitting is controlled by an API input parser.
@item PROCINFO["gid"]
@cindex group ID of @command{gawk} user
@@ -32179,7 +32208,8 @@ typedef struct awk_input @{
#define INVALID_HANDLE (-1)
void *opaque; /* private data for input parsers */
int (*get_record)(char **out, struct awk_input *iobuf,
- int *errcode, char **rt_start, size_t *rt_len);
+ int *errcode, char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **field_width);
ssize_t (*read_func)();
void (*close_func)(struct awk_input *iobuf);
struct stat sbuf; /* stat buf */
@@ -32231,7 +32261,8 @@ is not required to use this pointer.
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ struct@ awk_input *iobuf,
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ int *errcode,
@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ char **rt_start,
-@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t *rt_len);
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t *rt_len,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_fieldwidth_info_t **field_width);
This function pointer should point to a function that creates the input
records. Said function is the core of the input parser. Its behavior
is described in the text following this list.
@@ -32283,6 +32314,21 @@ If the concept of a ``record terminator'' makes sense, then
data. Otherwise, @code{*rt_len} should be set to zero.
@command{gawk} makes its own copy of this data, so the
extension must manage this storage.
+
+@item const awk_fieldwidth_info_t **field_width
+If @code{field_width} is not @code{NULL}, then @code{*field_width} will be initialized
+to @code{NULL}, and the function may set it to point to a structure
+supplying field width information to override the default
+field parsing mechanism. Note that this structure will not
+be copied by @command{gawk}; it must persist at least until the next call
+to @code{get_record} or @code{close_func}. Note also that @code{field_width} is
+@code{NULL} when @code{getline} is assigning the results to a variable, thus
+field parsing is not needed. If the parser does set @code{*field_width},
+then @command{gawk} uses this layout to parse the input record,
+and the @code{PROCINFO["FS"]} value will be @code{"API"} while this record
+is active in @code{$0}.
+The @code{awk_fieldwidth_info_t} data structure
+is described below.
@end table
The return value is the length of the buffer pointed to by
@@ -32341,6 +32387,50 @@ Register the input parser pointed to by @code{input_parser} with
@command{gawk}.
@end table
+If you would like to override the default field parsing mechanism for a given
+record, then you must populate an @code{awk_fieldwidth_info_t} structure,
+which looks like this:
+
+@example
+typedef struct @{
+ awk_bool_t use_chars; /* false ==> use bytes */
+ size_t nf; /* number of fields in record (NF) */
+ struct awk_field_info @{
+ size_t skip; /* amount to skip before field starts */
+ size_t len; /* length of field */
+ @} fields[1]; /* actual dimension should be nf */
+@} awk_fieldwidth_info_t;
+@end example
+
+The fields are:
+
+@table @code
+@item awk_bool_t use_chars;
+Set this to @code{awk_true} if the field lengths are specified in terms
+of potentially multi-byte characters, and set it to @code{awk_false} if
+the lengths are in terms of bytes.
+Performance will be better if the values are supplied in
+terms of bytes.
+
+@item size_t nf;
+Set this to the number of fields in the input record, i.e. @code{NF}.
+
+@item struct awk_field_info fields[nf];
+This is a variable-length array whose actual dimension should be @code{nf}.
+For each field, the @code{skip} element should be set to the number
+of characters or bytes, as controlled by the @code{use_chars} flag,
+to skip before the start of this field. The @code{len} element provides
+the length of the field. The values in @code{fields[0]} provide the information
+for @code{$1}, and so on through the @code{fields[nf-1]} element containing the information for @code{$NF}.
+@end table
+
+A convenience macro @code{awk_fieldwidth_info_size(NF)} is provided to
+calculate the appropriate size of a variable-length
+@code{awk_fieldwidth_info_t} structure containing @code{NF} fields. This can
+be used as an argument to @code{malloc()} or in a union to allocate space
+statically. Please refer to the @code{readdir_test} sample extension for an
+example.
+
@node Output Wrappers
@subsubsection Customized Output Wrappers
@cindex customized output wrapper
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 9ea2ea9a..d10dc766 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -4,6 +4,37 @@
wrong argument count error message. Thanks to Dan Neilsen
for the report.
+2017-03-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * readdir.c: Minor edits.
+ * readdir_test.c: Same minor edits, update copyright year,
+ bump version of extension in case this ever becomes the real one.
+
+2017-03-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * readdir.c (dir_get_record): Add additional parameter to make types
+ match and remove compiler warning.
+ * readfile.c (readfile_get_record): Ditto.
+ * revtwoway.c (rev2way_get_record): Ditto.
+
+2017-03-21 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * readdir_test.c (open_directory_t): Replace field_width array
+ with new awk_fieldwidth_info_t structure. Wrap it in a union so
+ we can allocate the proper size.
+ (dir_get_record): Update field_width type from
+ 'const awk_input_field_info_t **' to 'const awk_fieldwidth_info_t **'.
+ Update new fieldwidth parsing info appropriately.
+ (dir_take_control_of): Populate new fieldwidth parsing structure
+ with initial values.
+
+2017-03-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * readdir_test.c (open_directory_t): Update field_width type from an
+ array of integers to an array of awk_input_field_info_t.
+ (dir_get_record): Ditto.
+ (dir_take_control_of): Ditto.
+
2017-03-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am (pkgextension_LTLIBRARIES): Remove testext.la, since it
@@ -16,6 +47,13 @@
installed, automake cannot use the final destination directory to
determine -rpath by itself. The value doesn't matter.
+2017-03-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * readdir_test.c: Test extension using new get_record field_width
+ parsing feature.
+ * Makefile.am (noinst_LTLIBRARIES): Add readdir_test.la.
+ (readdir_test_la_*): Configure building of new extension library.
+
2017-01-21 Eli Zaretskii <eliz@gnu.org>
* testext.c (getuid) [__MINGW32__]: New function, mirrors what
diff --git a/extension/Makefile.am b/extension/Makefile.am
index 185bc795..6ea16f5d 100644
--- a/extension/Makefile.am
+++ b/extension/Makefile.am
@@ -48,6 +48,7 @@ pkgextension_LTLIBRARIES = \
time.la
noinst_LTLIBRARIES = \
+ readdir_test.la \
testext.la
MY_MODULE_FLAGS = -module -avoid-version -no-undefined
@@ -106,6 +107,13 @@ testext_la_SOURCES = testext.c
testext_la_LDFLAGS = $(MY_MODULE_FLAGS) -rpath /foo
testext_la_LIBADD = $(MY_LIBS)
+# N.B. Because we are not installing readdir_test, we must specify -rpath in
+# LDFLAGS to get automake to build a shared library, since it needs
+# an installation path.
+readdir_test_la_SOURCES = readdir_test.c
+readdir_test_la_LDFLAGS = $(MY_MODULE_FLAGS) -rpath /foo
+readdir_test_la_LIBADD = $(MY_LIBS)
+
install-data-hook:
for i in $(pkgextension_LTLIBRARIES) ; do \
$(RM) $(DESTDIR)$(pkgextensiondir)/$$i ; \
diff --git a/extension/Makefile.in b/extension/Makefile.in
index 6557693a..c0e2676b 100644
--- a/extension/Makefile.in
+++ b/extension/Makefile.in
@@ -199,6 +199,13 @@ readdir_la_OBJECTS = $(am_readdir_la_OBJECTS)
readdir_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(readdir_la_LDFLAGS) $(LDFLAGS) -o $@
+readdir_test_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_readdir_test_la_OBJECTS = readdir_test.lo
+readdir_test_la_OBJECTS = $(am_readdir_test_la_OBJECTS)
+readdir_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(readdir_test_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
readfile_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_readfile_la_OBJECTS = readfile.lo
readfile_la_OBJECTS = $(am_readfile_la_OBJECTS)
@@ -271,14 +278,16 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
$(fork_la_SOURCES) $(inplace_la_SOURCES) $(ordchr_la_SOURCES) \
- $(readdir_la_SOURCES) $(readfile_la_SOURCES) \
- $(revoutput_la_SOURCES) $(revtwoway_la_SOURCES) \
- $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(readdir_la_SOURCES) $(readdir_test_la_SOURCES) \
+ $(readfile_la_SOURCES) $(revoutput_la_SOURCES) \
+ $(revtwoway_la_SOURCES) $(rwarray_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
DIST_SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
$(fork_la_SOURCES) $(inplace_la_SOURCES) $(ordchr_la_SOURCES) \
- $(readdir_la_SOURCES) $(readfile_la_SOURCES) \
- $(revoutput_la_SOURCES) $(revtwoway_la_SOURCES) \
- $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(readdir_la_SOURCES) $(readdir_test_la_SOURCES) \
+ $(readfile_la_SOURCES) $(revoutput_la_SOURCES) \
+ $(revtwoway_la_SOURCES) $(rwarray_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
@@ -520,6 +529,7 @@ pkgextension_LTLIBRARIES = \
time.la
noinst_LTLIBRARIES = \
+ readdir_test.la \
testext.la
MY_MODULE_FLAGS = -module -avoid-version -no-undefined
@@ -567,6 +577,13 @@ time_la_LIBADD = $(MY_LIBS)
testext_la_SOURCES = testext.c
testext_la_LDFLAGS = $(MY_MODULE_FLAGS) -rpath /foo
testext_la_LIBADD = $(MY_LIBS)
+
+# N.B. Because we are not installing readdir_test, we must specify -rpath in
+# LDFLAGS to get automake to build a shared library, since it needs
+# an installation path.
+readdir_test_la_SOURCES = readdir_test.c
+readdir_test_la_LDFLAGS = $(MY_MODULE_FLAGS) -rpath /foo
+readdir_test_la_LIBADD = $(MY_LIBS)
EXTRA_DIST = build-aux/config.rpath \
ChangeLog \
ChangeLog.0 \
@@ -702,6 +719,9 @@ ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPE
readdir.la: $(readdir_la_OBJECTS) $(readdir_la_DEPENDENCIES) $(EXTRA_readdir_la_DEPENDENCIES)
$(AM_V_CCLD)$(readdir_la_LINK) -rpath $(pkgextensiondir) $(readdir_la_OBJECTS) $(readdir_la_LIBADD) $(LIBS)
+readdir_test.la: $(readdir_test_la_OBJECTS) $(readdir_test_la_DEPENDENCIES) $(EXTRA_readdir_test_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(readdir_test_la_LINK) $(readdir_test_la_OBJECTS) $(readdir_test_la_LIBADD) $(LIBS)
+
readfile.la: $(readfile_la_OBJECTS) $(readfile_la_DEPENDENCIES) $(EXTRA_readfile_la_DEPENDENCIES)
$(AM_V_CCLD)$(readfile_la_LINK) -rpath $(pkgextensiondir) $(readfile_la_OBJECTS) $(readfile_la_LIBADD) $(LIBS)
@@ -733,6 +753,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inplace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordchr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir_test.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revoutput.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revtwoway.Plo@am__quote@
diff --git a/extension/readdir.c b/extension/readdir.c
index 39acba68..2e34456e 100644
--- a/extension/readdir.c
+++ b/extension/readdir.c
@@ -51,7 +51,7 @@
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#else
-#error Cannot compile the dirent extension on this system!
+#error Cannot compile the readdir extension on this system!
#endif
#ifdef __MINGW32__
@@ -137,6 +137,7 @@ ftype(struct dirent *entry, const char *dirname)
}
/* get_inode --- get the inode of a file */
+
static long long
get_inode(struct dirent *entry, const char *dirname)
{
@@ -168,7 +169,8 @@ get_inode(struct dirent *entry, const char *dirname)
static int
dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
- char **rt_start, size_t *rt_len)
+ char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **unused)
{
DIR *dp;
struct dirent *dirent;
@@ -198,7 +200,7 @@ dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
return EOF;
}
- ino = get_inode (dirent, iobuf->name);
+ ino = get_inode(dirent, iobuf->name);
#if __MINGW32__
len = sprintf(the_dir->buf, "%I64u/%s", ino, dirent->d_name);
diff --git a/extension/readdir_test.c b/extension/readdir_test.c
new file mode 100644
index 00000000..6d6ee134
--- /dev/null
+++ b/extension/readdir_test.c
@@ -0,0 +1,343 @@
+/*
+ * readdir.c --- Provide an input parser to read directories
+ *
+ * Arnold Robbins
+ * arnold@skeeve.com
+ * Written 7/2012
+ *
+ * Andrew Schorr and Arnold Robbins: further fixes 8/2012.
+ * Simplified 11/2012.
+ */
+
+/*
+ * Copyright (C) 2012-2014, 2017 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#else
+#error Cannot compile the readdir extension on this system!
+#endif
+
+#ifdef __MINGW32__
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "gawkapi.h"
+
+#include "gawkdirfd.h"
+
+#include "gettext.h"
+#define _(msgid) gettext(msgid)
+#define N_(msgid) msgid
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* a good guess */
+#endif
+
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+static const char *ext_version = "readdir extension: version 2.0";
+
+static awk_bool_t init_readdir(void);
+static awk_bool_t (*init_func)(void) = init_readdir;
+
+int plugin_is_GPL_compatible;
+
+/* data type for the opaque pointer: */
+
+typedef struct open_directory {
+ DIR *dp;
+ char *buf;
+ union {
+ awk_fieldwidth_info_t fw;
+ char buf[awk_fieldwidth_info_size(3)];
+ } u;
+} open_directory_t;
+#define fw u.fw
+
+/* ftype --- return type of file as a single character string */
+
+static const char *
+ftype(struct dirent *entry, const char *dirname)
+{
+#ifdef DT_BLK
+ (void) dirname; /* silence warnings */
+ switch (entry->d_type) {
+ case DT_BLK: return "b";
+ case DT_CHR: return "c";
+ case DT_DIR: return "d";
+ case DT_FIFO: return "p";
+ case DT_LNK: return "l";
+ case DT_REG: return "f";
+ case DT_SOCK: return "s";
+ default:
+ case DT_UNKNOWN: return "u";
+ }
+#else
+ char fname[PATH_MAX];
+ struct stat sbuf;
+
+ strcpy(fname, dirname);
+ strcat(fname, "/");
+ strcat(fname, entry->d_name);
+ if (stat(fname, &sbuf) == 0) {
+ if (S_ISBLK(sbuf.st_mode))
+ return "b";
+ if (S_ISCHR(sbuf.st_mode))
+ return "c";
+ if (S_ISDIR(sbuf.st_mode))
+ return "d";
+ if (S_ISFIFO(sbuf.st_mode))
+ return "p";
+ if (S_ISREG(sbuf.st_mode))
+ return "f";
+#ifdef S_ISLNK
+ if (S_ISLNK(sbuf.st_mode))
+ return "l";
+#endif
+#ifdef S_ISSOCK
+ if (S_ISSOCK(sbuf.st_mode))
+ return "s";
+#endif
+ }
+ return "u";
+#endif
+}
+
+/* get_inode --- get the inode of a file */
+
+static long long
+get_inode(struct dirent *entry, const char *dirname)
+{
+#ifdef __MINGW32__
+ char fname[PATH_MAX];
+ HANDLE fh;
+ BY_HANDLE_FILE_INFORMATION info;
+
+ sprintf(fname, "%s\\%s", dirname, entry->d_name);
+ fh = CreateFile(fname, 0, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (fh == INVALID_HANDLE_VALUE)
+ return 0;
+ if (GetFileInformationByHandle(fh, &info)) {
+ long long inode = info.nFileIndexHigh;
+
+ inode <<= 32;
+ inode += info.nFileIndexLow;
+ return inode;
+ }
+ return 0;
+#else
+ (void) dirname; /* silence warnings */
+ return entry->d_ino;
+#endif
+}
+
+/* dir_get_record --- get one record at a time out of a directory */
+
+static int
+dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
+ char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **field_width)
+{
+ DIR *dp;
+ struct dirent *dirent;
+ int len, flen;
+ open_directory_t *the_dir;
+ const char *ftstr;
+ unsigned long long ino;
+
+ /*
+ * The caller sets *errcode to 0, so we should set it only if an
+ * error occurs.
+ */
+
+ if (out == NULL || iobuf == NULL || iobuf->opaque == NULL)
+ return EOF;
+
+ the_dir = (open_directory_t *) iobuf->opaque;
+ dp = the_dir->dp;
+
+ /*
+ * Initialize errno, since readdir does not set it to zero on EOF.
+ */
+ errno = 0;
+ dirent = readdir(dp);
+ if (dirent == NULL) {
+ *errcode = errno; /* in case there was an error */
+ return EOF;
+ }
+
+ ino = get_inode(dirent, iobuf->name);
+
+#if __MINGW32__
+ len = sprintf(the_dir->buf, "%I64u", ino);
+#else
+ len = sprintf(the_dir->buf, "%llu", ino);
+#endif
+ the_dir->fw.fields[0].len = len;
+ len += (flen = sprintf(the_dir->buf + len, "/%s", dirent->d_name));
+ the_dir->fw.fields[1].len = flen-1;
+
+ ftstr = ftype(dirent, iobuf->name);
+ len += (flen = sprintf(the_dir->buf + len, "/%s", ftstr));
+ the_dir->fw.fields[2].len = flen-1;
+
+ *out = the_dir->buf;
+
+ *rt_start = NULL;
+ *rt_len = 0; /* set RT to "" */
+ if (field_width)
+ *field_width = & the_dir->fw;
+ return len;
+}
+
+/* dir_close --- close up when done */
+
+static void
+dir_close(awk_input_buf_t *iobuf)
+{
+ open_directory_t *the_dir;
+
+ if (iobuf == NULL || iobuf->opaque == NULL)
+ return;
+
+ the_dir = (open_directory_t *) iobuf->opaque;
+
+ closedir(the_dir->dp);
+ gawk_free(the_dir->buf);
+ gawk_free(the_dir);
+
+ iobuf->fd = -1;
+}
+
+/* dir_can_take_file --- return true if we want the file */
+
+static awk_bool_t
+dir_can_take_file(const awk_input_buf_t *iobuf)
+{
+ if (iobuf == NULL)
+ return awk_false;
+
+ return (iobuf->fd != INVALID_HANDLE && S_ISDIR(iobuf->sbuf.st_mode));
+}
+
+/*
+ * dir_take_control_of --- set up input parser.
+ * We can assume that dir_can_take_file just returned true,
+ * and no state has changed since then.
+ */
+
+static awk_bool_t
+dir_take_control_of(awk_input_buf_t *iobuf)
+{
+ DIR *dp;
+ open_directory_t *the_dir;
+ size_t size;
+
+ errno = 0;
+#ifdef HAVE_FDOPENDIR
+ dp = fdopendir(iobuf->fd);
+#else
+ dp = opendir(iobuf->name);
+ if (dp != NULL)
+ iobuf->fd = dirfd(dp);
+#endif
+ if (dp == NULL) {
+ warning(ext_id, _("dir_take_control_of: opendir/fdopendir failed: %s"),
+ strerror(errno));
+ update_ERRNO_int(errno);
+ return awk_false;
+ }
+
+ emalloc(the_dir, open_directory_t *, sizeof(open_directory_t), "dir_take_control_of");
+ the_dir->dp = dp;
+ /* pre-populate the field_width struct with constant values: */
+ the_dir->fw.use_chars = awk_false;
+ the_dir->fw.nf = 3;
+ the_dir->fw.fields[0].skip = 0; /* no leading space */
+ the_dir->fw.fields[1].skip = 1; /* single '/' separator */
+ the_dir->fw.fields[2].skip = 1; /* single '/' separator */
+ size = sizeof(struct dirent) + 21 /* max digits in inode */ + 2 /* slashes */;
+ emalloc(the_dir->buf, char *, size, "dir_take_control_of");
+
+ iobuf->opaque = the_dir;
+ iobuf->get_record = dir_get_record;
+ iobuf->close_func = dir_close;
+
+ return awk_true;
+}
+
+static awk_input_parser_t readdir_parser = {
+ "readdir",
+ dir_can_take_file,
+ dir_take_control_of,
+ NULL
+};
+
+#ifdef TEST_DUPLICATE
+static awk_input_parser_t readdir_parser2 = {
+ "readdir2",
+ dir_can_take_file,
+ dir_take_control_of,
+ NULL
+};
+#endif
+
+/* init_readdir --- set things ups */
+
+static awk_bool_t
+init_readdir()
+{
+ register_input_parser(& readdir_parser);
+#ifdef TEST_DUPLICATE
+ register_input_parser(& readdir_parser2);
+#endif
+
+ return awk_true;
+}
+
+static awk_ext_func_t func_table[] = {
+ { NULL, NULL, 0, 0, awk_false, NULL }
+};
+
+/* define the dl_load function using the boilerplate macro */
+
+dl_load_func(func_table, readdir, "")
diff --git a/extension/readfile.c b/extension/readfile.c
index b453da21..fb1a376b 100644
--- a/extension/readfile.c
+++ b/extension/readfile.c
@@ -142,7 +142,8 @@ done:
static int
readfile_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
- char **rt_start, size_t *rt_len)
+ char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **unused)
{
char *text;
diff --git a/extension/revtwoway.c b/extension/revtwoway.c
index ac4e22cf..84989bfc 100644
--- a/extension/revtwoway.c
+++ b/extension/revtwoway.c
@@ -133,7 +133,8 @@ close_two_proc_data(two_way_proc_data_t *proc_data)
static int
rev2way_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
- char **rt_start, size_t *rt_len)
+ char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **unused)
{
int len = 0; /* for now */
two_way_proc_data_t *proc_data;
diff --git a/field.c b/field.c
index 0799fb1b..a3be9773 100644
--- a/field.c
+++ b/field.c
@@ -38,8 +38,17 @@ is_blank(int c)
typedef void (* Setfunc)(long, char *, long, NODE *);
-static long (*parse_field)(long, char **, int, NODE *,
+/* is the API currently overriding the default parsing mechanism? */
+static bool api_parser_override = false;
+typedef long (*parse_field_func_t)(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
+static parse_field_func_t parse_field;
+/*
+ * N.B. The normal_parse_field function pointer contains the parse_field value
+ * that should be used except when API field parsing is overriding the default
+ * field parsing mechanism.
+ */
+static parse_field_func_t normal_parse_field;
static long re_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
static long def_parse_field(long, char **, int, NODE *,
@@ -50,6 +59,7 @@ static long sc_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
static long fw_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
+static const awk_fieldwidth_info_t *api_fw = NULL;
static long fpat_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
static void set_element(long num, char * str, long len, NODE *arr);
@@ -64,7 +74,7 @@ static bool resave_fs;
static NODE *save_FS; /* save current value of FS when line is read,
* to be used in deferred parsing
*/
-static int *FIELDWIDTHS = NULL;
+static awk_fieldwidth_info_t *FIELDWIDTHS = NULL;
NODE **fields_arr; /* array of pointers to the field nodes */
bool field0_valid; /* $(>0) has not been changed yet */
@@ -252,7 +262,7 @@ rebuild_record()
* but better correct than fast.
*/
void
-set_record(const char *buf, int cnt)
+set_record(const char *buf, int cnt, const awk_fieldwidth_info_t *fw)
{
NODE *n;
static char *databuf;
@@ -306,6 +316,19 @@ set_record(const char *buf, int cnt)
n->stfmt = STFMT_UNUSED;
n->flags = (STRING|STRCUR|USER_INPUT); /* do not set MALLOC */
fields_arr[0] = n;
+ if (fw != api_fw) {
+ if ((api_fw = fw) != NULL) {
+ if (! api_parser_override) {
+ api_parser_override = true;
+ parse_field = fw_parse_field;
+ update_PROCINFO_str("FS", "API");
+ }
+ } else if (api_parser_override) {
+ api_parser_override = false;
+ parse_field = normal_parse_field;
+ update_PROCINFO_str("FS", current_field_sep_str());
+ }
+ }
#undef INITIAL_SIZE
#undef MAX_SIZE
@@ -691,6 +714,31 @@ sc_parse_field(long up_to, /* parse only up to this field number */
}
/*
+ * calc_mbslen --- calculate the length in bytes of a multi-byte string
+ * containing len characters.
+ */
+
+static size_t
+calc_mbslen(char *scan, char *end, size_t len, mbstate_t *mbs)
+{
+
+ size_t mbclen;
+ char *mbscan = scan;
+
+ while (len-- > 0 && mbscan < end) {
+ mbclen = mbrlen(mbscan, end - mbscan, mbs);
+ if (!(mbclen > 0 && mbclen <= (size_t)(end - mbscan)))
+ /*
+ * We treat it as a singlebyte character. This should
+ * catch error codes 0, (size_t) -1, and (size_t) -2.
+ */
+ mbclen = 1;
+ mbscan += mbclen;
+ }
+ return mbscan - scan;
+}
+
+/*
* fw_parse_field --- field parsing using FIELDWIDTHS spec
*
* This is called from get_field() via (*parse_field)().
@@ -710,53 +758,53 @@ fw_parse_field(long up_to, /* parse only up to this field number */
char *scan = *buf;
long nf = parse_high_water;
char *end = scan + len;
- int nmbc;
- size_t mbclen;
- size_t mbslen;
- size_t lenrest;
- char *mbscan;
+ const awk_fieldwidth_info_t *fw;
mbstate_t mbs;
+ size_t skiplen;
+ size_t flen;
- memset(&mbs, 0, sizeof(mbstate_t));
+ fw = (api_parser_override ? api_fw : FIELDWIDTHS);
if (up_to == UNLIMITED)
nf = 0;
if (len == 0)
return nf;
- for (; nf < up_to && (len = FIELDWIDTHS[nf+1]) != -1; ) {
- if (gawk_mb_cur_max > 1) {
- nmbc = 0;
- mbslen = 0;
- mbscan = scan;
- lenrest = end - scan;
- while (nmbc < len && mbslen < lenrest) {
- mbclen = mbrlen(mbscan, end - mbscan, &mbs);
- if ( mbclen == 1
- || mbclen == (size_t) -1
- || mbclen == (size_t) -2
- || mbclen == 0) {
- /* We treat it as a singlebyte character. */
- mbclen = 1;
- }
- if (mbclen <= end - mbscan) {
- mbscan += mbclen;
- mbslen += mbclen;
- ++nmbc;
- }
- }
- (*set)(++nf, scan, (long) mbslen, n);
- scan += mbslen;
- } else {
- if (len > end - scan)
- len = end - scan;
- (*set)(++nf, scan, (long) len, n);
- scan += len;
+ if (gawk_mb_cur_max > 1 && fw->use_chars) {
+ /*
+ * Reset the shift state. Arguably, the shift state should
+ * be part of the file state and carried forward at all times,
+ * but nobody has complained so far, so this may not matter
+ * in practice.
+ */
+ memset(&mbs, 0, sizeof(mbstate_t));
+ while (nf < up_to) {
+ if (nf >= fw->nf) {
+ *buf = end;
+ return nf;
+ }
+ scan += calc_mbslen(scan, end, fw->fields[nf].skip, &mbs);
+ flen = calc_mbslen(scan, end, fw->fields[nf].len, &mbs);
+ (*set)(++nf, scan, (long) flen, n);
+ scan += flen;
+ }
+ } else {
+ while (nf < up_to) {
+ if (nf >= fw->nf) {
+ *buf = end;
+ return nf;
+ }
+ skiplen = fw->fields[nf].skip;
+ if (skiplen > end - scan)
+ skiplen = end - scan;
+ scan += skiplen;
+ flen = fw->fields[nf].len;
+ if (flen > end - scan)
+ flen = end - scan;
+ (*set)(++nf, scan, (long) flen, n);
+ scan += flen;
}
}
- if (len == -1)
- *buf = end;
- else
- *buf = scan;
+ *buf = scan;
return nf;
}
@@ -845,7 +893,7 @@ get_field(long requested, Func_ptr *assign)
if (parse_extent == fields_arr[0]->stptr + fields_arr[0]->stlen)
NF = parse_high_water;
else if (parse_field == fpat_parse_field) {
- /* FPAT parsing is wierd, isolate the special cases */
+ /* FPAT parsing is weird, isolate the special cases */
char *rec_start = fields_arr[0]->stptr;
char *rec_end = fields_arr[0]->stptr + fields_arr[0]->stlen;
@@ -1057,6 +1105,18 @@ do_patsplit(int nargs)
return tmp;
}
+/* set_parser --- update the current (non-API) parser */
+
+static void
+set_parser(parse_field_func_t func)
+{
+ normal_parse_field = func;
+ if (! api_parser_override && parse_field != func) {
+ parse_field = func;
+ update_PROCINFO_str("FS", current_field_sep_str());
+ }
+}
+
/* set_FIELDWIDTHS --- handle an assignment to FIELDWIDTHS */
void
@@ -1078,27 +1138,27 @@ set_FIELDWIDTHS()
return;
/*
- * If changing the way fields are split, obey least-suprise
+ * If changing the way fields are split, obey least-surprise
* semantics, and force $0 to be split totally.
*/
if (fields_arr != NULL)
(void) get_field(UNLIMITED - 1, 0);
- parse_field = fw_parse_field;
+ set_parser(fw_parse_field);
tmp = force_string(FIELDWIDTHS_node->var_value);
scan = tmp->stptr;
- if (FIELDWIDTHS == NULL)
- emalloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
- FIELDWIDTHS[0] = 0;
- for (i = 1; ; i++) {
+ if (FIELDWIDTHS == NULL) {
+ emalloc(FIELDWIDTHS, awk_fieldwidth_info_t *, awk_fieldwidth_info_size(fw_alloc), "set_FIELDWIDTHS");
+ FIELDWIDTHS->use_chars = awk_true;
+ }
+ FIELDWIDTHS->nf = 0;
+ for (i = 0; ; i++) {
unsigned long int tmp;
- if (i + 1 >= fw_alloc) {
+ if (i >= fw_alloc) {
fw_alloc *= 2;
- erealloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
+ erealloc(FIELDWIDTHS, awk_fieldwidth_info_t *, awk_fieldwidth_info_size(fw_alloc), "set_FIELDWIDTHS");
}
- /* Initialize value to be end of list */
- FIELDWIDTHS[i] = -1;
/* Ensure that there is no leading `-' sign. Otherwise,
strtoul would accept it and return a bogus result. */
while (is_blank(*scan)) {
@@ -1116,6 +1176,13 @@ set_FIELDWIDTHS()
or a value that is not in the range [1..INT_MAX]. */
errno = 0;
tmp = strtoul(scan, &end, 10);
+ if (errno == 0 && *end == ':' && (0 < tmp && tmp <= INT_MAX)) {
+ FIELDWIDTHS->fields[i].skip = tmp;
+ scan = end + 1;
+ tmp = strtoul(scan, &end, 10);
+ }
+ else
+ FIELDWIDTHS->fields[i].skip = 0;
if (errno != 0
|| (*end != '\0' && ! is_blank(*end))
|| !(0 < tmp && tmp <= INT_MAX)
@@ -1123,7 +1190,8 @@ set_FIELDWIDTHS()
fatal_error = true;
break;
}
- FIELDWIDTHS[i] = tmp;
+ FIELDWIDTHS->fields[i].len = tmp;
+ FIELDWIDTHS->nf = i+1;
scan = end;
/* Skip past any trailing blanks. */
while (is_blank(*scan)) {
@@ -1132,12 +1200,10 @@ set_FIELDWIDTHS()
if (*scan == '\0')
break;
}
- FIELDWIDTHS[i+1] = -1;
- update_PROCINFO_str("FS", "FIELDWIDTHS");
if (fatal_error)
- fatal(_("invalid FIELDWIDTHS value, near `%s'"),
- scan);
+ fatal(_("invalid FIELDWIDTHS value, for field %d, near `%s'"),
+ i, scan);
}
/* set_FS --- handle things when FS is assigned to */
@@ -1205,7 +1271,7 @@ choose_fs_function:
if (! do_traditional && fs->stlen == 0) {
static bool warned = false;
- parse_field = null_parse_field;
+ set_parser(null_parse_field);
if (do_lint && ! warned) {
warned = true;
@@ -1214,10 +1280,10 @@ choose_fs_function:
} else if (fs->stlen > 1) {
if (do_lint_old)
warning(_("old awk does not support regexps as value of `FS'"));
- parse_field = re_parse_field;
+ set_parser(re_parse_field);
} else if (RS_is_null) {
/* we know that fs->stlen <= 1 */
- parse_field = sc_parse_field;
+ set_parser(sc_parse_field);
if (fs->stlen == 1) {
if (fs->stptr[0] == ' ') {
default_FS = true;
@@ -1233,7 +1299,7 @@ choose_fs_function:
}
}
} else {
- parse_field = def_parse_field;
+ set_parser(def_parse_field);
if (fs->stlen == 1) {
if (fs->stptr[0] == ' ')
@@ -1242,7 +1308,7 @@ choose_fs_function:
/* same special case */
strcpy(buf, "[\\\\]");
else
- parse_field = sc_parse_field;
+ set_parser(sc_parse_field);
}
}
if (remake_re) {
@@ -1254,7 +1320,7 @@ choose_fs_function:
FS_re_yes_case = make_regexp(buf, strlen(buf), false, true, true);
FS_re_no_case = make_regexp(buf, strlen(buf), true, true, true);
FS_regexp = (IGNORECASE ? FS_re_no_case : FS_re_yes_case);
- parse_field = re_parse_field;
+ set_parser(re_parse_field);
} else if (parse_field == re_parse_field) {
FS_re_yes_case = make_regexp(fs->stptr, fs->stlen, false, true, true);
FS_re_no_case = make_regexp(fs->stptr, fs->stlen, true, true, true);
@@ -1270,16 +1336,16 @@ choose_fs_function:
*/
if (fs->stlen == 1 && parse_field == re_parse_field)
FS_regexp = FS_re_yes_case;
-
- update_PROCINFO_str("FS", "FS");
}
-/* current_field_sep --- return what field separator is */
+/* current_field_sep --- return the field separator type */
field_sep_type
current_field_sep()
{
- if (parse_field == fw_parse_field)
+ if (api_parser_override)
+ return Using_API;
+ else if (parse_field == fw_parse_field)
return Using_FIELDWIDTHS;
else if (parse_field == fpat_parse_field)
return Using_FPAT;
@@ -1287,6 +1353,21 @@ current_field_sep()
return Using_FS;
}
+/* current_field_sep_str --- return the field separator type as a string */
+
+const char *
+current_field_sep_str()
+{
+ if (api_parser_override)
+ return "API";
+ else if (parse_field == fw_parse_field)
+ return "FIELDWIDTHS";
+ else if (parse_field == fpat_parse_field)
+ return "FPAT";
+ else
+ return "FS";
+}
+
/* update_PROCINFO_str --- update PROCINFO[sub] with string value */
void
@@ -1373,7 +1454,7 @@ set_FPAT()
set_fpat_function:
fpat = force_string(FPAT_node->var_value);
- parse_field = fpat_parse_field;
+ set_parser(fpat_parse_field);
if (remake_re) {
refree(FPAT_re_yes_case);
@@ -1384,8 +1465,6 @@ set_fpat_function:
FPAT_re_no_case = make_regexp(fpat->stptr, fpat->stlen, true, true, true);
FPAT_regexp = (IGNORECASE ? FPAT_re_no_case : FPAT_re_yes_case);
}
-
- update_PROCINFO_str("FS", "FPAT");
}
/*
diff --git a/gawkapi.h b/gawkapi.h
index 5071adce..484ab27e 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -117,6 +117,32 @@ typedef enum awk_bool {
awk_true
} awk_bool_t; /* we don't use <stdbool.h> on purpose */
+/*
+ * If the input parser would like to specify the field positions in the input
+ * record, it may populate an awk_fieldwidth_info_t structure to indicate
+ * the location of each field. The use_chars boolean controls whether the
+ * field lengths are specified in terms of bytes or potentially multi-byte
+ * characters. Performance will be better if the values are supplied in
+ * terms of bytes. The fields[0].skip value indicates how many bytes (or
+ * characters) to skip before $1, and fields[0].len is the length of $1, etc.
+ */
+
+typedef struct {
+ awk_bool_t use_chars; /* false ==> use bytes */
+ size_t nf;
+ struct awk_field_info {
+ size_t skip; /* amount to skip before field starts */
+ size_t len; /* length of field */
+ } fields[1]; /* actual dimension should be nf */
+} awk_fieldwidth_info_t;
+
+/*
+ * This macro calculates the total struct size needed. This is useful when
+ * calling malloc or realloc.
+ */
+#define awk_fieldwidth_info_size(NF) (sizeof(awk_fieldwidth_info_t) + \
+ (((NF)-1) * sizeof(struct awk_field_info)))
+
/* The information about input files that input parsers need to know: */
typedef struct awk_input {
const char *name; /* filename */
@@ -146,9 +172,19 @@ typedef struct awk_input {
* than zero, gawk will automatically update the ERRNO variable based
* on the value of *errcode (e.g., setting *errcode = errno should do
* the right thing).
+ *
+ * If field_width is non-NULL, then *field_width will be initialized
+ * to NULL, and the function may set it to point to a structure
+ * supplying field width information to override the default
+ * gawk field parsing mechanism. Note that this structure will not
+ * be copied by gawk; it must persist at least until the next call
+ * to get_record or close_func. Note also that field_width will
+ * be NULL when getline is assigning the results to a variable, thus
+ * field parsing is not needed.
*/
int (*get_record)(char **out, struct awk_input *iobuf, int *errcode,
- char **rt_start, size_t *rt_len);
+ char **rt_start, size_t *rt_len,
+ const awk_fieldwidth_info_t **field_width);
/*
* No argument prototype on read_func to allow for older systems
diff --git a/io.c b/io.c
index f854ec5a..a784e02d 100644
--- a/io.c
+++ b/io.c
@@ -287,7 +287,7 @@ static RECVALUE rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
static RECVALUE (*matchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = rs1scan;
-static int get_a_record(char **out, IOBUF *iop, int *errcode);
+static int get_a_record(char **out, IOBUF *iop, int *errcode, const awk_fieldwidth_info_t **field_width);
static void free_rp(struct redirect *rp);
@@ -590,13 +590,14 @@ inrec(IOBUF *iop, int *errcode)
char *begin;
int cnt;
bool retval = true;
+ const awk_fieldwidth_info_t *field_width = NULL;
if (at_eof(iop) && no_data_left(iop))
cnt = EOF;
else if ((iop->flag & IOP_CLOSED) != 0)
cnt = EOF;
else
- cnt = get_a_record(& begin, iop, errcode);
+ cnt = get_a_record(& begin, iop, errcode, & field_width);
/* Note that get_a_record may return -2 when I/O would block */
if (cnt < 0) {
@@ -604,7 +605,7 @@ inrec(IOBUF *iop, int *errcode)
} else {
INCREMENT_REC(NR);
INCREMENT_REC(FNR);
- set_record(begin, cnt);
+ set_record(begin, cnt, field_width);
if (*errcode > 0)
retval = false;
}
@@ -2658,6 +2659,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
NODE *redir_exp = NULL;
NODE **lhs = NULL;
int redir_error = 0;
+ const awk_fieldwidth_info_t *field_width = NULL;
if (into_variable)
lhs = POP_ADDRESS();
@@ -2686,7 +2688,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
return make_number((AWKNUM) 0.0);
errcode = 0;
- cnt = get_a_record(& s, iop, & errcode);
+ cnt = get_a_record(& s, iop, & errcode, (lhs ? NULL : & field_width));
if (errcode != 0) {
if (! do_traditional && (errcode != -1))
update_ERRNO_int(errcode);
@@ -2708,7 +2710,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
}
if (lhs == NULL) /* no optional var. */
- set_record(s, cnt);
+ set_record(s, cnt, field_width);
else { /* assignment to variable */
unref(*lhs);
*lhs = make_string(s, cnt);
@@ -2726,6 +2728,7 @@ do_getline(int into_variable, IOBUF *iop)
int cnt = EOF;
char *s = NULL;
int errcode;
+ const awk_fieldwidth_info_t *field_width = NULL;
if (iop == NULL) { /* end of input */
if (into_variable)
@@ -2734,7 +2737,7 @@ do_getline(int into_variable, IOBUF *iop)
}
errcode = 0;
- cnt = get_a_record(& s, iop, & errcode);
+ cnt = get_a_record(& s, iop, & errcode, (into_variable ? NULL : & field_width));
if (errcode != 0) {
if (! do_traditional && (errcode != -1))
update_ERRNO_int(errcode);
@@ -2749,7 +2752,7 @@ do_getline(int into_variable, IOBUF *iop)
INCREMENT_REC(FNR);
if (! into_variable) /* no optional var. */
- set_record(s, cnt);
+ set_record(s, cnt, field_width);
else { /* assignment to variable */
NODE **lhs;
lhs = POP_ADDRESS();
@@ -3693,7 +3696,9 @@ errno_io_retry(void)
static int
get_a_record(char **out, /* pointer to pointer to data */
IOBUF *iop, /* input IOP */
- int *errcode) /* pointer to error variable */
+ int *errcode, /* pointer to error variable */
+ const awk_fieldwidth_info_t **field_width)
+ /* pointer to pointer to field_width info */
{
struct recmatch recm;
SCANSTATE state;
@@ -3712,7 +3717,8 @@ get_a_record(char **out, /* pointer to pointer to data */
char *rt_start;
size_t rt_len;
int rc = iop->public.get_record(out, &iop->public, errcode,
- &rt_start, &rt_len);
+ &rt_start, &rt_len,
+ field_width);
if (rc == EOF)
iop->flag |= IOP_AT_EOF;
else {
diff --git a/main.c b/main.c
index b6841d57..195684c4 100644
--- a/main.c
+++ b/main.c
@@ -1015,22 +1015,7 @@ load_procinfo()
value = getegid();
update_PROCINFO_num("egid", value);
- switch (current_field_sep()) {
- case Using_FIELDWIDTHS:
- update_PROCINFO_str("FS", "FIELDWIDTHS");
- break;
- case Using_FPAT:
- update_PROCINFO_str("FS", "FPAT");
- break;
- case Using_FS:
- update_PROCINFO_str("FS", "FS");
- break;
- default:
- fatal(_("unknown value for field spec: %d\n"),
- current_field_sep());
- break;
- }
-
+ update_PROCINFO_str("FS", current_field_sep_str());
#if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
for (i = 0; i < ngroups; i++) {
diff --git a/test/ChangeLog b/test/ChangeLog
index df0ed8fa..d684e73a 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,14 @@
+2017-03-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * fwtest4: Renamed from fwtest3.
+ * fwtest3: Renamed from fwtest2b.
+ * Makefile.am: Updated.
+
+2017-03-21 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (fwtest2b): Add new test of enhanced FIELDWIDTHS syntax.
+ * fwtest2b.awk, fwtest2b.ok: New files.
+
2017-03-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am (argarray): Always copy argarray.in to the local
@@ -5,6 +16,13 @@
$(srcdir) is the current directory.
* argarray.ok: Replace argarray.in with argarray.input.
+2017-03-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (readdir_test): New test to check whether get_record
+ field_width parsing is working by comparing the results from the
+ readdir and readdir_test extensions.
+ (SHLIB_TESTS): Add readdir_test.
+
2017-02-21 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am (mktime): New test.
diff --git a/test/Makefile.am b/test/Makefile.am
index a356d63b..b1a97621 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -386,8 +386,10 @@ EXTRA_DIST = \
fwtest2.in \
fwtest2.ok \
fwtest3.awk \
- fwtest3.in \
fwtest3.ok \
+ fwtest4.awk \
+ fwtest4.in \
+ fwtest4.ok \
genpot.awk \
genpot.ok \
gensub.awk \
@@ -1221,7 +1223,7 @@ GAWK_EXT_TESTS = \
crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \
devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \
- functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
+ functab1 functab2 functab3 fwtest fwtest2 fwtest3 fwtest4 \
genpot gensub gensub2 gensub3 getlndir gnuops2 gnuops3 gnureops gsubind \
icasefs icasers id igncdym igncfs ignrcas2 ignrcas4 ignrcase \
incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \
@@ -1263,7 +1265,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
apiterm fnmatch filefuncs fork fork2 fts functab4 getfile inplace1 inplace2 inplace3 \
- ordchr ordchr2 readdir readfile readfile2 revout revtwoway rwarray testext time
+ ordchr ordchr2 readdir readdir_test readfile readfile2 revout revtwoway rwarray testext time
# List of the tests which should be run with --lint option:
NEED_LINT = \
@@ -2187,6 +2189,12 @@ readdir:
-v dirlist=_dirlist -v longlist=_longlist > $@.ok
@-$(CMP) $@.ok _$@ && rm -f $@.ok _$@ _dirlist _longlist
+readdir_test:
+ @echo $@
+ @$(AWK) -lreaddir -F/ '{printf "[%s] [%s] [%s] [%s]\n", $$1, $$2, $$3, $$4}' "$(top_srcdir)" > $@.ok
+ @$(AWK) -lreaddir_test '{printf "[%s] [%s] [%s] [%s]\n", $$1, $$2, $$3, $$4}' "$(top_srcdir)" > _$@
+ @-$(CMP) $@.ok _$@ && rm -f $@.ok _$@
+
fts:
@case `uname` in \
IRIX) \
@@ -2367,6 +2375,11 @@ arrdbg:
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok
# @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok || exit 0
+fwtest3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/fwtest2.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
# Targets generated for other tests:
include Maketests
diff --git a/test/Makefile.in b/test/Makefile.in
index 8719840b..57f5bf61 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -644,8 +644,10 @@ EXTRA_DIST = \
fwtest2.in \
fwtest2.ok \
fwtest3.awk \
- fwtest3.in \
fwtest3.ok \
+ fwtest4.awk \
+ fwtest4.in \
+ fwtest4.ok \
genpot.awk \
genpot.ok \
gensub.awk \
@@ -1478,7 +1480,7 @@ GAWK_EXT_TESTS = \
crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \
devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \
- functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
+ functab1 functab2 functab3 fwtest fwtest2 fwtest3 fwtest4 \
genpot gensub gensub2 gensub3 getlndir gnuops2 gnuops3 gnureops gsubind \
icasefs icasers id igncdym igncfs ignrcas2 ignrcas4 ignrcase \
incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \
@@ -1516,7 +1518,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
apiterm fnmatch filefuncs fork fork2 fts functab4 getfile inplace1 inplace2 inplace3 \
- ordchr ordchr2 readdir readfile readfile2 revout revtwoway rwarray testext time
+ ordchr ordchr2 readdir readdir_test readfile readfile2 revout revtwoway rwarray testext time
# List of the tests which should be run with --lint option:
@@ -2626,6 +2628,12 @@ readdir:
-v dirlist=_dirlist -v longlist=_longlist > $@.ok
@-$(CMP) $@.ok _$@ && rm -f $@.ok _$@ _dirlist _longlist
+readdir_test:
+ @echo $@
+ @$(AWK) -lreaddir -F/ '{printf "[%s] [%s] [%s] [%s]\n", $$1, $$2, $$3, $$4}' "$(top_srcdir)" > $@.ok
+ @$(AWK) -lreaddir_test '{printf "[%s] [%s] [%s] [%s]\n", $$1, $$2, $$3, $$4}' "$(top_srcdir)" > _$@
+ @-$(CMP) $@.ok _$@ && rm -f $@.ok _$@
+
fts:
@case `uname` in \
IRIX) \
@@ -2803,6 +2811,12 @@ arrdbg:
@echo $@
@$(AWK) -v "okfile=$(srcdir)/$@.ok" -f "$(srcdir)"/$@.awk | grep array_f >_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok
+# @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok || exit 0
+
+fwtest3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/fwtest2.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
Gt-dummy:
# file Maketests, generated from Makefile.am by the Gentests program
addcomma:
@@ -3982,7 +3996,7 @@ fwtest2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-fwtest3:
+fwtest4:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@@ -4457,7 +4471,6 @@ time:
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
# end of file Maketests
-# @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok || exit 0
# Targets generated for other tests:
diff --git a/test/Maketests b/test/Maketests
index d9183c0a..9ff8ef90 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1177,7 +1177,7 @@ fwtest2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-fwtest3:
+fwtest4:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
diff --git a/test/fwtest3.awk b/test/fwtest3.awk
index d1384eaf..5e96c1aa 100644
--- a/test/fwtest3.awk
+++ b/test/fwtest3.awk
@@ -1 +1,6 @@
-BEGIN { FIELDWIDTHS="5" } { print $1 }
+BEGIN {
+ FIELDWIDTHS = "2:13 2:13 2:13";
+}
+{
+ printf "%s|%s|%s\n", $1, $2, $3
+}
diff --git a/test/fwtest3.ok b/test/fwtest3.ok
index e56e15bb..f4d28232 100644
--- a/test/fwtest3.ok
+++ b/test/fwtest3.ok
@@ -1 +1,12 @@
-12345
+ 0.4867373206| 1.3206333033|-0.2333178127
+ 0.5668176165| 1.3711756314|-0.2193558040
+ 0.4325251781| 1.3399488722|-0.1568307497
+ 0.4900487563| 1.3295759570|-0.2217392402
+-0.6790064191| 1.2536623801|-0.2955415433
+-0.6311440220| 1.2966579993|-0.2246692210
+-0.7209390351| 1.1783407099|-0.2539408209
+-0.6782473356| 1.2495242556|-0.2811436366
+-0.7062054082| 1.1223820964|-1.1619805834
+-0.6491590119| 1.1248946162|-1.0851579675
+-0.7948856821| 1.1208852325|-1.1259821556
+-0.7102549262| 1.1225121126|-1.1475381286
diff --git a/test/fwtest4.awk b/test/fwtest4.awk
new file mode 100644
index 00000000..d1384eaf
--- /dev/null
+++ b/test/fwtest4.awk
@@ -0,0 +1 @@
+BEGIN { FIELDWIDTHS="5" } { print $1 }
diff --git a/test/fwtest3.in b/test/fwtest4.in
index a32a4347..a32a4347 100644
--- a/test/fwtest3.in
+++ b/test/fwtest4.in
diff --git a/test/fwtest4.ok b/test/fwtest4.ok
new file mode 100644
index 00000000..e56e15bb
--- /dev/null
+++ b/test/fwtest4.ok
@@ -0,0 +1 @@
+12345