#include "scanstrbuf.h"
#include "symtab.h"
#include "pragma.h"
+#include "wrappedcall.h"
typedef enum {
PRAGMA_ILLEGAL = -1,
PRAGMA_ALIGN,
+ PRAGMA_ALLOW_EAGER_INLINE,
PRAGMA_BSS_NAME,
PRAGMA_BSSSEG, /* obsolete */
PRAGMA_CHARMAP,
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 */
PRAGMA_STATIC_LOCALS,
PRAGMA_STATICLOCALS, /* obsolete */
PRAGMA_WARN,
+ PRAGMA_WRAPPED_CALL,
PRAGMA_WRITABLE_STRINGS,
PRAGMA_ZPSYM,
PRAGMA_COUNT
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 */
}
/* 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;
}
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:
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;
} 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");
}
if (!GetNumber (B, &Index)) {
return;
}
- if (Index < 1 || Index > 255) {
- if (Index == 0) {
- /* For groepaz */
- Error ("Remapping 0 is not allowed");
- } else {
- Error ("Character index out of range");
- }
+ if (Index < 0 || Index > 255) {
+ Error ("Character index out of range");
return;
}
if (!GetNumber (B, &C)) {
return;
}
- if (C < 1 || C > 255) {
- if (C == 0) {
- /* For groepaz */
- Error ("Remapping 0 is not allowed");
- } else {
- Error ("Character code out of range");
- }
+ if (C < 0 || C > 255) {
+ Error ("Character code out of range");
return;
}
+ /* Warn about remapping character code 0x00
+ ** (except when remapping it back to itself).
+ */
+ if (Index + C != 0 && IS_Get (&WarnRemapZero)) {
+ if (Index == 0) {
+ Warning ("Remapping from 0 is dangerous with string functions");
+ }
+ else if (C == 0) {
+ Warning ("Remapping to 0 can make string functions stop unexpectedly");
+ }
+ }
+
/* Remap the character */
TgtTranslateSet ((unsigned) Index, (unsigned char) C);
}
+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 */
{
** 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;
}
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 */
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;
FlagPragma (&B, &StaticLocals);
break;
+ case PRAGMA_WRAPPED_CALL:
+ WrappedCallPragma(&B);
+ break;
+
case PRAGMA_WARN:
WarnPragma (&B);
break;