X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fmain.c;h=10fff402e6c05a0d484397405ca2996453822e1f;hb=0807da74bd7c3ebe3e6e75129a07a810b17174b2;hp=a424d37f1342d864a9e3b779f9f313da3d00f2d0;hpb=9cd0b7705ca56486469724e85702f8ed08c7aa51;p=cc65 diff --git a/src/ld65/main.c b/src/ld65/main.c index a424d37f1..10fff402e 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -1,15 +1,15 @@ /*****************************************************************************/ -/* */ -/* main.c */ -/* */ +/* */ +/* main.c */ +/* */ /* Main program for the ld65 linker */ -/* */ -/* */ -/* */ -/* (C) 1998-2005 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* */ +/* */ +/* */ +/* (C) 1998-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,6 +39,8 @@ #include /* common */ +#include "addrsize.h" +#include "chartype.h" #include "cmdline.h" #include "filetype.h" #include "libdefs.h" @@ -89,37 +91,44 @@ static unsigned LibFiles = 0; /* Count of library files linked */ static void Usage (void) /* Print usage information and exit */ { - fprintf (stderr, - "Usage: %s [options] module ...\n" - "Short options:\n" - " -C name\t\tUse linker config file\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" - " -V\t\t\tPrint the linker version\n" - " -h\t\t\tHelp (this text)\n" - " -m name\t\tCreate a map file\n" - " -o name\t\tName the default output file\n" - " -t sys\t\tSet the target system\n" - " -v\t\t\tVerbose mode\n" - " -vm\t\t\tVerbose map file\n" - "\n" - "Long options:\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" - " --dump-config name\tDump a builtin configuration\n" - " --help\t\tHelp (this text)\n" - " --lib file\t\tLink this library\n" - " --lib-path path\tSpecify a library search path\n" - " --mapfile name\tCreate a map file\n" - " --module-id id\tSpecify a module id\n" - " --obj file\t\tLink this object file\n" - " --obj-path path\tSpecify an object file search path\n" - " --start-addr addr\tSet the default start address\n" - " --target sys\t\tSet the target system\n" - " --version\t\tPrint the linker version\n", - ProgName); + printf ("Usage: %s [options] module ...\n" + "Short options:\n" + " -(\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" + " -V\t\t\tPrint the linker version\n" + " -h\t\t\tHelp (this text)\n" + " -m name\t\tCreate a map file\n" + " -o name\t\tName the default output file\n" + " -t sys\t\tSet the target system\n" + " -u sym\t\tForce an import of symbol `sym'\n" + " -v\t\t\tVerbose mode\n" + " -vm\t\t\tVerbose map file\n" + "\n" + "Long options:\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" + " --force-import sym\tForce an import of symbol `sym'\n" + " --help\t\tHelp (this text)\n" + " --lib file\t\tLink this library\n" + " --lib-path path\tSpecify a library search path\n" + " --mapfile name\tCreate a map file\n" + " --module-id id\tSpecify a module id\n" + " --obj file\t\tLink this object file\n" + " --obj-path path\tSpecify an object file search path\n" + " --start-addr addr\tSet the default start address\n" + " --start-group\t\tStart a library group\n" + " --target sys\t\tSet the target system\n" + " --version\t\tPrint the linker version\n", + ProgName); } @@ -168,11 +177,11 @@ static void LinkFile (const char* Name, FILETYPE Type) switch (Type) { case FILETYPE_LIB: - PathName = SearchFile (Name, SEARCH_LIB); + PathName = SearchFile (LibSearchPath, Name); break; case FILETYPE_OBJ: - PathName = SearchFile (Name, SEARCH_OBJ); + PathName = SearchFile (ObjSearchPath, Name); break; default: @@ -224,10 +233,56 @@ static void LinkFile (const char* Name, FILETYPE Type) +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 */ { - AddSearchPath (Arg, SEARCH_CFG); + AddSearchPath (CfgSearchPath, Arg); } @@ -241,7 +296,7 @@ static void OptConfig (const char* Opt attribute ((unused)), const char* Arg) Error ("Cannot use -C/-t twice"); } /* Search for the file */ - PathName = SearchFile (Arg, SEARCH_CFG); + PathName = SearchFile (CfgSearchPath, Arg); if (PathName == 0) { Error ("Cannot find config file `%s'", Arg); } else { @@ -259,6 +314,14 @@ static void OptDbgFile (const char* Opt attribute ((unused)), const char* Arg) +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 */ { @@ -274,6 +337,53 @@ static void OptDumpConfig (const char* Opt attribute ((unused)), const char* Arg +static void OptEndGroup (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* End a library group */ +{ + LibEndGroup (); +} + + + +static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg) +/* Force an import of a symbol */ +{ + /* An optional address size may be specified */ + const char* ColPos = strchr (Arg, ':'); + if (ColPos == 0) { + + /* Use default address size (which for now is always absolute + * addressing) + */ + InsertImport (GenImport (Arg, ADDR_SIZE_ABS)); + + } else { + + char* A; + + /* Get the address size and check it */ + unsigned char AddrSize = AddrSizeFromStr (ColPos+1); + if (AddrSize == ADDR_SIZE_INVALID) { + Error ("Invalid address size `%s'", ColPos+1); + } + + /* Create a copy of the argument */ + A = xstrdup (Arg); + + /* We need just the symbol */ + A[ColPos - Arg] = '\0'; + + /* Generate the import */ + InsertImport (GenImport (A, AddrSize)); + + /* Delete the copy of the argument */ + xfree (A); + } +} + + + static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ @@ -295,7 +405,7 @@ static void OptLib (const char* Opt attribute ((unused)), const char* Arg) static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg) /* Specify a library file search path */ { - AddSearchPath (Arg, SEARCH_LIB); + AddSearchPath (LibSearchPath, Arg); } @@ -331,7 +441,7 @@ static void OptObj (const char* Opt attribute ((unused)), const char* Arg) static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg) /* Specify an object file search path */ { - AddSearchPath (Arg, SEARCH_OBJ); + AddSearchPath (ObjSearchPath, Arg); } @@ -345,6 +455,15 @@ static void OptStartAddr (const char* Opt, const char* Arg) +static void OptStartGroup (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Start a library group */ +{ + LibStartGroup (); +} + + + static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { @@ -371,8 +490,8 @@ static void OptVersion (const char* Opt attribute ((unused)), /* Print the assembler version */ { fprintf (stderr, - "ld65 V%u.%u.%u - (C) Copyright 1998-2002 Ullrich von Bassewitz\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + "ld65 V%s - (C) Copyright 1998-2009, Ullrich von Bassewitz\n", + GetVersionAsString ()); } @@ -385,7 +504,10 @@ int main (int argc, char* argv []) { "--cfg-path", 1, OptCfgPath }, { "--config", 1, OptConfig }, { "--dbgfile", 1, OptDbgFile }, + { "--define", 1, OptDefine }, { "--dump-config", 1, OptDumpConfig }, + { "--end-group", 0, OptEndGroup }, + { "--force-import", 1, OptForceImport }, { "--help", 0, OptHelp }, { "--lib", 1, OptLib }, { "--lib-path", 1, OptLibPath }, @@ -394,11 +516,13 @@ int main (int argc, char* argv []) { "--obj", 1, OptObj }, { "--obj-path", 1, OptObjPath }, { "--start-addr", 1, OptStartAddr }, + { "--start-group", 0, OptStartGroup }, { "--target", 1, OptTarget }, { "--version", 0, OptVersion }, }; unsigned I; + unsigned MemoryAreaOverflows; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "ld65"); @@ -426,6 +550,14 @@ int main (int argc, char* argv []) LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; + case '(': + OptStartGroup (Arg, 0); + break; + + case ')': + OptEndGroup (Arg, 0); + break; + case 'h': case '?': OptHelp (Arg, 0); @@ -441,16 +573,20 @@ int main (int argc, char* argv []) case 't': if (CfgAvail ()) { - Error ("Cannot use -C/-t twice"); + Error ("Cannot use -C/-t twice"); } OptTarget (Arg, GetArg (&I, 2)); break; + case 'u': + OptForceImport (Arg, GetArg (&I, 2)); + break; + case 'v': switch (Arg [2]) { - case 'm': VerboseMap = 1; break; - case '\0': ++Verbosity; break; - default: UnknownOption (Arg); + case 'm': VerboseMap = 1; break; + case '\0': ++Verbosity; break; + default: UnknownOption (Arg); } break; @@ -458,11 +594,15 @@ int main (int argc, char* argv []) OptConfig (Arg, GetArg (&I, 2)); break; - case 'L': + case 'D': + OptDefine (Arg, GetArg (&I, 2)); + break; + + case 'L': switch (Arg [2]) { /* ## The first one is obsolete and will go */ - case 'n': LabelFileName = GetArg (&I, 3); break; - default: OptLibPath (Arg, GetArg (&I, 2)); break; + case 'n': LabelFileName = GetArg (&I, 3); break; + default: OptLibPath (Arg, GetArg (&I, 2)); break; } break; @@ -500,14 +640,20 @@ int main (int argc, char* argv []) Error ("Memory configuration missing"); } + /* Check if we have open library groups */ + LibCheckGroup (); + /* Read the config file */ CfgRead (); /* Create the condes tables if requested */ ConDesCreate (); - /* Assign start addresses for the segments, define linker symbols */ - CfgAssignSegments (); + /* Assign start addresses for the segments, define linker symbols. The + * function will return the number of memory area overflows (zero on + * success). + */ + MemoryAreaOverflows = CfgAssignSegments (); /* Check module assertions */ CheckAssertions (); @@ -515,6 +661,18 @@ int main (int argc, char* argv []) /* Check for import/export mismatches */ CheckExports (); + /* If we had a memory area overflow before, we cannot generate the output + * file. However, we will generate a short map file if requested, since + * this will help the user to rearrange segments and fix the overflow. + */ + if (MemoryAreaOverflows) { + if (MapFileName) { + CreateMapFile (SHORT_MAPFILE); + } + Error ("Cannot generate output due to memory area overflow%s", + (MemoryAreaOverflows > 1)? "s" : ""); + } + /* Create the output file */ CfgWriteTarget (); @@ -523,7 +681,7 @@ int main (int argc, char* argv []) /* If requested, create a map file and a label file for VICE */ if (MapFileName) { - CreateMapFile (); + CreateMapFile (LONG_MAPFILE); } if (LabelFileName) { CreateLabelFile ();