Annotation of rpl/rplawk/lib.c, revision 1.1
1.1 ! bertrand 1: /****************************************************************
! 2: Copyright (C) Lucent Technologies 1997
! 3: All Rights Reserved
! 4:
! 5: Permission to use, copy, modify, and distribute this software and
! 6: its documentation for any purpose and without fee is hereby
! 7: granted, provided that the above copyright notice appear in all
! 8: copies and that both that the copyright notice and this
! 9: permission notice and warranty disclaimer appear in supporting
! 10: documentation, and that the name Lucent Technologies or any of
! 11: its entities not be used in advertising or publicity pertaining
! 12: to distribution of the software without specific, written prior
! 13: permission.
! 14:
! 15: LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
! 16: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
! 17: IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
! 18: SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 19: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
! 20: IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
! 21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
! 22: THIS SOFTWARE.
! 23: ****************************************************************/
! 24:
! 25: #define DEBUG
! 26: #include <stdio.h>
! 27: #include <string.h>
! 28: #include <ctype.h>
! 29: #include <errno.h>
! 30: #include <stdlib.h>
! 31: #include <stdarg.h>
! 32: #include "awk.h"
! 33: #include "ytab.h"
! 34:
! 35: FILE *infile = NULL;
! 36: char *file = "";
! 37: char *record;
! 38: int recsize = RECSIZE;
! 39: char *fields;
! 40: int fieldssize = RECSIZE;
! 41:
! 42: Cell **fldtab; /* pointers to Cells */
! 43: char inputFS[100] = " ";
! 44:
! 45: #define MAXFLD 2
! 46: int nfields = MAXFLD; /* last allocated slot for $i */
! 47:
! 48: int donefld; /* 1 = implies rec broken into fields */
! 49: int donerec; /* 1 = record is valid (no flds have changed) */
! 50:
! 51: int lastfld = 0; /* last used field */
! 52: int argno = 1; /* current input argument number */
! 53: extern Awkfloat *ARGC;
! 54:
! 55: static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE };
! 56: static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE };
! 57:
! 58: void recinit(unsigned int n)
! 59: {
! 60: if ( (record = (char *) malloc(n)) == NULL
! 61: || (fields = (char *) malloc(n+1)) == NULL
! 62: || (fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *))) == NULL
! 63: || (fldtab[0] = (Cell *) malloc(sizeof(Cell))) == NULL )
! 64: FATAL("out of space for $0 and fields");
! 65: *fldtab[0] = dollar0;
! 66: fldtab[0]->sval = record;
! 67: fldtab[0]->nval = tostring("0");
! 68: makefields(1, nfields);
! 69: }
! 70:
! 71: void makefields(int n1, int n2) /* create $n1..$n2 inclusive */
! 72: {
! 73: char temp[50];
! 74: int i;
! 75:
! 76: for (i = n1; i <= n2; i++) {
! 77: fldtab[i] = (Cell *) malloc(sizeof (struct Cell));
! 78: if (fldtab[i] == NULL)
! 79: FATAL("out of space in makefields %d", i);
! 80: *fldtab[i] = dollar1;
! 81: sprintf(temp, "%d", i);
! 82: fldtab[i]->nval = tostring(temp);
! 83: }
! 84: }
! 85:
! 86: void initgetrec(void)
! 87: {
! 88: int i;
! 89: char *p;
! 90:
! 91: for (i = 1; i < *ARGC; i++) {
! 92: if (!isclvar(p = getargv(i))) { /* find 1st real filename */
! 93: setsval(lookup("FILENAME", symtab), getargv(i));
! 94: return;
! 95: }
! 96: setclvar(p); /* a commandline assignment before filename */
! 97: argno++;
! 98: }
! 99: infile = stdin; /* no filenames, so use stdin */
! 100: }
! 101:
! 102: static int firsttime = 1;
! 103:
! 104: int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
! 105: { /* note: cares whether buf == record */
! 106: int c;
! 107: char *buf = *pbuf;
! 108: uschar saveb0;
! 109: int bufsize = *pbufsize, savebufsize = bufsize;
! 110:
! 111: if (firsttime) {
! 112: firsttime = 0;
! 113: initgetrec();
! 114: }
! 115: dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
! 116: *RS, *FS, *ARGC, *FILENAME) );
! 117: if (isrecord) {
! 118: donefld = 0;
! 119: donerec = 1;
! 120: }
! 121: saveb0 = buf[0];
! 122: buf[0] = 0;
! 123: while (argno < *ARGC || infile == stdin) {
! 124: dprintf( ("argno=%d, file=|%s|\n", argno, file) );
! 125: if (infile == NULL) { /* have to open a new file */
! 126: file = getargv(argno);
! 127: if (*file == '\0') { /* it's been zapped */
! 128: argno++;
! 129: continue;
! 130: }
! 131: if (isclvar(file)) { /* a var=value arg */
! 132: setclvar(file);
! 133: argno++;
! 134: continue;
! 135: }
! 136: *FILENAME = file;
! 137: dprintf( ("opening file %s\n", file) );
! 138: if (*file == '-' && *(file+1) == '\0')
! 139: infile = stdin;
! 140: else if ((infile = fopen(file, "r")) == NULL)
! 141: FATAL("can't open file %s", file);
! 142: setfval(fnrloc, 0.0);
! 143: }
! 144: c = readrec(&buf, &bufsize, infile);
! 145: if (c != 0 || buf[0] != '\0') { /* normal record */
! 146: if (isrecord) {
! 147: if (freeable(fldtab[0]))
! 148: xfree(fldtab[0]->sval);
! 149: fldtab[0]->sval = buf; /* buf == record */
! 150: fldtab[0]->tval = REC | STR | DONTFREE;
! 151: if (is_number(fldtab[0]->sval)) {
! 152: fldtab[0]->fval = atof(fldtab[0]->sval);
! 153: fldtab[0]->tval |= NUM;
! 154: }
! 155: }
! 156: setfval(nrloc, nrloc->fval+1);
! 157: setfval(fnrloc, fnrloc->fval+1);
! 158: *pbuf = buf;
! 159: *pbufsize = bufsize;
! 160: return 1;
! 161: }
! 162: /* EOF arrived on this file; set up next */
! 163: if (infile != stdin)
! 164: fclose(infile);
! 165: infile = NULL;
! 166: argno++;
! 167: }
! 168: buf[0] = saveb0;
! 169: *pbuf = buf;
! 170: *pbufsize = savebufsize;
! 171: return 0; /* true end of file */
! 172: }
! 173:
! 174: void nextfile(void)
! 175: {
! 176: if (infile != NULL && infile != stdin)
! 177: fclose(infile);
! 178: infile = NULL;
! 179: argno++;
! 180: }
! 181:
! 182: int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */
! 183: {
! 184: int sep, c;
! 185: char *rr, *buf = *pbuf;
! 186: int bufsize = *pbufsize;
! 187:
! 188: if (strlen(*FS) >= sizeof(inputFS))
! 189: FATAL("field separator %.10s... is too long", *FS);
! 190: strcpy(inputFS, *FS); /* for subsequent field splitting */
! 191: if ((sep = **RS) == 0) {
! 192: sep = '\n';
! 193: while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
! 194: ;
! 195: if (c != EOF)
! 196: ungetc(c, inf);
! 197: }
! 198: for (rr = buf; ; ) {
! 199: for (; (c=getc(inf)) != sep && c != EOF; ) {
! 200: if (rr-buf+1 > bufsize)
! 201: if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1"))
! 202: FATAL("input record `%.30s...' too long", buf);
! 203: *rr++ = c;
! 204: }
! 205: if (**RS == sep || c == EOF)
! 206: break;
! 207: if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
! 208: break;
! 209: if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2"))
! 210: FATAL("input record `%.30s...' too long", buf);
! 211: *rr++ = '\n';
! 212: *rr++ = c;
! 213: }
! 214: if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3"))
! 215: FATAL("input record `%.30s...' too long", buf);
! 216: *rr = 0;
! 217: dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
! 218: *pbuf = buf;
! 219: *pbufsize = bufsize;
! 220: return c == EOF && rr == buf ? 0 : 1;
! 221: }
! 222:
! 223: char *getargv(int n) /* get ARGV[n] */
! 224: {
! 225: Cell *x;
! 226: char *s, temp[50];
! 227: extern Array *ARGVtab;
! 228:
! 229: sprintf(temp, "%d", n);
! 230: x = setsymtab(temp, "", 0.0, STR, ARGVtab);
! 231: s = getsval(x);
! 232: dprintf( ("getargv(%d) returns |%s|\n", n, s) );
! 233: return s;
! 234: }
! 235:
! 236: void setclvar(char *s) /* set var=value from s */
! 237: {
! 238: char *p;
! 239: Cell *q;
! 240:
! 241: for (p=s; *p != '='; p++)
! 242: ;
! 243: *p++ = 0;
! 244: p = qstring(p, '\0');
! 245: q = setsymtab(s, p, 0.0, STR, symtab);
! 246: setsval(q, p);
! 247: if (is_number(q->sval)) {
! 248: q->fval = atof(q->sval);
! 249: q->tval |= NUM;
! 250: }
! 251: dprintf( ("command line set %s to |%s|\n", s, p) );
! 252: }
! 253:
! 254:
! 255: void fldbld(void) /* create fields from current record */
! 256: {
! 257: /* this relies on having fields[] the same length as $0 */
! 258: /* the fields are all stored in this one array with \0's */
! 259: char *r, *fr, sep;
! 260: Cell *p;
! 261: int i, j, n;
! 262:
! 263: if (donefld)
! 264: return;
! 265: if (!isstr(fldtab[0]))
! 266: getsval(fldtab[0]);
! 267: r = fldtab[0]->sval;
! 268: n = strlen(r);
! 269: if (n > fieldssize) {
! 270: xfree(fields);
! 271: if ((fields = (char *) malloc(n+1)) == NULL)
! 272: FATAL("out of space for fields in fldbld %d", n);
! 273: fieldssize = n;
! 274: }
! 275: fr = fields;
! 276: i = 0; /* number of fields accumulated here */
! 277: strcpy(inputFS, *FS);
! 278: if (strlen(inputFS) > 1) { /* it's a regular expression */
! 279: i = refldbld(r, inputFS);
! 280: } else if ((sep = *inputFS) == ' ') { /* default whitespace */
! 281: for (i = 0; ; ) {
! 282: while (*r == ' ' || *r == '\t' || *r == '\n')
! 283: r++;
! 284: if (*r == 0)
! 285: break;
! 286: i++;
! 287: if (i > nfields)
! 288: growfldtab(i);
! 289: if (freeable(fldtab[i]))
! 290: xfree(fldtab[i]->sval);
! 291: fldtab[i]->sval = fr;
! 292: fldtab[i]->tval = FLD | STR | DONTFREE;
! 293: do
! 294: *fr++ = *r++;
! 295: while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
! 296: *fr++ = 0;
! 297: }
! 298: *fr = 0;
! 299: } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */
! 300: for (i = 0; *r != 0; r++) {
! 301: char buf[2];
! 302: i++;
! 303: if (i > nfields)
! 304: growfldtab(i);
! 305: if (freeable(fldtab[i]))
! 306: xfree(fldtab[i]->sval);
! 307: buf[0] = *r;
! 308: buf[1] = 0;
! 309: fldtab[i]->sval = tostring(buf);
! 310: fldtab[i]->tval = FLD | STR;
! 311: }
! 312: *fr = 0;
! 313: } else if (*r != 0) { /* if 0, it's a null field */
! 314: /* subtlecase : if length(FS) == 1 && length(RS > 0)
! 315: * \n is NOT a field separator (cf awk book 61,84).
! 316: * this variable is tested in the inner while loop.
! 317: */
! 318: int rtest = '\n'; /* normal case */
! 319: if (strlen(*RS) > 0)
! 320: rtest = '\0';
! 321: for (;;) {
! 322: i++;
! 323: if (i > nfields)
! 324: growfldtab(i);
! 325: if (freeable(fldtab[i]))
! 326: xfree(fldtab[i]->sval);
! 327: fldtab[i]->sval = fr;
! 328: fldtab[i]->tval = FLD | STR | DONTFREE;
! 329: while (*r != sep && *r != rtest && *r != '\0') /* \n is always a separator */
! 330: *fr++ = *r++;
! 331: *fr++ = 0;
! 332: if (*r++ == 0)
! 333: break;
! 334: }
! 335: *fr = 0;
! 336: }
! 337: if (i > nfields)
! 338: FATAL("record `%.30s...' has too many fields; can't happen", r);
! 339: cleanfld(i+1, lastfld); /* clean out junk from previous record */
! 340: lastfld = i;
! 341: donefld = 1;
! 342: for (j = 1; j <= lastfld; j++) {
! 343: p = fldtab[j];
! 344: if(is_number(p->sval)) {
! 345: p->fval = atof(p->sval);
! 346: p->tval |= NUM;
! 347: }
! 348: }
! 349: setfval(nfloc, (Awkfloat) lastfld);
! 350: if (dbg) {
! 351: for (j = 0; j <= lastfld; j++) {
! 352: p = fldtab[j];
! 353: printf("field %d (%s): |%s|\n", j, p->nval, p->sval);
! 354: }
! 355: }
! 356: }
! 357:
! 358: void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */
! 359: { /* nvals remain intact */
! 360: Cell *p;
! 361: int i;
! 362:
! 363: for (i = n1; i <= n2; i++) {
! 364: p = fldtab[i];
! 365: if (freeable(p))
! 366: xfree(p->sval);
! 367: p->sval = "";
! 368: p->tval = FLD | STR | DONTFREE;
! 369: }
! 370: }
! 371:
! 372: void newfld(int n) /* add field n after end of existing lastfld */
! 373: {
! 374: if (n > nfields)
! 375: growfldtab(n);
! 376: cleanfld(lastfld+1, n);
! 377: lastfld = n;
! 378: setfval(nfloc, (Awkfloat) n);
! 379: }
! 380:
! 381: Cell *fieldadr(int n) /* get nth field */
! 382: {
! 383: if (n < 0)
! 384: FATAL("trying to access out of range field %d", n);
! 385: if (n > nfields) /* fields after NF are empty */
! 386: growfldtab(n); /* but does not increase NF */
! 387: return(fldtab[n]);
! 388: }
! 389:
! 390: void growfldtab(int n) /* make new fields up to at least $n */
! 391: {
! 392: int nf = 2 * nfields;
! 393: size_t s;
! 394:
! 395: if (n > nf)
! 396: nf = n;
! 397: s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */
! 398: if (s / sizeof(struct Cell *) - 1 == nf) /* didn't overflow */
! 399: fldtab = (Cell **) realloc(fldtab, s);
! 400: else /* overflow sizeof int */
! 401: xfree(fldtab); /* make it null */
! 402: if (fldtab == NULL)
! 403: FATAL("out of space creating %d fields", nf);
! 404: makefields(nfields+1, nf);
! 405: nfields = nf;
! 406: }
! 407:
! 408: int refldbld(const char *rec, const char *fs) /* build fields from reg expr in FS */
! 409: {
! 410: /* this relies on having fields[] the same length as $0 */
! 411: /* the fields are all stored in this one array with \0's */
! 412: char *fr;
! 413: int i, tempstat, n;
! 414: fa *pfa;
! 415:
! 416: n = strlen(rec);
! 417: if (n > fieldssize) {
! 418: xfree(fields);
! 419: if ((fields = (char *) malloc(n+1)) == NULL)
! 420: FATAL("out of space for fields in refldbld %d", n);
! 421: fieldssize = n;
! 422: }
! 423: fr = fields;
! 424: *fr = '\0';
! 425: if (*rec == '\0')
! 426: return 0;
! 427: pfa = makedfa(fs, 1);
! 428: dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
! 429: tempstat = pfa->initstat;
! 430: for (i = 1; ; i++) {
! 431: if (i > nfields)
! 432: growfldtab(i);
! 433: if (freeable(fldtab[i]))
! 434: xfree(fldtab[i]->sval);
! 435: fldtab[i]->tval = FLD | STR | DONTFREE;
! 436: fldtab[i]->sval = fr;
! 437: dprintf( ("refldbld: i=%d\n", i) );
! 438: if (nematch(pfa, rec)) {
! 439: pfa->initstat = 2; /* horrible coupling to b.c */
! 440: dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
! 441: strncpy(fr, rec, patbeg-rec);
! 442: fr += patbeg - rec + 1;
! 443: *(fr-1) = '\0';
! 444: rec = patbeg + patlen;
! 445: } else {
! 446: dprintf( ("no match %s\n", rec) );
! 447: strcpy(fr, rec);
! 448: pfa->initstat = tempstat;
! 449: break;
! 450: }
! 451: }
! 452: return i;
! 453: }
! 454:
! 455: void recbld(void) /* create $0 from $1..$NF if necessary */
! 456: {
! 457: int i;
! 458: char *r, *p;
! 459:
! 460: if (donerec == 1)
! 461: return;
! 462: r = record;
! 463: for (i = 1; i <= *NF; i++) {
! 464: p = getsval(fldtab[i]);
! 465: if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1"))
! 466: FATAL("created $0 `%.30s...' too long", record);
! 467: while ((*r = *p++) != 0)
! 468: r++;
! 469: if (i < *NF) {
! 470: if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2"))
! 471: FATAL("created $0 `%.30s...' too long", record);
! 472: for (p = *OFS; (*r = *p++) != 0; )
! 473: r++;
! 474: }
! 475: }
! 476: if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3"))
! 477: FATAL("built giant record `%.30s...'", record);
! 478: *r = '\0';
! 479: dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
! 480:
! 481: if (freeable(fldtab[0]))
! 482: xfree(fldtab[0]->sval);
! 483: fldtab[0]->tval = REC | STR | DONTFREE;
! 484: fldtab[0]->sval = record;
! 485:
! 486: dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) );
! 487: dprintf( ("recbld = |%s|\n", record) );
! 488: donerec = 1;
! 489: }
! 490:
! 491: int errorflag = 0;
! 492:
! 493: void yyerror(const char *s)
! 494: {
! 495: SYNTAX("%s", s);
! 496: }
! 497:
! 498: void SYNTAX(const char *fmt, ...)
! 499: {
! 500: extern char *cmdname, *curfname;
! 501: static int been_here = 0;
! 502: va_list varg;
! 503:
! 504: if (been_here++ > 2)
! 505: return;
! 506: fprintf(stderr, "%s: ", cmdname);
! 507: va_start(varg, fmt);
! 508: vfprintf(stderr, fmt, varg);
! 509: va_end(varg);
! 510: fprintf(stderr, " at source line %d", lineno);
! 511: if (curfname != NULL)
! 512: fprintf(stderr, " in function %s", curfname);
! 513: if (compile_time == 1 && cursource() != NULL)
! 514: fprintf(stderr, " source file %s", cursource());
! 515: fprintf(stderr, "\n");
! 516: errorflag = 2;
! 517: eprint();
! 518: }
! 519:
! 520: void fpecatch(int n)
! 521: {
! 522: FATAL("floating point exception %d", n);
! 523: }
! 524:
! 525: extern int bracecnt, brackcnt, parencnt;
! 526:
! 527: void bracecheck(void)
! 528: {
! 529: int c;
! 530: static int beenhere = 0;
! 531:
! 532: if (beenhere++)
! 533: return;
! 534: while ((c = input()) != EOF && c != '\0')
! 535: bclass(c);
! 536: bcheck2(bracecnt, '{', '}');
! 537: bcheck2(brackcnt, '[', ']');
! 538: bcheck2(parencnt, '(', ')');
! 539: }
! 540:
! 541: void bcheck2(int n, int c1, int c2)
! 542: {
! 543: if (n == 1)
! 544: fprintf(stderr, "\tmissing %c\n", c2);
! 545: else if (n > 1)
! 546: fprintf(stderr, "\t%d missing %c's\n", n, c2);
! 547: else if (n == -1)
! 548: fprintf(stderr, "\textra %c\n", c2);
! 549: else if (n < -1)
! 550: fprintf(stderr, "\t%d extra %c's\n", -n, c2);
! 551: }
! 552:
! 553: void FATAL(const char *fmt, ...)
! 554: {
! 555: extern char *cmdname;
! 556: va_list varg;
! 557:
! 558: fflush(stdout);
! 559: fprintf(stderr, "%s: ", cmdname);
! 560: va_start(varg, fmt);
! 561: vfprintf(stderr, fmt, varg);
! 562: va_end(varg);
! 563: error();
! 564: if (dbg > 1) /* core dump if serious debugging on */
! 565: abort();
! 566: exit(2);
! 567: }
! 568:
! 569: void WARNING(const char *fmt, ...)
! 570: {
! 571: extern char *cmdname;
! 572: va_list varg;
! 573:
! 574: fflush(stdout);
! 575: fprintf(stderr, "%s: ", cmdname);
! 576: va_start(varg, fmt);
! 577: vfprintf(stderr, fmt, varg);
! 578: va_end(varg);
! 579: error();
! 580: }
! 581:
! 582: void error()
! 583: {
! 584: extern Node *curnode;
! 585:
! 586: fprintf(stderr, "\n");
! 587: if (compile_time != 2 && NR && *NR > 0) {
! 588: fprintf(stderr, " input record number %d", (int) (*FNR));
! 589: if (strcmp(*FILENAME, "-") != 0)
! 590: fprintf(stderr, ", file %s", *FILENAME);
! 591: fprintf(stderr, "\n");
! 592: }
! 593: if (compile_time != 2 && curnode)
! 594: fprintf(stderr, " source line number %d", curnode->lineno);
! 595: else if (compile_time != 2 && lineno)
! 596: fprintf(stderr, " source line number %d", lineno);
! 597: if (compile_time == 1 && cursource() != NULL)
! 598: fprintf(stderr, " source file %s", cursource());
! 599: fprintf(stderr, "\n");
! 600: eprint();
! 601: }
! 602:
! 603: void eprint(void) /* try to print context around error */
! 604: {
! 605: char *p, *q;
! 606: int c;
! 607: static int been_here = 0;
! 608: extern char ebuf[], *ep;
! 609:
! 610: if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
! 611: return;
! 612: p = ep - 1;
! 613: if (p > ebuf && *p == '\n')
! 614: p--;
! 615: for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
! 616: ;
! 617: while (*p == '\n')
! 618: p++;
! 619: fprintf(stderr, " context is\n\t");
! 620: for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
! 621: ;
! 622: for ( ; p < q; p++)
! 623: if (*p)
! 624: putc(*p, stderr);
! 625: fprintf(stderr, " >>> ");
! 626: for ( ; p < ep; p++)
! 627: if (*p)
! 628: putc(*p, stderr);
! 629: fprintf(stderr, " <<< ");
! 630: if (*ep)
! 631: while ((c = input()) != '\n' && c != '\0' && c != EOF) {
! 632: putc(c, stderr);
! 633: bclass(c);
! 634: }
! 635: putc('\n', stderr);
! 636: ep = ebuf;
! 637: }
! 638:
! 639: void bclass(int c)
! 640: {
! 641: switch (c) {
! 642: case '{': bracecnt++; break;
! 643: case '}': bracecnt--; break;
! 644: case '[': brackcnt++; break;
! 645: case ']': brackcnt--; break;
! 646: case '(': parencnt++; break;
! 647: case ')': parencnt--; break;
! 648: }
! 649: }
! 650:
! 651: double errcheck(double x, const char *s)
! 652: {
! 653:
! 654: if (errno == EDOM) {
! 655: errno = 0;
! 656: WARNING("%s argument out of domain", s);
! 657: x = 1;
! 658: } else if (errno == ERANGE) {
! 659: errno = 0;
! 660: WARNING("%s result out of range", s);
! 661: x = 1;
! 662: }
! 663: return x;
! 664: }
! 665:
! 666: int isclvar(const char *s) /* is s of form var=something ? */
! 667: {
! 668: const char *os = s;
! 669:
! 670: if (!isalpha((uschar) *s) && *s != '_')
! 671: return 0;
! 672: for ( ; *s; s++)
! 673: if (!(isalnum((uschar) *s) || *s == '_'))
! 674: break;
! 675: return *s == '=' && s > os && *(s+1) != '=';
! 676: }
! 677:
! 678: /* strtod is supposed to be a proper test of what's a valid number */
! 679: /* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
! 680: /* wrong: violates 4.10.1.4 of ansi C standard */
! 681:
! 682: #include <math.h>
! 683: int is_number(const char *s)
! 684: {
! 685: double r;
! 686: char *ep;
! 687: errno = 0;
! 688: r = strtod(s, &ep);
! 689: if (ep == s || r == HUGE_VAL || errno == ERANGE)
! 690: return 0;
! 691: while (*ep == ' ' || *ep == '\t' || *ep == '\n')
! 692: ep++;
! 693: if (*ep == '\0')
! 694: return 1;
! 695: else
! 696: return 0;
! 697: }
CVSweb interface <joel.bertrand@systella.fr>