* src/SDCCmain.c (linkEdit),
[fw/sdcc] / src / SDCCmain.c
1 /*-------------------------------------------------------------------------
2   SDCCmain.c - main file
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #ifdef _WIN32
26 #include <io.h>
27 #else
28 #include <unistd.h>
29 #endif
30
31 #include <signal.h>
32 #include "common.h"
33 #include <ctype.h>
34 #include "newalloc.h"
35 #include "SDCCerr.h"
36 #include "BuildCmd.h"
37 #include "MySystem.h"
38 #include "SDCCmacro.h"
39 #include "SDCCutil.h"
40 #include "SDCCdebug.h"
41 #include "SDCCargs.h"
42
43 #ifdef _WIN32
44 #include <process.h>
45 #else
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #endif
49
50 /* REMOVE ME!!! */
51 extern int yyparse (void);
52
53 FILE *srcFile;                  /* source file          */
54 char *fullSrcFileName;          /* full name for the source file; */
55                                 /* can be NULL while c1mode or linking without compiling */
56 char *fullDstFileName;          /* full name for the output file; */
57                                 /* only given by -o, otherwise NULL */
58 char *dstFileName;              /* destination file name without extension */
59 char *dstPath = "";             /* path for the output files; */
60                                 /* "" is equivalent with cwd */
61 char *moduleName;               /* module name is source file without path and extension */
62                                 /* can be NULL while linking without compiling */
63 int currRegBank = 0;
64 int RegBankUsed[4] = {1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
65 struct optimize optimize;
66 struct options options;
67 int preProcOnly = 0;
68 int noAssemble = 0;
69 set *preArgvSet = NULL;         /* pre-processor arguments  */
70 set *asmOptionsSet = NULL;      /* set of assembler options */
71 set *linkOptionsSet = NULL;     /* set of linker options */
72 set *libFilesSet = NULL;
73 set *libPathsSet = NULL;
74 set *relFilesSet = NULL;
75 set *dataDirsSet = NULL;        /* list of data search directories */
76 set *includeDirsSet = NULL;     /* list of include search directories */
77 set *libDirsSet = NULL;         /* list of lib search directories */
78
79 /* uncomment JAMIN_DS390 to always override and use ds390 port
80   for mcs51 work.  This is temporary, for compatibility testing. */
81 /* #define JAMIN_DS390 */
82 #ifdef JAMIN_DS390
83 int ds390_jammed = 0;
84 #endif
85
86 /* Globally accessible scratch buffer for file names. */
87 char scratchFileName[PATH_MAX];
88 char buffer[PATH_MAX * 2];
89
90 #define OPTION_HELP     "-help"
91
92 #define LENGTH(_a)      (sizeof(_a)/sizeof(*(_a)))
93
94 #define OPTION_STACK_8BIT       "--stack-8bit"
95 #define OPTION_OUT_FMT_IHX      "--out-fmt-ihx"
96 #define OPTION_LARGE_MODEL      "--model-large"
97 #define OPTION_MEDIUM_MODEL     "--model-medium"
98 #define OPTION_SMALL_MODEL      "--model-small"
99 #define OPTION_FLAT24_MODEL     "--model-flat24"
100 #define OPTION_DUMP_ALL         "--dumpall"
101 #define OPTION_PEEP_FILE        "--peep-file"
102 #define OPTION_LIB_PATH         "--lib-path"
103 #define OPTION_XSTACK_LOC       "--xstack-loc"
104 #define OPTION_CALLEE_SAVES     "--callee-saves"
105 #define OPTION_STACK_LOC        "--stack-loc"
106 #define OPTION_XRAM_LOC         "--xram-loc"
107 #define OPTION_IRAM_SIZE        "--iram-size"
108 #define OPTION_VERSION          "--version"
109 #define OPTION_DATA_LOC         "--data-loc"
110 #define OPTION_CODE_LOC         "--code-loc"
111 #define OPTION_IDATA_LOC        "--idata-loc"
112 #define OPTION_NO_LABEL_OPT     "--nolabelopt"
113 #define OPTION_NO_LOOP_INV      "--noinvariant"
114 #define OPTION_NO_LOOP_IND      "--noinduction"
115 #define OPTION_LESS_PEDANTIC    "--less-pedantic"
116 #define OPTION_NO_GCSE          "--nogcse"
117 #define OPTION_SHORT_IS_8BITS   "--short-is-8bits"
118 #define OPTION_TINI_LIBID       "--tini-libid"
119 #define OPTION_NO_XINIT_OPT     "--no-xinit-opt"
120 #define OPTION_XRAM_SIZE        "--xram-size"
121 #define OPTION_CODE_SIZE        "--code-size"
122 #define OPTION_NO_CCODE_IN_ASM  "--no-c-code-in-asm"
123 #define OPTION_ICODE_IN_ASM     "--i-code-in-asm"
124 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
125 #define OPTION_MSVC_ERROR_STYLE "--vc"
126 #define OPTION_USE_STDOUT       "--use-stdout"
127 #define OPTION_STACK_SIZE       "--stack-size"
128 #define OPTION_PACK_IRAM        "--pack-iram"
129
130 static const OPTION
131 optionsTable[] = {
132     { 'm',  NULL,                   NULL, "Set the port to use e.g. -mz80." },
133     { 'p',  NULL,                   NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
134     { 'd',  NULL,                   NULL, NULL },
135     { 'D',  NULL,                   NULL, "Define macro as in -Dmacro" },
136     { 'I',  NULL,                   NULL, "Add to the include (*.h) path, as in -Ipath" },
137     { 'A',  NULL,                   NULL, NULL },
138     { 'U',  NULL,                   NULL, NULL },
139     { 'C',  NULL,                   NULL, "Preprocessor option" },
140     { 'M',  NULL,                   NULL, "Preprocessor option" },
141     { 'V',  NULL,                   &options.verboseExec, "Execute verbosely.  Show sub commands as they are run" },
142     { 'S',  NULL,                   &noAssemble, "Compile only; do not assemble or link" },
143     { 'W',  NULL,                   NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
144     { 'L',  NULL,                   NULL, "Add the next field to the library search path" },
145     { 'l',  NULL,                   NULL, "Include the given library in the link" },
146     { 0,    OPTION_LARGE_MODEL,     NULL, "external data space is used" },
147     { 0,    OPTION_MEDIUM_MODEL,    NULL, "not supported" },
148     { 0,    OPTION_SMALL_MODEL,     NULL, "internal data space is used (default)" },
149 #if !OPT_DISABLE_DS390
150     { 0,    OPTION_FLAT24_MODEL,    NULL, "use the flat24 model for the ds390 (default)" },
151 #endif
152     { 0,    "--stack-auto",         &options.stackAuto, "Stack automatic variables" },
153 #if !OPT_DISABLE_DS390
154     { 0,    OPTION_STACK_8BIT,      NULL, "use the 8bit stack for the ds390 (not supported yet)" },
155     { 0,    "--stack-10bit",        &options.stack10bit, "use the 10bit stack for ds390 (default)" },
156 #endif
157     { 0,    "--xstack",             &options.useXstack, "Use external stack" },
158     { 0,    OPTION_NO_GCSE,         NULL, "Disable the GCSE optimisation" },
159     { 0,    OPTION_NO_LABEL_OPT,    NULL, "Disable label optimisation" },
160     { 0,    OPTION_NO_LOOP_INV,     NULL, "Disable optimisation of invariants" },
161     { 0,    OPTION_NO_LOOP_IND,     NULL, NULL },
162     { 0,    "--nojtbound",          &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
163     { 0,    "--noloopreverse",      &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
164     { 'c',  "--compile-only",       &options.cc_only, "Compile and assemble, but do not link" },
165     { 'o',  NULL,                   NULL, "Place the output into the given path resp. file" },
166     { 0,    "--dumpraw",            &options.dump_raw, "Dump the internal structure after the initial parse" },
167     { 0,    "--dumpgcse",           &options.dump_gcse, NULL },
168     { 0,    "--dumploop",           &options.dump_loop, NULL },
169     { 0,    "--dumpdeadcode",       &options.dump_kill, NULL },
170     { 0,    "--dumpliverange",      &options.dump_range, NULL },
171     { 0,    "--dumpregpack",        &options.dump_pack, NULL },
172     { 0,    "--dumpregassign",      &options.dump_rassgn, NULL },
173     { 0,    "--dumptree",           &options.dump_tree, "dump front-end AST before generating iCode" },
174     { 0,    OPTION_DUMP_ALL,        NULL, "Dump the internal structure at all stages" },
175     { 0,    OPTION_XRAM_LOC,        NULL, "<nnnn> External Ram start location" },
176     { 0,    OPTION_XRAM_SIZE,       NULL, "<nnnn> External Ram size" },
177     { 0,    OPTION_IRAM_SIZE,       NULL, "<nnnn> Internal Ram size" },
178     { 0,    OPTION_XSTACK_LOC,      NULL, "<nnnn> External Ram start location" },
179     { 0,    OPTION_CODE_LOC,        NULL, "<nnnn> Code Segment Location" },
180     { 0,    OPTION_CODE_SIZE,       NULL, "<nnnn> Code Segment size" },
181     { 0,    OPTION_STACK_LOC,       NULL, "<nnnn> Stack pointer initial value" },
182     { 0,    OPTION_DATA_LOC,        NULL, "<nnnn> Direct data start location" },
183     { 0,    OPTION_IDATA_LOC,       NULL, NULL },
184     { 0,    OPTION_PEEP_FILE,       NULL, "<file> use this extra peep-hole file" },
185     { 0,    OPTION_LIB_PATH,        NULL, "<path> use this path to search for libraries" },
186     { 0,    "--int-long-reent",     &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
187     { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the float support functions" },
188     { 0,    OPTION_OUT_FMT_IHX,     NULL, NULL },
189     { 0,    "--out-fmt-s19",        &options.out_fmt, NULL },
190     { 0,    "--cyclomatic",         &options.cyclomatic, NULL },
191     { 0,    "--nooverlay",          &options.noOverlay, NULL },
192     { 0,    "--main-return",        &options.mainreturn, "Issue a return after main()" },
193     { 0,    "--xram-movc",          &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
194     { 0,    "--no-peep",            &options.nopeep, "Disable the peephole assembly file optimisation" },
195     { 0,    "--no-reg-params",      &options.noRegParams, "On some ports, disable passing some parameters in registers" },
196     { 0,    "--peep-asm",           &options.asmpeep, NULL },
197     { 0,    "--debug",              &options.debug, "Enable debugging symbol output" },
198     { 'v',  OPTION_VERSION,         NULL, "Display sdcc's version" },
199     { 'E',  "--preprocessonly",     &preProcOnly, "Preprocess only, do not compile" },
200     { 0,    "--c1mode",             &options.c1mode, "Act in c1 mode.  The standard input is preprocessed code, the output is assembly code." },
201     { 0,    "--help",               NULL, "Display this help" },
202     { 0,    OPTION_CALLEE_SAVES,    NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
203     { 0,    "--nostdlib",           &options.nostdlib, "Do not include the standard library directory in the search path" },
204     { 0,    "--nostdinc",           &options.nostdinc, "Do not include the standard include directory in the search path" },
205     { 0,    "--verbose",            &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
206     { 0,    OPTION_LESS_PEDANTIC,   NULL, "Disable some of the more pedantic warnings" },
207     { 0,    OPTION_SHORT_IS_8BITS,   NULL, "Make short 8bits (for old times sake)" },
208     { 0,    "--profile",            &options.profile, "On supported ports, generate extra profiling information" },
209     { 0,    "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
210     { 0,    "--all-callee-saves",   &options.all_callee_saves, "callee will always save registers used" },
211 #if !OPT_DISABLE_DS390
212     { 0,    "--use-accelerator",    &options.useAccelerator,"generate code for  DS390 Arithmetic Accelerator"},
213 #endif
214     { 0,    "--stack-probe",        &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
215 #if !OPT_DISABLE_TININative
216     { 0,    "--tini-libid",         NULL,"<nnnn> LibraryID used in -mTININative"},
217 #endif
218 #if !OPT_DISABLE_DS390
219     { 0,    "--protect-sp-update",  &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
220 #endif
221 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
222     { 0,    "--parms-in-bank1",     &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
223     { 0,    OPTION_STACK_SIZE,      NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
224     { 0,    OPTION_PACK_IRAM,       &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
225 #endif
226     { 0,    OPTION_NO_XINIT_OPT,    &options.noXinitOpt, "don't memcpy initialized xram from code"},
227     { 0,    OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
228     { 0,    OPTION_ICODE_IN_ASM,    &options.iCodeInAsm, "include i-code as comments in the asm file"},
229     { 0,    OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
230     { 0,    OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
231     { 0,    OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
232 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
233     { 0,    "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
234 #endif
235     /* End of options */
236     { 0,    NULL }
237 };
238
239 /** Table of all unsupported options and help text to display when one
240     is used.
241 */
242 typedef struct {
243     /** shortOpt as in OPTIONS. */
244     char shortOpt;
245     /** longOpt as in OPTIONS. */
246     const char *longOpt;
247     /** Message to display inside W_UNSUPPORTED_OPT when this option
248         is used. */
249     const char *message;
250 } UNSUPPORTEDOPT;
251
252 static const UNSUPPORTEDOPT 
253 unsupportedOptTable[] = {
254     { 'X',  NULL,       "use --xstack-loc instead" },
255     { 'x',  NULL,       "use --xstack instead" },
256     { 'i',  NULL,       "use --idata-loc instead" },
257     { 'r',  NULL,       "use --xdata-loc instead" },
258     { 's',  NULL,       "use --code-loc instead" },
259     { 'Y',  NULL,       "use -I instead" }
260 };
261
262 /** List of all default constant macros.
263  */
264 static const char *_baseValues[] = {
265   "cpp", "sdcpp",
266   "cppextraopts", "",
267   /* Path seperator character */
268   "sep", DIR_SEPARATOR_STRING,
269   NULL
270 };
271
272 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
273
274 PORT *port;
275
276 static PORT *_ports[] =
277 {
278 #if !OPT_DISABLE_MCS51
279   &mcs51_port,
280 #endif
281 #if !OPT_DISABLE_GBZ80
282   &gbz80_port,
283 #endif
284 #if !OPT_DISABLE_Z80
285   &z80_port,
286 #endif
287 #if !OPT_DISABLE_AVR
288   &avr_port,
289 #endif
290 #if !OPT_DISABLE_DS390
291   &ds390_port,
292 #endif
293 #if !OPT_DISABLE_PIC16
294   &pic16_port,
295 #endif
296 #if !OPT_DISABLE_PIC
297   &pic_port,
298 #endif
299 #if !OPT_DISABLE_TININative
300   &tininative_port,
301 #endif
302 #if !OPT_DISABLE_XA51
303   &xa51_port,
304 #endif
305 #if !OPT_DISABLE_DS400
306   &ds400_port,  
307 #endif
308 #if !OPT_DISABLE_HC08
309   &hc08_port,
310 #endif
311 };
312
313 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
314
315 /** Sets the port to the one given by the command line option.
316     @param    The name minus the option (eg 'mcs51')
317     @return     0 on success.
318 */
319 static void
320 _setPort (const char *name)
321 {
322   int i;
323   for (i = 0; i < NUM_PORTS; i++)
324     {
325       if (!strcmp (_ports[i]->target, name))
326         {
327           port = _ports[i];
328           return;
329         }
330     }
331   /* Error - didnt find */
332   werror (E_UNKNOWN_TARGET, name);
333   exit (1);
334 }
335
336 /* Override the default processor with the one specified 
337  * on the command line */
338 static void
339 _setProcessor (char *_processor)
340 {
341   port->processor = _processor;
342   fprintf(stderr,"Processor: %s\n",_processor);
343 }
344
345 static void
346 _validatePorts (void)
347 {
348   int i;
349   for (i = 0; i < NUM_PORTS; i++)
350     {
351       if (_ports[i]->magic != PORT_MAGIC)
352         {
353           /* Uncomment this line to debug which port is causing the problem
354            * (the target name is close to the beginning of the port struct 
355            * and probably can be accessed just fine). */
356           fprintf(stderr,"%s :",_ports[i]->target);
357           wassertl (0, "Port definition structure is incomplete");
358         }
359     }
360 }
361
362 /* search through the command line options for the port */
363 static void
364 _findPort (int argc, char **argv)
365 {
366   _validatePorts ();
367
368   while (argc--)
369     {
370       if (!strncmp (*argv, "-m", 2))
371         {
372           _setPort (*argv + 2);
373           return;
374         }
375       argv++;
376     }
377
378   /* Use the first in the list */
379         port = _ports[0];
380 }
381
382 /* search through the command line options for the processor */
383 static void
384 _findProcessor (int argc, char **argv)
385 {
386   while (argc--)
387     {
388       if (!strncmp (*argv, "-p", 2))
389         {
390           _setProcessor (*argv + 2);
391           return;
392         }
393       argv++;
394     }
395
396   /* no error if processor was not specified. */
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* printVersionInfo - prints the version info        */
401 /*-----------------------------------------------------------------*/
402 void
403 printVersionInfo (void)
404 {
405   int i;
406
407   fprintf (stderr,
408            "SDCC : ");
409   for (i = 0; i < NUM_PORTS; i++)
410     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
411   
412   fprintf (stderr, " " SDCC_VERSION_STR
413 #ifdef SDCC_SUB_VERSION_STR
414            "/" SDCC_SUB_VERSION_STR
415 #endif
416            " (" __DATE__ ")"
417 #ifdef __CYGWIN__
418            " (CYGWIN)\n"
419 #elif defined __MINGW32__
420            " (MINGW32)\n"
421 #elif defined __DJGPP__
422            " (DJGPP)\n"
423 #elif defined(_MSC_VER)
424            " (MSVC)\n"
425 #elif defined(__BORLANDC__)
426            " (BORLANDC)\n"
427 #else
428            " (UNIX) \n"
429 #endif
430     );
431 }
432
433 static void
434 printOptions(const OPTION *optionsTable)
435 {
436   int i;
437   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++) 
438     {
439       fprintf(stdout, "  %c%c  %-20s  %s\n", 
440               optionsTable[i].shortOpt !=0 ? '-' : ' ',
441               optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
442               optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
443               optionsTable[i].help != NULL ? optionsTable[i].help : ""
444               );
445     }
446 }
447
448 /*-----------------------------------------------------------------*/
449 /* printUsage - prints command line syntax         */
450 /*-----------------------------------------------------------------*/
451 void
452 printUsage (void)
453 {
454     int i;
455     printVersionInfo();
456     fprintf (stdout,
457              "Usage : sdcc [options] filename\n"
458              "Options :-\n"
459              );
460
461     printOptions(optionsTable);
462
463     for (i = 0; i < NUM_PORTS; i++)
464       {
465         if (_ports[i]->poptions != NULL)
466           {
467             fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
468             printOptions (_ports[i]->poptions);
469           }
470       }
471
472     exit (0);
473 }
474
475 /*-----------------------------------------------------------------*/
476 /* setParseWithComma - separates string with comma to a set        */
477 /*-----------------------------------------------------------------*/
478 void
479 setParseWithComma (set **dest, char *src)
480 {
481   char *p;
482   int length;
483
484   /* skip the initial white spaces */
485   while (isspace(*src))
486     src++;
487   
488   /* skip the trailing white spaces */
489   length = strlen(src);
490   while (length && isspace(src[length-1]))
491     src[--length] = '\0';
492
493   for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
494     addSet(dest, Safe_strdup(p));
495 }
496
497 /*-----------------------------------------------------------------*/
498 /* setDefaultOptions - sets the default options                    */
499 /*-----------------------------------------------------------------*/
500 static void
501 setDefaultOptions (void)
502 {
503   /* first the options part */
504   options.stack_loc = 0;        /* stack pointer initialised to 0 */
505   options.xstack_loc = 0;       /* xternal stack starts at 0 */
506   options.code_loc = 0;         /* code starts at 0 */
507   options.data_loc = 0;         /* JCF: By default let the linker locate data */
508   options.xdata_loc = 0;
509   options.idata_loc = 0x80;
510   options.nopeep = 0;
511   options.model = port->general.default_model;
512   options.nostdlib = 0;
513   options.nostdinc = 0;
514   options.verbose = 0;
515   options.shortis8bits = 0;
516
517   options.stack10bit=0;
518
519   /* now for the optimizations */
520   /* turn on the everything */
521   optimize.global_cse = 1;
522   optimize.label1 = 1;
523   optimize.label2 = 1;
524   optimize.label3 = 1;
525   optimize.label4 = 1;
526   optimize.loopInvariant = 1;
527   optimize.loopInduction = 1;
528
529   /* now for the ports */
530   port->setDefaultOptions ();
531 }
532
533 /*-----------------------------------------------------------------*/
534 /* processFile - determines the type of file from the extension    */
535 /*-----------------------------------------------------------------*/
536 static void
537 processFile (char *s)
538 {
539   char *fext = NULL;
540
541   /* get the file extension */
542   fext = s + strlen (s);
543   while ((fext != s) && *fext != '.')
544     fext--;
545
546   /* now if no '.' then we don't know what the file type is
547      so give a warning and return */
548   if (fext == s)
549     {
550       werror (W_UNKNOWN_FEXT, s);
551       return;
552     }
553
554   /* otherwise depending on the file type */
555   if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
556     {
557       /* source file name : not if we already have a
558          source file */
559       if (fullSrcFileName)
560         {
561           werror (W_TOO_MANY_SRC, s);
562           return;
563         }
564
565       /* the only source file */
566       fullSrcFileName = s;
567       if (!(srcFile = fopen (fullSrcFileName, "r")))
568         {
569           werror (E_FILE_OPEN_ERR, s);
570           exit (1);
571         }
572
573       /* copy the file name into the buffer */
574       strncpyz (buffer, s, sizeof(buffer));
575
576       /* get rid of the "."-extension */
577
578       /* is there a dot at all? */
579       if (strrchr (buffer, '.') &&
580           /* is the dot in the filename, not in the path? */
581           (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
582         {
583         *strrchr (buffer, '.') = '\0';
584         }
585
586       /* get rid of any path information
587          for the module name; */
588       fext = buffer + strlen (buffer);
589 #if NATIVE_WIN32
590       /* do this by going backwards till we
591          get '\' or ':' or start of buffer */
592       while (fext != buffer &&
593              *(fext - 1) != DIR_SEPARATOR_CHAR &&
594              *(fext - 1) != ':')
595         {
596         fext--;
597         }
598 #else
599       /* do this by going backwards till we
600          get '/' or start of buffer */
601       while (fext != buffer &&
602              *(fext - 1) != DIR_SEPARATOR_CHAR)
603         {
604           fext--;
605         }
606 #endif
607       moduleName = Safe_strdup ( fext );
608       return;
609     }
610
611   /* if the extention is type .rel or .r or .REL or .R
612      addtional object file will be passed to the linker */
613   if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
614       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
615       strcmp (fext, port->linker.rel_ext) == 0)
616     {
617       addSet(&relFilesSet, Safe_strdup(s));
618       return;
619     }
620
621   /* if .lib or .LIB */
622   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
623     {
624       addSet(&libFilesSet, Safe_strdup(s));
625       return;
626     }
627
628   werror (W_UNKNOWN_FEXT, s);
629
630 }
631
632 static void
633 _setModel (int model, const char *sz)
634 {
635   if (port->general.supported_models & model)
636     options.model = model;
637   else
638     werror (W_UNSUPPORTED_MODEL, sz, port->target);
639 }
640
641 /** Gets the string argument to this option.  If the option is '--opt'
642     then for input of '--optxyz' or '--opt xyz' returns xyz.
643 */
644 char *
645 getStringArg(const char *szStart, char **argv, int *pi, int argc)
646 {
647   if (argv[*pi][strlen(szStart)])
648     {
649       return &argv[*pi][strlen(szStart)];
650     }
651   else
652     {
653       ++(*pi);
654       if (*pi >= argc)
655         {
656           werror (E_ARGUMENT_MISSING, szStart);
657           /* Die here rather than checking for errors later. */
658           exit(-1);
659         }
660       else
661         {
662           return argv[*pi];
663         }
664     }
665 }
666
667 /** Gets the integer argument to this option using the same rules as
668     getStringArg.
669 */
670 int
671 getIntArg(const char *szStart, char **argv, int *pi, int argc)
672 {
673     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
674 }
675
676 static void
677 verifyShortOption(const char *opt)
678 {
679   if (strlen(opt) != 2)
680     {
681       werror (W_EXCESS_SHORT_OPTIONS, opt);
682     }
683 }
684
685 static bool
686 tryHandleUnsupportedOpt(char **argv, int *pi)
687 {
688     if (argv[*pi][0] == '-') 
689         {
690             const char *longOpt = "";
691             char shortOpt = -1;
692             int i;
693
694             if (argv[*pi][1] == '-') 
695                 {
696                     /* Long option. */
697                     longOpt = argv[*pi];
698                 }
699             else 
700                 {
701                     shortOpt = argv[*pi][1];
702                 }
703             for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
704                 {
705                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
706                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
707                         /* Found an unsupported opt. */
708                         char buffer[100];
709                         SNPRINTF(buffer, sizeof(buffer), 
710                                  "%s%c%c", 
711                                  longOpt ? longOpt : "", 
712                                  shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
713                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
714                         return 1;
715                     }
716                 }
717             /* Didn't find in the table */
718             return 0;
719         }
720     else 
721         {
722             /* Not an option, so can't be unsupported :) */
723             return 0;
724     }
725 }
726
727 static bool
728 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
729 {
730   int i;
731   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
732     {
733       if (optionsTable[i].shortOpt == shortOpt ||
734           (longOpt && optionsTable[i].longOpt && 
735            strcmp(optionsTable[i].longOpt, longOpt) == 0))
736         {
737
738           /* If it is a flag then we can handle it here */
739           if (optionsTable[i].pparameter != NULL) 
740             {
741               if (optionsTable[i].shortOpt == shortOpt)
742                 {
743                   verifyShortOption(argv[*pi]);
744                 }
745
746               (*optionsTable[i].pparameter)++;
747               return 1;
748             }
749           else {
750             /* Not a flag.  Handled manually later. */
751             return 0;
752           }
753         }
754     }
755   /* Didn't find in the table */
756   return 0;
757 }
758
759 static bool
760 tryHandleSimpleOpt(char **argv, int *pi)
761 {
762     if (argv[*pi][0] == '-') 
763         {
764             const char *longOpt = "";
765             char shortOpt = -1;
766
767             if (argv[*pi][1] == '-') 
768                 {
769                     /* Long option. */
770                     longOpt = argv[*pi];
771                 }
772             else 
773                 {
774                     shortOpt = argv[*pi][1];
775                 }
776
777             if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
778               {
779                 return 1;
780               }
781             else if (port && port->poptions &&
782                      scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
783               {
784                 return 1;
785               }
786             else
787               {
788                 return 0;
789               }
790         }
791     else 
792         {
793             /* Not an option, so can't be handled. */
794             return 0;
795         }
796 }
797
798 /*-----------------------------------------------------------------*/
799 /* parseCmdLine - parses the command line and sets the options     */
800 /*-----------------------------------------------------------------*/
801 static int
802 parseCmdLine (int argc, char **argv)
803 {
804   int i;
805
806   /* go thru all whole command line */
807   for (i = 1; i < argc; i++)
808     {
809       if (i >= argc)
810         break;
811
812       if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
813           {
814               continue;
815           }
816
817       if (tryHandleSimpleOpt(argv, &i) == TRUE)
818           {
819               continue;
820           }
821
822       /* options */
823       if (argv[i][0] == '-' && argv[i][1] == '-')
824         {
825           if (strcmp (argv[i], OPTION_HELP) == 0)
826             {
827               printUsage ();
828               exit (0);
829             }
830
831           if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
832             {
833               options.stack10bit = 0;
834               continue;
835             }
836
837           if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
838             {
839               options.out_fmt = 0;
840               continue;
841             }
842
843           if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
844             {
845               _setModel (MODEL_LARGE, argv[i]);
846               continue;
847             }
848
849           if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
850             {
851               _setModel (MODEL_MEDIUM, argv[i]);
852               continue;
853             }
854
855           if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
856             {
857               _setModel (MODEL_SMALL, argv[i]);
858               continue;
859             }
860
861           if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
862             {
863               _setModel (MODEL_FLAT24, argv[i]);
864               continue;
865             }
866
867           if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
868             {
869               options.dump_rassgn =
870                 options.dump_pack =
871                 options.dump_range =
872                 options.dump_kill =
873                 options.dump_loop =
874                 options.dump_gcse =
875                 options.dump_raw = 1;
876               continue;
877             }
878
879           if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
880             {
881                 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
882                 continue;
883             }
884
885           if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
886             {
887                 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
888                 continue;
889             }
890
891           if (strcmp (argv[i], OPTION_VERSION) == 0)
892             {
893               printVersionInfo ();
894               exit (0);
895               continue;
896             }
897
898           if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
899             {
900                 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
901                 continue;
902             }
903
904           if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
905             {
906                 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
907                 continue;
908             }
909
910           if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
911             {
912                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
913                 continue;
914             }
915           
916       if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
917             {
918                 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
919                 continue;
920             }
921
922           if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
923             {
924                 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
925                 continue;
926             }
927
928           if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
929             {
930                 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
931                 continue;
932             }
933
934           if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
935             {
936                 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
937                 options.xram_size_set = TRUE;
938                 continue;
939             }
940
941           if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
942             {
943                 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
944                 continue;
945             }
946
947           if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
948             {
949                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
950                 continue;
951             }
952
953           if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
954             {
955                 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
956                 continue;
957             }
958
959           if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
960             {
961                 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
962                 continue;
963             }
964
965           if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
966             {
967               optimize.global_cse = 0;
968               continue;
969             }
970
971           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
972             {
973               optimize.loopInvariant = 0;
974               continue;
975             }
976
977           if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
978             {
979               optimize.label4 = 0;
980               continue;
981             }
982
983           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
984             {
985               optimize.loopInduction = 0;
986               continue;
987             }
988
989           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
990             {
991               options.lessPedantic = 1;
992               setErrorLogLevel(ERROR_LEVEL_WARNING);
993               continue;
994             }
995
996           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
997             {
998               options.shortis8bits=1;
999               continue;
1000             }
1001
1002           if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1003             {
1004                 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1005                 continue;
1006             }
1007           
1008           if (!port->parseOption (&argc, argv, &i))
1009             {
1010               werror (W_UNKNOWN_OPTION, argv[i]);
1011             }
1012           else
1013             {
1014               continue;
1015             }
1016         }
1017
1018       /* if preceded by  '-' then option */
1019       if (*argv[i] == '-')
1020         {
1021           switch (argv[i][1])
1022             {
1023             case 'h':
1024               verifyShortOption(argv[i]);
1025
1026               printUsage ();
1027               exit (0);
1028               break;
1029
1030             case 'm':
1031               /* Used to select the port. But this has already been done. */
1032               break;
1033
1034             case 'p':
1035               /* Used to select the processor in port. But this has
1036                * already been done. */
1037               break;
1038
1039             case 'c':
1040               verifyShortOption(argv[i]);
1041
1042               options.cc_only = 1;
1043               break;
1044
1045             case 'L':
1046                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1047                 break;
1048
1049             case 'l':
1050                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1051                 break;
1052             
1053             case 'o':
1054               {
1055                 char *p;
1056
1057                 /* copy the file name into the buffer */
1058                 strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
1059                          sizeof(buffer));
1060                 /* point to last character */
1061                 p = buffer + strlen (buffer) - 1;
1062                 if (*p == DIR_SEPARATOR_CHAR)
1063                   {
1064                     /* only output path specified */
1065                     dstPath = Safe_strdup (buffer);
1066                     fullDstFileName = NULL;
1067                   }
1068                 else
1069                   {
1070                     fullDstFileName = Safe_strdup (buffer);
1071
1072                     /* get rid of the "."-extension */
1073
1074                     /* is there a dot at all? */
1075                     if (strrchr (buffer, '.') &&
1076                         /* is the dot in the filename, not in the path? */
1077                         (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1078                       *strrchr (buffer, '.') = '\0';
1079
1080                     dstFileName = Safe_strdup (buffer);
1081
1082                     /* strip module name to get path */
1083                     p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1084                     if (p)
1085                       {
1086                         /* path with trailing / */
1087                         p[1] = '\0';
1088                         dstPath = Safe_strdup (buffer);
1089                       }
1090                   }
1091                 break;
1092               }
1093
1094             case 'W':
1095               /* pre-processer options */
1096               if (argv[i][2] == 'p')
1097                 {
1098                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1099                 }
1100               /* linker options */
1101               else if (argv[i][2] == 'l')
1102                 {
1103                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1104                 }
1105               /* assembler options */
1106               else if (argv[i][2] == 'a')
1107                 {
1108                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1109                 }
1110               else
1111                 {
1112                   werror (W_UNKNOWN_OPTION, argv[i]);
1113                 }
1114               break;
1115
1116             case 'v':
1117               verifyShortOption(argv[i]);
1118
1119               printVersionInfo ();
1120               exit (0);
1121               break;
1122
1123               /* preprocessor options */
1124             case 'M':
1125               {
1126                 preProcOnly = 1;
1127                 if (argv[i][2] == 'M')
1128                   addSet(&preArgvSet, Safe_strdup("-MM"));
1129                 else
1130                   addSet(&preArgvSet, Safe_strdup("-M"));
1131                 break;
1132               }
1133             case 'C':
1134               {
1135                 addSet(&preArgvSet, Safe_strdup("-C"));
1136                 break;
1137               }
1138
1139             case 'd':
1140             case 'D':
1141             case 'I':
1142             case 'A':
1143             case 'U':
1144               {
1145                 char sOpt = argv[i][1];
1146                 char *rest;
1147
1148                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1149                   {
1150                     i++;
1151                     if (i >= argc)
1152                       {
1153                           /* No argument. */
1154                           werror(E_ARGUMENT_MISSING, argv[i-1]);
1155                           break;
1156                       }
1157                     else
1158                       {
1159                           rest = argv[i];
1160                       }
1161                   }
1162                 else
1163                   rest = &argv[i][2];
1164
1165                 if (sOpt == 'Y')
1166                   sOpt = 'I';
1167
1168                 SNPRINTF (buffer, sizeof(buffer),
1169                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1170                 addSet(&preArgvSet, Safe_strdup(buffer));
1171               }
1172               break;
1173
1174             default:
1175               if (!port->parseOption (&argc, argv, &i))
1176                 werror (W_UNKNOWN_OPTION, argv[i]);
1177             }
1178           continue;
1179         }
1180
1181       if (!port->parseOption (&argc, argv, &i))
1182         {
1183            /* no option must be a filename */
1184            if (options.c1mode)
1185              {
1186                 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1187              }
1188          else
1189              {
1190                 processFile (argv[i]);
1191              }
1192         }
1193     }
1194
1195   /* some sanity checks in c1 mode */
1196   if (options.c1mode)
1197     {
1198       const char *s;
1199
1200       if (fullSrcFileName)
1201         {
1202           fclose (srcFile);
1203           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1204         }
1205       fullSrcFileName = NULL;
1206       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1207         {
1208           werror (W_NO_FILE_ARG_IN_C1, s);
1209         }
1210       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1211         {
1212           werror (W_NO_FILE_ARG_IN_C1, s);
1213         }
1214       deleteSet(&relFilesSet);
1215       deleteSet(&libFilesSet);
1216
1217         if (options.cc_only || noAssemble || preProcOnly)
1218         {
1219           werror (W_ILLEGAL_OPT_COMBINATION);
1220         }
1221       options.cc_only = noAssemble = preProcOnly = 0;
1222       if (!dstFileName)
1223         {
1224           werror (E_NEED_OPT_O_IN_C1);
1225           exit (1);
1226         }
1227     }
1228   /* if no dstFileName given with -o, we've to find one: */
1229   if (!dstFileName)
1230     {
1231       const char *s;
1232
1233       /* use the modulename from the C-source */
1234       if (fullSrcFileName)
1235         {
1236           size_t bufSize = strlen (dstPath) + strlen (moduleName) + 1;
1237
1238           dstFileName = Safe_alloc (bufSize);
1239           strncpyz (dstFileName, dstPath, bufSize);
1240           strncatz (dstFileName, moduleName, bufSize);
1241         }
1242       /* use the modulename from the first object file */
1243       else if ((s = peekSet(relFilesSet)) != NULL)
1244         {
1245           char *objectName;
1246           size_t bufSize;
1247
1248           strncpyz (buffer, s, sizeof(buffer));
1249           /* remove extension (it must be .rel) */
1250           *strrchr (buffer, '.') = '\0';
1251           /* remove path */
1252           objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1253           if (objectName)
1254             {
1255               ++objectName;
1256             }
1257           else
1258             {
1259               objectName = buffer;
1260             }
1261           bufSize = strlen (dstPath) + strlen (objectName) + 1;  
1262           dstFileName = Safe_alloc (bufSize);
1263           strncpyz (dstFileName, dstPath, bufSize);
1264           strncatz (dstFileName, objectName, bufSize);
1265         }
1266       /* else no module given: help text is displayed */
1267     }
1268
1269   /* set up external stack location if not explicitly specified */
1270   if (!options.xstack_loc)
1271     options.xstack_loc = options.xdata_loc;
1272
1273   /* if debug option is set then open the cdbFile */
1274   if (options.debug && fullSrcFileName)
1275     {
1276       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1277                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1278       if(debugFile->openFile(scratchFileName))
1279         debugFile->writeModule(moduleName);
1280       else
1281         werror (E_FILE_OPEN_ERR, scratchFileName);
1282     }
1283   MSVC_style(options.vc_err_style);
1284   if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1285
1286   return 0;
1287 }
1288
1289 /*-----------------------------------------------------------------*/
1290 /* linkEdit : - calls the linkage editor  with options             */
1291 /*-----------------------------------------------------------------*/
1292 static void
1293 linkEdit (char **envp)
1294 {
1295   FILE *lnkfile;
1296   char *segName, *c;
1297   int system_ret;
1298   const char *s;
1299
1300
1301   if(port->linker.needLinkerScript)
1302     {
1303       char out_fmt;
1304       
1305       switch (options.out_fmt)
1306         {
1307         case 0:
1308           out_fmt = 'i';        /* Intel hex */
1309           break;
1310         case 1:
1311           out_fmt = 's';        /* Motorola S19 */
1312           break;
1313         case 2:
1314           out_fmt = 't';        /* Elf */
1315           break;
1316         default:
1317           out_fmt = 'i';
1318         }
1319       
1320       /* first we need to create the <filename>.lnk file */
1321       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1322         "%s.lnk", dstFileName);
1323       if (!(lnkfile = fopen (scratchFileName, "w")))
1324         {
1325           werror (E_FILE_OPEN_ERR, scratchFileName);
1326           exit (1);
1327         }
1328
1329       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1330         {
1331           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1332             out_fmt, dstFileName);
1333         }
1334       else /*For all the other ports.  Including pics???*/
1335         {
1336           fprintf (lnkfile, "-myux%c\n", out_fmt);
1337           if(options.pack_iram)
1338               fprintf (lnkfile, "-Y\n");
1339         }
1340
1341       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1342         {
1343           /* if iram size specified */
1344           if (options.iram_size)
1345             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1346
1347           /* if stack size specified*/
1348           if(options.stack_size)
1349               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1350
1351           /* if xram size specified */
1352           if (options.xram_size_set)
1353             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1354
1355           /* if code size specified */
1356           if (options.code_size)
1357             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1358
1359           if (options.debug)
1360             fprintf (lnkfile, "-z\n");
1361         }
1362
1363 #define WRITE_SEG_LOC(N, L) \
1364   segName = Safe_strdup(N); \
1365   c = strtok(segName, " \t"); \
1366   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1367   if (segName) { Safe_free(segName); }
1368
1369       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1370         {
1371
1372           /* code segment start */
1373           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1374
1375           /* data segment start. If zero, the linker chooses
1376              the best place for data */
1377           if(options.data_loc)
1378             {
1379               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1380             }
1381
1382           /* xdata start */
1383           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1384
1385           /* indirect data */
1386           if (IDATA_NAME)
1387             {
1388               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1389             }
1390
1391             /* bit segment start */
1392             WRITE_SEG_LOC (BIT_NAME, 0);
1393
1394             /* stack start */
1395             if ( (options.stack_loc) && (options.stack_loc<0x100) )
1396               {
1397                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1398               }
1399         }
1400       else /*For the z80, gbz80*/
1401         {
1402           WRITE_SEG_LOC ("_CODE", options.code_loc);
1403           WRITE_SEG_LOC ("_DATA", options.data_loc);
1404         }
1405   
1406       /* If the port has any special linker area declarations, get 'em */
1407       if (port->extraAreas.genExtraAreaLinkOptions)
1408         {
1409           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1410         }
1411
1412       /* add the extra linker options */
1413       fputStrSet(lnkfile, linkOptionsSet);
1414
1415       /* command line defined library paths if specified */
1416       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1417         fprintf (lnkfile, "-k %s\n", s);
1418
1419       /* standard library path */
1420       if (!options.nostdlib)
1421         {
1422           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1423             {
1424               switch (options.model)
1425                 {
1426                   case MODEL_SMALL:
1427                   c = "small";
1428                   break;
1429                 case MODEL_LARGE:
1430                   c = "large";
1431                   break;
1432                 case MODEL_FLAT24:
1433                   /* c = "flat24"; */
1434                   if (TARGET_IS_DS390)
1435                     {
1436                       c = "ds390";
1437                     }
1438                   else if (TARGET_IS_DS400)
1439                     {
1440                       c = "ds400";
1441                     }
1442                   else
1443                     {
1444                       fprintf(stderr, 
1445                         "Add support for your FLAT24 target in %s @ line %d\n",
1446                         __FILE__, __LINE__);
1447                       exit(-1);
1448                     }
1449                   break;
1450                 case MODEL_PAGE0:
1451                   c = "xa51";
1452                   break;
1453                 default:
1454                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1455                   c = "unknown";
1456                   break;
1457                 }
1458             }
1459           else /*for the z80, gbz80*/
1460             {
1461               if (TARGET_IS_HC08)
1462                 c = "hc08";
1463               else if (TARGET_IS_Z80)
1464                 c = "z80";
1465               else
1466                 c = "gbz80";
1467             }
1468           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1469             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1470         }
1471
1472       /* command line defined library files if specified */
1473       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1474         fprintf (lnkfile, "-l %s\n", s);
1475
1476       /* standard library files */
1477       if (!options.nostdlib)
1478         {
1479 #if !OPT_DISABLE_DS390
1480           if (options.model == MODEL_FLAT24)
1481             {
1482               if (TARGET_IS_DS390)
1483                 {
1484                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1485                 }
1486               else if (TARGET_IS_DS400)
1487                 {
1488                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1489                 }
1490               else
1491                 {
1492                   fprintf(stderr, 
1493                     "Add support for your FLAT24 target in %s @ line %d\n",
1494                     __FILE__, __LINE__);
1495                   exit(-1);
1496                 }
1497               }
1498 #endif
1499
1500 #if !OPT_DISABLE_XA51 
1501 #ifdef STD_XA51_LIB
1502           if (options.model == MODEL_PAGE0)
1503             {
1504               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1505             }
1506 #endif
1507 #endif
1508           if (TARGET_IS_MCS51)
1509             {
1510               fprintf (lnkfile, "-l mcs51\n");
1511             }
1512           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1513             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1514             { /*Why the z80 port is not using the standard libraries?*/
1515               fprintf (lnkfile, "-l %s\n", STD_LIB);
1516               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1517               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1518               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1519             }
1520           else if (TARGET_IS_HC08)
1521             {
1522               fprintf (lnkfile, "-l hc08\n");
1523             }
1524           else if (TARGET_IS_Z80)
1525             {
1526               fprintf (lnkfile, "-l z80\n");
1527             }
1528           else if (TARGET_IS_GBZ80)
1529             {
1530               fprintf (lnkfile, "-l gbz80\n");
1531             }
1532         }
1533
1534       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1535       It is very important for this file to be first on the linking proccess
1536       so the areas are set in the correct order, expecially _GSINIT*/
1537       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1538         !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1539         {
1540           char crt0path[PATH_MAX];
1541           FILE * crt0fp;
1542           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1543             {
1544               sprintf (crt0path, "%s%s%s%scrt0.o",
1545                 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1546
1547               crt0fp=fopen(crt0path, "r");
1548               if(crt0fp!=NULL)/*Found it!*/
1549                 {
1550                   fclose(crt0fp);
1551                   #ifdef __CYGWIN__
1552                   {
1553                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1554                     windows paths, so convert them to the CYGWIN format*/
1555                     char posix_path[PATH_MAX];
1556                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1557                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1558                     strcpy(crt0path, posix_path);
1559                   }
1560                   #endif
1561                   fprintf (lnkfile, "%s\n", crt0path);
1562                   break;
1563                 }
1564             }
1565           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1566         }
1567
1568       /* put in the object files */
1569       if (fullSrcFileName)
1570         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1571
1572       fputStrSet(lnkfile, relFilesSet);
1573
1574       fprintf (lnkfile, "\n-e\n");
1575       fclose (lnkfile);
1576     } /* if(port->linker.needLinkerScript) */
1577
1578   if (options.verbose)
1579     printf ("sdcc: Calling linker...\n");
1580
1581   /* build linker output filename */
1582
1583   /* -o option overrides default name? */
1584   if (fullDstFileName)
1585     {
1586       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1587     }
1588   else
1589     {
1590       /* the linked file gets the name of the first modul */
1591       if (fullSrcFileName)
1592         {
1593           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1594         }
1595       else
1596         {
1597           s = peekSet(relFilesSet);
1598
1599           assert(s);
1600
1601           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1602           /* strip ".rel" extension */
1603           *strrchr (scratchFileName, '.') = '\0';
1604         }
1605       strncatz (scratchFileName, 
1606         options.out_fmt ? ".S19" : ".ihx",
1607         sizeof(scratchFileName));
1608     }
1609
1610   if (port->linker.cmd)
1611     {
1612       char buffer2[PATH_MAX];
1613       set *libSet=NULL;
1614
1615       if(TARGET_IS_PIC16) {
1616          /* use $3 to set the linker include directories */
1617          libSet = appendStrSet(libDirsSet, "-I\"", "\"");
1618
1619          /* now add the libraries from command line */
1620          mergeSets(&libSet, libFilesSet);
1621       }
1622       
1623       buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1624       if(libSet)deleteSet(&libSet);
1625
1626       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1627     }
1628   else
1629     {
1630       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1631     }
1632
1633   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1634
1635   system_ret = my_system (buffer);
1636   /* TODO: most linker don't have a -o parameter */
1637   /* -o option overrides default name? */
1638   if (fullDstFileName)
1639     {
1640       char *p, *q;
1641       /* the linked file gets the name of the first modul */
1642       if (fullSrcFileName)
1643         {
1644           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1645           p = strlen (scratchFileName) + scratchFileName;
1646         }
1647       else
1648         {
1649           s = peekSet(relFilesSet);
1650
1651           assert(s);
1652
1653           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1654           /* strip ".rel" extension */
1655           p = strrchr (scratchFileName, '.');
1656           if (p)
1657             {
1658               *p = 0;
1659             }
1660         }
1661       strncatz (scratchFileName,
1662         options.out_fmt ? ".S19" : ".ihx",
1663         sizeof(scratchFileName));
1664       if (strcmp (fullDstFileName, scratchFileName))
1665         unlink (fullDstFileName);
1666       rename (scratchFileName, fullDstFileName);
1667
1668       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1669       q = strrchr (buffer, '.');
1670       if (!q)
1671         {
1672           /* no extension: append new extensions */
1673           q = strlen (buffer) + buffer;
1674         }
1675
1676       *p = 0;
1677       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1678       *q = 0;
1679       strncatz(buffer, ".map", sizeof(buffer));
1680       if (strcmp (scratchFileName, buffer))
1681         unlink (buffer);
1682       rename (scratchFileName, buffer);
1683       *p = 0;
1684       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1685       *q = 0;
1686       strncatz(buffer, ".mem", sizeof(buffer));
1687       if (strcmp (scratchFileName, buffer))
1688         unlink (buffer);
1689       rename (scratchFileName, buffer);
1690       if (options.debug)
1691         {
1692           *p = 0;
1693           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1694           *q = 0;
1695           strncatz(buffer, ".cdb", sizeof(buffer));
1696           if (strcmp (scratchFileName, buffer))
1697             unlink (buffer);
1698           rename (scratchFileName, buffer);
1699           /* and the OMF file without extension: */
1700           *p = 0;
1701           *q = 0;
1702           if (strcmp (scratchFileName, buffer))
1703             unlink (buffer);
1704           rename (scratchFileName, buffer);
1705         }
1706     }
1707   if (system_ret)
1708     {
1709       exit (1);
1710     }
1711 }
1712
1713 /*-----------------------------------------------------------------*/
1714 /* assemble - spawns the assembler with arguments                  */
1715 /*-----------------------------------------------------------------*/
1716 static void
1717 assemble (char **envp)
1718 {
1719     /* build assembler output filename */
1720
1721     /* -o option overrides default name? */
1722     if (options.cc_only && fullDstFileName) {
1723         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1724     } else {
1725         /* the assembled file gets the name of the first modul */
1726         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1727         strncatz (scratchFileName, port->linker.rel_ext, 
1728                   sizeof(scratchFileName));
1729     }
1730
1731     if (port->assembler.do_assemble) {
1732         port->assembler.do_assemble(asmOptionsSet);
1733         return ;
1734     } else if (port->assembler.cmd) {
1735         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1736                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1737                       asmOptionsSet);
1738     } else {
1739         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1740     }
1741
1742     if (my_system (buffer)) {
1743         /* either system() or the assembler itself has reported an error
1744            perror ("Cannot exec assembler");
1745         */
1746         exit (1);
1747     }
1748     /* TODO: most assembler don't have a -o parameter */
1749     /* -o option overrides default name? */
1750     if (options.cc_only && fullDstFileName) {
1751         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1752         strncatz (scratchFileName, 
1753                   port->linker.rel_ext,
1754                   sizeof(scratchFileName));
1755         if (strcmp (scratchFileName, fullDstFileName))
1756           unlink (fullDstFileName);
1757         rename (scratchFileName, fullDstFileName);
1758     }
1759 }
1760
1761 /*-----------------------------------------------------------------*/
1762 /* preProcess - spawns the preprocessor with arguments       */
1763 /*-----------------------------------------------------------------*/
1764 static int
1765 preProcess (char **envp)
1766 {
1767   if (options.c1mode)
1768     {
1769       yyin = stdin;
1770     }
1771   else
1772     {
1773       const char *s;
1774       set *inclList = NULL;
1775
1776       /* if using external stack define the macro */
1777       if (options.useXstack)
1778         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1779
1780       /* set the macro for stack autos  */
1781       if (options.stackAuto)
1782         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1783
1784       /* set the macro for stack autos  */
1785       if (options.stack10bit)
1786         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1787
1788       /* set the macro for no overlay  */
1789       if (options.noOverlay)
1790         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1791
1792       /* set the macro for large model  */
1793       switch (options.model)
1794         {
1795         case MODEL_LARGE:
1796           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1797           break;
1798         case MODEL_SMALL:
1799           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1800           break;
1801         case MODEL_COMPACT:
1802           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1803           break;
1804         case MODEL_MEDIUM:
1805           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1806           break;
1807         case MODEL_FLAT24:
1808           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1809           break;
1810         case MODEL_PAGE0:
1811           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1812           break;
1813         default:
1814           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1815           break;
1816         }
1817
1818       /* add port (processor information to processor */
1819       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1820       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1821
1822       /* standard include path */
1823       if (!options.nostdinc) {
1824         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1825         mergeSets(&preArgvSet, inclList);
1826       }
1827
1828       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1829       Safe_free((void *)s);
1830       if (inclList != NULL)
1831         deleteSet(&inclList);
1832
1833       if (preProcOnly && fullDstFileName)
1834         {
1835           /* -E and -o given */
1836           setMainValue ("cppoutfilename", fullDstFileName);
1837         }
1838       else
1839         {
1840           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1841           setMainValue ("cppoutfilename", NULL);
1842         }
1843
1844       if (options.verbose)
1845         printf ("sdcc: Calling preprocessor...\n");
1846
1847       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1848
1849       if (preProcOnly) {
1850         if (my_system (buffer)) {
1851           exit (1);
1852         }
1853
1854         exit (0);
1855       }
1856
1857       yyin = my_popen (buffer);
1858       if (yyin == NULL) {
1859           perror ("Preproc file not found");
1860           exit (1);
1861       }
1862       addSetHead (&pipeSet, yyin);
1863     }
1864
1865   return 0;
1866 }
1867
1868 /* Set bin paths */
1869 static void
1870 setBinPaths(const char *argv0)
1871 {
1872   char *p;
1873   char buf[PATH_MAX];
1874
1875   /*
1876    * Search logic:
1877    *
1878    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1879    * 2. - path(argv[0])
1880    * 3. - $PATH
1881    */
1882
1883   /* do it in reverse mode, so that addSetHead() can be used
1884      instead of slower addSet() */
1885
1886   if ((p = getBinPath(argv0)) != NULL)
1887     addSetHead(&binPathSet, Safe_strdup(p));
1888
1889   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1890     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1891     addSetHead(&binPathSet, Safe_strdup(buf));
1892   }
1893
1894   if (options.printSearchDirs) {
1895     printf("programs:\n");
1896     fputStrSet(stdout, binPathSet);
1897   }
1898 }
1899
1900 /* Set system include path */
1901 static void
1902 setIncludePath(void)
1903 {
1904   char *p;
1905
1906   /*
1907    * Search logic:
1908    *
1909    * 1. - $SDCC_INCLUDE
1910    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1911    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1912    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1913    */
1914
1915   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1916
1917   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1918     addSetHead(&includeDirsSet, p);
1919
1920   if (options.printSearchDirs) {
1921     printf("includedir:\n");
1922     fputStrSet(stdout, includeDirsSet);
1923   }
1924 }
1925
1926 /* Set system lib path */
1927 static void
1928 setLibPath(void)
1929 {
1930   char *p;
1931
1932   /*
1933    * Search logic:
1934    *
1935    * 1. - $SDCC_LIB
1936    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1937    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1938    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1939    */
1940
1941   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1942
1943   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1944     addSetHead(&libDirsSet, p);
1945
1946   if (options.printSearchDirs) {
1947     printf("libdir:\n");
1948     fputStrSet(stdout, libDirsSet);
1949   }
1950 }
1951
1952 /* Set data path */
1953 static void
1954 setDataPaths(const char *argv0)
1955 {
1956   char *p;
1957   char buf[PATH_MAX];
1958
1959   /*
1960    * Search logic:
1961    *
1962    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1963    * 2. - path(argv[0])/BIN2DATA_DIR
1964    * 3. - DATADIR (only on *nix)
1965    */
1966
1967   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1968     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1969     addSet(&dataDirsSet, Safe_strdup(buf));
1970   }
1971
1972   if ((p = getBinPath(argv0)) != NULL) {
1973     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1974     addSet(&dataDirsSet, Safe_strdup(buf));
1975   }
1976
1977 #ifdef _WIN32
1978   if (peekSet(dataDirsSet) == NULL) {
1979     /* this should never happen... */
1980     wassertl(0, "Can't get binary path");
1981   }
1982 #else
1983   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1984 #endif
1985
1986   if (options.printSearchDirs) {
1987     printf("datadir:\n");
1988     fputStrSet(stdout, dataDirsSet);
1989   }
1990
1991   setIncludePath();
1992   setLibPath();
1993 }
1994
1995 static void
1996 initValues (void)
1997 {
1998   populateMainValues (_baseValues);
1999   setMainValue ("port", port->target);
2000   setMainValue ("objext", port->linker.rel_ext);
2001   setMainValue ("asmext", port->assembler.file_ext);
2002
2003   setMainValue ("dstfilename", dstFileName);
2004   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2005
2006   if (options.cc_only && fullDstFileName)
2007     /* compile + assemble and -o given: -o specifies name of object file */
2008     {
2009       setMainValue ("objdstfilename", fullDstFileName);
2010     }
2011   else
2012     {
2013       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2014     }
2015   if (fullDstFileName)
2016     /* if we're linking, -o gives the final file name */
2017     {
2018       setMainValue ("linkdstfilename", fullDstFileName);
2019     }
2020   else
2021     {
2022       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2023     }
2024
2025 }
2026
2027 static void
2028 sig_handler (int signal)
2029 {
2030   char *sig_string;
2031
2032   switch (signal)
2033     {
2034     case SIGABRT:
2035       sig_string = "SIGABRT";
2036       break;
2037     case SIGTERM:
2038       sig_string = "SIGTERM";
2039       break;
2040     case SIGINT:
2041       sig_string = "SIGINT";
2042       break;
2043     case SIGSEGV:
2044       sig_string = "SIGSEGV";
2045       break;
2046     default:
2047       sig_string = "Unknown?";
2048       break;
2049     }
2050   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2051   exit (1);
2052 }
2053
2054 /*
2055  * main routine
2056  * initialises and calls the parser
2057  */
2058
2059 int
2060 main (int argc, char **argv, char **envp)
2061 {
2062   /* turn all optimizations off by default */
2063   memset (&optimize, 0, sizeof (struct optimize));
2064
2065   /*printVersionInfo (); */
2066
2067   if (NUM_PORTS==0) {
2068     fprintf (stderr, "Build error: no ports are enabled.\n");
2069     exit (1);
2070   }
2071
2072   /* install atexit handler */
2073   atexit(rm_tmpfiles);
2074
2075   /* install signal handler;
2076      it's only purpuse is to call exit() to remove temp files */
2077   if (!getenv("SDCC_LEAVE_SIGNALS"))
2078     {
2079       signal (SIGABRT, sig_handler);
2080       signal (SIGTERM, sig_handler);
2081       signal (SIGINT , sig_handler);
2082       signal (SIGSEGV, sig_handler);
2083     }
2084
2085   /* Before parsing the command line options, do a
2086    * search for the port and processor and initialize
2087    * them if they're found. (We can't gurantee that these
2088    * will be the first options specified).
2089    */
2090
2091   _findPort (argc, argv);
2092
2093 #ifdef JAMIN_DS390
2094   if (strcmp(port->target, "mcs51") == 0) {
2095     printf("DS390 jammed in A\n");
2096           _setPort ("ds390");
2097     ds390_jammed = 1;
2098   }
2099 #endif
2100
2101   _findProcessor (argc, argv);
2102
2103   /* Initalise the port. */
2104   if (port->init)
2105     port->init ();
2106
2107   setDefaultOptions ();
2108 #ifdef JAMIN_DS390
2109   if (ds390_jammed) {
2110     options.model = MODEL_SMALL;
2111     options.stack10bit=0;
2112   }
2113 #endif
2114   parseCmdLine (argc, argv);
2115
2116   initValues ();
2117   setBinPaths(argv[0]);
2118   setDataPaths(argv[0]);
2119
2120   /* if no input then printUsage & exit */
2121   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2122     if (!options.printSearchDirs)
2123       printUsage();
2124
2125     exit(0);
2126   }
2127
2128   /* initMem() is expensive, but
2129      initMem() must called before port->finaliseOptions ().
2130      And the z80 port needs port->finaliseOptions(),
2131      even if we're only linking. */
2132   initMem ();
2133   port->finaliseOptions ();
2134
2135   if (fullSrcFileName || options.c1mode)
2136     {
2137       preProcess (envp);
2138
2139       initSymt ();
2140       initiCode ();
2141       initCSupport ();
2142       initBuiltIns();
2143       initPeepHole ();
2144
2145       if (options.verbose)
2146         printf ("sdcc: Generating code...\n");
2147
2148       yyparse ();
2149
2150       pclose(yyin);
2151       deleteSetItem(&pipeSet, yyin);
2152
2153       if (fatalError) {
2154         exit (1);
2155       }
2156
2157       if (port->general.do_glue != NULL)
2158         (*port->general.do_glue)();
2159       else
2160         {
2161           /* this shouldn't happen */
2162           assert(FALSE);
2163           /* in case of NDEBUG */
2164           glue();
2165         }
2166
2167       if (fatalError) {
2168         exit (1);
2169       }
2170
2171       if (!options.c1mode && !noAssemble)
2172         {
2173           if (options.verbose)
2174             printf ("sdcc: Calling assembler...\n");
2175           assemble (envp);
2176         }
2177     }
2178   closeDumpFiles();
2179
2180   if (options.debug && debugFile)
2181     debugFile->closeFile();
2182
2183   if (!options.cc_only &&
2184       !fatalError &&
2185       !noAssemble &&
2186       !options.c1mode &&
2187       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2188     {
2189       if (port->linker.do_link)
2190         port->linker.do_link ();
2191       else
2192         linkEdit (envp);
2193     }
2194
2195   return 0;
2196 }