diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-03-31 06:45:14 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-03-31 06:45:14 -0700 |
commit | 4bcda3085764399bf9ae942492ea17aebde987e1 (patch) | |
tree | 63abec6c34f3bb52a061e1a3519b964828baa273 | |
parent | a7c84ea38a2883ba1b33d05d729715ed0acaccad (diff) | |
download | cppawk-4bcda3085764399bf9ae942492ea17aebde987e1.tar.gz cppawk-4bcda3085764399bf9ae942492ea17aebde987e1.tar.bz2 cppawk-4bcda3085764399bf9ae942492ea17aebde987e1.zip |
Adding Lisp-inspired data and control utilities.
-rw-r--r-- | cppawk-include/base.h | 3 | ||||
-rw-r--r-- | cppawk-include/cons.h | 719 | ||||
-rw-r--r-- | cppawk-include/fun.h | 54 | ||||
-rw-r--r-- | cppawk-include/iter.h | 166 | ||||
-rw-r--r-- | cppawk-include/narg-priv.h | 6 | ||||
-rw-r--r-- | cppawk-include/varg-priv.h | 392 | ||||
-rw-r--r-- | cppawk-include/varg.h | 45 |
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 |