per my mail, avoid slow strtod() and ferror(). maybe the strtod screen should go into all 3 or 4 versions of strtod (or maybe there should be fewer versions) instead. Reference: /n/sources/patch/applied/faster-awk Date: Sat Feb 4 11:08:35 CET 2006 --- /sys/src/cmd/awk/lib.c Sat Feb 4 11:07:27 2006 +++ /sys/src/cmd/awk/lib.c Sat Feb 4 11:07:24 2006 @@ -673,6 +673,32 @@ { double r; char *ep; + + /* + * fast could-it-be-a-number check before calling strtod, + * which takes a surprisingly long time to reject non-numbers. + */ + switch (*s) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + case '-': + case '+': + case '.': + case 'n': /* nans */ + case 'N': + case 'i': /* infs */ + case 'I': + break; + default: + return 0; /* can't be a number */ + } + errno = 0; r = strtod(s, &ep); if (ep == s || r == HUGE_VAL || errno == ERANGE) --- /sys/src/cmd/awk/run.c Sat Feb 4 11:07:44 2006 +++ /sys/src/cmd/awk/run.c Sat Feb 4 11:07:38 2006 @@ -133,6 +133,7 @@ Cell *execute(Node *u) /* execute a node of the parse tree */ { + int nobj; Cell *(*proc)(Node **, int); Cell *x; Node *a; @@ -149,10 +150,11 @@ recbld(); return(x); } - if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */ + nobj = a->nobj; + if (notlegal(nobj)) /* probably a Cell* but too risky to print */ FATAL("illegal statement"); - proc = proctab[a->nobj-FIRSTTOKEN]; - x = (*proc)(a->narg, a->nobj); + proc = proctab[nobj-FIRSTTOKEN]; + x = (*proc)(a->narg, nobj); if (isfld(x) && !donefld) fldbld(); else if (isrec(x) && !donerec) @@ -1540,6 +1542,7 @@ Cell *printstat(Node **a, int n) /* print a[0] */ { + int r; Node *x; Cell *y; FILE *fp; @@ -1553,14 +1556,15 @@ fputs(getsval(y), fp); tempfree(y); if (x->nnext == NULL) - fputs(*ORS, fp); + r = fputs(*ORS, fp); else - fputs(*OFS, fp); + r = fputs(*OFS, fp); + if (r == EOF) + FATAL("write error on %s", filename(fp)); } if (a[1] != 0) - fflush(fp); - if (ferror(fp)) - FATAL("write error on %s", filename(fp)); + if (fflush(fp) == EOF) + FATAL("write error on %s", filename(fp)); return(True); }