1 /*****************************************************************************/
5 /* Main program for the ld65 linker */
9 /* (C) 1998 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
41 #include "../common/cmdline.h"
42 #include "../common/libdefs.h"
43 #include "../common/objdefs.h"
44 #include "../common/version.h"
45 #include "../common/xmalloc.h"
61 /*****************************************************************************/
63 /*****************************************************************************/
67 static unsigned ObjFiles = 0; /* Count of object files linked */
68 static unsigned LibFiles = 0; /* Count of library files linked */
69 static const char* LibPath = 0; /* Search path for modules */
70 static unsigned LibPathLen = 0; /* Length of LibPath */
74 /*****************************************************************************/
76 /*****************************************************************************/
80 static void Usage (void)
81 /* Print usage information and exit */
84 "Usage: %s [options] module ...\n"
86 " -h\t\t\tHelp (this text)\n"
87 " -m name\t\tCreate a map file\n"
88 " -o name\t\tName the default output file\n"
89 " -t type\t\tType of target system\n"
90 " -v\t\t\tVerbose mode\n"
91 " -vm\t\t\tVerbose map file\n"
92 " -C name\t\tUse linker config file\n"
93 " -Ln name\t\tCreate a VICE label file\n"
94 " -Lp\t\t\tMark write protected segments as such (VICE)\n"
95 " -S addr\t\tSet the default start address\n"
96 " -V\t\t\tPrint the linker version\n"
99 " --help\t\tHelp (this text)\n"
100 " --version\t\tPrint the linker version\n",
106 static unsigned long CvtNumber (const char* Arg, const char* Number)
107 /* Convert a number from a string. Allow '$' and '0x' prefixes for hex
115 if (*Number == '$') {
117 Converted = sscanf (Number, "%lx", &Val);
119 Converted = sscanf (Number, "%li", (long*)&Val);
122 /* Check if we do really have a number */
123 if (Converted != 1) {
124 fprintf (stderr, "Invalid number given in argument: %s\n", Arg);
128 /* Return the result */
134 static int HasPath (const char* Name)
135 /* Check if the given Name has a path component */
137 return strchr (Name, '/') != 0 || strchr (Name, '\\') != 0;
142 static void LinkFile (const char* Name)
143 /* Handle one file */
149 /* Try to open the file */
150 FILE* F = fopen (Name, "rb");
152 /* We couldn't open the file. If the name doesn't have a path, and we
153 * have a search path given, try the name with the search path
156 if (LibPathLen > 0 && !HasPath (Name)) {
157 /* Allocate memory. Account for the trailing zero, and for a
158 * path separator character eventually needed.
161 NewName = xmalloc (strlen (Name) + Len + 2);
162 /* Build the new name */
163 memcpy (NewName, LibPath, Len);
164 if (NewName [Len-1] != '/' && NewName [Len-1] != '\\') {
165 /* We need an additional path separator */
166 NewName [Len++] = '/';
168 strcpy (NewName + Len, Name);
170 /* Now try to open the new file */
171 F = fopen (NewName, "rb");
175 Error ("Cannot open `%s': %s", Name, strerror (errno));
179 /* Read the magic word */
182 /* Do we know this type of file? */
197 Error ("File `%s' has unknown type", Name);
201 /* If we have allocated memory, free it here. Note: Memory will not always
202 * be freed if we run into an error, but that's no problem. Adding more
203 * code to work around it will use more memory than the chunk that's lost.
210 static void OptHelp (const char* Opt, const char* Arg)
211 /* Print usage information and exit */
219 static void OptVersion (const char* Opt, const char* Arg)
220 /* Print the assembler version */
223 "ld65 V%u.%u.%u - (C) Copyright 1998-2000 Ullrich von Bassewitz\n",
224 VER_MAJOR, VER_MINOR, VER_PATCH);
229 int main (int argc, char* argv [])
230 /* Assembler main program */
232 /* Program long options */
233 static const LongOpt OptTab[] = {
234 { "--help", 0, OptHelp },
235 { "--version", 0, OptVersion },
240 /* Initialize the cmdline module */
241 InitCmdLine (argc, argv, "ld65");
243 /* Evaluate the CC65_LIB environment variable */
244 LibPath = getenv ("CC65_LIB");
246 /* Use some default path */
250 LibPath = "/usr/lib/cc65/lib/";
253 LibPathLen = strlen (LibPath);
255 /* Check the parameters */
259 /* Get the argument */
260 const char* Arg = argv [I];
262 /* Check for an option */
263 if (Arg [0] == '-') {
269 LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
273 MapFileName = GetArg (&I, 2);
277 OutputName = GetArg (&I, 2);
282 Error ("Cannot use -C/-t twice");
284 TgtSet (GetArg (&I, 2));
289 case 'm': VerboseMap = 1; break;
290 case '\0': ++Verbose; break;
291 default: UnknownOption (Arg);
297 Error ("Cannot use -C/-t twice");
299 CfgSetName (GetArg (&I, 2));
304 case 'n': LabelFileName = GetArg (&I, 3); break;
305 case 'p': WProtSegs = 1; break;
306 default: UnknownOption (Arg); break;
311 StartAddr = CvtNumber (Arg, GetArg (&I, 2));
334 /* Check if we had any object files */
336 fprintf (stderr, "No object files to link\n");
340 /* Check if we have a valid configuration */
342 fprintf (stderr, "Memory configuration missing\n");
346 /* Read the config file */
349 /* Assign start addresses for the segments, define linker symbols */
350 CfgAssignSegments ();
352 /* Create the output file */
355 /* Check for segments not written to the output file */
358 /* If requested, create a map file and a label file for VICE */
366 /* Dump the data for debugging */
371 /* Return an apropriate exit code */