165390Sbostic /****************************************************************
265390Sbostic Copyright (C) AT&T 1993
365390Sbostic All Rights Reserved
465390Sbostic
565390Sbostic Permission to use, copy, modify, and distribute this software and
665390Sbostic its documentation for any purpose and without fee is hereby
765390Sbostic granted, provided that the above copyright notice appear in all
865390Sbostic copies and that both that the copyright notice and this
965390Sbostic permission notice and warranty disclaimer appear in supporting
1065390Sbostic documentation, and that the name of AT&T or any of its entities
1165390Sbostic not be used in advertising or publicity pertaining to
1265390Sbostic distribution of the software without specific, written prior
1365390Sbostic permission.
1465390Sbostic
1565390Sbostic AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1665390Sbostic INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1765390Sbostic IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
1865390Sbostic SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1965390Sbostic WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
2065390Sbostic IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2165390Sbostic ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2265390Sbostic THIS SOFTWARE.
2365390Sbostic ****************************************************************/
2465390Sbostic
2565390Sbostic #define DEBUG
2665390Sbostic #include <stdio.h>
2765390Sbostic #include <string.h>
2865390Sbostic #include <ctype.h>
2965390Sbostic #include <errno.h>
3065390Sbostic #include <stdlib.h>
3165390Sbostic #include "awk.h"
3265390Sbostic #include "y.tab.h"
3365390Sbostic
3465390Sbostic #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
3565390Sbostic #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
3665390Sbostic
3765390Sbostic FILE *infile = NULL;
3865390Sbostic uchar *file = (uchar*) "";
3965390Sbostic int recsize = RECSIZE;
4065390Sbostic uchar *recdata;
4165390Sbostic uchar *record;
4265390Sbostic uchar *fields;
4365390Sbostic Cell *fldtab;
4465390Sbostic
4565390Sbostic #define MAXFLD 200
4665390Sbostic int nfields = MAXFLD; /* can be set from commandline in main */
4765390Sbostic
4865390Sbostic int donefld; /* 1 = implies rec broken into fields */
4965390Sbostic int donerec; /* 1 = record is valid (no flds have changed) */
5065390Sbostic
5165390Sbostic int maxfld = 0; /* last used field */
5265390Sbostic int argno = 1; /* current input argument number */
5365390Sbostic extern Awkfloat *ARGC;
5465390Sbostic
recinit(unsigned int n)5565390Sbostic void recinit(unsigned int n)
5665390Sbostic {
5765390Sbostic static Cell dollar0 = {
5865390Sbostic OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE };
5965390Sbostic static Cell dollar1 = {
6065390Sbostic OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE };
6165390Sbostic int i;
6265390Sbostic
6365390Sbostic record = recdata = (uchar *) malloc(n);
6465390Sbostic fields = (uchar *) malloc(n);
6565390Sbostic fldtab = (Cell *) malloc(nfields * sizeof(Cell));
6665390Sbostic if (recdata == NULL || fields == NULL || fldtab == NULL)
6765390Sbostic ERROR "out of space for $0 and fields" FATAL;
6865390Sbostic fldtab[0] = dollar0;
6965390Sbostic fldtab[0].sval = recdata;
7065390Sbostic for (i = 1; i < nfields; i++)
7165390Sbostic fldtab[i] = dollar1;
7265390Sbostic }
7365390Sbostic
initgetrec(void)7465390Sbostic void initgetrec(void)
7565390Sbostic {
7665390Sbostic int i;
7765390Sbostic uchar *p;
7865390Sbostic
7965390Sbostic for (i = 1; i < *ARGC; i++) {
8065390Sbostic if (!isclvar(p = getargv(i))) { /* find 1st real filename */
8165390Sbostic setsval(lookup("FILENAME", symtab), getargv(i));
8265390Sbostic return;
8365390Sbostic }
8465390Sbostic setclvar(p); /* a commandline assignment before filename */
8565390Sbostic argno++;
8665390Sbostic }
8765390Sbostic infile = stdin; /* no filenames, so use stdin */
8865390Sbostic }
8965390Sbostic
getrec(uchar * buf)9065390Sbostic getrec(uchar *buf) /* get next input record from whatever source */
9165390Sbostic { /* note: tests whether buf == record */
9265390Sbostic int c;
9365390Sbostic static int firsttime = 1;
9465390Sbostic
9565390Sbostic if (firsttime) {
9665390Sbostic firsttime = 0;
9765390Sbostic initgetrec();
9865390Sbostic }
9965390Sbostic dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
10065390Sbostic *RS, *FS, *ARGC, *FILENAME) );
10165390Sbostic donefld = 0;
10265390Sbostic donerec = 1;
10365390Sbostic buf[0] = 0;
10465390Sbostic while (argno < *ARGC || infile == stdin) {
10565390Sbostic dprintf( ("argno=%d, file=|%s|\n", argno, file) );
10665390Sbostic if (infile == NULL) { /* have to open a new file */
10765390Sbostic file = getargv(argno);
10865390Sbostic if (*file == '\0') { /* it's been zapped */
10965390Sbostic argno++;
11065390Sbostic continue;
11165390Sbostic }
11265390Sbostic if (isclvar(file)) { /* a var=value arg */
11365390Sbostic setclvar(file);
11465390Sbostic argno++;
11565390Sbostic continue;
11665390Sbostic }
11765390Sbostic *FILENAME = file;
11865390Sbostic dprintf( ("opening file %s\n", file) );
11965390Sbostic if (*file == '-' && *(file+1) == '\0')
12065390Sbostic infile = stdin;
12165390Sbostic else if ((infile = fopen((char *)file, "r")) == NULL)
12265390Sbostic ERROR "can't open file %s", file FATAL;
12365390Sbostic setfval(fnrloc, 0.0);
12465390Sbostic }
12565390Sbostic c = readrec(buf, recsize, infile);
12665390Sbostic if (c != 0 || buf[0] != '\0') { /* normal record */
12765390Sbostic if (buf == record) {
12865390Sbostic if (!(recloc->tval & DONTFREE))
12965390Sbostic xfree(recloc->sval);
13065390Sbostic recloc->sval = record;
13165390Sbostic recloc->tval = REC | STR | DONTFREE;
132*65396Sbostic if (is_a_number(recloc->sval)) {
13365390Sbostic recloc->fval = atof(recloc->sval);
13465390Sbostic recloc->tval |= NUM;
13565390Sbostic }
13665390Sbostic }
13765390Sbostic setfval(nrloc, nrloc->fval+1);
13865390Sbostic setfval(fnrloc, fnrloc->fval+1);
13965390Sbostic return 1;
14065390Sbostic }
14165390Sbostic /* EOF arrived on this file; set up next */
14265390Sbostic if (infile != stdin)
14365390Sbostic fclose(infile);
14465390Sbostic infile = NULL;
14565390Sbostic argno++;
14665390Sbostic }
14765390Sbostic return 0; /* true end of file */
14865390Sbostic }
14965390Sbostic
readrec(uchar * buf,int bufsize,FILE * inf)15065390Sbostic readrec(uchar *buf, int bufsize, FILE *inf) /* read one record into buf */
15165390Sbostic {
15265390Sbostic register int sep, c;
15365390Sbostic register uchar *rr;
15465390Sbostic register int nrr;
15565390Sbostic
15665390Sbostic if ((sep = **RS) == 0) {
15765390Sbostic sep = '\n';
15865390Sbostic while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
15965390Sbostic ;
16065390Sbostic if (c != EOF)
16165390Sbostic ungetc(c, inf);
16265390Sbostic }
16365390Sbostic for (rr = buf, nrr = bufsize; ; ) {
16465390Sbostic for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c)
16565390Sbostic if (--nrr < 0)
16665390Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
16765390Sbostic if (**RS == sep || c == EOF)
16865390Sbostic break;
16965390Sbostic if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
17065390Sbostic break;
17165390Sbostic *rr++ = '\n';
17265390Sbostic *rr++ = c;
17365390Sbostic }
17465390Sbostic if (rr > buf + bufsize)
17565390Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
17665390Sbostic *rr = 0;
17765390Sbostic dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
17865390Sbostic return c == EOF && rr == buf ? 0 : 1;
17965390Sbostic }
18065390Sbostic
getargv(int n)18165390Sbostic uchar *getargv(int n) /* get ARGV[n] */
18265390Sbostic {
18365390Sbostic Cell *x;
18465390Sbostic uchar *s, temp[10];
18565390Sbostic extern Array *ARGVtab;
18665390Sbostic
18765390Sbostic sprintf((char *)temp, "%d", n);
18865390Sbostic x = setsymtab(temp, "", 0.0, STR, ARGVtab);
18965390Sbostic s = getsval(x);
19065390Sbostic dprintf( ("getargv(%d) returns |%s|\n", n, s) );
19165390Sbostic return s;
19265390Sbostic }
19365390Sbostic
setclvar(uchar * s)19465390Sbostic void setclvar(uchar *s) /* set var=value from s */
19565390Sbostic {
19665390Sbostic uchar *p;
19765390Sbostic Cell *q;
19865390Sbostic
19965390Sbostic for (p=s; *p != '='; p++)
20065390Sbostic ;
20165390Sbostic *p++ = 0;
20265390Sbostic p = qstring(p, '\0');
20365390Sbostic q = setsymtab(s, p, 0.0, STR, symtab);
20465390Sbostic setsval(q, p);
205*65396Sbostic if (is_a_number(q->sval)) {
20665390Sbostic q->fval = atof(q->sval);
20765390Sbostic q->tval |= NUM;
20865390Sbostic }
20965390Sbostic dprintf( ("command line set %s to |%s|\n", s, p) );
21065390Sbostic }
21165390Sbostic
21265390Sbostic
fldbld(void)21365390Sbostic void fldbld(void) /* create fields from current record */
21465390Sbostic {
21565390Sbostic register uchar *r, *fr, sep;
21665390Sbostic Cell *p;
21765390Sbostic int i;
21865390Sbostic
21965390Sbostic if (donefld)
22065390Sbostic return;
22165390Sbostic if (!(recloc->tval & STR))
22265390Sbostic getsval(recloc);
22365390Sbostic r = recloc->sval;
22465390Sbostic fr = fields;
22565390Sbostic i = 0; /* number of fields accumulated here */
22665390Sbostic if (strlen(*FS) > 1) { /* it's a regular expression */
22765390Sbostic i = refldbld(r, *FS);
22865390Sbostic } else if ((sep = **FS) == ' ') { /* default whitespace */
22965390Sbostic for (i = 0; ; ) {
23065390Sbostic while (*r == ' ' || *r == '\t' || *r == '\n')
23165390Sbostic r++;
23265390Sbostic if (*r == 0)
23365390Sbostic break;
23465390Sbostic i++;
23565390Sbostic if (i >= nfields)
23665390Sbostic break;
23765390Sbostic if (!(fldtab[i].tval & DONTFREE))
23865390Sbostic xfree(fldtab[i].sval);
23965390Sbostic fldtab[i].sval = fr;
24065390Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
24165390Sbostic do
24265390Sbostic *fr++ = *r++;
24365390Sbostic while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
24465390Sbostic *fr++ = 0;
24565390Sbostic }
24665390Sbostic *fr = 0;
24765390Sbostic } else if (*r != 0) { /* if 0, it's a null field */
24865390Sbostic for (;;) {
24965390Sbostic i++;
25065390Sbostic if (i >= nfields)
25165390Sbostic break;
25265390Sbostic if (!(fldtab[i].tval & DONTFREE))
25365390Sbostic xfree(fldtab[i].sval);
25465390Sbostic fldtab[i].sval = fr;
25565390Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
25665390Sbostic while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */
25765390Sbostic *fr++ = *r++;
25865390Sbostic *fr++ = 0;
25965390Sbostic if (*r++ == 0)
26065390Sbostic break;
26165390Sbostic }
26265390Sbostic *fr = 0;
26365390Sbostic }
26465390Sbostic if (i >= nfields)
26565390Sbostic ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL;
26665390Sbostic /* clean out junk from previous record */
26765390Sbostic cleanfld(i, maxfld);
26865390Sbostic maxfld = i;
26965390Sbostic donefld = 1;
27065390Sbostic for (p = fldtab+1; p <= fldtab+maxfld; p++) {
271*65396Sbostic if(is_a_number(p->sval)) {
27265390Sbostic p->fval = atof(p->sval);
27365390Sbostic p->tval |= NUM;
27465390Sbostic }
27565390Sbostic }
27665390Sbostic setfval(nfloc, (Awkfloat) maxfld);
27765390Sbostic if (dbg)
27865390Sbostic for (p = fldtab; p <= fldtab+maxfld; p++)
27965390Sbostic printf("field %d: |%s|\n", p-fldtab, p->sval);
28065390Sbostic }
28165390Sbostic
cleanfld(int n1,int n2)28265390Sbostic void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
28365390Sbostic {
28465390Sbostic static uchar *nullstat = (uchar *) "";
28565390Sbostic register Cell *p, *q;
28665390Sbostic
28765390Sbostic for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
28865390Sbostic if (!(p->tval & DONTFREE))
28965390Sbostic xfree(p->sval);
29065390Sbostic p->tval = FLD | STR | DONTFREE;
29165390Sbostic p->sval = nullstat;
29265390Sbostic }
29365390Sbostic }
29465390Sbostic
newfld(int n)29565390Sbostic void newfld(int n) /* add field n (after end) */
29665390Sbostic {
29765390Sbostic if (n >= nfields)
29865390Sbostic ERROR "creating too many fields (%d); try -mf n", n, record FATAL;
29965390Sbostic cleanfld(maxfld, n);
30065390Sbostic maxfld = n;
30165390Sbostic setfval(nfloc, (Awkfloat) n);
30265390Sbostic }
30365390Sbostic
refldbld(uchar * rec,uchar * fs)30465390Sbostic refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
30565390Sbostic {
30665390Sbostic uchar *fr;
30765390Sbostic int i, tempstat;
30865390Sbostic fa *pfa;
30965390Sbostic
31065390Sbostic fr = fields;
31165390Sbostic *fr = '\0';
31265390Sbostic if (*rec == '\0')
31365390Sbostic return 0;
31465390Sbostic pfa = makedfa(fs, 1);
31565390Sbostic dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
31665390Sbostic tempstat = pfa->initstat;
31765390Sbostic for (i = 1; i < nfields; i++) {
31865390Sbostic if (!(fldtab[i].tval & DONTFREE))
31965390Sbostic xfree(fldtab[i].sval);
32065390Sbostic fldtab[i].tval = FLD | STR | DONTFREE;
32165390Sbostic fldtab[i].sval = fr;
32265390Sbostic dprintf( ("refldbld: i=%d\n", i) );
32365390Sbostic if (nematch(pfa, rec)) {
32465390Sbostic pfa->initstat = 2; /* horrible coupling */
32565390Sbostic dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
32665390Sbostic strncpy(fr, rec, patbeg-rec);
32765390Sbostic fr += patbeg - rec + 1;
32865390Sbostic *(fr-1) = '\0';
32965390Sbostic rec = patbeg + patlen;
33065390Sbostic } else {
33165390Sbostic dprintf( ("no match %s\n", rec) );
33265390Sbostic strcpy(fr, rec);
33365390Sbostic pfa->initstat = tempstat;
33465390Sbostic break;
33565390Sbostic }
33665390Sbostic }
33765390Sbostic return i;
33865390Sbostic }
33965390Sbostic
recbld(void)34065390Sbostic void recbld(void) /* create $0 from $1..$NF if necessary */
34165390Sbostic {
34265390Sbostic register int i;
34365390Sbostic register uchar *r, *p;
34465390Sbostic static uchar *rec = 0;
34565390Sbostic
34665390Sbostic if (donerec == 1)
34765390Sbostic return;
34865390Sbostic if (rec == 0) {
34965390Sbostic rec = (uchar *) malloc(recsize);
35065390Sbostic if (rec == 0)
35165390Sbostic ERROR "out of space building $0, record size %d", recsize FATAL;
35265390Sbostic }
35365390Sbostic r = rec;
35465390Sbostic for (i = 1; i <= *NF; i++) {
35565390Sbostic p = getsval(&fldtab[i]);
35665390Sbostic while (r < rec+recsize-1 && (*r = *p++))
35765390Sbostic r++;
35865390Sbostic if (i < *NF)
35965390Sbostic for (p = *OFS; r < rec+recsize-1 && (*r = *p++); )
36065390Sbostic r++;
36165390Sbostic }
36265390Sbostic if (r > rec + recsize - 1)
36365390Sbostic ERROR "built giant record `%.30s...'; try -mr n", record FATAL;
36465390Sbostic *r = '\0';
36565390Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
36665390Sbostic recloc->tval = REC | STR | DONTFREE;
36765390Sbostic recloc->sval = record = rec;
36865390Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
36965390Sbostic dprintf( ("recbld = |%s|\n", record) );
37065390Sbostic donerec = 1;
37165390Sbostic }
37265390Sbostic
fieldadr(int n)37365390Sbostic Cell *fieldadr(int n)
37465390Sbostic {
37565390Sbostic if (n < 0 || n >= nfields)
37665390Sbostic ERROR "trying to access field %d; try -mf n", n FATAL;
37765390Sbostic return(&fldtab[n]);
37865390Sbostic }
37965390Sbostic
38065390Sbostic int errorflag = 0;
38165390Sbostic char errbuf[200];
38265390Sbostic
yyerror(uchar * s)38365390Sbostic void yyerror(uchar *s)
38465390Sbostic {
38565390Sbostic extern uchar *cmdname, *curfname;
38665390Sbostic static int been_here = 0;
38765390Sbostic
38865390Sbostic if (been_here++ > 2)
38965390Sbostic return;
39065390Sbostic fprintf(stderr, "%s: %s", cmdname, s);
39165390Sbostic fprintf(stderr, " at source line %d", lineno);
39265390Sbostic if (curfname != NULL)
39365390Sbostic fprintf(stderr, " in function %s", curfname);
39465390Sbostic fprintf(stderr, "\n");
39565390Sbostic errorflag = 2;
39665390Sbostic eprint();
39765390Sbostic }
39865390Sbostic
fpecatch(int n)39965390Sbostic void fpecatch(int n)
40065390Sbostic {
40165390Sbostic ERROR "floating point exception %d", n FATAL;
40265390Sbostic }
40365390Sbostic
40465390Sbostic extern int bracecnt, brackcnt, parencnt;
40565390Sbostic
bracecheck(void)40665390Sbostic void bracecheck(void)
40765390Sbostic {
40865390Sbostic int c;
40965390Sbostic static int beenhere = 0;
41065390Sbostic
41165390Sbostic if (beenhere++)
41265390Sbostic return;
413*65396Sbostic while ((c = lex_input()) != EOF && c != '\0')
41465390Sbostic bclass(c);
41565390Sbostic bcheck2(bracecnt, '{', '}');
41665390Sbostic bcheck2(brackcnt, '[', ']');
41765390Sbostic bcheck2(parencnt, '(', ')');
41865390Sbostic }
41965390Sbostic
bcheck2(int n,int c1,int c2)42065390Sbostic void bcheck2(int n, int c1, int c2)
42165390Sbostic {
42265390Sbostic if (n == 1)
42365390Sbostic fprintf(stderr, "\tmissing %c\n", c2);
42465390Sbostic else if (n > 1)
42565390Sbostic fprintf(stderr, "\t%d missing %c's\n", n, c2);
42665390Sbostic else if (n == -1)
42765390Sbostic fprintf(stderr, "\textra %c\n", c2);
42865390Sbostic else if (n < -1)
42965390Sbostic fprintf(stderr, "\t%d extra %c's\n", -n, c2);
43065390Sbostic }
43165390Sbostic
error(int f,char * s)43265390Sbostic void error(int f, char *s)
43365390Sbostic {
43465390Sbostic extern Node *curnode;
43565390Sbostic extern uchar *cmdname;
43665390Sbostic
43765390Sbostic fflush(stdout);
43865390Sbostic fprintf(stderr, "%s: ", cmdname);
43965390Sbostic fprintf(stderr, "%s", s);
44065390Sbostic fprintf(stderr, "\n");
44165390Sbostic if (compile_time != 2 && NR && *NR > 0) {
44265390Sbostic fprintf(stderr, " input record number %g", *FNR);
44365390Sbostic if (strcmp(*FILENAME, "-") != 0)
44465390Sbostic fprintf(stderr, ", file %s", *FILENAME);
44565390Sbostic fprintf(stderr, "\n");
44665390Sbostic }
44765390Sbostic if (compile_time != 2 && curnode)
44865390Sbostic fprintf(stderr, " source line number %d\n", curnode->lineno);
44965390Sbostic else if (compile_time != 2 && lineno)
45065390Sbostic fprintf(stderr, " source line number %d\n", lineno);
45165390Sbostic eprint();
45265390Sbostic if (f) {
45365390Sbostic if (dbg > 1) /* core dump if serious debugging on */
45465390Sbostic abort();
45565390Sbostic exit(2);
45665390Sbostic }
45765390Sbostic }
45865390Sbostic
eprint(void)45965390Sbostic void eprint(void) /* try to print context around error */
46065390Sbostic {
461*65396Sbostic #if 0
46265390Sbostic uchar *p, *q;
46365390Sbostic int c;
46465390Sbostic static int been_here = 0;
46565390Sbostic extern uchar ebuf[], *ep;
46665390Sbostic
46765390Sbostic if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
46865390Sbostic return;
46965390Sbostic p = ep - 1;
47065390Sbostic if (p > ebuf && *p == '\n')
47165390Sbostic p--;
47265390Sbostic for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
47365390Sbostic ;
47465390Sbostic while (*p == '\n')
47565390Sbostic p++;
47665390Sbostic fprintf(stderr, " context is\n\t");
47765390Sbostic for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
47865390Sbostic ;
47965390Sbostic for ( ; p < q; p++)
48065390Sbostic if (*p)
48165390Sbostic putc(*p, stderr);
48265390Sbostic fprintf(stderr, " >>> ");
48365390Sbostic for ( ; p < ep; p++)
48465390Sbostic if (*p)
48565390Sbostic putc(*p, stderr);
48665390Sbostic fprintf(stderr, " <<< ");
48765390Sbostic if (*ep)
48865390Sbostic while ((c = input()) != '\n' && c != '\0' && c != EOF) {
48965390Sbostic putc(c, stderr);
49065390Sbostic bclass(c);
49165390Sbostic }
49265390Sbostic putc('\n', stderr);
49365390Sbostic ep = ebuf;
494*65396Sbostic #endif
49565390Sbostic }
49665390Sbostic
bclass(int c)49765390Sbostic void bclass(int c)
49865390Sbostic {
49965390Sbostic switch (c) {
50065390Sbostic case '{': bracecnt++; break;
50165390Sbostic case '}': bracecnt--; break;
50265390Sbostic case '[': brackcnt++; break;
50365390Sbostic case ']': brackcnt--; break;
50465390Sbostic case '(': parencnt++; break;
50565390Sbostic case ')': parencnt--; break;
50665390Sbostic }
50765390Sbostic }
50865390Sbostic
errcheck(double x,uchar * s)50965390Sbostic double errcheck(double x, uchar *s)
51065390Sbostic {
51165390Sbostic extern int errno;
51265390Sbostic
51365390Sbostic if (errno == EDOM) {
51465390Sbostic errno = 0;
51565390Sbostic ERROR "%s argument out of domain", s WARNING;
51665390Sbostic x = 1;
51765390Sbostic } else if (errno == ERANGE) {
51865390Sbostic errno = 0;
51965390Sbostic ERROR "%s result out of range", s WARNING;
52065390Sbostic x = 1;
52165390Sbostic }
52265390Sbostic return x;
52365390Sbostic }
52465390Sbostic
isclvar(uchar * s)52565390Sbostic isclvar(uchar *s) /* is s of form var=something ? */
52665390Sbostic {
52765390Sbostic uchar *os = s;
52865390Sbostic
52965390Sbostic if (!isalpha(*s) && *s != '_')
53065390Sbostic return 0;
53165390Sbostic for ( ; *s; s++)
53265390Sbostic if (!(isalnum(*s) || *s == '_'))
53365390Sbostic break;
53465390Sbostic return *s == '=' && s > os && *(s+1) != '=';
53565390Sbostic }
53665390Sbostic
53765390Sbostic #define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */
53865390Sbostic
is_a_number(uchar * s)539*65396Sbostic is_a_number(uchar *s) /* probably should be done by a library function */
54065390Sbostic {
54165390Sbostic register int d1, d2;
54265390Sbostic int point;
54365390Sbostic uchar *es;
54465390Sbostic
54565390Sbostic d1 = d2 = point = 0;
54665390Sbostic while (*s == ' ' || *s == '\t' || *s == '\n')
54765390Sbostic s++;
54865390Sbostic if (*s == '\0')
54965390Sbostic return(0); /* empty stuff isn't number */
55065390Sbostic if (*s == '+' || *s == '-')
55165390Sbostic s++;
55265390Sbostic if (!isdigit(*s) && *s != '.')
55365390Sbostic return(0);
55465390Sbostic if (isdigit(*s)) {
55565390Sbostic do {
55665390Sbostic d1++;
55765390Sbostic s++;
55865390Sbostic } while (isdigit(*s));
55965390Sbostic }
56065390Sbostic if (*s == '.') {
56165390Sbostic point++;
56265390Sbostic s++;
56365390Sbostic }
56465390Sbostic if (isdigit(*s)) {
56565390Sbostic d2++;
56665390Sbostic do {
56765390Sbostic s++;
56865390Sbostic } while (isdigit(*s));
56965390Sbostic }
57065390Sbostic if (!(d1 || point && d2))
57165390Sbostic return(0);
57265390Sbostic if (*s == 'e' || *s == 'E') {
57365390Sbostic s++;
57465390Sbostic if (*s == '+' || *s == '-')
57565390Sbostic s++;
57665390Sbostic if (!isdigit(*s))
57765390Sbostic return(0);
57865390Sbostic es = s;
57965390Sbostic do {
58065390Sbostic s++;
58165390Sbostic } while (isdigit(*s));
58265390Sbostic if (s - es > 2)
58365390Sbostic return(0);
58465390Sbostic else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
58565390Sbostic return(0);
58665390Sbostic }
58765390Sbostic while (*s == ' ' || *s == '\t' || *s == '\n')
58865390Sbostic s++;
58965390Sbostic if (*s == '\0')
59065390Sbostic return(1);
59165390Sbostic else
59265390Sbostic return(0);
59365390Sbostic }
594