]> git.sur5r.net Git - cc65/blobdiff - src/ld65/scanner.c
Corrected indentation - no code change.
[cc65] / src / ld65 / scanner.c
index 56870f11e5abd0e237a701a1d3ce0bcac4860a93..b27ec62c5f7661c79f8cfc9e7ba29ba9a9686f74 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -40,6 +40,8 @@
 #include <ctype.h>
 
 /* common */
+#include "chartype.h"
+#include "strbuf.h"
 #include "xsprintf.h"
 
 /* ld65 */
@@ -56,8 +58,8 @@
 
 
 /* Current token and attributes */
-unsigned        CfgTok;
-char                   CfgSVal [CFG_MAX_IDENT_LEN+1];
+cfgtok_t       CfgTok;
+StrBuf          CfgSVal = STATIC_STRBUF_INITIALIZER;
 unsigned long   CfgIVal;
 
 /* Error location */
@@ -85,14 +87,15 @@ static FILE*                InputFile       = 0;
 void CfgWarning (const char* Format, ...)
 /* Print a warning message adding file name and line number of the config file */
 {
-    char Buf [512];
+    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
     va_list ap;
 
     va_start (ap, Format);
-    xvsprintf (Buf, sizeof (Buf), Format, ap);
+    SB_VPrintf (&Buf, Format, ap);
     va_end (ap);
 
-    Warning ("%s(%u): %s", CfgName, CfgErrorLine, Buf);
+    Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
+    SB_Done (&Buf);
 }
 
 
@@ -100,14 +103,15 @@ void CfgWarning (const char* Format, ...)
 void CfgError (const char* Format, ...)
 /* Print an error message adding file name and line number of the config file */
 {
-    char Buf [512];
+    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
     va_list ap;
 
     va_start (ap, Format);
-    xvsprintf (Buf, sizeof (Buf), Format, ap);
+    SB_VPrintf (&Buf, Format, ap);
     va_end (ap);
 
-    Error ("%s(%u): %s", CfgName, CfgErrorLine, Buf);
+    Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf));
+    SB_Done (&Buf);
 }
 
 
@@ -125,7 +129,7 @@ static void NextChar (void)
        /* Read from buffer */
        C = (unsigned char)(*CfgBuf);
        if (C == 0) {
-           C = EOF;
+           C = EOF;
        } else {
            ++CfgBuf;
        }
@@ -160,12 +164,75 @@ static unsigned DigitVal (int C)
 
 
 
