]> git.sur5r.net Git - cc65/blob - src/ld65/main.c
Merge pull request #99 from groessler/something_to_pull
[cc65] / src / ld65 / main.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  main.c                                   */
4 /*                                                                           */
5 /*                     Main program for the ld65 linker                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2013, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40
41 /* common */
42 #include "addrsize.h"
43 #include "chartype.h"
44 #include "cmdline.h"
45 #include "filetype.h"
46 #include "libdefs.h"
47 #include "objdefs.h"
48 #include "print.h"
49 #include "target.h"
50 #include "version.h"
51 #include "xmalloc.h"
52
53 /* ld65 */
54 #include "asserts.h"
55 #include "binfmt.h"
56 #include "condes.h"
57 #include "config.h"
58 #include "dbgfile.h"
59 #include "error.h"
60 #include "exports.h"
61 #include "fileio.h"
62 #include "filepath.h"
63 #include "global.h"
64 #include "library.h"
65 #include "mapfile.h"
66 #include "objfile.h"
67 #include "scanner.h"
68 #include "segments.h"
69 #include "spool.h"
70 #include "tpool.h"
71
72
73
74 /*****************************************************************************/
75 /*                                   Data                                    */
76 /*****************************************************************************/
77
78
79
80 static unsigned         ObjFiles   = 0; /* Count of object files linked */
81 static unsigned         LibFiles   = 0; /* Count of library files linked */
82
83 /* struct InputFile.Type definitions */
84 #define INPUT_FILES_FILE       0        /* Entry is a file (unknown type) */
85 #define INPUT_FILES_FILE_OBJ   1        /* Entry is a object file */
86 #define INPUT_FILES_FILE_LIB   2        /* Entry is a library file */
87 #define INPUT_FILES_SGROUP     3        /* Entry is 'StartGroup' */
88 #define INPUT_FILES_EGROUP     4        /* Entry is 'EndGroup' */
89
90 #define MAX_INPUTFILES         256
91
92 /* Array of inputs (libraries and object files) */
93 static struct InputFile {
94     const char *FileName;
95     unsigned Type;
96 }                              *InputFiles;
97 static unsigned                InputFilesCount = 0;
98 static const char              *CmdlineCfgFile = NULL,
99                                *CmdlineTarget = NULL;
100
101
102
103 /*****************************************************************************/
104 /*                                   Code                                    */
105 /*****************************************************************************/
106
107
108
109 static void Usage (void)
110 /* Print usage information and exit */
111 {
112     printf ("Usage: %s [options] module ...\n"
113             "Short options:\n"
114             "  -(\t\t\tStart a library group\n"
115             "  -)\t\t\tEnd a library group\n"
116             "  -C name\t\tUse linker config file\n"
117             "  -D sym=val\t\tDefine a symbol\n"
118             "  -L path\t\tSpecify a library search path\n"
119             "  -Ln name\t\tCreate a VICE label file\n"
120             "  -S addr\t\tSet the default start address\n"
121             "  -V\t\t\tPrint the linker version\n"
122             "  -h\t\t\tHelp (this text)\n"
123             "  -m name\t\tCreate a map file\n"
124             "  -o name\t\tName the default output file\n"
125             "  -t sys\t\tSet the target system\n"
126             "  -u sym\t\tForce an import of symbol `sym'\n"
127             "  -v\t\t\tVerbose mode\n"
128             "  -vm\t\t\tVerbose map file\n"
129             "\n"
130             "Long options:\n"
131             "  --cfg-path path\tSpecify a config file search path\n"
132             "  --config name\t\tUse linker config file\n"
133             "  --dbgfile name\tGenerate debug information\n"
134             "  --define sym=val\tDefine a symbol\n"
135             "  --end-group\t\tEnd a library group\n"
136             "  --force-import sym\tForce an import of symbol `sym'\n"
137             "  --help\t\tHelp (this text)\n"
138             "  --lib file\t\tLink this library\n"
139             "  --lib-path path\tSpecify a library search path\n"
140             "  --mapfile name\tCreate a map file\n"
141             "  --module-id id\tSpecify a module id\n"
142             "  --obj file\t\tLink this object file\n"
143             "  --obj-path path\tSpecify an object file search path\n"
144             "  --start-addr addr\tSet the default start address\n"
145             "  --start-group\t\tStart a library group\n"
146             "  --target sys\t\tSet the target system\n"
147             "  --version\t\tPrint the linker version\n",
148             ProgName);
149 }
150
151
152
153 static unsigned long CvtNumber (const char* Arg, const char* Number)
154 /* Convert a number from a string. Allow '$' and '0x' prefixes for hex
155  * numbers.
156  */
157 {
158     unsigned long Val;
159     int           Converted;
160
161     /* Convert */
162     if (*Number == '$') {
163         ++Number;
164         Converted = sscanf (Number, "%lx", &Val);
165     } else {
166         Converted = sscanf (Number, "%li", (long*)&Val);
167     }
168
169     /* Check if we do really have a number */
170     if (Converted != 1) {
171         Error ("Invalid number given in argument: %s\n", Arg);
172     }
173
174     /* Return the result */
175     return Val;
176 }
177
178
179
180 static void LinkFile (const char* Name, FILETYPE Type)
181 /* Handle one file */
182 {
183     char*         PathName;
184     FILE*         F;
185     unsigned long Magic;
186
187
188     /* If we don't know the file type, determine it from the extension */
189     if (Type == FILETYPE_UNKNOWN) {
190         Type = GetFileType (Name);
191     }
192
193     /* For known file types, search the file in the directory list */
194     switch (Type) {
195
196         case FILETYPE_LIB:
197             PathName = SearchFile (LibSearchPath, Name);
198             if (PathName == 0) {
199                 PathName = SearchFile (LibDefaultPath, Name);
200             }
201             break;
202
203         case FILETYPE_OBJ:
204             PathName = SearchFile (ObjSearchPath, Name);
205             if (PathName == 0) {
206                 PathName = SearchFile (ObjDefaultPath, Name);
207             }
208             break;
209
210         default:
211             PathName = xstrdup (Name);   /* Use the name as is */
212             break;
213     }
214
215     /* We must have a valid name now */
216     if (PathName == 0) {
217         Error ("Input file `%s' not found", Name);
218     }
219
220     /* Try to open the file */
221     F = fopen (PathName, "rb");
222     if (F == 0) {
223         Error ("Cannot open `%s': %s", PathName, strerror (errno));
224     }
225
226     /* Read the magic word */
227     Magic = Read32 (F);
228
229     /* Check the magic for known file types. The handling is somewhat weird
230      * since we may have given a file with a ".lib" extension, which was
231      * searched and found in a directory for library files, but we now find
232      * out (by looking at the magic) that it's indeed an object file. We just
233      * ignore the problem and hope no one will notice...
234      */
235     switch (Magic) {
236
237         case OBJ_MAGIC:
238             ObjAdd (F, PathName);
239             ++ObjFiles;
240             break;
241
242         case LIB_MAGIC:
243             LibAdd (F, PathName);
244             ++LibFiles;
245             break;
246
247         default:
248             fclose (F);
249             Error ("File `%s' has unknown type", PathName);
250
251     }
252
253     /* Free allocated memory. */
254     xfree (PathName);
255 }
256
257
258
259 static void DefineSymbol (const char* Def)
260 /* Define a symbol from the command line */
261 {
262     const char* P;
263     long Val;
264     StrBuf SymName = AUTO_STRBUF_INITIALIZER;
265
266
267     /* The symbol must start with a character or underline */
268     if (Def [0] != '_' && !IsAlpha (Def [0])) {
269         InvDef (Def);
270     }
271     P = Def;
272
273     /* Copy the symbol, checking the remainder */
274     while (IsAlNum (*P) || *P == '_') {
275         SB_AppendChar (&SymName, *P++);
276     }
277     SB_Terminate (&SymName);
278
279     /* Do we have a value given? */
280     if (*P != '=') {
281         InvDef (Def);
282     } else {
283         /* We have a value */
284         ++P;
285         if (*P == '$') {
286             ++P;
287             if (sscanf (P, "%lx", &Val) != 1) {
288                 InvDef (Def);
289             }
290         } else {
291             if (sscanf (P, "%li", &Val) != 1) {
292                 InvDef (Def);
293             }
294         }
295     }
296
297     /* Define the new symbol */
298     CreateConstExport (GetStringId (SB_GetConstBuf (&SymName)), Val);
299 }
300
301
302
303 static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg)
304 /* Specify a config file search path */
305 {
306     AddSearchPath (CfgSearchPath, Arg);
307 }
308
309
310
311 static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
312 /* Define the config file */
313 {
314     char* PathName;
315
316     if (CfgAvail ()) {
317         Error ("Cannot use -C/-t twice");
318     }
319     /* Search for the file */
320     PathName = SearchFile (CfgSearchPath, Arg);
321     if (PathName == 0) {
322         PathName = SearchFile (CfgDefaultPath, Arg);
323     }
324     if (PathName == 0) {
325         Error ("Cannot find config file `%s'", Arg);
326     }
327
328     /* Read the config */
329     CfgSetName (PathName);
330     CfgRead ();
331 }
332
333
334
335 static void OptDbgFile (const char* Opt attribute ((unused)), const char* Arg)
336 /* Give the name of the debug file */
337 {
338     DbgFileName = Arg;
339 }
340
341
342
343 static void OptDefine (const char* Opt attribute ((unused)), const char* Arg)
344 /* Define a symbol on the command line */
345 {
346     DefineSymbol (Arg);
347 }
348
349
350
351 static void OptEndGroup (const char* Opt attribute ((unused)),
352                          const char* Arg attribute ((unused)))
353 /* End a library group */
354 {
355     LibEndGroup ();
356 }
357
358
359
360 static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg)
361 /* Force an import of a symbol */
362 {
363     /* An optional address size may be specified */
364     const char* ColPos = strchr (Arg, ':');
365     if (ColPos == 0) {
366
367         /* Use default address size (which for now is always absolute
368          * addressing)
369          */
370         InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS));
371
372     } else {
373
374         char* A;
375
376         /* Get the address size and check it */
377         unsigned char AddrSize = AddrSizeFromStr (ColPos+1);
378         if (AddrSize == ADDR_SIZE_INVALID) {
379             Error ("Invalid address size `%s'", ColPos+1);
380         }
381
382         /* Create a copy of the argument */
383         A = xstrdup (Arg);
384
385         /* We need just the symbol */
386         A[ColPos - Arg] = '\0';
387
388         /* Generate the import */
389         InsertImport (GenImport (GetStringId (A), AddrSize));
390
391         /* Delete the copy of the argument */
392         xfree (A);
393     }
394 }
395
396
397
398 static void OptHelp (const char* Opt attribute ((unused)),
399                      const char* Arg attribute ((unused)))
400 /* Print usage information and exit */
401 {
402     Usage ();
403     exit (EXIT_SUCCESS);
404 }
405
406
407
408 static void OptLib (const char* Opt attribute ((unused)), const char* Arg)
409 /* Link a library */
410 {
411     InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_LIB;
412     InputFiles[InputFilesCount].FileName = Arg;
413     if (++InputFilesCount >= MAX_INPUTFILES)
414         Error ("Too many input files");
415 }
416
417
418
419 static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg)
420 /* Specify a library file search path */
421 {
422     AddSearchPath (LibSearchPath, Arg);
423 }
424
425
426
427 static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg)
428 /* Give the name of the map file */
429 {
430     if (MapFileName) {
431         Error ("Cannot use -m twice");
432     }
433     MapFileName = Arg;
434 }
435
436
437
438 static void OptModuleId (const char* Opt, const char* Arg)
439 /* Specify a module id */
440 {
441     unsigned long Id = CvtNumber (Opt, Arg);
442     if (Id > 0xFFFFUL) {
443         Error ("Range error in module id");
444     }
445     ModuleId = (unsigned) Id;
446 }
447
448
449
450 static void OptObj (const char* Opt attribute ((unused)), const char* Arg)
451 /* Link an object file */
452 {
453     InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_OBJ;
454     InputFiles[InputFilesCount].FileName = Arg;
455     if (++InputFilesCount >= MAX_INPUTFILES)
456         Error ("Too many input files");
457 }
458
459
460
461 static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg)
462 /* Specify an object file search path */
463 {
464     AddSearchPath (ObjSearchPath, Arg);
465 }
466
467
468
469 static void OptOutputName (const char* Opt attribute ((unused)), const char* Arg)
470 /* Give the name of the output file */
471 {
472     static int OutputNameSeen = 0;
473     if (OutputNameSeen) {
474         Error ("Cannot use -o twice");
475     }
476     OutputNameSeen = 1;
477     OutputName = Arg;
478 }
479
480
481
482 static void OptStartAddr (const char* Opt, const char* Arg)
483 /* Set the default start address */
484 {
485     if (HaveStartAddr) {
486         Error ("Cannot use -S twice");
487     }
488     StartAddr = CvtNumber (Opt, Arg);
489     HaveStartAddr = 1;
490 }
491
492
493
494 static void OptStartGroup (const char* Opt attribute ((unused)),
495                            const char* Arg attribute ((unused)))
496 /* Start a library group */
497 {
498     LibStartGroup ();
499 }
500
501
502
503 static void OptTarget (const char* Opt attribute ((unused)), const char* Arg)
504 /* Set the target system */
505 {
506     StrBuf FileName = STATIC_STRBUF_INITIALIZER;
507     char*  PathName;
508
509     /* Map the target name to a target id */
510     Target = FindTarget (Arg);
511     if (Target == TGT_UNKNOWN) {
512         Error ("Invalid target name: `%s'", Arg);
513     }
514
515     /* Set the target binary format */
516     DefaultBinFmt = GetTargetProperties (Target)->BinFmt;
517
518     /* Build config file name from target name */
519     SB_CopyStr (&FileName, GetTargetName (Target));
520     SB_AppendStr (&FileName, ".cfg");
521     SB_Terminate (&FileName);
522
523     /* Search for the file */
524     PathName = SearchFile (CfgSearchPath, SB_GetBuf (&FileName));
525     if (PathName == 0) {
526         PathName = SearchFile (CfgDefaultPath, SB_GetBuf (&FileName));
527     }
528     if (PathName == 0) {
529         Error ("Cannot find config file `%s'", SB_GetBuf (&FileName));
530     }
531
532     /* Free file name memory */
533     SB_Done (&FileName);
534
535     /* Read the file */
536     CfgSetName (PathName);
537     CfgRead ();
538 }
539
540
541
542 static void OptVersion (const char* Opt attribute ((unused)),
543                         const char* Arg attribute ((unused)))
544 /* Print the assembler version */
545 {
546     fprintf (stderr, "ld65 V%s\n", GetVersionAsString ());
547 }
548
549
550
551 static void CmdlOptStartGroup (const char* Opt attribute ((unused)),
552                                const char* Arg attribute ((unused)))
553 /* Remember 'start group' occurrence in input files array */
554 {
555     InputFiles[InputFilesCount].Type = INPUT_FILES_SGROUP;
556     InputFiles[InputFilesCount].FileName = Arg;  /* Unused */
557     if (++InputFilesCount >= MAX_INPUTFILES)
558         Error ("Too many input files");
559 }
560
561
562
563 static void CmdlOptEndGroup (const char* Opt attribute ((unused)),
564                              const char* Arg attribute ((unused)))
565 /* Remember 'end group' occurrence in input files array */
566 {
567     InputFiles[InputFilesCount].Type = INPUT_FILES_EGROUP;
568     InputFiles[InputFilesCount].FileName = Arg;  /* Unused */
569     if (++InputFilesCount >= MAX_INPUTFILES)
570         Error ("Too many input files");
571 }
572
573
574
575 static void CmdlOptConfig (const char* Opt attribute ((unused)), const char* Arg)
576 /* Set 'config file' command line parameter */
577 {
578     if (CmdlineCfgFile || CmdlineTarget) {
579         Error ("Cannot use -C/-t twice");
580     }
581     CmdlineCfgFile = Arg;
582 }
583
584
585
586 static void CmdlOptTarget (const char* Opt attribute ((unused)), const char* Arg)
587 /* Set 'target' command line parameter */
588 {
589     if (CmdlineCfgFile || CmdlineTarget) {
590         Error ("Cannot use -C/-t twice");
591     }
592     CmdlineTarget = Arg;
593 }
594
595
596
597 static void ParseCommandLine(void)
598 {
599     /* Program long options */
600     static const LongOpt OptTab[] = {
601         { "--cfg-path",         1,      OptCfgPath              },
602         { "--config",           1,      CmdlOptConfig           },
603         { "--dbgfile",          1,      OptDbgFile              },
604         { "--define",           1,      OptDefine               },
605         { "--end-group",        0,      CmdlOptEndGroup         },
606         { "--force-import",     1,      OptForceImport          },
607         { "--help",             0,      OptHelp                 },
608         { "--lib",              1,      OptLib                  },
609         { "--lib-path",         1,      OptLibPath              },
610         { "--mapfile",          1,      OptMapFile              },
611         { "--module-id",        1,      OptModuleId             },
612         { "--obj",              1,      OptObj                  },
613         { "--obj-path",         1,      OptObjPath              },
614         { "--start-addr",       1,      OptStartAddr            },
615         { "--start-group",      0,      CmdlOptStartGroup       },
616         { "--target",           1,      CmdlOptTarget           },
617         { "--version",          0,      OptVersion              },
618     };
619
620     unsigned I;
621     unsigned LabelFileGiven = 0;
622
623     /* Allocate memory for input file array */
624     InputFiles = xmalloc (MAX_INPUTFILES * sizeof (struct InputFile));
625
626     /* Defer setting of config/target and input files until all options are parsed */
627     I = 1;
628     while (I < ArgCount) {
629
630         /* Get the argument */
631         const char* Arg = ArgVec[I];
632
633         /* Check for an option */
634         if (Arg [0] == '-') {
635
636             /* An option */
637             switch (Arg [1]) {
638
639                 case '-':
640                     LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
641                     break;
642
643                 case '(':
644                     CmdlOptStartGroup (Arg, 0);
645                     break;
646
647                 case ')':
648                     CmdlOptEndGroup (Arg, 0);
649                     break;
650
651                 case 'h':
652                 case '?':
653                     OptHelp (Arg, 0);
654                     break;
655
656                 case 'm':
657                     OptMapFile (Arg, GetArg (&I, 2));
658                     break;
659
660                 case 'o':
661                     OptOutputName (NULL, GetArg (&I, 2));
662                     break;
663
664                 case 't':
665                     CmdlOptTarget (Arg, GetArg (&I, 2));
666                     break;
667
668                 case 'u':
669                     OptForceImport (Arg, GetArg (&I, 2));
670                     break;
671
672                 case 'v':
673                     switch (Arg [2]) {
674                         case 'm':   VerboseMap = 1;     break;
675                         case '\0':  ++Verbosity;        break;
676                         default:    UnknownOption (Arg);
677                     }
678                     break;
679
680                 case 'C':
681                     CmdlOptConfig (Arg, GetArg (&I, 2));
682                     break;
683
684                 case 'D':
685                     OptDefine (Arg, GetArg (&I, 2));
686                     break;
687
688                 case 'L':
689                     switch (Arg [2]) {
690                         case 'n':
691                             /* ## This one is obsolete and will go */
692                             if (LabelFileGiven) {
693                                 Error ("Cannot use -Ln twice");
694                             }
695                             LabelFileGiven = 1;
696                             LabelFileName = GetArg (&I, 3);
697                             break;
698                         default:
699                             OptLibPath (Arg, InputFiles[I].FileName);
700                             break;
701                     }
702                     break;
703
704                 case 'S':
705                     OptStartAddr (Arg, GetArg (&I, 2));
706                     break;
707
708                 case 'V':
709                     OptVersion (Arg, 0);
710                     break;
711
712                 default:
713                     UnknownOption (Arg);
714                     break;
715             }
716
717         } else {
718
719             /* A filename */
720             InputFiles[InputFilesCount].Type = INPUT_FILES_FILE;
721             InputFiles[InputFilesCount].FileName = Arg;
722             if (++InputFilesCount >= MAX_INPUTFILES)
723                 Error ("Too many input files");
724
725         }
726
727         /* Next argument */
728         ++I;
729     }
730
731     if (CmdlineTarget) {
732         OptTarget (NULL, CmdlineTarget);
733     } else if (CmdlineCfgFile) {
734         OptConfig (NULL, CmdlineCfgFile);
735     }
736
737     /* Process input files */
738     for (I = 0; I < InputFilesCount; ++I) {
739         switch (InputFiles[I].Type) {
740             case INPUT_FILES_FILE:
741                 LinkFile (InputFiles[I].FileName, FILETYPE_UNKNOWN);
742                 break;
743             case INPUT_FILES_FILE_LIB:
744                 LinkFile (InputFiles[I].FileName, FILETYPE_LIB);
745                 break;
746             case INPUT_FILES_FILE_OBJ:
747                 LinkFile (InputFiles[I].FileName, FILETYPE_OBJ);
748                 break;
749             case INPUT_FILES_SGROUP:
750                 OptStartGroup (NULL, 0);
751                 break;
752             case INPUT_FILES_EGROUP:
753                 OptEndGroup (NULL, 0);
754                 break;
755             default:
756                 abort ();
757         }
758     }
759
760     /* Free memory used for input file array */
761     xfree (InputFiles);
762 }
763
764
765
766 int main (int argc, char* argv [])
767 /* Linker main program */
768 {
769     unsigned MemoryAreaOverflows;
770
771     /* Initialize the cmdline module */
772     InitCmdLine (&argc, &argv, "ld65");
773
774     /* Initialize the input file search paths */
775     InitSearchPaths ();
776
777     /* Initialize the string pool */
778     InitStrPool ();
779
780     /* Initialize the type pool */
781     InitTypePool ();
782
783     /* Parse the command line */
784     ParseCommandLine ();
785
786     /* Check if we had any object files */
787     if (ObjFiles == 0) {
788         Error ("No object files to link");
789     }
790
791     /* Check if we have a valid configuration */
792     if (!CfgAvail ()) {
793         Error ("Memory configuration missing");
794     }
795
796     /* Check if we have open library groups */
797     LibCheckGroup ();
798
799     /* Create the condes tables if requested */
800     ConDesCreate ();
801
802     /* Process data from the config file. Assign start addresses for the
803      * segments, define linker symbols. The function will return the number
804      * of memory area overflows (zero on success).
805      */
806     MemoryAreaOverflows = CfgProcess ();
807
808     /* Check module assertions */
809     CheckAssertions ();
810
811     /* Check for import/export mismatches */
812     CheckExports ();
813
814     /* If we had a memory area overflow before, we cannot generate the output
815      * file. However, we will generate a short map file if requested, since
816      * this will help the user to rearrange segments and fix the overflow.
817      */
818     if (MemoryAreaOverflows) {
819         if (MapFileName) {
820             CreateMapFile (SHORT_MAPFILE);
821         }
822         Error ("Cannot generate output due to memory area overflow%s",
823                (MemoryAreaOverflows > 1)? "s" : "");
824     }
825
826     /* Create the output file */
827     CfgWriteTarget ();
828
829     /* Check for segments not written to the output file */
830     CheckSegments ();
831
832     /* If requested, create a map file and a label file for VICE */
833     if (MapFileName) {
834         CreateMapFile (LONG_MAPFILE);
835     }
836     if (LabelFileName) {
837         CreateLabelFile ();
838     }
839     if (DbgFileName) {
840         CreateDbgFile ();
841     }
842
843     /* Dump the data for debugging */
844     if (Verbosity > 1) {
845         SegDump ();
846         ConDesDump ();
847     }
848
849     /* Return an apropriate exit code */
850     return EXIT_SUCCESS;
851 }