default:
- Error ("Unexpected feature token");
+ FAIL ("Unexpected feature token");
}
/* Skip the semicolon */
while (CfgTok == CFGTOK_IDENT) {
long Val = 0L;
- int Weak;
+ int Weak = 0;
/* Remember the name */
unsigned Name = GetStringId (CfgSVal);
Val = CfgIVal;
CfgNextTok ();
- /* Generate an export with the given value */
- CreateConstExport (Name, Val);
-
} else {
/* Bitmask to remember the attributes we got already */
Weak = 0;
}
- /* Generate an export with the given value */
+ }
+
+ /* Check if the symbol is already defined */
+ if (FindExport (Name) != 0) {
+ /* If the symbol is not marked as weak, this is an error.
+ * Otherwise ignore the symbol from the config.
+ */
+ if (!Weak) {
+ CfgError ("Symbol `%s' is already defined", GetString (Name));
+ }
+ } else {
+ /* The symbol is undefined, generate an export */
CreateConstExport (Name, Val);
}
#include <errno.h>
/* common */
+#include "chartype.h"
#include "cmdline.h"
#include "filetype.h"
#include "libdefs.h"
" -(\t\t\tStart a library group\n"
" -)\t\t\tEnd a library group\n"
" -C name\t\tUse linker config file\n"
+ " -D sym=val\t\tDefine a symbol\n"
" -L path\t\tSpecify a library search path\n"
" -Ln name\t\tCreate a VICE label file\n"
" -S addr\t\tSet the default start address\n"
" --cfg-path path\tSpecify a config file search path\n"
" --config name\t\tUse linker config file\n"
" --dbgfile name\tGenerate debug information\n"
+ " --define sym=val\tDefine a symbol\n"
" --dump-config name\tDump a builtin configuration\n"
" --end-group\t\tEnd a library group\n"
" --help\t\tHelp (this text)\n"
+static void DefineSymbol (const char* Def)
+/* Define a symbol from the command line */
+{
+ const char* P;
+ unsigned I;
+ long Val;
+ StrBuf SymName = AUTO_STRBUF_INITIALIZER;
+
+
+ /* The symbol must start with a character or underline */
+ if (Def [0] != '_' && !IsAlpha (Def [0])) {
+ InvDef (Def);
+ }
+ P = Def;
+
+ /* Copy the symbol, checking the remainder */
+ I = 0;
+ while (IsAlNum (*P) || *P == '_') {
+ SB_AppendChar (&SymName, *P++);
+ }
+ SB_Terminate (&SymName);
+
+ /* Do we have a value given? */
+ if (*P != '=') {
+ InvDef (Def);
+ } else {
+ /* We have a value */
+ ++P;
+ if (*P == '$') {
+ ++P;
+ if (sscanf (P, "%lx", &Val) != 1) {
+ InvDef (Def);
+ }
+ } else {
+ if (sscanf (P, "%li", &Val) != 1) {
+ InvDef (Def);
+ }
+ }
+ }
+
+ /* Define the new symbol */
+ CreateConstExport (GetStringId (SB_GetConstBuf (&SymName)), Val);
+}
+
+
+
static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg)
/* Specify a config file search path */
{
+static void OptDefine (const char* Opt attribute ((unused)), const char* Arg)
+/* Define a symbol on the command line */
+{
+ DefineSymbol (Arg);
+}
+
+
+
static void OptDumpConfig (const char* Opt attribute ((unused)), const char* Arg)
/* Dump a builtin linker configuration */
{
{ "--cfg-path", 1, OptCfgPath },
{ "--config", 1, OptConfig },
{ "--dbgfile", 1, OptDbgFile },
+ { "--define", 1, OptDefine },
{ "--dump-config", 1, OptDumpConfig },
{ "--end-group", 0, OptEndGroup },
{ "--help", 0, OptHelp },
OptConfig (Arg, GetArg (&I, 2));
break;
+ case 'D':
+ OptDefine (Arg, GetArg (&I, 2));
+ break;
+
case 'L':
switch (Arg [2]) {
/* ## The first one is obsolete and will go */