Added alternate lexer
authormichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 19 Aug 2000 21:58:54 +0000 (21:58 +0000)
committermichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 19 Aug 2000 21:58:54 +0000 (21:58 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@326 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/Makefile.in
src/SDCCast.c
src/SDCCerr.c
src/SDCCglue.c
src/SDCCmain.c
src/SDCCmem.c
src/SDCCsymt.c
src/altlex.c
src/reswords.gperf [new file with mode: 0644]

index 5fd7f0f6aff5f76d1b65b036a9f09b1c5d4f01c0..85e870b15b20bfdbf1ee243189c207a627a1f884 100644 (file)
@@ -6,6 +6,8 @@ PRJDIR          = ..
 
 include $(PRJDIR)/Makefile.common
 
+USE_ALT_LEX    = 0
+
 PORTS          = mcs51 z80 avr ds390
 PORT_LIBS      = $(PORTS:%=%/port.a)
 
@@ -20,13 +22,21 @@ ifdef SDCC_SUB_VERSION
 CFLAGS         += -DSDCC_SUB_VERSION_STR=\"$(SDCC_SUB_VERSION)\"
 endif
 
-OBJECTS        = SDCCy.o SDCClex.o SDCCerr.o SDCChasht.o SDCCmain.o \
+OBJECTS        = SDCCy.o SDCCerr.o SDCChasht.o SDCCmain.o \
                  SDCCsymt.o SDCCopt.o SDCCast.o SDCCmem.o SDCCval.o \
                  SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \
                  SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \
                  SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o spawn.o \
                  asm.o
 
+SPECIAL                = SDCCy.h 
+ifeq ($(USE_ALT_LEX), 1)
+OBJECTS                += altlex.o
+SPECIAL                += reswords.h
+else
+OBJECTS                += SDCClex.o
+endif
+
 SOURCES                = $(patsubst %.o,%.c,$(OBJECTS))
 
 TARGET         = $(PRJDIR)/bin/sdcc
@@ -73,7 +83,7 @@ installdirs:
 # ---------------------
 dep: Makefile.dep
 
-Makefile.dep: $(SOURCES) *.h $(PRJDIR)/*.h
+Makefile.dep: $(SOURCES) $(SPECIAL) *.h $(PRJDIR)/*.h
        $(CPP) $(CPPFLAGS) $(M_OR_MM) $(SOURCES) >Makefile.dep
 
 include Makefile.dep
@@ -88,6 +98,11 @@ $(TARGET): $(OBJECTS) $(PORT_LIBS)
 .c.o:
        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
 
+reswords.h: reswords.gperf Makefile
+       gperf -o -k1,2,4 -t -C -N is_reserved_word $< > $@
+
+altlex.o: altlex.c SDCCy.h reswords.h
+
 SDCCy.h: SDCCy.c
 
 SDCCy.c: SDCC.y
index bf8f2f60cacafeea8da012e5b427222d7e0909fe..cfa68e040219774a5e2e6f8444d669321787e816 100644 (file)
@@ -3639,7 +3639,7 @@ ast  *createFunction   (symbol  *name,   ast  *body )
     addSet(&operKeyReset,name);
     applyToSet(operKeyReset,resetParmKey);
        
-    if (options.debug)
+    if (options.debug && !options.nodebug)
        cdbStructBlock(1,cdbFile);
 
     cleanUpLevel(LabelTab,0);
index 0ad85971a1be3d50992524b6235e24fab462dca7..d2e770548a0820f533066673b1080ea202a84f28 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "common.h"
 
-#define USE_STDOUT_FOR_ERRORS          0
+#define USE_STDOUT_FOR_ERRORS          1
 
 #if USE_STDOUT_FOR_ERRORS
 #define ERRSINK                stdout
@@ -156,25 +156,28 @@ struct  {
 { WARNING,"warning *** Indirect call to a banked function not implemented.\n"},
 { WARNING,"warning *** Model '%s' not supported for %s, ignored.\n"},
 { WARNING,"warning *** Both banked and nonbanked attributes used.  nonbanked wins.\n"},
-{ WARNING,"warning *** Both banked and static used.  static wins.\n"},
+{ WARNING,"warning *** Both banked and static used.  static wins.\n"}
 };
 
+void   vwerror (int errNum, va_list marker)
+{
+    if ( ErrTab[errNum].errType== ERROR )
+       fatalError++ ;
+    
+    if ( filename && lineno ) {
+       fprintf(ERRSINK, "%s(%d):",filename,lineno);
+    }
+    vfprintf(ERRSINK, ErrTab[errNum].errText,marker);
+}
+
 /****************************************************************************/
 /* werror - writes an error to the listing file & to standarderr           */
 /****************************************************************************/
 void   werror (int errNum, ... )
 {
-       va_list marker;
-
-       
-       if ( ErrTab[errNum].errType== ERROR )
-               fatalError++ ;
-       
-       if ( filename && lineno ) {
-               fprintf(ERRSINK, "%s(%d):",filename,lineno);
-       }
-       va_start(marker,errNum);
-       vfprintf(ERRSINK, ErrTab[errNum].errText,marker);
-       va_end( marker );
+    va_list    marker;
+    va_start(marker,errNum);
+    vwerror(errNum, marker);
+    va_end( marker );
 }
 
index 448034e8ea3775cc329cf45b471780cdefd3b431..3b329f912c3d6d5b4d70c21a47b21813074fd947 100644 (file)
@@ -1032,7 +1032,7 @@ void glue ()
     
     addSetHead(&tmpfileSet,ovrFile);
     /* print the global struct definitions */
-    if (options.debug)
+    if (options.debug && !options.nodebug)
        cdbStructBlock (0,cdbFile);
 
     vFile = tempfile();
index 66b52605bab2f1ecd7149fbf0473fbd223ede8ba..9f42bb5dc0ca6e2c046b97927dcd2359c895fbd2 100644 (file)
@@ -118,6 +118,7 @@ char    *preOutName;
 #define OPTION_NOPEEP      "-no-peep"
 #define OPTION_ASMPEEP     "-peep-asm"
 #define OPTION_DEBUG       "-debug"
+#define OPTION_NODEBUG    "-nodebug"
 #define OPTION_VERSION     "-version"
 #define OPTION_STKAFTRDATA "-stack-after-data"
 #define OPTION_PREPROC_ONLY "-preprocessonly"
@@ -654,6 +655,11 @@ int   parseCmdLine ( int argc, char **argv )
                 continue;
            }
 
