* device/include/pic16/pic18f*.h: add bit aliases in INTCONbits_t
[fw/sdcc] / src / SDCC.lex
index a0b0297c4e7b5e5b8a9feb64a2b2e2b7b4018a1b..0fc43d00445ed1bd3f5881bb047b091f04423282 100644 (file)
@@ -1,29 +1,30 @@
 /*-----------------------------------------------------------------------
-  SDCC.lex - lexical analyser for use with sdcc ( a freeware compiler for
-  8/16 bit microcontrollers)
+  SDCC.lex - lexical analyser for use with sdcc (free open source
+  compiler for 8/16 bit microcontrollers)
   Written by : Sandeep Dutta . sandeep.dutta@usa.net (1997)
-  
+
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    
-   In other words, you are welcome to use, share and improve this program.
-   You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+B       [0-1]
 D       [0-9]
-L       [a-zA-Z_]
+L       [a-zA-Z_$]
 H       [a-fA-F0-9]
 E       [Ee][+-]?{D}+
 FS      (f|F|l|L)
@@ -35,7 +36,7 @@ IS      (u|U|l|L)*
 #include <ctype.h>
 #include "common.h"
 #include "newalloc.h"
-#include "dbuf.h"
+#include "dbuf_string.h"
 
 #define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
                                 check_type())
@@ -45,23 +46,26 @@ IS      (u|U|l|L)*
 
 #define TKEYWORD99(token) return (options.std_c99 ? token : check_type())
 
-extern int lineno, column;
 extern char *filename;
+extern int lineno;
+int column = 0;         /* current column */
 
 /* global definitions */
-char *currFname;
-int mylineno = 1;
+char *lexFilename;
+int lexLineno = 1;
 
 /* local definitions */
-static struct dbuf_s asmbuff;
+static struct dbuf_s asmbuff; /* reusable _asm buffer */
 
 /* forward declarations */
-static char *stringLiteral(void);
+int yyerror(char *s);
+static const char *stringLiteral(void);
 static void count(void);
-static int process_pragma(char *);
+static void count_char(int);
+static int process_pragma(const char *);
 static int check_type(void);
-static int isTargetKeyword(char *s);
-static int checkCurrFile(char *s);
+static int isTargetKeyword(const char *s);
+static int checkCurrFile(const char *s);
 %}
 
 %x asm
@@ -70,30 +74,32 @@ _?"_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);
+  if (asmbuff.buf == NULL)
+    dbuf_init(&asmbuff, INITIAL_INLINEASM);
+  else
+    dbuf_set_length(&asmbuff, 0);
+
   BEGIN(asm);
 }
 <asm>_?"_endasm" {
   count();
   if (!options.std_sdcc && yytext[1] != '_')
     {
-      dbuf_append(&asmbuff, yytext, strlen(yytext));
+      dbuf_append_str(&asmbuff, yytext);
     }
   else
     {
       yylval.yyinline = dbuf_c_str(&asmbuff);
-      dbuf_detach(&asmbuff);
       BEGIN(INITIAL);
       return (INLINEASM);
     }
 }
 <asm>\n        {
   count();
-  dbuf_append(&asmbuff, yytext, 1);
+  dbuf_append_char(&asmbuff, *yytext);
 }
 <asm>.         {
-  dbuf_append(&asmbuff, yytext, 1);
+  dbuf_append_char(&asmbuff, *yytext);
 }
 "at"           { count(); TKEYWORDSDCC(AT); }
 "__at"         { count(); TKEYWORD(AT); }
