no bitfields yet
[fw/sdcc] / src / SDCC.lex
index a39f0c4fef4b5030a5967efa26c7dc6c9d93e65b..87d26948fdf1574858ccc215282e721e941f7861 100644 (file)
@@ -34,16 +34,16 @@ IS       (u|U|l|L)*
 #include <string.h>
 #include <ctype.h>
 #include "common.h"
-    
+#include "newalloc.h"
+#include "dbuf.h"
+
 char *stringLiteral();
 char *currFname;
 
-extern int lineno                      ;
+extern int lineno, column;
 extern char *filename ;
-extern char *fullSrcFileName ;
 int   yylineno = 1               ;
 void count()                     ;
-void comment();
 int process_pragma(char *);
 #undef yywrap
 
@@ -53,7 +53,8 @@ int yywrap YY_PROTO((void))
 }
 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
                                check_type(yytext))
-char asmbuff[MAX_INLINEASM]                    ;
+char *asmbuff=NULL;
+int asmbuffSize=0;
 char *asmp ;
 extern int check_type          ();
  extern int isTargetKeyword     ();
@@ -62,34 +63,43 @@ extern int processPragma    (char *);
 extern int printListing                (int   );
 struct optimize save_optimize ;
 struct options  save_options  ;
-
- enum {
-     P_SAVE = 1,
-     P_RESTORE ,
-     P_NOINDUCTION,
-     P_NOINVARIANT,
-     P_INDUCTION ,
-     P_STACKAUTO ,
-     P_NOJTBOUND ,
-     P_NOOVERLAY ,
-     P_NOGCSE    ,
-     P_CALLEE_SAVES,
-     P_EXCLUDE   ,
-     P_LOOPREV
- };
-
 %}
 %x asm
 %%
-"_asm"        {  count(); asmp = asmbuff ;BEGIN(asm) ;}
-<asm>"_endasm" { count()               ; 
-                  *asmp = '\0'                         ; 
-                  strcpy(yylval.yyinline,asmbuff)              ; 
-                  BEGIN(INITIAL)       ;
-                  return (INLINEASM)                   ; }
-<asm>.         { *asmp++ = yytext[0]   ; }
-<asm>\n        { count(); *asmp++ = '\n' ;}
-"/*"          { comment(); }
+"_asm"         {  
+  count(); 
+  asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
+  asmbuffSize=INITIAL_INLINEASM;
+  BEGIN(asm) ;
+}
+<asm>"_endasm" { 
+  count();
+  *asmp = '\0';
+  yylval.yyinline = strdup (asmbuff);
+  BEGIN(INITIAL);
+  return (INLINEASM);
+}
+<asm>.         { 
+  if (asmp-asmbuff >= asmbuffSize-2) {
+    // increase the buffersize with 50%
+    int size=asmp-asmbuff;
+    asmbuffSize=asmbuffSize*3/2;
+    asmbuff = realloc (asmbuff, asmbuffSize); 
+    asmp=asmbuff+size;
+  }
+  *asmp++ = yytext[0];
+}
+<asm>\n        { 
+  count(); 
+  if (asmp-asmbuff >= asmbuffSize-3) {
+    // increase the buffersize with 50%
+    int size=asmp-asmbuff;
+    asmbuffSize=asmbuffSize*3/2;
+    asmbuff = realloc (asmbuff, asmbuffSize); 
+    asmp=asmbuff+size;
+  }
+  *asmp++ = '\n' ;
+}
 "at"          { count(); TKEYWORD(AT)  ; }
 "auto"        { count(); return(AUTO); }
 "bit"         { count(); TKEYWORD(BIT) ; }
@@ -140,24 +150,18 @@ struct options  save_options  ;
 "void"         { count(); return(VOID); }
 "volatile"     { count(); return(VOLATILE); }
 "using"        { count(); TKEYWORD(USING); }
+"_naked"       { count(); TKEYWORD(NAKED); }
 "while"        { count(); return(WHILE); }
 "xdata"        { count(); TKEYWORD(XDATA); }
