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