fox@emunix.emich.edu (Kenneth Fox [UC90_439875]) (01/15/91)
I've been having a severe problem running lex on a Sun 4. The problem occurs under both SunOS 4.1 and 4.0.3. It seems to be specific to sparc as the file lexes fine on a Sun 3 (4.1) and microVAX II (Ultrix v3.0). The bug itself seems to be caused by start conditions, and only when more than 5 patterns active in the same start condition are used. This could be all wrong because I haven't extensively tested the failure conditions. I can't give any better guess because lex is stripped as distributed by Sun. Another problem I have is that pattern lookahead doesn't seem to work when a start condition is active. Lex generates a message that an extra slash has been removed. Is this "correct"? Personally, I think it would be useful to specify left AND right context... Hopefully, somebody with source code access will post a better explanation. I apologize for such a large post (with such long lines), but I don't know what part of this file is exactly causing the problem... I'm praying that the long lines will go through, but if they don't I'd be happy to send somebody a good copy through mail. Thanks in advance, Ken Fox (fox@emunix.emich.edu) ------------------------------ Cut Here ------------------------------ %{ /* ** Ken Fox (fox@emunix.emich.edu) ** ** this code is in the public domain. ** ** this is a fragment of an Oracle SQL*FORMS converter. It's big ** and ugly, but that shouldn't surprise anybody that's work with ** Oracle products before... 8-) ** ** use 4 character tabs for best results. ** */ #include <stdio.h> #include <ctype.h> #include "generic.h" /* lex won't complain about not having these */ #include "global.h" #include "y.tab.h" #define MAX_VALUE_LEN 10240 extern long strtol(); extern double atof(); int readEscapeCode(); int readComment(); char *readString(); char *readValue(); char *readLine(); int inputLineCount = 1; extern char *inputFileName; extern YYSTYPE yylval; #undef input #undef unput extern int inputUpper(); extern int inputRaw(); #define ReadKeywords() input = inputUpper; BEGIN 0 #define ReadValues() input = inputRaw; BEGIN ASSIGN int (*input)() = inputUpper; %} %e 2000 %p 5000 %n 2000 %k 500 %a 4000 %o 4000 WS [^a-zA-Z0-9] D [0-9] H [0-9a-fA-F] %START ASSIGN %% [ \t]* ; "/*" { (void)readComment(); } \n { ++inputLineCount; } DEFINE { return(T_DEFINE); } FORM/{WS} { return(T_FORM); } PROCEDURE/{WS} { return(T_PROCEDURE); } TRIGGER { return(T_TRIGGER); } STEP/{WS} { return(T_STEP); } BLOCK/{WS} { return(T_BLOCK); } FIELD/{WS} { return(T_FIELD); } REFERENCE/{WS} { return(T_REFERENCE); } SCREEN/{WS} { return(T_SCREEN); } PAGE/{WS} { return(T_PAGE); } ENDDEFINE { return(T_ENDDEFINE); } ABORT { return(T_ABORT); } APPLICATION { return(T_APPLICATION); } ARRAY_SIZE { return(T_ARRAY_SIZE); } AUTOHELP { return(T_AUTOHELP); } AUTOSKIP { return(T_AUTOSKIP); } BASE_LINE { return(T_BASE_LINE); } BASE_TABLE { return(T_BASE_TABLE); } BOILER { return(T_BOILER); } BORDER { return(T_BORDER); } COLUMN/{WS} { return(T_COLUMN); } COLUMN_SECURITY { return(T_COLUMN_SECURITY); } DATATYPE { return(T_DATATYPE); } DEFAULT/{WS} { return(T_DEFAULT); } DEFAULT_MENU_APPLICATION { return(T_DEFAULT_MENU_APPLICATION); } DEFINITION { return(T_DEFINITION); } DESCRIPTION { return(T_DESCRIPTION); } DISPLAYED { return(T_DISPLAYED); } DISPLAY_LENGTH { return(T_DISPLAY_LENGTH); } DISSOLVE { return(T_DISSOLVE); } ECHO { return(T_ECHO); } EDIT_WORD_WRAP { return(T_EDIT_WORD_WRAP); } EDIT_X { return(T_EDIT_X); } EDIT_Y { return(T_EDIT_Y); } ENFORCE_KEY_FROM { return(T_ENFORCE_KEY_FROM); } FAILURE_STEP { return(T_FAILURE_STEP); } FAIL_MESSAGE { return(T_FAIL_MESSAGE); } FIXED_LENGTH { return(T_FIXED_LENGTH); } GROUP_NAME { return(T_GROUP_NAME); } HELP { return(T_HELP); } HIGH_VALUE { return(T_HIGH_VALUE); } HORIZONTAL_SCROLL_BAR { return(T_HORIZONTAL_SCROLL_BAR); } IGNORE { return(T_IGNORE); } INPUT/{WS} { return(T_INPUT); } INPUT_MASK { return(T_INPUT_MASK); } IN_MENU { return(T_IN_MENU); } LABEL { return(T_LABEL); } LENGTH { return(T_LENGTH); } LINE/{WS} { return(T_LINE); } LINES_PER_ROW { return(T_LINES_PER_ROW); } LOV_TEXT { return(T_LOV_TEXT); } LOV_TITLE { return(T_LOV_TITLE); } LOV_X { return(T_LOV_X); } LOV_Y { return(T_LOV_Y); } LOW_VALUE { return(T_LOW_VALUE); } MANDATORY { return(T_MANDATORY); } MODE { return(T_MODE); } MOUSE_NAVIGATION_LIMIT { return(T_MOUSE_NAVIGATION_LIMIT); } NAME { return(T_NAME); } NEW_CURSOR { return(T_NEW_CURSOR); } ORDERING { return(T_ORDERING); } OUTPUT_MASK { return(T_OUTPUT_MASK); } OWNER { return(T_OWNER); } PAGE_PX0 { return(T_PAGE_PX0); } PAGE_PXS { return(T_PAGE_PXS); } PAGE_PY0 { return(T_PAGE_PY0); } PAGE_PYS { return(T_PAGE_PYS); } PAGE_SX0 { return(T_PAGE_SX0); } PAGE_SY0 { return(T_PAGE_SY0); } PAGE_XS { return(T_PAGE_XS); } PAGE_YS { return(T_PAGE_YS); } POPUP { return(T_POPUP); } PRIMARY_KEY { return(T_PRIMARY_KEY); } QUERY/{WS} { return(T_QUERY); } QUERY_LENGTH { return(T_QUERY_LENGTH); } REVERSE { return(T_REVERSE); } ROOT_MENU { return(T_ROOT_MENU); } ROWS_BUFFERED { return(T_ROWS_BUFFERED); } ROWS_DISPLAYED { return(T_ROWS_DISPLAYED); } SHOW_KEY { return(T_SHOW_KEY); } SUCCESS_STEP { return(T_SUCCESS_STEP); } TABLE { return(T_TABLE); } TEXT { return(T_TEXT); } TITLE { return(T_TITLE); } TRIGGER_TYPE { return(T_TRIGGER_TYPE); } UNIQUE_KEY { return(T_UNIQUE_KEY); } UPDATE/{WS} { return(T_UPDATE); } UPDATE_KEY { return(T_UPDATE_KEY); } UPDATE_NULL { return(T_UPDATE_NULL); } UPPERCASE { return(T_UPPERCASE); } VALIDATION_UNIT { return(T_VALIDATION_UNIT); } VERTICAL_SCROLL_BAR { return(T_VERTICAL_SCROLL_BAR); } "=" { ReadValues(); return('='); } /* ** BUGGY! ** ** this is where the problem is... combining ** the decimal and hexadecimal integer patterns ** into one pattern with an or (|) avoids the ** core dump. */ <ASSIGN>(({D}*\.{D}+)|({D}+\.{D}*))([eE][+-]?{D}+)?{WS}*$ { ReadKeywords(); ++inputLineCount; fprintf(stderr, "REAL\n"); yylval.vReal = atof(yytext); return(T_REAL); } <ASSIGN>{D}+{WS}*$ { ReadKeywords(); ++inputLineCount; fprintf(stderr, "INTEGER\n"); yylval.vInteger = strtol(yytext, NULL, 0); return(T_INTEGER); } <ASSIGN>0[Xx]{D}+{WS}*$ { ReadKeywords(); ++inputLineCount; fprintf(stderr, "INTEGER\n"); yylval.vInteger = strtol(yytext, NULL, 0); return(T_INTEGER); } <ASSIGN>(([Oo][Nn])|([Oo][Ff][Ff])){WS}*$ { ReadKeywords(); ++inputLineCount; fprintf(stderr, "BOOLEAN\n"); yylval.vBoolean = (tolower(yytext[1]) == 'n') ? True : False; return(T_BOOLEAN); } <ASSIGN>"<<<" { ReadKeywords(); fprintf(stderr, "<<<\n"); yylval.vString = readValue(); return(T_STRING); } <ASSIGN>. { ReadKeywords(); fprintf(stderr, "STRING\n"); yylval.vString = readLine(yytext[0]); return(T_STRING); } . { return(yytext[0]); } %% int readEscapeCode() { int letter; switch (letter = inputRaw()) { case 'g': return('\007'); case 'b': return('\b'); case 'f': return('\f'); case 'n': return('\n'); case 'r': return('\r'); case 't': return('\t'); case '\\': return('\\'); default: if (isdigit(letter)) { char buffer[10]; char *ptr = buffer; int base = 10; if (letter == '0') { letter = inputRaw(); if ((letter == 'x') || (letter == 'X')) { letter = inputRaw(); base = 16; } else { unput(letter); letter = '0'; base = 8; } } while ((isdigit(letter) || ((base == 16) && isxdigit(letter))) && (ptr - buffer < 3)) { *ptr++ = letter; letter = inputRaw(); } unput(letter); *ptr = 0; return((int)strtol(buffer, NULL, base)); } else { return(letter); } } } int readComment() { int letter; int level = 1; int commentStart = inputLineCount; while ((level > 0) && ((letter = inputRaw()) > 0)) { if (letter == '*') { if (inputRaw() == '/') { --level; } } else if (letter == '\n') { ++inputLineCount; } else if (letter == '/') { if (inputRaw() == '*') { ++level; } } } if (level == 0) { return(1); } else { fprintf(stderr, "file \"%s\": line %d: syntax error: unterminated comment\n", inputFileName, commentStart); return(0); } } char *readString(quote) int quote; { static char buffer[MAX_VALUE_LEN]; int stringStart = inputLineCount; char *ptr = buffer; while ((*ptr = inputRaw()) > 0) { if (*ptr == quote) { *ptr = 0; return(buffer); } else if (*ptr == '\\') { *ptr = (char)readEscapeCode(); } else if (*ptr == '\n') { ++inputLineCount; } if (++ptr - buffer >= MAX_VALUE_LEN) { fprintf(stderr, "file \"%s\": line %d: syntax error: string too long\n", inputFileName, stringStart); *buffer = 0; return(buffer); } } fprintf(stderr, "file \"%s\": line %d: syntax error: unterminated string?\n", inputFileName, stringStart); *buffer = 0; return(buffer); } char *readValue() { static char buffer[MAX_VALUE_LEN]; int stringStart = inputLineCount; char *ptr = buffer; int letter; int foundTerminator = 0; while (((letter = inputRaw()) > 0) && (isspace(letter))) ; unput(letter); while ((*ptr = inputRaw()) > 0) { if (*ptr == '<') { if (++foundTerminator >= 3) { *ptr = 0; return(buffer); } continue; } else { if (foundTerminator) { while (foundTerminator--) { *ptr++ = '<'; } } if (*ptr == '\n') { ++inputLineCount; } } if (++ptr - buffer >= MAX_VALUE_LEN) { fprintf(stderr, "file \"%s\": line %d: syntax error: string too long\n", inputFileName, stringStart); *buffer = 0; return(buffer); } } fprintf(stderr, "file \"%s\": line %d: syntax error: unterminated string?\n", inputFileName, stringStart); *buffer = 0; return(buffer); } char *readLine(letter) int letter; { static char buffer[MAX_VALUE_LEN]; char *ptr = buffer; while ((isspace(letter)) && ((letter = inputRaw()) > 0)) ; unput(letter); while ((*ptr = inputRaw()) > 0) { if (*ptr == '\n') { unput(*ptr); do { --ptr; } while ((isspace(*ptr)) && (ptr >= buffer)); if (ptr >= buffer) { *(ptr + 1) = 0; } else { *buffer = 0; } return(buffer); } else { ++ptr; } } fprintf(stderr, "file \"%s\": line %d: syntax error: line does not end in carriage return\n", inputFileName, inputLineCount); *buffer = 0; return(buffer); } int unput(c) int c; { extern char *yysptr; *yysptr++ = yytchar = c; } int inputRaw() { yytchar = (yysptr > yysbuf) ? *--yysptr : getc(yyin); return((yytchar == EOF) ? 0 : yytchar); } int inputUpper() { yytchar = (yysptr > yysbuf) ? *--yysptr : getc(yyin); return((yytchar == EOF) ? 0 : toupper(yytchar)); }