-"_data"               { count(); TKEYWORD(_NEAR); }
-"_code"               { count(); TKEYWORD(_CODE); }
-"_eeprom"      { count(); TKEYWORD(_EEPROM); }
-"_flash"       { count(); TKEYWORD(_CODE); }
-"_generic"     { count(); TKEYWORD(_GENERIC); }
-"_near"               { count(); TKEYWORD(_NEAR); }
-"_sram"        { count(); TKEYWORD(_XDATA);}
-"_xdata"       { count(); TKEYWORD(_XDATA);}
-"_pdata"       { count(); TKEYWORD(_PDATA); }
-"_idata"       { count(); TKEYWORD(_IDATA); }
 "..."         { count(); return(VAR_ARGS);}
+"__typeof"     { count(); return TYPEOF;}
+"_JavaNative"  { count(); TKEYWORD(JAVANATIVE);}
+"_overlay"     { count(); TKEYWORD(OVERLAY);}
 {L}({L}|{D})*  { count(); return(check_type()); }
 0[xX]{H}+{IS}? { count(); yylval.val = constVal(yytext); return(CONSTANT); }
 0{D}+{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
 {D}+{IS}?      { count(); yylval.val = constVal(yytext); return(CONSTANT); }
-'(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); }
+'(\\.|[^\\'])+' { count();yylval.val = charVal (yytext); return(CONSTANT); /* ' make syntax highliter happy */}
 {D}+{E}{FS}?   { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
 {D}*"."{D}+({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
 {D}+"."{D}*({E})?{FS}? { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
@@ -215,9 +219,17 @@ struct options  save_options  ;
 "\r\n"            { count(); }
 "\n"              { count(); }
 [ \t\v\f]      { count(); }
+\\ {
+  char ch=input();
+  if (ch!='\n') {
+    // that could have been removed by the preprocessor anyway
+    werror (W_STRAY_BACKSLASH, column);
+    unput(ch);
+  }
+}
 .                         { count()    ; }
 %%
-   
+
 int checkCurrFile ( char *s)
 {
     char lineNum[10]                   ;
@@ -245,8 +257,8 @@ int checkCurrFile ( char *s)
     /* set the current line number to   */
     /* line number if printFlag is on   */
     if (!*s) {         
-       yylineno = lNum ;
-       return 0;
+      lineno = yylineno = lNum ;
+      return 0;
     }
     
     /* if we have a filename then check */
@@ -254,256 +266,323 @@ int checkCurrFile ( char *s)
     /* get the currentfile name info    */
     s++ ;
 
-    if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
-           yylineno = lNum - 2;                                        
-           currFname = fullSrcFileName ;
+    /* in c1mode fullSrcFileName is NULL */
+    if ( fullSrcFileName &&
+         strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
+      lineno = yylineno = lNum;                                        
+      currFname = fullSrcFileName ;
     }  else {
        char *sb = s;
        /* mark the end of the filename */
        while (*s != '"') s++;
        *s = '\0';
-       ALLOC_ATOMIC(currFname,strlen(sb)+1);
-       strcpy(currFname,sb);
-       yylineno = lNum - 2;
+       currFname = strdup (sb);
+       lineno = yylineno = lNum;
     }
     filename = currFname ;
     return 0;
 }
     
-void comment()
-{
-       char c, c1;
-
-loop:
-       while ((c = input()) != '*' && c != 0)
-               if ( c == '\n')
-                       yylineno++ ;
-
-       if ((c1 = input()) != '/' && c != 0)  {
-               if ( c1 == '\n' )
-                       yylineno++ ;
-
-               unput(c1);
-               goto loop;
-   }
-
-}
-   
-   
-
 int column = 0;
 int plineIdx=0;
 
 void count()
 {
-       int i;
-       for (i = 0; yytext[i] != '\0'; i++)   {                         
-               if (yytext[i] == '\n')      {         
-                  column = 0;
-                  lineno = ++yylineno ;
-               }
-               else 
-                       if (yytext[i] == '\t')
-                               column += 8 - (column % 8);
-                       else
-                               column++;
-   }
-         
-   /* ECHO; */
+  int i;
+  for (i = 0; yytext[i] != '\0'; i++)   {                              
+    if (yytext[i] == '\n')      {         
+      column = 0;
+      lineno = ++yylineno ;
+    }
+    else 
+      if (yytext[i] == '\t')
+       column += 8 - (column % 8);
+      else
+       column++;
+  }
+  /* ECHO; */
 }
 
 int check_type()
 {
        /* check if it is in the typedef table */
        if (findSym(TypedefTab,NULL,yytext)) {
-               strcpy(yylval.yychar,yytext);
+               strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
                return (TYPE_NAME) ;
        }
        else   {
-               strcpy (yylval.yychar,yytext);
+               strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
                return(IDENTIFIER);
        }
 }
 
-char strLitBuff[2048]                  ;
+/*
+ * Change by JTV 2001-05-19 to not concantenate strings
+ * to support ANSI hex and octal escape sequences in string liteals 
+ */
 
-char *stringLiteral ()
+char *stringLiteral()
 {
-       int ch;
-       char *str = strLitBuff                  ;
-       
-       *str++ = '\"'                   ;
-       /* put into the buffer till we hit the */
-       /* first \" */
-       while (1) {
-
-          ch = input()                 ;
-          if (!ch)         break       ; /* end of input */
-         /* if it is a \ then everything allowed */
-         if (ch == '\\') {
-            *str++ = ch     ; /* backslash in place */
-            *str++ = input()           ; /* following char in place */
-            continue                   ;      /* carry on */
-            }
-            
-        /* if new line we have a new line break */
-        if (ch == '\n') break          ;
-        
-        /* if this is a quote then we have work to do */
-        /* find the next non whitespace character     */
-        /* if that is a double quote then carry on    */
-        if (ch == '\"') {
-        
-            while ((ch = input()) && isspace(ch)) ;
-            if (!ch) break             ; 
-            if (ch != '\"') {
-                 unput(ch)                     ;
-                 break                 ;
-                 }
-                 
-                 continue              ;
+#define STR_BUF_CHUNCK_LEN  1024
+  int ch;
+  static struct dbuf_s dbuf;
+  char buf[2];
+
+  if (dbuf.alloc == 0)
+    dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
+  else
+    dbuf_set_size(&dbuf, 0);
+
+
+  dbuf_append(&dbuf, "\"", 1);
+  /* put into the buffer till we hit the first \" */
+
+  while ((ch = input()) != 0) {
+    switch (ch) {
+    case '\\':
+      /* if it is a \ then escape char's are allowed */
+      ch = input();
+      if (ch == '\n') {
+        /* \<newline> is a continuator */
+        lineno = ++yylineno;
+        column = 0;
+      }
+      else {
+        buf[0] = '\\';
+        buf[1] = ch;
+        dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
+      }
+      break; /* carry on */
+
+    case '\n':
+      /* if new line we have a new line break, which is illegal */
+      werror(W_NEWLINE_IN_STRING);
+      dbuf_append(&dbuf, "\n", 1);
+      lineno = ++yylineno;
+      column = 0;
+      break;
+
+    case '"':
+      /* if this is a quote then we have work to do */
+      /* find the next non whitespace character     */
+      /* if that is a double quote then carry on    */
+      dbuf_append(&dbuf, "\"", 1);  /* Pass end of this string or substring to evaluator */
+      while ((ch = input()) && (isspace(ch) || ch=='\\')) {
+        switch (ch) {
+        case '\\':
+          if ((ch = input()) != '\n') {
+            werror(W_STRAY_BACKSLASH, column);
+            unput(ch);
+          }
+          else {
+            lineno = ++yylineno;
+            column = 0;
+          }
+          break;
+
+        case '\n':
+          yylineno++;
+          break;
         }
-       *str++  = ch;     
-     }  
-     *str++ = '\"'                     ;
-     *str = '\0';
-     return strLitBuff                 ;
-}
+      }
 
-void doPragma (int op, char *cp)
-{
-    switch (op) {
-    case P_SAVE:
-       memcpy(&save_options,&options,sizeof(options));
-       memcpy(&save_optimize,&optimize,sizeof(optimize));
-       break;
-    case P_RESTORE:
-       memcpy(&options,&save_options,sizeof(options));
-       memcpy(&optimize,&save_optimize,sizeof(optimize));
-       break;
-    case P_NOINDUCTION:
-       optimize.loopInduction = 0 ;
-       break;
-    case P_NOINVARIANT:
-       optimize.loopInvariant = 0 ;
-       break;
-    case P_INDUCTION:
-        optimize.loopInduction = 1 ;
-        break;
-    case P_STACKAUTO:
-       options.stackAuto = 1;
-       break;
-    case P_NOJTBOUND:
-       optimize.noJTabBoundary = 1;
-       break;
-    case P_NOGCSE:
-       optimize.global_cse = 0;
-       break;
-    case P_NOOVERLAY:
-       options.noOverlay = 1;
-       break;
-    case P_CALLEE_SAVES:
-       {
-           int i=0;
-           /* append to the functions already listed
-              in callee-saves */
-           for (; options.calleeSaves[i] ;i++);
-           parseWithComma(&options.calleeSaves[i],strdup(cp));
-       }
-       break;
-    case P_EXCLUDE:
-       parseWithComma(options.excludeRegs,strdup(cp));
-       break;
-    case P_LOOPREV:
-       optimize.noLoopReverse = 1;
-       break;
+      if (!ch) 
+        goto out;
+
+      if (ch != '\"') {
+        unput(ch) ;
+        goto out;
+      }
+      break;
+
+    default:
+      buf[0] = ch;
+      dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
     }
+  }
+
+out:
+  return (char *)dbuf_c_str(&dbuf);
 }
 
-int process_pragma(char *s)
-{
-    char *cp ;
-    /* find the pragma */
-    while (strncmp(s,"#pragma",7))
-       s++;
-    s += 7;
-    
-    /* look for the directive */
-    while(isspace(*s)) s++;
 
-    cp = s;
-    /* look for the end of the directive */
-    while ((! isspace(*s)) && 
-          (*s != '\n')) 
-       s++ ;    
+enum pragma_id {
+     P_SAVE = 1,
+     P_RESTORE ,
+     P_NOINDUCTION,
+     P_NOINVARIANT,
+     P_INDUCTION ,
+     P_STACKAUTO ,
+     P_NOJTBOUND ,
+     P_NOOVERLAY ,
+     P_LESSPEDANTIC,
+     P_NOGCSE    ,
+     P_CALLEE_SAVES,
+     P_EXCLUDE   ,
+     P_NOIV      ,
+     P_LOOPREV   ,
+     P_OVERLAY_      /* I had a strange conflict with P_OVERLAY while */
+                     /* cross-compiling for MINGW32 with gcc 3.2 */
+};
 
-    /* First give the port a chance */
-    if (port->process_pragma && !port->process_pragma(cp))
-       return 0;
 
-    /* now compare and do what needs to be done */
-    if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
-       doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
-       return 0;
-    }
+/* SAVE/RESTORE stack */
+#define SAVE_RESTORE_SIZE 128
 
-    if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
-       doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
-       return 0;
-    }
+STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
+STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
 
-    if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
-       doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
-       return 0;
-    }
 
-    if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
-       doPragma (P_NOINVARIANT,NULL)   ;
-       return 0;
+void doPragma (int op, char *cp)
+{
+  switch (op) {
+  case P_SAVE:
+    {
+      struct options *optionsp;
+      struct optimize *optimizep;
+
+      optionsp = Safe_malloc(sizeof (struct options));
+      *optionsp = options;
+      STACK_PUSH(options_stack, optionsp);
+
+      optimizep = Safe_malloc(sizeof (struct optimize));
+      *optimizep = optimize;
+      STACK_PUSH(optimize_stack, optimizep);
     }
+    break;
 
-    if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
-       doPragma (P_INDUCTION,NULL)     ;
-       return 0;
-    }
+  case P_RESTORE:
+    {
+      struct options *optionsp;
+      struct optimize *optimizep;
 
-    if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
-       doPragma (P_STACKAUTO,NULL);
-       return 0;
-    }
+      optionsp = STACK_POP(options_stack);
+      options = *optionsp;
+      Safe_free(optionsp);
 
-    if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
-       doPragma (P_NOJTBOUND,NULL);
-       return 0;
+      optimizep = STACK_POP(optimize_stack);
+      optimize = *optimizep;
+      Safe_free(optimizep);
     }
-
-    if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
-       doPragma (P_NOGCSE,NULL);
-       return 0;
+    break;
+
+  case P_NOINDUCTION:
+    optimize.loopInduction = 0 ;
+    break;
+
+  case P_NOINVARIANT:
+    optimize.loopInvariant = 0 ;
+    break;
+
+  case P_INDUCTION:
+    optimize.loopInduction = 1 ;
+    break;
+
+  case P_STACKAUTO:
+    options.stackAuto = 1;
+    break;
+
+  case P_NOJTBOUND:
+    optimize.noJTabBoundary = 1;
+    break;
+
+  case P_NOGCSE:
+    optimize.global_cse = 0;
+    break;
+
+  case P_NOOVERLAY:
+    options.noOverlay = 1;
+    break;
+
+  case P_LESSPEDANTIC:
+    options.lessPedantic = 1;
+    break;
+
+  case P_CALLEE_SAVES:
+    {
+      int i=0;
+      /* append to the functions already listed
+         in callee-saves */
+      for (; options.calleeSaves[i] ;i++);
+        parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
     }
+    break;
 
-    if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
-       doPragma (P_NOOVERLAY,NULL);
-       return 0;
-    }
-    
-    if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
-       doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
-       return 0;
-    }
+  case P_EXCLUDE:
+    parseWithComma(options.excludeRegs, Safe_strdup(cp));
+    break;
+
+  case P_NOIV:
+    options.noiv = 1;
+    break;
+
+  case P_LOOPREV:
+    optimize.noLoopReverse = 1;
+    break;
+
+  case P_OVERLAY_:
+    break; /* notyet */
+  }
+}
+
+int process_pragma(char *s)
+{
+#define NELEM(x)  (sizeof (x) / sizeof (x)[0])
+#define PRAGMA    "#pragma"
+
+  static struct pragma_s {
+    const char *name;
+    enum pragma_id id;
+  } pragma_tbl[] = {
+    { "SAVE",           P_SAVE },
+    { "RESTORE",        P_RESTORE },
+    { "NOINDUCTION",    P_NOINDUCTION },
+    { "NOINVARIANT",    P_NOINVARIANT },
+    { "NOLOOPREVERSE",  P_LOOPREV },
+    { "INDUCTION",      P_INDUCTION },
+    { "STACKAUTO",      P_STACKAUTO },
+    { "NOJTBOUND",      P_NOJTBOUND },
+    { "NOGCSE",         P_NOGCSE },
+    { "NOOVERLAY",      P_NOOVERLAY },
+    { "CALLEE-SAVES",   P_CALLEE_SAVES },
+    { "EXCLUDE",        P_EXCLUDE },
+    { "NOIV",           P_NOIV },
+    { "OVERLAY",        P_OVERLAY_ },
+    { "LESS_PEDANTIC",  P_LESSPEDANTIC },
+  };
+  char *cp ;
+  int i;
+
+  /* find the pragma */
+  while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
+    s++;
+  s += (sizeof PRAGMA) - 1;
     
-    if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
-       doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
-       return 0;
-    }
+  /* look for the directive */
+  while(isspace(*s))
+    s++;
 
