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