File:  [local] / rpl / rplawk / lib.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Sep 7 12:53:05 2010 UTC (13 years, 8 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_9, rpl-4_1_8, rpl-4_1_7, rpl-4_1_6, rpl-4_1_5, rpl-4_1_4, rpl-4_1_3, rpl-4_1_2, rpl-4_1_13, rpl-4_1_12, rpl-4_1_11, rpl-4_1_10, rpl-4_1_1, rpl-4_1_0, rpl-4_0_24, rpl-4_0_22, rpl-4_0_21, rpl-4_0_20, rpl-4_0_19, rpl-4_0, HEAD
Ajout d'un AWK interne pour éviter des problèmes sur les OS non Unix.

    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>