]> git.sur5r.net Git - cc65/blobdiff - src/cc65/pragma.c
remove TABs
[cc65] / src / cc65 / pragma.c
index 86739ce22887db1bdb8692d5f8740d8be559317d..b05ef6122bb4fce4efc24bd4f649999e395f16cc 100644 (file)
@@ -51,6 +51,7 @@
 #include "scanstrbuf.h"
 #include "symtab.h"
 #include "pragma.h"
+#include "wrappedcall.h"
 
 
 
@@ -64,6 +65,7 @@
 typedef enum {
     PRAGMA_ILLEGAL = -1,
     PRAGMA_ALIGN,
+    PRAGMA_ALLOW_EAGER_INLINE,
     PRAGMA_BSS_NAME,
     PRAGMA_BSSSEG,                                      /* obsolete */
     PRAGMA_CHARMAP,
@@ -74,10 +76,12 @@ typedef enum {
     PRAGMA_CODESIZE,
     PRAGMA_DATA_NAME,
     PRAGMA_DATASEG,                                     /* obsolete */
+    PRAGMA_INLINE_STDFUNCS,
     PRAGMA_LOCAL_STRINGS,
+    PRAGMA_MESSAGE,
     PRAGMA_OPTIMIZE,
-    PRAGMA_REGVARADDR,
     PRAGMA_REGISTER_VARS,
+    PRAGMA_REGVARADDR,
     PRAGMA_REGVARS,                                     /* obsolete */
     PRAGMA_RODATA_NAME,
     PRAGMA_RODATASEG,                                   /* obsolete */
@@ -86,6 +90,7 @@ typedef enum {
     PRAGMA_STATIC_LOCALS,
     PRAGMA_STATICLOCALS,                                /* obsolete */
     PRAGMA_WARN,
+    PRAGMA_WRAPPED_CALL,
     PRAGMA_WRITABLE_STRINGS,
     PRAGMA_ZPSYM,
     PRAGMA_COUNT
@@ -96,31 +101,35 @@ static const struct Pragma {
     const char* Key;            /* Keyword */
     pragma_t    Tok;            /* Token */
 } Pragmas[PRAGMA_COUNT] = {
-    { "align",                  PRAGMA_ALIGN            },
-    { "bss-name",               PRAGMA_BSS_NAME         },
-    { "bssseg",                 PRAGMA_BSSSEG           },      /* obsolete */
-    { "charmap",                PRAGMA_CHARMAP          },
-    { "check-stack",            PRAGMA_CHECK_STACK      },
-    { "checkstack",             PRAGMA_CHECKSTACK       },      /* obsolete */
-    { "code-name",              PRAGMA_CODE_NAME        },
-    { "codeseg",                PRAGMA_CODESEG          },      /* obsolete */
-    { "codesize",               PRAGMA_CODESIZE         },
-    { "data-name",              PRAGMA_DATA_NAME        },
-    { "dataseg",                PRAGMA_DATASEG          },      /* obsolete */
-    { "local-strings",          PRAGMA_LOCAL_STRINGS    },
-    { "optimize",               PRAGMA_OPTIMIZE         },
-    { "register-vars",          PRAGMA_REGISTER_VARS    },
-    { "regvaraddr",             PRAGMA_REGVARADDR       },
-    { "regvars",                PRAGMA_REGVARS          },      /* obsolete */
-    { "rodata-name",            PRAGMA_RODATA_NAME      },
-    { "rodataseg",              PRAGMA_RODATASEG        },      /* obsolete */
-    { "signed-chars",           PRAGMA_SIGNED_CHARS     },
-    { "signedchars",            PRAGMA_SIGNEDCHARS      },      /* obsolete */
-    { "static-locals",          PRAGMA_STATIC_LOCALS    },
-    { "staticlocals",           PRAGMA_STATICLOCALS     },      /* obsolete */
-    { "warn",                   PRAGMA_WARN             },
-    { "writable-strings",       PRAGMA_WRITABLE_STRINGS },
-    { "zpsym",                  PRAGMA_ZPSYM            },
+    { "align",                  PRAGMA_ALIGN              },
+    { "allow-eager-inline",     PRAGMA_ALLOW_EAGER_INLINE },
+    { "bss-name",               PRAGMA_BSS_NAME           },
+    { "bssseg",                 PRAGMA_BSSSEG             },      /* obsolete */
+    { "charmap",                PRAGMA_CHARMAP            },
+    { "check-stack",            PRAGMA_CHECK_STACK        },
+    { "checkstack",             PRAGMA_CHECKSTACK         },      /* obsolete */
+    { "code-name",              PRAGMA_CODE_NAME          },
+    { "codeseg",                PRAGMA_CODESEG            },      /* obsolete */
+    { "codesize",               PRAGMA_CODESIZE           },
+    { "data-name",              PRAGMA_DATA_NAME          },
+    { "dataseg",                PRAGMA_DATASEG            },      /* obsolete */
+    { "inline-stdfuncs",        PRAGMA_INLINE_STDFUNCS    },
+    { "local-strings",          PRAGMA_LOCAL_STRINGS      },
+    { "message",                PRAGMA_MESSAGE            },
+    { "optimize",               PRAGMA_OPTIMIZE           },
+    { "register-vars",          PRAGMA_REGISTER_VARS      },
+    { "regvaraddr",             PRAGMA_REGVARADDR         },
+    { "regvars",                PRAGMA_REGVARS            },      /* obsolete */
+    { "rodata-name",            PRAGMA_RODATA_NAME        },
+    { "rodataseg",              PRAGMA_RODATASEG          },      /* obsolete */
+    { "signed-chars",           PRAGMA_SIGNED_CHARS       },
+    { "signedchars",            PRAGMA_SIGNEDCHARS        },      /* obsolete */
+    { "static-locals",          PRAGMA_STATIC_LOCALS      },
+    { "staticlocals",           PRAGMA_STATICLOCALS       },      /* obsolete */
+    { "warn",                   PRAGMA_WARN               },
+    { "wrapped-call",           PRAGMA_WRAPPED_CALL       },
+    { "writable-strings",       PRAGMA_WRITABLE_STRINGS   },
+    { "zpsym",                  PRAGMA_ZPSYM              },
 };
 
 /* Result of ParsePushPop */
@@ -347,7 +356,7 @@ static int BoolKeyword (StrBuf* Ident)
     }
 
     /* Error */
-    Error ("Pragma argument must be one of `on', `off', `true' or `false'");
+    Error ("Pragma argument must be one of 'on', 'off', 'true' or 'false'");
     return 0;
 }
 
@@ -379,11 +388,11 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*))
 static void SegNamePragma (StrBuf* B, segment_t Seg)
 /* Handle a pragma that expects a segment name parameter */
 {
-    StrBuf      S = AUTO_STRBUF_INITIALIZER;
     const char* Name;
+    StrBuf S = AUTO_STRBUF_INITIALIZER;
+    int Push = 0;
 
     /* Check for the "push" or "pop" keywords */
-    int Push = 0;
     switch (ParsePushPop (B)) {
 
         case PP_NONE:
@@ -396,7 +405,13 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
         case PP_POP:
             /* Pop the old value and output it */
             PopSegName (Seg);
-            g_segname (Seg);
+
+            /* BSS variables are output at the end of the compilation.  Don't
+            ** bother to change their segment, now.
+            */
+            if (Seg != SEG_BSS) {
+                g_segname (Seg);
+            }
 
             /* Done */
             goto ExitPoint;
@@ -427,12 +442,97 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
         } else {
             SetSegName (Seg, Name);
         }
-        g_segname (Seg);
+
+        /* BSS variables are output at the end of the compilation.  Don't
+        ** bother to change their segment, now.
+        */
+        if (Seg != SEG_BSS) {
+            g_segname (Seg);
+        }
+
+    } else {
+
+        /* Segment name is invalid */
+        Error ("Illegal segment name: '%s'", Name);
+
+    }
+
+ExitPoint:
+    /* Call the string buf destructor */
+    SB_Done (&S);
+}
+
+
+static void WrappedCallPragma (StrBuf* B)
+/* Handle the wrapped-call pragma */
+{
+    StrBuf      S = AUTO_STRBUF_INITIALIZER;
+    const char *Name;
+    long Val;
+    SymEntry *Entry;
+
+    /* Check for the "push" or "pop" keywords */
+    switch (ParsePushPop (B)) {
+
+        case PP_NONE:
+            Error ("Push or pop required");
+            break;
+
+        case PP_PUSH:
+            break;
+
+        case PP_POP:
+            PopWrappedCall();
+
+            /* Done */
+            goto ExitPoint;
+
+        case PP_ERROR:
+            /* Bail out */
+            goto ExitPoint;
+
+        default:
+            Internal ("Invalid result from ParsePushPop");
+
+    }
+
+    /* A symbol argument must follow */
+    if (!SB_GetSym (B, &S, NULL)) {
+        goto ExitPoint;
+    }
+
+    /* Skip the following comma */
+    if (!GetComma (B)) {
+        /* Error already flagged by GetComma */
+        Error ("Value required for wrapped-call identifier");
+        goto ExitPoint;
+    }
+
+    if (!GetNumber (B, &Val)) {
+        Error ("Value required for wrapped-call identifier");
+        goto ExitPoint;
+    }
+
+    if (Val < 0 || Val > 255) {
+        Error ("Identifier must be between 0-255");
+        goto ExitPoint;
+    }
+
+    /* Get the string */
+    Name = SB_GetConstBuf (&S);
+    Entry = FindSym(Name);
+
+    /* Check if the name is valid */
+    if (Entry && Entry->Flags & SC_FUNC) {
+
+        PushWrappedCall(Entry, (unsigned char) Val);
+        Entry->Flags |= SC_REF;
+        Entry->V.F.Func->Flags |= FD_CALL_WRAPPER;
 
     } else {
 
         /* Segment name is invalid */
-        Error ("Illegal segment name: `%s'", Name);
+        Error ("Wrapped-call target does not exist or is not a function");
 
     }
 
@@ -652,6 +752,13 @@ static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High)
 
 
 
