* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[fw/sdcc] / src / SDCC.lex
index 4eddd3ee77a507cd4513327bcce86108b9577e48..4f9b51887143ffac7c794b995ac355ef74005628 100644 (file)
    what you give them.   Help stamp out software-hoarding!  
 -------------------------------------------------------------------------*/
 
-D        [0-9]
-L        [a-zA-Z_]
-H        [a-fA-F0-9]
-E        [Ee][+-]?{D}+
-FS       (f|F|l|L)
-IS       (u|U|l|L)*
-%{
+D       [0-9]
+L       [a-zA-Z_]
+H       [a-fA-F0-9]
+E       [Ee][+-]?{D}+
+FS      (f|F|l|L)
+IS      (u|U|l|L)*
 
+%{
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include "common.h"
 #include "newalloc.h"
-    
-char *stringLiteral();
-char *currFname;
+#include "dbuf.h"
 
-extern int lineno, column;
-extern char *filename ;
-extern char *fullSrcFileName ;
-int   yylineno = 1               ;
-void count()                     ;
-int process_pragma(char *);
-#undef yywrap
-
-int yywrap YY_PROTO((void))
-{
-   return(1);
-}
 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
-                               check_type(yytext))
-char *asmbuff=NULL;
-int asmbuffSize=0;
-char *asmp ;
-extern int check_type          ();
- extern int isTargetKeyword     ();
-extern int checkCurrFile       (char *);
-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
- };
+                                check_type())
+
+#define TKEYWORDSDCC(token) return (options.std_sdcc && isTargetKeyword(yytext)\
+                                    ? token : check_type())
+
+#define TKEYWORD99(token) return (options.std_c99 ? token : check_type())
+
+extern int lineno, column;
+extern char *filename;
 
+/* global definitions */
+char *currFname;
+int mylineno = 1;
+
+/* local definitions */
+static struct dbuf_s asmbuff;
+
+/* forward declarations */
+static char *stringLiteral(void);
+static void count(void);
+static int process_pragma(char *);
+static int check_type(void);
+static int isTargetKeyword(char *s);
+static int checkCurrFile(char *s);
 %}
+
 %x asm
 %%
