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