ref: c0526c8928a2b554d9421bca2fc04ba044fe06af
parent: 5086f3453d6716d6dcd782a45831c1ebb0f2b115
author: qwx <qwx@sciops.net>
date: Thu Sep 25 06:04:18 EDT 2025
lex: use to_number and don't discard the results setsymtab in lex: STR should be set to avoid a leak, but some work is necessary for it first. right now the string cannot be unset without breakingt.coerce2 but adding STR breaks t.strcmp. we have to first allow sval to be unset.
--- a/lex.c
+++ b/lex.c
@@ -79,7 +79,7 @@
return c;
}
-int gettok(char **pbuf, int *psz) /* get next input token */
+static int gettok(char **pbuf, int *psz, Awkfloat *fp) /* get next input token */
{int c;
char *buf = *pbuf;
@@ -108,6 +108,7 @@
break;
}
}
+ c = 'a';
} else { /* it's a number */char *rem;
/* read input until can't be a number */
@@ -124,13 +125,14 @@
}
}
*bp = 0;
- strtod(buf, &rem); /* parse the number */
+ to_number(buf, fp, &rem); /* parse the number */
unputstr(rem); /* put rest back for later */
rem[0] = 0;
+ c = '0';
}
*pbuf = buf;
*psz = sz;
- return buf[0];
+ return c;
}
int word(char *);
@@ -142,6 +144,7 @@
int yylex(void)
{int c;
+ Awkfloat f;
static char *buf = 0;
static int bufsize = 500;
@@ -156,14 +159,14 @@
return regexpr();
}
for (;;) {- c = gettok(&buf, &bufsize);
+ c = gettok(&buf, &bufsize, &f);
if (c == 0)
return 0;
- if (isalpha(c) || c == '_')
+ if (c == 'a')
return word(buf);
- if (isdigit(c) || c == '.') {- yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
- /* should this also have STR set? */
+ if (c == '0') {+ yylval.cp = setsymtab(buf, tostring(buf), f, CON|NUM, symtab);
+ /* should this also have STR set? */ /* FIXME: yes. */
RET(NUMBER);
}
@@ -273,7 +276,7 @@
case '$':
/* BUG: awkward, if not wrong */
- c = gettok(&buf, &bufsize);
+ c = gettok(&buf, &bufsize, &f);
if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {unputstr(buf);
RET(INDIRECT);
--- a/lib.c
+++ b/lib.c
@@ -121,7 +121,7 @@
xfree(fldtab[0]->sval);
fldtab[0]->sval = buf; /* buf == record */
fldtab[0]->tval = REC | STR | DONTFREE;
- if (to_number(fldtab[0]->sval, &fldtab[0]->fval))
+ if (to_number(fldtab[0]->sval, &fldtab[0]->fval, nil))
fldtab[0]->tval |= NUM;
}
setfval(nrloc, nrloc->fval+1);
@@ -211,7 +211,7 @@
p = qstring(p, '\0');
q = setsymtab(s, p, 0.0, STR, symtab);
setsval(q, p);
- if (to_number(q->sval, &q->fval))
+ if (to_number(q->sval, &q->fval, nil))
q->tval |= NUM;
dprint( ("command line set %s to |%s|\n", s, p) );}
@@ -301,7 +301,7 @@
donefld = 1;
for (j = 1; j <= lastfld; j++) {p = fldtab[j];
- if (to_number(p->sval, &p->fval))
+ if (to_number(p->sval, &p->fval, nil))
p->tval |= NUM;
}
setfval(nfloc, (Awkfloat) lastfld);
@@ -635,12 +635,14 @@
return *s == '=' && s > os && *(s+1) != '=';
}
-static int is_float(char *s, Awkfloat *fp)
+static int is_float(char *s, Awkfloat *fp, char **tp)
{char c, *p, *q;
Awkfloat f;
f = *fp = strtod(s, &p);
+ if (tp != nil)
+ *tp = p;
if (p == s)
return 0;
else if (isInf(f, 1) || isInf(f, -1) || isNaN(f))
@@ -665,7 +667,7 @@
return 1;
}
-int to_number(char *s, Awkfloat *fp)
+int to_number(char *s, Awkfloat *fp, char **tp)
{vlong v;
char *p, *q;
@@ -672,6 +674,8 @@
v = strtoll(s, &p, 0);
*fp = (Awkfloat)v;
+ if (tp != nil)
+ *tp = p;
switch(*p){case '.':
case 'E':
@@ -680,7 +684,7 @@
case 'e':
case 'i':
case 'n':
- if (is_float(s, fp))
+ if (is_float(s, fp, tp))
return NUM;
return 0;
case '\0':
--- a/proto.h
+++ b/proto.h
@@ -93,7 +93,7 @@
extern void bclass(int);
extern double errcheck(double, char *);
extern int isclvar(char *);
-extern int to_number(char *, Awkfloat *);
+extern int to_number(char *, Awkfloat *, char **);
extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, char *what);
extern void run(Node *);
--- a/run.c
+++ b/run.c
@@ -405,7 +405,7 @@
tfree(x);
} else { /* getline <file */setsval(fldtab[0], buf);
- if (to_number(fldtab[0]->sval, &fldtab[0]->fval))
+ if (to_number(fldtab[0]->sval, &fldtab[0]->fval, nil))
fldtab[0]->tval |= NUM;
}
} else { /* bare getline; use current input */@@ -711,7 +711,7 @@
x = execute(a[0]);
m = (int) getfval(x);
if (m == 0) {- if (!to_number(s = getsval(x), &x->fval)) /* suspicion! */
+ if (!to_number(s = getsval(x), &x->fval, nil)) /* suspicion! */
FATAL("illegal field $(%s), name \"%s\"", s, x->nval);/* BUG: can x->nval ever be null??? */
}
@@ -1280,7 +1280,7 @@
sprint(num, "%d", n);
temp = *patbeg;
*patbeg = '\0';
- if (to_number(t, &f))
+ if (to_number(t, &f, nil))
setsymtab(num, t, f, STR|NUM, (Array *) ap->sval);
else
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
@@ -1296,7 +1296,7 @@
}
n++;
sprint(num, "%d", n);
- if (to_number(t, &f))
+ if (to_number(t, &f, nil))
setsymtab(num, t, f, STR|NUM, (Array *) ap->sval);
else
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
@@ -1317,7 +1317,7 @@
temp = *s;
*s = '\0';
sprint(num, "%d", n);
- if (to_number(t, &f))
+ if (to_number(t, &f, nil))
setsymtab(num, t, f, STR|NUM, (Array *) ap->sval);
else
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
@@ -1349,7 +1349,7 @@
temp = *s;
*s = '\0';
sprint(num, "%d", n);
- if (to_number(t, &f))
+ if (to_number(t, &f, nil))
setsymtab(num, t, f, STR|NUM, (Array *) ap->sval);
else
setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
--- a/tran.c
+++ b/tran.c
@@ -82,7 +82,7 @@
cp->sval = (char *) ARGVtab;
for (i = 0; i < ac; i++) {sprint(temp, "%d", i);
- if (to_number(*av, &f))
+ if (to_number(*av, &f, nil))
setsymtab(temp, *av, f, STR|NUM, ARGVtab);
else
setsymtab(temp, *av, 0.0, STR, ARGVtab);
@@ -109,7 +109,7 @@
continue;
if ((v = getenv(k)) == nil)
continue;
- if (to_number(v, &f))
+ if (to_number(v, &f, nil))
setsymtab(k, v, f, STR|NUM, ENVtab);
else
setsymtab(k, v, 0.0, STR, ENVtab);
@@ -336,7 +336,7 @@
recbld();
if (!isnum(vp)) { /* not a number */vp->fval = 0;
- if (to_number(vp->sval, &vp->fval)) {+ if (to_number(vp->sval, &vp->fval, nil)) {if (!(vp->tval&CON))
vp->tval |= NUM; /* make NUM only sparingly */
}
--
⑨