-"_asm"         {  
-  count(); 
-  asmp = asmbuff = Safe_realloc (asmbuff, INITIAL_INLINEASM);
-  asmbuffSize=INITIAL_INLINEASM;
-  BEGIN(asm) ;
+_?"_asm"         {
+  count();
+  if (!options.std_sdcc && yytext[1] != '_')
+    return check_type();
+  assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
+  dbuf_init(&asmbuff, INITIAL_INLINEASM);
+  BEGIN(asm);
 }
-<asm>"_endasm" { 
+<asm>_?"_endasm" {
   count();
-  *asmp = '\0';
-  yylval.yyinline = Safe_alloc (strlen(asmbuff)+1);
-  strcpy(yylval.yyinline,asmbuff);
-  BEGIN(INITIAL);
-  return (INLINEASM);
+  if (!options.std_sdcc && yytext[1] != '_')
+    {
+      dbuf_append(&asmbuff, yytext, strlen(yytext));
+    }
+  else
+    {
+      yylval.yyinline = dbuf_c_str(&asmbuff);
+      dbuf_detach(&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 = Safe_realloc (asmbuff, asmbuffSize); 
-    asmp=asmbuff+size;
-  }
-  *asmp++ = yytext[0];
+<asm>\n        {
+  count();
+  dbuf_append(&asmbuff, yytext, 1);
 }
-<asm>\n        { 
-  count(); 
-  if (asmp-asmbuff >= asmbuffSize-3) {
-    // increase the buffersize with 50%
-    int size=asmp-asmbuff;
-    asmbuffSize=asmbuffSize*3/2;
-    asmbuff = Safe_realloc (asmbuff, asmbuffSize); 
-    asmp=asmbuff+size;
-  }
-  *asmp++ = '\n' ;
+<asm>.         {
+  dbuf_append(&asmbuff, yytext, 1);
 }
-"at"          { count(); TKEYWORD(AT)  ; }
-"auto"        { count(); return(AUTO); }
-"bit"         { count(); TKEYWORD(BIT) ; }
+"at"           { count(); TKEYWORDSDCC(AT); }
+"__at"         { count(); TKEYWORD(AT); }
+"auto"         { count(); return(AUTO); }
+"bit"          { count(); TKEYWORDSDCC(BIT); }
+"__bit"        { count(); TKEYWORD(BIT); }
 "break"        { count(); return(BREAK); }
 "case"         { count(); return(CASE); }
 "char"         { count(); return(CHAR); }
-"code"         { count(); TKEYWORD(CODE); }
+"code"         { count(); TKEYWORDSDCC(CODE); }
+"__code"       { count(); TKEYWORD(CODE); }
 "const"        { count(); return(CONST); }
 "continue"     { count(); return(CONTINUE); }
-"critical"     { count(); TKEYWORD(CRITICAL); } 
-"data"        { count(); TKEYWORD(DATA);   }
+"critical"     { count(); TKEYWORDSDCC(CRITICAL); }
+"__critical"   { count(); TKEYWORD(CRITICAL); }
+"data"         { count(); TKEYWORDSDCC(DATA); }
+"__data"       { count(); TKEYWORD(DATA); }
 "default"      { count(); return(DEFAULT); }
 "do"           { count(); return(DO); }
 "double"       { count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
 "else"         { count(); return(ELSE); }
 "enum"         { count(); return(ENUM); }
 "extern"       { count(); return(EXTERN); }
-"far"          { count(); TKEYWORD(XDATA);  }
-"eeprom"       { count(); TKEYWORD(EEPROM);  }
+"far"          { count(); TKEYWORDSDCC(XDATA); }
+"__far"        { count(); TKEYWORD(XDATA); }
+"eeprom"       { count(); TKEYWORDSDCC(EEPROM); }
+"__eeprom"     { count(); TKEYWORD(EEPROM); }
 "float"        { count(); return(FLOAT); }
-"flash"        { count(); TKEYWORD(CODE);}
+"fixed16x16"   { count(); TKEYWORDSDCC(FIXED16X16); }
+"__fixed16x16"   { count(); TKEYWORD(FIXED16X16); }
+"flash"        { count(); TKEYWORDSDCC(CODE); }
+"__flash"      { count(); TKEYWORD(CODE); }
 "for"          { count(); return(FOR); }
-"goto"        { count(); return(GOTO); }
-"idata"        { count(); TKEYWORD(IDATA);}
+"goto"         { count(); return(GOTO); }
+"idata"        { count(); TKEYWORDSDCC(IDATA); }
+"__idata"      { count(); TKEYWORD(IDATA); }
 "if"           { count(); return(IF); }
 "int"          { count(); return(INT); }
-"interrupt"    { count(); return(INTERRUPT);}
-"nonbanked"    { count(); TKEYWORD(NONBANKED);}
-"banked"       { count(); TKEYWORD(BANKED);}
-"long"        { count(); return(LONG); }
-"near"        { count(); TKEYWORD(DATA);}
-"pdata"        { count(); TKEYWORD(PDATA); }
-"reentrant"    { count(); TKEYWORD(REENTRANT);}
+"interrupt"    { count(); TKEYWORDSDCC(INTERRUPT); }
+"__interrupt"  { count(); TKEYWORD(INTERRUPT); }
+"nonbanked"    { count(); TKEYWORDSDCC(NONBANKED); }
+"__nonbanked"  { count(); TKEYWORD(NONBANKED); }
+"banked"       { count(); TKEYWORDSDCC(BANKED); }
+"__banked"     { count(); TKEYWORD(BANKED); }
+"long"         { count(); return(LONG); }
+"near"         { count(); TKEYWORDSDCC(DATA); }
+"__near"       { count(); TKEYWORD(DATA); }
+"pdata"        { count(); TKEYWORDSDCC(PDATA); }
+"__pdata"      { count(); TKEYWORD(PDATA); }
+"reentrant"    { count(); TKEYWORDSDCC(REENTRANT); }
+"__reentrant"  { count(); TKEYWORD(REENTRANT); }
+"shadowregs"   { count(); TKEYWORDSDCC(SHADOWREGS); }
+"__shadowregs" { count(); TKEYWORD(SHADOWREGS); }
+"wparam"       { count(); TKEYWORDSDCC(WPARAM); }
+"__wparam"     { count(); TKEYWORD(WPARAM); }
 "register"     { count(); return(REGISTER); }
 "return"       { count(); return(RETURN); }
-"sfr"         { count(); TKEYWORD(SFR) ; }
-"sbit"        { count(); TKEYWORD(SBIT)        ; }
+"sfr"          { count(); TKEYWORDSDCC(SFR); }
+"__sfr"        { count(); TKEYWORD(SFR); }
+"sfr16"        { count(); TKEYWORDSDCC(SFR16); }
+"__sfr16"      { count(); TKEYWORD(SFR16); }
+"sfr32"        { count(); TKEYWORDSDCC(SFR32); }
+"__sfr32"      { count(); TKEYWORD(SFR32); }
+"sbit"         { count(); TKEYWORDSDCC(SBIT); }
+"__sbit"       { count(); TKEYWORD(SBIT); }
 "short"        { count(); return(SHORT); }
 "signed"       { count(); return(SIGNED); }
 "sizeof"       { count(); return(SIZEOF); }
-"sram"         { count(); TKEYWORD(XDATA);}
+"sram"         { count(); TKEYWORDSDCC(XDATA); }
+"__sram"       { count(); TKEYWORD(XDATA); }
 "static"       { count(); return(STATIC); }
 "struct"       { count(); return(STRUCT); }
 "switch"       { count(); return(SWITCH); }
@@ -166,30 +172,39 @@ struct options  save_options  ;
 "unsigned"     { count(); return(UNSIGNED); }
 "void"         { count(); return(VOID); }
 "volatile"     { count(); return(VOLATILE); }
-"using"        { count(); TKEYWORD(USING); }
-"_naked"       { count(); TKEYWORD(NAKED); }
+"using"        { count(); TKEYWORDSDCC(USING); }
+"__using"      { count(); TKEYWORD(USING); }
+"_naked"       { count(); TKEYWORDSDCC(NAKED); }
+"__naked"      { count(); TKEYWORD(NAKED); }
 "while"        { count(); return(WHILE); }
-"xdata"        { count(); TKEYWORD(XDATA); }
-"..."         { count(); return(VAR_ARGS);}
+"xdata"        { count(); TKEYWORDSDCC(XDATA); }
+"__xdata"      { count(); TKEYWORD(XDATA); }
+"..."          { count(); return(VAR_ARGS); }
+"__typeof"     { count(); return TYPEOF; }
+"_JavaNative"  { count(); TKEYWORD(JAVANATIVE); }
+"_overlay"     { count(); TKEYWORDSDCC(OVERLAY); }
+"__overlay"    { count(); TKEYWORD(OVERLAY); }
+"inline"       { count(); TKEYWORD99(INLINE); }
+"restrict"     { count(); TKEYWORD99(RESTRICT); }
 {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); }
+0[0-7]*{IS}?     { count(); yylval.val = constVal(yytext); return(CONSTANT); }
+[1-9]{D}*{IS}?      { count(); yylval.val = constVal(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); }
-\"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);}
+{D}+"."{D}*({E})?{FS}?  { count(); yylval.val = constFloatVal(yytext);return(CONSTANT); }
+\"             { count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL); }
 ">>=" { count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); }
-"<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN) ; }
-"+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN)  ; }
-"-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN)  ; }
-"*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN)  ; }
-"/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN)  ; }
-"%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN)  ; }
-"&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN)  ; }
-"^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN)  ; }
-"|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN)   ; }
+"<<=" { count(); yylval.yyint = LEFT_ASSIGN  ; return(LEFT_ASSIGN); }
+"+="  { count(); yylval.yyint = ADD_ASSIGN   ; return(ADD_ASSIGN); }
+"-="  { count(); yylval.yyint = SUB_ASSIGN   ; return(SUB_ASSIGN); }
+"*="  { count(); yylval.yyint = MUL_ASSIGN   ; return(MUL_ASSIGN); }
+"/="  { count(); yylval.yyint = DIV_ASSIGN   ; return(DIV_ASSIGN); }
+"%="  { count(); yylval.yyint = MOD_ASSIGN   ; return(MOD_ASSIGN); }
+"&="  { count(); yylval.yyint = AND_ASSIGN   ; return(AND_ASSIGN); }
+"^="  { count(); yylval.yyint = XOR_ASSIGN   ; return(XOR_ASSIGN); }
+"|="  { count(); yylval.yyint = OR_ASSIGN    ; return(OR_ASSIGN); }
 ">>"           { count(); return(RIGHT_OP); }
 "<<"           { count(); return(LEFT_OP); }
 "++"           { count(); return(INC_OP); }
@@ -202,12 +217,12 @@ struct options  save_options  ;
 "=="           { count(); return(EQ_OP); }
 "!="           { count(); return(NE_OP); }
 ";"            { count(); return(';'); }
-"{"           { count(); NestLevel++ ;  return('{'); }
-"}"           { count(); NestLevel--; return('}'); }
+"{"            { count(); NestLevel++ ; ignoreTypedefType = 0; return('{'); }
+"}"            { count(); NestLevel--; return('}'); }
 ","            { count(); return(','); }
 ":"            { count(); return(':'); }
 "="            { count(); return('='); }
-"("            { count(); return('('); }
+"("            { count(); ignoreTypedefType = 0; return('('); }
 ")"            { count(); return(')'); }
 "["            { count(); return('['); }
 "]"            { count(); return(']'); }
@@ -225,352 +240,640 @@ struct options  save_options  ;
 "^"            { count(); return('^'); }
 "|"            { count(); return('|'); }
 "?"            { count(); return('?'); }
-^#line.*"\n"      { count(); checkCurrFile(yytext); }
-^#pragma.*"\n"   { count(); process_pragma(yytext); }
+^#pragma.*"\n" { count(); process_pragma(yytext); }
+^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
 
-^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED,yytext);count(); }
-^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING,yytext);count(); }
-"\r\n"            { count(); }
-"\n"              { count(); }
+^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
+^[^(]+"("[0-9]+") : warning"[^\n]+ { werror(W_PRE_PROC_WARNING, yytext); count(); }
+"\r\n"         { count(); }
+"\n"           { count(); }
 [ \t\v\f]      { count(); }
 \\ {
-  char ch=input();
-  if (ch!='\n') {
-    // that could have been removed by the preprocessor anyway
+  int ch = input();
+  if (ch != '\n') {
+    /* that could have been removed by the preprocessor anyway */
     werror (W_STRAY_BACKSLASH, column);
     unput(ch);
   }
 }
-.                         { count()    ; }
+.              { count(); }
 %%
-   
-int checkCurrFile ( char *s)
+
+/* flex 2.5.31 undefines yytext_ptr, so we have to define it again */
+#ifndef yytext_ptr
+#define yytext_ptr yytext
+#endif
+
+
+static int checkCurrFile (char *s)
 {
-    char lineNum[10]                   ;
-    int  lNum                          ;
-    char *tptr                         ;
-       
-    /* first check if this is a #line */
-    if ( strncmp(s,"#line",5) )
-       return  0                               ;
-    
-    /* get to the line number */
-    while (!isdigit(*s))
-       s++ ;
-    tptr = lineNum ;
-    while (isdigit(*s))
-       *tptr++ = *s++ ;
-    *tptr = '\0'; 
-    sscanf(lineNum,"%d",&lNum);
-    
+    int  lNum;
+    char *tptr;
+
+    /* skip '#' character */
+    if (*s++ != '#')
+      return 0;
+
+    /* check if this is a #line
+       this is not standard and can be removed in the future */
+#define LINE_STR  "line"
+#define LINE_LEN  ((sizeof LINE_STR) - 1)
+
+    if (strncmp(s, LINE_STR, LINE_LEN) == 0)
+      s += LINE_LEN;
+
+    /* get the line number */
+    lNum = strtol(s, &tptr, 10);
+    if (tptr == s || !isspace((unsigned char)*tptr))
+      return 0;
+    s = tptr;
+
     /* now see if we have a file name */
-    while (*s != '\"' && *s) 
-       s++ ;
-    
+    while (*s != '\"' && *s)
+      s++;
+
     /* if we don't have a filename then */
     /* set the current line number to   */
     /* line number if printFlag is on   */
-    if (!*s) {         
-      lineno = yylineno = lNum ;
+    if (!*s) {
+      lineno = mylineno = lNum;
       return 0;
     }
-    
+
     /* if we have a filename then check */
     /* if it is "standard in" if yes then */
     /* get the currentfile name info    */
     s++ ;
 
-    if ( 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';
-       currFname = Safe_alloc (strlen(sb)+1);
-       strcpy(currFname,sb);
-       lineno = yylineno = lNum;
+    /* in c1mode fullSrcFileName is NULL */
+    if (fullSrcFileName &&
+         strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0) {
+      lineno = mylineno = lNum;
+      currFname = fullSrcFileName;
+    } else {
+        char *sb = s;
+        /* mark the end of the filename */
+        while (*s != '"') s++;
+        *s = '\0';
+        currFname = strdup (sb);
+        lineno = mylineno = lNum;
     }
     filename = currFname ;
     return 0;
 }
-    
+
 int column = 0;
-int plineIdx=0;
+int plineIdx =0;
 
-void count()
+static void count(void)
 {
   int i;
-  for (i = 0; yytext[i] != '\0'; i++)   {                              
-    if (yytext[i] == '\n')      {         
+  for (i = 0; yytext[i] != '\0'; i++) {
+    if (yytext[i] == '\n') {
       column = 0;
-      lineno = ++yylineno ;
+      lineno = ++mylineno;
     }
-    else 
+    else
       if (yytext[i] == '\t')
-       column += 8 - (column % 8);
+        column += 8 - (column % 8);
       else
-       column++;
+        column++;
   }
   /* ECHO; */
 }
 
-int check_type()
+static int check_type(void)
 {
-       /* check if it is in the typedef table */
-       if (findSym(TypedefTab,NULL,yytext)) {
-               strcpy(yylval.yychar,yytext);
-               return (TYPE_NAME) ;
-       }
-       else   {
-               strcpy (yylval.yychar,yytext);
-               return(IDENTIFIER);
-       }
-}
+  symbol *sym = findSym(SymbolTab, NULL, yytext);
 
-char strLitBuff[2048]; // TODO: this is asking for the next bug :)
+  /* check if it is in the table as a typedef */
+  if (!ignoreTypedefType && sym && IS_SPEC (sym->etype)
+      && SPEC_TYPEDEF (sym->etype)) {
+    strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
+    return (TYPE_NAME);
+  }
+  else {
+    strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
+    return(IDENTIFIER);
+  }
+}
 
 /*
  * Change by JTV 2001-05-19 to not concantenate strings
- * to support ANSI hex and octal escape sequences in string liteals 
+ * to support ANSI hex and octal escape sequences in string literals
  */
 
-char *stringLiteral () {
+static char *stringLiteral(void)
+{
+#define STR_BUF_CHUNCK_LEN  1024
   int ch;
-  char *str = strLitBuff;
-  
-  *str++ = '\"';
+  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 (1) {
-    ch = input();
-    
-    if (!ch)
-      break; /* end of input */
-    
-    /* if it is a \ then escape char's are allowed */
-    if (ch == '\\') {
-      ch=input();
-      if (ch=='\n') {
-       /* \<newline> is a continuator */
-       lineno=++yylineno;
-       column=0;
-       continue;
+
+  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 = ++mylineno;
+        column = 0;
       }
-      *str++ = '\\'; /* backslash in place */
-      *str++ = ch; /* get the escape char, no further check */
-      continue; /* carry on */
-    }
-    
-    /* if new line we have a new line break, which is illegal */
-    if (ch == '\n') {
-      werror (W_NEWLINE_IN_STRING);
-      *str++ = '\n';
-      lineno=++yylineno;
-      column=0;
-      continue;
-    }
-    
-    /* 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 == '\"') {
-      *str++  = ch ; /* 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;
-       }
+      else {
+        buf[0] = '\\';
+        buf[1] = ch;
+        dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
       }
+      break; /* carry on */
 
-      if (!ch) 
-       break; 
+    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 = ++mylineno;
+      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 = ++mylineno;
+            column = 0;
+          }
+          break;
+
+        case '\n':
+          mylineno++;
+          break;
+        }
+      }
+
+      if (!ch)
+        goto out;
 
       if (ch != '\"') {
-       unput(ch) ;
-       break ;
+        unput(ch);
+        goto out;
       }
+      break;
+
+    default:
+      buf[0] = ch;
+      dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
     }
-    *str++  = ch; /* Put next substring introducer into output string */
-  }  
-  *str = '\0';
-  
-  return strLitBuff;
+  }
+
+out:
+  return (char *)dbuf_c_str(&dbuf);
 }
 
-void doPragma (int op, char *cp)
+
+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 */
+     P_DISABLEWARN,
+     P_OPTCODESPEED,
+     P_OPTCODESIZE,
+     P_OPTCODEBALANCED,
+     P_STD_C89,
+     P_STD_C99,
+     P_STD_SDCC89,
+     P_STD_SDCC99,
+     P_CODESEG,
+     P_CONSTSEG
+};
+
+
+/* SAVE/RESTORE stack */
+#define SAVE_RESTORE_SIZE 128
+
+STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
+STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
+STACK_DCL(SDCCERRG_stack, struct SDCCERRG *, SAVE_RESTORE_SIZE)
+
+/*
+ * cloneXxx functions should be updated every time a new set is
+ * added to the options or optimize structure!
+ */
+
+static struct options *cloneOptions(struct options *opt)
 {
-    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;
-    }
+  struct options *new_opt;
+
+  new_opt = Safe_malloc(sizeof (struct options));
+
+  /* clone scalar values */
+  *new_opt = *opt;
+
+  /* clone sets */
+  new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
+  new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
+  /* not implemented yet: */
+  /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
+
+  return new_opt;
 }
 