+           if (strcmp(&argv[i][1],OPTION_NODEBUG) == 0) {
+               options.nodebug = 1;            
+                continue;
+           }
+
            if (strcmp(&argv[i][1],OPTION_NOREGPARMS) == 0) {
                options.noregparms = 1;         
                 continue;
@@ -1028,7 +1034,7 @@ int   parseCmdLine ( int argc, char **argv )
        options.xstack_loc = options.xdata_loc ;
 
     /* if debug option is set the open the cdbFile */
-    if (/* options.debug && */ srcFileName) {
+    if (!options.nodebug && srcFileName) {
        sprintf(cdbfnbuf,"%s.cdb",srcFileName);
        if ((cdbFile = fopen(cdbfnbuf,"w")) == NULL)
            werror(E_FILE_OPEN_ERR,cdbfnbuf);
@@ -1338,7 +1344,7 @@ int main ( int argc, char **argv , char **envp)
 {
     /* turn all optimizations off by default */
     memset(&optimize,0,sizeof(struct optimize));
-    
+
     /*printVersionInfo ();*/
 
     _findPort(argc, argv);
index ca4eff72c20b6d5fa767df5df18348adb44f4cf9..b3c8381f50cfae85bac5f6e1ad5e92e08ee72b86 100644 (file)
@@ -865,7 +865,7 @@ void redoStackOffsets ()
 
     /* if the debug option is set then output the
        symbols to the map file */
-    if (options.debug) {
+    if (options.debug && !options.nodebug) {
        for (sym = setFirstItem(istack->syms); sym;
             sym = setNextItem(istack->syms))
            cdbSymbol(sym,cdbFile,FALSE,FALSE);
index 393e3c97b6b7948050fe99229dd6e05dc369ab56..7ef86605e5084e1d34543598d8ca5455999cdc89 100644 (file)
@@ -1846,7 +1846,8 @@ void cdbStructBlock (int block , FILE *of)
     int i ;
     bucket **table = StructTab;
     bucket  *chain;
-    
+    wassert(of);
+
     /* go thru the entire  table  */
     for ( i = 0 ; i < 256; i++ ) {
        for ( chain = table[i]; chain ; chain = chain->next ) {
index da1862bdf97880e4579965a903d056f84a7c203e..572826b6edc2b1a4e07de233756cf5d700debb8d 100644 (file)
@@ -3,8 +3,11 @@
     In development - ie messy and just plain wrong.
 */
 #include "common.h"
+#include "reswords.h"
 #include <assert.h>
 
+#define DUMP_OUTPUT            0
+
 FILE *yyin;
 
 int yylineno;
@@ -48,6 +51,27 @@ char linebuf[10000];
 int linepos, linelen;
 
 #define INLINE inline
+#define ERRSINK stdout
+
+extern int fatalError ;
+extern int lineno ;
+extern char *filename;
+
+static void error(const char *sz, ...)
+{
+    va_list ap;
+    fatalError++;
+    
+    if ( filename && lineno ) {
+       fprintf(ERRSINK, "%s(%d):",filename,lineno);
+    }
+    fprintf(ERRSINK, "error:");
+    va_start(ap, sz);
+    vfprintf(ERRSINK, sz, ap);
+    va_end(ap);
+    fprintf(ERRSINK, "\n");
+    fflush(ERRSINK);
+}
 
 static int underflow(void)
 {
@@ -81,7 +105,7 @@ static int INLINE yungetc(int c)
 #define ISALNUM(_a)    isalnum(_a)
 #define ISHEX(_a)      isalnum(_a)
 
-char *stringLiteral (void)
+static char *stringLiteral (void)
 {
     static char line[1000];
     int ch;
@@ -125,7 +149,7 @@ char *stringLiteral (void)
     return line;
 }
 
-void discard_comments(int type)
+static void discard_comments(int type)
 {
     int c;
     if (type == '*') {
@@ -141,217 +165,52 @@ void discard_comments(int type)
        } while (1);
     }
     else if (type == '/') {
-       while (c != '\n' && c != EOF) {
+       do {
            c = GETC();
-       }
+       } while (c != '\n' && c != EOF);
     }
     else {
        assert(0);
     }
 }
 
-#define TKEYWORD(_a)   return _a
-
-int check_token(const char *sz)
+/* will return 1 if the string is a part
+   of a target specific keyword */
+static int isTargetKeyword(const char *s)
 {
-    if (!strcmp(sz, "at")) {
-       TKEYWORD(AT)  ; }
+    int i;
     
-    else if (!strcmp(sz, "auto")) {
-        return(AUTO); }
-    
-    else if (!strcmp(sz, "bit")) {
-        TKEYWORD(BIT) ; }
+    if (port->keywords == NULL)
+       return 0;
+    for ( i = 0 ; port->keywords[i] ; i++ ) {
+       if (strcmp(port->keywords[i],s) == 0)
+           return 1;
+    }
     
-    else if (!strcmp(sz, "break")) {
-        return(BREAK); }
-
-    else if (!strcmp(sz, "case")) {
-        return(CASE); }
-
-    else if (!strcmp(sz, "char")) {
-        return(CHAR); }
-
-    else if (!strcmp(sz, "code")) {
-        TKEYWORD(CODE); }
-
-    else if (!strcmp(sz, "const")) {
-        return(CONST); }
-
-    else if (!strcmp(sz, "continue")) {
-        return(CONTINUE); }
-
-    else if (!strcmp(sz, "critical")) {
-        TKEYWORD(CRITICAL); } 
-
-    else if (!strcmp(sz, "data")) {
-        TKEYWORD(DATA);   }
-
-    else if (!strcmp(sz, "default")) {
-        return(DEFAULT); }
-
-    else if (!strcmp(sz, "do")) {
-        return(DO); }
-
-    else if (!strcmp(sz, "double")) {
-        werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
-
-    else if (!strcmp(sz, "else")) {
-        return(ELSE); }
-
-    else if (!strcmp(sz, "enum")) {
-        return(ENUM); }
-
-    else if (!strcmp(sz, "extern")) {
-        return(EXTERN); }
-
-    else if (!strcmp(sz, "far")) {
-        TKEYWORD(XDATA);  }
-
-    else if (!strcmp(sz, "eeprom")) {
-        TKEYWORD(EEPROM);  }
-
-    else if (!strcmp(sz, "float")) {
-        return(FLOAT); }
-
-    else if (!strcmp(sz, "flash")) {
-        TKEYWORD(CODE);}
-
-    else if (!strcmp(sz, "for")) {
-        return(FOR); }
-
-    else if (!strcmp(sz, "goto")) {
-        return(GOTO); }
-
-    else if (!strcmp(sz, "idata")) {
-        TKEYWORD(IDATA);}
-
-    else if (!strcmp(sz, "if")) {
-        return(IF); }
-
-    else if (!strcmp(sz, "int")) {
-        return(INT); }
-
-    else if (!strcmp(sz, "interrupt")) {
-        return(INTERRUPT);}
-
-    else if (!strcmp(sz, "nonbanked")) {
-        TKEYWORD(NONBANKED);}
-
-    else if (!strcmp(sz, "banked")) {
-        TKEYWORD(BANKED);}
-
-    else if (!strcmp(sz, "long")) {
-        return(LONG); }
-
-    else if (!strcmp(sz, "near")) {
-        TKEYWORD(DATA);}
-
-    else if (!strcmp(sz, "pdata")) {
-        TKEYWORD(PDATA); }
-
-    else if (!strcmp(sz, "reentrant")) {
-        TKEYWORD(REENTRANT);}
-
-    else if (!strcmp(sz, "register")) {
-        return(REGISTER); }
-
-    else if (!strcmp(sz, "return")) {
-        return(RETURN); }
-
-    else if (!strcmp(sz, "sfr")) {
-        TKEYWORD(SFR)  ; }
-
-    else if (!strcmp(sz, "sbit")) {
-        TKEYWORD(SBIT) ; }
-
-    else if (!strcmp(sz, "short")) {
-        return(SHORT); }
-
-    else if (!strcmp(sz, "signed")) {
-        return(SIGNED); }
-
-    else if (!strcmp(sz, "sizeof")) {
-        return(SIZEOF); }
-
-    else if (!strcmp(sz, "sram")) {
-        TKEYWORD(XDATA);}
-
-    else if (!strcmp(sz, "static")) {
-        return(STATIC); }
-
-    else if (!strcmp(sz, "struct")) {
-        return(STRUCT); }
-
-    else if (!strcmp(sz, "switch")) {
-        return(SWITCH); }
-
-    else if (!strcmp(sz, "typedef")) {
-        return(TYPEDEF); }
-
-    else if (!strcmp(sz, "union")) {
-        return(UNION); }
-
-    else if (!strcmp(sz, "unsigned")) {
-        return(UNSIGNED); }
-
-    else if (!strcmp(sz, "void")) {
-        return(VOID); }
-
-    else if (!strcmp(sz, "volatile")) {
-        return(VOLATILE); }
-
-    else if (!strcmp(sz, "using")) {
-        TKEYWORD(USING); }
-
-    else if (!strcmp(sz, "while")) {
-        return(WHILE); }
-
-    else if (!strcmp(sz, "xdata")) {
-        TKEYWORD(XDATA); }
-
-    else if (!strcmp(sz, "_data")) {
-        TKEYWORD(_NEAR); }
-
-    else if (!strcmp(sz, "_code")) {
-        TKEYWORD(_CODE); }
-
-    else if (!strcmp(sz, "_eeprom")) {
-        TKEYWORD(_EEPROM); }
-
-    else if (!strcmp(sz, "_flash")) {
-        TKEYWORD(_CODE); }
-
-    else if (!strcmp(sz, "_generic")) {
-        TKEYWORD(_GENERIC); }
-
-    else if (!strcmp(sz, "_near")) {
-        TKEYWORD(_NEAR); }
-
-    else if (!strcmp(sz, "_sram")) {
-        TKEYWORD(_XDATA);}
-
-    else if (!strcmp(sz, "_xdata")) {
-        TKEYWORD(_XDATA);}
-
-    else if (!strcmp(sz, "_pdata")) {
-        TKEYWORD(_PDATA); }
+    return 0;
+}
 
-    else if (!strcmp(sz, "_idata")) {
-        TKEYWORD(_IDATA); }
+static int check_token(const char *sz)
+{
+    const struct reserved_words *p;
+    p = is_reserved_word(sz, strlen(sz));
+    if (p) {
+       if (!p->is_special || isTargetKeyword(sz))
+           return p->token;
+    }
 
     /* check if it is in the typedef table */
     if (findSym(TypedefTab,NULL,sz)) {
        strcpy(yylval.yychar,sz);
-       return (TYPE_NAME) ;
+       return TYPE_NAME;
     }
     else   {
        strcpy (yylval.yychar,sz);
-       return(IDENTIFIER);
+       return IDENTIFIER;
     }
 }
 
-int yylex(void)
+static int _yylex(void)
 {
     int c;
     char line[128];
@@ -429,8 +288,27 @@ int yylex(void)
            yylval.val = strVal(p);
            return(STRING_LITERAL);
        case '\'':
-           /* ie '\n' */
-           break;
+           /* Possible formats:
+              ['\n', '\\', '\'', '\"'...]
+              ['a'...]
+           */
+           p = line;
+           *p++ = c;
+           c = GETC();
+           if (c == '\\') {
+               *p++ = c;
+               c = GETC();
+               /* Fall through */
+           }
+           *p++ = c;
+           c = GETC();
+           *p++ = c;
+           *p = '\0';
+           if (c != '\'') {
+               error("Unrecognised character constant %s", line);
+           }
+           yylval.val = charVal(line);
+           return CONSTANT;
        case '#':
            /* Assume a pragma and toast the rest of the line. */
            c = GETC();
@@ -449,9 +327,108 @@ int yylex(void)
        case '<':
        case '>':
        case '^':
-       case '|':
+       case '|': {
            /* Cases which can be compounds */
-           return c;
+           /* The types and classes of composites are:
+              >>= <<=
+              += -= *= /= %= &= ^= |=
+              >> << ++ --
+              && ||
+              <= >= == !=
+              ->
+              So a composite started by char 'x' can be:
+                1. Followed by itself then an equals
+                2. Followed by itself
+                3. Followed by an equals
+                4. Be a '->'
+                5. Be by itself
+           */
+           int next = GETC();
+           /* Class 1 and 2 */
+           if (next == c) {
+               next = GETC();
+               /* Class 1 */
+               if (next == '=') {
+                   switch (c) {
+                   case '>':   // >>=
+                       yylval.yyint = RIGHT_ASSIGN;
+                       return RIGHT_ASSIGN;
+                   case '<':   // <<=
+                       yylval.yyint = LEFT_ASSIGN;
+                       return LEFT_ASSIGN;
+                   default:
+                       error("Unrecognised token %c%c=", c, c);
+                   }
+               }
+               else {
+                   /* Push the next char back on and find the class */
+                   UNGETC(next);
+                   /* Case 2 */
+                   switch (c) {
+                   case '>':   // >>
+                       return RIGHT_OP;
+                   case '<':   // <<
+                       return LEFT_OP;
+                   case '+':
+                       return INC_OP;
+                   case '-':
+                       return DEC_OP;
+                   case '&':
+                       return AND_OP;
+                   case '|':
+                       return OR_OP;
+                   case '=':
+                       return EQ_OP;
+                   default:
+                       error("Unrecognised token %c%c", c, c);
+                   }
+               }
+           }
+           /* Case 3 */
+           else if (next == '=') {
+               int result = 0;
+               switch (c) {
+               case '+':
+                   result = ADD_ASSIGN; break;
+               case '-':
+                   result = SUB_ASSIGN; break;
+               case '*':
+                   result = MUL_ASSIGN; break;
+               case '/':
+                   result = DIV_ASSIGN; break;
+               case '%':
+                   result = MOD_ASSIGN; break;
+               case '&':
+                   result = AND_ASSIGN; break;
+               case '^':
+                   result = XOR_ASSIGN; break;
+               case '|':
+                   result = OR_ASSIGN; break;
+               case '<':
+                   result = LE_OP; break;
+               case '>':
+                   result = GE_OP; break;
+               case '!':
+                   result = NE_OP; break;
+               default:
+                   error("Unrecognised token %c=", c);
+               }
+               if (result) {
+                   yylval.yyint = result;
+                   return result;
+               }
+           }
+           /* Case 4 */
+           else if (c == '-' && next == '>') {
+               return PTR_OP;
+           }
+           /* Case 5 */
+           else {
+               UNGETC(next);
+               return c;
+           }
+           break;
+       }
        case '{':
            NestLevel++;
            return c;
@@ -467,19 +444,340 @@ int yylex(void)
                }
            }
            UNGETC(c);
-           /* Fall through */
+           return '.';
+       case '[': case ']':
+           return c;
        case ',':
        case ':':
        case '(': case ')':
-       case '[': case ']':
        case '~':
        case '?':
+       case ';':
            /* Special characters that cant be part of a composite */
            return c;
        default:
-           printf("Unhandled char %c\n", c);
+           error("Unhandled char %c", c);
        }
        c = GETC();
     }
     return 0;
 }
+
+#define ENTRY(_a)      case (_a): printf(#_a); break;
+
+int yylex(void)
+{
+    int ret = _yylex();
+#if DUMP_OUTPUT
+    static int lastpos = 0;
+    char tmp;
+
+    printf("Returning ");
+    switch (ret) {
+       /* Wrapper */
+       ENTRY(IDENTIFIER);
+       ENTRY(TYPE_NAME);
+       ENTRY(CONSTANT);
+       ENTRY(STRING_LITERAL);
+       ENTRY(SIZEOF);
+       ENTRY(PTR_OP);
+       ENTRY(INC_OP);
+       ENTRY(DEC_OP);
+       ENTRY(LEFT_OP);
+       ENTRY(RIGHT_OP);
+       ENTRY(LE_OP);
+       ENTRY(GE_OP);
+       ENTRY(EQ_OP);
+       ENTRY(NE_OP);
+       ENTRY(AND_OP);
+       ENTRY(OR_OP);
+       ENTRY(MUL_ASSIGN);
+       ENTRY(DIV_ASSIGN);
+       ENTRY(MOD_ASSIGN);
+       ENTRY(ADD_ASSIGN);
+       ENTRY(SUB_ASSIGN);
+       ENTRY(LEFT_ASSIGN);
+       ENTRY(RIGHT_ASSIGN);
+       ENTRY(AND_ASSIGN);
+       ENTRY(XOR_ASSIGN);
+       ENTRY(OR_ASSIGN);
+       ENTRY(TYPEDEF);
+       ENTRY(EXTERN);
+       ENTRY(STATIC);
+       ENTRY(AUTO);
+       ENTRY(REGISTER);
+       ENTRY(CODE);
+       ENTRY(EEPROM);
+       ENTRY(INTERRUPT);
+       ENTRY(SFR);
+       ENTRY(AT);
+       ENTRY(SBIT);
+       ENTRY(REENTRANT);
+       ENTRY(USING);
+       ENTRY(XDATA);
+       ENTRY(DATA);
+       ENTRY(IDATA);
+       ENTRY(PDATA);
+       ENTRY(VAR_ARGS);
+       ENTRY(CRITICAL);
+       ENTRY(NONBANKED);
+       ENTRY(BANKED);
+       ENTRY(CHAR);
+       ENTRY(SHORT);
+       ENTRY(INT);
+       ENTRY(LONG);
+       ENTRY(SIGNED);
+       ENTRY(UNSIGNED);
+       ENTRY(FLOAT);
+       ENTRY(DOUBLE);
+       ENTRY(CONST);
+       ENTRY(VOLATILE);
+       ENTRY(VOID);
+       ENTRY(BIT);
+       ENTRY(STRUCT);
+       ENTRY(UNION);
+       ENTRY(ENUM);
+       ENTRY(ELIPSIS);
+       ENTRY(RANGE);
+       ENTRY(FAR);
+       ENTRY(_XDATA);
+       ENTRY(_CODE);
+       ENTRY(_GENERIC);
+       ENTRY(_NEAR);
+       ENTRY(_PDATA);
+       ENTRY(_IDATA);
+       ENTRY(_EEPROM);
+       ENTRY(CASE);
+       ENTRY(DEFAULT);
+       ENTRY(IF);
+       ENTRY(ELSE);
+       ENTRY(SWITCH);
+       ENTRY(WHILE);
+       ENTRY(DO);
+       ENTRY(FOR);
+       ENTRY(GOTO);
+       ENTRY(CONTINUE);
+       ENTRY(BREAK);
+       ENTRY(RETURN);
+       ENTRY(INLINEASM);
+       ENTRY(IFX);
+       ENTRY(ADDRESS_OF);
+       ENTRY(GET_VALUE_AT_ADDRESS);
+       ENTRY(SPIL);
+       ENTRY(UNSPIL);
+       ENTRY(GETHBIT);
+       ENTRY(BITWISEAND);
+       ENTRY(UNARYMINUS);
+       ENTRY(IPUSH);
+       ENTRY(IPOP);
+       ENTRY(PCALL);
+       ENTRY(ENDFUNCTION);
+       ENTRY(JUMPTABLE);
+       ENTRY(RRC);
+       ENTRY(RLC);
+       ENTRY(CAST);
+       ENTRY(CALL);
+       ENTRY(PARAM);
+       ENTRY(NULLOP);
+       ENTRY(BLOCK);
+       ENTRY(LABEL);
+       ENTRY(RECEIVE);
+       ENTRY(SEND);
+    default:
+       printf("default: %c", ret);
+    }
+    tmp = linebuf[linepos];
+    linebuf[linepos] = '\0';
+    printf(" for %s (%u bytes)\n", linebuf + lastpos, linepos - lastpos);
+    linebuf[linepos] = tmp;
+    lastpos = linepos;
+    fflush(stdout);
+#endif
+    return ret;
+}
+
+#define TEST(_a)       (_a) ? (void)0 : printf("Test %s failed\n", #_a);
+
+int altlex_testparse(const char *input)
+{
+    /* Fiddle with the read-ahead buffer to insert ourselves */
+    strcpy(linebuf, input);
+    linelen = strlen(linebuf)+1;
+    linepos = 0;
+    
+    return yylex();
+}
+
+int altlex_testchar(const char *input)
+{
+    value *val;
+    if (altlex_testparse(input) != CONSTANT)
+       return -2;
+    val = yylval.val;
+    if (val->type->class != SPECIFIER)
+       return -3;
+    if (SPEC_NOUN(val->type) != V_CHAR)
+       return -4;
+    if (SPEC_SCLS(val->type) != S_LITERAL)
+       return -5;
+    return SPEC_CVAL(val->type).v_int;
+}
+
+int altlex_testnum(const char *input)
+{
+    value *val;
+    if (altlex_testparse(input) != CONSTANT)
+       return -2;
+    val = yylval.val;
+    if (val->type->class != SPECIFIER)
+       return -3;
+    if (SPEC_NOUN(val->type) != V_INT)
+       return -4;
+    if (SPEC_SCLS(val->type) != S_LITERAL)
+       return -5;
+    if (SPEC_USIGN(val->type))
+       return SPEC_CVAL(val->type).v_uint;
+    else
+       return SPEC_CVAL(val->type).v_int;
+}
+
+int altlex_runtests(void)
+{
+    /* These conditions are ripped directly from SDCC.lex */
+    /* First check the parsing of the basic tokens */
+    TEST(altlex_testparse(">>=") == RIGHT_ASSIGN);
+    TEST(altlex_testparse("<<=") == LEFT_ASSIGN);
+    TEST(altlex_testparse("+=") == ADD_ASSIGN);
+    TEST(altlex_testparse("-=") == SUB_ASSIGN);
+    TEST(altlex_testparse("*=") == MUL_ASSIGN);
+    TEST(altlex_testparse("/=") == DIV_ASSIGN);
+    TEST(altlex_testparse("%=") == MOD_ASSIGN);
+    TEST(altlex_testparse("&=") == AND_ASSIGN);
+    TEST(altlex_testparse("^=") == XOR_ASSIGN);
+    TEST(altlex_testparse("|=") == OR_ASSIGN);
+    TEST(altlex_testparse(">>") == RIGHT_OP);
+    TEST(altlex_testparse("<<") == LEFT_OP);
+    TEST(altlex_testparse("++") == INC_OP);
+    TEST(altlex_testparse("--") == DEC_OP);
+    TEST(altlex_testparse("->") == PTR_OP);
+    TEST(altlex_testparse("&&") == AND_OP);
+    TEST(altlex_testparse("||") == OR_OP);
+    TEST(altlex_testparse("<=") == LE_OP);
+    TEST(altlex_testparse(">=") == GE_OP);
+    TEST(altlex_testparse("==") == EQ_OP);
+    TEST(altlex_testparse("!=") == NE_OP);
+    TEST(altlex_testparse(";") == ';');
+    TEST(altlex_testparse("{") == '{');
+    TEST(altlex_testparse("}") == '}');
+    TEST(altlex_testparse(",") == ',');
+    TEST(altlex_testparse(":") == ':');
+    TEST(altlex_testparse("=") == '=');
+    TEST(altlex_testparse("(") == '(');
+    TEST(altlex_testparse(")") == ')');
+    TEST(altlex_testparse("[") == '[');
+    TEST(altlex_testparse("]") == ']');
+    TEST(altlex_testparse(".") == '.');
+    TEST(altlex_testparse("&") == '&');
+    TEST(altlex_testparse("!") == '!');
+    TEST(altlex_testparse("~") == '~');
+    TEST(altlex_testparse("-") == '-');
+    TEST(altlex_testparse("+") == '+');
+    TEST(altlex_testparse("*") == '*');
+    TEST(altlex_testparse("/") == '/');
+    TEST(altlex_testparse("%") == '%');
+    TEST(altlex_testparse("<") == '<');
+    TEST(altlex_testparse(">") == '>');
+    TEST(altlex_testparse("^") == '^');
+    TEST(altlex_testparse("|") == '|');
+    TEST(altlex_testparse("?") == '?');
+
+    /* Now some character constants */
+    TEST(altlex_testchar("'1'") == '1');
+    TEST(altlex_testchar("'a'") == 'a');
+    TEST(altlex_testchar("'A'") == 'A');
+    TEST(altlex_testchar("'z'") == 'z');
+    TEST(altlex_testchar("'Z'") == 'Z');
+    TEST(altlex_testchar("'\n'") == '\n');
+    TEST(altlex_testchar("'\\\\'") == '\\');
+    TEST(altlex_testchar("'\\''") == '\'');
+
+    /* And some numbers */
+    TEST(altlex_testnum("0") == 0);
+    TEST(altlex_testnum("1") == 1);
+    TEST(altlex_testnum("075") == 075);
+    TEST(altlex_testnum("0xfeed") == 0xfeed);
+    TEST(altlex_testnum("0xFEED") == 0xFEED);
+    TEST(altlex_testnum("0x00005678") == 0x5678);
+
+    /* Keywords */
+    TEST(altlex_testparse("auto") == AUTO);
+    TEST(altlex_testparse("break") == BREAK);
+    TEST(altlex_testparse("case") == CASE);
+    TEST(altlex_testparse("char") == CHAR);
+    TEST(altlex_testparse("const") == CONST);
+    TEST(altlex_testparse("continue") == CONTINUE);
+    TEST(altlex_testparse("default") == DEFAULT);
+    TEST(altlex_testparse("do") == DO);
+    /* Prints a warning */
+    //    TEST(altlex_testparse("double") == FLOAT);
+    TEST(altlex_testparse("else") == ELSE);
+    TEST(altlex_testparse("enum") == ENUM);
+    TEST(altlex_testparse("extern") == EXTERN);
+    TEST(altlex_testparse("float") == FLOAT);
+    TEST(altlex_testparse("for") == FOR);
+    TEST(altlex_testparse("goto") == GOTO);
+    TEST(altlex_testparse("if") == IF);
+    TEST(altlex_testparse("int") == INT);
+    TEST(altlex_testparse("interrupt") == INTERRUPT);
+    TEST(altlex_testparse("long") == LONG);
+    TEST(altlex_testparse("register") == REGISTER);
+    TEST(altlex_testparse("return") == RETURN);
+    TEST(altlex_testparse("short") == SHORT);
+    TEST(altlex_testparse("signed") == SIGNED);
+    TEST(altlex_testparse("sizeof") == SIZEOF);
+    TEST(altlex_testparse("static") == STATIC);
+    TEST(altlex_testparse("struct") == STRUCT);
+    TEST(altlex_testparse("switch") == SWITCH);
+    TEST(altlex_testparse("typedef") == TYPEDEF);
+    TEST(altlex_testparse("union") == UNION);
+    TEST(altlex_testparse("unsigned") == UNSIGNED);
+    TEST(altlex_testparse("void") == VOID);
+    TEST(altlex_testparse("volatile") == VOLATILE);
+    TEST(altlex_testparse("while") == WHILE);
+    TEST(altlex_testparse("...") == VAR_ARGS);
+
+#if 0
+    /* Platform specific keywords */
+    TEST(altlex_testparse("sram") ==)         { count(); TKEYWORD(XDATA);}
+    TEST(altlex_testparse("using") ==)        { count(); TKEYWORD(USING); }
+    TEST(altlex_testparse("near") ==)         { count(); TKEYWORD(DATA);}
+    TEST(altlex_testparse("at") ==)           { count(); TKEYWORD(AT)  ; }
+    TEST(altlex_testparse("bit") ==)          { count(); TKEYWORD(BIT) ; }
+    TEST(altlex_testparse("code") ==)         { count(); TKEYWORD(CODE); }
+    TEST(altlex_testparse("critical") ==)     { count(); TKEYWORD(CRITICAL); } 
+    TEST(altlex_testparse("data") ==)         { count(); TKEYWORD(DATA);   }
+    TEST(altlex_testparse("far") ==)          { count(); TKEYWORD(XDATA);  }
+    TEST(altlex_testparse("eeprom") ==)       { count(); TKEYWORD(EEPROM);  }
+    TEST(altlex_testparse("flash") ==)        { count(); TKEYWORD(CODE);}
+    TEST(altlex_testparse("idata") ==)        { count(); TKEYWORD(IDATA);}
+    TEST(altlex_testparse("nonbanked") ==)    { count(); TKEYWORD(NONBANKED);}
+    TEST(altlex_testparse("banked") ==)       { count(); TKEYWORD(BANKED);}
+    TEST(altlex_testparse("pdata") ==)        { count(); TKEYWORD(PDATA); }
+    TEST(altlex_testparse("reentrant") ==)    { count(); TKEYWORD(REENTRANT);}
+    TEST(altlex_testparse("sfr") ==)          { count(); TKEYWORD(SFR) ; }
+    TEST(altlex_testparse("sbit") ==)         { count(); TKEYWORD(SBIT)        ; }
+    TEST(altlex_testparse("xdata") ==)        { count(); TKEYWORD(XDATA); }
+    TEST(altlex_testparse("_data") ==)        { count(); TKEYWORD(_NEAR); }
+    TEST(altlex_testparse("_code") ==)        { count(); TKEYWORD(_CODE); }
+    TEST(altlex_testparse("_eeprom") ==)      { count(); TKEYWORD(_EEPROM); }
+    TEST(altlex_testparse("_flash") ==)       { count(); TKEYWORD(_CODE); }
+    TEST(altlex_testparse("_generic") ==)     { count(); TKEYWORD(_GENERIC); }
+    TEST(altlex_testparse("_near") ==)        { count(); TKEYWORD(_NEAR); }
+    TEST(altlex_testparse("_sram") ==)        { count(); TKEYWORD(_XDATA);}
+    TEST(altlex_testparse("_xdata") ==)       { count(); TKEYWORD(_XDATA);}
+    TEST(altlex_testparse("_pdata") ==)       { count(); TKEYWORD(_PDATA); }
+    TEST(altlex_testparse("_idata") ==)       { count(); TKEYWORD(_IDATA); }
+#endif
+
+    return 0;
+}
diff --git a/src/reswords.gperf b/src/reswords.gperf
new file mode 100644 (file)
index 0000000..651d581
--- /dev/null
@@ -0,0 +1,67 @@
+%{
+/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf  */ 
+%}
+struct reserved_words { const char *name; int token; bool is_special; };
+%%
+auto,          AUTO,           0
+break,         BREAK,          0
+case,          CASE,           0
+char,          CHAR,           0
+const,         CONST,          0
+continue,      CONTINUE,       0
+default,       DEFAULT,        0
+do,            DO,             0
+double,                FLOAT,          0
+else,          ELSE,           0
+enum,          ENUM,           0
+extern,                EXTERN,         0
+float,         FLOAT,          0
+for,           FOR,            0
+goto,          GOTO,           0
+if,            IF,             0
+int,           INT,            0
+interrupt,     INTERRUPT,      0
+long,          LONG,           0
+register,      REGISTER,       0
+return,                RETURN,         0
+short,         SHORT,          0
+signed,                SIGNED,         0
+sizeof,                SIZEOF,         0
+static,                STATIC,         0
+struct,                STRUCT,         0
+switch,                SWITCH,         0
+typedef,       TYPEDEF,        0
+union,         UNION,          0
+unsigned,      UNSIGNED,       0
+void,          VOID,           0
+volatile,      VOLATILE,       0
+while,         WHILE,          0
+_code,         _CODE,          1
+_eeprom,       _EEPROM,        1
+_flash,                _CODE,          1
+_generic,      _GENERIC,       1
+_near,         _NEAR,          1
+_sram,         _XDATA,         1
+_xdata,                _XDATA,         1
+_pdata,                _PDATA,         1
+_idata,                _IDATA,         1
+at,            AT,             1
+bit,           BIT,            1
+critical,      CRITICAL,       1
+data,          DATA,           1
+far,           XDATA,          1
+eeprom,                EEPROM,         1
+flash,         CODE,           1
+idata,         IDATA,          1
+nonbanked,     NONBANKED,      1
+banked,                BANKED,         1
+near,          DATA,           1
+pdata,         PDATA,          1
+reentrant,     REENTRANT,      1
+sfr,           SFR,            1
+sbit,          SBIT,           1
+sram,          XDATA,          1
+using,         USING,          1
+code,          CODE,           1
+xdata,         XDATA,          1
+_data,         _NEAR,          1