@@ -123,7 +129,7 @@ _?"_asm"         {
 "__eeprom"     { count(); TKEYWORD(EEPROM); }
 "float"        { count(); return(FLOAT); }
 "fixed16x16"   { count(); TKEYWORDSDCC(FIXED16X16); }
-"__fixed16x16"   { count(); TKEYWORD(FIXED16X16); }
+"__fixed16x16" { count(); TKEYWORD(FIXED16X16); }
 "flash"        { count(); TKEYWORDSDCC(CODE); }
 "__flash"      { count(); TKEYWORD(CODE); }
 "for"          { count(); return(FOR); }
@@ -186,7 +192,23 @@ _?"_asm"         {
 "__overlay"    { count(); TKEYWORD(OVERLAY); }
 "inline"       { count(); TKEYWORD99(INLINE); }
 "restrict"     { count(); TKEYWORD99(RESTRICT); }
-{L}({L}|{D})*  { count(); return(check_type()); }
+{L}({L}|{D})*  {
+  if (!options.dollars_in_ident && strchr(yytext, '$'))
+    {
+      yyerror("stray '$' in program");
+    }
+  count();
+  return(check_type());
+}
+0[bB]{B}+{IS}? {
+  if (!options.std_sdcc)
+    {
+      yyerror("binary (0b) constants are not allowed in ISO C");
+    }
+  count();
+  yylval.val = constVal(yytext);
+  return(CONSTANT);
+}
 0[xX]{H}+{IS}? { count(); yylval.val = constVal(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); }
@@ -195,16 +217,16 @@ _?"_asm"         {
 {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); }
-">>=" { 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 = 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(); return(RIGHT_OP); }
 "<<"           { count(); return(LEFT_OP); }
 "++"           { count(); return(INC_OP); }
@@ -240,7 +262,7 @@ _?"_asm"         {
 "^"            { count(); return('^'); }
 "|"            { count(); return('|'); }
 "?"            { count(); return('?'); }
-^#pragma.*"\n" { count(); process_pragma(yytext); }
+^#pragma.*$    { count(); process_pragma(yytext); }
 ^(#line.*"\n")|(#.*"\n") { count(); checkCurrFile(yytext); }
 
 ^[^(]+"("[0-9]+") : error"[^\n]+ { werror(E_PRE_PROC_FAILED, yytext); count(); }
@@ -250,11 +272,15 @@ _?"_asm"         {
 [ \t\v\f]      { count(); }
 \\ {
   int ch = input();
-  if (ch != '\n') {
-    /* that could have been removed by the preprocessor anyway */
-    werror (W_STRAY_BACKSLASH, column);
-    unput(ch);
-  }
+
+  if (ch == '\n')
+    count_char(ch);
+  else
+    {
+      /* that could have been removed by the preprocessor anyway */
+      werror (W_STRAY_BACKSLASH, column);
+      unput(ch);
+    }
 }
 .              { count(); }
 %%
@@ -265,97 +291,112 @@ _?"_asm"         {
 #endif
 
 
-static int checkCurrFile (char *s)
+static int checkCurrFile (const char *s)
 {
-    int  lNum;
-    char *tptr;
+  int  lNum;
+  char *tptr;
 
-    /* skip '#' character */
-    if (*s++ != '#')
-      return 0;
+  /* skip '#' character */
+  if (*s++ != '#')
+    return 0;
 
-    /* check if this is a #line
-       this is not standard and can be removed in the future */
+  /* 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;
+  if (strncmp(s, LINE_STR, LINE_LEN) == 0)
+    s += LINE_LEN;
 
-    /* get the line number */
-    lNum = strtol(s, &tptr, 10);
-    if (tptr == s || !isspace(*tptr))
-      return 0;
-    s = tptr;
+  /* 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++;
+  /* adjust the line number */
+  lineno = lexLineno = lNum;
 
-    /* if we don't have a filename then */
-    /* set the current line number to   */
-    /* line number if printFlag is on   */
-    if (!*s) {
-      lineno = mylineno = lNum;
+  /* now see if we have a file name */
+  while (*s != '"' && *s)
+    ++s;
+
+  if (!*s)
+    {
+      /* no file name: return */
       return 0;
     }
 
-    /* if we have a filename then check */
-    /* if it is "standard in" if yes then */
-    /* get the currentfile name info    */
-    s++ ;
-
-    /* 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;
+  /* skip the double quote */
+  ++s;
+
+  /* get the file name and see if it is different from current one.
+     in c1mode fullSrcFileName is NULL */
+  if (fullSrcFileName &&
+    strncmp(s, fullSrcFileName, strlen(fullSrcFileName)) == 0 && fullSrcFileName[strlen(fullSrcFileName) - 1] == '"')
+    {
+      lexFilename = fullSrcFileName;
     }
-    filename = currFname ;
-    return 0;
-}
+  else
+    {
+      const char *sb = s;
+      char *tmpFname;
 
-int column = 0;
-int plineIdx =0;
+      /* find the end of the file name */
+      while (*s && *s != '"')
+        ++s;
 
-static void count(void)
+      tmpFname = Safe_malloc(s - sb + 1);
+      memcpy(tmpFname, sb, s - sb);
+      tmpFname[s - sb] = '\0';
+
+      lexFilename = Safe_malloc(s - sb + 1);
+      copyStr(lexFilename, tmpFname);
+    }
+  filename = lexFilename;
+
+  return 0;
+}
+
+static void count_char(int ch)
 {
-  int i;
-  for (i = 0; yytext[i] != '\0'; i++) {
-    if (yytext[i] == '\n') {
+  switch (ch)
+    {
+    case '\n':
       column = 0;
-      lineno = ++mylineno;
+      lineno = ++lexLineno;
+      break;
+
+    case '\t':
+      column += 8 - (column % 8);
+      break;
+
+    default:
+      ++column;
+      break;
     }
-    else
-      if (yytext[i] == '\t')
-        column += 8 - (column % 8);
-      else
-        column++;
-  }
-  /* ECHO; */
+}
+
+static void count(void)
+{
+  const char *p;
+
+  for (p = yytext; *p; ++p)
+    count_char(*p);
 }
 
 static int check_type(void)
 {
   symbol *sym = findSym(SymbolTab, NULL, yytext);
 
+  strncpyz(yylval.yychar, yytext, SDCC_NAME_MAX);
+
   /* 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);
+      && SPEC_TYPEDEF (sym->etype) && findSym(TypedefTab, NULL, yytext))
     return (TYPE_NAME);
-  }
-  else {
-    strncpyz (yylval.yychar, yytext, SDCC_NAME_MAX);
+  else
     return(IDENTIFIER);
-  }
 }
 
 /*
@@ -363,117 +404,172 @@ static int check_type(void)
  * to support ANSI hex and octal escape sequences in string literals
  */
 
-static char *stringLiteral(void)
+static const char *stringLiteral(void)
 {
 #define STR_BUF_CHUNCK_LEN  1024
   int ch;
-  static struct dbuf_s dbuf;
-  char buf[2];
+  static struct dbuf_s dbuf;  /* reusable string literal buffer */
 
   if (dbuf.alloc == 0)
     dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
   else
-    dbuf_set_size(&dbuf, 0);
+    dbuf_set_length(&dbuf, 0);
+
+  dbuf_append_char(&dbuf, '"');
 
-  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 */
+  for (; ; )
+    {
       ch = input();
-      if (ch == '\n') {
-        /* \<newline> is a continuator */
-        lineno = ++mylineno;
-        column = 0;
-      }
-      else {
-        buf[0] = '\\';
-        buf[1] = ch;
-        dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
-      }
-      break; /* carry on */
+      count_char(ch);
+      if (ch == EOF)
+        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) {
+      switch (ch)
+        {
         case '\\':
-          if ((ch = input()) != '\n') {
-            werror(W_STRAY_BACKSLASH, column);
-            unput(ch);
-          }
-          else {
-            lineno = ++mylineno;
-            column = 0;
-          }
-          break;
+          /* if it is a \ then escape char's are allowed */
+          ch = input();
+          count_char(ch);
+          if (ch == '\n')
+            {
+              /* \<newline> is a continuator */
+            }
+          else
+            {
+              char buf[2];
+
+              if (ch == EOF)
+                goto out;
+
+              buf[0] = '\\';
+              buf[1] = ch;
+              dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
+            }
+          break; /* carry on */
 
         case '\n':
-          mylineno++;
+          /* if new line we have a new line break, which is illegal */
+          werror(W_NEWLINE_IN_STRING);
+          dbuf_append_char(&dbuf, '\n');
           break;
-        }
-      }
 
-      if (!ch)
-        goto out;
-
-      if (ch != '\"') {
-        unput(ch);
-        goto out;
-      }
-      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_char(&dbuf, '"');  /* Pass end of this string or substring to evaluator */
+          while ((ch = input()) && (isspace(ch) || ch == '\\' || ch == '#'))
+            {
+              switch (ch)
+                {
+                case '\\':
+                  count_char(ch);
+                  if ((ch = input()) != '\n')
+                    {
+                      werror(W_STRAY_BACKSLASH, column);
+                      if (ch != EOF)
+                        unput(ch);
+                      else
+                        count_char(ch);
+                    }
+                  else
+                    count_char(ch);
+                  break;
+
+                case '\n':
+                  count_char(ch);
+                  break;
+
+                case '#':
+                  if (column == 0)
+                    {
+                      /* # at the beginning of the line: collect the entire line */
+                      struct dbuf_s linebuf;
+                      const char *line;
+
+                      count_char(ch);
+
+                      dbuf_init(&linebuf, STR_BUF_CHUNCK_LEN);
+                      dbuf_append_char(&linebuf, '#');
+
+                      while ((ch = input()) != EOF && ch != '\n')
+                        dbuf_append_char(&linebuf, (char)ch);
+
+                      if (ch == '\n')
+                        count_char(ch);
+
+                      line = dbuf_c_str(&linebuf);
+
+                      /* process the line */
+                      if (startsWith(line, "#pragma"))
+                        process_pragma(line);
+                      else
+                        checkCurrFile(line);
+
+                      dbuf_destroy(&linebuf);
+                    }
+                  else
+                    {
+                      unput(ch);
+                      goto out;
+                    }
+
+                default:
+                  count_char(ch);
+                  break;
+                }
+            }
+
+          if (ch == EOF)
+            goto out;
+
+          if (ch != '"')
+            {
+              unput(ch);
+              goto out;
+            }
+          count_char(ch);
+          break;
 
-    default:
-      buf[0] = ch;
-      dbuf_append(&dbuf, buf, 1);  /* Put next substring introducer into output string */
+        default:
+          dbuf_append_char(&dbuf, (char)ch);  /* Put next substring introducer into output string */
+        }
     }
-  }
 
 out:
-  return (char *)dbuf_c_str(&dbuf);
+  return dbuf_c_str(&dbuf);
 }
 
 
-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
+enum {
+   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
 };
 
 
@@ -561,272 +657,451 @@ static void copyAndFreeSDCCERRG(struct SDCCERRG *dest, struct SDCCERRG *src)
   Safe_free(src);
 }
 
-static void doPragma(int op, char *cp)
+/*
+ * returns 1 if the pragma was processed, 0 if not
+ */
+static int doPragma(int id, const char *name, const char *cp)
 {
-  int i;
+  struct pragma_token_s token;
+  int err = 0;
+  int processed = 1;
 
-  switch (op) {
-  case P_SAVE:
-    {
-      STACK_PUSH(options_stack, cloneOptions(&options));
-      STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
-      STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
-    }
-    break;
+  init_pragma_token(&token);
 
-  case P_RESTORE:
+  switch (id) 
     {
-      struct options *optionsp;
-      struct optimize *optimizep;
-      struct SDCCERRG *sdccerrgp;
+    case P_SAVE:
+      {
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
+
+        STACK_PUSH(options_stack, cloneOptions(&options));
+        STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
+        STACK_PUSH(SDCCERRG_stack, cloneSDCCERRG(&_SDCCERRG));
+      }
+      break;
 
-      optionsp = STACK_POP(options_stack);
-      copyAndFreeOptions(&options, optionsp);
+    case P_RESTORE:
+      {
+        struct options *optionsp;
+        struct optimize *optimizep;
+        struct SDCCERRG *sdccerrgp;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
 
-      optimizep = STACK_POP(optimize_stack);
-      copyAndFreeOptimize(&optimize, optimizep);
+        optionsp = STACK_POP(options_stack);
+        copyAndFreeOptions(&options, optionsp);
 
-      sdccerrgp = STACK_POP(SDCCERRG_stack);
-      copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
-    }
-    break;
+        optimizep = STACK_POP(optimize_stack);
+        copyAndFreeOptimize(&optimize, optimizep);
+
+        sdccerrgp = STACK_POP(SDCCERRG_stack);
+        copyAndFreeSDCCERRG(&_SDCCERRG, sdccerrgp);
+      }
+      break;
+
+    case P_NOINDUCTION:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      optimize.loopInduction = 0;
+      break;
 
-  case P_NOINDUCTION:
-    optimize.loopInduction = 0;
-    break;
+    case P_NOINVARIANT:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_NOINVARIANT:
-    optimize.loopInvariant = 0;
-    break;
+      optimize.loopInvariant = 0;
+      break;
 
-  case P_INDUCTION:
-    optimize.loopInduction = 1;
-    break;
+    case P_INDUCTION:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_STACKAUTO:
-    options.stackAuto = 1;
-    break;
+      optimize.loopInduction = 1;
+      break;
 
-  case P_NOJTBOUND:
-    optimize.noJTabBoundary = 1;
-    break;
+    case P_STACKAUTO:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_NOGCSE:
-    optimize.global_cse = 0;
-    break;
+      options.stackAuto = 1;
+      break;
 
-  case P_NOOVERLAY:
-    options.noOverlay = 1;
-    break;
+    case P_NOJTBOUND:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_LESSPEDANTIC:
-    options.lessPedantic = 1;
-    setErrorLogLevel(ERROR_LEVEL_WARNING);
-    break;
+      optimize.noJTabBoundary = 1;
+      break;
+
+    case P_NOGCSE:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_CALLEE_SAVES:
-    /* append to the functions already listed
-       in callee-saves */
-    setParseWithComma(&options.calleeSavesSet, cp);
-    break;
+      optimize.global_cse = 0;
+      break;
 
-  case P_EXCLUDE:
-    {
-      deleteSet(&options.excludeRegsSet);
-      setParseWithComma(&options.excludeRegsSet, cp);
-    }
-    break;
+    case P_NOOVERLAY:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.noOverlay = 1;
+      break;
+
+    case P_LESSPEDANTIC:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      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);
+      err = -1;
+      break;
+
+    case P_EXCLUDE:
+      {
+        deleteSet(&options.excludeRegsSet);
+        setParseWithComma(&options.excludeRegsSet, cp);
+        err = -1;
+      }
+      break;
+
+    case P_NOIV:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.noiv = 1;
+      break;
 
-  case P_NOIV:
-    options.noiv = 1;
-    break;
+    case P_LOOPREV:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      optimize.noLoopReverse = 1;
+      break;
 
-  case P_LOOPREV:
-    optimize.noLoopReverse = 1;
-    break;
+    case P_OVERLAY_:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
 
-  case P_OVERLAY_:
-    break; /* notyet */
+      break; /* notyet */
 
-  case P_DISABLEWARN:
-    if (sscanf(cp, "%d", &i) && (i<MAX_ERROR_WARNING))
+    case P_DISABLEWARN:
       {
-        setWarningDisabled(i);
+        int warn;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_INT != token.type)
+          {
+            err = 1;
+            break;
+          }
+        warn = token.val.int_val;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
+
+        if (warn < MAX_ERROR_WARNING)
+          setWarningDisabled(warn);
       }
-    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;
+      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;
+    case P_OPTCODESPEED:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      optimize.codeSpeed = 1;
+      optimize.codeSize = 0;
+      break;
+
+    case P_OPTCODESIZE:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      optimize.codeSpeed = 0;
+      optimize.codeSize = 1;
+      break;
+
+    case P_OPTCODEBALANCED:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      optimize.codeSpeed = 0;
+      optimize.codeSize = 0;
+      break;
+
+    case P_STD_C89:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.std_c99 = 0;
+      options.std_sdcc = 0;
+      break;
+
+    case P_STD_C99:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.std_c99 = 1;
+      options.std_sdcc = 0;
+      break;
+
+    case P_STD_SDCC89:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.std_c99 = 0;
+      options.std_sdcc = 1;
+      break;
+
+    case P_STD_SDCC99:
+      cp = get_pragma_token(cp, &token);
+      if (TOKEN_EOL != token.type)
+        {
+          err = 1;
+          break;
+        }
+
+      options.std_c99 = 1;
+      options.std_sdcc = 1;
+      break;
+
+    case P_CODESEG:
+    case P_CONSTSEG:
+      {
+        struct dbuf_s segname;
+
+        cp = get_pragma_token(cp, &token);
+        if (token.type == TOKEN_EOL)
+          {
+            err = 1;
+            break;
+          }
+
+        dbuf_init(&segname, 16);
+        dbuf_printf(&segname, "%-8s(CODE)", get_pragma_string(&token));
+
+        cp = get_pragma_token(cp, &token);
+        if (token.type != TOKEN_EOL)
+          {
+            dbuf_destroy(&segname);
+            err = 1;
+            break;
+          }
+
+        if (id == P_CODESEG)
+          options.code_seg = dbuf_detach(&segname);
+        else
+          options.const_seg = dbuf_detach(&segname);
+      }
+      break;
+
+    default:
+      processed = 0;
+      break;
     }
-    break;
-  }
+
+  get_pragma_token(cp, &token);
+
+  if (1 == err || (0 == err && token.type != TOKEN_EOL))
+    werror(W_BAD_PRAGMA_ARGUMENTS, name);
+
+  free_pragma_token(&token);
+  return processed;
 }
 
-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 pragma_tbl[] = {
+  { "save",           P_SAVE,         0, doPragma },
+  { "restore",        P_RESTORE,      0, doPragma },
+  { "noinduction",    P_NOINDUCTION,  0, doPragma },
+  { "noinvariant",    P_NOINVARIANT,  0, doPragma },
+  { "noloopreverse",  P_LOOPREV,      0, doPragma },
+  { "induction",      P_INDUCTION,    0, doPragma },
+  { "stackauto",      P_STACKAUTO,    0, doPragma },
+  { "nojtbound",      P_NOJTBOUND,    0, doPragma },
+  { "nogcse",         P_NOGCSE,       0, doPragma },
+  { "nooverlay",      P_NOOVERLAY,    0, doPragma },
+  { "callee_saves",   P_CALLEE_SAVES, 0, doPragma },
+  { "exclude",        P_EXCLUDE,      0, doPragma },
+  { "noiv",           P_NOIV,         0, doPragma },
+  { "overlay",        P_OVERLAY_,     0, doPragma },
+  { "less_pedantic",  P_LESSPEDANTIC, 0, doPragma },
+  { "disable_warning",P_DISABLEWARN,  0, doPragma },
+  { "opt_code_speed", P_OPTCODESPEED, 0, doPragma },
+  { "opt_code_size",  P_OPTCODESIZE,  0, doPragma },
+  { "opt_code_balanced", P_OPTCODEBALANCED, 0, doPragma },
+  { "std_c89",        P_STD_C89,      0, doPragma },
+  { "std_c99",        P_STD_C99,      0, doPragma },
+  { "std_sdcc89",     P_STD_SDCC89,   0, doPragma },
+  { "std_sdcc99",     P_STD_SDCC99,   0, doPragma },
+  { "codeseg",        P_CODESEG,      0, doPragma },
+  { "constseg",       P_CONSTSEG,     0, doPragma },
+  { NULL,             0,              0, NULL },
+};
 
-  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;
+/*
+ * returns 1 if the pragma was processed, 0 if not
+ */
+int
+process_pragma_tbl(const struct pragma_s *pragma_tbl, const char *s)
+{
+  struct pragma_token_s token;
   int i;
+  int ret = 0;
 
-  /* find the pragma */
-  while (strncmp(s, PRAGMA_STR, PRAGMA_LEN))
-    s++;
-  s += PRAGMA_LEN;
-
-  /* look for the directive */
-  while(isspace(*s))
-    s++;
+  init_pragma_token(&token);
 
-  cp = s;
-  /* look for the end of the directive */
-  while ((!isspace(*s)) && (*s != '\n'))
-    s++ ;
+  s = get_pragma_token(s, &token);
 
   /* skip separating whitespace */
-  while (isspace(*s) && (*s != '\n'))
+  while ('\n' != *s && isspace((unsigned char)*s))
     s++;
 
-  /* First give the port a chance */
-  if (port->process_pragma && !port->process_pragma(cp))
-    return 0;
-
-  for (i = 0; i < NELEM(pragma_tbl); i++)
+  for (i = 0; NULL != pragma_tbl[i].name; ++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 (strcmp(get_pragma_string(&token), pragma_tbl[i].name) == 0)
         {
           if (pragma_tbl[i].deprecated != 0)
             werror(W_DEPRECATED_PRAGMA, pragma_tbl[i].name);
 
-          doPragma(pragma_tbl[i].id, s);
-          return 0;
+          ret = (*pragma_tbl[i].func)(pragma_tbl[i].id, pragma_tbl[i].name, s);
+          break;
         }
     }
 
-  werror(W_UNKNOWN_PRAGMA, cp);
-  return 0;
+  free_pragma_token(&token);
+  return ret;
+}
+
+static int process_pragma(const char *s)
+{
+  struct pragma_token_s token;
+
+  init_pragma_token(&token);
+
+  s = get_pragma_token(s, &token);
+  if (0 != strcmp("#pragma", get_pragma_string(&token)))
+    {
+      /* Oops, womething went totally wrong - internal error */
+      wassertl(0, "pragma parser internal error");
+    }
+
+  /* skip spaces */
+  while ('\n' != *s && isspace((unsigned char)*s))
+    ++s;
+
+  /* First give the port a chance */
+  if (port->process_pragma && port->process_pragma(s))
+    return 1;
+
+  if (process_pragma_tbl(pragma_tbl, s))
+    {
+      return 1;
+    }
+  else
+    {
+      werror(W_UNKNOWN_PRAGMA, s);
+      return 0;
+    }
 }
 
 /* will return 1 if the string is a part
    of a target specific keyword */
-static int isTargetKeyword(char *s)
+static int isTargetKeyword(const char *s)
 {
   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, */
@@ -864,16 +1139,13 @@ int yyerror(char *s)
 {
   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 */
-  }
+  if(options.vc_err_style)
+    fprintf(stderr, "\n%s(%d) : %s: token -> '%s' ; column %d\n",
+      lexFilename, lexLineno, s, yytext, column);
+  else
+    fprintf(stderr, "\n%s:%d: %s: token -> '%s' ; column %d\n",
+      lexFilename, lexLineno, s ,yytext, column);
+  fatalError++;
+
   return 0;
 }