-int process_pragma(char *s)
+static struct optimize *cloneOptimize(struct optimize *opt)
 {
-    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++ ;    
-
-    /* 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;
-    }
+  struct optimize *new_opt;
 
-    if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
-       doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
-       return 0;
-    }
+  new_opt = Safe_malloc(sizeof (struct optimize));
 
-    if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
-       doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION))  ;
-       return 0;
-    }
+  /* clone scalar values */
+  *new_opt = *opt;
 
-    if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
-       doPragma (P_NOINVARIANT,NULL)   ;
-       return 0;
-    }
+  return new_opt;
+}
 
-    if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
-       doPragma (P_INDUCTION,NULL)     ;
-       return 0;
-    }
+static struct SDCCERRG *cloneSDCCERRG (struct SDCCERRG *val)
+{
+  struct SDCCERRG *new_val;
 
-    if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
-       doPragma (P_STACKAUTO,NULL);
-       return 0;
-    }
+  new_val = Safe_malloc(sizeof (struct SDCCERRG));
 
-    if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
-       doPragma (P_NOJTBOUND,NULL);
-       return 0;
-    }
+  /* clone scalar values */
+  *new_val = *val;
 
-    if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
-       doPragma (P_NOGCSE,NULL);
-       return 0;
-    }
+  return new_val;
+}
+
+static void copyAndFreeOptions(struct options *dest, struct options *src)
+{
+  /* delete dest sets */
+  deleteSet(&dest->calleeSavesSet);
+  deleteSet(&dest->excludeRegsSet);
+  /* not implemented yet: */
+  /* deleteSet(&dest->olaysSet); */
+
+  /* copy src to dest */
+  *dest = *src;
+
+  Safe_free(src);
+}
+
+static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
+{
+  /* copy src to dest */
+  *dest = *src;
+
+  Safe_free(src);
+}
 
