int yylex() { char *p = line + linelim; int ret=0; static int isfunc = 0; static bool isgoto = 0; static bool colstate = 0; static int dateflag; static char *tokenst = NULL; static int tokenl; while (isspace(*p)) p++; if (*p == '\0') { isfunc = isgoto = 0; ret = -1; } else if (isalpha(*p) || (*p == '_')) { register char *la; /* lookahead pointer */ register struct key *tblp; if (!tokenst) { tokenst = p; tokenl = 0; } /* * This picks up either 1 or 2 alpha characters (a column) or * tokens made up of alphanumeric chars and '_' (a function or * token or command or a range name) */ while (isalpha(*p) && isascii(*p)) { p++; tokenl++; } la = p; while (isdigit(*la) || (*la == '$')) la++; /* * A COL is 1 or 2 char alpha with nothing but digits following * (no alpha or '_') */ if (!isdigit(*tokenst) && tokenl && tokenl <= 2 && (colstate || (isdigit(*(la-1)) && !(isalpha(*la) || (*la == '_'))))) { ret = COL; yylval.ival = atocol(tokenst, tokenl); } else { while (isalpha(*p) || (*p == '_') || isdigit(*p)) { p++; tokenl++; } ret = WORD; if (!linelim || isfunc) { if (isfunc) isfunc--; for (tblp = linelim ? experres : statres; tblp->key; tblp++) if (((tblp->key[0]^tokenst[0])&0137)==0 && tblp->key[tokenl]==0) { int i = 1; while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0) i++; if (i >= tokenl) { ret = tblp->val; colstate = (ret <= S_FORMAT); if (isgoto) { isfunc = isgoto = 0; if (ret != K_ERROR && ret != K_INVALID) ret = WORD; } break; } } } if (ret == WORD) { struct range *r; char *path; if (!find_range(tokenst, tokenl, (struct ent *)0, (struct ent *)0, &r)) { yylval.rval.left = r->r_left; yylval.rval.right = r->r_right; if (r->r_is_range) ret = RANGE; else ret = VAR; } else if ((path = scxmalloc((unsigned)PATHLEN)) && plugin_exists(tokenst, tokenl, path)) { strcat(path, p); yylval.sval = path; ret = PLUGIN; } else { scxfree(path); linelim = p-line; yyerror("Unintelligible word"); } } } } else if ((*p == '.') || isdigit(*p)) { #ifdef SIGVOID void (*sig_save)(); #else int (*sig_save)(); #endif double v = 0.0; int temp; char *nstart = p; sig_save = signal(SIGFPE, fpe_trap); if (setjmp(fpe_buf)) { (void) signal(SIGFPE, sig_save); yylval.fval = v; error("Floating point exception\n"); isfunc = isgoto = 0; tokenst = NULL; return FNUMBER; } if (*p=='.' && dateflag) { /* .'s in dates are returned as tokens. */ ret = *p++; dateflag--; } else { if (*p != '.') { tokenst = p; tokenl = 0; do { v = v*10.0 + (double) ((unsigned) *p - '0'); tokenl++; } while (isdigit(*++p)); if (dateflag) { ret = NUMBER; yylval.ival = (int)v; /* * If a string of digits is followed by two .'s separated by * one or two digits, assume this is a date and return the * .'s as tokens instead of interpreting them as decimal * points. dateflag counts the .'s as they're returned. */ } else if (*p=='.' && isdigit(*(p+1)) && (*(p+2)=='.' || (isdigit(*(p+2)) && *(p+3)=='.'))) { ret = NUMBER; yylval.ival = (int)v; dateflag = 2; } else if (*p == 'e' || *p == 'E') { while (isdigit(*++p)) /* */; if (isalpha(*p) || *p == '_') { linelim = p - line; return (yylex()); } else ret = FNUMBER; } else if (isalpha(*p) || *p == '_') { linelim = p - line; return (yylex()); } } if ((!dateflag && *p=='.') || ret == FNUMBER) { ret = FNUMBER; yylval.fval = strtod(nstart, &p); if (!finite(yylval.fval)) ret = K_ERR; else decimal = TRUE; } else { /* A NUMBER must hold at least MAXROW and MAXCOL */ /* This is consistent with a short row and col in struct ent */ if (v > (double)32767 || v < (double)-32768) { ret = FNUMBER; yylval.fval = v; } else { temp = (int)v; if((double)temp != v) { ret = FNUMBER; yylval.fval = v; } else { ret = NUMBER; yylval.ival = temp; } } } } (void) signal(SIGFPE, sig_save); } else if (*p=='"') { char *ptr; ptr = p+1; /* "string" or "string\"quoted\"" */ while (*ptr && ((*ptr != '"') || (*(ptr-1) == '\\'))) ptr++; ptr = scxmalloc((unsigned)(ptr-p)); yylval.sval = ptr; p++; while (*p && ((*p != '"') || (*(p-1) == '\\' && *(p+1) != '\0' && *(p+1) != '\n'))) *ptr++ = *p++; *ptr = '\0'; if (*p) p++; ret = STRING; } else if (*p=='[') { while (*p && *p!=']') p++; if (*p) p++; linelim = p-line; tokenst = NULL; return yylex(); } else ret = *p++; linelim = p-line; if (!isfunc) isfunc = ((ret == '@') + (ret == S_GOTO) - (ret == S_SET)); if (ret == S_GOTO) isgoto = TRUE; tokenst = NULL; return ret; }
static fill_stack_t* xyread_stream(FILE* stream, xycpt_opt_t opt) { char buf[BUFSIZE]; char *tok[NTOK]; int i; fill_stack_t* f; /* chose the string to colour function */ int (*atocol)(const char*) = (opt.unital ? unital : dchar); /* read first non-comment line */ do if (fgets(buf, BUFSIZE, stream) == NULL) { btrace("no first data line"); return NULL; } while (skipline(buf)); /* tokenise */ if ((tok[0] = strtok(buf, " \t\n")) == NULL) { btrace("no tokens"); return NULL; } for (i=1 ; i<NTOK ; i++) { if ((tok[i] = strtok(NULL, " \t")) == NULL) break; } if ((f = malloc(sizeof(fill_stack_t))) == NULL) return NULL; switch (i) { case 1: f->fill.type = fill_grey; f->val = 0; f->fill.u.grey = atocol(tok[0]); f->next = (opt.unital ? xyread1f(stream, buf, 1) : xyread1i(stream, buf, 1)); break; case 2: f->fill.type = fill_grey; f->val = atof(tok[0]); f->fill.u.grey = atocol(tok[1]); f->next = (opt.unital ? xyread2f(stream, buf) : xyread2i(stream, buf)); break; case 3: f->fill.type = fill_colour; f->val = 0; f->fill.u.colour.rgb.red = atocol(tok[0]); f->fill.u.colour.rgb.green = atocol(tok[1]); f->fill.u.colour.rgb.blue = atocol(tok[2]); f->next = (opt.unital ? xyread3f(stream, buf, 1) : xyread3i(stream, buf, 1)); break; case 4: f->fill.type = fill_colour; f->val = atof(tok[0]); f->fill.u.colour.rgb.red = atocol(tok[1]); f->fill.u.colour.rgb.green = atocol(tok[2]); f->fill.u.colour.rgb.blue = atocol(tok[3]); f->next = (opt.unital ? xyread4f(stream, buf) : xyread4i(stream, buf)); break; default: btrace("bad input: found %i tokens", i); free(f); return NULL; } return f; }