+static void MakeMessage (const char* Message)
+{
+    fprintf (stderr, "%s(%u): Note: %s\n", GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Message);
+}
+
+
+
 static void ParsePragma (void)
 /* Parse the contents of the _Pragma statement */
 {
@@ -681,7 +788,7 @@ static void ParsePragma (void)
         ** for unknown pragmas, but warn about them if enabled (the default).
         */
         if (IS_Get (&WarnUnknownPragma)) {
-            Warning ("Unknown pragma `%s'", SB_GetConstBuf (&Ident));
+            Warning ("Unknown pragma '%s'", SB_GetConstBuf (&Ident));
         }
         goto ExitPoint;
     }
@@ -703,6 +810,10 @@ static void ParsePragma (void)
             IntPragma (&B, &DataAlignment, 1, 4096);
             break;
 
+        case PRAGMA_ALLOW_EAGER_INLINE:
+            FlagPragma (&B, &EagerlyInlineFuncs);
+            break;
+
         case PRAGMA_BSSSEG:
             Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead");
             /* FALLTHROUGH */
@@ -739,10 +850,18 @@ static void ParsePragma (void)
             SegNamePragma (&B, SEG_DATA);
             break;
 
+        case PRAGMA_INLINE_STDFUNCS:
+            FlagPragma (&B, &InlineStdFuncs);
+            break;
+
         case PRAGMA_LOCAL_STRINGS:
             FlagPragma (&B, &LocalStrings);
             break;
 
+        case PRAGMA_MESSAGE:
+            StringPragma (&B, MakeMessage);
+            break;
+
         case PRAGMA_OPTIMIZE:
             FlagPragma (&B, &Optimize);
             break;
@@ -779,6 +898,10 @@ static void ParsePragma (void)
             FlagPragma (&B, &StaticLocals);
             break;
 
+        case PRAGMA_WRAPPED_CALL:
+            WrappedCallPragma(&B);
+            break;
+
         case PRAGMA_WARN:
             WarnPragma (&B);
             break;