aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--cppawk-field.1188
-rw-r--r--cppawk-include/field.h88
-rwxr-xr-xruntests5
-rw-r--r--testcases-field176
5 files changed, 460 insertions, 2 deletions
diff --git a/README.md b/README.md
index e35440b..8cfc05d 100644
--- a/README.md
+++ b/README.md
@@ -147,9 +147,10 @@ There are currently
* [`<varg.h>`](../tree/cppawk-varg.1): utilities for working with
variadic functions in Awk, as well as with optional arguments.
-Several unreleased headers are in the development queue:
+* [`<field.h>`](../tree/cppawk-field.1): utilities for manipulating
+ the Awk positional parameters ("fields").
-* `<field.h>`: utilities for manipulating fields.
+Several unreleased headers are in the development queue:
* `<array.h>`: some associative array utilities.
diff --git a/cppawk-field.1 b/cppawk-field.1
new file mode 100644
index 0000000..6389540
--- /dev/null
+++ b/cppawk-field.1
@@ -0,0 +1,188 @@
+.\" cppawk: C preprocessor wrapper around awk
+.\" Copyright 2022 Kaz Kylheku <kaz@kylheku.com>
+.\"
+.\" BSD-2 License
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright notice,
+.\" this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright notice,
+.\" this list of conditions and the following disclaimer in the documentation
+.\" and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.de bk
+.IP " "
+.PP
+..
+.TH CPPAWK-FIELD 1 "19 April 2022" "cppawk Libraries" "Field Utilities"
+
+.SH NAME
+.I field
+\- utilities for working with positional parameters ("fields")
+
+.SH SYNOPSIS
+.ft B
+ #include <field.h>
+
+ delf(\fIi\fP[, \fIn\fP]) \fI// delete n fields starting with i.\fP
+ insf(\fIi\fP, ...) \fI// insert one or more fields at position i.\fP
+.ft R
+
+.SH DESCRIPTION
+.bk
+The
+.I <field.h>
+header provides utilities for performing bulk operations on Awk positional
+parameters, also referred to as fields.
+
+.SS Function \fIdelf\fP
+.bk
+.B Syntax:
+
+.ft B
+ delf(\fIi\fP[ ,\fIn\fP])
+.ft R
+
+.B Description:
+
+The
+.B delf
+function deletes
+.I n
+fields starting at field
+.IR i .
+
+If
+.I i
+exceeds
+.B NF
+or is less than
+.BR 1 ,
+or if
+.I n
+is less than 1, the function has no effect.
+
+If
+.I n
+is omitted, it defaults to 1: one field is deleted.
+
+If there are fields after the deleted fields, they are relocated so
+that they start at position
+.I i
+and
+.B NF
+is adjusted accordingly.
+
+If there are are only
+.B n
+or fewer fields starting at position
+.BR i ,
+then no fields have to be moved. In this case,
+.B NF
+is simply adjusted to the value of
+.I i
+.B "- 1"
+to trim the fields away.
+
+In all cases when
+.B NF
+is adjusted or fields are moved, the record
+.B $0
+is re-calculated in accordance with the Awk semantics for field manipulation.
+
+.SS Macro \fIinsf\fP
+.bk
+.B Syntax:
+
+.ft B
+ insf(\fIi\fP, ...)
+.ft R
+
+.B Description:
+
+The
+.B insf
+macro expands to a statement which inserts one or more fields at position
+.IR i .
+The number of fields inserted is determined by the number of variable
+arguments after
+.IR i ,
+of which there must be between 1 and 32. These are the
+.IR "field arguments" .
+
+If
+.I i
+is less than 1, there is no effect. In that case, the argument expressions
+which give the inserted field values are also not evaluated.
+
+Let
+.I n
+be the number of field arguments being inserted.
+
+The
+.I i
+argument may be greater than
+.BR NF ,
+in which case the specified fields are created, and
+.B NF
+is adjusted to include all of them in the position parameter array;
+.B NF
+will take on the value
+.I i
+.B +
+.IR n .
+
+If
+.I i
+is between 1 and
+.BR NF ,
+then the existing fields from
+.I i
+to
+.B NF
+move to higher positions to create a space for the inserted fields.
+Field
+.BI $ i
+moves to
+.BI $( i " + " n )
+and so forth. Then the
+.I n
+field parameters are assigned into the positions
+.BI $ i \fR,\fP
+.BI $( i " + 1)" \fR,\fP
+\fR...,\fP
+.BI $( i " + " n " - 1)" \fR.\fP
+
+In all cases when
+.B NF
+is adjusted and fields are assigned or moved, the record
+.B $0
+is re-calculated in accordance with the Awk semantics for field manipulation.
+
+.SH SEE ALSO
+cppawk(1), cppawk-cons(1)
+
+.SH BUGS
+The
+.B insf
+function is limited to 32 variadic arguments.
+
+.SH AUTHOR
+Kaz Kylheku <kaz@kylheku.com>
+
+.SH COPYRIGHT
+Copyright 2022, BSD2 License.
diff --git a/cppawk-include/field.h b/cppawk-include/field.h
new file mode 100644
index 0000000..a18000d
--- /dev/null
+++ b/cppawk-include/field.h
@@ -0,0 +1,88 @@
+// cppawk: C preprocessor wrapper around awk
+// Copyright 2022 Kaz Kylheku <kaz@kylheku.com>
+//
+// BSD-2 License
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef __CPPAWK_FIELD_H
+#define __CPPAWK_FIELD_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_NARG_PRIV_H
+#include "narg-priv.h"
+#endif
+
+function delf(__at, __count,
+ __i, __j)
+{
+ if (!__present(__count))
+ __count = 1
+
+ if (0 < __count && 1 <= __at && __at <= NF) {
+ __i = __at
+ __j = __at + __count
+
+ while (__j <= NF)
+ $(__i++) = $(__j++)
+
+ NF = __i - 1;
+ }
+}
+
+function __insf(__at, __count,
+ __i, __j)
+{
+ if (!__present(__count))
+ __count = 1
+
+ if (NF < __at)
+ NF = __at - 1
+
+ if (0 < __count && 1 <= __at) {
+ __i = NF + __count
+ __j = NF
+
+ NF = __i
+
+ while (__j >= __at)
+ $(__i--) = $(__j--)
+ return 1
+ }
+
+ return 0
+}
+
+#define __insf_first(arg, n, at) $(at + n - 1) = arg
+#define __insf_next(prev, arg, n, at) prev; $(at + n - 1) = arg
+
+#define insf(at, ...) { \
+ if (__insf(at, __narg(__VA_ARGS__))) { \
+ __variaexpand(__insf_first, __insf_next, at, __VA_ARGS__); \
+ } \
+}
+
+#endif
diff --git a/runtests b/runtests
index 457df59..6216efc 100755
--- a/runtests
+++ b/runtests
@@ -31,3 +31,8 @@ if [ -z "$suite" -o "$suite" = "cons" ] ; then
cppawk=./cppawk ./testsuite.awk testcases-cons
cppawk="./cppawk --awk=mawk" ./testsuite.awk -v skip=37,38 testcases-cons
fi
+
+if [ -z "$suite" -o "$suite" = "field" ] ; then
+ cppawk=./cppawk ./testsuite.awk testcases-field
+ cppawk="./cppawk --awk=mawk" ./testsuite.awk testcases-field
+fi
diff --git a/testcases-field b/testcases-field
new file mode 100644
index 0000000..788f325
--- /dev/null
+++ b/testcases-field
@@ -0,0 +1,176 @@
+1:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = ""
+ delf(1, 0)
+ pf
+ delf(1, 5)
+ pf
+ delf(3, 5)
+ pf
+}'
+:
+nil
+nil
+nil
+--
+2:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = "1 2 3 4"
+ delf(1, 1)
+ pf
+ delf(2, 1)
+ pf
+ delf(3, 0)
+ pf
+ delf(0, 0)
+ pf
+ delf(1, 2)
+ pf
+}'
+:
+(2 3 4)
+(2 4)
+(2 4)
+(2 4)
+nil
+--
+3:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = "1 2 3 4 5"
+ delf(1)
+ pf
+ delf(1)
+ pf
+ delf(1, 10)
+ pf
+}'
+:
+(2 3 4 5)
+(3 4 5)
+nil
+--
+4:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = "1 2 3 4 5"
+ delf(5)
+ pf
+ delf(4)
+ pf
+ delf(3, 15)
+ pf
+ delf(2, 1000)
+ pf
+ delf(1)
+ pf
+}'
+:
+(1 2 3 4)
+(1 2 3)
+(1 2)
+(1)
+nil
+--
+5:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = "1 2 3 4 5"
+ delf(4, 13)
+ pf
+}'
+:
+(1 2 3)
+--
+6:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = "1 2 3 4 5"
+ delf(2, 3)
+ pf
+}'
+:
+(1 5)
+--
+7:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = ""
+ insf(1, 1)
+ pf
+ insf(2, 2)
+ pf
+ insf(3, 3)
+ pf
+ insf(4, 4, 5, 6)
+ pf
+}'
+:
+(1)
+(1 2)
+(1 2 3)
+(1 2 3 4 5 6)
+--
+8:
+$cppawk '
+#include <cons.h>
+#include <field.h>
+
+#define pf {print sexp(fields())}
+
+BEGIN {
+ $0 = ""
+ insf(3, 3, 4)
+ pf
+ insf(5, 5, 6)
+ pf
+ insf(9, 9)
+ pf
+ insf(0, 1, 2, 3)
+ pf
+ insf(1, 1, 2)
+ pf
+}'
+:
+(nil nil 3 4)
+(nil nil 3 4 5 6)
+(nil nil 3 4 5 6 nil nil 9)
+(nil nil 3 4 5 6 nil nil 9)
+(1 2 nil nil 3 4 5 6 nil nil 9)