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