diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | awk.h | 4 | ||||
-rw-r--r-- | bool.notes | 47 | ||||
-rw-r--r-- | builtin.c | 5 | ||||
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | gawkapi.h | 47 | ||||
-rw-r--r-- | main.c | 17 | ||||
-rw-r--r-- | node.c | 22 |
8 files changed, 136 insertions, 23 deletions
@@ -1,3 +1,19 @@ +2021-03-05 Arnold D. Robbins <arnold@skeeve.com> + + Start on a bool type for gawk. + + * awk.h (BOOL): New flag value. + (make_bool_node): Add declaration of new function. + (bool_val): Check for BOOL along with NUMBER. + * builtin.c (do_typeof): Add support for BOOL. + * eval.c (flags2str): Ditto. + * gawkapi.h (awk_val_type): Add AWK_BOOL. + (awk_value_t): Add awk_bool_t element to the union and macro for it. + (struct gawk_api): Update the table of request/return values. + * main.c (load_procinfo_bools): New function. + (load_procinfo): Call it. + * node.c (make_bool_node): New function. + 2021-02-13 Arnold D. Robbins <arnold@skeeve.com> * io.c (nextfile): Use the value of ARGC directly in the for @@ -463,6 +463,7 @@ typedef struct exp_node { XARRAY = 0x10000, NUMCONSTSTR = 0x20000, /* have string value for numeric constant */ REGEX = 0x40000, /* this is a typed regex */ + BOOL = 0x80000, /* this is a boolean value */ } flags; long valref; } NODE; @@ -1714,6 +1715,7 @@ extern NODE *r_force_number(NODE *n); extern NODE *r_format_val(const char *format, int index, NODE *s); extern NODE *r_dupnode(NODE *n); extern NODE *make_str_node(const char *s, size_t len, int flags); +extern NODE *make_bool_node(bool value); extern NODE *make_typed_regex(const char *re, size_t len); extern void *more_blocks(int id); extern int parse_escape(const char **string_ptr); @@ -1995,7 +1997,7 @@ static inline bool boolval(NODE *t) { (void) fixtype(t); - if ((t->flags & NUMBER) != 0) + if ((t->flags & (BOOL|NUMBER)) != 0) return ! is_zero(t); return (t->stlen > 0); } diff --git a/bool.notes b/bool.notes new file mode 100644 index 00000000..51ea7268 --- /dev/null +++ b/bool.notes @@ -0,0 +1,47 @@ +Fri Mar 5 13:42:44 IST 2021 +============================ + +Design Notes for a Boolean Type in Gawk + +1. At first glance, two new variables named TRUE and FALSE would make sense +to be predefined values of boolean type. However, since it's likely that +many awk programs already use them, instead we'll add two new entries +to PROCINFO: variables PROCINFO["true"] and PROCINFO["false"] of type bool. + +Assigning from them copies the bool type, thus they are "factories" of bool +variables. + +2. They have numeric values 1 and 0 respectively, and string values +"TRUE" and "FALSE". Thus they differ from other variables where a +"false" value must be zero and null. + +This implies all of the following: + + print(PROCINFO["true"]) --> "TRUE" + print(PROCINFO["false"]) --> "FALSE" + Same for %s in printf + Same for bool_var "" + printf %d gives 0/1 + +3. Function bool(val) converts val to bool, returning Boolean TRUE or FALSE. + +4. typeof() returns "bool". + +5. Numeric operators treat booleans as numbers. asort() sorts booleans before +numbers, and false before true. + +6. These string function generate a runtime fatal error +if given an argument / target of boolean type: + + substr match index gensub gsub + sub length split patsplit + tolower toupper + +7. Updates to API needed for an additional type, and the table +for requested vs. returns. + +8. The following extensions need revising: + + - JSON extension + - dump / read array extensions + - what else? @@ -4112,7 +4112,10 @@ do_typeof(int nargs) } break; case Node_val: - switch (fixtype(arg)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) { + switch (fixtype(arg)->flags & (STRING|NUMBER|USER_INPUT|REGEX|BOOL)) { + case BOOL: + res = "bool"; + break; case NUMBER: res = "number"; break; @@ -455,6 +455,7 @@ flags2str(int flagval) { XARRAY, "XARRAY" }, { NUMCONSTSTR, "NUMCONSTSTR" }, { REGEX, "REGEX" }, + { BOOL, "BOOL" }, { 0, NULL }, }; @@ -366,7 +366,8 @@ typedef enum { AWK_STRNUM, AWK_ARRAY, AWK_SCALAR, /* opaque access to a variable */ - AWK_VALUE_COOKIE /* for updating a previously created value */ + AWK_VALUE_COOKIE, /* for updating a previously created value */ + AWK_BOOL } awk_valtype_t; /* @@ -381,6 +382,7 @@ typedef struct awk_value { awk_array_t a; awk_scalar_t scl; awk_value_cookie_t vc; + awk_bool_t b; } u; #define str_value u.s #define strnum_value str_value @@ -391,6 +393,7 @@ typedef struct awk_value { #define array_cookie u.a #define scalar_cookie u.scl #define value_cookie u.vc +#define bool_value u.b } awk_value_t; /* @@ -567,26 +570,28 @@ typedef struct gawk_api { +-------------------------------------------------------+ | Type of Actual Value: | - +--------+--------+--------+--------+-------+-----------+ - | String | Strnum | Number | Regex | Array | Undefined | - +-----------+-----------+--------+--------+--------+--------+-------+-----------+ - | | String | String | String | String | String | false | false | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | | Strnum | false | Strnum | Strnum | false | false | false | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | | Number | Number | Number | Number | false | false | false | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | | Regex | false | false | false | Regex | false | false | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | Type | Array | false | false | false | false | Array | false | - | Requested +-----------+--------+--------+--------+--------+-------+-----------+ - | | Scalar | Scalar | Scalar | Scalar | Scalar | false | false | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | | Undefined | String | Strnum | Number | Regex | Array | Undefined | - | +-----------+--------+--------+--------+--------+-------+-----------+ - | | Value | false | false | false | false | false | false | - | | Cookie | | | | | | | - +-----------+-----------+--------+--------+--------+--------+-------+-----------+ + +--------+--------+--------+--------+--------+-------+-----------+ + | String | Strnum | Number | Regex | Bool | Array | Undefined | + +-----------+-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | String | String | String | String | String | String | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Strnum | false | Strnum | Strnum | false | false | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Number | Number | Number | Number | false | Number | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Regex | false | false | false | Regex | false | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Bool | false | false | false | false | Bool | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | Type | Array | false | false | false | false | false | Array | false | + | Requested +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Scalar | Scalar | Scalar | Scalar | Scalar | Scalar | false | false | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Undefined | String | Strnum | Number | Regex | Bool | Array | Undefined | + | +-----------+--------+--------+--------+--------+--------+-------+-----------+ + | | Value | false | false | false | false | false | false | false | + | | Cookie | | | | | | | | + +-----------+-----------+--------+--------+--------+--------+--------+-------+-----------+ */ /* Functions to handle parameters passed to the extension. */ @@ -980,7 +980,23 @@ load_procinfo_argv() // hook it into PROCINFO sub = make_string("argv", 4); assoc_set(PROCINFO_node, sub, argv_array); +} + +/* load_procinfo_bools --- populate PROCINFO["true"] and PROCINFO["false"] */ + +static void +load_procinfo_bools() +{ + NODE *sub; + NODE *val; + + val = make_bool_node(false); + sub = make_string("false", 5); + assoc_set(PROCINFO_node, sub, val); + val = make_bool_node(true); + sub = make_string("true", 4); + assoc_set(PROCINFO_node, sub, val); } /* load_procinfo --- populate the PROCINFO array */ @@ -1069,6 +1085,7 @@ load_procinfo() } #endif load_procinfo_argv(); + load_procinfo_bools(); return PROCINFO_node; } @@ -1082,3 +1082,25 @@ more_blocks(int id) } #endif + +/* make_bool_node --- make a boolean-valued node */ + +extern NODE * +make_bool_node(bool value) +{ + NODE *val; + const char *sval; + AWKNUM nval; + + sval = (value ? "TRUE" : "FALSE"); + nval = (value ? 1.0 : 0.0); + + val = make_number(nval); + val->stptr = estrdup(sval, strlen(sval)); + val->stlen = strlen(sval); + val->flags &= ~NUMBER; + val->flags |= NUMCUR|STRCUR|BOOL; + val->stfmt = STFMT_UNUSED; + + return val; +} |