aboutsummaryrefslogtreecommitdiffstats
path: root/awk.h
diff options
context:
space:
mode:
Diffstat (limited to 'awk.h')
-rw-r--r--awk.h76
1 files changed, 71 insertions, 5 deletions
diff --git a/awk.h b/awk.h
index bee0e125..34755581 100644
--- a/awk.h
+++ b/awk.h
@@ -392,8 +392,11 @@ typedef struct exp_node {
/* type = Node_val */
/*
- * STRING and NUMBER are mutually exclusive. They represent the
- * type of a value as assigned.
+ * STRING and NUMBER are mutually exclusive, except for the special
+ * case of an uninitialized value, represented internally by
+ * Nnull_string. They represent the type of a value as assigned.
+ * Nnull_string has both STRING and NUMBER attributes, but all other
+ * scalar values should have precisely one of these bits set.
*
* STRCUR and NUMCUR are not mutually exclusive. They represent that
* the particular type of value is up to date. For example,
@@ -408,7 +411,8 @@ typedef struct exp_node {
*
* MAYBE_NUM is the joker. It means "this is string data, but
* the user may have really wanted it to be a number. If we have
- * to guess, like in a comparison, turn it into a number."
+ * to guess, like in a comparison, turn it into a number if the string
+ * is indeed numeric."
* For example, gawk -v a=42 ....
* Here, `a' gets STRING|STRCUR|MAYBE_NUM and then when used where
* a number is needed, it gets turned into a NUMBER and STRING
@@ -472,6 +476,13 @@ typedef struct exp_node {
#define re_cnt flags
/* Node_val */
+/*
+ * Note that the string in stptr may not be NUL-terminated, but it is
+ * guaranteed to have at least one extra byte that may be temporarily set
+ * to '\0'. This is helpful when calling functions such as strtod that require
+ * a NUL-terminated argument. In particular, field values $n for n > 0 and
+ * n < NF will not have a NUL terminator, since they point into the $0 buffer.
+ */
#define stptr sub.val.sp
#define stlen sub.val.slen
#define valref sub.val.sref
@@ -486,6 +497,16 @@ typedef struct exp_node {
#define numbr sub.val.fltnum
#endif
+/*
+ * If stfmt is set to STFMT_UNUSED, it means that the string representation
+ * stored in stptr is not a function of the value of CONVFMT or OFMT. That
+ * indicates that either the string value was explicitly assigned, or it
+ * was converted from a NUMBER that has an integer value. When stfmt is not
+ * set to STFMT_UNUSED, it is an offset into the fmt_list array of distinct
+ * CONVFMT and OFMT node pointers.
+ */
+#define STFMT_UNUSED -1
+
/* Node_arrayfor */
#define for_list sub.nodep.r.av
#define for_list_size sub.nodep.reflags
@@ -1401,7 +1422,7 @@ extern NODE *do_or(int nargs);
extern NODE *do_xor(int nargs);
extern NODE *do_compl(int nargs);
extern NODE *do_strtonum(int nargs);
-extern AWKNUM nondec2awknum(char *str, size_t len);
+extern AWKNUM nondec2awknum(char *str, size_t len, char **endptr);
extern NODE *do_dcgettext(int nargs);
extern NODE *do_dcngettext(int nargs);
extern NODE *do_bindtextdomain(int nargs);
@@ -1787,7 +1808,7 @@ force_string(NODE *s)
return dupnode(s->re_exp);
if ((s->flags & STRCUR) != 0
- && (s->stfmt == -1 || s->stfmt == CONVFMTidx)
+ && (s->stfmt == STFMT_UNUSED || s->stfmt == CONVFMTidx)
)
return s;
return format_val(CONVFMT, CONVFMTidx, s);
@@ -1820,6 +1841,51 @@ force_number(NODE *n)
#endif /* GAWKDEBUG */
+
+/* fixtype --- make a node decide if it's a number or a string */
+
+/*
+ * In certain contexts, the true type of a scalar value matters, and we
+ * must ascertain whether it is a NUMBER or a STRING. In such situations,
+ * please use this function to resolve the type.
+ *
+ * It is safe to assume that the return value will be the same NODE,
+ * since force_number on a MAYBE_NUM should always return the same NODE,
+ * and force_string on an INTIND should as well.
+ *
+ * There is no way to handle a Node_typedregex correctly, so we ignore
+ * that case.
+ */
+
+static inline NODE *
+fixtype(NODE *n)
+{
+ assert(n->type == Node_val || n->type == Node_typedregex);
+ if (n->type == Node_val) {
+ if ((n->flags & MAYBE_NUM) != 0)
+ return force_number(n);
+ if ((n->flags & INTIND) != 0)
+ return force_string(n);
+ }
+ return n;
+}
+
+/* boolval --- return true/false based on awk's criteria */
+
+/*
+ * In awk, a value is considered to be true if it is nonzero _or_
+ * non-null. Otherwise, the value is false.
+ */
+
+static inline int
+boolval(NODE *t)
+{
+ (void) fixtype(t);
+ if ((t->flags & NUMBER) != 0)
+ return ! iszero(t);
+ return (t->stlen > 0);
+}
+
/* emalloc_real --- malloc with error checking */
static inline void *