// cppawk: C preprocessor wrapper around awk // Copyright 2022 Kaz Kylheku // // 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_PRIV_H #define __CPPAWK_CONS_PRIV_H #ifndef __CPPAWK_BASE_H #include "base.h" #endif #ifndef __CPPAWK_ITER_PRIV_H #include "iter-priv.h" #endif #ifndef __CPPAWK_CASE_PRIV_H #include "case-priv.h" #endif #ifndef __CPPAWK_NARG_PRIV_H #include "narg-priv.h" #endif #if __have_indirect_functions #ifndef __CPPAWK_FUN_PRIV_H #include "fun-priv.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) ((__g(or) = prev) ? __g(or) : (next)) #define __or(...) __varexpand(__or_first, __or_next, \ __VA_ARGS__) #define __and_first(expr) (expr) #define __and_next(prev, \ next) ((__g(and) = prev) ? next : __g(and)) #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 __doconses(iter, list) \ for (iter = list; __consp(iter); iter = __cdr(iter)) #define __list_begin() "" #define __list_add(stk, item) __pack(stk, item) #define __list_end(stk) __unpack(stk, __nil) #define __list_end_atom(stk, atom) __unpack(stk, atom) #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 && __obj != 0 } function __endp(__obj) { if (__obj == __nil && __obj != 0) return 1 if (__consp(__obj)) return 0 __error("endp: a proper list ends with nil, not %s", __obj) } function __bs_esc(raw) { gsub(/[\\\042]/, "\\\\&", raw) return raw } function __numberp(__obj) { return __obj != "" && (__obj == 0 || __obj + 0 != 0) } #define __numberp(obj) (obj != "" && ((obj) == 0 || (obj) + 0 != 0)) function __stringp(__obj) { return __typecode(__obj) == "T" } #define __stringp(obj) (__typecode(obj) == "T") function __symbolp(__obj) { return __obj != 0 && __typecode(__obj) ~ /^S?$/ } function __box(__raw, __check, __case_temps) { if (!__present(__raw)) return "U"; if (__present(__check)) __error("box; excess argument %s", __check) if (__numberp(__raw)) return __raw; return "T" __raw; } function __unbox(__obj, __check, __case_temps) { if (!__present(__obj)) __error("unbox: missing or undefined argument") if (__present(__check)) __error("unbox; excess argument %s", __check) __case (__typecode(__obj)) { __of ("T", "S") __cret (substr(__obj, 2)) __of ("C") __error("unbox: %s looks like a cons", __obj) __cbreak __of ("U") __cret(__check) __of ("") __cret("nil") __otherwise if (!__numberp(__obj)) __error("unbox: %s isn't symbol, number or boxed string", __obj) __cret (__obj) } } function __box_str(__str) { return "T" __str } #define __box_str(str) ("T" (str)) function __box_sym(__name) { return __name == "nil" ? __nil : "S" __name } function __cons(__a, __d) { return "C" length(__a) "," length(__d) ":" __a __d } function __car(__cell, __col, __com, len) { if (__consp(__cell)) { __col = match(__cell, /:/) __com = match(__cell, /,/) if (__col == 0 || __com == 0 || __col <= __com) __error("car: %s has a malformed cons header", __cell) len = substr(__cell, 2, __com - 2 + 1) return substr(__cell, __col + 1, len) } else if (__null(__cell)) { return __nil } else { __error("car: %s isn't a cons", __cell) } } function __cdr(__cell, __col, __com, __alen, __dlen) { if (__consp(__cell)) { __col = match(__cell, /:/) __com = match(__cell, /,/) if (__col == 0 || __com == 0 || __col <= __com) __error("cdr: %s has a malformed cons header", __cell) __alen = substr(__cell, 2, __com - 2 + 1) __dlen = substr(__cell, __com + 1, __col - __com) return substr(__cell, __col + 1 + __alen, __dlen) } else if (__null(__cell)) { return __nil } else { __error("cdr: %s isn't a cons", __cell) } } function __sexp(__obj, __d, __x, __y, __case_temps) { if (!__present(__obj)) __error("sexp: missing or undefined argument") __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))) __of ("U") __cret ("#U") } if (__numberp(__obj)) { return __obj } else if (__null(__obj)) { return "nil" } else { return "\"" __bs_esc(__obj) "\"" } } function __reverse(__lst, __tmp) { __tmp = __nil while (!__endp(__lst)) { __push(__car(__lst), __tmp); __lst = __cdr(__lst); } return __tmp; } function __values(__arr, __tmp, __key, __value) { __tmp = __list_begin() __doarray (__key, __value, __arr) __tmp = __list_add(__tmp,__value) return __list_end(__tmp) } function __keys(__array, __key, __tmp) { __tmp = __list_begin() for (__key in __array) __tmp = __list_add(__tmp, __key) return __list_end(__tmp) } function __fields(__start, __count, __tmp, __end, __val) { if (!__present(__start)) __start = 1 if (!__present(__count)) __count = NF - __start + 1 if (__count < 1) return __nil __end = __start + __count - 1 if (__end > NF) __end = NF if (__start < 1) __start = 1 if (__start > __end) return __nil __tmp = __list_begin() for (; __start <= __end; __start++) __tmp = __list_add(__tmp, $(__start)) return __list_end(__tmp) } function __set_fields(__lst, __start, __tmp, __item, __n) { if (!__present(__start)) __start = 1 __dolisti (__item, __n, __lst) $(__n + __start) = __item NF = __n + __start - 1 return __n } 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 __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 (/[UTSC][UTSC]/) __cret (0); } if (__tc1 == "T") return __numberp(__obj2) ? 0 : (__obj1 == __box_str(__obj2)) if (__tc2 == "T") return __numberp(__obj1) ? 0 : (__box_str(__obj1) == __obj2) if (__numberp(__obj1) && __numberp(__obj2)) return __obj1 + 0 == __obj2 + 0 return 0 } function __equalize(__obj, __tc, __str) { if (!__present(__obj)) return "" __tc = __typecode(__obj) __case (__tc) { __of("C") __cret (__cons(__equalize(__car(__obj)), __equalize(__cdr(__obj)))) __of("T", "S", "U", "") __cret (__obj) } if (__numberp(__obj)) return __obj + 0 return __box_str(__obj) } function __pack(__stk, __item) { return length(__item) ":" __item __stk } function __unpack(__stk, __out, __col) { while (__stk != "") { __col = match(__stk, /:/) if (__col == 0) break; __push(substr(__stk, __col + 1, __stk), __out) __stk = substr(__stk, __col + 1 + __stk); } return __out } #ifndef __CPPAWK_VARG_PRIV_H #include "varg-priv.h" #endif 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 __append2(__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 = __append2(__r31, __out) __cfall __of (30) __out = __append2(__r30, __out) __cfall __of (29) __out = __append2(__r29, __out) __cfall __of (28) __out = __append2(__r28, __out) __cfall __of (27) __out = __append2(__r27, __out) __cfall __of (26) __out = __append2(__r26, __out) __cfall __of (25) __out = __append2(__r25, __out) __cfall __of (24) __out = __append2(__r24, __out) __cfall __of (23) __out = __append2(__r23, __out) __cfall __of (22) __out = __append2(__r22, __out) __cfall __of (21) __out = __append2(__r21, __out) __cfall __of (20) __out = __append2(__r20, __out) __cfall __of (19) __out = __append2(__r19, __out) __cfall __of (18) __out = __append2(__r18, __out) __cfall __of (17) __out = __append2(__r17, __out) __cfall __of (16) __out = __append2(__r16, __out) __cfall __of (15) __out = __append2(__r15, __out) __cfall __of (14) __out = __append2(__r14, __out) __cfall __of (13) __out = __append2(__r13, __out) __cfall __of (12) __out = __append2(__r12, __out) __cfall __of (11) __out = __append2(__r11, __out) __cfall __of (10) __out = __append2(__r10, __out) __cfall __of (9) __out = __append2(__r9, __out) __cfall __of (8) __out = __append2(__r8, __out) __cfall __of (7) __out = __append2(__r7, __out) __cfall __of (6) __out = __append2(__r6, __out) __cfall __of (5) __out = __append2(__r5, __out) __cfall __of (4) __out = __append2(__r4, __out) __cfall __of (3) __out = __append2(__r3, __out) __cfall __of (2) __out = __append2(__r2, __out) __cfall __of (1) __out = __append2(__r1, __out) __cfall } return __out } function __member(__item, __lst) { while (!__endp(__lst)) { if (__equal(__item, __car(__lst))) return __lst; __lst = __cdr(__lst) } return __nil } function __position(__item, __lst, __pos) { for (__pos = 0; !__endp(__lst); __pos++) { if (__equal(__item, __car(__lst))) return __pos; __lst = __cdr(__lst) } return __nil } function __nth(__pos, __lst) { for (; __pos > 0 && !__endp(__lst); __pos--) __lst = __cdr(__lst) return __pos == 0 ? __car(__lst) : __nil } function __nthcdr(__pos, __lst) { for (; __pos > 0 && !__endp(__lst); __pos--) __lst = __cdr(__lst) return __lst } function __ldiff(__main, __tail, __out, __iter) { if (__null(__main)) return __nil if (__null(__tail)) return __main __out = __list_begin() __doconses (__iter, __main) { if (__iter == __tail) break __out = __list_add(__out, __car(__iter)) } if (__atom(__iter) && __iter != __tail) return __list_end_atom(__out, __iter) return __list_end(__out) } function __last(__lst, __n, __circbuf, __i) { if (!__present(__n)) __n = 1 else if (__n < 0) __error("last: number argument %s must be non-negative", __n) if (__n == 0) { __doconses (__iter, __lst) ; // nothing return __iter } delete __circbuf __i = 0 __n++ __doconses (__iter, __lst) __circbuf[__i++ % __n] = __iter __i = (__i + 1) % __n return (__i in __circbuf) ? __circbuf[__i] : __lst } function __butlast(__lst, __n, __circbuf, __i, __out) { if (!__present(__n)) __n = 1 else if (__n < 0) __error("butlast: number argument %s must be non-negative", __n) __out = __list_begin() if (__n == 0) { __doconses (__iter, __lst) __out = __list_add(__out, __car(__iter)) return __list_end(__out) } delete __circbuf __i = 0 __n++ __doconses (__iter, __lst) { __circbuf[__i++ % __n] = __out __out = __list_add(__out, __car(__iter)) } __i = (__i + 1) % __n return (__i in __circbuf) ? __list_end(__circbuf[__i]) : __nil } function __iota(__from, __to, __delta, __out, __i, __val) { __out = __list_begin(); if (__from < __to) { if (!__present(__delta)) __delta = 1 if (__delta <= 0) return __nil; __i = 0 __val = __from while (__val <= __to) { __out = __list_add(__out, __val) __i++ __val = __from + (__i * __delta) } } else if (__from > __to) { if (!__present(__delta)) __delta = -1 if (__delta >= 0) return __nil; __i = 0 __val = __from while (__val >= __to) { __out = __list_add(__out, __val) __i++ __val = __from + (__i * __delta) } } else { return __list(__from) } return __list_end(__out) } function __uniq(__lst, __out, __item, __seen) { __out = __list_begin(); __dolist(__item, __lst) { if (__item in __seen) continue __seen[__item] __out = __list_add(__out, __item) } return __list_end(__out) } function __uniqual(__lst, __out, __item, __itemeq, __seen) { __out = __list_begin(); __dolist(__item, __lst) { __itemq = __equalize(__item) if (__itemq in __seen) continue __seen[__itemq] __out = __list_add(__out, __item) } return __list_end(__out) } #if __have_indirect_functions function __mapcar(__fun, __lst, __temp, __item, out) { __temp = __list_begin() __dolist(__item, __lst) __temp = __list_add(__temp, __call(__fun, __item)) return __list_end(__temp) } function __mappend(__fun, __lst, __temp, __item, out) { __temp = __nil __dolist(__item, __lst) __temp = __append2(__temp, __call(__fun, __item)) return __temp } #endif #endif