Added options --stack-size and --pack-iram
[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       /* first we need to create the <filename>.lnk file */
1304       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1305         "%s.lnk", dstFileName);
1306       if (!(lnkfile = fopen (scratchFileName, "w")))
1307         {
1308           werror (E_FILE_OPEN_ERR, scratchFileName);
1309           exit (1);
1310         }
1311
1312       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1313         {
1314           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1315             (options.out_fmt ? 's' : 'i'), dstFileName);
1316         }
1317       else /*For all the other ports.  Including pics???*/
1318         {
1319           fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1320           if(options.pack_iram)
1321               fprintf (lnkfile, "-Y\n");
1322         }
1323
1324       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1325         {
1326           /* if iram size specified */
1327           if (options.iram_size)
1328             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1329
1330           /* if stack size specified*/
1331           if(options.stack_size)
1332               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1333
1334           /* if xram size specified */
1335           if (options.xram_size_set)
1336             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1337
1338           /* if code size specified */
1339           if (options.code_size)
1340             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1341
1342           if (options.debug)
1343             fprintf (lnkfile, "-z\n");
1344         }
1345
1346 #define WRITE_SEG_LOC(N, L) \
1347   segName = Safe_strdup(N); \
1348   c = strtok(segName, " \t"); \
1349   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1350   if (segName) { Safe_free(segName); }
1351
1352       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1353         {
1354
1355           /* code segment start */
1356           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1357
1358           /* data segment start. If zero, the linker chooses
1359              the best place for data */
1360           if(options.data_loc)
1361             {
1362               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1363             }
1364
1365           /* xdata start */
1366           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1367
1368           /* indirect data */
1369           if (IDATA_NAME)
1370             {
1371               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1372             }
1373
1374             /* bit segment start */
1375             WRITE_SEG_LOC (BIT_NAME, 0);
1376
1377             /* stack start */
1378             if ( (options.stack_loc) && (options.stack_loc<0x100) )
1379               {
1380                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1381               }
1382         }
1383       else /*For the z80, gbz80*/
1384         {
1385           WRITE_SEG_LOC ("_CODE", options.code_loc);
1386           WRITE_SEG_LOC ("_DATA", options.data_loc);
1387         }
1388   
1389       /* If the port has any special linker area declarations, get 'em */
1390       if (port->extraAreas.genExtraAreaLinkOptions)
1391         {
1392           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1393         }
1394
1395       /* add the extra linker options */
1396       fputStrSet(lnkfile, linkOptionsSet);
1397
1398       /* command line defined library paths if specified */
1399       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1400         fprintf (lnkfile, "-k %s\n", s);
1401
1402       /* standard library path */
1403       if (!options.nostdlib)
1404         {
1405           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1406             {
1407               switch (options.model)
1408                 {
1409                   case MODEL_SMALL:
1410                   c = "small";
1411                   break;
1412                 case MODEL_LARGE:
1413                   c = "large";
1414                   break;
1415                 case MODEL_FLAT24:
1416                   /* c = "flat24"; */
1417                   if (TARGET_IS_DS390)
1418                     {
1419                       c = "ds390";
1420                     }
1421                   else if (TARGET_IS_DS400)
1422                     {
1423                       c = "ds400";
1424                     }
1425                   else
1426                     {
1427                       fprintf(stderr, 
1428                         "Add support for your FLAT24 target in %s @ line %d\n",
1429                         __FILE__, __LINE__);
1430                       exit(-1);
1431                     }
1432                   break;
1433                 case MODEL_PAGE0:
1434                   c = "xa51";
1435                   break;
1436                 default:
1437                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1438                   c = "unknown";
1439                   break;
1440                 }
1441             }
1442           else /*for the z80, gbz80*/
1443             {
1444               if (TARGET_IS_HC08)
1445                 c = "hc08";
1446               else if (TARGET_IS_Z80)
1447                 c = "z80";
1448               else
1449                 c = "gbz80";
1450             }
1451           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1452             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1453         }
1454
1455       /* command line defined library files if specified */
1456       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1457         fprintf (lnkfile, "-l %s\n", s);
1458
1459       /* standard library files */
1460       if (!options.nostdlib)
1461         {
1462 #if !OPT_DISABLE_DS390
1463           if (options.model == MODEL_FLAT24)
1464             {
1465               if (TARGET_IS_DS390)
1466                 {
1467                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1468                 }
1469               else if (TARGET_IS_DS400)
1470                 {
1471                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1472                 }
1473               else
1474                 {
1475                   fprintf(stderr, 
1476                     "Add support for your FLAT24 target in %s @ line %d\n",
1477                     __FILE__, __LINE__);
1478                   exit(-1);
1479                 }
1480               }
1481 #endif
1482
1483 #if !OPT_DISABLE_XA51 
1484 #ifdef STD_XA51_LIB
1485           if (options.model == MODEL_PAGE0)
1486             {
1487               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1488             }
1489 #endif
1490 #endif
1491           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1492             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1493             { /*Why the z80 port is not using the standard libraries?*/
1494               fprintf (lnkfile, "-l %s\n", STD_LIB);
1495               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1496               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1497               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1498             }
1499           else if (TARGET_IS_HC08)
1500             {
1501               fprintf (lnkfile, "-l hc08\n");
1502             }
1503           else if (TARGET_IS_Z80)
1504             {
1505               fprintf (lnkfile, "-l z80\n");
1506             }
1507           else if (TARGET_IS_GBZ80)
1508             {
1509               fprintf (lnkfile, "-l gbz80\n");
1510             }
1511         }
1512
1513       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1514       It is very important for this file to be first on the linking proccess
1515       so the areas are set in the correct order, expecially _GSINIT*/
1516       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1517         !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1518         {
1519           char crt0path[PATH_MAX];
1520           FILE * crt0fp;
1521           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1522             {
1523               sprintf (crt0path, "%s%s%s%scrt0.o",
1524                 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1525
1526               crt0fp=fopen(crt0path, "r");
1527               if(crt0fp!=NULL)/*Found it!*/
1528                 {
1529                   fclose(crt0fp);
1530                   #ifdef __CYGWIN__
1531                   {
1532                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1533                     windows paths, so convert them to the CYGWIN format*/
1534                     char posix_path[PATH_MAX];
1535                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1536                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1537                     strcpy(crt0path, posix_path);
1538                   }
1539                   #endif
1540                   fprintf (lnkfile, "%s\n", crt0path);
1541                   break;
1542                 }
1543             }
1544           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1545         }
1546
1547       /* put in the object files */
1548       if (fullSrcFileName)
1549         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1550
1551       fputStrSet(lnkfile, relFilesSet);
1552
1553       fprintf (lnkfile, "\n-e\n");
1554       fclose (lnkfile);
1555     } /* if(port->linker.needLinkerScript) */
1556
1557   if (options.verbose)
1558     printf ("sdcc: Calling linker...\n");
1559
1560   /* build linker output filename */
1561
1562   /* -o option overrides default name? */
1563   if (fullDstFileName)
1564     {
1565       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1566     }
1567   else
1568     {
1569       /* the linked file gets the name of the first modul */
1570       if (fullSrcFileName)
1571         {
1572           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1573         }
1574       else
1575         {
1576           s = peekSet(relFilesSet);
1577
1578           assert(s);
1579
1580           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1581           /* strip ".rel" extension */
1582           *strrchr (scratchFileName, '.') = '\0';
1583         }
1584       strncatz (scratchFileName, 
1585         options.out_fmt ? ".S19" : ".ihx",
1586         sizeof(scratchFileName));
1587     }
1588
1589   if (port->linker.cmd)
1590     {
1591       char buffer2[PATH_MAX];
1592       set *libSet=NULL;
1593
1594       if(TARGET_IS_PIC16) {
1595          /* use $3 to set the linker include directories */
1596          libSet = appendStrSet(libDirsSet, "-I\"", "\"");
1597
1598          /* now add the libraries from command line */
1599          mergeSets(&libSet, libFilesSet);
1600       }
1601       
1602       buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1603       if(libSet)deleteSet(&libSet);
1604
1605       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1606     }
1607   else
1608     {
1609       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1610     }
1611
1612   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1613
1614   system_ret = my_system (buffer);
1615   /* TODO: most linker don't have a -o parameter */
1616   /* -o option overrides default name? */
1617   if (fullDstFileName)
1618     {
1619       char *p, *q;
1620       /* the linked file gets the name of the first modul */
1621       if (fullSrcFileName)
1622         {
1623           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1624           p = strlen (scratchFileName) + scratchFileName;
1625         }
1626       else
1627         {
1628           s = peekSet(relFilesSet);
1629
1630           assert(s);
1631
1632           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1633           /* strip ".rel" extension */
1634           p = strrchr (scratchFileName, '.');
1635           if (p)
1636             {
1637               *p = 0;
1638             }
1639         }
1640       strncatz (scratchFileName,
1641         options.out_fmt ? ".S19" : ".ihx",
1642         sizeof(scratchFileName));
1643       if (strcmp (fullDstFileName, scratchFileName))
1644         unlink (fullDstFileName);
1645       rename (scratchFileName, fullDstFileName);
1646
1647       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1648       q = strrchr (buffer, '.');
1649       if (!q)
1650         {
1651           /* no extension: append new extensions */
1652           q = strlen (buffer) + buffer;
1653         }
1654
1655       *p = 0;
1656       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1657       *q = 0;
1658       strncatz(buffer, ".map", sizeof(buffer));
1659       if (strcmp (scratchFileName, buffer))
1660         unlink (buffer);
1661       rename (scratchFileName, buffer);
1662       *p = 0;
1663       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1664       *q = 0;
1665       strncatz(buffer, ".mem", sizeof(buffer));
1666       if (strcmp (scratchFileName, buffer))
1667         unlink (buffer);
1668       rename (scratchFileName, buffer);
1669       if (options.debug)
1670         {
1671           *p = 0;
1672           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1673           *q = 0;
1674           strncatz(buffer, ".cdb", sizeof(buffer));
1675           if (strcmp (scratchFileName, buffer))
1676             unlink (buffer);
1677           rename (scratchFileName, buffer);
1678           /* and the OMF file without extension: */
1679           *p = 0;
1680           *q = 0;
1681           if (strcmp (scratchFileName, buffer))
1682             unlink (buffer);
1683           rename (scratchFileName, buffer);
1684         }
1685     }
1686   if (system_ret)
1687     {
1688       exit (1);
1689     }
1690 }
1691
1692 /*-----------------------------------------------------------------*/
1693 /* assemble - spawns the assembler with arguments                  */
1694 /*-----------------------------------------------------------------*/
1695 static void
1696 assemble (char **envp)
1697 {
1698     /* build assembler output filename */
1699
1700     /* -o option overrides default name? */
1701     if (options.cc_only && fullDstFileName) {
1702         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1703     } else {
1704         /* the assembled file gets the name of the first modul */
1705         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1706         strncatz (scratchFileName, port->linker.rel_ext, 
1707                   sizeof(scratchFileName));
1708     }
1709
1710     if (port->assembler.do_assemble) {
1711         port->assembler.do_assemble(asmOptionsSet);
1712         return ;
1713     } else if (port->assembler.cmd) {
1714         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1715                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1716                       asmOptionsSet);
1717     } else {
1718         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1719     }
1720
1721     if (my_system (buffer)) {
1722         /* either system() or the assembler itself has reported an error
1723            perror ("Cannot exec assembler");
1724         */
1725         exit (1);
1726     }
1727     /* TODO: most assembler don't have a -o parameter */
1728     /* -o option overrides default name? */
1729     if (options.cc_only && fullDstFileName) {
1730         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1731         strncatz (scratchFileName, 
1732                   port->linker.rel_ext,
1733                   sizeof(scratchFileName));
1734         if (strcmp (scratchFileName, fullDstFileName))
1735           unlink (fullDstFileName);
1736         rename (scratchFileName, fullDstFileName);
1737     }
1738 }
1739
1740 /*-----------------------------------------------------------------*/
1741 /* preProcess - spawns the preprocessor with arguments       */
1742 /*-----------------------------------------------------------------*/
1743 static int
1744 preProcess (char **envp)
1745 {
1746   if (options.c1mode)
1747     {
1748       yyin = stdin;
1749     }
1750   else
1751     {
1752       const char *s;
1753       set *inclList = NULL;
1754
1755       /* if using external stack define the macro */
1756       if (options.useXstack)
1757         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1758
1759       /* set the macro for stack autos  */
1760       if (options.stackAuto)
1761         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1762
1763       /* set the macro for stack autos  */
1764       if (options.stack10bit)
1765         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1766
1767       /* set the macro for no overlay  */
1768       if (options.noOverlay)
1769         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1770
1771       /* set the macro for large model  */
1772       switch (options.model)
1773         {
1774         case MODEL_LARGE:
1775           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1776           break;
1777         case MODEL_SMALL:
1778           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1779           break;
1780         case MODEL_COMPACT:
1781           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1782           break;
1783         case MODEL_MEDIUM:
1784           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1785           break;
1786         case MODEL_FLAT24:
1787           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1788           break;
1789         case MODEL_PAGE0:
1790           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1791           break;
1792         default:
1793           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1794           break;
1795         }
1796
1797       /* add port (processor information to processor */
1798       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1799       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1800
1801       /* standard include path */
1802       if (!options.nostdinc) {
1803         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1804         mergeSets(&preArgvSet, inclList);
1805       }
1806
1807       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1808       Safe_free((void *)s);
1809       if (inclList != NULL)
1810         deleteSet(&inclList);
1811
1812       if (preProcOnly && fullDstFileName)
1813         {
1814           /* -E and -o given */
1815           setMainValue ("cppoutfilename", fullDstFileName);
1816         }
1817       else
1818         {
1819           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1820           setMainValue ("cppoutfilename", NULL);
1821         }
1822
1823       if (options.verbose)
1824         printf ("sdcc: Calling preprocessor...\n");
1825
1826       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1827
1828       if (preProcOnly) {
1829         if (my_system (buffer)) {
1830           exit (1);
1831         }
1832
1833         exit (0);
1834       }
1835
1836       yyin = my_popen (buffer);
1837       if (yyin == NULL) {
1838           perror ("Preproc file not found");
1839           exit (1);
1840       }
1841       addSetHead (&pipeSet, yyin);
1842     }
1843
1844   return 0;
1845 }
1846
1847 /* Set bin paths */
1848 static void
1849 setBinPaths(const char *argv0)
1850 {
1851   char *p;
1852   char buf[PATH_MAX];
1853
1854   /*
1855    * Search logic:
1856    *
1857    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1858    * 2. - path(argv[0])
1859    * 3. - $PATH
1860    */
1861
1862   /* do it in reverse mode, so that addSetHead() can be used
1863      instead of slower addSet() */
1864
1865   if ((p = getBinPath(argv0)) != NULL)
1866     addSetHead(&binPathSet, Safe_strdup(p));
1867
1868   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1869     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1870     addSetHead(&binPathSet, Safe_strdup(buf));
1871   }
1872
1873   if (options.printSearchDirs) {
1874     printf("programs:\n");
1875     fputStrSet(stdout, binPathSet);
1876   }
1877 }
1878
1879 /* Set system include path */
1880 static void
1881 setIncludePath(void)
1882 {
1883   char *p;
1884
1885   /*
1886    * Search logic:
1887    *
1888    * 1. - $SDCC_INCLUDE
1889    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1890    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1891    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1892    */
1893
1894   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1895
1896   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1897     addSetHead(&includeDirsSet, p);
1898
1899   if (options.printSearchDirs) {
1900     printf("includedir:\n");
1901     fputStrSet(stdout, includeDirsSet);
1902   }
1903 }
1904
1905 /* Set system lib path */
1906 static void
1907 setLibPath(void)
1908 {
1909   char *p;
1910
1911   /*
1912    * Search logic:
1913    *
1914    * 1. - $SDCC_LIB
1915    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1916    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1917    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1918    */
1919
1920   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1921
1922   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1923     addSetHead(&libDirsSet, p);
1924
1925   if (options.printSearchDirs) {
1926     printf("libdir:\n");
1927     fputStrSet(stdout, libDirsSet);
1928   }
1929 }
1930
1931 /* Set data path */
1932 static void
1933 setDataPaths(const char *argv0)
1934 {
1935   char *p;
1936   char buf[PATH_MAX];
1937
1938   /*
1939    * Search logic:
1940    *
1941    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1942    * 2. - path(argv[0])/BIN2DATA_DIR
1943    * 3. - DATADIR (only on *nix)
1944    */
1945
1946   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1947     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1948     addSet(&dataDirsSet, Safe_strdup(buf));
1949   }
1950
1951   if ((p = getBinPath(argv0)) != NULL) {
1952     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1953     addSet(&dataDirsSet, Safe_strdup(buf));
1954   }
1955
1956 #ifdef _WIN32
1957   if (peekSet(dataDirsSet) == NULL) {
1958     /* this should never happen... */
1959     wassertl(0, "Can't get binary path");
1960   }
1961 #else
1962   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1963 #endif
1964
1965   if (options.printSearchDirs) {
1966     printf("datadir:\n");
1967     fputStrSet(stdout, dataDirsSet);
1968   }
1969
1970   setIncludePath();
1971   setLibPath();
1972 }
1973
1974 static void
1975 initValues (void)
1976 {
1977   populateMainValues (_baseValues);
1978   setMainValue ("port", port->target);
1979   setMainValue ("objext", port->linker.rel_ext);
1980   setMainValue ("asmext", port->assembler.file_ext);
1981
1982   setMainValue ("dstfilename", dstFileName);
1983   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1984
1985   if (options.cc_only && fullDstFileName)
1986     /* compile + assemble and -o given: -o specifies name of object file */
1987     {
1988       setMainValue ("objdstfilename", fullDstFileName);
1989     }
1990   else
1991     {
1992       setMainValue ("objdstfilename", "{stdobjdstfilename}");
1993     }
1994   if (fullDstFileName)
1995     /* if we're linking, -o gives the final file name */
1996     {
1997       setMainValue ("linkdstfilename", fullDstFileName);
1998     }
1999   else
2000     {
2001       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2002     }
2003
2004 }
2005
2006 static void
2007 sig_handler (int signal)
2008 {
2009   char *sig_string;
2010
2011   switch (signal)
2012     {
2013     case SIGABRT:
2014       sig_string = "SIGABRT";
2015       break;
2016     case SIGTERM:
2017       sig_string = "SIGTERM";
2018       break;
2019     case SIGINT:
2020       sig_string = "SIGINT";
2021       break;
2022     case SIGSEGV:
2023       sig_string = "SIGSEGV";
2024       break;
2025     default:
2026       sig_string = "Unknown?";
2027       break;
2028     }
2029   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2030   exit (1);
2031 }
2032
2033 /*
2034  * main routine
2035  * initialises and calls the parser
2036  */
2037
2038 int
2039 main (int argc, char **argv, char **envp)
2040 {
2041   /* turn all optimizations off by default */
2042   memset (&optimize, 0, sizeof (struct optimize));
2043
2044   /*printVersionInfo (); */
2045
2046   if (NUM_PORTS==0) {
2047     fprintf (stderr, "Build error: no ports are enabled.\n");
2048     exit (1);
2049   }
2050
2051   /* install atexit handler */
2052   atexit(rm_tmpfiles);
2053
2054   /* install signal handler;
2055      it's only purpuse is to call exit() to remove temp files */
2056   if (!getenv("SDCC_LEAVE_SIGNALS"))
2057     {
2058       signal (SIGABRT, sig_handler);
2059       signal (SIGTERM, sig_handler);
2060       signal (SIGINT , sig_handler);
2061       signal (SIGSEGV, sig_handler);
2062     }
2063
2064   /* Before parsing the command line options, do a
2065    * search for the port and processor and initialize
2066    * them if they're found. (We can't gurantee that these
2067    * will be the first options specified).
2068    */
2069
2070   _findPort (argc, argv);
2071
2072 #ifdef JAMIN_DS390
2073   if (strcmp(port->target, "mcs51") == 0) {
2074     printf("DS390 jammed in A\n");
2075           _setPort ("ds390");
2076     ds390_jammed = 1;
2077   }
2078 #endif
2079
2080   _findProcessor (argc, argv);
2081
2082   /* Initalise the port. */
2083   if (port->init)
2084     port->init ();
2085
2086   setDefaultOptions ();
2087 #ifdef JAMIN_DS390
2088   if (ds390_jammed) {
2089     options.model = MODEL_SMALL;
2090     options.stack10bit=0;
2091   }
2092 #endif
2093   parseCmdLine (argc, argv);
2094
2095   initValues ();
2096   setBinPaths(argv[0]);
2097   setDataPaths(argv[0]);
2098
2099   /* if no input then printUsage & exit */
2100   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2101     if (!options.printSearchDirs)
2102       printUsage();
2103
2104     exit(0);
2105   }
2106
2107   /* initMem() is expensive, but
2108      initMem() must called before port->finaliseOptions ().
2109      And the z80 port needs port->finaliseOptions(),
2110      even if we're only linking. */
2111   initMem ();
2112   port->finaliseOptions ();
2113
2114   if (fullSrcFileName || options.c1mode)
2115     {
2116       preProcess (envp);
2117
2118       initSymt ();
2119       initiCode ();
2120       initCSupport ();
2121       initBuiltIns();
2122       initPeepHole ();
2123
2124       if (options.verbose)
2125         printf ("sdcc: Generating code...\n");
2126
2127       yyparse ();
2128
2129       pclose(yyin);
2130       deleteSetItem(&pipeSet, yyin);
2131
2132       if (fatalError) {
2133         exit (1);
2134       }
2135
2136       if (port->general.do_glue != NULL)
2137         (*port->general.do_glue)();
2138       else
2139         {
2140           /* this shouldn't happen */
2141           assert(FALSE);
2142           /* in case of NDEBUG */
2143           glue();
2144         }
2145
2146       if (fatalError) {
2147         exit (1);
2148       }
2149
2150       if (!options.c1mode && !noAssemble)
2151         {
2152           if (options.verbose)
2153             printf ("sdcc: Calling assembler...\n");
2154           assemble (envp);
2155         }
2156     }
2157   closeDumpFiles();
2158
2159   if (options.debug && debugFile)
2160     debugFile->closeFile();
2161
2162   if (!options.cc_only &&
2163       !fatalError &&
2164       !noAssemble &&
2165       !options.c1mode &&
2166       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2167     {
2168       if (port->linker.do_link)
2169         port->linker.do_link ();
2170       else
2171         linkEdit (envp);
2172     }
2173
2174   return 0;
2175 }