aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2013-01-08 20:56:33 -0500
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2013-01-08 20:56:33 -0500
commit1abfe5e82822a9e81a3bd1df2e7747afbc0ae1b9 (patch)
tree2deac40bf78a9acbb4d777f5f4520fd5731df5e5
parent155fc0deca8d8976915fdc5edc84c4c6a1af652b (diff)
downloadegawk-1abfe5e82822a9e81a3bd1df2e7747afbc0ae1b9.tar.gz
egawk-1abfe5e82822a9e81a3bd1df2e7747afbc0ae1b9.tar.bz2
egawk-1abfe5e82822a9e81a3bd1df2e7747afbc0ae1b9.zip
Add inplace file editing extension.
-rw-r--r--awklib/ChangeLog4
-rw-r--r--awklib/eg/lib/inplace.awk14
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/gawk.info1144
-rw-r--r--doc/gawk.texi57
-rw-r--r--extension/ChangeLog5
-rw-r--r--extension/Makefile.am5
-rw-r--r--extension/Makefile.in29
-rw-r--r--extension/inplace.c241
9 files changed, 947 insertions, 556 deletions
diff --git a/awklib/ChangeLog b/awklib/ChangeLog
index 98bdc3dc..1b6a31e6 100644
--- a/awklib/ChangeLog
+++ b/awklib/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-08 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * eg/lib/inplace.awk: Add new file generated from doc/gawk.texi.
+
2012-12-24 Arnold D. Robbins <arnold@skeeve.com>
* 4.0.2: Release tar ball made.
diff --git a/awklib/eg/lib/inplace.awk b/awklib/eg/lib/inplace.awk
new file mode 100644
index 00000000..a090d9e0
--- /dev/null
+++ b/awklib/eg/lib/inplace.awk
@@ -0,0 +1,14 @@
+# inplace --- load and invoke the inplace extension.
+
+@load "inplace"
+
+# Please set INPLACE_SUFFIX to make a backup copy. For example,
+# you may want to set INPLACE_SUFFIX to .bak on the command-line or in a
+# BEGIN block.
+
+BEGINFILE {
+ inplace_begin(FILENAME, INPLACE_SUFFIX)
+}
+ENDFILE {
+ inplace_end(FILENAME, INPLACE_SUFFIX)
+}
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 09beb1e4..6f141ad6 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-08 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawk.texi: Add documentation for new inplace extension.
+
2013-01-08 Arnold D. Robbins <arnold@skeeve.com>
* gawk.texi, awkcard.in: Sync what mawk has. Main point of
diff --git a/doc/gawk.info b/doc/gawk.info
index 82ff0c46..32971266 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -557,6 +557,7 @@ texts being (a) (see below), and with the Back-Cover Texts being (b)
* Extension Sample Fnmatch:: An interface to `fnmatch()'.
* Extension Sample Fork:: An interface to `fork()' and
other process functions.
+* Extension Sample Inplace:: Enabling in-place file editing.
* Extension Sample Ord:: Character to value to character
conversions.
* Extension Sample Readdir:: An interface to `readdir()'.
@@ -3527,7 +3528,7 @@ Class Meaning
`[:upper:]' Uppercase alphabetic characters.
`[:xdigit:]'Characters that are hexadecimal digits.
-Table 3.1: POSIX Character Classes
+Table 3.1: POSIX Character Classes
For example, before the POSIX standard, you had to write
`/[A-Za-z0-9]/' to match alphanumeric characters. If your character
@@ -5515,7 +5516,7 @@ COMMAND `|& getline' Sets `$0' and `NF' Extension
COMMAND `|& getline' Sets VAR Extension
VAR
-Table 4.1: `getline' Variants and What They Set
+Table 4.1: `getline' Variants and What They Set

File: gawk.info, Node: Read Timeout, Next: Command line directories, Prev: Getline, Up: Reading Files
@@ -7183,7 +7184,7 @@ Feature Default `--posix' or `--use-lc-numeric'
Input Use period Use locale
`strtonum()'Use period Use locale
-Table 6.1: Locale Decimal Point versus A Period
+Table 6.1: Locale Decimal Point versus A Period
Finally, modern day formal standards and IEEE standard floating point
representation can have an unusual but important effect on the way
@@ -7525,7 +7526,7 @@ LVALUE `%=' MODULUS Sets LVALUE to its remainder by MODULUS.
LVALUE `^=' POWER
LVALUE `**=' POWER Raises LVALUE to the power POWER. (c.e.)
-Table 6.2: Arithmetic Assignment Operators
+Table 6.2: Arithmetic Assignment Operators
NOTE: Only the `^=' operator is specified by POSIX. For maximum
portability, do not use the `**=' operator.
@@ -7830,7 +7831,7 @@ X `!~' Y True if the string X does not match the regexp
SUBSCRIPT `in' True if the array ARRAY has an element with the
ARRAY subscript SUBSCRIPT.
-Table 6.3: Relational Operators
+Table 6.3: Relational Operators
Comparison expressions have the value one if true and zero if false.
When comparing operands of mixed types, numeric operands are converted
@@ -11747,7 +11748,7 @@ is illustrated in *note table-sub-escapes::.
`\\\\\\&' `\\\&' a literal `\\&'
`\\q' `\q' a literal `\q'
-Table 9.1: Historical Escape Sequence Processing for `sub()' and
+Table 9.1: Historical Escape Sequence Processing for `sub()' and
`gsub()'
This table shows both the lexical-level processing, where an odd number
@@ -11772,7 +11773,7 @@ literally. The interpretation of `\' and `&' then becomes as shown in
`\\\\&' `\\&' a literal `\', then the matched text
`\\\\\\&' `\\\&' a literal `\&'
-Table 9.2: 1992 POSIX Rules for `sub()' and `gsub()' Escape Sequence
+Table 9.2: 1992 POSIX Rules for `sub()' and `gsub()' Escape Sequence
Processing
This appears to solve the problem. Unfortunately, the phrasing of the
@@ -11802,7 +11803,7 @@ table-sub-proposed::.
`\\q' `\q' a literal `\q'
`\\\\' `\\' `\\'
-Table 9.3: Proposed Rules For `sub()' And Backslash
+Table 9.3: Proposed Rules For `sub()' And Backslash
In a nutshell, at the runtime level, there are now three special
sequences of characters (`\\\&', `\\&' and `\&') whereas historically
@@ -11829,7 +11830,7 @@ rules are presented in *note table-posix-sub::.
`\\q' `\q' a literal `\q'
`\\\\' `\\' `\'
-Table 9.4: POSIX Rules For `sub()' And `gsub()'
+Table 9.4: POSIX Rules For `sub()' And `gsub()'
The only case where the difference is noticeable is the last one:
`\\\\' is seen as `\\' and produces `\' instead of `\\'.
@@ -11861,7 +11862,7 @@ the `\' does not, as shown in *note table-gensub-escapes::.
`\\\\\\&' `\\\&' a literal `\&'
`\\q' `\q' a literal `q'
-Table 9.5: Escape Sequence Processing For `gensub()'
+Table 9.5: Escape Sequence Processing For `gensub()'
Because of the complexity of the lexical and runtime level processing
and the special cases for `sub()' and `gsub()', we recommend the use of
@@ -12420,7 +12421,7 @@ table-bitwise-ops::.
0 | 0 0 | 0 1 | 0 1
1 | 0 1 | 1 1 | 1 0
-Table 9.6: Bitwise Operations
+Table 9.6: Bitwise Operations
As you can see, the result of an AND operation is 1 only when _both_
bits are 1. The result of an OR operation is 1 if _either_ bit is 1.
@@ -20864,7 +20865,7 @@ Single 32 24 -126 +127
Double 64 53 -1022 +1023
Quadruple 128 113 -16382 +16383
-Table 15.1: Basic IEEE Format Context Values
+Table 15.1: Basic IEEE Format Context Values
NOTE: The precision numbers include the implied leading one that
gives them one extra bit of significand.
@@ -20906,7 +20907,7 @@ Round toward zero `roundTowardZero'
Round to nearest, ties away `roundTiesToAway'
from zero
-Table 15.2: IEEE 754 Rounding Modes
+Table 15.2: IEEE 754 Rounding Modes
The default mode `roundTiesToEven' is the most preferred, but the
least intuitive. This method does the obvious thing for most values, by
@@ -21138,10 +21139,10 @@ Round toward zero `roundTowardZero' `"Z"' or `"z"'
Round to nearest, ties away `roundTiesToAway' `"A"' or `"a"'
from zero
-Table 15.3: `gawk' Rounding Modes
+Table 15.3: `gawk' Rounding Modes
`ROUNDMODE' has the default value `"N"', which selects the IEEE-754
-rounding mode `roundTiesToEven'. *note Table 15.3:
+rounding mode `roundTiesToEven'. *note Table 15.3:
table-gawk-rounding-modes, lists `"A"' to select the IEEE-754 mode
`roundTiesToAway'. This is only available if your version of the MPFR
library supports it; otherwise setting `ROUNDMODE' to this value has no
@@ -21478,7 +21479,7 @@ fields are function pointers. This is shown in *note load-extension::.
+-------+-+---+-+---+-+------------------+--------------------+
gawk Main Program Address Space Extension
-Figure 16.1: Loading The Extension
+Figure 16.1: Loading The Extension
The extension can call functions inside `gawk' through these
function pointers, at runtime, without needing (link-time) access to
@@ -21498,7 +21499,7 @@ load-new-function::.
+-------+-+---+-+---+-+------------------+--------------+-+---+
gawk Main Program Address Space Extension
-Figure 16.2: Loading The New Function
+Figure 16.2: Loading The New Function
In the other direction, the extension registers its new functions
with `gawk' by passing function pointers to the functions that provide
@@ -21519,7 +21520,7 @@ calling convention. This is shown in *note call-new-function::.
+-------+-+---+-+---+-+------------------+--------------+-+---+
gawk Main Program Address Space Extension
-Figure 16.3: Calling The New Function
+Figure 16.3: Calling The New Function
The `do_XXX()' function, in turn, then uses the function pointers in
the API `struct' to do its work, such as updating variables or arrays,
@@ -21875,7 +21876,7 @@ Requested: Scalar Scalar Scalar false false
Value false false false false
Cookie
-Table 16.1: Value Types Returned
+Table 16.1: Value Types Returned

File: gawk.info, Node: Constructor Functions, Next: Registration Functions, Prev: Requesting Values, Up: Extension API Description
@@ -22510,7 +22511,7 @@ your extension function. They are:
Fill in the `awk_value_t' structure pointed to by `result' with
the `count''th argument. Return true if the actual type matches
`wanted', false otherwise. In the latter case, `result->val_type'
- indicates the actual type (*note Table 16.1:
+ indicates the actual type (*note Table 16.1:
table-value-types-returned.). Counts are zero based--the first
argument is numbered zero, the second one, and so on. `wanted'
indicates the type of value expected.
@@ -22556,7 +22557,7 @@ termed a "symbol table".
regular C string. `wanted' indicates the type of value expected.
Return true if the actual type matches `wanted', false otherwise
In the latter case, `result->val_type' indicates the actual type
- (*note Table 16.1: table-value-types-returned.).
+ (*note Table 16.1: table-value-types-returned.).
`awk_bool_t sym_update(const char *name, awk_value_t *value);'
Update the variable named by the string `name', which is a regular
@@ -22891,7 +22892,7 @@ The following functions relate to individual array elements.
value of the element whose index is `index'. `wanted' specifies
the type of value you wish to retrieve. Return false if `wanted'
does not match the actual type or if `index' is not in the array
- (*note Table 16.1: table-value-types-returned.).
+ (*note Table 16.1: table-value-types-returned.).
The value for `index' can be numeric, in which case `gawk'
converts it to a string. Using non-integral values is possible, but
@@ -24057,8 +24058,9 @@ File: gawk.info, Node: Extension Samples, Next: gawkextlib, Prev: Extension E
This minor node provides brief overviews of the sample extensions that
come in the `gawk' distribution. Some of them are intended for
-production use, such the `filefuncs' and `readdir' extensions. Others
-mainly provide example code that shows how to use the extension API.
+production use, such the `filefuncs', `readdir' and `inplace'
+extensions. Others mainly provide example code that shows how to use
+the extension API.
* Menu:
@@ -24066,6 +24068,7 @@ mainly provide example code that shows how to use the extension API.
* Extension Sample Fnmatch:: An interface to `fnmatch()'.
* Extension Sample Fork:: An interface to `fork()' and other
process functions.
+* Extension Sample Inplace:: Enabling in-place file editing.
* Extension Sample Ord:: Character to value to character
conversions.
* Extension Sample Readdir:: An interface to `readdir()'.
@@ -24319,7 +24322,7 @@ occurred.
print "no match"

-File: gawk.info, Node: Extension Sample Fork, Next: Extension Sample Ord, Prev: Extension Sample Fnmatch, Up: Extension Samples
+File: gawk.info, Node: Extension Sample Fork, Next: Extension Sample Inplace, Prev: Extension Sample Fnmatch, Up: Extension Samples
16.6.3 Interface To `fork()', `wait()' and `waitpid()'
------------------------------------------------------
@@ -24356,9 +24359,55 @@ The `fork' extension adds three functions, as follows.
print "hello from the parent"

-File: gawk.info, Node: Extension Sample Ord, Next: Extension Sample Readdir, Prev: Extension Sample Fork, Up: Extension Samples
+File: gawk.info, Node: Extension Sample Inplace, Next: Extension Sample Ord, Prev: Extension Sample Fork, Up: Extension Samples
-16.6.4 Character and Numeric values: `ord()' and `chr()'
+16.6.4 Enabling in-place file editing.
+--------------------------------------
+
+The `inplace' extension emulates the `sed' `-i' option. It uses the
+bundled `inplace.awk' include file to invoke the extension properly:
+
+ # inplace --- load and invoke the inplace extension.
+
+ @load "inplace"
+
+ # Please set INPLACE_SUFFIX to make a backup copy. For example,
+ # you may want to set INPLACE_SUFFIX to .bak on the command-line or in a
+ # BEGIN block.
+
+ BEGINFILE {
+ inplace_begin(FILENAME, INPLACE_SUFFIX)
+ }
+ ENDFILE {
+ inplace_end(FILENAME, INPLACE_SUFFIX)
+ }
+
+ For each regular file that is processed, the extension redirects
+stdout to a temporary file configured to have the same owner and
+permissions. After the file has been processed, stdout is restored to
+its default destination. If `INPLACE_SUFFIX' is not an empty string,
+the original file will be linked to a backup filename created by
+appending that suffix. Finally, the temporary file is renamed to the
+original filename.
+
+ If any error is encountered, the extension issues a fatal error to
+terminate processing immediately without damaging the original file.
+
+ Here are a couple of simple examples:
+
+ $ gawk -i inplace '{gsub(/foo/, "bar")} {print}' file1 file2 file3
+
+ To keep a backup copy of the original files, try this:
+
+ $ gawk -i inplace -vINPLACE_SUFFIX=.bak '{gsub(/foo/, "bar")} {print}' file1 file2 file3
+
+ It is left as an exercise to write a wrapper script that presents an
+interface similar to the `sed' `-i' option.
+
+
+File: gawk.info, Node: Extension Sample Ord, Next: Extension Sample Readdir, Prev: Extension Sample Inplace, Up: Extension Samples
+
+16.6.5 Character and Numeric values: `ord()' and `chr()'
--------------------------------------------------------
The `ordchr' extension adds two functions, named `ord()' and `chr()',
@@ -24382,7 +24431,7 @@ same name. Here is an example:

File: gawk.info, Node: Extension Sample Readdir, Next: Extension Sample Revout, Prev: Extension Sample Ord, Up: Extension Samples
-16.6.5 Reading Directories
+16.6.6 Reading Directories
--------------------------
The `readdir' extension adds an input parser for directories. The
@@ -24430,7 +24479,7 @@ always `u'.

File: gawk.info, Node: Extension Sample Revout, Next: Extension Sample Rev2way, Prev: Extension Sample Readdir, Up: Extension Samples
-16.6.6 Reversing Output
+16.6.7 Reversing Output
-----------------------
The `revoutput' extension adds a simple output wrapper that reverses
@@ -24450,7 +24499,7 @@ unwary. Here is an example:

File: gawk.info, Node: Extension Sample Rev2way, Next: Extension Sample Read write array, Prev: Extension Sample Revout, Up: Extension Samples
-16.6.7 Two-Way I/O Example
+16.6.8 Two-Way I/O Example
--------------------------
The `revtwoway' extension adds a simple two-way processor that reverses
@@ -24472,7 +24521,7 @@ example shows how to use it:

File: gawk.info, Node: Extension Sample Read write array, Next: Extension Sample Readfile, Prev: Extension Sample Rev2way, Up: Extension Samples
-16.6.8 Dumping and Restoring An Array
+16.6.9 Dumping and Restoring An Array
-------------------------------------
The `rwarray' extension adds two functions, named `writea()' and
@@ -24516,8 +24565,8 @@ restored on systems with a different one, but this has not been tried.

File: gawk.info, Node: Extension Sample Readfile, Next: Extension Sample API Tests, Prev: Extension Sample Read write array, Up: Extension Samples
-16.6.9 Reading An Entire File
------------------------------
+16.6.10 Reading An Entire File
+------------------------------
The `readfile' extension adds a single function named `readfile()':
@@ -24539,7 +24588,7 @@ The `readfile' extension adds a single function named `readfile()':

File: gawk.info, Node: Extension Sample API Tests, Next: Extension Sample Time, Prev: Extension Sample Readfile, Up: Extension Samples
-16.6.10 API Tests
+16.6.11 API Tests
-----------------
The `testext' extension exercises parts of the extension API that are
@@ -24551,7 +24600,7 @@ code and runs the tests. See the source file for more information.

File: gawk.info, Node: Extension Sample Time, Prev: Extension Sample API Tests, Up: Extension Samples
-16.6.11 Extension Time Functions
+16.6.12 Extension Time Functions
--------------------------------
These functions can be used by either invoking `gawk' with a
@@ -31859,517 +31908,518 @@ Index

Tag Table:
Node: Top1358
-Node: Foreword40229
-Node: Preface44574
-Ref: Preface-Footnote-147627
-Ref: Preface-Footnote-247733
-Node: History47965
-Node: Names50356
-Ref: Names-Footnote-151833
-Node: This Manual51905
-Ref: This Manual-Footnote-157811
-Node: Conventions57911
-Node: Manual History60045
-Ref: Manual History-Footnote-163315
-Ref: Manual History-Footnote-263356
-Node: How To Contribute63430
-Node: Acknowledgments64574
-Node: Getting Started69070
-Node: Running gawk71449
-Node: One-shot72635
-Node: Read Terminal73860
-Ref: Read Terminal-Footnote-175510
-Ref: Read Terminal-Footnote-275786
-Node: Long75957
-Node: Executable Scripts77333
-Ref: Executable Scripts-Footnote-179202
-Ref: Executable Scripts-Footnote-279304
-Node: Comments79851
-Node: Quoting82318
-Node: DOS Quoting86941
-Node: Sample Data Files87616
-Node: Very Simple90648
-Node: Two Rules95247
-Node: More Complex97394
-Ref: More Complex-Footnote-1100324
-Node: Statements/Lines100409
-Ref: Statements/Lines-Footnote-1104871
-Node: Other Features105136
-Node: When106064
-Node: Invoking Gawk108211
-Node: Command Line109672
-Node: Options110455
-Ref: Options-Footnote-1125853
-Node: Other Arguments125878
-Node: Naming Standard Input128536
-Node: Environment Variables129630
-Node: AWKPATH Variable130188
-Ref: AWKPATH Variable-Footnote-1132946
-Node: AWKLIBPATH Variable133206
-Node: Other Environment Variables133803
-Node: Exit Status136298
-Node: Include Files136973
-Node: Loading Shared Libraries140542
-Node: Obsolete141767
-Node: Undocumented142464
-Node: Regexp142707
-Node: Regexp Usage144096
-Node: Escape Sequences146122
-Node: Regexp Operators151885
-Ref: Regexp Operators-Footnote-1159265
-Ref: Regexp Operators-Footnote-2159412
-Node: Bracket Expressions159510
-Ref: table-char-classes161400
-Node: GNU Regexp Operators163923
-Node: Case-sensitivity167646
-Ref: Case-sensitivity-Footnote-1170614
-Ref: Case-sensitivity-Footnote-2170849
-Node: Leftmost Longest170957
-Node: Computed Regexps172158
-Node: Reading Files175568
-Node: Records177571
-Ref: Records-Footnote-1186495
-Node: Fields186532
-Ref: Fields-Footnote-1189565
-Node: Nonconstant Fields189651
-Node: Changing Fields191853
-Node: Field Separators197834
-Node: Default Field Splitting200463
-Node: Regexp Field Splitting201580
-Node: Single Character Fields204922
-Node: Command Line Field Separator205981
-Node: Field Splitting Summary209422
-Ref: Field Splitting Summary-Footnote-1212614
-Node: Constant Size212715
-Node: Splitting By Content217299
-Ref: Splitting By Content-Footnote-1221025
-Node: Multiple Line221065
-Ref: Multiple Line-Footnote-1226912
-Node: Getline227091
-Node: Plain Getline229307
-Node: Getline/Variable231396
-Node: Getline/File232537
-Node: Getline/Variable/File233859
-Ref: Getline/Variable/File-Footnote-1235458
-Node: Getline/Pipe235545
-Node: Getline/Variable/Pipe238105
-Node: Getline/Coprocess239212
-Node: Getline/Variable/Coprocess240455
-Node: Getline Notes241169
-Node: Getline Summary243956
-Ref: table-getline-variants244364
-Node: Read Timeout245222
-Ref: Read Timeout-Footnote-1248967
-Node: Command line directories249024
-Node: Printing249654
-Node: Print251285
-Node: Print Examples252622
-Node: Output Separators255406
-Node: OFMT257166
-Node: Printf258524
-Node: Basic Printf259430
-Node: Control Letters260969
-Node: Format Modifiers264781
-Node: Printf Examples270790
-Node: Redirection273505
-Node: Special Files280489
-Node: Special FD281022
-Ref: Special FD-Footnote-1284647
-Node: Special Network284721
-Node: Special Caveats285571
-Node: Close Files And Pipes286367
-Ref: Close Files And Pipes-Footnote-1293390
-Ref: Close Files And Pipes-Footnote-2293538
-Node: Expressions293688
-Node: Values294820
-Node: Constants295496
-Node: Scalar Constants296176
-Ref: Scalar Constants-Footnote-1297035
-Node: Nondecimal-numbers297217
-Node: Regexp Constants300276
-Node: Using Constant Regexps300751
-Node: Variables303806
-Node: Using Variables304461
-Node: Assignment Options306185
-Node: Conversion308057
-Ref: table-locale-affects313433
-Ref: Conversion-Footnote-1314057
-Node: All Operators314166
-Node: Arithmetic Ops314796
-Node: Concatenation317301
-Ref: Concatenation-Footnote-1320094
-Node: Assignment Ops320214
-Ref: table-assign-ops325202
-Node: Increment Ops326610
-Node: Truth Values and Conditions330080
-Node: Truth Values331163
-Node: Typing and Comparison332212
-Node: Variable Typing333001
-Ref: Variable Typing-Footnote-1336898
-Node: Comparison Operators337020
-Ref: table-relational-ops337430
-Node: POSIX String Comparison340979
-Ref: POSIX String Comparison-Footnote-1341935
-Node: Boolean Ops342073
-Ref: Boolean Ops-Footnote-1346151
-Node: Conditional Exp346242
-Node: Function Calls347974
-Node: Precedence351568
-Node: Locales355237
-Node: Patterns and Actions356326
-Node: Pattern Overview357380
-Node: Regexp Patterns359049
-Node: Expression Patterns359592
-Node: Ranges363277
-Node: BEGIN/END366243
-Node: Using BEGIN/END367005
-Ref: Using BEGIN/END-Footnote-1369736
-Node: I/O And BEGIN/END369842
-Node: BEGINFILE/ENDFILE372124
-Node: Empty375028
-Node: Using Shell Variables375344
-Node: Action Overview377629
-Node: Statements379986
-Node: If Statement381840
-Node: While Statement383339
-Node: Do Statement385383
-Node: For Statement386539
-Node: Switch Statement389691
-Node: Break Statement391788
-Node: Continue Statement393778
-Node: Next Statement395571
-Node: Nextfile Statement397961
-Node: Exit Statement400602
-Node: Built-in Variables403018
-Node: User-modified404113
-Ref: User-modified-Footnote-1412468
-Node: Auto-set412530
-Ref: Auto-set-Footnote-1424881
-Ref: Auto-set-Footnote-2425086
-Node: ARGC and ARGV425142
-Node: Arrays428993
-Node: Array Basics430498
-Node: Array Intro431324
-Node: Reference to Elements435642
-Node: Assigning Elements437912
-Node: Array Example438403
-Node: Scanning an Array440135
-Node: Controlling Scanning442449
-Ref: Controlling Scanning-Footnote-1447382
-Node: Delete447698
-Ref: Delete-Footnote-1450463
-Node: Numeric Array Subscripts450520
-Node: Uninitialized Subscripts452703
-Node: Multi-dimensional454331
-Node: Multi-scanning457425
-Node: Arrays of Arrays459016
-Node: Functions463661
-Node: Built-in464480
-Node: Calling Built-in465558
-Node: Numeric Functions467546
-Ref: Numeric Functions-Footnote-1471378
-Ref: Numeric Functions-Footnote-2471735
-Ref: Numeric Functions-Footnote-3471783
-Node: String Functions472052
-Ref: String Functions-Footnote-1495549
-Ref: String Functions-Footnote-2495678
-Ref: String Functions-Footnote-3495926
-Node: Gory Details496013
-Ref: table-sub-escapes497692
-Ref: table-sub-posix-92499046
-Ref: table-sub-proposed500397
-Ref: table-posix-sub501751
-Ref: table-gensub-escapes503296
-Ref: Gory Details-Footnote-1504503
-Ref: Gory Details-Footnote-2504554
-Node: I/O Functions504705
-Ref: I/O Functions-Footnote-1511810
-Node: Time Functions511957
-Ref: Time Functions-Footnote-1522890
-Ref: Time Functions-Footnote-2522958
-Ref: Time Functions-Footnote-3523116
-Ref: Time Functions-Footnote-4523227
-Ref: Time Functions-Footnote-5523339
-Ref: Time Functions-Footnote-6523566
-Node: Bitwise Functions523832
-Ref: table-bitwise-ops524390
-Ref: Bitwise Functions-Footnote-1528611
-Node: Type Functions528795
-Node: I18N Functions529265
-Node: User-defined530892
-Node: Definition Syntax531696
-Ref: Definition Syntax-Footnote-1536606
-Node: Function Example536675
-Node: Function Caveats539269
-Node: Calling A Function539690
-Node: Variable Scope540805
-Node: Pass By Value/Reference543768
-Node: Return Statement547208
-Node: Dynamic Typing550189
-Node: Indirect Calls550924
-Node: Library Functions560609
-Ref: Library Functions-Footnote-1564122
-Ref: Library Functions-Footnote-2564265
-Node: Library Names564436
-Ref: Library Names-Footnote-1567907
-Ref: Library Names-Footnote-2568127
-Node: General Functions568213
-Node: Strtonum Function569166
-Node: Assert Function572096
-Node: Round Function575422
-Node: Cliff Random Function576965
-Node: Ordinal Functions577981
-Ref: Ordinal Functions-Footnote-1581051
-Ref: Ordinal Functions-Footnote-2581303
-Node: Join Function581512
-Ref: Join Function-Footnote-1583283
-Node: Getlocaltime Function583483
-Node: Data File Management587198
-Node: Filetrans Function587830
-Node: Rewind Function591969
-Node: File Checking593356
-Node: Empty Files594450
-Node: Ignoring Assigns596680
-Node: Getopt Function598233
-Ref: Getopt Function-Footnote-1609537
-Node: Passwd Functions609740
-Ref: Passwd Functions-Footnote-1618715
-Node: Group Functions618803
-Node: Walking Arrays626887
-Node: Sample Programs628456
-Node: Running Examples629133
-Node: Clones629861
-Node: Cut Program631085
-Node: Egrep Program640930
-Ref: Egrep Program-Footnote-1648703
-Node: Id Program648813
-Node: Split Program652429
-Ref: Split Program-Footnote-1655948
-Node: Tee Program656076
-Node: Uniq Program658879
-Node: Wc Program666308
-Ref: Wc Program-Footnote-1670574
-Ref: Wc Program-Footnote-2670774
-Node: Miscellaneous Programs670866
-Node: Dupword Program672054
-Node: Alarm Program674085
-Node: Translate Program678834
-Ref: Translate Program-Footnote-1683221
-Ref: Translate Program-Footnote-2683449
-Node: Labels Program683583
-Ref: Labels Program-Footnote-1686954
-Node: Word Sorting687038
-Node: History Sorting690922
-Node: Extract Program692761
-Ref: Extract Program-Footnote-1700244
-Node: Simple Sed700372
-Node: Igawk Program703434
-Ref: Igawk Program-Footnote-1718591
-Ref: Igawk Program-Footnote-2718792
-Node: Anagram Program718930
-Node: Signature Program721998
-Node: Internationalization723098
-Node: I18N and L10N724530
-Node: Explaining gettext725216
-Ref: Explaining gettext-Footnote-1730282
-Ref: Explaining gettext-Footnote-2730466
-Node: Programmer i18n730631
-Node: Translator i18n734831
-Node: String Extraction735624
-Ref: String Extraction-Footnote-1736585
-Node: Printf Ordering736671
-Ref: Printf Ordering-Footnote-1739455
-Node: I18N Portability739519
-Ref: I18N Portability-Footnote-1741968
-Node: I18N Example742031
-Ref: I18N Example-Footnote-1744666
-Node: Gawk I18N744738
-Node: Advanced Features745355
-Node: Nondecimal Data746859
-Node: Array Sorting748442
-Node: Controlling Array Traversal749139
-Node: Array Sorting Functions757377
-Ref: Array Sorting Functions-Footnote-1761051
-Ref: Array Sorting Functions-Footnote-2761144
-Node: Two-way I/O761338
-Ref: Two-way I/O-Footnote-1766770
-Node: TCP/IP Networking766840
-Node: Profiling769684
-Node: Debugger777138
-Node: Debugging778106
-Node: Debugging Concepts778539
-Node: Debugging Terms780395
-Node: Awk Debugging782992
-Node: Sample Debugging Session783884
-Node: Debugger Invocation784404
-Node: Finding The Bug785733
-Node: List of Debugger Commands792221
-Node: Breakpoint Control793555
-Node: Debugger Execution Control797219
-Node: Viewing And Changing Data800579
-Node: Execution Stack803935
-Node: Debugger Info805402
-Node: Miscellaneous Debugger Commands809383
-Node: Readline Support814828
-Node: Limitations815659
-Node: Arbitrary Precision Arithmetic817911
-Ref: Arbitrary Precision Arithmetic-Footnote-1819553
-Node: General Arithmetic819701
-Node: Floating Point Issues821421
-Node: String Conversion Precision822302
-Ref: String Conversion Precision-Footnote-1824008
-Node: Unexpected Results824117
-Node: POSIX Floating Point Problems826270
-Ref: POSIX Floating Point Problems-Footnote-1830095
-Node: Integer Programming830133
-Node: Floating-point Programming831886
-Ref: Floating-point Programming-Footnote-1838195
-Node: Floating-point Representation838459
-Node: Floating-point Context839624
-Ref: table-ieee-formats840466
-Node: Rounding Mode841850
-Ref: table-rounding-modes842329
-Ref: Rounding Mode-Footnote-1845333
-Node: Gawk and MPFR845514
-Node: Arbitrary Precision Floats846756
-Ref: Arbitrary Precision Floats-Footnote-1849185
-Node: Setting Precision849496
-Node: Setting Rounding Mode852229
-Ref: table-gawk-rounding-modes852633
-Node: Floating-point Constants853813
-Node: Changing Precision855237
-Ref: Changing Precision-Footnote-1856637
-Node: Exact Arithmetic856811
-Node: Arbitrary Precision Integers859919
-Ref: Arbitrary Precision Integers-Footnote-1862919
-Node: Dynamic Extensions863066
-Node: Extension Intro864443
-Node: Plugin License865651
-Node: Extension Mechanism Outline866336
-Ref: load-extension866753
-Ref: load-new-function868231
-Ref: call-new-function869212
-Node: Extension API Description871206
-Node: Extension API Functions Introduction872545
-Node: General Data Types877323
-Ref: General Data Types-Footnote-1882925
-Node: Requesting Values883224
-Ref: table-value-types-returned883955
-Node: Constructor Functions884909
-Node: Registration Functions887905
-Node: Extension Functions888590
-Node: Exit Callback Functions890764
-Node: Extension Version String892007
-Node: Input Parsers892657
-Node: Output Wrappers902374
-Node: Two-way processors906790
-Node: Printing Messages908920
-Ref: Printing Messages-Footnote-1909997
-Node: Updating `ERRNO'910149
-Node: Accessing Parameters910888
-Node: Symbol Table Access912118
-Node: Symbol table by name912630
-Node: Symbol table by cookie914203
-Ref: Symbol table by cookie-Footnote-1918332
-Node: Cached values918395
-Ref: Cached values-Footnote-1921838
-Node: Array Manipulation921929
-Ref: Array Manipulation-Footnote-1923027
-Node: Array Data Types923066
-Ref: Array Data Types-Footnote-1925769
-Node: Array Functions925861
-Node: Flattening Arrays929627
-Node: Creating Arrays936466
-Node: Extension API Variables941261
-Node: Extension Versioning941897
-Node: Extension API Informational Variables943798
-Node: Extension API Boilerplate944884
-Node: Finding Extensions948715
-Node: Extension Example949262
-Node: Internal File Description950000
-Node: Internal File Ops953688
-Ref: Internal File Ops-Footnote-1965135
-Node: Using Internal File Ops965275
-Ref: Using Internal File Ops-Footnote-1967628
-Node: Extension Samples967894
-Node: Extension Sample File Functions969337
-Node: Extension Sample Fnmatch977810
-Node: Extension Sample Fork979536
-Node: Extension Sample Ord980750
-Node: Extension Sample Readdir981526
-Node: Extension Sample Revout983030
-Node: Extension Sample Rev2way983623
-Node: Extension Sample Read write array984313
-Node: Extension Sample Readfile986196
-Node: Extension Sample API Tests986951
-Node: Extension Sample Time987476
-Node: gawkextlib988783
-Node: Language History991164
-Node: V7/SVR3.1992686
-Node: SVR4995007
-Node: POSIX996449
-Node: BTL997457
-Node: POSIX/GNU998262
-Node: Common Extensions1003797
-Node: Ranges and Locales1004904
-Ref: Ranges and Locales-Footnote-11009522
-Ref: Ranges and Locales-Footnote-21009549
-Ref: Ranges and Locales-Footnote-31009809
-Node: Contributors1010030
-Node: Installation1014326
-Node: Gawk Distribution1015220
-Node: Getting1015704
-Node: Extracting1016530
-Node: Distribution contents1018222
-Node: Unix Installation1023483
-Node: Quick Installation1024100
-Node: Additional Configuration Options1026062
-Node: Configuration Philosophy1027539
-Node: Non-Unix Installation1029881
-Node: PC Installation1030339
-Node: PC Binary Installation1031638
-Node: PC Compiling1033486
-Node: PC Testing1036430
-Node: PC Using1037606
-Node: Cygwin1041791
-Node: MSYS1042791
-Node: VMS Installation1043305
-Node: VMS Compilation1043908
-Ref: VMS Compilation-Footnote-11044915
-Node: VMS Installation Details1044973
-Node: VMS Running1046608
-Node: VMS Old Gawk1048215
-Node: Bugs1048689
-Node: Other Versions1052541
-Node: Notes1058197
-Node: Compatibility Mode1058997
-Node: Additions1059780
-Node: Accessing The Source1060707
-Node: Adding Code1062310
-Node: New Ports1068352
-Node: Derived Files1072487
-Ref: Derived Files-Footnote-11077808
-Ref: Derived Files-Footnote-21077842
-Ref: Derived Files-Footnote-31078442
-Node: Future Extensions1078540
-Node: Implementation Limitations1079121
-Node: Extension Design1080373
-Node: Old Extension Problems1081522
-Ref: Old Extension Problems-Footnote-11083030
-Node: Extension New Mechanism Goals1083087
-Ref: Extension New Mechanism Goals-Footnote-11086446
-Node: Extension Other Design Decisions1086632
-Node: Extension Future Growth1088738
-Node: Old Extension Mechansim1089559
-Node: Basic Concepts1091316
-Node: Basic High Level1091997
-Ref: figure-general-flow1092268
-Ref: figure-process-flow1092867
-Ref: Basic High Level-Footnote-11096096
-Node: Basic Data Typing1096281
-Node: Glossary1099636
-Node: Copying1124947
-Node: GNU Free Documentation License1162504
-Node: Index1187641
+Node: Foreword40301
+Node: Preface44646
+Ref: Preface-Footnote-147699
+Ref: Preface-Footnote-247805
+Node: History48037
+Node: Names50428
+Ref: Names-Footnote-151905
+Node: This Manual51977
+Ref: This Manual-Footnote-157883
+Node: Conventions57983
+Node: Manual History60117
+Ref: Manual History-Footnote-163387
+Ref: Manual History-Footnote-263428
+Node: How To Contribute63502
+Node: Acknowledgments64646
+Node: Getting Started69142
+Node: Running gawk71521
+Node: One-shot72707
+Node: Read Terminal73932
+Ref: Read Terminal-Footnote-175582
+Ref: Read Terminal-Footnote-275858
+Node: Long76029
+Node: Executable Scripts77405
+Ref: Executable Scripts-Footnote-179274
+Ref: Executable Scripts-Footnote-279376
+Node: Comments79923
+Node: Quoting82390
+Node: DOS Quoting87013
+Node: Sample Data Files87688
+Node: Very Simple90720
+Node: Two Rules95319
+Node: More Complex97466
+Ref: More Complex-Footnote-1100396
+Node: Statements/Lines100481
+Ref: Statements/Lines-Footnote-1104943
+Node: Other Features105208
+Node: When106136
+Node: Invoking Gawk108283
+Node: Command Line109744
+Node: Options110527
+Ref: Options-Footnote-1125925
+Node: Other Arguments125950
+Node: Naming Standard Input128608
+Node: Environment Variables129702
+Node: AWKPATH Variable130260
+Ref: AWKPATH Variable-Footnote-1133018
+Node: AWKLIBPATH Variable133278
+Node: Other Environment Variables133875
+Node: Exit Status136370
+Node: Include Files137045
+Node: Loading Shared Libraries140614
+Node: Obsolete141839
+Node: Undocumented142536
+Node: Regexp142779
+Node: Regexp Usage144168
+Node: Escape Sequences146194
+Node: Regexp Operators151957
+Ref: Regexp Operators-Footnote-1159337
+Ref: Regexp Operators-Footnote-2159484
+Node: Bracket Expressions159582
+Ref: table-char-classes161472
+Node: GNU Regexp Operators163998
+Node: Case-sensitivity167721
+Ref: Case-sensitivity-Footnote-1170689
+Ref: Case-sensitivity-Footnote-2170924
+Node: Leftmost Longest171032
+Node: Computed Regexps172233
+Node: Reading Files175643
+Node: Records177646
+Ref: Records-Footnote-1186570
+Node: Fields186607
+Ref: Fields-Footnote-1189640
+Node: Nonconstant Fields189726
+Node: Changing Fields191928
+Node: Field Separators197909
+Node: Default Field Splitting200538
+Node: Regexp Field Splitting201655
+Node: Single Character Fields204997
+Node: Command Line Field Separator206056
+Node: Field Splitting Summary209497
+Ref: Field Splitting Summary-Footnote-1212689
+Node: Constant Size212790
+Node: Splitting By Content217374
+Ref: Splitting By Content-Footnote-1221100
+Node: Multiple Line221140
+Ref: Multiple Line-Footnote-1226987
+Node: Getline227166
+Node: Plain Getline229382
+Node: Getline/Variable231471
+Node: Getline/File232612
+Node: Getline/Variable/File233934
+Ref: Getline/Variable/File-Footnote-1235533
+Node: Getline/Pipe235620
+Node: Getline/Variable/Pipe238180
+Node: Getline/Coprocess239287
+Node: Getline/Variable/Coprocess240530
+Node: Getline Notes241244
+Node: Getline Summary244031
+Ref: table-getline-variants244439
+Node: Read Timeout245300
+Ref: Read Timeout-Footnote-1249045
+Node: Command line directories249102
+Node: Printing249732
+Node: Print251363
+Node: Print Examples252700
+Node: Output Separators255484
+Node: OFMT257244
+Node: Printf258602
+Node: Basic Printf259508
+Node: Control Letters261047
+Node: Format Modifiers264859
+Node: Printf Examples270868
+Node: Redirection273583
+Node: Special Files280567
+Node: Special FD281100
+Ref: Special FD-Footnote-1284725
+Node: Special Network284799
+Node: Special Caveats285649
+Node: Close Files And Pipes286445
+Ref: Close Files And Pipes-Footnote-1293468
+Ref: Close Files And Pipes-Footnote-2293616
+Node: Expressions293766
+Node: Values294898
+Node: Constants295574
+Node: Scalar Constants296254
+Ref: Scalar Constants-Footnote-1297113
+Node: Nondecimal-numbers297295
+Node: Regexp Constants300354
+Node: Using Constant Regexps300829
+Node: Variables303884
+Node: Using Variables304539
+Node: Assignment Options306263
+Node: Conversion308135
+Ref: table-locale-affects313511
+Ref: Conversion-Footnote-1314138
+Node: All Operators314247
+Node: Arithmetic Ops314877
+Node: Concatenation317382
+Ref: Concatenation-Footnote-1320175
+Node: Assignment Ops320295
+Ref: table-assign-ops325283
+Node: Increment Ops326694
+Node: Truth Values and Conditions330164
+Node: Truth Values331247
+Node: Typing and Comparison332296
+Node: Variable Typing333085
+Ref: Variable Typing-Footnote-1336982
+Node: Comparison Operators337104
+Ref: table-relational-ops337514
+Node: POSIX String Comparison341066
+Ref: POSIX String Comparison-Footnote-1342022
+Node: Boolean Ops342160
+Ref: Boolean Ops-Footnote-1346238
+Node: Conditional Exp346329
+Node: Function Calls348061
+Node: Precedence351655
+Node: Locales355324
+Node: Patterns and Actions356413
+Node: Pattern Overview357467
+Node: Regexp Patterns359136
+Node: Expression Patterns359679
+Node: Ranges363364
+Node: BEGIN/END366330
+Node: Using BEGIN/END367092
+Ref: Using BEGIN/END-Footnote-1369823
+Node: I/O And BEGIN/END369929
+Node: BEGINFILE/ENDFILE372211
+Node: Empty375115
+Node: Using Shell Variables375431
+Node: Action Overview377716
+Node: Statements380073
+Node: If Statement381927
+Node: While Statement383426
+Node: Do Statement385470
+Node: For Statement386626
+Node: Switch Statement389778
+Node: Break Statement391875
+Node: Continue Statement393865
+Node: Next Statement395658
+Node: Nextfile Statement398048
+Node: Exit Statement400689
+Node: Built-in Variables403105
+Node: User-modified404200
+Ref: User-modified-Footnote-1412555
+Node: Auto-set412617
+Ref: Auto-set-Footnote-1424968
+Ref: Auto-set-Footnote-2425173
+Node: ARGC and ARGV425229
+Node: Arrays429080
+Node: Array Basics430585
+Node: Array Intro431411
+Node: Reference to Elements435729
+Node: Assigning Elements437999
+Node: Array Example438490
+Node: Scanning an Array440222
+Node: Controlling Scanning442536
+Ref: Controlling Scanning-Footnote-1447469
+Node: Delete447785
+Ref: Delete-Footnote-1450550
+Node: Numeric Array Subscripts450607
+Node: Uninitialized Subscripts452790
+Node: Multi-dimensional454418
+Node: Multi-scanning457512
+Node: Arrays of Arrays459103
+Node: Functions463748
+Node: Built-in464567
+Node: Calling Built-in465645
+Node: Numeric Functions467633
+Ref: Numeric Functions-Footnote-1471465
+Ref: Numeric Functions-Footnote-2471822
+Ref: Numeric Functions-Footnote-3471870
+Node: String Functions472139
+Ref: String Functions-Footnote-1495636
+Ref: String Functions-Footnote-2495765
+Ref: String Functions-Footnote-3496013
+Node: Gory Details496100
+Ref: table-sub-escapes497779
+Ref: table-sub-posix-92499136
+Ref: table-sub-proposed500490
+Ref: table-posix-sub501847
+Ref: table-gensub-escapes503395
+Ref: Gory Details-Footnote-1504605
+Ref: Gory Details-Footnote-2504656
+Node: I/O Functions504807
+Ref: I/O Functions-Footnote-1511912
+Node: Time Functions512059
+Ref: Time Functions-Footnote-1522992
+Ref: Time Functions-Footnote-2523060
+Ref: Time Functions-Footnote-3523218
+Ref: Time Functions-Footnote-4523329
+Ref: Time Functions-Footnote-5523441
+Ref: Time Functions-Footnote-6523668
+Node: Bitwise Functions523934
+Ref: table-bitwise-ops524492
+Ref: Bitwise Functions-Footnote-1528716
+Node: Type Functions528900
+Node: I18N Functions529370
+Node: User-defined530997
+Node: Definition Syntax531801
+Ref: Definition Syntax-Footnote-1536711
+Node: Function Example536780
+Node: Function Caveats539374
+Node: Calling A Function539795
+Node: Variable Scope540910
+Node: Pass By Value/Reference543873
+Node: Return Statement547313
+Node: Dynamic Typing550294
+Node: Indirect Calls551029
+Node: Library Functions560714
+Ref: Library Functions-Footnote-1564227
+Ref: Library Functions-Footnote-2564370
+Node: Library Names564541
+Ref: Library Names-Footnote-1568012
+Ref: Library Names-Footnote-2568232
+Node: General Functions568318
+Node: Strtonum Function569271
+Node: Assert Function572201
+Node: Round Function575527
+Node: Cliff Random Function577070
+Node: Ordinal Functions578086
+Ref: Ordinal Functions-Footnote-1581156
+Ref: Ordinal Functions-Footnote-2581408
+Node: Join Function581617
+Ref: Join Function-Footnote-1583388
+Node: Getlocaltime Function583588
+Node: Data File Management587303
+Node: Filetrans Function587935
+Node: Rewind Function592074
+Node: File Checking593461
+Node: Empty Files594555
+Node: Ignoring Assigns596785
+Node: Getopt Function598338
+Ref: Getopt Function-Footnote-1609642
+Node: Passwd Functions609845
+Ref: Passwd Functions-Footnote-1618820
+Node: Group Functions618908
+Node: Walking Arrays626992
+Node: Sample Programs628561
+Node: Running Examples629238
+Node: Clones629966
+Node: Cut Program631190
+Node: Egrep Program641035
+Ref: Egrep Program-Footnote-1648808
+Node: Id Program648918
+Node: Split Program652534
+Ref: Split Program-Footnote-1656053
+Node: Tee Program656181
+Node: Uniq Program658984
+Node: Wc Program666413
+Ref: Wc Program-Footnote-1670679
+Ref: Wc Program-Footnote-2670879
+Node: Miscellaneous Programs670971
+Node: Dupword Program672159
+Node: Alarm Program674190
+Node: Translate Program678939
+Ref: Translate Program-Footnote-1683326
+Ref: Translate Program-Footnote-2683554
+Node: Labels Program683688
+Ref: Labels Program-Footnote-1687059
+Node: Word Sorting687143
+Node: History Sorting691027
+Node: Extract Program692866
+Ref: Extract Program-Footnote-1700349
+Node: Simple Sed700477
+Node: Igawk Program703539
+Ref: Igawk Program-Footnote-1718696
+Ref: Igawk Program-Footnote-2718897
+Node: Anagram Program719035
+Node: Signature Program722103
+Node: Internationalization723203
+Node: I18N and L10N724635
+Node: Explaining gettext725321
+Ref: Explaining gettext-Footnote-1730387
+Ref: Explaining gettext-Footnote-2730571
+Node: Programmer i18n730736
+Node: Translator i18n734936
+Node: String Extraction735729
+Ref: String Extraction-Footnote-1736690
+Node: Printf Ordering736776
+Ref: Printf Ordering-Footnote-1739560
+Node: I18N Portability739624
+Ref: I18N Portability-Footnote-1742073
+Node: I18N Example742136
+Ref: I18N Example-Footnote-1744771
+Node: Gawk I18N744843
+Node: Advanced Features745460
+Node: Nondecimal Data746964
+Node: Array Sorting748547
+Node: Controlling Array Traversal749244
+Node: Array Sorting Functions757482
+Ref: Array Sorting Functions-Footnote-1761156
+Ref: Array Sorting Functions-Footnote-2761249
+Node: Two-way I/O761443
+Ref: Two-way I/O-Footnote-1766875
+Node: TCP/IP Networking766945
+Node: Profiling769789
+Node: Debugger777243
+Node: Debugging778211
+Node: Debugging Concepts778644
+Node: Debugging Terms780500
+Node: Awk Debugging783097
+Node: Sample Debugging Session783989
+Node: Debugger Invocation784509
+Node: Finding The Bug785838
+Node: List of Debugger Commands792326
+Node: Breakpoint Control793660
+Node: Debugger Execution Control797324
+Node: Viewing And Changing Data800684
+Node: Execution Stack804040
+Node: Debugger Info805507
+Node: Miscellaneous Debugger Commands809488
+Node: Readline Support814933
+Node: Limitations815764
+Node: Arbitrary Precision Arithmetic818016
+Ref: Arbitrary Precision Arithmetic-Footnote-1819658
+Node: General Arithmetic819806
+Node: Floating Point Issues821526
+Node: String Conversion Precision822407
+Ref: String Conversion Precision-Footnote-1824113
+Node: Unexpected Results824222
+Node: POSIX Floating Point Problems826375
+Ref: POSIX Floating Point Problems-Footnote-1830200
+Node: Integer Programming830238
+Node: Floating-point Programming831991
+Ref: Floating-point Programming-Footnote-1838300
+Node: Floating-point Representation838564
+Node: Floating-point Context839729
+Ref: table-ieee-formats840571
+Node: Rounding Mode841957
+Ref: table-rounding-modes842436
+Ref: Rounding Mode-Footnote-1845442
+Node: Gawk and MPFR845623
+Node: Arbitrary Precision Floats846865
+Ref: Arbitrary Precision Floats-Footnote-1849294
+Node: Setting Precision849605
+Node: Setting Rounding Mode852338
+Ref: table-gawk-rounding-modes852742
+Node: Floating-point Constants853926
+Node: Changing Precision855350
+Ref: Changing Precision-Footnote-1856750
+Node: Exact Arithmetic856924
+Node: Arbitrary Precision Integers860032
+Ref: Arbitrary Precision Integers-Footnote-1863032
+Node: Dynamic Extensions863179
+Node: Extension Intro864556
+Node: Plugin License865764
+Node: Extension Mechanism Outline866449
+Ref: load-extension866866
+Ref: load-new-function868346
+Ref: call-new-function869329
+Node: Extension API Description871325
+Node: Extension API Functions Introduction872664
+Node: General Data Types877442
+Ref: General Data Types-Footnote-1883044
+Node: Requesting Values883343
+Ref: table-value-types-returned884074
+Node: Constructor Functions885030
+Node: Registration Functions888026
+Node: Extension Functions888711
+Node: Exit Callback Functions890885
+Node: Extension Version String892128
+Node: Input Parsers892778
+Node: Output Wrappers902495
+Node: Two-way processors906911
+Node: Printing Messages909041
+Ref: Printing Messages-Footnote-1910118
+Node: Updating `ERRNO'910270
+Node: Accessing Parameters911009
+Node: Symbol Table Access912241
+Node: Symbol table by name912753
+Node: Symbol table by cookie914328
+Ref: Symbol table by cookie-Footnote-1918457
+Node: Cached values918520
+Ref: Cached values-Footnote-1921963
+Node: Array Manipulation922054
+Ref: Array Manipulation-Footnote-1923152
+Node: Array Data Types923191
+Ref: Array Data Types-Footnote-1925894
+Node: Array Functions925986
+Node: Flattening Arrays929754
+Node: Creating Arrays936593
+Node: Extension API Variables941388
+Node: Extension Versioning942024
+Node: Extension API Informational Variables943925
+Node: Extension API Boilerplate945011
+Node: Finding Extensions948842
+Node: Extension Example949389
+Node: Internal File Description950127
+Node: Internal File Ops953815
+Ref: Internal File Ops-Footnote-1965262
+Node: Using Internal File Ops965402
+Ref: Using Internal File Ops-Footnote-1967755
+Node: Extension Samples968021
+Node: Extension Sample File Functions969545
+Node: Extension Sample Fnmatch978018
+Node: Extension Sample Fork979744
+Node: Extension Sample Inplace980962
+Node: Extension Sample Ord982657
+Node: Extension Sample Readdir983436
+Node: Extension Sample Revout984940
+Node: Extension Sample Rev2way985533
+Node: Extension Sample Read write array986223
+Node: Extension Sample Readfile988106
+Node: Extension Sample API Tests988863
+Node: Extension Sample Time989388
+Node: gawkextlib990695
+Node: Language History993076
+Node: V7/SVR3.1994598
+Node: SVR4996919
+Node: POSIX998361
+Node: BTL999369
+Node: POSIX/GNU1000174
+Node: Common Extensions1005709
+Node: Ranges and Locales1006816
+Ref: Ranges and Locales-Footnote-11011434
+Ref: Ranges and Locales-Footnote-21011461
+Ref: Ranges and Locales-Footnote-31011721
+Node: Contributors1011942
+Node: Installation1016238
+Node: Gawk Distribution1017132
+Node: Getting1017616
+Node: Extracting1018442
+Node: Distribution contents1020134
+Node: Unix Installation1025395
+Node: Quick Installation1026012
+Node: Additional Configuration Options1027974
+Node: Configuration Philosophy1029451
+Node: Non-Unix Installation1031793
+Node: PC Installation1032251
+Node: PC Binary Installation1033550
+Node: PC Compiling1035398
+Node: PC Testing1038342
+Node: PC Using1039518
+Node: Cygwin1043703
+Node: MSYS1044703
+Node: VMS Installation1045217
+Node: VMS Compilation1045820
+Ref: VMS Compilation-Footnote-11046827
+Node: VMS Installation Details1046885
+Node: VMS Running1048520
+Node: VMS Old Gawk1050127
+Node: Bugs1050601
+Node: Other Versions1054453
+Node: Notes1060109
+Node: Compatibility Mode1060909
+Node: Additions1061692
+Node: Accessing The Source1062619
+Node: Adding Code1064222
+Node: New Ports1070264
+Node: Derived Files1074399
+Ref: Derived Files-Footnote-11079720
+Ref: Derived Files-Footnote-21079754
+Ref: Derived Files-Footnote-31080354
+Node: Future Extensions1080452
+Node: Implementation Limitations1081033
+Node: Extension Design1082285
+Node: Old Extension Problems1083434
+Ref: Old Extension Problems-Footnote-11084942
+Node: Extension New Mechanism Goals1084999
+Ref: Extension New Mechanism Goals-Footnote-11088358
+Node: Extension Other Design Decisions1088544
+Node: Extension Future Growth1090650
+Node: Old Extension Mechansim1091471
+Node: Basic Concepts1093228
+Node: Basic High Level1093909
+Ref: figure-general-flow1094180
+Ref: figure-process-flow1094779
+Ref: Basic High Level-Footnote-11098008
+Node: Basic Data Typing1098193
+Node: Glossary1101548
+Node: Copying1126859
+Node: GNU Free Documentation License1164416
+Node: Index1189553

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 6d476b73..6f44c969 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -765,6 +765,7 @@ particular records in a file and perform operations upon them.
* Extension Sample Fnmatch:: An interface to @code{fnmatch()}.
* Extension Sample Fork:: An interface to @code{fork()} and
other process functions.
+* Extension Sample Inplace:: Enabling in-place file editing.
* Extension Sample Ord:: Character to value to character
conversions.
* Extension Sample Readdir:: An interface to @code{readdir()}.
@@ -31156,7 +31157,7 @@ $ @kbd{AWKLIBPATH=$PWD gawk -f testff.awk}
This @value{SECTION} provides brief overviews of the sample extensions
that come in the @command{gawk} distribution. Some of them are intended
-for production use, such the @code{filefuncs} and @code{readdir} extensions.
+for production use, such the @code{filefuncs}, @code{readdir} and @code{inplace} extensions.
Others mainly provide example code that shows how to use the extension API.
@menu
@@ -31164,6 +31165,7 @@ Others mainly provide example code that shows how to use the extension API.
* Extension Sample Fnmatch:: An interface to @code{fnmatch()}.
* Extension Sample Fork:: An interface to @code{fork()} and other
process functions.
+* Extension Sample Inplace:: Enabling in-place file editing.
* Extension Sample Ord:: Character to value to character
conversions.
* Extension Sample Readdir:: An interface to @code{readdir()}.
@@ -31504,6 +31506,59 @@ else
print "hello from the parent"
@end example
+@node Extension Sample Inplace
+@subsection Enabling in-place file editing.
+
+The @code{inplace} extension emulates the @command{sed} @option{-i} option.
+It uses the bundled @file{inplace.awk} include file to invoke the extension
+properly:
+
+@example
+@c file eg/lib/inplace.awk
+@group
+# inplace --- load and invoke the inplace extension.
+
+@@load "inplace"
+
+# Please set INPLACE_SUFFIX to make a backup copy. For example,
+# you may want to set INPLACE_SUFFIX to .bak on the command-line or in a
+# BEGIN block.
+
+BEGINFILE @{
+ inplace_begin(FILENAME, INPLACE_SUFFIX)
+@}
+ENDFILE @{
+ inplace_end(FILENAME, INPLACE_SUFFIX)
+@}
+@end group
+@c endfile
+@end example
+
+For each regular file that is processed, the extension redirects stdout
+to a temporary file configured to have the same owner and permissions.
+After the file has been processed, stdout is restored to its default
+destination. If @code{INPLACE_SUFFIX} is not an empty string, the
+original file will be linked to a backup filename created by appending
+that suffix. Finally, the temporary file is renamed to the original filename.
+
+If any error is encountered, the extension issues a fatal error to terminate
+processing immediately without damaging the original file.
+
+Here are a couple of simple examples:
+
+@example
+$ @kbd{gawk -i inplace '@{gsub(/foo/, "bar")@} @{print@}' file1 file2 file3}
+@end example
+
+To keep a backup copy of the original files, try this:
+
+@example
+$ @kbd{gawk -i inplace -vINPLACE_SUFFIX=.bak '@{gsub(/foo/, "bar")@} @{print@}' file1 file2 file3}
+@end example
+
+It is left as an exercise to write a wrapper script that presents an
+interface similar to the @command{sed} @option{-i} option.
+
@node Extension Sample Ord
@subsection Character and Numeric values: @code{ord()} and @code{chr()}
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 3091fac8..7fea3bf0 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,8 @@
+2013-01-08 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * inplace.c: New extension to implement in-place editing.
+ * Makefile.am: Add inplace extension.
+
2012-12-25 Arnold D. Robbins <arnold@skeeve.com>
* filefuncs.3am, fnmatch.3am: Predefined variables are no
diff --git a/extension/Makefile.am b/extension/Makefile.am
index 33902a6d..d5977f2e 100644
--- a/extension/Makefile.am
+++ b/extension/Makefile.am
@@ -35,6 +35,7 @@ pkgextension_LTLIBRARIES = \
filefuncs.la \
fnmatch.la \
fork.la \
+ inplace.la \
ordchr.la \
readdir.la \
readfile.la \
@@ -60,6 +61,10 @@ fork_la_SOURCES = fork.c
fork_la_LDFLAGS = $(MY_MODULE_FLAGS)
fork_la_LIBADD = $(MY_LIBS)
+inplace_la_SOURCES = inplace.c
+inplace_la_LDFLAGS = $(MY_MODULE_FLAGS)
+inplace_la_LIBADD = $(MY_LIBS)
+
ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
ordchr_la_LIBADD = $(MY_LIBS)
diff --git a/extension/Makefile.in b/extension/Makefile.in
index e0bb2430..21a56636 100644
--- a/extension/Makefile.in
+++ b/extension/Makefile.in
@@ -155,6 +155,12 @@ fork_la_OBJECTS = $(am_fork_la_OBJECTS)
fork_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(fork_la_LDFLAGS) \
$(LDFLAGS) -o $@
+inplace_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_inplace_la_OBJECTS = inplace.lo
+inplace_la_OBJECTS = $(am_inplace_la_OBJECTS)
+inplace_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(inplace_la_LDFLAGS) $(LDFLAGS) -o $@
ordchr_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
am_ordchr_la_OBJECTS = ordchr.lo
ordchr_la_OBJECTS = $(am_ordchr_la_OBJECTS)
@@ -217,15 +223,15 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
- $(fork_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)
+ $(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)
DIST_SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
- $(fork_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)
+ $(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)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
@@ -434,6 +440,7 @@ pkgextension_LTLIBRARIES = \
filefuncs.la \
fnmatch.la \
fork.la \
+ inplace.la \
ordchr.la \
readdir.la \
readfile.la \
@@ -455,6 +462,9 @@ fnmatch_la_LIBADD = $(MY_LIBS)
fork_la_SOURCES = fork.c
fork_la_LDFLAGS = $(MY_MODULE_FLAGS)
fork_la_LIBADD = $(MY_LIBS)
+inplace_la_SOURCES = inplace.c
+inplace_la_LDFLAGS = $(MY_MODULE_FLAGS)
+inplace_la_LIBADD = $(MY_LIBS)
ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
ordchr_la_LIBADD = $(MY_LIBS)
@@ -587,6 +597,8 @@ fnmatch.la: $(fnmatch_la_OBJECTS) $(fnmatch_la_DEPENDENCIES) $(EXTRA_fnmatch_la_
$(fnmatch_la_LINK) -rpath $(pkgextensiondir) $(fnmatch_la_OBJECTS) $(fnmatch_la_LIBADD) $(LIBS)
fork.la: $(fork_la_OBJECTS) $(fork_la_DEPENDENCIES) $(EXTRA_fork_la_DEPENDENCIES)
$(fork_la_LINK) -rpath $(pkgextensiondir) $(fork_la_OBJECTS) $(fork_la_LIBADD) $(LIBS)
+inplace.la: $(inplace_la_OBJECTS) $(inplace_la_DEPENDENCIES) $(EXTRA_inplace_la_DEPENDENCIES)
+ $(inplace_la_LINK) -rpath $(pkgextensiondir) $(inplace_la_OBJECTS) $(inplace_la_LIBADD) $(LIBS)
ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPENDENCIES)
$(ordchr_la_LINK) -rpath $(pkgextensiondir) $(ordchr_la_OBJECTS) $(ordchr_la_LIBADD) $(LIBS)
readdir.la: $(readdir_la_OBJECTS) $(readdir_la_DEPENDENCIES) $(EXTRA_readdir_la_DEPENDENCIES)
@@ -614,6 +626,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fork.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gawkfts.Plo@am__quote@
+@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)/readfile.Plo@am__quote@
diff --git a/extension/inplace.c b/extension/inplace.c
new file mode 100644
index 00000000..69b188b8
--- /dev/null
+++ b/extension/inplace.c
@@ -0,0 +1,241 @@
+/*
+ * inplace.c - Provide support for in-place editing.
+ */
+
+/*
+ * Copyright (C) 2013 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
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "gawkapi.h"
+
+#include "gettext.h"
+#define _(msgid) gettext(msgid)
+#define N_(msgid) msgid
+
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+static const char *ext_version = "inplace extension: version 1.0";
+
+int plugin_is_GPL_compatible;
+
+static struct {
+ char *tname;
+ int default_stdout;
+ int posrc; /* return code from fgetpos */
+ fpos_t pos;
+} state = { NULL, -1 };
+
+/*
+ * XXX Known problems:
+ * 1. Should copy ACL.
+ * 2. Not reentrant, so will not work if multiple files are open at
+ * the same time. I'm not sure this is a meaningful problem in practice.
+ */
+
+static void
+at_exit(void *data, int exit_status)
+{
+ if (state.tname) {
+ unlink(state.tname);
+ free(state.tname);
+ state.tname = NULL;
+ }
+}
+
+/*
+ * N.B. Almost everything is a fatal error because this feature is typically
+ * used for one-liners where the user is not going to be worrying about
+ * checking errors. If anything unexpected occurs, we want to abort
+ * immediately!
+ */
+
+static int
+invalid_filename(const awk_string_t *filename)
+{
+ return filename->len == 0 ||
+ (filename->len == 1 && *filename->str == '-');
+}
+
+/* do_inplace_begin --- start in-place editing */
+
+static awk_value_t *
+do_inplace_begin(int nargs, awk_value_t *result)
+{
+ awk_value_t filename, suffix;
+ struct stat sbuf;
+ char *p;
+ int fd;
+
+ assert(result != NULL);
+
+ if (state.tname)
+ fatal(ext_id, _("inplace_begin: in-place editing already active"));
+
+ if (nargs != 2)
+ fatal(ext_id, _("inplace_begin: expects 2 arguments but called with %d"), nargs);
+
+ if (! get_argument(0, AWK_STRING, &filename))
+ fatal(ext_id, _("inplace_begin: cannot retrieve 1st argument as a string filename"));
+
+ if (! get_argument(1, AWK_STRING, &suffix))
+ suffix.str_value.str = NULL;
+
+ if (invalid_filename(&filename.str_value)) {
+ warning(ext_id, _("inplace_begin: disabling in-place editing for invalid FILENAME `%s'"),
+ filename.str_value.str);
+ unset_ERRNO();
+ return make_number(-1, result);
+ }
+
+ if (stat(filename.str_value.str, & sbuf) < 0) {
+ warning(ext_id, _("inplace_begin: Cannot stat `%s' (%s)"),
+ filename.str_value.str, strerror(errno));
+ update_ERRNO_int(errno);
+ return make_number(-1, result);
+ }
+
+ if (! S_ISREG(sbuf.st_mode)) {
+ warning(ext_id, _("inplace_begin: `%s' is not a regular file"),
+ filename.str_value.str);
+ unset_ERRNO();
+ return make_number(-1, result);
+ }
+
+ /* create a temporary file to which to redirect stdout */
+ emalloc(state.tname, char *, filename.str_value.len+14, "do_inplace_begin");
+ sprintf(state.tname, "%s.gawk.XXXXXX", filename.str_value.str);
+
+ if ((fd = mkstemp(state.tname)) < 0)
+ fatal(ext_id, _("inplace_begin: mkstemp(`%s') failed (%s)"),
+ state.tname, strerror(errno));
+
+ /* N.B. chown/chmod should be more portable than fchown/fchmod */
+ if (chown(state.tname, sbuf.st_uid, sbuf.st_gid) < 0)
+ chown(state.tname, -1, sbuf.st_gid);
+ if (chmod(state.tname, sbuf.st_mode) < 0)
+ fatal(ext_id, _("inplace_begin: chmod failed (%s)"),
+ strerror(errno));
+
+ fflush(stdout);
+ /* N.B. fgetpos fails when stdout is a tty */
+ state.posrc = fgetpos(stdout, &state.pos);
+ if ((state.default_stdout = dup(STDOUT_FILENO)) < 0)
+ fatal(ext_id, _("inplace_begin: dup(stdout) failed (%s)"),
+ strerror(errno));
+ if (dup2(fd, STDOUT_FILENO) < 0)
+ fatal(ext_id, _("inplace_begin: dup2(%d, stdout) failed (%s)"),
+ fd, strerror(errno));
+ if (close(fd) < 0)
+ fatal(ext_id, _("inplace_begin: close(%d) failed (%s)"),
+ fd, strerror(errno));
+ rewind(stdout);
+ return make_number(0, result);
+}
+
+/* do_inplace_end --- finish in-place editing */
+
+static awk_value_t *
+do_inplace_end(int nargs, awk_value_t *result)
+{
+ awk_value_t filename, suffix;
+
+ assert(result != NULL);
+
+ if (nargs != 2)
+ fatal(ext_id, _("inplace_begin: expects 2 arguments but called with %d"), nargs);
+
+ if (! get_argument(0, AWK_STRING, &filename))
+ fatal(ext_id, _("inplace_end: cannot retrieve 1st argument as a string filename"));
+
+ if (! get_argument(1, AWK_STRING, &suffix))
+ suffix.str_value.str = NULL;
+
+ if (! state.tname) {
+ if (! invalid_filename(&filename.str_value))
+ warning(ext_id, _("inplace_end: in-place editing not active"));
+ return make_number(0, result);
+ }
+
+ fflush(stdout);
+ if (dup2(state.default_stdout, STDOUT_FILENO) < 0)
+ fatal(ext_id, _("inplace_end: dup2(%d, stdout) failed (%s)"),
+ state.default_stdout, strerror(errno));
+ if (close(state.default_stdout) < 0)
+ fatal(ext_id, _("inplace_end: close(%d) failed (%s)"),
+ state.default_stdout, strerror(errno));
+ state.default_stdout = -1;
+ if (state.posrc == 0 && fsetpos(stdout, &state.pos) < 0)
+ fatal(ext_id, _("inplace_end: fsetpos(stdout) failed (%s)"),
+ strerror(errno));
+
+ if (suffix.str_value.str && suffix.str_value.str[0]) {
+ /* backup requested */
+ char *bakname;
+
+ emalloc(bakname, char *, filename.str_value.len+suffix.str_value.len+1,
+ "do_inplace_end");
+ sprintf(bakname, "%s%s",
+ filename.str_value.str, suffix.str_value.str);
+ unlink(bakname); /* if backup file exists already, remove it */
+ if (link(filename.str_value.str, bakname) < 0)
+ fatal(ext_id, _("inplace_end: link(`%s', `%s') failed (%s)"),
+ filename.str_value.str, bakname, strerror(errno));
+ free(bakname);
+ }
+
+ if (rename(state.tname, filename.str_value.str) < 0)
+ fatal(ext_id, _("inplace_end: rename(`%s', `%s') failed (%s)"),
+ state.tname, filename.str_value.str, strerror(errno));
+ free(state.tname);
+ state.tname = NULL;
+ return make_number(0, result);
+}
+
+static awk_ext_func_t func_table[] = {
+ { "inplace_begin", do_inplace_begin, 2 },
+ { "inplace_end", do_inplace_end, 2 },
+};
+
+static awk_bool_t init_inplace(void)
+{
+ awk_atexit(at_exit, NULL);
+ return awk_true;
+}
+
+static awk_bool_t (*init_func)(void) = init_inplace;
+
+/* define the dl_load function using the boilerplate macro */
+
+dl_load_func(func_table, inplace, "")