aboutsummaryrefslogtreecommitdiffstats
path: root/cppawk-include
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-03-31 06:45:14 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-03-31 06:45:14 -0700
commit4bcda3085764399bf9ae942492ea17aebde987e1 (patch)
tree63abec6c34f3bb52a061e1a3519b964828baa273 /cppawk-include
parenta7c84ea38a2883ba1b33d05d729715ed0acaccad (diff)
downloadcppawk-4bcda3085764399bf9ae942492ea17aebde987e1.tar.gz
cppawk-4bcda3085764399bf9ae942492ea17aebde987e1.tar.bz2
cppawk-4bcda3085764399bf9ae942492ea17aebde987e1.zip
Adding Lisp-inspired data and control utilities.
Diffstat (limited to 'cppawk-include')
-rw-r--r--cppawk-include/base.h3
-rw-r--r--cppawk-include/cons.h719
-rw-r--r--cppawk-include/fun.h54
-rw-r--r--cppawk-include/iter.h166
-rw-r--r--cppawk-include/narg-priv.h6
-rw-r--r--cppawk-include/varg-priv.h392
-rw-r--r--cppawk-include/varg.h45
7 files changed, 1385 insertions, 0 deletions
diff --git a/cppawk-include/base.h b/cppawk-include/base.h
index aa8cada..f22f599 100644
--- a/cppawk-include/base.h
+++ b/cppawk-include/base.h
@@ -42,6 +42,9 @@
#if __gawk__
#define __have_switch 1
+#if __gawk_ver >= 040000
+#define __have_indirect_functions 1
+#endif
#endif
#endif
diff --git a/cppawk-include/cons.h b/cppawk-include/cons.h
new file mode 100644
index 0000000..f5d9671
--- /dev/null
+++ b/cppawk-include/cons.h
@@ -0,0 +1,719 @@
+// cppawk: C preprocessor wrapper around awk
+// 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_CONS_H
+#define __CPPAWK_CONS_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_ITER_H
+#include "iter.h"
+#endif
+
+#ifndef __CPPAWK_CASE_PRIV_H
+#include "case-priv.h"
+#endif
+
+#ifndef __CPPAWK_VARG_PRIV_H
+#include "varg-priv.h"
+#endif
+
+#ifndef __CPPAWK_NARG_PRIV_H
+#include "narg-priv.h"
+#endif
+
+#if __have_indirect_functions
+#ifndef __CPPAWK_FUN_H
+#include "fun.h"
+#endif
+#endif
+
+#define nil ""
+
+#define __prog_first(expr) ((expr) || 1)
+#define __prog_next(prev, \
+ expr) prev && ((expr) || 1)
+#define prog(...) (__varexpand(__prog_first, __prog_next, \
+ __VA_ARGS__))
+
+#define __progn_first(expr) (expr)
+#define __progn_next(prev, \
+ next) ((prev || 1) ? (next) : 0)
+#define progn(...) __varexpand(__progn_first, __progn_next, \
+ __VA_ARGS__)
+
+#define __or_first(expr) (expr)
+#define __or_next(prev, \
+ next) (false(__g(or) = prev) ? (next) : __g(or))
+#define or(...) __varexpand(__or_first, __or_next, \
+ __VA_ARGS__)
+
+#define __and_first(expr) (expr)
+#define __and_next(prev, \
+ next) (false(prev) ? nil : next)
+#define and(...) __varexpand(__and_first, __and_next, \
+ __VA_ARGS__)
+
+
+#define push(item, list) (list = cons(item, list))
+
+#define pop(list) (progn(__g(ol) = (list), \
+ list = cdr(__g(ol)), \
+ car(__g(ol))))
+
+#define dolist(item, list) \
+ for (__g(i) = list; \
+ !endp(__g(i)) && ((item = car(__g(i))) || 1); \
+ __g(i) = cdr(__g(i)))
+
+#define dolisti(item, index, list) \
+ for (prog(__g(i) = list, index = 0); \
+ !endp(__g(i)) && ((item = car(__g(i))) || 1); \
+ prog(__g(i) = cdr(__g(i)), index++))
+
+#define list_begin() ""
+#define list_add(stk, item) (length(item) ":" item stk)
+#define list_end(stk) __unpack(stk)
+
+#define __bag_init_first(x) (x = list_begin())
+#define __bag_init_next(p, x) (p || 1) && __bag_init_first(x)
+
+#define __bag_done_first(x) (x = list_end(x))
+#define __bag_done_next(p, x) (p || 1) && __bag_done_first(x)
+
+#define bags(...) for ((__g(once) = 1) && \
+ __varexpand(__bag_init_first, \
+ __bag_init_next, \
+ __VA_ARGS__); \
+ __g(once) || \
+ __varexpand(__bag_done_first, \
+ __bag_done_next, \
+ __VA_ARGS__) && 0; \
+ __g(once) = 0)
+#define bag(bag, expr) bag = list_add(bag, expr)
+
+#define typecode(obj) (substr(obj, 1, 1))
+
+function consp(__obj)
+{
+ return typecode(__obj) == "C"
+}
+#define consp(obj) (typecode(obj) == "C")
+
+function atom(__obj)
+{
+ return typecode(__obj) != "C"
+}
+#define atom(obj) (typecode(obj) != "C")
+
+function null(__obj)
+{
+ return __obj == nil
+}
+#define null(obj) ((obj) == nil)
+
+function endp(__obj)
+{
+ if (__obj == nil)
+ return 1
+ if (consp(__obj))
+ return nil
+ __error("endp: a proper list ends with nil, not %s", __obj)
+}
+
+#if __config_strict_false
+function false(__obj)
+{
+ return __obj == nil
+}
+#define false(obj) null(obj)
+#else
+function false(__obj)
+{
+ return !obj
+}
+#define false(obj) (!(obj))
+#endif
+
+function true(__obj)
+{
+ return !false(__obj)
+}
+#define true(obj) (!false(obj))
+
+
+function __bs_esc(raw)
+{
+ gsub(/[\\\042]/, "\\\\&", raw)
+ return raw
+}
+
+function nump(__obj)
+{
+ return __obj == 0 || __obj + 0 != 0
+}
+#define nump(obj) ((obj) == 0 || (obj) + 0 != 0)
+
+function tolisp(__raw,
+ __case_temps)
+{
+ __case (typecode(__raw)) {
+ __of ("T", "S", "C")
+ __cret ("T" __raw) // represent as unescaped string
+ __otherwise
+ __cret (__raw)
+ }
+}
+
+function toawk(__obj,
+ __case_temps)
+{
+ __case (typecode(__obj)) {
+ __of ("T", "S")
+ __cret (substr(__obj, 2))
+ __of ("C")
+ __error("toawk: %s looks like a cons", __obj, i)
+ __cbreak
+ __otherwise
+ __cret (__obj)
+ }
+}
+
+function sym(__name)
+{
+ return "S" __name
+}
+
+function cons(__a, __d)
+{
+ return "C" length(__a) "," length(__d) ":" __a __d
+}
+
+function car(__cons,
+ __col, __com, len)
+{
+ if (consp(__cons)) {
+ __col = match(__cons, /:/)
+ __com = match(__cons, /,/)
+ if (__col == 0 || __com == 0 || __col <= __com)
+ __error("car: %s has a malformed cons header", __cons)
+ len = substr(__cons, 2, __com - 2 + 1)
+ return substr(__cons, __col + 1, len)
+ } else if (null(__cons)) {
+ return nil
+ } else {
+ __error("car: %s isn't a cons", __cons)
+ }
+}
+
+function cdr(__cons,
+ __col, __com, __alen, __dlen)
+{
+ if (consp(__cons)) {
+ __col = match(__cons, /:/)
+ __com = match(__cons, /,/)
+ if (__col == 0 || __com == 0 || __col <= __com)
+ __error("car: %s has a malformed cons header", __cons)
+ __alen = substr(__cons, 2, __com - 2 + 1)
+ __dlen = substr(__cons, __com + 1, __col - __com)
+ return substr(__cons, __col + 1 + __alen, __dlen)
+ } else if (null(__cons)) {
+ return nil
+ } else {
+ __error("car: %s isn't a cons", __cons)
+ }
+}
+
+function sexp(__obj,
+ __d, __x, __y, __case_temps)
+{
+ __case (typecode(__obj)) {
+ __of ("C")
+ __d = cdr(__obj)
+ __x = sexp(car(__obj))
+ if (null(__d)) {
+ return "(" __x ")"
+ } else {
+ __y = sexp(__d)
+ if (typecode(__d) == "C")
+ return "(" __x " " substr(__y, 2)
+ else
+ return "(" __x " . " __y ")"
+ }
+ __cbreak
+ __of ("T")
+ __cret ("\"" __bs_esc(substr(__obj, 2)) "\"")
+ __of ("S")
+ __cret (__bs_esc(substr(__obj, 2)))
+ }
+
+ if (nump(__obj)) {
+ return __obj
+ } else if (null(__obj)) {
+ return "nil"
+ } else {
+ return "\"" __bs_esc(__obj) "\""
+ }
+}
+
+function reverse(__list,
+ __tmp)
+{
+ __tmp = nil
+
+ while (!endp(__list)) {
+ push(car(__list), __tmp);
+ __list = cdr(__list);
+ }
+
+ return __tmp;
+}
+
+function atol(__arr,
+ __tmp, __key, __value)
+{
+ __tmp = list_begin()
+
+ doarray (__key, __value, __arr)
+ __tmp = list_add(__tmp,__value)
+
+ return list_end(__tmp)
+}
+
+function ftol( __tmp, __i, __val)
+{
+ __tmp = list_begin()
+
+ dofields (__i, __val)
+ __tmp = list_add(__tmp, __val)
+
+ return list_end(__tmp)
+}
+
+function ltof(__list, __start,
+ __tmp, __item, __n)
+{
+ if (!__present(__start))
+ __start = 1
+
+ dolisti (__item, __n, __list)
+ $(__n + __start) = __item
+
+ NF = __n + __start - 1
+
+ return __n
+}
+
+function keys(__array,
+ __key, __tmp)
+{
+ __tmp = list_begin()
+
+ for (__key in __array)
+ __tmp = list_add(__tmp, __key)
+
+ return list_end(__tmp)
+}
+
+function __slow_equal(__obj1, __obj2,
+ __tc1, __tc2, __case_temps)
+{
+ __tc1 = typecode(__obj1)
+ __tc2 = typecode(__obj2)
+
+ __case (__tc1 __tc2) {
+ __of ("CC")
+ __cret (equal(car(__obj1), car(__obj2)) &&
+ equal(cdr(__obj1), cdr(__obj2)))
+ __matching (/[TSC][TSC]/)
+ __cret (0);
+ }
+
+ if (__tc1 == "T")
+ return toawk(__obj1) == __obj2;
+
+ if (__tc2 == "T")
+ return __obj1 == toawk(__obj2);
+
+ if (nump(__obj1))
+ return __obj1 + 0 == __obj2
+
+ return 0;
+}
+
+function equal(__obj1, __obj2)
+{
+ if (__obj1 == __obj2)
+ return 1;
+ return __slow_equal(__obj1, __obj2)
+}
+
+#define equal(obj1, obj2) ((obj1) == (obj2) ? 1 : __slow_equal(obj1, obj2))
+
+function __unpack(__stk,
+ __col, __out)
+{
+ __out = nil
+
+ while (__stk != "") {
+ __col = match(__stk, /:/)
+ if (__col == 0)
+ break;
+ push(substr(__stk, __col + 1, __stk), __out)
+ __stk = substr(__stk, __col + 1 + __stk);
+ }
+
+ return __out
+}
+
+
+function list(__rest,
+ __check)
+{
+ return __arglist("list", __rest, __check)
+}
+#define __list_first(item) cons(item, nil)
+#define __list_next(list, item) cons(item, list)
+#define li(...) __varexpand(__list_first, \
+ __list_next, \
+ __revarg(__VA_ARGS__))
+
+#define __listar_first(item) item
+#define listar(...) __varexpand(__listar_first, \
+ __list_next, \
+ __revarg(__VA_ARGS__))
+
+function __append(__left, __right,
+ tmp)
+{
+ tmp = reverse(__left)
+ while (!endp(tmp))
+ __right = cons(pop(tmp), __right)
+ return __right
+}
+
+function append(__rest,
+ __count, __out)
+{
+ __varg_count("append", __count, __count)
+ __out = nil
+ __case (__count) {
+ __of (32)
+ __out = __r32
+ __cbreak
+ __of (31)
+ __out = __r31
+ __cbreak
+ __of (30)
+ __out = __r30
+ __cbreak
+ __of (29)
+ __out = __r29
+ __cbreak
+ __of (28)
+ __out = __r28
+ __cbreak
+ __of (27)
+ __out = __r27
+ __cbreak
+ __of (26)
+ __out = __r26
+ __cbreak
+ __of (25)
+ __out = __r25
+ __cbreak
+ __of (24)
+ __out = __r24
+ __cbreak
+ __of (23)
+ __out = __r23
+ __cbreak
+ __of (22)
+ __out = __r22
+ __cbreak
+ __of (21)
+ __out = __r21
+ __cbreak
+ __of (20)
+ __out = __r20
+ __cbreak
+ __of (19)
+ __out = __r19
+ __cbreak
+ __of (18)
+ __out = __r18
+ __cbreak
+ __of (17)
+ __out = __r17
+ __cbreak
+ __of (16)
+ __out = __r16
+ __cbreak
+ __of (15)
+ __out = __r15
+ __cbreak
+ __of (14)
+ __out = __r14
+ __cbreak
+ __of (13)
+ __out = __r13
+ __cbreak
+ __of (12)
+ __out = __r12
+ __cbreak
+ __of (11)
+ __out = __r11
+ __cbreak
+ __of (10)
+ __out = __r10
+ __cbreak
+ __of (9)
+ __out = __r9
+ __cbreak
+ __of (8)
+ __out = __r8
+ __cbreak
+ __of (7)
+ __out = __r7
+ __cbreak
+ __of (6)
+ __out = __r6
+ __cbreak
+ __of (5)
+ __out = __r5
+ __cbreak
+ __of (4)
+ __out = __r4
+ __cbreak
+ __of (3)
+ __out = __r3
+ __cbreak
+ __of (2)
+ __out = __r2
+ __cbreak
+ __of (1)
+ __out = __r1
+ __cbreak
+ }
+ __case (__count - 1) {
+ __of (31)
+ __out = __append(__r31, __out)
+ __cfall
+ __of (30)
+ __out = __append(__r30, __out)
+ __cfall
+ __of (29)
+ __out = __append(__r29, __out)
+ __cfall
+ __of (28)
+ __out = __append(__r28, __out)
+ __cfall
+ __of (27)
+ __out = __append(__r27, __out)
+ __cfall
+ __of (26)
+ __out = __append(__r26, __out)
+ __cfall
+ __of (25)
+ __out = __append(__r25, __out)
+ __cfall
+ __of (24)
+ __out = __append(__r24, __out)
+ __cfall
+ __of (23)
+ __out = __append(__r23, __out)
+ __cfall
+ __of (22)
+ __out = __append(__r22, __out)
+ __cfall
+ __of (21)
+ __out = __append(__r21, __out)
+ __cfall
+ __of (20)
+ __out = __append(__r20, __out)
+ __cfall
+ __of (19)
+ __out = __append(__r19, __out)
+ __cfall
+ __of (18)
+ __out = __append(__r18, __out)
+ __cfall
+ __of (17)
+ __out = __append(__r17, __out)
+ __cfall
+ __of (16)
+ __out = __append(__r16, __out)
+ __cfall
+ __of (15)
+ __out = __append(__r15, __out)
+ __cfall
+ __of (14)
+ __out = __append(__r14, __out)
+ __cfall
+ __of (13)
+ __out = __append(__r13, __out)
+ __cfall
+ __of (12)
+ __out = __append(__r12, __out)
+ __cfall
+ __of (11)
+ __out = __append(__r11, __out)
+ __cfall
+ __of (10)
+ __out = __append(__r10, __out)
+ __cfall
+ __of (9)
+ __out = __append(__r9, __out)
+ __cfall
+ __of (8)
+ __out = __append(__r8, __out)
+ __cfall
+ __of (7)
+ __out = __append(__r7, __out)
+ __cfall
+ __of (6)
+ __out = __append(__r6, __out)
+ __cfall
+ __of (5)
+ __out = __append(__r5, __out)
+ __cfall
+ __of (4)
+ __out = __append(__r4, __out)
+ __cfall
+ __of (3)
+ __out = __append(__r3, __out)
+ __cfall
+ __of (2)
+ __out = __append(__r2, __out)
+ __cfall
+ __of (1)
+ __out = __append(__r1, __out)
+ __cfall
+ }
+
+ return __out
+}
+
+function member(__item, __list)
+{
+ while (!endp(__list)) {
+ if (equal(__item, car(__list)))
+ return __list;
+ __list = cdr(__list)
+ }
+
+ return nil
+}
+
+function position(__item, __list,
+ __pos)
+{
+ for (__pos = 0; !endp(__list); __pos++) {
+ if (equal(__item, car(__list)))
+ return __pos;
+ __list = cdr(__list)
+ }
+
+ return nil
+}
+
+function nth(__pos, __list)
+{
+ for (; __pos > 0 && !endp(__list); __pos--)
+ __list = cdr(__list)
+ return car(__list)
+}
+
+function nthcdr(__pos, __list)
+{
+ for (; __pos > 0 && !endp(__list); __pos--)
+ __list = cdr(__list)
+ return __list
+}
+
+function iota(__from, __to, __step,
+ i, __out)
+{
+ __out = list_begin();
+
+ if (__from < __to) {
+ if (!__present(__step))
+ __step = 1
+ if (__step > 0)
+ for (__i = __from; __i <= __to; __i += __step)
+ __out = list_add(__out, __i)
+ } else {
+ if (!__present(__step))
+ __step = -1
+ if (__step < 0)
+ for (__i = __from; __i >= __to; __i += __step)
+ __out = list_add(__out, __i)
+ }
+
+ return list_end(__out)
+}
+
+function uniq(__list,
+ __out, __item, __seen)
+{
+ __out = list_begin();
+
+ dolist(__item, __list) {
+ if (__item in __seen)
+ continue
+ __seen[__item]
+ __out = list_add(__out, __item)
+ }
+
+ return list_end(__out)
+}
+
+#if __have_indirect_functions
+
+function mapcar(__fun, __list,
+ __temp, __item, out)
+{
+ __temp = list_begin()
+ dolist(__item, __list)
+ __temp = list_add(__temp, call(__fun, __item))
+ return list_end(__temp)
+}
+
+function mappend(__fun, __list,
+ __temp, __item, out)
+{
+ __temp = nil
+ dolist(__item, __list)
+ __temp = __append(__temp, call(__fun, __item))
+ return __temp
+}
+
+#endif
+
+#endif
diff --git a/cppawk-include/fun.h b/cppawk-include/fun.h
new file mode 100644
index 0000000..e14adf5
--- /dev/null
+++ b/cppawk-include/fun.h
@@ -0,0 +1,54 @@
+// cppawk: C preprocessor wrapper around awk
+// 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_FUN_H
+#define __CPPAWK_FUN_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_ITER_H
+#include "iter.h"
+#endif
+
+#ifndef __CPPAWK_CONS_H
+#include "cons.h"
+#endif
+
+#if !__have_indirect_functions
+#warning "<fun.h> requires an Awk with function indirection like newer GNU Awk"
+#endif
+
+#define bind(fname, env) cons(#fname, env)
+#define fun(fname) #fname
+#define call(fobj, ...) (consp(fobj) \
+ ? progn(__g(f) = car(fobj), \
+ @__g(f)(cdr(fobj), __VA_ARGS__)) \
+ : @fobj(__VA_ARGS__))
+
+#endif
diff --git a/cppawk-include/iter.h b/cppawk-include/iter.h
new file mode 100644
index 0000000..57ff81e
--- /dev/null
+++ b/cppawk-include/iter.h
@@ -0,0 +1,166 @@
+// cppawk: C preprocessor wrapper around awk
+// 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_ITER_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_CONS_H
+#include "cons.h"
+#endif
+
+#ifndef __CPPAWK_NARG_PRIV_H
+#include "narg-priv.h"
+#endif
+
+#define doarray(key, value, arr) \
+ for (key in arr) \
+ if ((value = arr[key]) || 1)
+
+#define dostring(index, chr, str) \
+ __g(s) = str; \
+ __g(l) = length(__g(s)); \
+ for (index = 1; index <= __g(l); i++) \
+ if ((chr = substr(__g(s), index, 1)) || 1)
+
+#define dofields(index, val) \
+ for (index = 1; index <= NF; index++) \
+ if ((val = $ index) || 1)
+
+#define loop(...) for (__loop_init(__VA_ARGS__); \
+ (__loop_test(__VA_ARGS__) || \
+ __loop_fini(__VA_ARGS__)) && \
+ __loop_prep(__VA_ARGS__); \
+ __loop_step(__VA_ARGS__))
+
+#define __loop_init(...) prog(__varexpand(__init_first, __init_next, \
+ __VA_ARGS__))
+#define __loop_test(...) __and(__varexpand(__test_first, __test_next, \
+ __VA_ARGS__))
+#define __loop_prep(...) prog(__varexpand(__prep_first, __prep_next, \
+ __VA_ARGS__))
+#define __loop_fini(...) prog(__varexpand(__fini_first, __fini_next, \
+ __VA_ARGS__)) && 0
+#define __loop_step(...) prog(__varexpand(__step_first, __step_next, \
+ __VA_ARGS__))
+
+#define __and(...) __varexpand(__nd_first, __nd_next, __VA_ARGS__)
+#define __nd_first(x) (x)
+#define __nd_next(p, x) p && (x)
+
+#define loop_cross(...) __varexpand2(__cross_first, __cross_next, __VA_ARGS__)
+
+#define __cross_first(args) for (__init_ ## args; \
+ ((__test_ ## args) || \
+ (__fini_ ## args) && 0) && \
+ __prep_ ## args; \
+ __step_ ## args)
+#define __cross_next(prev, args) prev __cross_first(args)
+
+#define __init_first(args) __init_ ## args
+#define __init_next(prev, args) prev, __init_ ## args
+
+#define __test_first(args) __test_ ## args
+#define __test_next(prev, args) prev, __test_ ## args
+
+#define __prep_first(args) __prep_ ## args
+#define __prep_next(prev, args) prev, __prep_ ## args
+
+#define __fini_first(args) __fini_ ## args
+#define __fini_next(prev, args) prev, __fini_ ## args
+
+#define __step_first(args) __step_ ## args
+#define __step_next(prev, args) prev, __step_ ## args
+
+#define __init_str(idx, ch, str) idx = 1
+#define __test_str(idx, ch, str) idx <= length(str)
+#define __prep_str(idx, ch, str) ch = substr(str, idx, 1)
+#define __fini_str(idx, ch, str) 1
+#define __step_str(idx, ch, str) idx++
+
+#define __init_range(idx, from, to) idx = (from)
+#define __test_range(idx, from, to) idx <= (to)
+#define __prep_range(idx, from, to) 1
+#define __fini_range(idx, from, to) 1
+#define __step_range(idx, from, to) idx++
+
+#define __init_range_step(idx, from, to, step) idx = (from)
+#define __test_range_step(idx, from, to, step) idx <= (to)
+#define __prep_range_step(idx, from, to, step) 1
+#define __fini_range_step(idx, from, to, step) 1
+#define __step_range_step(idx, from, to, step) idx += (step)
+
+#define __init_from(idx, from) idx = (from)
+#define __test_from(idx, from) 1
+#define __prep_from(idx, from) 1
+#define __fini_from(idx, from) 1
+#define __step_from(idx, from) idx++
+
+#define __init_from_step(idx, from, step) idx = (from)
+#define __test_from_step(idx, from, step) 1
+#define __prep_from_step(idx, from, step) 1
+#define __fini_from_step(idx, from, step) 1
+#define __step_from_step(idx, from, step) idx += (step)
+
+#define __init_list(iter, var, list) iter = (list)
+#define __test_list(iter, var, list) !endp(iter)
+#define __prep_list(iter, var, list) var = car(list)
+#define __fini_list(iter, var, list) 0
+#define __step_list(iter, var, list) iter = cdr(iter)
+
+#define __init_fields(var) __g(var) = 1
+#define __test_fields(var) __g(var) <= NF
+#define __prep_fields(var) var = $ __g(var)
+#define __fini_fields(var) 1
+#define __step_fields(var) __g(var)++
+
+#define __init_keys(key, array) __g(key) = keys(array)
+#define __test_keys(key, array) !endp(__g(key))
+#define __prep_keys(key, array) key = car(__g(key))
+#define __fini_keys(key, array) 1
+#define __step_keys(key, array) __g(key) = cdr(__g(key))
+
+#define __init_collect(var, expr) var = list_begin()
+#define __test_collect(var, expr) 1
+#define __prep_collect(var, expr) var = list_add(var, expr)
+#define __fini_collect(var, expr) var = list_end(var)
+#define __step_collect(var, expr) 1
+
+#define __init_lockstep(...) prog(__varexpand3(__init_first, __init_next, \
+ __VA_ARGS__))
+#define __test_lockstep(...) __and(__varexpand3(__test_first, __test_next, \
+ __VA_ARGS__))
+#define __prep_lockstep(...) (__and(__varexpand3(__prep_first, __prep_next, \
+ __VA_ARGS__)) || 1)
+#define __fini_lockstep(...) (__and(__varexpand3(__fini_first, __fini_next, \
+ __VA_ARGS__)) && 0)
+#define __step_lockstep(...) prog(__varexpand3(__step_first, __step_next, \
+ __VA_ARGS__))
+
+#endif
diff --git a/cppawk-include/narg-priv.h b/cppawk-include/narg-priv.h
index 6a96080..73a00b1 100644
--- a/cppawk-include/narg-priv.h
+++ b/cppawk-include/narg-priv.h
@@ -155,6 +155,12 @@
#define __varexpand(mac1, mac2, ...) \
__xcat(__repn_, __narg(__VA_ARGS__)) (mac1, mac2, __VA_ARGS__)
+#define __varexpand2(mac1, mac2, ...) \
+ __xcat(__repn_, __narg(__VA_ARGS__)) (mac1, mac2, __VA_ARGS__)
+
+#define __varexpand3(mac1, mac2, ...) \
+ __xcat(__repn_, __narg(__VA_ARGS__)) (mac1, mac2, __VA_ARGS__)
+
#define __rev_first(arg) arg
#define __rev_next(args, arg) arg, args
#define __revarg(...) __varexpand(__rev_first, __rev_next, __VA_ARGS__)
diff --git a/cppawk-include/varg-priv.h b/cppawk-include/varg-priv.h
new file mode 100644
index 0000000..33616fd
--- /dev/null
+++ b/cppawk-include/varg-priv.h
@@ -0,0 +1,392 @@
+// cppawk: C preprocessor wrapper around awk
+// 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_VARG_PRIV_H
+#define __CPPAWK_VARG_PRIV_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_CASE_PRIV_H
+#include "case-priv.h"
+#endif
+
+#ifndef __CPPAWK_CONS_H
+#include "cons.h"
+#endif
+
+#define __rest \
+ __r1, __r2, __r3, __r4, __r5, __r6, __r7, __r8, __r9, __r10, __r11, \
+ __r12, __r13, __r14, __r15, __r16, __r17, __r18, __r19, __r20, __r21, \
+ __r22, __r23, __r24, __r25, __r26, __r27, __r28, __r29, __r30, __r31, __r32
+
+#define __varg_count(name, check, count) \
+ if (__present(check)) \
+ __error(name ": too many arguments"); \
+ count = 0; \
+ if (__present(__r16)) { \
+ if (__present(__r24)) { \
+ if (__present(__r28)) { \
+ if (__present(__r30)) { \
+ if (__present(__r31)) { \
+ if (__present(__r32)) \
+ count = 32; \
+ else \
+ count = 31; \
+ } else { \
+ count = 30; \
+ } \
+ } else { /* !__present(__r30) */ \
+ if (__present(__r29)) \
+ count = 29; \
+ else \
+ count = 28; \
+ } \
+ } else { /* !__present(__r28) */ \
+ if (__present(__r26)) { \
+ if (__present(__r27)) \
+ count = 27; \
+ else \
+ count = 26; \
+ } else { /* !__present(__r26) */ \
+ if (__present(__r25)) \
+ count = 25; \
+ else \
+ count = 24; \
+ } \
+ } \
+ } else { /* !__present(__r24) */ \
+ if (__present(__r20)) { \
+ if (__present(__r22)) { \
+ if (__present(__r23)) \
+ count = 23; \
+ else \
+ count = 22; \
+ } else { /* !__present(__r22) */ \
+ if (__present(__r21)) \
+ count = 21; \
+ else \
+ count = 20; \
+ } \
+ } else { /* !__present(__r20) */ \
+ if (__present(__r18)) { \
+ if (__present(__r19)) \
+ count = 19; \
+ else \
+ count = 18; \
+ } else { /* !__present(__r18) */ \
+ if (__present(__r17)) \
+ count = 17; \
+ else \
+ count = 16; \
+ } \
+ } \
+ } \
+ } else { /*!__present(__r16) */ \
+ if (__present(__r8)) { \
+ if (__present(__r12)) { \
+ if (__present(__r14)) { \
+ if (__present(__r15)) { \
+ count = 15; \
+ } else { \
+ count = 14; \
+ } \
+ } else { /* !__present(__r14) */ \
+ if (__present(__r13)) \
+ count = 13; \
+ else \
+ count = 12; \
+ } \
+ } else { /* !__present(__r12) */ \
+ if (__present(__r10)) { \
+ if (__present(__r11)) \
+ count = 11; \
+ else \
+ count = 10; \
+ } else { /* !__present(__r10) */ \
+ if (__present(__r9)) \
+ count = 9; \
+ else \
+ count = 8; \
+ } \
+ } \
+ } else { /* !__present(__r8) */ \
+ if (__present(__r4)) { \
+ if (__present(__r6)) { \
+ if (__present(__r7)) \
+ count = 7; \
+ else \
+ count = 6; \
+ } else { /* !__present(__r6) */ \
+ if (__present(__r5)) \
+ count = 5; \
+ else \
+ count = 4; \
+ } \
+ } else { /* !__present(__r4) */ \
+ if (__present(__r2)) { \
+ if (__present(__r3)) \
+ count = 3; \
+ else \
+ count = 2; \
+ } else { /* !__present(__r2) */ \
+ if (__present(__r1)) \
+ count = 1; \
+ } \
+ } \
+ } \
+ }
+
+#define __varg_list(name, check, count, out) \
+ __varg_count(name, check, count); \
+ out = nil; \
+ __case (count) { \
+ __of (32) \
+ out = cons(__r32, out); \
+ __cfall; \
+ __of (31) \
+ out = cons(__r31, out); \
+ __cfall; \
+ __of (30) \
+ out = cons(__r30, out); \
+ __cfall; \
+ __of (29) \
+ out = cons(__r29, out); \
+ __cfall; \
+ __of (28) \
+ out = cons(__r28, out); \
+ __cfall; \
+ __of (27) \
+ out = cons(__r27, out); \
+ __cfall; \
+ __of (26) \
+ out = cons(__r26, out); \
+ __cfall; \
+ __of (25) \
+ out = cons(__r25, out); \
+ __cfall; \
+ __of (24) \
+ out = cons(__r24, out); \
+ __cfall; \
+ __of (23) \
+ out = cons(__r23, out); \
+ __cfall; \
+ __of (22) \
+ out = cons(__r22, out); \
+ __cfall; \
+ __of (21) \
+ out = cons(__r21, out); \
+ __cfall; \
+ __of (20) \
+ out = cons(__r20, out); \
+ __cfall; \
+ __of (19) \
+ out = cons(__r19, out); \
+ __cfall; \
+ __of (18) \
+ out = cons(__r18, out); \
+ __cfall; \
+ __of (17) \
+ out = cons(__r17, out); \
+ __cfall; \
+ __of (16) \
+ out = cons(__r16, out); \
+ __cfall; \
+ __of (15) \
+ out = cons(__r15, out); \
+ __cfall; \
+ __of (14) \
+ out = cons(__r14, out); \
+ __cfall; \
+ __of (13) \
+ out = cons(__r13, out); \
+ __cfall; \
+ __of (12) \
+ out = cons(__r12, out); \
+ __cfall; \
+ __of (11) \
+ out = cons(__r11, out); \
+ __cfall; \
+ __of (10) \
+ out = cons(__r10, out); \
+ __cfall; \
+ __of (9) \
+ out = cons(__r9, out); \
+ __cfall; \
+ __of (8) \
+ out = cons(__r8, out); \
+ __cfall; \
+ __of (7) \
+ out = cons(__r7, out); \
+ __cfall; \
+ __of (6) \
+ out = cons(__r6, out); \
+ __cfall; \
+ __of (5) \
+ out = cons(__r5, out); \
+ __cfall; \
+ __of (4) \
+ out = cons(__r4, out); \
+ __cfall; \
+ __of (3) \
+ out = cons(__r3, out); \
+ __cfall; \
+ __of (2) \
+ out = cons(__r2, out); \
+ __cfall; \
+ __of (1) \
+ out = cons(__r1, out); \
+ __cfall; \
+ }
+
+#define __varg_array(name, check, count, out) \
+ __varg_count(name, check, count); \
+ delete out; \
+ __case (count) { \
+ __of (32) \
+ out[32] = __r32; \
+ __cfall; \
+ __of (31) \
+ out[31] = __r31; \
+ __cfall; \
+ __of (30) \
+ out[30] = __r30; \
+ __cfall; \
+ __of (29) \
+ out[29] = __r29; \
+ __cfall; \
+ __of (28) \
+ out[28] = __r28; \
+ __cfall; \
+ __of (27) \
+ out[27] = __r27; \
+ __cfall; \
+ __of (26) \
+ out[26] = __r26; \
+ __cfall; \
+ __of (25) \
+ out[25] = __r25; \
+ __cfall; \
+ __of (24) \
+ out[24] = __r24; \
+ __cfall; \
+ __of (23) \
+ out[23] = __r23; \
+ __cfall; \
+ __of (22) \
+ out[22] = __r22; \
+ __cfall; \
+ __of (21) \
+ out[21] = __r21; \
+ __cfall; \
+ __of (20) \
+ out[20] = __r20; \
+ __cfall; \
+ __of (19) \
+ out[19] = __r19; \
+ __cfall; \
+ __of (18) \
+ out[18] = __r18; \
+ __cfall; \
+ __of (17) \
+ out[17] = __r17; \
+ __cfall; \
+ __of (16) \
+ out[16] = __r16; \
+ __cfall; \
+ __of (15) \
+ out[15] = __r15; \
+ __cfall; \
+ __of (14) \
+ out[14] = __r14; \
+ __cfall; \
+ __of (13) \
+ out[13] = __r13; \
+ __cfall; \
+ __of (12) \
+ out[12] = __r12; \
+ __cfall; \
+ __of (11) \
+ out[11] = __r11; \
+ __cfall; \
+ __of (10) \
+ out[10] = __r10; \
+ __cfall; \
+ __of (9) \
+ out[9] = __r9; \
+ __cfall; \
+ __of (8) \
+ out[8] = __r8; \
+ __cfall; \
+ __of (7) \
+ out[7] = __r7; \
+ __cfall; \
+ __of (6) \
+ out[6] = __r6; \
+ __cfall; \
+ __of (5) \
+ out[5] = __r5; \
+ __cfall; \
+ __of (4) \
+ out[4] = __r4; \
+ __cfall; \
+ __of (3) \
+ out[3] = __r3; \
+ __cfall; \
+ __of (2) \
+ out[2] = __r2; \
+ __cfall; \
+ __of (1) \
+ out[1] = __r1; \
+ __cfall; \
+ }
+
+function __argcount(__name, __rest,
+ __narg, // check argument; doubles as local count
+ __case_temps)
+{
+ __varg_count(__name, __narg, __narg)
+ return __narg;
+}
+
+function __arglist(__name, __rest,
+ __narg, // check argument; doubles as local count
+ __out, __case_temps)
+{
+ __varg_list(__name, __narg, __narg, __out)
+ return __out;
+}
+
+function __argarray(__name, __to_array, __rest,
+ __narg, // check argument; doubles as local count
+ __case_temps)
+{
+ __varg_array(__name, __narg, __narg, __to_array)
+}
+
+#endif
diff --git a/cppawk-include/varg.h b/cppawk-include/varg.h
new file mode 100644
index 0000000..5c1659e
--- /dev/null
+++ b/cppawk-include/varg.h
@@ -0,0 +1,45 @@
+// cppawk: C preprocessor wrapper around awk
+// 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_VARG_H
+#define __CPPAWK_VARG_H
+
+#ifndef __CPPAWK_BASE_H
+#include "base.h"
+#endif
+
+#ifndef __CPPAWK_VARG_PRIV_H
+#include "varg-priv.h"
+#endif
+
+#define restargs __rest
+#define present(arg) __present(arg)
+#define argcount __argcount
+#define arglist __arglist
+#define argarray __argarray
+
+#endif