File:  [local] / rpl / rplawk / lib.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Wed Jun 12 09:47:52 2013 UTC (10 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, rpl-4_1_33, rpl-4_1_32, rpl-4_1_31, rpl-4_1_30, rpl-4_1_29, rpl-4_1_28, rpl-4_1_27, rpl-4_1_26, rpl-4_1_25, rpl-4_1_24, rpl-4_1_23, rpl-4_1_22, rpl-4_1_21, rpl-4_1_20, rpl-4_1_19, rpl-4_1_18, rpl-4_1_17, rpl-4_1_16, rpl-4_1_15, rpl-4_1_14, HEAD
Quelques patches pour rplawk et ncurses.

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

CVSweb interface <joel.bertrand@systella.fr>