-    if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
-       doPragma(P_EXCLUDE,NULL);
-       return 0;
-    }
+  cp = s;
+  /* look for the end of the directive */
+  while ((!isspace(*s)) && (*s != '\n')) 
+    s++ ;    
 
-    werror(W_UNKNOWN_PRAGMA,cp);
+  /* First give the port a chance */
+  if (port->process_pragma && !port->process_pragma(cp))
     return 0;
+
+  for (i = 0; i < NELEM(pragma_tbl); i++) {
+    /* now compare and do what needs to be done */
+    size_t len = strlen(pragma_tbl[i].name);
+
+    if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
+      doPragma(pragma_tbl[i].id, cp + len);
+      return 0;
+    }
+  }
+
+  werror(W_UNKNOWN_PRAGMA,cp);
+  return 0;
 }
 
 /* will return 1 if the string is a part
@@ -528,10 +607,13 @@ int yyerror(char *s)
 {
    fflush(stdout);
 
-   if (yylineno && filename)
-       fprintf(stdout,"\n%s(%d) %s: token -> '%s' ; column %d\n",
-               filename,yylineno,
-               s,yytext,column);
-   fatalError++;
+   if (yylineno && filename) {
+     fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
+            filename,yylineno,
+            s,yytext,column);
+     fatalError++;
+   } else {
+     // this comes from an empy file, no problem
+   }
    return 0;
 }