* src/SDCCmain.c: removed option -C since SDCC compiler doesn't know
[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,       &options.xram_size, "<nnnn> External Ram size", CLAT_INTEGER },
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_NO_GCSE) == 0)
992             {
993               optimize.global_cse = 0;
994               continue;
995             }
996
997           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
998             {
999               optimize.loopInvariant = 0;
1000               continue;
1001             }
1002
1003           if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1004             {
1005               optimize.label4 = 0;
1006               continue;
1007             }
1008
1009           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1010             {
1011               optimize.loopInduction = 0;
1012               continue;
1013             }
1014
1015           if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1016             {
1017               optimize.codeSpeed = 1;
1018               optimize.codeSize = 0;
1019               continue;
1020             }
1021
1022           if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1023             {
1024               optimize.codeSpeed = 0;
1025               optimize.codeSize = 1;
1026               continue;
1027             }
1028
1029           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1030             {
1031               options.lessPedantic = 1;
1032               setErrorLogLevel(ERROR_LEVEL_WARNING);
1033               continue;
1034             }
1035
1036           if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1037             {
1038               int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1039               if (w < MAX_ERROR_WARNING)
1040                 {
1041                   setWarningDisabled(w);
1042                 }
1043               continue;
1044             }
1045
1046           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1047             {
1048               options.shortis8bits=1;
1049               continue;
1050             }
1051
1052           if (strcmp (argv[i], OPTION_STD_C89) == 0)
1053             {
1054               options.std_c99 = 0;
1055               options.std_sdcc = 0;
1056               continue;
1057             }
1058
1059           if (strcmp (argv[i], OPTION_STD_C99) == 0)
1060             {
1061               options.std_c99 = 1;
1062               options.std_sdcc = 0;
1063               continue;
1064             }
1065
1066           if (strcmp (argv[i], OPTION_STD_SDCC89) == 0)
1067             {
1068               options.std_c99 = 0;
1069               options.std_sdcc = 1;
1070               continue;
1071             }
1072
1073           if (strcmp (argv[i], OPTION_STD_SDCC99) == 0)
1074             {
1075               options.std_c99 = 1;
1076               options.std_sdcc = 1;
1077               continue;
1078             }
1079
1080           if (strcmp (argv[i], OPTION_CODE_SEG) == 0)
1081             {
1082               struct dbuf_s segname;
1083
1084               dbuf_init (&segname, 16);
1085               dbuf_printf (&segname, "%-8s(CODE)", getStringArg (OPTION_CODE_SEG, argv, &i, argc));
1086               if (options.code_seg) Safe_free(options.code_seg);
1087               options.code_seg = dbuf_detach (&segname);
1088               continue;
1089             }
1090
1091           if (strcmp (argv[i], OPTION_CONST_SEG) == 0)
1092             {
1093               struct dbuf_s segname;
1094
1095               dbuf_init (&segname, 16);
1096               dbuf_printf (&segname, "%-8s(CODE)", getStringArg (OPTION_CONST_SEG, argv, &i, argc));
1097               if (options.const_seg) Safe_free(options.const_seg);
1098               options.const_seg = dbuf_detach (&segname);
1099               continue;
1100             }
1101
1102           werror (W_UNKNOWN_OPTION, argv[i]);
1103           continue;
1104         }
1105
1106       /* if preceded by  '-' then option */
1107       if (*argv[i] == '-')
1108         {
1109           switch (argv[i][1])
1110             {
1111             case 'h':
1112               verifyShortOption(argv[i]);
1113
1114               printUsage ();
1115               exit (EXIT_SUCCESS);
1116               break;
1117
1118             case 'm':
1119               /* Used to select the port. But this has already been done. */
1120               break;
1121
1122             case 'p':
1123               /* Used to select the processor in port. But this has
1124                * already been done. */
1125               break;
1126
1127             case 'c':
1128               verifyShortOption(argv[i]);
1129
1130               options.cc_only = 1;
1131               break;
1132
1133             case 'L':
1134                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1135                 break;
1136
1137             case 'l':
1138                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1139                 break;
1140
1141             case 'o':
1142               {
1143                 char *outName = getStringArg("-o", argv, &i, argc);
1144                 size_t len = strlen(outName);
1145
1146                 /* point to last character */
1147                 if (IS_DIR_SEPARATOR(outName[len - 1]))
1148                   {
1149                     /* only output path specified */
1150                     dstPath = Safe_malloc(len);
1151                     memcpy(dstPath, outName, len - 1);
1152                     dstPath[len - 1] = '\0';
1153                     fullDstFileName = NULL;
1154                   }
1155                 else
1156                   {
1157                     struct dbuf_s path;
1158
1159                     dbuf_init (&path, 128);
1160                     fullDstFileName = Safe_strdup (outName);
1161
1162                     /* get rid of the "."-extension */
1163                     dbuf_splitFile (outName, &path, NULL);
1164
1165                     dbuf_c_str (&path);
1166                     dstFileName = dbuf_detach (&path);
1167
1168                     dbuf_init (&path, 128);
1169                     /* strip module name to get path */
1170                     if (dbuf_splitPath (dstFileName, &path, NULL))
1171                       {
1172                         dbuf_c_str (&path);
1173                         dstPath = dbuf_detach (&path);
1174                       }
1175                     else
1176                       dbuf_destroy (&path);
1177                   }
1178                 break;
1179               }
1180
1181             case 'W':
1182               /* pre-processer options */
1183               if (argv[i][2] == 'p')
1184                 {
1185                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1186                 }
1187               /* linker options */
1188               else if (argv[i][2] == 'l')
1189                 {
1190                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1191                 }
1192               /* assembler options */
1193               else if (argv[i][2] == 'a')
1194                 {
1195                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1196                 }
1197               else
1198                 {
1199                   werror (W_UNKNOWN_OPTION, argv[i]);
1200                 }
1201               break;
1202
1203             case 'v':
1204               verifyShortOption(argv[i]);
1205
1206               printVersionInfo (stdout);
1207               exit (EXIT_SUCCESS);
1208               break;
1209
1210               /* preprocessor options */
1211             case 'M':
1212               {
1213                 preProcOnly = 1;
1214                 if (argv[i][2] == 'M')
1215                   addSet(&preArgvSet, Safe_strdup("-MM"));
1216                 else
1217                   addSet(&preArgvSet, Safe_strdup("-M"));
1218                 break;
1219               }
1220
1221             case 'd':
1222             case 'D':
1223             case 'I':
1224             case 'A':
1225             case 'U':
1226               {
1227                 char sOpt = argv[i][1];
1228                 char *rest;
1229
1230                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1231                   {
1232                     i++;
1233                     if (i >= argc)
1234                       {
1235                         /* No argument. */
1236                         werror(E_ARGUMENT_MISSING, argv[i-1]);
1237                         break;
1238                       }
1239                     else
1240                       {
1241                         rest = argv[i];
1242                       }
1243                   }
1244                 else
1245                   rest = &argv[i][2];
1246
1247                 if (sOpt == 'Y')
1248                   sOpt = 'I';
1249
1250                 SNPRINTF (buffer, sizeof(buffer),
1251                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1252                 addSet(&preArgvSet, Safe_strdup(buffer));
1253                 if(sOpt == 'I') {
1254                   addSet(&includeDirsSet, Safe_strdup(rest));
1255                   addSet(&userIncDirsSet, Safe_strdup(rest));
1256                 }
1257               }
1258               break;
1259
1260             default:
1261               werror (W_UNKNOWN_OPTION, argv[i]);
1262             }
1263           continue;
1264         }
1265
1266       /* no option must be a filename */
1267       if (options.c1mode)
1268         {
1269           werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1270         }
1271       else
1272         {
1273           processFile (argv[i]);
1274         }
1275     }
1276
1277   /* some sanity checks in c1 mode */
1278   if (options.c1mode)
1279     {
1280       const char *s;
1281
1282       if (fullSrcFileName)
1283         {
1284           fclose (srcFile);
1285           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1286         }
1287       fullSrcFileName = NULL;
1288       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1289         {
1290           werror (W_NO_FILE_ARG_IN_C1, s);
1291         }
1292       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1293         {
1294           werror (W_NO_FILE_ARG_IN_C1, s);
1295         }
1296       deleteSet(&relFilesSet);
1297       deleteSet(&libFilesSet);
1298
1299       if (options.cc_only || noAssemble || preProcOnly)
1300         {
1301           werror (W_ILLEGAL_OPT_COMBINATION);
1302         }
1303       options.cc_only = noAssemble = preProcOnly = 0;
1304       if (!dstFileName)
1305         {
1306           werror (E_NEED_OPT_O_IN_C1);
1307           exit (EXIT_FAILURE);
1308         }
1309     }
1310   /* if no dstFileName given with -o, we've to find one: */
1311   if (!dstFileName)
1312     {
1313       const char *s;
1314
1315       /* use the modulename from the C-source */
1316       if (fullSrcFileName)
1317         {
1318           struct dbuf_s path;
1319
1320           if (*dstPath != '\0')
1321             {
1322               dbuf_init(&path, 128);
1323               dbuf_makePath (&path, dstPath, moduleNameBase);
1324               dbuf_c_str (&path);
1325               dstFileName = dbuf_detach (&path);
1326             }
1327           else
1328             dstFileName = Safe_strdup(moduleNameBase);
1329         }
1330       /* use the modulename from the first object file */
1331       else if ((s = peekSet(relFilesSet)) != NULL)
1332         {
1333           struct dbuf_s file;
1334
1335           dbuf_init(&file, 128);
1336
1337           /* get rid of the "."-extension */
1338           dbuf_splitFile (s, &file, NULL);
1339
1340           dbuf_c_str (&file);
1341           s = dbuf_detach (&file);
1342
1343           dbuf_init (&file, 128);
1344
1345           dbuf_splitPath (s, NULL, &file);
1346
1347           if (*dstPath != '\0')
1348             {
1349               struct dbuf_s path;
1350
1351               dbuf_init(&path, 128);
1352               dbuf_makePath (&path, dstPath, dbuf_c_str (&file));
1353               dbuf_destroy (&file);
1354               dbuf_c_str (&path);
1355               dstFileName = dbuf_detach (&path);
1356             }
1357           else
1358             {
1359               dbuf_c_str (&file);
1360               dstFileName = dbuf_detach (&file);
1361             }
1362         }
1363       /* else no module given: help text is displayed */
1364     }
1365
1366   /* set int, long and float reentrancy based on stack-auto */
1367   if (options.stackAuto)
1368     {
1369       options.intlong_rent++;
1370       options.float_rent++;
1371     }
1372
1373   /* mcs51 has an assembly coded float library that's always reentrant */
1374   if (TARGET_IS_MCS51)
1375     {
1376       options.float_rent++;
1377
1378       /* set up external stack location if not explicitly specified */
1379       if (!options.xstack_loc)
1380         options.xstack_loc = options.xdata_loc;
1381     }
1382
1383   /* if debug option is set then open the cdbFile */
1384   if (options.debug && fullSrcFileName)
1385     {
1386       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1387                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1388       if(debugFile->openFile(scratchFileName))
1389         debugFile->writeModule(moduleName);
1390       else
1391         werror (E_FILE_OPEN_ERR, scratchFileName);
1392     }
1393   MSVC_style(options.vc_err_style);
1394
1395   return 0;
1396 }
1397
1398 /*-----------------------------------------------------------------*/
1399 /* finalizeOptions - finalize (post-process( options               */
1400 /*-----------------------------------------------------------------*/
1401 static void
1402 finalizeOptions (void)
1403 {
1404   /* no peephole comments if not verbose asm */
1405   if (!options.verboseAsm)
1406     options.noPeepComments = 1;
1407 }
1408
1409 /*-----------------------------------------------------------------*/
1410 /* linkEdit : - calls the linkage editor  with options             */
1411 /*-----------------------------------------------------------------*/
1412 static void
1413 linkEdit (char **envp)
1414 {
1415   FILE *lnkfile;
1416   char *segName, *c;
1417   int system_ret;
1418   const char *s;
1419   char linkerScriptFileName[PATH_MAX];
1420
1421   linkerScriptFileName[0] = 0;
1422   c = NULL;
1423
1424   if (port->linker.needLinkerScript)
1425     {
1426       char out_fmt;
1427
1428       switch (options.out_fmt)
1429         {
1430         case 0:
1431           out_fmt = 'i';        /* Intel hex */
1432           break;
1433         case 1:
1434           out_fmt = 's';        /* Motorola S19 */
1435           break;
1436         case 2:
1437           out_fmt = 't';        /* Elf */
1438           break;
1439         default:
1440           out_fmt = 'i';
1441         }
1442
1443       /* first we need to create the <filename>.lnk file */
1444       SNPRINTF (linkerScriptFileName, sizeof(linkerScriptFileName),
1445         "%s.lnk", dstFileName);
1446       if (!(lnkfile = fopen (linkerScriptFileName, "w")))
1447         {
1448           werror (E_FILE_OPEN_ERR, linkerScriptFileName);
1449           exit (EXIT_FAILURE);
1450         }
1451
1452       if (TARGET_Z80_LIKE)
1453         {
1454           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1455             out_fmt, dstFileName);
1456         }
1457       else /*For all the other ports.  Including pics???*/
1458         {
1459           fprintf (lnkfile, "-myux%c\n", out_fmt);
1460           if(!options.no_pack_iram)
1461               fprintf (lnkfile, "-Y\n");
1462         }
1463
1464       if (!(TARGET_Z80_LIKE)) /*Not for the z80, gbz80*/
1465         {
1466           /* if iram size specified */
1467           if (options.iram_size)
1468             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1469
1470           /* if stack size specified*/
1471           if(options.stack_size)
1472               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1473
1474           /* if xram size specified */
1475           if (options.xram_size_set)
1476             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1477
1478           /* if code size specified */
1479           if (options.code_size)
1480             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1481
1482           if (options.debug)
1483             fprintf (lnkfile, "-z\n");
1484         }
1485
1486 #define WRITE_SEG_LOC(N, L) \
1487   if (N) \
1488   { \
1489     segName = Safe_strdup(N); \
1490     c = strtok(segName, " \t"); \
1491     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1492     if (segName) { Safe_free(segName); } \
1493   }
1494
1495       if (!(TARGET_Z80_LIKE)) /*Not for the z80, gbz80*/
1496         {
1497
1498           /* code segment start */
1499           WRITE_SEG_LOC (HOME_NAME, options.code_loc);
1500
1501           /* data segment start. If zero, the linker chooses
1502              the best place for data */
1503           if (options.data_loc)
1504             {
1505               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1506             }
1507
1508           /* xdata segment start. If zero, the linker chooses
1509              the best place for xdata */
1510           if (options.xdata_loc)
1511             {
1512               WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1513             }
1514
1515           /* pdata/xstack segment start. If zero, the linker
1516              chooses the best place for them */
1517           if (options.xstack_loc)
1518             {
1519               WRITE_SEG_LOC (PDATA_NAME, options.xstack_loc);
1520             }
1521
1522           /* indirect data */
1523           if (IDATA_NAME)
1524             {
1525               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1526             }
1527
1528           /* bit segment start */
1529           WRITE_SEG_LOC (BIT_NAME, 0);
1530
1531           /* stack start */
1532           if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1533                !TARGET_IS_HC08)
1534             {
1535               WRITE_SEG_LOC ("SSEG", options.stack_loc);
1536             }
1537         }
1538       else /*For the z80, gbz80*/
1539         {
1540           WRITE_SEG_LOC ("_CODE", options.code_loc);
1541           WRITE_SEG_LOC ("_DATA", options.data_loc);
1542         }
1543
1544       /* If the port has any special linker area declarations, get 'em */
1545       if (port->extraAreas.genExtraAreaLinkOptions)
1546         {
1547           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1548         }
1549
1550       /* add the extra linker options */
1551       fputStrSet(lnkfile, linkOptionsSet);
1552
1553       /* command line defined library paths if specified */
1554       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1555         fprintf (lnkfile, "-k %s\n", s);
1556
1557       /* standard library path */
1558       if (!options.nostdlib)
1559         {
1560           if (!(TARGET_Z80_LIKE || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1561             {
1562               switch (options.model)
1563                 {
1564                 case MODEL_SMALL:
1565                   if (options.stackAuto)
1566                     c = "small-stack-auto";
1567                   else
1568                     c = "small";
1569                   break;
1570                 case MODEL_MEDIUM:
1571                   if (options.stackAuto)
1572                     c = "medium-stack-auto";
1573                   else
1574                     c = "medium";
1575                   break;
1576                 case MODEL_LARGE:
1577                   if (options.stackAuto)
1578                     c = "large-stack-auto";
1579                   else
1580                     c = "large";
1581                   break;
1582                 case MODEL_FLAT24:
1583                   /* c = "flat24"; */
1584                   if (TARGET_IS_DS390)
1585                     {
1586                       c = "ds390";
1587                     }
1588                   else if (TARGET_IS_DS400)
1589                     {
1590                       c = "ds400";
1591                     }
1592                   else
1593                     {
1594                       fprintf(stderr,
1595                         "Add support for your FLAT24 target in %s @ line %d\n",
1596                         __FILE__, __LINE__);
1597                       exit (EXIT_FAILURE);
1598                     }
1599                   break;
1600                 case MODEL_PAGE0:
1601                   c = "xa51";
1602                   break;
1603                 default:
1604                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1605                   c = "unknown";
1606                   break;
1607                 }
1608             }
1609           else /*for the z80, gbz80*/
1610             {
1611               if (TARGET_IS_HC08)
1612                 c = "hc08";
1613               else if (TARGET_IS_Z80)
1614                 c = "z80";
1615               else
1616                 c = "gbz80";
1617             }
1618           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1619             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1620         }
1621
1622       /* command line defined library files if specified */
1623       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1624         fprintf (lnkfile, "-l %s\n", s);
1625
1626       /* standard library files */
1627       if (!options.nostdlib)
1628         {
1629 #if !OPT_DISABLE_DS390
1630           if (options.model == MODEL_FLAT24)
1631             {
1632               if (TARGET_IS_DS390)
1633                 {
1634                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1635                 }
1636               else if (TARGET_IS_DS400)
1637                 {
1638                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1639                 }
1640               else
1641                 {
1642                   fprintf(stderr,
1643                     "Add support for your FLAT24 target in %s @ line %d\n",
1644                     __FILE__, __LINE__);
1645                   exit (EXIT_FAILURE);
1646                 }
1647               }
1648 #endif
1649
1650 #if !OPT_DISABLE_XA51
1651 #ifdef STD_XA51_LIB
1652           if (options.model == MODEL_PAGE0)
1653             {
1654               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1655             }
1656 #endif
1657 #endif
1658           if (TARGET_IS_MCS51)
1659             {
1660               fprintf (lnkfile, "-l mcs51\n");
1661             }
1662           if (!(TARGET_Z80_LIKE || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1663             { /*Why the z80 port is not using the standard libraries?*/
1664               fprintf (lnkfile, "-l %s\n", STD_LIB);
1665               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1666               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1667               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1668             }
1669           else if (TARGET_IS_HC08)
1670             {
1671               fprintf (lnkfile, "-l hc08\n");
1672             }
1673           else if (TARGET_IS_Z80)
1674             {
1675               fprintf (lnkfile, "-l z80\n");
1676             }
1677           else if (TARGET_IS_GBZ80)
1678             {
1679               fprintf (lnkfile, "-l gbz80\n");
1680             }
1681         }
1682
1683       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1684       It is very important for this file to be first on the linking proccess
1685       so the areas are set in the correct order, expecially _GSINIT*/
1686       if ((TARGET_Z80_LIKE) && !options.no_std_crt0) /*For the z80, gbz80*/
1687         {
1688           char crt0path[PATH_MAX];
1689           FILE * crt0fp;
1690           set *tempSet=NULL;
1691
1692           tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1693           tempSet = appendStrSet(tempSet, NULL, c);
1694           mergeSets(&tempSet, libPathsSet);
1695
1696           for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1697             {
1698               sprintf (crt0path, "%s%scrt0.o",
1699                 s, DIR_SEPARATOR_STRING);
1700
1701               crt0fp=fopen(crt0path, "r");
1702               if(crt0fp!=NULL)/*Found it!*/
1703                 {
1704                   fclose(crt0fp);
1705                   #ifdef __CYGWIN__
1706                   {
1707                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1708                     windows paths, so convert them to the CYGWIN format*/
1709                     char posix_path[PATH_MAX];
1710                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1711                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1712                     strcpy(crt0path, posix_path);
1713                   }
1714                   #endif
1715                   fprintf (lnkfile, "%s\n", crt0path);
1716                   break;
1717                 }
1718             }
1719           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1720         }
1721
1722       /* put in the object files */
1723       if (fullSrcFileName)
1724         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1725
1726       fputStrSet(lnkfile, relFilesSet);
1727
1728       fprintf (lnkfile, "\n-e\n");
1729       fclose (lnkfile);
1730     } /* if(port->linker.needLinkerScript) */
1731
1732   if (options.verbose)
1733     printf ("sdcc: Calling linker...\n");
1734
1735   /* build linker output filename */
1736
1737   /* -o option overrides default name? */
1738   if (fullDstFileName)
1739     {
1740       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1741     }
1742   else
1743     {
1744       /* the linked file gets the name of the first modul */
1745       if (fullSrcFileName)
1746         {
1747           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1748         }
1749       else
1750         {
1751           s = peekSet(relFilesSet);
1752
1753           assert(s);
1754
1755           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1756           /* strip ".rel" extension */
1757           *strrchr (scratchFileName, '.') = '\0';
1758         }
1759       strncatz (scratchFileName,
1760         options.out_fmt ? ".S19" : ".ihx",
1761         sizeof(scratchFileName));
1762     }
1763
1764   if (port->linker.cmd)
1765     {
1766       char buffer2[PATH_MAX];
1767       char buffer3[PATH_MAX];
1768       set *tempSet=NULL, *libSet=NULL;
1769
1770       strcpy(buffer3, linkerScriptFileName);
1771       if(/*TARGET_IS_PIC16 ||*/ TARGET_IS_PIC) {
1772
1773          /* use $l to set the linker include directories */
1774          tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1775          mergeSets(&linkOptionsSet, tempSet);
1776
1777          tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1778          mergeSets(&linkOptionsSet, tempSet);
1779
1780          /* use $3 for libraries from command line --> libSet */
1781          mergeSets(&libSet, libFilesSet);
1782
1783          tempSet = appendStrSet(relFilesSet, "", "");
1784          mergeSets(&libSet, tempSet);
1785 //         libSet = reverseSet(libSet);
1786
1787         if(fullSrcFileName) {
1788 //              strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1789                 /* if it didn't work, revert to old behaviour */
1790                 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1791                 strcat(buffer3, port->linker.rel_ext);
1792
1793         } else strcpy(buffer3, "");
1794       }
1795
1796       buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1797
1798       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1799     }
1800   else
1801     {
1802       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1803     }
1804
1805   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1806
1807   system_ret = my_system (buffer);
1808
1809   /* TODO: most linker don't have a -o parameter */
1810   /* -o option overrides default name? */
1811   if (fullDstFileName)
1812     {
1813       char *p, *q;
1814       /* the linked file gets the name of the first modul */
1815       if (fullSrcFileName)
1816         {
1817           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1818           p = strlen (scratchFileName) + scratchFileName;
1819         }
1820       else
1821         {
1822           s = peekSet(relFilesSet);
1823
1824           assert(s);
1825
1826           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1827           /* strip ".rel" extension */
1828           p = strrchr (scratchFileName, '.');
1829           if (p)
1830             {
1831               *p = 0;
1832             }
1833         }
1834       strncatz (scratchFileName,
1835         options.out_fmt ? ".S19" : ".ihx",
1836         sizeof(scratchFileName));
1837       if (FILENAME_CMP (fullDstFileName, scratchFileName))
1838         remove (fullDstFileName);
1839       rename (scratchFileName, fullDstFileName);
1840
1841       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1842       q = strrchr (buffer, '.');
1843       if (!q)
1844         {
1845           /* no extension: append new extensions */
1846           q = strlen (buffer) + buffer;
1847         }
1848
1849       *p = 0;
1850       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1851       *q = 0;
1852       strncatz(buffer, ".map", sizeof(buffer));
1853       if (FILENAME_CMP (scratchFileName, buffer))
1854         remove (buffer);
1855       rename (scratchFileName, buffer);
1856       *p = 0;
1857       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1858       *q = 0;
1859       strncatz(buffer, ".mem", sizeof(buffer));
1860       if (FILENAME_CMP (scratchFileName, buffer))
1861         remove (buffer);
1862       rename (scratchFileName, buffer);
1863       if (options.debug)
1864         {
1865           *p = 0;
1866           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1867           *q = 0;
1868           strncatz(buffer, ".cdb", sizeof(buffer));
1869           if (FILENAME_CMP (scratchFileName, buffer))
1870             remove (buffer);
1871           rename (scratchFileName, buffer);
1872           /* and the OMF file without extension: */
1873           *p = 0;
1874           *q = 0;
1875           if (FILENAME_CMP (scratchFileName, buffer))
1876             remove (buffer);
1877           rename (scratchFileName, buffer);
1878         }
1879     }
1880   if (system_ret)
1881     {
1882       exit (EXIT_FAILURE);
1883     }
1884 }
1885
1886 /*-----------------------------------------------------------------*/
1887 /* assemble - spawns the assembler with arguments                  */
1888 /*-----------------------------------------------------------------*/
1889 static void
1890 assemble (char **envp)
1891 {
1892     /* build assembler output filename */
1893
1894     /* -o option overrides default name? */
1895     if (options.cc_only && fullDstFileName) {
1896         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1897     } else {
1898         /* the assembled file gets the name of the first modul */
1899         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1900         strncatz (scratchFileName, port->linker.rel_ext,
1901                   sizeof(scratchFileName));
1902     }
1903
1904     if (port->assembler.do_assemble) {
1905         port->assembler.do_assemble(asmOptionsSet);
1906         return ;
1907     } else if (port->assembler.cmd) {
1908         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1909                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1910                       asmOptionsSet);
1911     } else {
1912         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1913     }
1914
1915     if (my_system (buffer)) {
1916         /* either system() or the assembler itself has reported an error
1917            perror ("Cannot exec assembler");
1918         */
1919         exit (EXIT_FAILURE);
1920     }
1921     /* TODO: most assembler don't have a -o parameter */
1922     /* -o option overrides default name? */
1923     if (options.cc_only && fullDstFileName) {
1924         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1925         strncatz (scratchFileName,
1926                   port->linker.rel_ext,
1927                   sizeof(scratchFileName));
1928         if (strcmp (scratchFileName, fullDstFileName))
1929           remove (fullDstFileName);
1930         rename (scratchFileName, fullDstFileName);
1931     }
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* preProcess - spawns the preprocessor with arguments       */
1936 /*-----------------------------------------------------------------*/
1937 static int
1938 preProcess (char **envp)
1939 {
1940   if (options.c1mode)
1941     {
1942       yyin = stdin;
1943     }
1944   else
1945     {
1946       const char *s;
1947       set *inclList = NULL;
1948
1949       if (NULL != port->linker.rel_ext)
1950         {
1951 #define OBJ_EXT_STR     "-obj-ext="
1952 #define OBJ_EXT_LEN     ((sizeof OBJ_EXT_STR) - 1)
1953           char *buf = Safe_alloc(strlen(port->linker.rel_ext) + (OBJ_EXT_LEN + 1));
1954           strcpy(buf, OBJ_EXT_STR);
1955           strcpy(&buf[OBJ_EXT_LEN], port->linker.rel_ext);
1956           addSet(&preArgvSet, buf);
1957         }
1958
1959       /* if using dollar signs in identifiers */
1960       if (options.dollars_in_ident)
1961         addSet(&preArgvSet, Safe_strdup("-fdollars-in-identifiers"));
1962
1963       /* if using external stack define the macro */
1964       if (options.useXstack)
1965         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1966
1967       /* set the macro for stack autos  */
1968       if (options.stackAuto)
1969         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1970
1971       /* set the macro for stack autos  */
1972       if (options.stack10bit)
1973         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1974
1975       /* set the macro for no overlay  */
1976       if (options.noOverlay)
1977         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1978
1979       /* set the macro for large model  */
1980       switch (options.model)
1981         {
1982         case MODEL_LARGE:
1983           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1984           break;
1985         case MODEL_SMALL:
1986           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1987           break;
1988         case MODEL_COMPACT:
1989           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1990           break;
1991         case MODEL_MEDIUM:
1992           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1993           break;
1994         case MODEL_FLAT24:
1995           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1996           break;
1997         case MODEL_PAGE0:
1998           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1999           break;
2000         default:
2001           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
2002           break;
2003         }
2004
2005       /* add SDCC version number */
2006       {
2007         char buf[20];
2008         SNPRINTF(buf, sizeof(buf), "-DSDCC=%d%d%d",
2009                  SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2010         addSet(&preArgvSet, Safe_strdup(buf));
2011       }
2012
2013       /* add port (processor information to processor */
2014       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
2015       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
2016
2017       if (port && port->processor && TARGET_IS_PIC) {
2018         char proc[512];
2019         SNPRINTF(&proc[0], 512, "-DSDCC_PROCESSOR=\"%s\"", port->processor);
2020         addSet(&preArgvSet, Safe_strdup(proc));
2021       }
2022
2023       /* standard include path */
2024       if (!options.nostdinc) {
2025         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
2026         mergeSets(&preArgvSet, inclList);
2027       }
2028
2029       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
2030       Safe_free((void *)s);
2031       if (inclList != NULL)
2032         deleteSet(&inclList);
2033
2034       if (preProcOnly && fullDstFileName)
2035         {
2036           /* -E and -o given */
2037           setMainValue ("cppoutfilename", fullDstFileName);
2038         }
2039       else
2040         {
2041           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2042           setMainValue ("cppoutfilename", NULL);
2043         }
2044
2045       if (options.verbose)
2046         printf ("sdcc: Calling preprocessor...\n");
2047       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2048
2049       if (preProcOnly) {
2050         if (my_system (buffer)) {
2051           exit (EXIT_FAILURE);
2052         }
2053
2054         exit (EXIT_SUCCESS);
2055       }
2056
2057       yyin = my_popen (buffer);
2058       if (yyin == NULL) {
2059           perror ("Preproc file not found");
2060           exit (EXIT_FAILURE);
2061       }
2062     }
2063
2064   return 0;
2065 }
2066
2067 /* Set bin paths */
2068 static void
2069 setBinPaths(const char *argv0)
2070 {
2071   const char *p;
2072   char buf[PATH_MAX];
2073
2074   /*
2075    * Search logic:
2076    *
2077    * 1. - $SDCCDIR/PREFIX2BIN_DIR
2078    * 2. - path(argv[0])
2079    * 3. - $PATH
2080    */
2081
2082   /* do it in reverse mode, so that addSetHead() can be used
2083      instead of slower addSet() */
2084
2085   if ((p = getBinPath(argv0)) != NULL)
2086     addSetHead(&binPathSet, (void *)p);
2087
2088   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2089     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2090     addSetHead(&binPathSet, Safe_strdup(buf));
2091   }
2092 }
2093
2094 /* Set system include path */
2095 static void
2096 setIncludePath(void)
2097 {
2098   char *p;
2099   char *p2=NULL;
2100   set *tempSet=NULL;
2101
2102   /*
2103    * Search logic:
2104    *
2105    * 1. - $SDCC_INCLUDE/target
2106    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2107    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2108    * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2109    * 5. - $SDCC_INCLUDE
2110    * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2111    * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2112    * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2113    */
2114
2115   if (options.nostdinc)
2116       return;
2117
2118   tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2119   includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2120   includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2121   mergeSets(&includeDirsSet, tempSet);
2122
2123   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2124   {
2125     addSetHead(&includeDirsSet, p);
2126     p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2127     if(p2!=NULL)
2128     {
2129         strcpy(p2, p);
2130         strcat(p2, DIR_SEPARATOR_STRING);
2131         strcat(p2, port->target);
2132         addSetHead(&includeDirsSet, p2);
2133     }
2134   }
2135 }
2136
2137 /* Set system lib path */
2138 static void
2139 setLibPath(void)
2140 {
2141   char *p;
2142
2143   /*
2144    * Search logic:
2145    *
2146    * 1. - $SDCC_LIB
2147    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2148    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2149    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2150    */
2151
2152   if (options.nostdlib)
2153       return;
2154
2155   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2156
2157   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2158     addSetHead(&libDirsSet, p);
2159 }
2160
2161 /* Set data path */
2162 static void
2163 setDataPaths(const char *argv0)
2164 {
2165   const char *p;
2166   char buf[PATH_MAX];
2167
2168   /*
2169    * Search logic:
2170    *
2171    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2172    * 2. - path(argv[0])/BIN2DATA_DIR
2173    * 3. - DATADIR (only on *nix)
2174    */
2175
2176   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2177     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2178     addSet(&dataDirsSet, Safe_strdup(buf));
2179   }
2180
2181   if ((p = getBinPath(argv0)) != NULL) {
2182     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2183     free((void *)p);
2184     addSet(&dataDirsSet, Safe_strdup(buf));
2185   }
2186
2187 #ifdef _WIN32
2188   if (peekSet(dataDirsSet) == NULL) {
2189     /* this should never happen... */
2190     wassertl(0, "Can't get binary path");
2191   }
2192 #else
2193   addSet(&dataDirsSet, Safe_strdup(DATADIR));
2194 #endif
2195
2196   setIncludePath();
2197   setLibPath();
2198 }
2199
2200 static void
2201 initValues (void)
2202 {
2203   populateMainValues (_baseValues);
2204   setMainValue ("port", port->target);
2205   setMainValue ("objext", port->linker.rel_ext);
2206   setMainValue ("asmext", port->assembler.file_ext);
2207
2208   setMainValue ("dstfilename", dstFileName);
2209   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2210
2211   if (options.cc_only && fullDstFileName)
2212     /* compile + assemble and -o given: -o specifies name of object file */
2213     {
2214       setMainValue ("objdstfilename", fullDstFileName);
2215     }
2216   else
2217     {
2218       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2219     }
2220   if (fullDstFileName)
2221     /* if we're linking, -o gives the final file name */
2222     {
2223       setMainValue ("linkdstfilename", fullDstFileName);
2224     }
2225   else
2226     {
2227       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2228     }
2229
2230 }
2231
2232 static void doPrintSearchDirs(void)
2233 {
2234     printf("programs:\n");
2235     fputStrSet(stdout, binPathSet);
2236
2237     printf("datadir:\n");
2238     fputStrSet(stdout, dataDirsSet);
2239
2240     printf("includedir:\n");
2241     fputStrSet(stdout, includeDirsSet);
2242
2243     printf("libdir:\n");
2244     fputStrSet(stdout, libDirsSet);
2245     fputStrSet(stdout, libPathsSet);
2246 }
2247
2248
2249 static void
2250 sig_handler (int signal)
2251 {
2252   char *sig_string;
2253
2254   switch (signal)
2255     {
2256     case SIGABRT:
2257       sig_string = "SIGABRT";
2258       break;
2259     case SIGTERM:
2260       sig_string = "SIGTERM";
2261       break;
2262     case SIGINT:
2263       sig_string = "SIGINT";
2264       break;
2265     case SIGSEGV:
2266       sig_string = "SIGSEGV";
2267       break;
2268     default:
2269       sig_string = "Unknown?";
2270       break;
2271     }
2272   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2273   exit (EXIT_FAILURE);
2274 }
2275
2276 /*
2277  * main routine
2278  * initialises and calls the parser
2279  */
2280
2281 int
2282 main (int argc, char **argv, char **envp)
2283 {
2284   /* turn all optimizations off by default */
2285   memset (&optimize, 0, sizeof (struct optimize));
2286
2287   if (NUM_PORTS==0)
2288     {
2289       fprintf (stderr, "Build error: no ports are enabled.\n");
2290       exit (EXIT_FAILURE);
2291     }
2292
2293   /* install signal handler;
2294      it's only purpose is to call exit() to remove temp files */
2295   if (!getenv("SDCC_LEAVE_SIGNALS"))
2296     {
2297       signal (SIGABRT, sig_handler);
2298       signal (SIGTERM, sig_handler);
2299       signal (SIGINT , sig_handler);
2300       signal (SIGSEGV, sig_handler);
2301     }
2302
2303   /* Before parsing the command line options, do a
2304    * search for the port and processor and initialize
2305    * them if they're found. (We can't gurantee that these
2306    * will be the first options specified).
2307    */
2308
2309   _findPort (argc, argv);
2310
2311 #ifdef JAMIN_DS390
2312   if (strcmp(port->target, "mcs51") == 0) {
2313     printf("DS390 jammed in A\n");
2314     _setPort ("ds390");
2315     ds390_jammed = 1;
2316   }
2317 #endif
2318
2319   _findProcessor (argc, argv);
2320
2321   /* Initalise the port. */
2322   if (port->init)
2323     port->init ();
2324
2325   setDefaultOptions ();
2326 #ifdef JAMIN_DS390
2327   if (ds390_jammed) {
2328     options.model = MODEL_SMALL;
2329     options.stack10bit=0;
2330   }
2331 #endif
2332
2333   parseCmdLine (argc, argv);
2334
2335   if (options.verbose && NULL != port->processor)
2336     printf("Processor: %s\n", port->processor);
2337
2338   initValues ();
2339
2340   setBinPaths(argv[0]);
2341   setDataPaths(argv[0]);
2342
2343   if (port->initPaths)
2344     port->initPaths();
2345
2346   if (options.printSearchDirs)
2347     doPrintSearchDirs();
2348
2349   /* if no input then printUsage & exit */
2350   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL)
2351     {
2352       if (options.printSearchDirs)
2353         exit (EXIT_SUCCESS);
2354       printUsage();
2355       exit (EXIT_FAILURE);
2356     }
2357
2358   /* initMem() is expensive, but
2359      initMem() must called before port->finaliseOptions ().
2360      And the z80 port needs port->finaliseOptions(),
2361      even if we're only linking. */
2362   initMem ();
2363
2364   /* finalize target specific options */
2365   port->finaliseOptions ();
2366
2367   /* finalize common options */
2368   finalizeOptions ();
2369
2370   if (fullSrcFileName || options.c1mode)
2371     {
2372       preProcess (envp);
2373
2374       initSymt ();
2375       initiCode ();
2376       initCSupport ();
2377       initBuiltIns();
2378       initPeepHole ();
2379
2380       if (options.verbose)
2381         printf ("sdcc: Generating code...\n");
2382
2383       yyparse ();
2384
2385       if (pclose(yyin))
2386         fatalError = 1;
2387
2388       if (fatalError) {
2389         exit (EXIT_FAILURE);
2390       }
2391
2392       if (port->general.do_glue != NULL)
2393         (*port->general.do_glue) ();
2394       else
2395         {
2396           /* this shouldn't happen */
2397           assert (FALSE);
2398           /* in case of NDEBUG */
2399           glue ();
2400         }
2401
2402       if (fatalError) {
2403         exit (EXIT_FAILURE);
2404       }
2405
2406       if (!options.c1mode && !noAssemble)
2407         {
2408           if (options.verbose)
2409             printf ("sdcc: Calling assembler...\n");
2410           assemble (envp);
2411         }
2412     }
2413   closeDumpFiles();
2414
2415   if (options.debug && debugFile)
2416     debugFile->closeFile();
2417
2418   if (!options.cc_only &&
2419       !fatalError &&
2420       !noAssemble &&
2421       !options.c1mode &&
2422       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2423     {
2424       if (options.verbose)
2425         printf ("sdcc: Calling linker...\n");
2426
2427       if (port->linker.do_link)
2428         port->linker.do_link ();
2429       else
2430         linkEdit (envp);
2431     }
2432
2433   return 0;
2434 }