diff --git a/WEGA/contrib/ingres/dbs/src/eql/number.c b/WEGA/contrib/ingres/dbs/src/eql/number.c new file mode 100644 index 0000000..438250c --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/eql/number.c @@ -0,0 +1,122 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "constants.h" +# include "globals.h" + +/* +** NUMBER -- process a numeric token +** Number gets a number as, either floating or integer, +** with the QL format, from inside a QL statement, +** and adds it to the symbol space. +** +** Parameters: +** chr -- the first character of the number +** +** Returns: +** The lexical code for the appropriate +** type of number. +** +** Side Effects: +** Adds a token to the symbols space. +** yylval is set to the node added. +*/ +number(chr) +register int chr; +{ + register char *ptr; + register int toktyp; + double ftemp; + long ltemp; + char buf[MAXFIELD + 1]; + extern char *yylval; + extern char *addsym(); + extern char *salloc(); + + ptr = buf; + if ((*ptr = toktyp = chr) != '.') + { + do + { + /* get integer portion */ + if ((ptr - buf) > MAXFIELD) + { + /* buffer overflow + * return integer 0, + * and signal error. + */ +bufovflo : + *ptr = '\0'; + yysemerr("numeric too long", buf); + yylval = addsym("0"); + return (Tokens.sp_i2const); + } + + *++ptr = toktyp = getch(); + } while (CMAP(toktyp) == NUMBR); + } + + /* do rest of type determination */ + switch (toktyp) + { + case '.': + /* floating point */ + do + { + /* fill into ptr with up to next non-digit */ + if ((ptr - buf) > MAXFIELD) + goto bufovflo; + *++ptr = toktyp = getch(); + } while (CMAP(toktyp) == NUMBR); + if (toktyp != 'e' && toktyp != 'E') + { + backup(toktyp); + *ptr = '\0'; + goto convr; + } + + case 'e': + case 'E': + if ((ptr - buf) > MAXFIELD) + goto bufovflo; + *++ptr = toktyp = getch(); + if (CMAP(toktyp) == NUMBR || toktyp == '-' || toktyp == '+') + { + do + { + /* get exponent */ + if ((ptr - buf) > MAXFIELD) + goto bufovflo; + *++ptr = toktyp = getch(); + } while (CMAP(toktyp) == NUMBR); + } + backup(toktyp); + *ptr = '\0'; +convr: + if (AA_atof(buf, &ftemp)) + { + /* floating conversion error */ + yysemerr("numeric ofverflow", buf); + yylval = addsym("0"); + return (Tokens.sp_f8const); + } + yylval = addsym(salloc(buf)); + toktyp = Tokens.sp_f8const; + break; + + default: + /* integer */ + backup(toktyp); + *ptr = '\0'; + + /* long conversion error */ + if (AA_atol(buf, <emp) || ltemp > 32767 || ltemp < -32768) + goto convr; + yylval = addsym(salloc(buf)); + toktyp = Tokens.sp_i2const; + break; + } + + return (toktyp); +} diff --git a/WEGA/contrib/ingres/dbs/src/eql/operator.c b/WEGA/contrib/ingres/dbs/src/eql/operator.c new file mode 100644 index 0000000..06a4e37 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/eql/operator.c @@ -0,0 +1,88 @@ +# include +# include "gen.h" +# include "constants.h" +# include "globals.h" + +/* +** OPERATOR -- process a token starting with an operator +** +** Processes operators, strings, comments, and +** floating constants without a leading 0. +** +** Parameters: +** chr - first character of token {CMAP(chr) == OPATR} +** +** Returns: +** NUMBER or STRING token, or operator token. +** CONTINUE on error. +** +** Side Effects: +** Adds a node to the Symbol space, and returns adress +** in "yylval". +** Opcode is set to the opcode of the operator. +** May backup a character. +*/ +operator(chr) +register int chr; +{ + register struct optab *op; + register int next_ch; + char opbuf[3]; + extern char *yylval; + extern char *addsym(); + + opbuf[0] = chr; + opbuf[1] = next_ch = getch(); + opbuf[2] = '\0'; + + if (opbuf[0] == '.' && CMAP(next_ch) == NUMBR) + { + /* floating mantissa w/o leading 0 */ + backup(next_ch); + return (number(opbuf[0])); + } + if (CMAP(next_ch) != OPATR) + { + backup(next_ch); + opbuf[1] = '\0'; + } + /* operator has been reduced to its smallest + * possible length, now try to find it in the + * operator table[tokens.y] + */ + for ( ; ; ) + { + for (op = Optab; op->op_term; op++) + if (AAsequal(op->op_term, opbuf)) + break; + if (!op->op_term && opbuf[1]) + { + /* reduce a 2 char operator to 1 char, + * and re-search + */ + backup(opbuf[1]); + opbuf[1] = '\0'; + continue; + } + break; + } + if (op->op_term) + { + /* string quotes ? */ + if (op->op_token == Tokens.sp_quote) + return (string(op)); + + /* comment indicator ? */ + if (op->op_token == Tokens.sp_bgncmnt) + return (comment()); + + /* {AAsequal(opbuf, op->op_term)} */ + Opcode = op->op_code; + yylval = addsym(op->op_term); + return (op->op_token); + } + yysemerr("bad operator", opbuf); + + /* operator not found, skip token and try again */ + return (CONTINUE); +} diff --git a/WEGA/contrib/ingres/dbs/src/eql/string.c b/WEGA/contrib/ingres/dbs/src/eql/string.c new file mode 100644 index 0000000..a7982b9 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/eql/string.c @@ -0,0 +1,87 @@ +# include +# include "gen.h" +# include "constants.h" +# include "globals.h" + +/* +** STRING -- processes a string constant +** Strings are kept internally exactly as their external +** appearance, except for the outermost '"'. +** A string may be at most MAXSTRING characters +** long, and may have escaped newlines. +** +** Parameters: +** op -- pointer to string quote operator +** table entry. +** +** Returns: +** SCONST +*/ +string(op) +struct optab *op; +{ + char buf[MAXSTRING + 1]; + register int c; + register char *cp; + register int escape; + register int error; + extern char *yylval; + extern char *addsym(); + extern char *salloc(); + + error = escape = 0; + cp = buf; + for ( ; ; ) + { + switch (c = getch()) + { + case '\\' : + if (!escape) + escape = 2; + goto regchar; + + case '\n' : + if (escape) + goto regchar; + *cp = '\0'; + yysemerr("non-terminated string", !error? buf :(char *) 0); + break; + + case EOF_TOK : + backup(c); + *cp = '\0'; + yysemerr("EOF in string", !error? buf :(char *) 0); + break; + + default : +regchar : + if (c == *op->op_term && !escape) + { + /* end of string */ + *cp = '\0'; + break; + } + if (!error) + { + if (cp - buf < MAXSTRING) + { + if (CMAP(c) == CNTRL) + yysemerr("control character in string eliminated", (char *) 0); + else + *cp++ = c; + } + else + { + yysemerr("string too long, rest discarded", (char *) 0); + error = 1; + } + } + if (escape) + --escape; + continue; + } + break; + } + yylval = addsym(salloc(buf)); + return (Tokens.sp_sconst); +} diff --git a/WEGA/contrib/ingres/dbs/src/eql/yylex.c b/WEGA/contrib/ingres/dbs/src/eql/yylex.c new file mode 100644 index 0000000..852f064 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/eql/yylex.c @@ -0,0 +1,167 @@ +# include +# include "gen.h" +# include "constants.h" +# include "globals.h" + +int yyline; + +/* +** YYLEX -- Lexical analyzer +** Yylex controls the return to the parser of lexemes, +** and the copying out of C_CODE on the all to yylex +** after yylex() returned the C_CODE. +** +** Returns: +** Lexical tokens. +** +** Side Effects: +** Copies C code out on call after seeing it. +** Puts terminals in symbol space. +*/ +yylex() +{ + register int rtval; + register int chr; + extern char *yysterm[]; + + /* get next token */ + rtval = CONTINUE; + + while (rtval == CONTINUE) + { + if (C_code_flag) + { + copy_c_code(); + Newline = 1; + } + Pre_proc_flag = 0; + + /* END OF FILE ? */ + if ((chr = getch()) == EOF_TOK) + { +# ifdef xDEBUG + if (Lex_debug) + printf("end of file\n"); +# endif + return (0); + } + + /* Test for a line of C code */ + if (Newline && if_c_code(chr)) + { + if (C_code_flag) + continue; + rtval = Tokens.sp_c_code; + C_code_flag = 1; + break; + } + else + { + C_code_flag = 0; + if (Newline) + { + Newline = 0; + continue; + } + } + + /* CARRIAGE CONTROL ? */ + Newline = chr == '\n'; + + switch (CMAP(chr)) + { + + case PUNCT : + continue; + + case OPATR : + rtval = operator(chr); + break; + + case NUMBR : + rtval = number(chr); + break; + + case ALPHA : + rtval = name(chr); + break; + + } + } + if (Lex_debug) + printf("YYLEX : %s: '%s'\n", yysterm[rtval - 256], + yylval? ((struct disp_node *) yylval)->d_elm: ""); + return (rtval); +} + + +/* +** COPY_C_CODE -- Copies out a line of C code +** The test for Charcnt != 0 is beacuse if a C pre-processor +** line follows an EQL line, and equate_lines() puts out no +** newline, the initial '#' will not be on the beginning of +** the line. As is, if this should happen, then the line +** with the '#' will be one line in the output ahead of +** where it should be. +*/ +copy_c_code() +{ + register int c; + char ch[2]; + + ch[1] = 0; + equate_lines(); + if (Pre_proc_flag) + { + if (Charcnt) + w_raw("\n"); + w_raw("#"); + } + do + { + if ((c = getch()) == EOF_TOK) + return; + *ch = c; + w_raw(ch); + } while (*ch != '\n'); +} + + +/* +** IF_C_CODE -- Test to see if a line is C code +** +** Sees if a line begins with "##" to see if it is EQL. +** +** Parameters: +** chr -- first char of line +** +** Returns: +** 0 -- QL line +** 1 -- C line +*/ +if_c_code(chr) +register int chr; +{ + for ( ; ; ) + { + if (chr != '#') + { + backup(chr); + return (1); + } + Pre_proc_flag = 1; + if ((chr = getch()) == EOF_TOK) + { + return (0); + } + if (chr != '#') + { + backup(chr); + return (1); + } + else + { + return (0); + } + } +}