-    if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
-       doPragma (P_NOOVERLAY,NULL);
-       return 0;
+static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
+{
+  /* copy src to dest */
+  *dest = *src;
+
+  Safe_free(src);
+}
+
+static void doPragma(int op, char *cp)
+{
+  int i;
+
+  switch (op) {
+  case P_SAVE:
+    {
+      STACK_PUSH(options_stack, cloneOptions(&options));
+      STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
+      STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
     }
-    
-    if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
-       doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
-       return 0;
+    break;
+
+  case P_RESTORE:
+    {
+      struct options *optionsp;
+      struct optimize *optimizep;
+      struct SDCCERRG *sdccerrgp;
+
+      optionsp = STACK_POP(options_stack);
+      copyAndFreeOptions(&options, optionsp);
+
+      optimizep = STACK_POP(optimize_stack);
+      copyAndFreeOptimize(&optimize, optimizep);
+
+      sdccerrgp = STACK_POP(SDCCERRG_stack);
+      copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
     }
-    
-    if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
-       doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
-       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;
+    setErrorLogLevel(ERROR_LEVEL_WARNING);
+    break;
+
+  case P_CALLEE_SAVES:
+    /* append to the functions already listed
+       in callee-saves */
+    setParseWithComma(&options.calleeSavesSet, cp);
+    break;
+
+  case P_EXCLUDE:
+    {
+      deleteSet(&options.excludeRegsSet);
+      setParseWithComma(&options.excludeRegsSet, cp);
     }
+    break;
+
+  case P_NOIV:
+    options.noiv = 1;
+    break;
 
-    if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
-       doPragma(P_LOOPREV,NULL);
-       return 0;
+  case P_LOOPREV:
+    optimize.noLoopReverse = 1;
+    break;
+
+  case P_OVERLAY_:
+    break; /* notyet */
+
+  case P_DISABLEWARN:
+    if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
+      {
+        setWarningDisabled(i);
+      }
+    break;
+  
+  case P_OPTCODESPEED:
+    optimize.codeSpeed = 1;
+    optimize.codeSize = 0;
+    break;
+
+  case P_OPTCODESIZE:
+    optimize.codeSpeed = 0;
+    optimize.codeSize = 1;
+    break;
+
+  case P_OPTCODEBALANCED:
+    optimize.codeSpeed = 0;
+    optimize.codeSize = 0;
+    break;
+  
+  case P_STD_C89:
+    options.std_c99 = 0;
+    options.std_sdcc = 0;
+    break;
+  
+  case P_STD_C99:
+    options.std_c99 = 1;
+    options.std_sdcc = 0;
+    break;
+  
+  case P_STD_SDCC89:
+    options.std_c99 = 0;
+    options.std_sdcc = 1;
+    break;
+  
+  case P_STD_SDCC99:
+    options.std_c99 = 1;
+    options.std_sdcc = 1;
+    break;
+
+  case P_CODESEG:
+    {
+      char str[9];
+      char *segname = Safe_malloc(15);
+      sscanf(cp, " %8s", str);
+      str[8] = '\0';
+      sprintf(segname, "%-8.8s(CODE)", str);
+      options.code_seg = segname;
     }
+    break;
+
+  case P_CONSTSEG:
+    {
+      char str[9];
+      char *segname = Safe_malloc(15);
+      sscanf(cp, " %8s", str);
+      str[8] = '\0';
+      sprintf(segname, "%-8.8s(CODE)", str);
+      options.const_seg = segname;
+    }
+    break;
+  }
+}
+
+static int process_pragma(char *s)
+{
+#define NELEM(x)    (sizeof (x) / sizeof (x)[0])
+#define PRAGMA_STR  "#pragma"
+#define PRAGMA_LEN  ((sizeof PRAGMA_STR) - 1)
+
+  static struct pragma_s
+    {
+      const char *name;
+      enum pragma_id id;
+      char deprecated;
+    } pragma_tbl[] = {
+    { "save",           P_SAVE,         0 },
+    { "restore",        P_RESTORE,      0 },
+    { "noinduction",    P_NOINDUCTION,  0 },
+    { "noinvariant",    P_NOINVARIANT,  0 },
+    { "noloopreverse",  P_LOOPREV,      0 },
+    { "induction",      P_INDUCTION,    0 },
+    { "stackauto",      P_STACKAUTO,    0 },
+    { "nojtbound",      P_NOJTBOUND,    0 },
+    { "nogcse",         P_NOGCSE,       0 },
+    { "nooverlay",      P_NOOVERLAY,    0 },
+    { "callee_saves",   P_CALLEE_SAVES, 0 },
+    { "exclude",        P_EXCLUDE,      0 },
+    { "noiv",           P_NOIV,         0 },
+    { "overlay",        P_OVERLAY_,     0 },
+    { "less_pedantic",  P_LESSPEDANTIC, 0 },
+    { "disable_warning",P_DISABLEWARN,  0 },
+    { "opt_code_speed", P_OPTCODESPEED, 0 },
+    { "opt_code_size",  P_OPTCODESIZE,  0 },
+    { "opt_code_balanced",  P_OPTCODEBALANCED,  0 },
+    { "std_c89",        P_STD_C89,      0 },
+    { "std_c99",        P_STD_C99,      0 },
+    { "std_sdcc89",     P_STD_SDCC89,   0 },
+    { "std_sdcc99",     P_STD_SDCC99,   0 },
+    { "codeseg",        P_CODESEG,      0 },
+    { "constseg",       P_CONSTSEG,     0 },
+
+    /*
+     * The following lines are deprecated pragmas,
+     * only for bacward compatibility.
+     * They should be removed in next major release after 1.4.0
+     */
+
+    { "SAVE",           P_SAVE,         1 },
+    { "RESTORE",        P_RESTORE,      1 },
+    { "NOINDUCTION",    P_NOINDUCTION,  1 },
+    { "NOINVARIANT",    P_NOINVARIANT,  1 },
+    { "NOLOOPREVERSE",  P_LOOPREV,      1 },
+    { "INDUCTION",      P_INDUCTION,    1 },
+    { "STACKAUTO",      P_STACKAUTO,    1 },
+    { "NOJTBOUND",      P_NOJTBOUND,    1 },
+    { "NOGCSE",         P_NOGCSE,       1 },
+    { "NOOVERLAY",      P_NOOVERLAY,    1 },
+    { "CALLEE-SAVES",   P_CALLEE_SAVES, 1 },
+    { "EXCLUDE",        P_EXCLUDE,      1 },
+    { "NOIV",           P_NOIV,         1 },
+    { "OVERLAY",        P_OVERLAY_,     1 },
+    { "LESS_PEDANTIC",  P_LESSPEDANTIC, 1 },
+  };
+  char *cp;
+  int i;
+
+  /* find the pragma */
+  while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
+    s++;
+  s += PRAGMA_LEN;
+
+  /* look for the directive */
+  while(isspace((unsigned char)*s))
+    s++;
+
+  cp = s;
+  /* look for the end of the directive */
+  while ((!isspace((unsigned char)*s)) && (*s != '\n'))
+    s++ ;
+
+  /* skip separating whitespace */
+  while (isspace((unsigned char)*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)
+        {
+          if (pragma_tbl[i].deprecated != 0)
+            werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
+
+          doPragma(pragma_tbl[i].id, s);
+          return 0;
+        }
+    }
+
+  werror(W_UNKNOWN_PRAGMA, cp);
+  return 0;
 }
 
 /* will return 1 if the string is a part
    of a target specific keyword */
