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