aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2021-03-05 14:26:15 +0200
committerArnold D. Robbins <arnold@skeeve.com>2021-03-05 14:26:15 +0200
commitb9931e852ba21180c380639135f96cdcd0a3015f (patch)
treef9941c423cacfcdbeec956dfd6d1150ad7e17bf6
parent09887734833d47e9c2ea1203689a9bc7bccae723 (diff)
downloadegawk-b9931e852ba21180c380639135f96cdcd0a3015f.tar.gz
egawk-b9931e852ba21180c380639135f96cdcd0a3015f.tar.bz2
egawk-b9931e852ba21180c380639135f96cdcd0a3015f.zip
Start on a bool type for gawk.
-rw-r--r--ChangeLog16
-rw-r--r--awk.h4
-rw-r--r--bool.notes47
-rw-r--r--builtin.c5
-rw-r--r--eval.c1
-rw-r--r--gawkapi.h47
-rw-r--r--main.c17
-rw-r--r--node.c22
8 files changed, 136 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 89767c0f..52b74a78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/awk.h b/awk.h
index c9eec663..ee055f49 100644
--- a/awk.h
+++ b/awk.h
@@ -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?
diff --git a/builtin.c b/builtin.c
index 1b612f4a..67a89bd1 100644
--- a/builtin.c
+++ b/builtin.c
@@ -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;
diff --git a/eval.c b/eval.c
index 640f939f..75c39327 100644
--- a/eval.c
+++ b/eval.c
@@ -455,6 +455,7 @@ flags2str(int flagval)
{ XARRAY, "XARRAY" },
{ NUMCONSTSTR, "NUMCONSTSTR" },
{ REGEX, "REGEX" },
+ { BOOL, "BOOL" },
{ 0, NULL },
};
diff --git a/gawkapi.h b/gawkapi.h
index 54130b15..3fd02df7 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -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. */
diff --git a/main.c b/main.c
index 5b153bc3..9833d848 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/node.c b/node.c
index c22c06ab..dda90f0f 100644
--- a/node.c
+++ b/node.c
@@ -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;
+}