-int isTargetKeyword(char *s)
+static int isTargetKeyword(char *s)
 {
-    int i;
-    
-    if (port->keywords == NULL)
-       return 0;
-    for ( i = 0 ; port->keywords[i] ; i++ ) {
-       if (strcmp(port->keywords[i],s) == 0)
-           return 1;
-    }
-    
+  int i;
+
+  if (port->keywords == NULL)
     return 0;
+  
+  if (s[0] == '_' && s[1] == '_')
+    {
+      /* Keywords in the port's array have either 0 or 1 underscore, */
+      /* so skip over the appropriate number of chars when comparing */
+      for (i = 0 ; port->keywords[i] ; i++ )
+        {
+          if (port->keywords[i][0] == '_' &&
+              strcmp(port->keywords[i],s+1) == 0)
+            return 1;
+          else if (strcmp(port->keywords[i],s+2) == 0)
+            return 1;
+        }
+    }
+  else
+    {
+      for (i = 0 ; port->keywords[i] ; i++ )
+        {
+          if (strcmp(port->keywords[i],s) == 0)
+            return 1;
+        }
+    }
+
+  return 0;
 }
 
-extern int fatalError;
+int yywrap(void)
+{
+  if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
+    werror(W_SAVE_RESTORE);
+
+  return 1;
+}
 
 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++;
-   return 0;
+  fflush(stdout);
+
+  if (mylineno && filename) {
+    if(options.vc_err_style)
+      fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
+        filename, mylineno, s, yytext, column);
+    else
+      fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
+        filename, mylineno, s ,yytext, column);
+    fatalError++;
+  } else {
+    /* this comes from an empy file, no problem */
+  }
+  return 0;
 }