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