[BACK]Return to scanner.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/scanner.c, Revision 1.1

1.1     ! maekawa     1: #ifndef lint
        !             2: static char *RCSid = "$Id: scanner.c,v 1.56 1998/06/18 14:55:16 ddenholm Exp $";
        !             3: #endif
        !             4:
        !             5: /* GNUPLOT - scanner.c */
        !             6:
        !             7: /*[
        !             8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
        !             9:  *
        !            10:  * Permission to use, copy, and distribute this software and its
        !            11:  * documentation for any purpose with or without fee is hereby granted,
        !            12:  * provided that the above copyright notice appear in all copies and
        !            13:  * that both that copyright notice and this permission notice appear
        !            14:  * in supporting documentation.
        !            15:  *
        !            16:  * Permission to modify the software is granted, but not the right to
        !            17:  * distribute the complete modified source code.  Modifications are to
        !            18:  * be distributed as patches to the released version.  Permission to
        !            19:  * distribute binaries produced by compiling modified sources is granted,
        !            20:  * provided you
        !            21:  *   1. distribute the corresponding source modifications from the
        !            22:  *    released version in the form of a patch file along with the binaries,
        !            23:  *   2. add special version identification to distinguish your version
        !            24:  *    in addition to the base release version number,
        !            25:  *   3. provide your name and address as the primary contact for the
        !            26:  *    support of your modified version, and
        !            27:  *   4. retain our contact information in regard to use of the base
        !            28:  *    software.
        !            29:  * Permission to distribute the released version of the source code along
        !            30:  * with corresponding source modifications in the form of a patch file is
        !            31:  * granted with same provisions 2 through 4 for binary distributions.
        !            32:  *
        !            33:  * This software is provided "as is" without express or implied warranty
        !            34:  * to the extent permitted by applicable law.
        !            35: ]*/
        !            36:
        !            37: #include "plot.h"
        !            38:
        !            39: static int get_num __PROTO((char str[]));
        !            40: static void substitute __PROTO((char *str, int max));
        !            41:
        !            42: #ifdef AMIGA_AC_5
        !            43: #define O_RDONLY       0
        !            44: int open(const char *_name, int _mode,...);
        !            45: int close(int);
        !            46: #endif /* AMIGA_AC_5 */
        !            47:
        !            48: #ifdef VMS
        !            49: #include <descrip.h>
        !            50: #define MAILBOX "PLOT$MAILBOX"
        !            51: #define pclose(f) fclose(f)
        !            52: #ifdef __DECC
        !            53: #include <lib$routines.h>      /* avoid some IMPLICITFNC warnings */
        !            54: #include <starlet.h>
        !            55: #endif /* __DECC */
        !            56: #endif /* VMS */
        !            57:
        !            58:
        !            59: #define isident(c) (isalnum(c) || (c) == '_')
        !            60:
        !            61: #ifndef STDOUT
        !            62: #define STDOUT 1
        !            63: #endif
        !            64:
        !            65: #define LBRACE '{'
        !            66: #define RBRACE '}'
        !            67:
        !            68: #define APPEND_TOKEN {token[t_num].length++; current++;}
        !            69:
        !            70: #define SCAN_IDENTIFIER while (isident((int)expression[current + 1]))\
        !            71:                                APPEND_TOKEN
        !            72:
        !            73: static int t_num;              /* number of token I'm working on */
        !            74:
        !            75: /*
        !            76:  * scanner() breaks expression[] into lexical units, storing them in token[].
        !            77:  *   The total number of tokens found is returned as the function value.
        !            78:  *   Scanning will stop when '\0' is found in expression[], or when token[]
        !            79:  *     is full.
        !            80:  *
        !            81:  *       Scanning is performed by following rules:
        !            82:  *
        !            83:  *      Current char    token should contain
        !            84:  *     -------------    -----------------------
        !            85:  *      1.  alpha,_     all following alpha-numerics
        !            86:  *      2.  digit       0 or more following digits, 0 or 1 decimal point,
        !            87:  *                              0 or more digits, 0 or 1 'e' or 'E',
        !            88:  *                              0 or more digits.
        !            89:  *      3.  ^,+,-,/     only current char
        !            90:  *          %,~,(,)
        !            91:  *          [,],;,:,
        !            92:  *          ?,comma
        !            93:  *          $           for using patch (div)
        !            94:  *      4.  &,|,=,*     current char; also next if next is same
        !            95:  *      5.  !,<,>       current char; also next if next is =
        !            96:  *      6.  ", '        all chars up until matching quote
        !            97:  *      7.  #           this token cuts off scanning of the line (DFK).
        !            98:  *
        !            99:  *                      white space between tokens is ignored
        !           100:  */
        !           101: int scanner(expression)
        !           102: char expression[];
        !           103: {
        !           104:     register int current;      /* index of current char in expression[] */
        !           105:     register int quote;
        !           106:     char brace;
        !           107:
        !           108:     for (current = t_num = 0; expression[current] != NUL; current++) {
        !           109:       again:
        !           110:        if (t_num + 1 >= token_table_size) {
        !           111:            /* leave space for dummy end token */
        !           112:            extend_token_table();
        !           113:        }
        !           114:        if (isspace((int) expression[current]))
        !           115:            continue;           /* skip the whitespace */
        !           116:        token[t_num].start_index = current;
        !           117:        token[t_num].length = 1;
        !           118:        token[t_num].is_token = TRUE;   /* to start with... */
        !           119:
        !           120:        if (expression[current] == '`') {
        !           121:            substitute(&expression[current], MAX_LINE_LEN - current);
        !           122:            goto again;
        !           123:        }
        !           124:        /* allow _ to be the first character of an identifier */
        !           125:        if (isalpha((int) expression[current]) || expression[current] == '_') {
        !           126:            SCAN_IDENTIFIER;
        !           127:        } else if (isdigit((int) expression[current]) || expression[current] == '.') {
        !           128:            token[t_num].is_token = FALSE;
        !           129:            token[t_num].length = get_num(&expression[current]);
        !           130:            current += (token[t_num].length - 1);
        !           131:        } else if (expression[current] == LBRACE) {
        !           132:            token[t_num].is_token = FALSE;
        !           133:            token[t_num].l_val.type = CMPLX;
        !           134: #ifdef __PUREC__
        !           135:            {
        !           136:                char l[80];
        !           137:                if ((sscanf(&expression[++current], "%lf,%lf%[ }]s",
        !           138:                            &token[t_num].l_val.v.cmplx_val.real,
        !           139:                            &token[t_num].l_val.v.cmplx_val.imag,
        !           140:                            &l) != 3) || (!strchr(l, RBRACE)))
        !           141:                    int_error("invalid complex constant", t_num);
        !           142:            }
        !           143: #else
        !           144:            if ((sscanf(&expression[++current], "%lf , %lf %c",
        !           145:                        &token[t_num].l_val.v.cmplx_val.real,
        !           146:                        &token[t_num].l_val.v.cmplx_val.imag,
        !           147:                        &brace) != 3) || (brace != RBRACE))
        !           148:                int_error("invalid complex constant", t_num);
        !           149: #endif
        !           150:            token[t_num].length += 2;
        !           151:            while (expression[++current] != RBRACE) {
        !           152:                token[t_num].length++;
        !           153:                if (expression[current] == NUL) /* { for vi % */
        !           154:                    int_error("no matching '}'", t_num);
        !           155:            }
        !           156:        } else if (expression[current] == '\'' || expression[current] == '\"') {
        !           157:            token[t_num].length++;
        !           158:            quote = expression[current];
        !           159:            while (expression[++current] != quote) {
        !           160:                if (!expression[current]) {
        !           161:                    expression[current] = quote;
        !           162:                    expression[current + 1] = NUL;
        !           163:                    break;
        !           164:                } else if (expression[current] == '\\'
        !           165:                           && expression[current + 1]) {
        !           166:                    current++;
        !           167:                    token[t_num].length += 2;
        !           168:                } else
        !           169:                    token[t_num].length++;
        !           170:            }
        !           171:        } else
        !           172:            switch (expression[current]) {
        !           173:            case '#':           /* DFK: add comments to gnuplot */
        !           174:                goto endline;   /* ignore the rest of the line */
        !           175:            case '^':
        !           176:            case '+':
        !           177:            case '-':
        !           178:            case '/':
        !           179:            case '%':
        !           180:            case '~':
        !           181:            case '(':
        !           182:            case ')':
        !           183:            case '[':
        !           184:            case ']':
        !           185:            case ';':
        !           186:            case ':':
        !           187:            case '?':
        !           188:            case ',':
        !           189:            case '$':           /* div */
        !           190:                break;
        !           191:            case '&':
        !           192:            case '|':
        !           193:            case '=':
        !           194:            case '*':
        !           195:                if (expression[current] == expression[current + 1])
        !           196:                    APPEND_TOKEN;
        !           197:                break;
        !           198:            case '!':
        !           199:            case '<':
        !           200:            case '>':
        !           201:                if (expression[current + 1] == '=')
        !           202:                    APPEND_TOKEN;
        !           203:                break;
        !           204:            default:
        !           205:                int_error("invalid character", t_num);
        !           206:            }
        !           207:        ++t_num;                /* next token if not white space */
        !           208:     }
        !           209:
        !           210:   endline:                     /* comments jump here to ignore line */
        !           211:
        !           212: /* Now kludge an extra token which points to '\0' at end of expression[].
        !           213:    This is useful so printerror() looks nice even if we've fallen off the
        !           214:    line. */
        !           215:
        !           216:     token[t_num].start_index = current;
        !           217:     token[t_num].length = 0;
        !           218:     /* print 3+4  then print 3+  is accepted without
        !           219:      * this, since string is ignored if it is not
        !           220:      * a token
        !           221:      */
        !           222:     token[t_num].is_token = TRUE;
        !           223:     return (t_num);
        !           224: }
        !           225:
        !           226:
        !           227: static int get_num(str)
        !           228: char str[];
        !           229: {
        !           230:     register int count = 0;
        !           231:     register long lval;
        !           232:
        !           233:     token[t_num].is_token = FALSE;
        !           234:     token[t_num].l_val.type = INTGR;   /* assume unless . or E found */
        !           235:     while (isdigit((int) str[count]))
        !           236:        count++;
        !           237:     if (str[count] == '.') {
        !           238:        token[t_num].l_val.type = CMPLX;
        !           239:        /* swallow up digits until non-digit */
        !           240:        while (isdigit((int) str[++count]))
        !           241:            ;
        !           242:        /* now str[count] is other than a digit */
        !           243:     }
        !           244:     if (str[count] == 'e' || str[count] == 'E') {
        !           245:        token[t_num].l_val.type = CMPLX;
        !           246: /* modified if statement to allow + sign in exponent
        !           247:    rjl 26 July 1988 */
        !           248:        count++;
        !           249:        if (str[count] == '-' || str[count] == '+')
        !           250:            count++;
        !           251:        if (!isdigit((int) str[count])) {
        !           252:            token[t_num].start_index += count;
        !           253:            int_error("expecting exponent", t_num);
        !           254:        }
        !           255:        while (isdigit((int) str[++count]));
        !           256:     }
        !           257:     if (token[t_num].l_val.type == INTGR) {
        !           258:        lval = atol(str);
        !           259:        if ((token[t_num].l_val.v.int_val = lval) != lval)
        !           260:            int_error("integer overflow; change to floating point", t_num);
        !           261:     } else {
        !           262:        token[t_num].l_val.v.cmplx_val.imag = 0.0;
        !           263:        token[t_num].l_val.v.cmplx_val.real = atof(str);
        !           264:     }
        !           265:     return (count);
        !           266: }
        !           267:
        !           268: #if defined(VMS) || defined(PIPES) || (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
        !           269:
        !           270: /* this really ought to make use of the dynamic-growth of the
        !           271:  * input line in 3.6.  And it definitely should not have
        !           272:  * static arrays !
        !           273:  */
        !           274: /* A macro to reduce clutter ... */
        !           275: # ifdef AMIGA_AC_5
        !           276: #  define CLOSE_FILE_OR_PIPE ((void) close(fd))
        !           277: # elif (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
        !           278: #  define CLOSE_FILE_OR_PIPE ((void) fclose(f); (void) unlink(atari_tmpfile))
        !           279: # else /* Rest of the world */
        !           280: #  define CLOSE_FILE_OR_PIPE ((void) pclose(f))
        !           281: # endif
        !           282:
        !           283: static void substitute(str, max)       /* substitute output from ` ` */
        !           284: char *str;
        !           285: int max;
        !           286: {
        !           287:     register char *last;
        !           288:     register int i, c;
        !           289:     register FILE *f;
        !           290: # ifdef AMIGA_AC_5
        !           291:     int fd;
        !           292: # elif (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
        !           293:     char *atari_tmpfile;
        !           294:     char *atari_pgm[MAX_LINE_LEN+100];
        !           295: # endif /* !AMIGA_AC_5 */
        !           296:     static char pgm[MAX_LINE_LEN+1], output[MAX_LINE_LEN+1];
        !           297:
        !           298: # ifdef VMS
        !           299:     int chan, one = 1;
        !           300:     static $DESCRIPTOR(pgmdsc, pgm);
        !           301:     static $DESCRIPTOR(lognamedsc, MAILBOX);
        !           302: # endif /* VMS */
        !           303:
        !           304:     /* forgive missing closing backquote at end of line */
        !           305:     i = 0;
        !           306:     last = str;
        !           307:     while (*++last) {
        !           308:        if (*last == '`') {
        !           309:            ++last;             /* move past it */
        !           310:            break;
        !           311:        }
        !           312:        pgm[i++] = *last;
        !           313:     }
        !           314:     pgm[i] = NUL;              /* end with null */
        !           315:     max -= strlen(last);       /* max is now the max length of output sub. */
        !           316:
        !           317: # ifdef VMS
        !           318:     pgmdsc.dsc$w_length = i;
        !           319:     if (!((vaxc$errno = sys$crembx(0, &chan, 0, 0, 0, 0, &lognamedsc)) & 1))
        !           320:        os_error("sys$crembx failed", NO_CARET);
        !           321:
        !           322:     if (!((vaxc$errno = lib$spawn(&pgmdsc, 0, &lognamedsc, &one)) & 1))
        !           323:        os_error("lib$spawn failed", NO_CARET);
        !           324:
        !           325:     if ((f = fopen(MAILBOX, "r")) == NULL)
        !           326:        os_error("mailbox open failed", NO_CARET);
        !           327: # elif (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
        !           328:     if (system(NULL) == 0)
        !           329:        os_error("no command shell", NO_CARET);
        !           330:     if ((strlen(atari_tmpfile) + strlen(pgm) + 5) > MAX_LINE_LEN + 100)
        !           331:        os_error("sorry, command to long", NO_CARET);
        !           332:     atari_tmpfile = tmpnam(NULL);
        !           333:     strcpy(atari_pgm, pgm);
        !           334:     strcat(atari_pgm, " >> ");
        !           335:     strcat(atari_pgm, atari_tmpfile);
        !           336:     system(atari_pgm);
        !           337:     if ((f = fopen(atari_tmpfile, "r")) == NULL)
        !           338: # elif defined(AMIGA_AC_5)
        !           339:     if ((fd = open(pgm, "O_RDONLY")) == -1)
        !           340: # else /* everyone else */
        !           341:     if ((f = popen(pgm, "r")) == NULL)
        !           342:        os_error("popen failed", NO_CARET);
        !           343: # endif /* !VMS */
        !           344:
        !           345:     i = 0;
        !           346:     while ((c = getc(f)) != EOF) {
        !           347:        output[i++] = ((c == '\n') ? ' ' : c);  /* newlines become blanks */
        !           348:        if (i == max) {
        !           349:            CLOSE_FILE_OR_PIPE;
        !           350:            int_error("substitution overflow", t_num);
        !           351:        }
        !           352:     }
        !           353:
        !           354:     CLOSE_FILE_OR_PIPE;
        !           355:
        !           356:     if (i + strlen(last) > max)
        !           357:        int_error("substitution overflowed rest of line", t_num);
        !           358:     /* tack on rest of line to output */
        !           359:     safe_strncpy(output + i, last, MAX_LINE_LEN - i);
        !           360:     /* now replace ` ` with output */
        !           361:     safe_strncpy(str, output, max);
        !           362:     screen_ok = FALSE;
        !           363: }
        !           364:
        !           365: #else /* VMS || PIPES || ATARI && PUREC */
        !           366:
        !           367: static void substitute(str, max)
        !           368: char *str;
        !           369: int max;
        !           370: {
        !           371:     char line[100];
        !           372:
        !           373:     sprintf(line, "substitution not supported by %s", OS);
        !           374:     int_error(line, t_num);
        !           375: }
        !           376:
        !           377: #endif /* unix || VMS || PIPES || ATARI && PUREC */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>