static ZZJSON *parse_value(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL; int c; SKIPWS(); c = GETC(); UNGETC(c); switch (c) { case '"': retval = parse_string2(config); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': retval = parse_number(config); break; case '{': retval = parse_object(config); break; case '[': retval = parse_array(config); break; case 't': retval = parse_true(config); break; case 'f': retval = parse_false(config); break; case 'n': retval = parse_null(config); break; } if (!retval) { ERROR("value: invalid value"); return retval; } return retval; }
/* * local function to read a cons node */ static LVAL readcons(tpLspObject pLSP,FILE *f) { int ch; spaceat(ch,f); if( ch == pLSP->cClose )return NIL; UNGETC(ch); return readlist(f); }
int peekc( FILE *file ) { int const c = getc( file ); if ( c == EOF ) { if ( ferror( file ) ) PERROR_EXIT( READ_ERROR ); } else { UNGETC( c, file ); } return c; }
/*FUNCTION*/ LVAL c_readexpr(tpLspObject pLSP, FILE *f ){ /*noverbatim CUT*/ int ch; spaceat(ch,f); if( ch == EOF )return NIL; UNGETC(ch); return _readexpr(pLSP,f); }
static int skip(char *s) { int n, c; n = 0; while((c=GETC()) >= 0 && strchr(s, c)) n++; if(c != Beof) UNGETC(c); return n; }
static int fail(int st) { int c; while((c=GETC()) >= 0 && c != '\n') ; if(c == '\n') UNGETC(c); setstate(st); return Terror; }
/* getherevar -- read a variable from a here doc */ extern Tree *getherevar(void) { int c; char *s; Buffer *buf = openbuffer(0); while (!dnw[c = GETC()]) buf = bufputc(buf, c); s = sealcountedbuffer(buf); if (buf->len == 0) { yyerror("null variable name in here document"); return NULL; } if (c != '^') UNGETC(c); return flatten(mk(nVar, mk(nWord, s)), " "); }
void push_back_char( int ch ) { if (input_from_file) UNGETC(ch, ip_file); else { if (ch == '\n') { ip_file->col_no = ip_file->prev_line_col_no; ip_file->prev_line_col_no = -1; --ip_file->line_no; } --ip_file->col_no; remote_config.pos--; } }
static Boolean getfds(int fd[2], int c, int default0, int default1) { int n; fd[0] = default0; fd[1] = default1; if (c != '[') { UNGETC(c); return TRUE; } if ((unsigned int) (n = GETC() - '0') > 9) { scanerror("expected digit after '['"); return FALSE; } while ((unsigned int) (c = GETC() - '0') <= 9) n = n * 10 + c; fd[0] = n; switch (c += '0') { case '=': if ((unsigned int) (n = GETC() - '0') > 9) { if (n != ']' - '0') { scanerror("expected digit or ']' after '='"); return FALSE; } fd[1] = CLOSED; } else { while ((unsigned int) (c = GETC() - '0') <= 9) n = n * 10 + c; if (c != ']' - '0') { scanerror("expected ']' after digit"); return FALSE; } fd[1] = n; } break; case ']': break; default: scanerror("expected '=' or ']' after digit"); return FALSE; } return TRUE; }
static int rreadstr(char *delim, char *s) /* if s != 0, skip this chars before reading */ { int c; s_reset(sbuf); if(s) skip(s); while((c=GETC()) >= 0){ if(strchr(delim, c)){ UNGETC(c); s_terminate(sbuf); return Tstring; } s_putc(sbuf, c); } if(c == Beof) yyerror("eof in string"); return Terror; }
/*FUNCTION*/ LVAL c_readlist(tpLspObject pLSP, FILE *f ){ /*noverbatim CUT*/ int ch; LVAL p,q; spaceat(ch,f); if( ch == pLSP->cClose || ch == EOF )return NIL; UNGETC(ch); q = cons(); if( null(q) ) { return NIL; } p = _readexpr(pLSP,f); setcar(q,p); setcdr(q,readlist(f)); return q; }
static void skipws(ZZJSON_CONFIG *config) { int d, c = GETC(); morews: while (isspace(c)) c = GETC(); if (!ALLOW_COMMENTS) goto endws; if (c != '/') goto endws; d = GETC(); if (d != '*') goto endws; /* pushing back c will generate a parse error */ c = GETC(); morecomments: while (c != '*') { if (c == EOF) goto endws; c = GETC(); } c = GETC(); if (c != '/') goto morecomments; c = GETC(); if (isspace(c) || c == '/') goto morews; endws: UNGETC(c); }
static int readname(char *s) { int c; s_reset(sbuf); if(s) skip(s); while((c=GETC()) >= 0 && (isalnum(c) || c == '-')) s_putc(sbuf, c); if(c == Beof){ yyerror("eof in id/class"); return Terror; } UNGETC(c); if(s_len(sbuf) == 0){ yyerror("empty name"); return Terror; } s_terminate(sbuf); return Tstring; }
ZZJSON *zzjson_parse(ZZJSON_CONFIG *config) { ZZJSON *retval; int c; SKIPWS(); c = GETC(); UNGETC(c); if (c == '[') retval = parse_array(config); else if (c == '{') retval = parse_object(config); else { ERROR("expected '[' or '{'"); return NULL; } if (!retval) return NULL; SKIPWS(); c = GETC(); if (c >= 0 && !ALLOW_GARBAGE_AT_END) { ERROR("parse: garbage at end of file"); zzjson_free(config, retval); return NULL; } return retval; }
static int getcc(char *c, char *s) /* returning inline cmd or 0, c as a text */ { int c1, c2; c1 = GETC(); if(c1 == Beof || c1 == '\n') return c1; if(strchr(s, c1) == nil){ *c = c1; return 0; } c2 = GETC(); if(c2 == c1){ *c = c1; return 0; } UNGETC(c2); return c1; }
static char *parse_string(ZZJSON_CONFIG *config) { unsigned int len = 16, pos = 0; int c; char *str = NULL; SKIPWS(); c = GETC(); if (c != '"') { ERROR("string: expected \" at the start"); return NULL; } str = config->malloc(len); if (!str) { MEMERROR(); return NULL; } c = GETC(); while (c > 0 && c != '"') { if (!ALLOW_CONTROL_CHARS && c >= 0 && c <= 31) { ERROR("string: control characters not allowed"); goto errout; } if (c == '\\') { c = GETC(); switch (c) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'u': { UNGETC(c); /* ignore \uHHHH, copy verbatim */ c = '\\'; break; } case '\\': case '/': case '"': break; default: if (!ALLOW_ILLEGAL_ESCAPE) { ERROR("string: illegal escape character"); goto errout; } } } str[pos++] = c; if (pos == len-1) { void *tmp = str; len *= 2; str = config->realloc(str, len); if (!str) { MEMERROR(); str = tmp; goto errout; } } c = GETC(); } if (c != '"') { ERROR("string: expected \" at the end"); goto errout; } str[pos] = 0; return str; errout: config->free(str); return NULL; }
static ZZJSON *parse_number(ZZJSON_CONFIG *config) { ZZJSON *zzjson; unsigned long long ival = 0, expo = 0; double dval = 0.0, frac = 0.0, fracshft = 10.0; int c, dbl = 0, sign = 1, signexpo = 1; SKIPWS(); c = GETC(); if (c == '-') { sign = -1; c = GETC(); } if (c == '0') { c = GETC(); goto skip; } if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { ival *= 10; ival += c - '0'; c = GETC(); } skip: if (c != '.') goto skipfrac; dbl = 1; c = GETC(); if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { frac += (double)(c - '0') / fracshft; fracshft *= 10.0; c = GETC(); } skipfrac: if (c != 'e' && c != 'E') goto skipexpo; dbl = 1; c = GETC(); if (c == '+') c = GETC(); else if (c == '-') { signexpo = -1; c = GETC(); } if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { expo *= 10; expo += c - '0'; c = GETC(); } skipexpo: UNGETC(c); if (dbl) { dval = sign * (long long) ival; dval += sign * frac; dval *= pow(10.0, (double) signexpo * expo); } zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); return NULL; } if (dbl) { zzjson->type = ZZJSON_NUMBER_DOUBLE; zzjson->value.number.val.dval = dval; } else { zzjson->type = sign < 0 ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT; zzjson->value.number.val.ival = ival; } return zzjson; }
extern int yylex(void) { static Boolean dollar = FALSE; int c; size_t i; /* The purpose of all these local assignments is to */ const char *meta; /* allow optimizing compilers like gcc to load these */ char *buf = tokenbuf; /* values into registers. On a sparc this is a */ YYSTYPE *y = &yylval; /* win, in code size *and* execution time */ if (goterror) { goterror = FALSE; return NL; } /* rc variable-names may contain only alnum, '*' and '_', so use dnw if we are scanning one. */ meta = (dollar ? dnw : nw); dollar = FALSE; if (newline) { --input->lineno; /* slight space optimization; print_prompt2() always increments lineno */ print_prompt2(); newline = FALSE; } top: while ((c = GETC()) == ' ' || c == '\t') w = NW; if (c == EOF) return ENDFILE; if (!meta[(unsigned char) c]) { /* it's a word or keyword. */ InsertFreeCaret(); w = RW; i = 0; do { buf[i++] = c; if (i >= bufsize) buf = tokenbuf = erealloc(buf, bufsize *= 2); } while ((c = GETC()) != EOF && !meta[(unsigned char) c]); UNGETC(c); buf[i] = '\0'; w = KW; if (buf[1] == '\0') { int k = *buf; if (k == '@' || k == '~') return k; } else if (*buf == 'f') { if (streq(buf + 1, "n")) return FN; if (streq(buf + 1, "or")) return FOR; } else if (*buf == 'l') { if (streq(buf + 1, "ocal")) return LOCAL; if (streq(buf + 1, "et")) return LET; } else if (streq(buf, "~~")) return EXTRACT; else if (streq(buf, "%closure")) return CLOSURE; w = RW; y->str = gcdup(buf); return WORD; } if (c == '`' || c == '!' || c == '$' || c == '\'') { InsertFreeCaret(); if (c == '!') w = KW; } switch (c) { case '!': return '!'; case '`': c = GETC(); if (c == '`') return BACKBACK; UNGETC(c); return '`'; case '$': dollar = TRUE; switch (c = GETC()) { case '#': return COUNT; case '^': return FLAT; case '&': return PRIM; default: UNGETC(c); return '$'; } case '\'': w = RW; i = 0; while ((c = GETC()) != '\'' || (c = GETC()) == '\'') { buf[i++] = c; if (c == '\n') print_prompt2(); if (c == EOF) { w = NW; scanerror("eof in quoted string"); return ERROR; } if (i >= bufsize) buf = tokenbuf = erealloc(buf, bufsize *= 2); } UNGETC(c); buf[i] = '\0'; y->str = gcdup(buf); return QWORD; case '\\': if ((c = GETC()) == '\n') { print_prompt2(); UNGETC(' '); goto top; /* Pretend it was just another space. */ } if (c == EOF) { UNGETC(EOF); goto badescape; } UNGETC(c); c = '\\'; InsertFreeCaret(); w = RW; c = GETC(); switch (c) { case 'a': *buf = '\a'; break; case 'b': *buf = '\b'; break; case 'e': *buf = '\033'; break; case 'f': *buf = '\f'; break; case 'n': *buf = '\n'; break; case 'r': *buf = '\r'; break; case 't': *buf = '\t'; break; case 'x': case 'X': { int n = 0; for (;;) { c = GETC(); if (!isxdigit(c)) break; n = (n << 4) | (c - (isdigit(c) ? '0' : ((islower(c) ? 'a' : 'A') - 0xA))); } if (n == 0) goto badescape; UNGETC(c); *buf = n; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int n = 0; do { n = (n << 3) | (c - '0'); c = GETC(); } while (isodigit(c)); if (n == 0) goto badescape; UNGETC(c); *buf = n; break; } default: if (isalnum(c)) { badescape: scanerror("bad backslash escape"); return ERROR; } *buf = c; break; } buf[1] = 0; y->str = gcdup(buf); return QWORD; case '#': while ((c = GETC()) != '\n') /* skip comment until newline */ if (c == EOF) return ENDFILE; /* FALLTHROUGH */ case '\n': input->lineno++; newline = TRUE; w = NW; return NL; case '(': if (w == RW) /* not keywords, so let & friends work */ c = SUB; /* FALLTHROUGH */ case ';': case '^': case ')': case '=': case '{': case '}': w = NW; return c; case '&': w = NW; c = GETC(); if (c == '&') return ANDAND; UNGETC(c); return '&'; case '|': { int p[2]; w = NW; c = GETC(); if (c == '|') return OROR; if (!getfds(p, c, 1, 0)) return ERROR; if (p[1] == CLOSED) { scanerror("expected digit after '='"); /* can't close a pipe */ return ERROR; } y->tree = mk(nPipe, p[0], p[1]); return PIPE; } { char *cmd; int fd[2]; case '<': fd[0] = 0; if ((c = GETC()) == '>') if ((c = GETC()) == '>') { c = GETC(); cmd = "%open-append"; } else cmd = "%open-write"; else if (c == '<') if ((c = GETC()) == '<') { c = GETC(); cmd = "%here"; } else cmd = "%heredoc"; else if (c == '=') return CALL; else cmd = "%open"; goto redirection; case '>': fd[0] = 1; if ((c = GETC()) == '>') if ((c = GETC()) == '<') { c = GETC(); cmd = "%open-append"; } else cmd = "%append"; else if (c == '<') { c = GETC(); cmd = "%open-create"; } else cmd = "%create"; goto redirection; redirection: w = NW; if (!getfds(fd, c, fd[0], DEFAULT)) return ERROR; if (fd[1] != DEFAULT) { y->tree = (fd[1] == CLOSED) ? mkclose(fd[0]) : mkdup(fd[0], fd[1]); return DUP; } y->tree = mkredircmd(cmd, fd[0]); return REDIR; } default: assert(c != '\0'); w = NW; return c; /* don't know what it is, let yacc barf on it */ } }
static ZZJSON *parse_array(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL, **next = &retval; int c; SKIPWS(); c = GETC(); if (c != '[') { ERROR("array: expected '['"); return NULL; } SKIPWS(); c = GETC(); while (c > 0 && c != ']') { ZZJSON *zzjson = NULL, *val = NULL; UNGETC(c); SKIPWS(); val = parse_value(config); if (!val) { ERROR("array: value expected"); goto errout; } SKIPWS(); c = GETC(); if (c != ',' && c != ']') { ERROR("array: expected ',' or ']'"); errout_with_val: zzjson_free(config, val); goto errout; } if (c == ',') { SKIPWS(); c = GETC(); if (c == ']' && !ALLOW_EXTRA_COMMA) { ERROR("array: expected value after ','"); goto errout_with_val; } } UNGETC(c); zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); zzjson_free(config, val); goto errout_with_val; } zzjson->type = ZZJSON_ARRAY; zzjson->value.array.val = val; *next = zzjson; next = &zzjson->next; c = GETC(); } if (c != ']') { ERROR("array: expected ']'"); goto errout; } if (!retval) { /* empty array, [ ] */ retval = config->calloc(1, sizeof(ZZJSON)); if (!retval) { MEMERROR(); return NULL; } retval->type = ZZJSON_ARRAY; } return retval; errout: zzjson_free(config, retval); return NULL; }
static ZZJSON *parse_object(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL; int c; ZZJSON **next = &retval; SKIPWS(); c = GETC(); if (c != '{') { ERROR("object: expected '{'"); return NULL; } SKIPWS(); c = GETC(); while (c > 0 && c != '}') { ZZJSON *zzjson = NULL, *val = NULL; char *str; UNGETC(c); str = parse_string(config); if (!str) { ERROR("object: expected string"); errout_with_str: config->free(str); goto errout; } SKIPWS(); c = GETC(); if (c != ':') { ERROR("object: expected ':'"); goto errout_with_str; } SKIPWS(); val = parse_value(config); if (!val) { ERROR("object: value expected"); goto errout_with_str; } SKIPWS(); c = GETC(); if (c != ',' && c != '}') { ERROR("object: expected ',' or '}'"); errout_with_str_and_val: zzjson_free(config, val); goto errout_with_str; } if (c == ',') { SKIPWS(); c = GETC(); if (c == '}' && !ALLOW_EXTRA_COMMA) { ERROR("object: expected pair after ','"); goto errout_with_str_and_val; } } UNGETC(c); zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); goto errout_with_str_and_val; } zzjson->type = ZZJSON_OBJECT; zzjson->value.object.label = str; zzjson->value.object.val = val; *next = zzjson; next = &zzjson->next; c = GETC(); } if (c != '}') { ERROR("object: expected '}'"); goto errout; } if (!retval) { /* empty object, { } */ retval = config->calloc(1, sizeof(ZZJSON)); if (!retval) { MEMERROR(); return NULL; } retval->type = ZZJSON_OBJECT; } return retval; errout: zzjson_free(config, retval); return NULL; }
/* * local function to read an expression */ static LVAL _readexpr(tpLspObject pLSP,FILE *f) { int ch,ch1,ch2,i; LVAL p; char *s; double dval; long lval; spaceat(ch,f); if( ch == EOF ) { return NIL; } if( ch == pLSP->cClose ) { return NIL; } if( ch == pLSP->cOpen )/* Read a cons node. */ return readcons(pLSP,f); /**** Note: XLISP allows 1E++10 as a symbol. This is dangerous. We do not change XLISP (so far), but here I exclude all symbol names starting with numeral. */ if( const_p1(ch) )/* Read a symbol. */ { for( i = 0 ; const_p(ch) ; i++ ){ if( storech(pLSP,i,ch) )return NIL; ch = getC(pLSP,f); } UNGETC(ch); /* Recognize NIL and nil symbols. */ if( !strcmp(BUFFER,"NIL") || !strcmp(BUFFER,"nil") ) return NIL; p = newsymbol(); s = StrDup( BUFFER ); if( null(p) || s == NULL )return NIL; setsymbol(p,s); return p; } if( ch == '\"' ){ ch = GETC(f); storech(pLSP,0,0); /* inititalize the buffer */ if( ch != '\"' )goto SimpleString; ch = GETC(f); if( ch != '\"' ){ UNGETC(ch); ch = '\"';/* ch should hold the first character of the string that is " now */ goto SimpleString; } ch = GETC(f); /* multi line string */ for( i = 0 ; ch != EOF ; i++ ){ if( ch == '\"' ){ ch1 = GETC(f); ch2 = GETC(f); if( ch1 == '\"' && ch2 == '\"' )break; UNGETC(ch2); UNGETC(ch1); } if( ch == '\\' ){ ch = GETC(f); s = escapers; while( *s ){ if( *s++ == ch ){ ch = *s; break; } if( *s )s++; } } if( storech(pLSP,i,ch) )return NIL; ch = GETC(f); } p = newstring(); s = StrDup( BUFFER ); if( null(p) || s == NULL )return NIL; setstring(p,s); return p; } if( ch == '\"' ){/* Read a string. */ ch = GETC(f);/* Eat the " character. */ SimpleString: for( i = 0 ; ch != '\"' && ch != EOF ; i++ ){ if( ch == '\\' ){ ch = GETC(f); s = escapers; while( *s ){ if( *s++ == ch ){ ch = *s; break; } if( *s )s++; } } if( ch == '\n' )return NIL; if( storech(pLSP,i,ch) )return NIL; ch = GETC(f); } p = newstring(); s = StrDup( BUFFER ); if( null(p) || s == NULL ) { return NIL; } setstring(p,s); return p; } if( numeral1(ch) ) { for( i = 0 ; isinset(ch,"0123456789+-eE.") ; i++ ) { if( storech(pLSP,i,ch) )return NIL; ch = getC(pLSP,f); } UNGETC(ch); cnumeric(BUFFER,&i,&dval,&lval); switch( i ) { case 0: return NIL; case 1: /* A float number is coming. */ p = newfloat(); if( null(p) ) { return NIL; } setfloat(p,dval); return p; case 2: /* An integer is coming. */ p = newint(); if( null(p) ) { return NIL; } setint(p,lval); return p; default: return NIL; } } return NIL; }
int yylex(void) { int c, r; char c1; Sym *s; genblock: if(block != nblock){ if(block > nblock){ if(debug) fprint(2, "%s %d -> %d\n", ty(Tend), block, nblock); block--; return Tend; }else{ if(debug) fprint(2, "%s %d -> %d\n", ty(Tbegin), block, nblock); block++; return Tbegin; } } c = GETC(); if(c == Beof){ nblock = 0; if(block != nblock) goto genblock; return 0; } UNGETC(c); switch(state){ case Head0: /* [%type] string */ c = GETC(); if(c != '%'){ UNGETC(c); setstate(Body0); goto genblock; } r = readname(" \t"); if(r == Terror) return fail(Head2); s = lookup(s_to_c(sbuf)); yylval.sym = s; if(debug) fprint(2, "Sym[%s] %s\n", ty(s->type), s->name); setstate(Head1); return s->type; case Head1: /* %type [string] */ r = readstr("\n", " \t", 0); if(r == Terror) return fail(Head2); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); setstate(Head2); return Tstring; case Head2: skip(" \t"); c = GETC(); assert(c == '\n' || c == Beof); setstate(Head0); return ';'; case Body0: /* [indent] cmd inline */ c = GETC(); if(c == '%'){ UNGETC(c); setstate(Head0); goto genblock; } UNGETC(c); r = skip(" \t"); c = GETC(); if(c == '\n'){ if(debug) fprint(2, "%s\n", ty(Tbreak)); return Tbreak; } UNGETC(c); nblock = r; setstate(Body1); goto genblock; case Body1: /* indent [cmd] inline */ switch(c = GETC()){ case Beof: yyerror("eof in body"); if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); case '=': case '\\': case '+': case '*': case ':': case '-': case '>': if(debug) fprint(2, "%c\n", c); setstate(Body2); return c; case '!': if(debug) fprint(2, "%c\n", c); setstate(Code); return c; case '{': case '}': if(debug) fprint(2, "%c\n", c); setstate(Body3); return c; case '#': if(debug) fprint(2, "%c\n", c); setstate(ID); return c; case '.': if(debug) fprint(2, "%c\n", c); setstate(Class); return c; case '|': if(debug) fprint(2, "%c\n", c); setstate(Table); return c; default: UNGETC(c); if(debug) fprint(2, "\\\n"); setstate(Body2); return '\\'; } case Body2: /* indent cmd [inline] */ case Table: r = skip(" \t"); if(state == Table && r > 0) return ','; switch(c = getcc(&c1, "*[]|<>")){ case Beof: yyerror("eof in body"); if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); case '\n': UNGETC(c); setstate(Body3); break; case '*': case '[': case ']': case '|': case '<': case '>': if(c == '[' || c == '|' || c == '<') skip(" \t\n"); if(debug) fprint(2, "%c\n", c); return c; default: s_reset(sbuf); s_putc(sbuf, c1); while((c=getcc(&c1, "*[]|<>")) == 0){ if(state == Table && c1 == '\t'){ UNGETC(c); break; } s_putc(sbuf, c1); } s_terminate(sbuf); if(c > 0) UNGETC(c); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; } case Body3: skip(" \t"); c = GETC(); if(c != '\n') return fail(Body3); setstate(Body0); return ';'; case Code: r = readstr("\n", "", 1); if(r == Terror){ if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); } setstate(Body3); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; case ID: case Class: r = readname(" \t"); if(r == Terror){ if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); } setstate(Body3); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; default: assert(0); return Terror; } }
/* snarfheredoc -- read a heredoc until the eof marker */ extern Tree *snarfheredoc(const char *eof, Boolean quoted) { Tree *tree, **tailp; Buffer *buf; unsigned char *s; assert(quoted || strchr(eof, '$') == NULL); /* can never be typed (whew!) */ if (strchr(eof, '\n') != NULL) { yyerror("here document eof-marker contains a newline"); return NULL; } disablehistory = TRUE; for (tree = NULL, tailp = &tree, buf = openbuffer(0);;) { int c; print_prompt2(); for (s = (unsigned char *) eof; (c = GETC()) == *s; s++) ; if (*s == '\0' && (c == '\n' || c == EOF)) { if (buf->current == 0 && tree != NULL) freebuffer(buf); else *tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL); break; } if (s != (unsigned char *) eof) buf = bufncat(buf, eof, s - (unsigned char *) eof); for (;; c = GETC()) { if (c == EOF) { yyerror("incomplete here document"); freebuffer(buf); disablehistory = FALSE; return NULL; } if (c == '$' && !quoted && (c = GETC()) != '$') { Tree *var; UNGETC(c); if (buf->current == 0) freebuffer(buf); else { *tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL); tailp = &(*tailp)->CDR; } var = getherevar(); if (var == NULL) { freebuffer(buf); disablehistory = FALSE; return NULL; } *tailp = treecons(var, NULL); tailp = &(*tailp)->CDR; buf = openbuffer(0); continue; } buf = bufputc(buf, c); if (c == '\n') break; } } disablehistory = FALSE; return tree->CDR == NULL ? tree->CAR : tree; }
static int yylex2(void) { int ch; int chkcomment = FALSE; yuk_a_goto: eatwhite(); if ((ch = GETC(fname)) == EOF) { if (firstsemi == 1) { firstsemi = 0; fclose(fname); fname = fnamesave; goto yuk_a_goto; } else { return(TENDOFFILE); } } do { if (ch == '/') if ((ch = GETC(fname)) == '*') { eatcomment(); eatwhite(); chkcomment = TRUE; if ((ch = GETC(fname)) == EOF) return(TENDOFFILE); } else { UNGETC(ch, fname); ch = '/'; chkcomment = FALSE; } else if (ch == '-') /* -- is a comment in our language */ { if ((ch = GETC(fname)) == '-') { eatline(); /* ignore rest of line */ if (firstsemi != 1) yylineno++; eatwhite(); chkcomment = TRUE; if ((ch = GETC(fname)) == EOF) return(TENDOFFILE); } else { UNGETC(ch, fname); ch = '-'; chkcomment = FALSE; } } else chkcomment = FALSE; } while (chkcomment); if (isalpha(ch) || ch == '_') return(eatident(ch)); if (isdigit(ch)) return(eatnumber(ch)); if (ch == '"') return(eatstring()); if (ch == '\'') { char ch2; char ch3; char chat; int ate; ch2 = GETC(fname); ch3 = GETC(fname); UNGETC(ch3,fname); UNGETC(ch2,fname); if (ch2 != ' ' || ch3 != '\'') { /* can't eat whitespace if char contains whitespace */ ate = eatwhite(); chat = GETC(fname); UNGETC(chat,fname); if (chat == '@') { if (ate || (ch2 != '@' && ch3 != '\'')) { return TPRIME; } } } return eatcharacter(); } if (ch == '.') { if (isdigit(ch = GETC(fname))) { UNGETC(ch, fname); ch = '.'; return(eatnumber(ch)); } else { UNGETC(ch, fname); ch = '.'; } } if (ch == '#') { char ch2; eatwhite(); /* remove "line" if it exists - some vers of cpp have this */ if ((ch2 = GETC(fname)) == '[') { UNGETC(ch2, fname); return eatleftovers(ch); } else { UNGETC(ch2, fname); } if (!isdigit(ch = GETC(fname))) { UNGETC(ch, fname); yylex2(); if (!strcmp(buffer,"pragma")) { for (ch = GETC(fname); ch != '\n'; ch = GETC(fname)) ; goto yuk_a_goto; } if (strcmp(buffer,"line")) { USR_FATALX(yylineno, in_file, "syntax error (appears to be a cpp directive: try -cpp)"); } eatwhite(); } else { UNGETC(ch, fname); } if (!isdigit(ch = GETC(fname))) { UNGETC(ch, fname); USR_FATALX(yylineno, in_file, "syntax error (appears to be a cpp directive: use -cpp)"); } else UNGETC(ch, fname); yylex2(); yylineno = atoi(buffer); for (ch = GETC(fname); ch != '"' && ch != '\n'; ch = GETC(fname)) ; if (ch != '"') { goto yuk_a_goto; } else UNGETC(ch, fname); yylex2(); in_file = (char *)PMALLOC((strlen(buffer) + 1)*sizeof(char)); strcpy(in_file, buffer); base_in_file = strrchr(in_file,'/'); if (base_in_file == NULL) { base_in_file = in_file; } else { base_in_file++; } for (ch = GETC(fname); ch != '\n'; ch = GETC(fname)) ; goto yuk_a_goto; } if (ispunct(ch)) return(eatleftovers(ch)); buffer[0] = ch; buffer[1] = '\0'; if (firstsemi == 1) { firstsemi = 0; fclose(fname); fname = fnamesave; goto yuk_a_goto; } return(-1); }
static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr) { int count, chars, c, width, radix, d, i; int *int_ptr; long *long_ptr; short *short_ptr; char *char_ptr; unsigned char f; char neg, assign, ok, size; long n; char map[256], end; double dx, dd, *dbl_ptr; float *flt_ptr; int exp; char eneg; count = 0; chars = 0; c = 0; while ((f = *fmt) != 0) { if (WHITE(f)) { do { ++fmt; f = *fmt; } while (WHITE(f)); do { c = *buf++; if (!c) { if (!f || count) return count; else return EOF; } else ++chars; } while (WHITE(c)); UNGETC(); } else if (f != '%') { NEXT(c); if (c != f) return count; ++fmt; } else { assign = TRUE; width = INT_MAX; char_ptr = NULL; ++fmt; if (*fmt == '*') { assign = FALSE; ++fmt; } if (isdigit(*fmt)) { width = 0; while (isdigit(*fmt)) width = width * 10 + (*fmt++ - '0'); if (!width) width = INT_MAX; } size = 0; if (*fmt == 'h' || *fmt == 'l') size = *fmt++; f = *fmt; switch (f) { case 'c': if (width == INT_MAX) width = 1; if (assign) char_ptr = va_arg(arg_ptr, char *); while (width > 0) { --width; NEXT(c); if (assign) { *char_ptr++ = (char) c; ++count; } } break; case '[': memset(map, 0, 256); end = 0; ++fmt; if (*fmt == '^') { ++fmt; end = 1; } i = 0; for (;;) { f = (unsigned char) *fmt; switch (f) { case 0: /* avoid skipping past 0 */ --fmt; NEXT(c); goto string; case ']': if (i > 0) { NEXT(c); goto string; } /* no break */ default: if (fmt[1] == '-' && fmt[2] && f < (unsigned char)fmt[2]) { memset(map + f, 1, (unsigned char)fmt[2] - f); fmt += 2; } else map[f] = 1; break; } ++fmt; ++i; } case 's': memset(map, 0, 256); map[' '] = 1; map['\n'] = 1; map['\r'] = 1; map['\t'] = 1; end = 1; do { NEXT(c); } while (WHITE(c)); string: if (assign) char_ptr = va_arg(arg_ptr, char *); while (width > 0 && map[(unsigned char) c] != end) { --width; if (assign) *char_ptr++ = (char) c; c = *buf++; if (!c) break; else ++chars; } if (assign) { *char_ptr = 0; ++count; } if (!c) return count; else UNGETC(); break; case 'f': case 'e': case 'E': case 'g': case 'G': neg = ok = FALSE; dx = 0.0; do { NEXT(c); } while (WHITE(c)); if (c == '+') { NEXT(c); --width; } else if (c == '-') { neg = TRUE; NEXT(c); --width; } while (width > 0 && isdigit(c)) { --width; dx = dx * 10.0 + (double) (c - '0'); ok = TRUE; c = *buf++; if (!c) break; else ++chars; } if (width > 0 && c == '.') { --width; dd = 10.0; NEXT(c); while (width > 0 && isdigit(c)) { --width; dx += (double) (c - '0') / dd; dd *= 10.0; ok = TRUE; c = *buf++; if (!c) break; else ++chars; } } if (!ok) return count; if (width > 0 && (c == 'e' || c == 'E')) { eneg = FALSE; exp = 0; NEXT(c); --width; if (width > 0 && c == '+') { NEXT(c); --width; } else if (width > 0 && c == '-') { eneg = TRUE; NEXT(c); --width; } if (!(width > 0 && isdigit(c))) { UNGETC(); return count; } while (width > 0 && isdigit(c)) { --width; exp = exp * 10 + (c - '0'); c = *buf++; if (!c) break; else ++chars; } if (eneg) exp = -exp; while (exp > 0) { dx *= 10.0; --exp; } while (exp < 0) { dx /= 10.0; ++exp; } } if (assign) { if (neg) dx = -dx; if (size == 'l') { dbl_ptr = va_arg(arg_ptr, double *); *dbl_ptr = dx; } else { flt_ptr = va_arg(arg_ptr, float *); *flt_ptr = (float)dx; } ++count; } if (!c) return count; else UNGETC(); break; case 'i': neg = FALSE; radix = 10; do { NEXT(c); } while (WHITE(c)); if (!(width > 0 && c == '0')) goto scan_complete_number; NEXT(c); --width; if (width > 0 && (c == 'x' || c == 'X')) { NEXT(c); radix = 16; --width; } else if (width > 0 && (c >= '0' && c <= '7')) radix = 8; goto scan_unsigned_number; case 'd': case 'u': case 'o': case 'x': case 'X': do { NEXT(c); } while (WHITE(c)); switch (f) { case 'o': radix = 8; break; case 'x': case 'X': radix = 16; break; default: radix = 10; break; } scan_complete_number: neg = FALSE; if (width > 0 && c == '+') { NEXT(c); --width; } else if (width > 0 && c == '-' && radix == 10) { neg = TRUE; NEXT(c); --width; } scan_unsigned_number: n = 0; ok = FALSE; while (width > 0) { --width; if (isdigit(c)) d = c - '0'; else if (isupper(c)) d = c - 'A' + 10; else if (islower(c)) d = c - 'a' + 10; else break; if (d < 0 || d >= radix) break; ok = TRUE; n = n * radix + d; c = *buf++; if (!c) break; else ++chars; } if (!ok) return count; if (assign) { if (neg) n = -n; switch (size) { case 'h': short_ptr = va_arg(arg_ptr, short *); *short_ptr = (short) n; break; case 'l': long_ptr = va_arg(arg_ptr, long *); *long_ptr = (long) n; break; default: int_ptr = va_arg(arg_ptr, int *); *int_ptr = (int) n; } ++count; } if (!c) return count; else UNGETC(); break; case 'n': if (assign) { int_ptr = va_arg(arg_ptr, int *); *int_ptr = chars; ++count; } break; default: if (!f) /* % at end of string */ return count; NEXT(c); if (c != f) return count; break; } ++fmt; }
char *sed_compile(sed_commands_t *commands, sed_comp_args *compargs, char *ep, char *endbuf, int seof) { int c; int eof = seof; char *lastep; int cclcnt; char bracket[NBRA], *bracketp; int closed; int neg; int lc; int i, cflg; int iflag; /* used for non-ascii characters in brackets */ int nodelim = 0; char *sp = commands->cp; int regerrno = 0; lastep = 0; if ((c = GETC()) == eof || c == '\n') { if (c == '\n') { UNGETC(c); nodelim = 1; } commands->cp = sp; goto out; } bracketp = bracket; compargs->circf = closed = compargs->nbra = 0; if (c == '^') compargs->circf++; else UNGETC(c); while (1) { if (ep >= endbuf) SEDCOMPILE_ERROR(50); c = GETC(); if (c != '*' && ((c != '\\') || (PEEKC() != '{'))) lastep = ep; if (c == eof) { *ep++ = CCEOF; if (bracketp != bracket) SEDCOMPILE_ERROR(42); commands->cp = sp; goto out; } switch (c) { case '.': *ep++ = CDOT; continue; case '\n': SEDCOMPILE_ERROR(36); commands->cp = sp; goto out; case '*': if (lastep == 0 || *lastep == CBRA || *lastep == CKET) goto defchar; *lastep |= STAR; continue; case '$': if (PEEKC() != eof && PEEKC() != '\n') goto defchar; *ep++ = CDOL; continue; case '[': if (&ep[17] >= endbuf) SEDCOMPILE_ERROR(50); *ep++ = CCL; lc = 0; for (i = 0; i < 16; i++) ep[i] = 0; neg = 0; if ((c = GETC()) == '^') { neg = 1; c = GETC(); } iflag = 1; do { c &= 0377; if (c == '\0' || c == '\n') SEDCOMPILE_ERROR(49); if ((c & 0200) && iflag) { iflag = 0; if (&ep[32] >= endbuf) SEDCOMPILE_ERROR(50); ep[-1] = CXCL; for (i = 16; i < 32; i++) ep[i] = 0; } if (c == '-' && lc != 0) { if ((c = GETC()) == ']') { PLACE('-'); break; } if ((c & 0200) && iflag) { iflag = 0; if (&ep[32] >= endbuf) SEDCOMPILE_ERROR(50); ep[-1] = CXCL; for (i = 16; i < 32; i++) ep[i] = 0; } while (lc < c) { PLACE(lc); lc++; } } lc = c; PLACE(c); } while ((c = GETC()) != ']'); if (iflag) iflag = 16; else iflag = 32; if (neg) { if (iflag == 32) { for (cclcnt = 0; cclcnt < iflag; cclcnt++) ep[cclcnt] ^= 0377; ep[0] &= 0376; } else { ep[-1] = NCCL; /* make nulls match so test fails */ ep[0] |= 01; } } ep += iflag; continue; case '\\': switch (c = GETC()) { case '(': if (compargs->nbra >= NBRA) SEDCOMPILE_ERROR(43); *bracketp++ = compargs->nbra; *ep++ = CBRA; *ep++ = compargs->nbra++; continue; case ')': if (bracketp <= bracket) SEDCOMPILE_ERROR(42); *ep++ = CKET; *ep++ = *--bracketp; closed++; continue; case '{': if (lastep == (char *) 0) goto defchar; *lastep |= RNGE; cflg = 0; nlim: c = GETC(); i = 0; do { if ('0' <= c && c <= '9') i = 10 * i + c - '0'; else SEDCOMPILE_ERROR(16); } while (((c = GETC()) != '\\') && (c != ',')); if (i >= 255) SEDCOMPILE_ERROR(11); *ep++ = i; if (c == ',') { if (cflg++) SEDCOMPILE_ERROR(44); if ((c = GETC()) == '\\') *ep++ = (char) 255; else { UNGETC(c); goto nlim; /* get 2'nd number */ } } if (GETC() != '}') SEDCOMPILE_ERROR(45); if (!cflg) /* one number */ *ep++ = i; else if ((ep[-1] & 0377) < (ep[-2] & 0377)) SEDCOMPILE_ERROR(46); continue; case '\n': SEDCOMPILE_ERROR(36); case 'n': c = '\n'; goto defchar; default: if (c >= '1' && c <= '9') { if ((c -= '1') >= closed) SEDCOMPILE_ERROR(25); *ep++ = CBACK; *ep++ = c; continue; } } /* Drop through to default to use \ to turn off special chars */ defchar: default: lastep = ep; *ep++ = CCHR; *ep++ = c; } } out: if (regerrno) { regerr(commands, regerrno); return (char*) NULL; } /* XXX : Basant : what extra */ /* int reglength = (int)(ep - expbuf); */ return ep; }
int sc_next (SCAN *scan) { /* --- get next token */ int c, ccl; /* character and character class */ int quote = 0; /* quote at the start of a string */ int ec = 0; /* escaped character */ int state = 0; /* state of automaton */ int level = 0; /* comment nesting level */ char *p; /* to traverse the scan buffer */ char *end; /* end of the scan buffer */ if (scan->back) { /* if a step backwards has been made, */ scan->back = 0; /* clear the corresponding flag, */ return _swap(scan); /* swap back the token information, */ } /* and return the current token */ scan->pline = scan->line; /* note the relevant information */ scan->ptoken = scan->token; /* of the current token */ scan->plen = scan->len; /* and swap scan buffers */ if (scan->value == scan->buf[0]) scan->value = p = scan->buf[1]; else scan->value = p = scan->buf[0]; end = p +SC_BUFSIZE -1; /* get the end of the scan buffer */ while (1) { /* read loop */ c = getc(scan->file); /* get character and character class */ ccl = (c < 0) ? EOF : _ccltab[c]; if (c == '\n') scan->line++; /* count the line */ switch (state) { /* evaluate state of automaton */ case S_SPACE: /* --- skip white space */ switch (ccl) { /* evaluate character category */ case C_SPACE : /* do nothing */ break; case C_LETTER: *p++ = c; state = S_ID; break; case C_DIGIT : *p++ = c; state = S_NUMDIG; break; case C_POINT : *p++ = c; state = S_NUMPT; break; case C_SIGN : *p++ = c; state = S_SIGN; break; case C_CMPOP : *p++ = c; state = S_CMPOP; break; case C_QUOTE : quote = c; state = S_STRING; break; case C_SLASH : state = S_SLASH; break; case C_ACTIVE: *p++ = c; *p = '\0'; scan->len = 1; return scan->token = c; case EOF : strcpy(p, "<eof>"); scan->len = 4; return scan->token = (ferror(scan->file)) ? E_FREAD : T_EOF; default : *p++ = c; *p = '\0'; scan->len = 1; return scan->token = E_ILLCHR; } break; case S_ID: /* --- identifier (letter read) */ if ((ccl == C_LETTER) /* if another letter */ || (ccl == C_DIGIT) /* or a digit */ || (ccl == C_POINT) /* or a decimal point */ || (ccl == C_SIGN)) { /* or a sign follows */ if (p >= end) return scan->token = E_BUFOVF; *p++ = c; break; /* buffer character */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_NUMDIG: /* --- number (digit read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_DIGIT) /* if another digit follows, */ break; /* do nothing */ if (ccl == C_POINT) { /* if a decimal point follows, */ state = S_FRAC; break; } /* go to 'fraction' state */ if ((c == 'e') /* if an exponent indicator follows */ || (c == 'E')) { /* (lower- or uppercase), */ state = S_EXPIND; break; } /* go to 'exponent' state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_SIGN)) { /* or a sign follows, */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_NUM; /* and return 'number' */ case S_NUMPT: /* --- number (point read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_DIGIT) { /* if a digit follows, */ state = S_FRAC; break; } /* go to 'fraction' state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_POINT) /* or a decimal point */ || (ccl == C_SIGN)) { /* or a sign follows */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_FRAC: /* --- number (digit & point read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_DIGIT) /* if another digit follows, */ break; /* do nothing else */ if ((c == 'e') /* if an exponent indicator follows, */ || (c == 'E')) { /* (lower- or uppercase), */ state = S_EXPIND; break; } /* go to exponent state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_POINT) /* or a decimal point */ || (ccl == C_SIGN)) { /* or a sign follows, */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_NUM; /* and return 'number' */ case S_EXPIND: /* --- exponent (indicator read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_SIGN) { /* if a sign follows, */ state = S_EXPSGN; break; } /* go to 2nd 'exponent' state */ if (ccl == C_DIGIT) { /* if a digit follows, */ state = S_EXPDIG; break; } /* go to 3rd 'exponent' state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_POINT)) { /* or a decimal point follows */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_EXPSGN: /* --- exponent (sign read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_DIGIT) { /* if a digit follows, */ state = S_EXPDIG; break;} /* do nothing else */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_POINT) /* or a decimal point */ || (ccl == C_SIGN)) { /* or a sign follows */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_EXPDIG: /* --- exponent (digit read) */ if (p < end) *p++ = c; /* buffer character */ else return scan->token = E_BUFOVF; if (ccl == C_DIGIT) /* if another digit follows, */ break; /* do nothing else */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_POINT) /* or a decimal point */ || (ccl == C_SIGN)) { /* or a sign follows, */ state = S_ID; break; /* go to 'identifier' state */ } /* otherwise */ UNGETC(scan, c); /* put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_NUM; /* and return 'number' */ case S_SIGN: /* --- number (sign read) */ *p++ = c; /* buffer character */ if (ccl == C_DIGIT) { /* if a digit follows, */ state = S_NUMDIG; break; } /* go to 'number' state */ if (ccl == C_POINT) { /* if a decimal point follows, */ state = S_NUMPT; break; } /* go to fraction state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_SIGN)) { /* or a sign follows, */ state = S_ID; break; } /* go to 'identifier' state */ if ((c == '>') /* if a '>' follows and previous */ && (scan->value[0] == '-')) { /* char was a minus sign */ *p = '\0'; scan->len = 2; return scan->token = T_RGT; } UNGETC(scan, c); /* otherwise put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_CMPOP: /* --- comparison operator read */ if ((c == '-') /* if a minus sign follows and */ && (scan->value[0] == '<')) { /* prev. char was a '<' */ *p++ = '-'; scan->token = T_LFT; } else if (c == '=') { /* if an equal sign follows */ *p++ = '='; scan->token = T_CMP; } else { /* if anything else follows */ UNGETC(scan, c); scan->token = scan->value[0]; } *p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token; /* and return the token read */ case S_STRING: /* --- quoted string */ if ((c == '\n') || (c == EOF)) /* if end of line or file, */ return scan->token = E_UNTSTR; /* string is unterminated */ if (c != quote) { /* if not at end of string */ if (p >= end) return scan->token = E_BUFOVF; if (c == '\\') { /* if escaped character follows, */ state = S_ESC; break; } /* go to escaped char state */ *p++ = c; break; /* otherwise buffer character */ } /* if at end of string, */ *p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_ESC: /* --- after '\' in quoted string */ if ((c >= '0') && (c <= '7')) { /* if octal digit, */ ec = c -'0'; state = S_OCT1; break; }/* evaluate digit */ if (c == 'x') { /* if hexadecimal character code, */ state = S_HEX1; break;} /* go to hexadecimal evaluation */ switch (c) { /* evaluate character after '\' */ case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '\n': c = -1; break; default : break; } /* get escaped character */ if (c >= 0) *p++ = c; /* and store it, then */ state = S_STRING; break;/* return to quoted string state */ case S_OCT1: /* --- escaped octal number 1 */ if ((c >= '0') /* if an octal digit follows, */ && (c <= '7')) { /* evaluate it */ ec = ec *8 +c -'0'; state = S_OCT2; break; } UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_OCT2: /* --- escaped octal number 2 */ if ((c >= '0') || (c <= '7')) ec = ec *8 +c -'0'; /* if octal digit, evaluate it */ else UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_HEX1: /* --- escaped hexadecimal number 1 */ if (ccl == C_DIGIT) { /* if hexadecimal digit, evaluate it */ ec = c -'0'; state = S_HEX2; break; } if ((c >= 'a') && (c <= 'f')) { ec = c -'a' +10; state = S_HEX2; break; } if ((c >= 'A') && (c <= 'F')) { ec = c -'A' +10; state = S_HEX2; break; } UNGETC(scan, c); /* otherwise put back last character */ *p++ = 'x'; /* store escaped character ('x') and */ state = S_STRING; break;/* return to quoted string state */ case S_HEX2: /* --- escaped hexadecimal number 2 */ if (ccl == C_DIGIT) /* if hexadecimal digit, evaluate it */ ec = ec*16 +c -'0'; else if ((c >= 'a') && (c <= 'f')) ec = ec*16 +c -'a' +10; else if ((c >= 'A') && (c <= 'F')) ec = ec*16 +c -'A' +10; else UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_SLASH: /* --- slash '/' */ if (c == '/') { /* if C++ style comment, then */ state = S_CPPCOM; break; } /* skip to end of line */ if (c == '*') { /* if C style comment */ scan->start = scan->line; level = 1; state = S_CCOM1; break; /* note start line, init. level */ } /* and go to first 'comment' state */ UNGETC(scan, c); /* otherwise put back last character */ *p++ = '/'; *p = '\0'; /* store character in buffer */ scan->len = 1; /* set string length and */ return scan->token = '/'; /* return `character' */ case S_CPPCOM: /* --- C++ style comment */ if ((c == '\n') /* if at end of line */ || (c == EOF)) /* or at end of file */ state = S_SPACE; /* return to white space skipping */ break; /* (skip to end of line) */ case S_CCOM1: /* --- C style comment 1 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '*') /* if possibly 'end of comment', */ state = S_CCOM2; /* go to 2nd 'comment' state */ else if (c == '/') /* if possibly 'start of comment', */ state = S_CCOM3; /* go to 3rd 'comment' state */ break; case S_CCOM2: /* --- C style comment 2 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '/') { /* if end of comment found */ if (--level <= 0) state = S_SPACE; else state = S_CCOM1; } else if (c != '*') /* if end of comment impossible */ state = S_CCOM1; /* return to comment skipping */ break; /* (possible start of comment) */ case S_CCOM3: /* --- C style comment 3 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '*') { /* if start of comment found */ level++; state = S_CCOM1; } else if (c != '/') /* if start of comment impossible */ state = S_CCOM1; /* return to comment skipping */ break; /* (possible end of comment) */ default: /* if state is illegal, abort */ return scan->token = E_STATE; } /* switch() */ } /* while(1) */ } /* sc_next() */