-void CfgNextTok (void)
-/* Read the next token from the input stream */
+static void StrVal (void)
+/* Parse a string value and expand escape sequences */
 {
-    unsigned I;
+    /* Skip the starting double quotes */
+    NextChar ();
+
+    /* Read input chars */
+    SB_Clear (&CfgSVal);
+    while (C != '\"') {
+        switch (C) {
+
+            case EOF:
+            case '\n':
+                CfgError ("Unterminated string");
+                break;
+
+            case '%':
+                NextChar ();
+                switch (C) {
+
+                    case EOF:
+                    case '\n':
+                    case '\"':
+                        CfgError ("Unterminated '%%' escape sequence");
+                        break;
+
+                    case '%':
+                        SB_AppendChar (&CfgSVal, '%');
+                        NextChar ();
+                        break;
+
+                    case 'O':
+                        /* Replace by output file */
+                        if (OutputName) {
+                            SB_AppendStr (&CfgSVal, OutputName);
+                        }
+                        NextChar ();
+                        break;
+
+                    default:
+                        CfgWarning ("Unkown escape sequence `%%%c'", C);
+                        SB_AppendChar (&CfgSVal, '%');
+                        SB_AppendChar (&CfgSVal, C);
+                        NextChar ();
+                        break;
+                }
+                break;
+
+            default:
+                SB_AppendChar (&CfgSVal, C);
+                NextChar ();
+        }
+    }
+
+    /* Skip the terminating double quotes */
+    NextChar ();
+
+    /* Terminate the string */
+    SB_Terminate (&CfgSVal);
+
+    /* We've read a string value */
+    CfgTok = CFGTOK_STRCON;
+}
 
 
+
+void CfgNextTok (void)
+/* Read the next token from the input stream */
+{
 Again:
     /* Skip whitespace */
     while (isspace (C)) {
@@ -177,17 +244,15 @@ Again:
     CfgErrorCol  = InputCol;
 
     /* Identifier? */
-    if (C == '_' || isalpha (C)) {
+    if (C == '_' || IsAlpha (C)) {
 
        /* Read the identifier */
-       I = 0;
-       while (C == '_' || isalnum (C)) {
-           if (I < CFG_MAX_IDENT_LEN) {
-               CfgSVal [I++] = C;
-           }
+       SB_Clear (&CfgSVal);
+       while (C == '_' || IsAlNum (C)) {
+            SB_AppendChar (&CfgSVal, C);
            NextChar ();
        }
-       CfgSVal [I] = '\0';
+               SB_Terminate (&CfgSVal);
        CfgTok = CFGTOK_IDENT;
        return;
     }
@@ -196,7 +261,7 @@ Again:
     if (C == '$') {
        NextChar ();
        if (!isxdigit (C)) {
-           Error ("%s(%u): Hex digit expected", CfgName, InputLine);
+           CfgError ("Hex digit expected");
        }
        CfgIVal = 0;
        while (isxdigit (C)) {
@@ -221,6 +286,36 @@ Again:
     /* Other characters */
     switch (C) {
 
+        case '-':
+            NextChar ();
+            CfgTok = CFGTOK_MINUS;
+            break;
+
+        case '+':
+            NextChar ();
+            CfgTok = CFGTOK_PLUS;
+            break;
+
+        case '*':
+            NextChar ();
+            CfgTok = CFGTOK_MUL;
+            break;
+
+        case '/':
+            NextChar ();
+            CfgTok = CFGTOK_DIV;
+            break;
+
+       case '(':
+           NextChar ();
+           CfgTok = CFGTOK_LPAR;
+           break;
+
+       case ')':
+           NextChar ();
+           CfgTok = CFGTOK_RPAR;
+           break;
+
        case '{':
            NextChar ();
            CfgTok = CFGTOK_LCURLY;
@@ -254,23 +349,10 @@ Again:
         case ':':
            NextChar ();
            CfgTok = CFGTOK_COLON;
-           break;
+           break;
 
         case '\"':
-           NextChar ();
-           I = 0;
-           while (C != '\"') {
-               if (C == EOF || C == '\n') {
-                   Error ("%s(%u): Unterminated string", CfgName, InputLine);
-               }
-               if (I < CFG_MAX_IDENT_LEN) {
-                   CfgSVal [I++] = C;
-               }
-               NextChar ();
-           }
-                   NextChar ();
-           CfgSVal [I] = '\0';
-           CfgTok = CFGTOK_STRCON;
+            StrVal ();
            break;
 
         case '#':
@@ -291,13 +373,13 @@ Again:
                case 'O':
                    NextChar ();
                    if (OutputName) {
-                       strncpy (CfgSVal, OutputName, CFG_MAX_IDENT_LEN);
-                       CfgSVal [CFG_MAX_IDENT_LEN] = '\0';
+                        SB_CopyStr (&CfgSVal, OutputName);
                    } else {
-                       CfgSVal [0] = '\0';
+                       SB_Clear (&CfgSVal);
                    }
+                    SB_Terminate (&CfgSVal);
                    CfgTok = CFGTOK_STRCON;
-                   break;
+                   break;
 
                case 'S':
                    NextChar ();
@@ -315,18 +397,18 @@ Again:
            break;
 
        default:
-           Error ("%s(%u): Invalid character `%c'", CfgName, InputLine, C);
+           CfgError ("Invalid character `%c'", C);
 
     }
 }
 
 
 
-void CfgConsume (unsigned T, const char* Msg)
+void CfgConsume (cfgtok_t T, const char* Msg)
 /* Skip a token, print an error message if not found */
 {
     if (CfgTok != T) {
-               CfgError (Msg);
+               CfgError ("%s", Msg);
     }
     CfgNextTok ();
 }
@@ -418,16 +500,12 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
     if (CfgTok == CFGTOK_IDENT) {
 
        /* Make it upper case */
-       I = 0;
-       while (CfgSVal [I]) {
-           CfgSVal [I] = toupper (CfgSVal [I]);
-           ++I;
-       }
+        SB_ToUpper (&CfgSVal);
 
                /* Linear search */
        for (I = 0; I < Size; ++I) {
-           if (strcmp (CfgSVal, Table [I].Ident) == 0) {
-               CfgTok = Table [I].Tok;
+                   if (SB_CompareStr (&CfgSVal, Table[I].Ident) == 0) {
+               CfgTok = Table[I].Tok;
                return;
            }
        }
@@ -435,7 +513,7 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
     }
 
     /* Not found or no identifier */
-    Error ("%s(%u): %s expected", CfgName, InputLine, Name);
+    CfgError ("%s expected", Name);
 }
 
 
@@ -475,7 +553,13 @@ void CfgSetName (const char* Name)
 const char* CfgGetName (void)
 /* Get the name of the config file */
 {
-    return CfgName? CfgName : "";
+    if (CfgName) {
+       return CfgName;
+    } else if (CfgBuf) {
+       return "[builtin config]";
+    } else {
+       return "";
+    }
 }
 
 
@@ -535,3 +619,4 @@ void CfgCloseInput (void)
 
 
 
+