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