17dd7cddfSDavid du Colombier /****************************************************************
27dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997
33e12c5d1SDavid du Colombier All Rights Reserved
43e12c5d1SDavid du Colombier
57dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and
67dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby
77dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all
87dd7cddfSDavid du Colombier copies and that both that the copyright notice and this
97dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting
107dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of
117dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining
127dd7cddfSDavid du Colombier to distribution of the software without specific, written prior
137dd7cddfSDavid du Colombier permission.
143e12c5d1SDavid du Colombier
157dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
167dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
177dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
187dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
197dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
207dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
217dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
227dd7cddfSDavid du Colombier THIS SOFTWARE.
237dd7cddfSDavid du Colombier ****************************************************************/
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier #define DEBUG
263e12c5d1SDavid du Colombier #include <stdio.h>
273e12c5d1SDavid du Colombier #include <string.h>
283e12c5d1SDavid du Colombier #include <ctype.h>
293e12c5d1SDavid du Colombier #include <errno.h>
303e12c5d1SDavid du Colombier #include <stdlib.h>
317dd7cddfSDavid du Colombier #include <stdarg.h>
323e12c5d1SDavid du Colombier #include "awk.h"
333e12c5d1SDavid du Colombier #include "y.tab.h"
343e12c5d1SDavid du Colombier
353e12c5d1SDavid du Colombier FILE *infile = NULL;
367dd7cddfSDavid du Colombier char *file = "";
377dd7cddfSDavid du Colombier char *record;
38219b2ee8SDavid du Colombier int recsize = RECSIZE;
397dd7cddfSDavid du Colombier char *fields;
407dd7cddfSDavid du Colombier int fieldssize = RECSIZE;
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier Cell **fldtab; /* pointers to Cells */
437dd7cddfSDavid du Colombier char inputFS[100] = " ";
443e12c5d1SDavid du Colombier
453e12c5d1SDavid du Colombier #define MAXFLD 200
467dd7cddfSDavid du Colombier int nfields = MAXFLD; /* last allocated slot for $i */
47219b2ee8SDavid du Colombier
483e12c5d1SDavid du Colombier int donefld; /* 1 = implies rec broken into fields */
493e12c5d1SDavid du Colombier int donerec; /* 1 = record is valid (no flds have changed) */
503e12c5d1SDavid du Colombier
517dd7cddfSDavid du Colombier int lastfld = 0; /* last used field */
523e12c5d1SDavid du Colombier int argno = 1; /* current input argument number */
533e12c5d1SDavid du Colombier extern Awkfloat *ARGC;
543e12c5d1SDavid du Colombier
557dd7cddfSDavid du Colombier static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE };
567dd7cddfSDavid du Colombier static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
577dd7cddfSDavid du Colombier
recinit(unsigned int n)58219b2ee8SDavid du Colombier void recinit(unsigned int n)
59219b2ee8SDavid du Colombier {
607dd7cddfSDavid du Colombier record = (char *) malloc(n);
617dd7cddfSDavid du Colombier fields = (char *) malloc(n);
627dd7cddfSDavid du Colombier fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *));
637dd7cddfSDavid du Colombier if (record == NULL || fields == NULL || fldtab == NULL)
647dd7cddfSDavid du Colombier FATAL("out of space for $0 and fields");
657dd7cddfSDavid du Colombier fldtab[0] = (Cell *) malloc(sizeof (Cell));
667dd7cddfSDavid du Colombier *fldtab[0] = dollar0;
677dd7cddfSDavid du Colombier fldtab[0]->sval = record;
687dd7cddfSDavid du Colombier fldtab[0]->nval = tostring("0");
697dd7cddfSDavid du Colombier makefields(1, nfields);
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier
makefields(int n1,int n2)727dd7cddfSDavid du Colombier void makefields(int n1, int n2) /* create $n1..$n2 inclusive */
737dd7cddfSDavid du Colombier {
747dd7cddfSDavid du Colombier char temp[50];
75219b2ee8SDavid du Colombier int i;
76219b2ee8SDavid du Colombier
777dd7cddfSDavid du Colombier for (i = n1; i <= n2; i++) {
787dd7cddfSDavid du Colombier fldtab[i] = (Cell *) malloc(sizeof (struct Cell));
797dd7cddfSDavid du Colombier if (fldtab[i] == NULL)
807dd7cddfSDavid du Colombier FATAL("out of space in makefields %d", i);
817dd7cddfSDavid du Colombier *fldtab[i] = dollar1;
827dd7cddfSDavid du Colombier sprintf(temp, "%d", i);
837dd7cddfSDavid du Colombier fldtab[i]->nval = tostring(temp);
847dd7cddfSDavid du Colombier }
85219b2ee8SDavid du Colombier }
86219b2ee8SDavid du Colombier
initgetrec(void)873e12c5d1SDavid du Colombier void initgetrec(void)
883e12c5d1SDavid du Colombier {
893e12c5d1SDavid du Colombier int i;
907dd7cddfSDavid du Colombier char *p;
913e12c5d1SDavid du Colombier
923e12c5d1SDavid du Colombier for (i = 1; i < *ARGC; i++) {
93219b2ee8SDavid du Colombier if (!isclvar(p = getargv(i))) { /* find 1st real filename */
94219b2ee8SDavid du Colombier setsval(lookup("FILENAME", symtab), getargv(i));
953e12c5d1SDavid du Colombier return;
96219b2ee8SDavid du Colombier }
973e12c5d1SDavid du Colombier setclvar(p); /* a commandline assignment before filename */
983e12c5d1SDavid du Colombier argno++;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier infile = stdin; /* no filenames, so use stdin */
1013e12c5d1SDavid du Colombier }
1023e12c5d1SDavid du Colombier
getrec(char ** pbuf,int * pbufsize,int isrecord)1037dd7cddfSDavid du Colombier int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
1047dd7cddfSDavid du Colombier { /* note: cares whether buf == record */
1053e12c5d1SDavid du Colombier int c;
1063e12c5d1SDavid du Colombier static int firsttime = 1;
1077dd7cddfSDavid du Colombier char *buf = *pbuf;
1087dd7cddfSDavid du Colombier int bufsize = *pbufsize;
1093e12c5d1SDavid du Colombier
1103e12c5d1SDavid du Colombier if (firsttime) {
1113e12c5d1SDavid du Colombier firsttime = 0;
1123e12c5d1SDavid du Colombier initgetrec();
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
1153e12c5d1SDavid du Colombier *RS, *FS, *ARGC, *FILENAME) );
1167dd7cddfSDavid du Colombier if (isrecord) {
1173e12c5d1SDavid du Colombier donefld = 0;
1183e12c5d1SDavid du Colombier donerec = 1;
1197dd7cddfSDavid du Colombier }
1203e12c5d1SDavid du Colombier buf[0] = 0;
1213e12c5d1SDavid du Colombier while (argno < *ARGC || infile == stdin) {
1223e12c5d1SDavid du Colombier dprintf( ("argno=%d, file=|%s|\n", argno, file) );
1233e12c5d1SDavid du Colombier if (infile == NULL) { /* have to open a new file */
1243e12c5d1SDavid du Colombier file = getargv(argno);
1253e12c5d1SDavid du Colombier if (*file == '\0') { /* it's been zapped */
1263e12c5d1SDavid du Colombier argno++;
1273e12c5d1SDavid du Colombier continue;
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier if (isclvar(file)) { /* a var=value arg */
1303e12c5d1SDavid du Colombier setclvar(file);
1313e12c5d1SDavid du Colombier argno++;
1323e12c5d1SDavid du Colombier continue;
1333e12c5d1SDavid du Colombier }
1343e12c5d1SDavid du Colombier *FILENAME = file;
1353e12c5d1SDavid du Colombier dprintf( ("opening file %s\n", file) );
1363e12c5d1SDavid du Colombier if (*file == '-' && *(file+1) == '\0')
1373e12c5d1SDavid du Colombier infile = stdin;
1387dd7cddfSDavid du Colombier else if ((infile = fopen(file, "r")) == NULL)
1397dd7cddfSDavid du Colombier FATAL("can't open file %s", file);
1403e12c5d1SDavid du Colombier setfval(fnrloc, 0.0);
1413e12c5d1SDavid du Colombier }
1427dd7cddfSDavid du Colombier c = readrec(&buf, &bufsize, infile);
1433e12c5d1SDavid du Colombier if (c != 0 || buf[0] != '\0') { /* normal record */
1447dd7cddfSDavid du Colombier if (isrecord) {
1457dd7cddfSDavid du Colombier if (freeable(fldtab[0]))
1467dd7cddfSDavid du Colombier xfree(fldtab[0]->sval);
1477dd7cddfSDavid du Colombier fldtab[0]->sval = buf; /* buf == record */
1487dd7cddfSDavid du Colombier fldtab[0]->tval = REC | STR | DONTFREE;
1497dd7cddfSDavid du Colombier if (is_number(fldtab[0]->sval)) {
1507dd7cddfSDavid du Colombier fldtab[0]->fval = atof(fldtab[0]->sval);
1517dd7cddfSDavid du Colombier fldtab[0]->tval |= NUM;
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier }
1543e12c5d1SDavid du Colombier setfval(nrloc, nrloc->fval+1);
1553e12c5d1SDavid du Colombier setfval(fnrloc, fnrloc->fval+1);
1567dd7cddfSDavid du Colombier *pbuf = buf;
1577dd7cddfSDavid du Colombier *pbufsize = bufsize;
1583e12c5d1SDavid du Colombier return 1;
1593e12c5d1SDavid du Colombier }
1603e12c5d1SDavid du Colombier /* EOF arrived on this file; set up next */
1613e12c5d1SDavid du Colombier if (infile != stdin)
1623e12c5d1SDavid du Colombier fclose(infile);
1633e12c5d1SDavid du Colombier infile = NULL;
1643e12c5d1SDavid du Colombier argno++;
1653e12c5d1SDavid du Colombier }
1667dd7cddfSDavid du Colombier *pbuf = buf;
1677dd7cddfSDavid du Colombier *pbufsize = bufsize;
1683e12c5d1SDavid du Colombier return 0; /* true end of file */
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier
nextfile(void)1717dd7cddfSDavid du Colombier void nextfile(void)
1723e12c5d1SDavid du Colombier {
1737dd7cddfSDavid du Colombier if (infile != stdin)
1747dd7cddfSDavid du Colombier fclose(infile);
1757dd7cddfSDavid du Colombier infile = NULL;
1767dd7cddfSDavid du Colombier argno++;
1777dd7cddfSDavid du Colombier }
1783e12c5d1SDavid du Colombier
readrec(char ** pbuf,int * pbufsize,FILE * inf)1797dd7cddfSDavid du Colombier int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
1807dd7cddfSDavid du Colombier {
1817dd7cddfSDavid du Colombier int sep, c;
1827dd7cddfSDavid du Colombier char *rr, *buf = *pbuf;
1837dd7cddfSDavid du Colombier int bufsize = *pbufsize;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier if (strlen(*FS) >= sizeof(inputFS))
1867dd7cddfSDavid du Colombier FATAL("field separator %.10s... is too long", *FS);
1877dd7cddfSDavid du Colombier strcpy(inputFS, *FS); /* for subsequent field splitting */
1883e12c5d1SDavid du Colombier if ((sep = **RS) == 0) {
1893e12c5d1SDavid du Colombier sep = '\n';
1903e12c5d1SDavid du Colombier while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
1913e12c5d1SDavid du Colombier ;
1923e12c5d1SDavid du Colombier if (c != EOF)
1933e12c5d1SDavid du Colombier ungetc(c, inf);
1943e12c5d1SDavid du Colombier }
1957dd7cddfSDavid du Colombier for (rr = buf; ; ) {
1967dd7cddfSDavid du Colombier for (; (c=getc(inf)) != sep && c != EOF; ) {
1977dd7cddfSDavid du Colombier if (rr-buf+1 > bufsize)
1987dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
1997dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf);
2007dd7cddfSDavid du Colombier *rr++ = c;
2017dd7cddfSDavid du Colombier }
2023e12c5d1SDavid du Colombier if (**RS == sep || c == EOF)
2033e12c5d1SDavid du Colombier break;
2043e12c5d1SDavid du Colombier if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
2053e12c5d1SDavid du Colombier break;
2067dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
2077dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf);
2083e12c5d1SDavid du Colombier *rr++ = '\n';
2093e12c5d1SDavid du Colombier *rr++ = c;
2103e12c5d1SDavid du Colombier }
2117dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
2127dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf);
2133e12c5d1SDavid du Colombier *rr = 0;
2143e12c5d1SDavid du Colombier dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
2157dd7cddfSDavid du Colombier *pbuf = buf;
2167dd7cddfSDavid du Colombier *pbufsize = bufsize;
2173e12c5d1SDavid du Colombier return c == EOF && rr == buf ? 0 : 1;
2183e12c5d1SDavid du Colombier }
2193e12c5d1SDavid du Colombier
getargv(int n)2207dd7cddfSDavid du Colombier char *getargv(int n) /* get ARGV[n] */
2213e12c5d1SDavid du Colombier {
2223e12c5d1SDavid du Colombier Cell *x;
2237dd7cddfSDavid du Colombier char *s, temp[50];
2243e12c5d1SDavid du Colombier extern Array *ARGVtab;
2253e12c5d1SDavid du Colombier
2267dd7cddfSDavid du Colombier sprintf(temp, "%d", n);
2273e12c5d1SDavid du Colombier x = setsymtab(temp, "", 0.0, STR, ARGVtab);
2283e12c5d1SDavid du Colombier s = getsval(x);
2293e12c5d1SDavid du Colombier dprintf( ("getargv(%d) returns |%s|\n", n, s) );
2303e12c5d1SDavid du Colombier return s;
2313e12c5d1SDavid du Colombier }
2323e12c5d1SDavid du Colombier
setclvar(char * s)2337dd7cddfSDavid du Colombier void setclvar(char *s) /* set var=value from s */
2343e12c5d1SDavid du Colombier {
2357dd7cddfSDavid du Colombier char *p;
2363e12c5d1SDavid du Colombier Cell *q;
2373e12c5d1SDavid du Colombier
2383e12c5d1SDavid du Colombier for (p=s; *p != '='; p++)
2393e12c5d1SDavid du Colombier ;
2403e12c5d1SDavid du Colombier *p++ = 0;
2413e12c5d1SDavid du Colombier p = qstring(p, '\0');
2423e12c5d1SDavid du Colombier q = setsymtab(s, p, 0.0, STR, symtab);
2433e12c5d1SDavid du Colombier setsval(q, p);
2447dd7cddfSDavid du Colombier if (is_number(q->sval)) {
2453e12c5d1SDavid du Colombier q->fval = atof(q->sval);
2463e12c5d1SDavid du Colombier q->tval |= NUM;
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier dprintf( ("command line set %s to |%s|\n", s, p) );
2493e12c5d1SDavid du Colombier }
2503e12c5d1SDavid du Colombier
2513e12c5d1SDavid du Colombier
fldbld(void)252219b2ee8SDavid du Colombier void fldbld(void) /* create fields from current record */
2533e12c5d1SDavid du Colombier {
2547dd7cddfSDavid du Colombier /* this relies on having fields[] the same length as $0 */
2557dd7cddfSDavid du Colombier /* the fields are all stored in this one array with \0's */
2567dd7cddfSDavid du Colombier char *r, *fr, sep;
2573e12c5d1SDavid du Colombier Cell *p;
2587dd7cddfSDavid du Colombier int i, j, n;
2593e12c5d1SDavid du Colombier
2603e12c5d1SDavid du Colombier if (donefld)
2613e12c5d1SDavid du Colombier return;
2627dd7cddfSDavid du Colombier if (!isstr(fldtab[0]))
2637dd7cddfSDavid du Colombier getsval(fldtab[0]);
2647dd7cddfSDavid du Colombier r = fldtab[0]->sval;
2657dd7cddfSDavid du Colombier n = strlen(r);
2667dd7cddfSDavid du Colombier if (n > fieldssize) {
2677dd7cddfSDavid du Colombier xfree(fields);
2687dd7cddfSDavid du Colombier if ((fields = (char *) malloc(n+1)) == NULL)
2697dd7cddfSDavid du Colombier FATAL("out of space for fields in fldbld %d", n);
2707dd7cddfSDavid du Colombier fieldssize = n;
2717dd7cddfSDavid du Colombier }
2723e12c5d1SDavid du Colombier fr = fields;
2733e12c5d1SDavid du Colombier i = 0; /* number of fields accumulated here */
2747dd7cddfSDavid du Colombier if (strlen(inputFS) > 1) { /* it's a regular expression */
2757dd7cddfSDavid du Colombier i = refldbld(r, inputFS);
2767dd7cddfSDavid du Colombier } else if ((sep = *inputFS) == ' ') { /* default whitespace */
2773e12c5d1SDavid du Colombier for (i = 0; ; ) {
2783e12c5d1SDavid du Colombier while (*r == ' ' || *r == '\t' || *r == '\n')
2793e12c5d1SDavid du Colombier r++;
2803e12c5d1SDavid du Colombier if (*r == 0)
2813e12c5d1SDavid du Colombier break;
2823e12c5d1SDavid du Colombier i++;
2837dd7cddfSDavid du Colombier if (i > nfields)
2847dd7cddfSDavid du Colombier growfldtab(i);
2857dd7cddfSDavid du Colombier if (freeable(fldtab[i]))
2867dd7cddfSDavid du Colombier xfree(fldtab[i]->sval);
2877dd7cddfSDavid du Colombier fldtab[i]->sval = fr;
2887dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE;
2893e12c5d1SDavid du Colombier do
2903e12c5d1SDavid du Colombier *fr++ = *r++;
2913e12c5d1SDavid du Colombier while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
2923e12c5d1SDavid du Colombier *fr++ = 0;
2933e12c5d1SDavid du Colombier }
2943e12c5d1SDavid du Colombier *fr = 0;
2957dd7cddfSDavid du Colombier } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */
2967dd7cddfSDavid du Colombier for (i = 0; *r != 0; r++) {
2977dd7cddfSDavid du Colombier char buf[2];
2987dd7cddfSDavid du Colombier i++;
2997dd7cddfSDavid du Colombier if (i > nfields)
3007dd7cddfSDavid du Colombier growfldtab(i);
3017dd7cddfSDavid du Colombier if (freeable(fldtab[i]))
3027dd7cddfSDavid du Colombier xfree(fldtab[i]->sval);
3037dd7cddfSDavid du Colombier buf[0] = *r;
3047dd7cddfSDavid du Colombier buf[1] = 0;
3057dd7cddfSDavid du Colombier fldtab[i]->sval = tostring(buf);
3067dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR;
3077dd7cddfSDavid du Colombier }
3087dd7cddfSDavid du Colombier *fr = 0;
3093e12c5d1SDavid du Colombier } else if (*r != 0) { /* if 0, it's a null field */
3103e12c5d1SDavid du Colombier for (;;) {
3113e12c5d1SDavid du Colombier i++;
3127dd7cddfSDavid du Colombier if (i > nfields)
3137dd7cddfSDavid du Colombier growfldtab(i);
3147dd7cddfSDavid du Colombier if (freeable(fldtab[i]))
3157dd7cddfSDavid du Colombier xfree(fldtab[i]->sval);
3167dd7cddfSDavid du Colombier fldtab[i]->sval = fr;
3177dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE;
318219b2ee8SDavid du Colombier while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */
3193e12c5d1SDavid du Colombier *fr++ = *r++;
3203e12c5d1SDavid du Colombier *fr++ = 0;
3213e12c5d1SDavid du Colombier if (*r++ == 0)
3223e12c5d1SDavid du Colombier break;
3233e12c5d1SDavid du Colombier }
3243e12c5d1SDavid du Colombier *fr = 0;
3253e12c5d1SDavid du Colombier }
3267dd7cddfSDavid du Colombier if (i > nfields)
3277dd7cddfSDavid du Colombier FATAL("record `%.30s...' has too many fields; can't happen", r);
3287dd7cddfSDavid du Colombier cleanfld(i+1, lastfld); /* clean out junk from previous record */
3297dd7cddfSDavid du Colombier lastfld = i;
3303e12c5d1SDavid du Colombier donefld = 1;
3317dd7cddfSDavid du Colombier for (j = 1; j <= lastfld; j++) {
3327dd7cddfSDavid du Colombier p = fldtab[j];
3337dd7cddfSDavid du Colombier if(is_number(p->sval)) {
3343e12c5d1SDavid du Colombier p->fval = atof(p->sval);
3353e12c5d1SDavid du Colombier p->tval |= NUM;
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier }
3387dd7cddfSDavid du Colombier setfval(nfloc, (Awkfloat) lastfld);
3397dd7cddfSDavid du Colombier if (dbg) {
3407dd7cddfSDavid du Colombier for (j = 0; j <= lastfld; j++) {
3417dd7cddfSDavid du Colombier p = fldtab[j];
3427dd7cddfSDavid du Colombier printf("field %d (%s): |%s|\n", j, p->nval, p->sval);
3437dd7cddfSDavid du Colombier }
3447dd7cddfSDavid du Colombier }
3453e12c5d1SDavid du Colombier }
3463e12c5d1SDavid du Colombier
cleanfld(int n1,int n2)3473e12c5d1SDavid du Colombier void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */
3487dd7cddfSDavid du Colombier { /* nvals remain intact */
3497dd7cddfSDavid du Colombier Cell *p;
3507dd7cddfSDavid du Colombier int i;
3513e12c5d1SDavid du Colombier
3527dd7cddfSDavid du Colombier for (i = n1; i <= n2; i++) {
3537dd7cddfSDavid du Colombier p = fldtab[i];
3547dd7cddfSDavid du Colombier if (freeable(p))
3553e12c5d1SDavid du Colombier xfree(p->sval);
3567dd7cddfSDavid du Colombier p->sval = "";
3573e12c5d1SDavid du Colombier p->tval = FLD | STR | DONTFREE;
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier }
3603e12c5d1SDavid du Colombier
newfld(int n)3617dd7cddfSDavid du Colombier void newfld(int n) /* add field n after end of existing lastfld */
3623e12c5d1SDavid du Colombier {
3637dd7cddfSDavid du Colombier if (n > nfields)
3647dd7cddfSDavid du Colombier growfldtab(n);
3657dd7cddfSDavid du Colombier cleanfld(lastfld+1, n);
3667dd7cddfSDavid du Colombier lastfld = n;
3673e12c5d1SDavid du Colombier setfval(nfloc, (Awkfloat) n);
3683e12c5d1SDavid du Colombier }
3693e12c5d1SDavid du Colombier
fieldadr(int n)3707dd7cddfSDavid du Colombier Cell *fieldadr(int n) /* get nth field */
3713e12c5d1SDavid du Colombier {
3727dd7cddfSDavid du Colombier if (n < 0)
3737dd7cddfSDavid du Colombier FATAL("trying to access field %d", n);
3747dd7cddfSDavid du Colombier if (n > nfields) /* fields after NF are empty */
3757dd7cddfSDavid du Colombier growfldtab(n); /* but does not increase NF */
3767dd7cddfSDavid du Colombier return(fldtab[n]);
3777dd7cddfSDavid du Colombier }
3783e12c5d1SDavid du Colombier
growfldtab(int n)3797dd7cddfSDavid du Colombier void growfldtab(int n) /* make new fields up to at least $n */
3807dd7cddfSDavid du Colombier {
3817dd7cddfSDavid du Colombier int nf = 2 * nfields;
3827dd7cddfSDavid du Colombier
3837dd7cddfSDavid du Colombier if (n > nf)
3847dd7cddfSDavid du Colombier nf = n;
3857dd7cddfSDavid du Colombier fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *)));
3867dd7cddfSDavid du Colombier if (fldtab == NULL)
3877dd7cddfSDavid du Colombier FATAL("out of space creating %d fields", nf);
3887dd7cddfSDavid du Colombier makefields(nfields+1, nf);
3897dd7cddfSDavid du Colombier nfields = nf;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier
refldbld(char * rec,char * fs)3927dd7cddfSDavid du Colombier int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */
3937dd7cddfSDavid du Colombier {
3947dd7cddfSDavid du Colombier /* this relies on having fields[] the same length as $0 */
3957dd7cddfSDavid du Colombier /* the fields are all stored in this one array with \0's */
3967dd7cddfSDavid du Colombier char *fr;
3977dd7cddfSDavid du Colombier void *p;
3987dd7cddfSDavid du Colombier int i, tempstat, n;
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier n = strlen(rec);
4017dd7cddfSDavid du Colombier if (n > fieldssize) {
4027dd7cddfSDavid du Colombier xfree(fields);
4037dd7cddfSDavid du Colombier if ((fields = (char *) malloc(n+1)) == NULL)
4047dd7cddfSDavid du Colombier FATAL("out of space for fields in refldbld %d", n);
4057dd7cddfSDavid du Colombier fieldssize = n;
4067dd7cddfSDavid du Colombier }
4073e12c5d1SDavid du Colombier fr = fields;
4083e12c5d1SDavid du Colombier *fr = '\0';
4093e12c5d1SDavid du Colombier if (*rec == '\0')
4103e12c5d1SDavid du Colombier return 0;
4113e12c5d1SDavid du Colombier p = compre(fs);
4123e12c5d1SDavid du Colombier dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
4137dd7cddfSDavid du Colombier for (i = 1; ; i++) {
4147dd7cddfSDavid du Colombier if (i > nfields)
4157dd7cddfSDavid du Colombier growfldtab(i);
4167dd7cddfSDavid du Colombier if (freeable(fldtab[i]))
4177dd7cddfSDavid du Colombier xfree(fldtab[i]->sval);
4187dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE;
4197dd7cddfSDavid du Colombier fldtab[i]->sval = fr;
4203e12c5d1SDavid du Colombier dprintf( ("refldbld: i=%d\n", i) );
4213e12c5d1SDavid du Colombier if (nematch(p, rec, rec)) {
4223e12c5d1SDavid du Colombier dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
4233e12c5d1SDavid du Colombier strncpy(fr, rec, patbeg-rec);
4243e12c5d1SDavid du Colombier fr += patbeg - rec + 1;
4253e12c5d1SDavid du Colombier *(fr-1) = '\0';
4263e12c5d1SDavid du Colombier rec = patbeg + patlen;
4273e12c5d1SDavid du Colombier } else {
4283e12c5d1SDavid du Colombier dprintf( ("no match %s\n", rec) );
4293e12c5d1SDavid du Colombier strcpy(fr, rec);
4303e12c5d1SDavid du Colombier break;
4313e12c5d1SDavid du Colombier }
4323e12c5d1SDavid du Colombier }
4333e12c5d1SDavid du Colombier return i;
4343e12c5d1SDavid du Colombier }
4353e12c5d1SDavid du Colombier
recbld(void)436219b2ee8SDavid du Colombier void recbld(void) /* create $0 from $1..$NF if necessary */
4373e12c5d1SDavid du Colombier {
4387dd7cddfSDavid du Colombier int i;
4397dd7cddfSDavid du Colombier char *r, *p;
4403e12c5d1SDavid du Colombier
4413e12c5d1SDavid du Colombier if (donerec == 1)
4423e12c5d1SDavid du Colombier return;
4437dd7cddfSDavid du Colombier r = record;
4443e12c5d1SDavid du Colombier for (i = 1; i <= *NF; i++) {
4457dd7cddfSDavid du Colombier p = getsval(fldtab[i]);
4467dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1"))
4477dd7cddfSDavid du Colombier FATAL("created $0 `%.30s...' too long", record);
4487dd7cddfSDavid du Colombier while ((*r = *p++) != 0)
4493e12c5d1SDavid du Colombier r++;
4507dd7cddfSDavid du Colombier if (i < *NF) {
4517dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
4527dd7cddfSDavid du Colombier FATAL("created $0 `%.30s...' too long", record);
4537dd7cddfSDavid du Colombier for (p = *OFS; (*r = *p++) != 0; )
4543e12c5d1SDavid du Colombier r++;
4553e12c5d1SDavid du Colombier }
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
4587dd7cddfSDavid du Colombier FATAL("built giant record `%.30s...'", record);
4593e12c5d1SDavid du Colombier *r = '\0';
4607dd7cddfSDavid du Colombier dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
4617dd7cddfSDavid du Colombier
4627dd7cddfSDavid du Colombier if (freeable(fldtab[0]))
4637dd7cddfSDavid du Colombier xfree(fldtab[0]->sval);
4647dd7cddfSDavid du Colombier fldtab[0]->tval = REC | STR | DONTFREE;
4657dd7cddfSDavid du Colombier fldtab[0]->sval = record;
4667dd7cddfSDavid du Colombier
4677dd7cddfSDavid du Colombier dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
4683e12c5d1SDavid du Colombier dprintf( ("recbld = |%s|\n", record) );
4693e12c5d1SDavid du Colombier donerec = 1;
4703e12c5d1SDavid du Colombier }
4713e12c5d1SDavid du Colombier
4727dd7cddfSDavid du Colombier int errorflag = 0;
4737dd7cddfSDavid du Colombier
yyerror(char * s)4747dd7cddfSDavid du Colombier void yyerror(char *s)
4753e12c5d1SDavid du Colombier {
4767dd7cddfSDavid du Colombier SYNTAX(s);
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier
SYNTAX(char * fmt,...)4797dd7cddfSDavid du Colombier void SYNTAX(char *fmt, ...)
4803e12c5d1SDavid du Colombier {
4817dd7cddfSDavid du Colombier extern char *cmdname, *curfname;
4823e12c5d1SDavid du Colombier static int been_here = 0;
4837dd7cddfSDavid du Colombier va_list varg;
4843e12c5d1SDavid du Colombier
4853e12c5d1SDavid du Colombier if (been_here++ > 2)
4863e12c5d1SDavid du Colombier return;
4877dd7cddfSDavid du Colombier fprintf(stderr, "%s: ", cmdname);
4887dd7cddfSDavid du Colombier va_start(varg, fmt);
4897dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg);
4907dd7cddfSDavid du Colombier va_end(varg);
4917dd7cddfSDavid du Colombier if(compile_time == 1 && cursource() != NULL)
4927dd7cddfSDavid du Colombier fprintf(stderr, " at %s:%d", cursource(), lineno);
4937dd7cddfSDavid du Colombier else
4947dd7cddfSDavid du Colombier fprintf(stderr, " at line %d", lineno);
4953e12c5d1SDavid du Colombier if (curfname != NULL)
4963e12c5d1SDavid du Colombier fprintf(stderr, " in function %s", curfname);
4973e12c5d1SDavid du Colombier fprintf(stderr, "\n");
4983e12c5d1SDavid du Colombier errorflag = 2;
4993e12c5d1SDavid du Colombier eprint();
5003e12c5d1SDavid du Colombier }
5013e12c5d1SDavid du Colombier
fpecatch(int n)5023e12c5d1SDavid du Colombier void fpecatch(int n)
5033e12c5d1SDavid du Colombier {
5047dd7cddfSDavid du Colombier FATAL("floating point exception %d", n);
5053e12c5d1SDavid du Colombier }
5063e12c5d1SDavid du Colombier
5073e12c5d1SDavid du Colombier extern int bracecnt, brackcnt, parencnt;
5083e12c5d1SDavid du Colombier
bracecheck(void)5093e12c5d1SDavid du Colombier void bracecheck(void)
5103e12c5d1SDavid du Colombier {
5113e12c5d1SDavid du Colombier int c;
5123e12c5d1SDavid du Colombier static int beenhere = 0;
5133e12c5d1SDavid du Colombier
5143e12c5d1SDavid du Colombier if (beenhere++)
5153e12c5d1SDavid du Colombier return;
5163e12c5d1SDavid du Colombier while ((c = input()) != EOF && c != '\0')
5173e12c5d1SDavid du Colombier bclass(c);
5183e12c5d1SDavid du Colombier bcheck2(bracecnt, '{', '}');
5193e12c5d1SDavid du Colombier bcheck2(brackcnt, '[', ']');
5203e12c5d1SDavid du Colombier bcheck2(parencnt, '(', ')');
5213e12c5d1SDavid du Colombier }
5223e12c5d1SDavid du Colombier
bcheck2(int n,int c1,int c2)5233e12c5d1SDavid du Colombier void bcheck2(int n, int c1, int c2)
5243e12c5d1SDavid du Colombier {
5253e12c5d1SDavid du Colombier if (n == 1)
5263e12c5d1SDavid du Colombier fprintf(stderr, "\tmissing %c\n", c2);
5273e12c5d1SDavid du Colombier else if (n > 1)
5283e12c5d1SDavid du Colombier fprintf(stderr, "\t%d missing %c's\n", n, c2);
5293e12c5d1SDavid du Colombier else if (n == -1)
5303e12c5d1SDavid du Colombier fprintf(stderr, "\textra %c\n", c2);
5313e12c5d1SDavid du Colombier else if (n < -1)
5323e12c5d1SDavid du Colombier fprintf(stderr, "\t%d extra %c's\n", -n, c2);
5333e12c5d1SDavid du Colombier }
5343e12c5d1SDavid du Colombier
FATAL(char * fmt,...)5357dd7cddfSDavid du Colombier void FATAL(char *fmt, ...)
5363e12c5d1SDavid du Colombier {
5377dd7cddfSDavid du Colombier extern char *cmdname;
5387dd7cddfSDavid du Colombier va_list varg;
5393e12c5d1SDavid du Colombier
5403e12c5d1SDavid du Colombier fflush(stdout);
5413e12c5d1SDavid du Colombier fprintf(stderr, "%s: ", cmdname);
5427dd7cddfSDavid du Colombier va_start(varg, fmt);
5437dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg);
5447dd7cddfSDavid du Colombier va_end(varg);
5457dd7cddfSDavid du Colombier error();
546219b2ee8SDavid du Colombier if (dbg > 1) /* core dump if serious debugging on */
5473e12c5d1SDavid du Colombier abort();
5483e12c5d1SDavid du Colombier exit(2);
5493e12c5d1SDavid du Colombier }
5507dd7cddfSDavid du Colombier
WARNING(char * fmt,...)5517dd7cddfSDavid du Colombier void WARNING(char *fmt, ...)
5527dd7cddfSDavid du Colombier {
5537dd7cddfSDavid du Colombier extern char *cmdname;
5547dd7cddfSDavid du Colombier va_list varg;
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier fflush(stdout);
5577dd7cddfSDavid du Colombier fprintf(stderr, "%s: ", cmdname);
5587dd7cddfSDavid du Colombier va_start(varg, fmt);
5597dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg);
5607dd7cddfSDavid du Colombier va_end(varg);
5617dd7cddfSDavid du Colombier error();
5627dd7cddfSDavid du Colombier }
5637dd7cddfSDavid du Colombier
error()5647dd7cddfSDavid du Colombier void error()
5657dd7cddfSDavid du Colombier {
5667dd7cddfSDavid du Colombier extern Node *curnode;
5677dd7cddfSDavid du Colombier int line;
5687dd7cddfSDavid du Colombier
5697dd7cddfSDavid du Colombier fprintf(stderr, "\n");
5707dd7cddfSDavid du Colombier if (compile_time != 2 && NR && *NR > 0) {
5717dd7cddfSDavid du Colombier if (strcmp(*FILENAME, "-") != 0)
5727dd7cddfSDavid du Colombier fprintf(stderr, " input record %s:%d", *FILENAME, (int) (*FNR));
5737dd7cddfSDavid du Colombier else
5747dd7cddfSDavid du Colombier fprintf(stderr, " input record number %d", (int) (*FNR));
5757dd7cddfSDavid du Colombier fprintf(stderr, "\n");
5767dd7cddfSDavid du Colombier }
5777dd7cddfSDavid du Colombier if (compile_time != 2 && curnode)
5787dd7cddfSDavid du Colombier line = curnode->lineno;
5797dd7cddfSDavid du Colombier else if (compile_time != 2 && lineno)
5807dd7cddfSDavid du Colombier line = lineno;
5817dd7cddfSDavid du Colombier else
5827dd7cddfSDavid du Colombier line = -1;
5837dd7cddfSDavid du Colombier if (compile_time == 1 && cursource() != NULL){
5847dd7cddfSDavid du Colombier if(line >= 0)
5857dd7cddfSDavid du Colombier fprintf(stderr, " source %s:%d", cursource(), line);
5867dd7cddfSDavid du Colombier else
5877dd7cddfSDavid du Colombier fprintf(stderr, " source file %s", cursource());
5887dd7cddfSDavid du Colombier }else if(line >= 0)
5897dd7cddfSDavid du Colombier fprintf(stderr, " source line %d", line);
5907dd7cddfSDavid du Colombier fprintf(stderr, "\n");
5917dd7cddfSDavid du Colombier eprint();
5923e12c5d1SDavid du Colombier }
5933e12c5d1SDavid du Colombier
eprint(void)5943e12c5d1SDavid du Colombier void eprint(void) /* try to print context around error */
5953e12c5d1SDavid du Colombier {
5967dd7cddfSDavid du Colombier char *p, *q;
5973e12c5d1SDavid du Colombier int c;
5983e12c5d1SDavid du Colombier static int been_here = 0;
5997dd7cddfSDavid du Colombier extern char ebuf[], *ep;
6003e12c5d1SDavid du Colombier
6013e12c5d1SDavid du Colombier if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
6023e12c5d1SDavid du Colombier return;
6033e12c5d1SDavid du Colombier p = ep - 1;
6043e12c5d1SDavid du Colombier if (p > ebuf && *p == '\n')
6053e12c5d1SDavid du Colombier p--;
6063e12c5d1SDavid du Colombier for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
6073e12c5d1SDavid du Colombier ;
6083e12c5d1SDavid du Colombier while (*p == '\n')
6093e12c5d1SDavid du Colombier p++;
6103e12c5d1SDavid du Colombier fprintf(stderr, " context is\n\t");
6113e12c5d1SDavid du Colombier for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
6123e12c5d1SDavid du Colombier ;
6133e12c5d1SDavid du Colombier for ( ; p < q; p++)
6143e12c5d1SDavid du Colombier if (*p)
6153e12c5d1SDavid du Colombier putc(*p, stderr);
6163e12c5d1SDavid du Colombier fprintf(stderr, " >>> ");
6173e12c5d1SDavid du Colombier for ( ; p < ep; p++)
6183e12c5d1SDavid du Colombier if (*p)
6193e12c5d1SDavid du Colombier putc(*p, stderr);
6203e12c5d1SDavid du Colombier fprintf(stderr, " <<< ");
6213e12c5d1SDavid du Colombier if (*ep)
6223e12c5d1SDavid du Colombier while ((c = input()) != '\n' && c != '\0' && c != EOF) {
6233e12c5d1SDavid du Colombier putc(c, stderr);
6243e12c5d1SDavid du Colombier bclass(c);
6253e12c5d1SDavid du Colombier }
6263e12c5d1SDavid du Colombier putc('\n', stderr);
6273e12c5d1SDavid du Colombier ep = ebuf;
6283e12c5d1SDavid du Colombier }
6293e12c5d1SDavid du Colombier
bclass(int c)6303e12c5d1SDavid du Colombier void bclass(int c)
6313e12c5d1SDavid du Colombier {
6323e12c5d1SDavid du Colombier switch (c) {
6333e12c5d1SDavid du Colombier case '{': bracecnt++; break;
6343e12c5d1SDavid du Colombier case '}': bracecnt--; break;
6353e12c5d1SDavid du Colombier case '[': brackcnt++; break;
6363e12c5d1SDavid du Colombier case ']': brackcnt--; break;
6373e12c5d1SDavid du Colombier case '(': parencnt++; break;
6383e12c5d1SDavid du Colombier case ')': parencnt--; break;
6393e12c5d1SDavid du Colombier }
6403e12c5d1SDavid du Colombier }
6413e12c5d1SDavid du Colombier
errcheck(double x,char * s)6427dd7cddfSDavid du Colombier double errcheck(double x, char *s)
6433e12c5d1SDavid du Colombier {
6443e12c5d1SDavid du Colombier
6453e12c5d1SDavid du Colombier if (errno == EDOM) {
6463e12c5d1SDavid du Colombier errno = 0;
6477dd7cddfSDavid du Colombier WARNING("%s argument out of domain", s);
6483e12c5d1SDavid du Colombier x = 1;
6493e12c5d1SDavid du Colombier } else if (errno == ERANGE) {
6503e12c5d1SDavid du Colombier errno = 0;
6517dd7cddfSDavid du Colombier WARNING("%s result out of range", s);
6523e12c5d1SDavid du Colombier x = 1;
6533e12c5d1SDavid du Colombier }
6543e12c5d1SDavid du Colombier return x;
6553e12c5d1SDavid du Colombier }
6563e12c5d1SDavid du Colombier
isclvar(char * s)6577dd7cddfSDavid du Colombier int isclvar(char *s) /* is s of form var=something ? */
6583e12c5d1SDavid du Colombier {
6597dd7cddfSDavid du Colombier char *os = s;
6603e12c5d1SDavid du Colombier
6613e12c5d1SDavid du Colombier if (!isalpha(*s) && *s != '_')
6623e12c5d1SDavid du Colombier return 0;
6633e12c5d1SDavid du Colombier for ( ; *s; s++)
6643e12c5d1SDavid du Colombier if (!(isalnum(*s) || *s == '_'))
6653e12c5d1SDavid du Colombier break;
6663e12c5d1SDavid du Colombier return *s == '=' && s > os && *(s+1) != '=';
6673e12c5d1SDavid du Colombier }
6683e12c5d1SDavid du Colombier
6697dd7cddfSDavid du Colombier /* strtod is supposed to be a proper test of what's a valid number */
6703e12c5d1SDavid du Colombier
6717dd7cddfSDavid du Colombier #include <math.h>
is_number(char * s)6727dd7cddfSDavid du Colombier int is_number(char *s)
6733e12c5d1SDavid du Colombier {
6747dd7cddfSDavid du Colombier double r;
6757dd7cddfSDavid du Colombier char *ep;
676*05bfb676SDavid du Colombier
677*05bfb676SDavid du Colombier /*
678*05bfb676SDavid du Colombier * fast could-it-be-a-number check before calling strtod,
679*05bfb676SDavid du Colombier * which takes a surprisingly long time to reject non-numbers.
680*05bfb676SDavid du Colombier */
681*05bfb676SDavid du Colombier switch (*s) {
682*05bfb676SDavid du Colombier case '0': case '1': case '2': case '3': case '4':
683*05bfb676SDavid du Colombier case '5': case '6': case '7': case '8': case '9':
684*05bfb676SDavid du Colombier case '\t':
685*05bfb676SDavid du Colombier case '\n':
686*05bfb676SDavid du Colombier case '\v':
687*05bfb676SDavid du Colombier case '\f':
688*05bfb676SDavid du Colombier case '\r':
689*05bfb676SDavid du Colombier case ' ':
690*05bfb676SDavid du Colombier case '-':
691*05bfb676SDavid du Colombier case '+':
692*05bfb676SDavid du Colombier case '.':
693*05bfb676SDavid du Colombier case 'n': /* nans */
694*05bfb676SDavid du Colombier case 'N':
695*05bfb676SDavid du Colombier case 'i': /* infs */
696*05bfb676SDavid du Colombier case 'I':
697*05bfb676SDavid du Colombier break;
698*05bfb676SDavid du Colombier default:
699*05bfb676SDavid du Colombier return 0; /* can't be a number */
700*05bfb676SDavid du Colombier }
701*05bfb676SDavid du Colombier
7027dd7cddfSDavid du Colombier errno = 0;
7037dd7cddfSDavid du Colombier r = strtod(s, &ep);
7047dd7cddfSDavid du Colombier if (ep == s || r == HUGE_VAL || errno == ERANGE)
7057dd7cddfSDavid du Colombier return 0;
7067dd7cddfSDavid du Colombier while (*ep == ' ' || *ep == '\t' || *ep == '\n')
7077dd7cddfSDavid du Colombier ep++;
7087dd7cddfSDavid du Colombier if (*ep == '\0')
7097dd7cddfSDavid du Colombier return 1;
7103e12c5d1SDavid du Colombier else
7117dd7cddfSDavid du Colombier return 0;
7123e12c5d1SDavid du Colombier }
713