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