* src/SDCCmain.c (linkEdit): fixed bug 1195202
[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   char linkerScriptFileName[PATH_MAX];
1429
1430
1431   if(port->linker.needLinkerScript)
1432     {
1433       char out_fmt;
1434
1435       switch (options.out_fmt)
1436         {
1437         case 0:
1438           out_fmt = 'i';        /* Intel hex */
1439           break;
1440         case 1:
1441           out_fmt = 's';        /* Motorola S19 */
1442           break;
1443         case 2:
1444           out_fmt = 't';        /* Elf */
1445           break;
1446         default:
1447           out_fmt = 'i';
1448         }
1449
1450       /* first we need to create the <filename>.lnk file */
1451       SNPRINTF (linkerScriptFileName, sizeof(scratchFileName),
1452         "%s.lnk", dstFileName);
1453       if (!(lnkfile = fopen (linkerScriptFileName, "w")))
1454         {
1455           werror (E_FILE_OPEN_ERR, linkerScriptFileName);
1456           exit (1);
1457         }
1458
1459       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1460         {
1461           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1462             out_fmt, dstFileName);
1463         }
1464       else /*For all the other ports.  Including pics???*/
1465         {
1466           fprintf (lnkfile, "-myux%c\n", out_fmt);
1467           if(!options.no_pack_iram)
1468               fprintf (lnkfile, "-Y\n");
1469         }
1470
1471       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1472         {
1473           /* if iram size specified */
1474           if (options.iram_size)
1475             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1476
1477           /* if stack size specified*/
1478           if(options.stack_size)
1479               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1480
1481           /* if xram size specified */
1482           if (options.xram_size_set)
1483             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1484
1485           /* if code size specified */
1486           if (options.code_size)
1487             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1488
1489           if (options.debug)
1490             fprintf (lnkfile, "-z\n");
1491         }
1492
1493 #define WRITE_SEG_LOC(N, L) \
1494   segName = Safe_strdup(N); \
1495   c = strtok(segName, " \t"); \
1496   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1497   if (segName) { Safe_free(segName); }
1498
1499       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1500         {
1501
1502           /* code segment start */
1503           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1504
1505           /* data segment start. If zero, the linker chooses
1506              the best place for data */
1507           if(options.data_loc)
1508             {
1509               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1510             }
1511
1512           /* xdata segment start. If zero, the linker chooses
1513              the best place for xdata */
1514           if(options.xdata_loc)
1515             {
1516               WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1517             }
1518
1519           /* indirect data */
1520           if (IDATA_NAME)
1521             {
1522               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1523             }
1524
1525           /* bit segment start */
1526           WRITE_SEG_LOC (BIT_NAME, 0);
1527
1528           /* stack start */
1529           if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1530                !TARGET_IS_HC08)
1531             {
1532               WRITE_SEG_LOC ("SSEG", options.stack_loc);
1533             }
1534         }
1535       else /*For the z80, gbz80*/
1536         {
1537           WRITE_SEG_LOC ("_CODE", options.code_loc);
1538           WRITE_SEG_LOC ("_DATA", options.data_loc);
1539         }
1540
1541       /* If the port has any special linker area declarations, get 'em */
1542       if (port->extraAreas.genExtraAreaLinkOptions)
1543         {
1544           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1545         }
1546
1547       /* add the extra linker options */
1548       fputStrSet(lnkfile, linkOptionsSet);
1549
1550       /* command line defined library paths if specified */
1551       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1552         fprintf (lnkfile, "-k %s\n", s);
1553
1554       /* standard library path */
1555       if (!options.nostdlib)
1556         {
1557           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1558             {
1559               switch (options.model)
1560                 {
1561                 case MODEL_SMALL:
1562                   c = "small";
1563                   break;
1564                 case MODEL_LARGE:
1565                   c = "large";
1566                   break;
1567                 case MODEL_FLAT24:
1568                   /* c = "flat24"; */
1569                   if (TARGET_IS_DS390)
1570                     {
1571                       c = "ds390";
1572                     }
1573                   else if (TARGET_IS_DS400)
1574                     {
1575                       c = "ds400";
1576                     }
1577                   else
1578                     {
1579                       fprintf(stderr,
1580                         "Add support for your FLAT24 target in %s @ line %d\n",
1581                         __FILE__, __LINE__);
1582                       exit(-1);
1583                     }
1584                   break;
1585                 case MODEL_PAGE0:
1586                   c = "xa51";
1587                   break;
1588                 default:
1589                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1590                   c = "unknown";
1591                   break;
1592                 }
1593             }
1594           else /*for the z80, gbz80*/
1595             {
1596               if (TARGET_IS_HC08)
1597                 c = "hc08";
1598               else if (TARGET_IS_Z80)
1599                 c = "z80";
1600               else
1601                 c = "gbz80";
1602             }
1603           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1604             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1605         }
1606
1607       /* command line defined library files if specified */
1608       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1609         fprintf (lnkfile, "-l %s\n", s);
1610
1611       /* standard library files */
1612       if (!options.nostdlib)
1613         {
1614 #if !OPT_DISABLE_DS390
1615           if (options.model == MODEL_FLAT24)
1616             {
1617               if (TARGET_IS_DS390)
1618                 {
1619                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1620                 }
1621               else if (TARGET_IS_DS400)
1622                 {
1623                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1624                 }
1625               else
1626                 {
1627                   fprintf(stderr,
1628                     "Add support for your FLAT24 target in %s @ line %d\n",
1629                     __FILE__, __LINE__);
1630                   exit(-1);
1631                 }
1632               }
1633 #endif
1634
1635 #if !OPT_DISABLE_XA51
1636 #ifdef STD_XA51_LIB
1637           if (options.model == MODEL_PAGE0)
1638             {
1639               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1640             }
1641 #endif
1642 #endif
1643           if (TARGET_IS_MCS51)
1644             {
1645               fprintf (lnkfile, "-l mcs51\n");
1646             }
1647           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1648             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1649             { /*Why the z80 port is not using the standard libraries?*/
1650               fprintf (lnkfile, "-l %s\n", STD_LIB);
1651               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1652               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1653               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1654             }
1655           else if (TARGET_IS_HC08)
1656             {
1657               fprintf (lnkfile, "-l hc08\n");
1658             }
1659           else if (TARGET_IS_Z80)
1660             {
1661               fprintf (lnkfile, "-l z80\n");
1662             }
1663           else if (TARGET_IS_GBZ80)
1664             {
1665               fprintf (lnkfile, "-l gbz80\n");
1666             }
1667         }
1668
1669       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1670       It is very important for this file to be first on the linking proccess
1671       so the areas are set in the correct order, expecially _GSINIT*/
1672       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1673         !options.no_std_crt0) /*For the z80, gbz80*/
1674         {
1675           char crt0path[PATH_MAX];
1676           FILE * crt0fp;
1677           set *tempSet=NULL;
1678
1679           tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1680           tempSet = appendStrSet(tempSet, NULL, c);
1681           mergeSets(&tempSet, libPathsSet);
1682
1683           for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1684             {
1685               sprintf (crt0path, "%s%scrt0.o",
1686                 s, DIR_SEPARATOR_STRING);
1687
1688               crt0fp=fopen(crt0path, "r");
1689               if(crt0fp!=NULL)/*Found it!*/
1690                 {
1691                   fclose(crt0fp);
1692                   #ifdef __CYGWIN__
1693                   {
1694                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1695                     windows paths, so convert them to the CYGWIN format*/
1696                     char posix_path[PATH_MAX];
1697                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1698                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1699                     strcpy(crt0path, posix_path);
1700                   }
1701                   #endif
1702                   fprintf (lnkfile, "%s\n", crt0path);
1703                   break;
1704                 }
1705             }
1706           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1707         }
1708
1709       /* put in the object files */
1710       if (fullSrcFileName)
1711         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1712
1713       fputStrSet(lnkfile, relFilesSet);
1714
1715       fprintf (lnkfile, "\n-e\n");
1716       fclose (lnkfile);
1717     } /* if(port->linker.needLinkerScript) */
1718
1719   if (options.verbose)
1720     printf ("sdcc: Calling linker...\n");
1721
1722   /* build linker output filename */
1723
1724   /* -o option overrides default name? */
1725   if (fullDstFileName)
1726     {
1727       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1728     }
1729   else
1730     {
1731       /* the linked file gets the name of the first modul */
1732       if (fullSrcFileName)
1733         {
1734           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1735         }
1736       else
1737         {
1738           s = peekSet(relFilesSet);
1739
1740           assert(s);
1741
1742           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1743           /* strip ".rel" extension */
1744           *strrchr (scratchFileName, '.') = '\0';
1745         }
1746       strncatz (scratchFileName,
1747         options.out_fmt ? ".S19" : ".ihx",
1748         sizeof(scratchFileName));
1749     }
1750
1751   if (port->linker.cmd)
1752     {
1753       char buffer2[PATH_MAX];
1754       char buffer3[PATH_MAX];
1755       set *tempSet=NULL, *libSet=NULL;
1756
1757       strcpy(buffer3, linkerScriptFileName);
1758       if(TARGET_IS_PIC16) {
1759
1760          /* use $l to set the linker include directories */
1761          tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1762          mergeSets(&linkOptionsSet, tempSet);
1763
1764          tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1765          mergeSets(&linkOptionsSet, tempSet);
1766
1767          /* use $3 for libraries from command line --> libSet */
1768          mergeSets(&libSet, libFilesSet);
1769
1770          tempSet = appendStrSet(relFilesSet, "", "");
1771          mergeSets(&libSet, tempSet);
1772 //         libSet = reverseSet(libSet);
1773
1774         if(fullSrcFileName) {
1775 //              strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1776                 /* if it didn't work, revert to old behaviour */
1777                 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1778                 strcat(buffer3, port->linker.rel_ext);
1779
1780         } else strcpy(buffer3, "");
1781       }
1782
1783       buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1784
1785       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1786     }
1787   else
1788     {
1789       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1790     }
1791
1792   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1793
1794   system_ret = my_system (buffer);
1795   /* TODO: most linker don't have a -o parameter */
1796   /* -o option overrides default name? */
1797   if (fullDstFileName)
1798     {
1799       char *p, *q;
1800       /* the linked file gets the name of the first modul */
1801       if (fullSrcFileName)
1802         {
1803           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1804           p = strlen (scratchFileName) + scratchFileName;
1805         }
1806       else
1807         {
1808           s = peekSet(relFilesSet);
1809
1810           assert(s);
1811
1812           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1813           /* strip ".rel" extension */
1814           p = strrchr (scratchFileName, '.');
1815           if (p)
1816             {
1817               *p = 0;
1818             }
1819         }
1820       strncatz (scratchFileName,
1821         options.out_fmt ? ".S19" : ".ihx",
1822         sizeof(scratchFileName));
1823       if (strcmp (fullDstFileName, scratchFileName))
1824         unlink (fullDstFileName);
1825       rename (scratchFileName, fullDstFileName);
1826
1827       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1828       q = strrchr (buffer, '.');
1829       if (!q)
1830         {
1831           /* no extension: append new extensions */
1832           q = strlen (buffer) + buffer;
1833         }
1834
1835       *p = 0;
1836       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1837       *q = 0;
1838       strncatz(buffer, ".map", sizeof(buffer));
1839       if (strcmp (scratchFileName, buffer))
1840         unlink (buffer);
1841       rename (scratchFileName, buffer);
1842       *p = 0;
1843       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1844       *q = 0;
1845       strncatz(buffer, ".mem", sizeof(buffer));
1846       if (strcmp (scratchFileName, buffer))
1847         unlink (buffer);
1848       rename (scratchFileName, buffer);
1849       if (options.debug)
1850         {
1851           *p = 0;
1852           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1853           *q = 0;
1854           strncatz(buffer, ".cdb", sizeof(buffer));
1855           if (strcmp (scratchFileName, buffer))
1856             unlink (buffer);
1857           rename (scratchFileName, buffer);
1858           /* and the OMF file without extension: */
1859           *p = 0;
1860           *q = 0;
1861           if (strcmp (scratchFileName, buffer))
1862             unlink (buffer);
1863           rename (scratchFileName, buffer);
1864         }
1865     }
1866   if (system_ret)
1867     {
1868       exit (1);
1869     }
1870 }
1871
1872 /*-----------------------------------------------------------------*/
1873 /* assemble - spawns the assembler with arguments                  */
1874 /*-----------------------------------------------------------------*/
1875 static void
1876 assemble (char **envp)
1877 {
1878     /* build assembler output filename */
1879
1880     /* -o option overrides default name? */
1881     if (options.cc_only && fullDstFileName) {
1882         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1883     } else {
1884         /* the assembled file gets the name of the first modul */
1885         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1886         strncatz (scratchFileName, port->linker.rel_ext,
1887                   sizeof(scratchFileName));
1888     }
1889
1890     if (port->assembler.do_assemble) {
1891         port->assembler.do_assemble(asmOptionsSet);
1892         return ;
1893     } else if (port->assembler.cmd) {
1894         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1895                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1896                       asmOptionsSet);
1897     } else {
1898         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1899     }
1900
1901     if (my_system (buffer)) {
1902         /* either system() or the assembler itself has reported an error
1903            perror ("Cannot exec assembler");
1904         */
1905         exit (1);
1906     }
1907     /* TODO: most assembler don't have a -o parameter */
1908     /* -o option overrides default name? */
1909     if (options.cc_only && fullDstFileName) {
1910         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1911         strncatz (scratchFileName,
1912                   port->linker.rel_ext,
1913                   sizeof(scratchFileName));
1914         if (strcmp (scratchFileName, fullDstFileName))
1915           unlink (fullDstFileName);
1916         rename (scratchFileName, fullDstFileName);
1917     }
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* preProcess - spawns the preprocessor with arguments       */
1922 /*-----------------------------------------------------------------*/
1923 static int
1924 preProcess (char **envp)
1925 {
1926   if (options.c1mode)
1927     {
1928       yyin = stdin;
1929     }
1930   else
1931     {
1932       const char *s;
1933       set *inclList = NULL;
1934
1935       /* if using external stack define the macro */
1936       if (options.useXstack)
1937         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1938
1939       /* set the macro for stack autos  */
1940       if (options.stackAuto)
1941         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1942
1943       /* set the macro for stack autos  */
1944       if (options.stack10bit)
1945         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1946
1947       /* set the macro for no overlay  */
1948       if (options.noOverlay)
1949         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1950
1951       /* set the macro for large model  */
1952       switch (options.model)
1953         {
1954         case MODEL_LARGE:
1955           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1956           break;
1957         case MODEL_SMALL:
1958           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1959           break;
1960         case MODEL_COMPACT:
1961           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1962           break;
1963         case MODEL_MEDIUM:
1964           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1965           break;
1966         case MODEL_FLAT24:
1967           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1968           break;
1969         case MODEL_PAGE0:
1970           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1971           break;
1972         default:
1973           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1974           break;
1975         }
1976
1977       /* add port (processor information to processor */
1978       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1979       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1980
1981       /* standard include path */
1982       if (!options.nostdinc) {
1983         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1984         mergeSets(&preArgvSet, inclList);
1985       }
1986
1987       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1988       Safe_free((void *)s);
1989       if (inclList != NULL)
1990         deleteSet(&inclList);
1991
1992       if (preProcOnly && fullDstFileName)
1993         {
1994           /* -E and -o given */
1995           setMainValue ("cppoutfilename", fullDstFileName);
1996         }
1997       else
1998         {
1999           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2000           setMainValue ("cppoutfilename", NULL);
2001         }
2002
2003       if (options.verbose)
2004         printf ("sdcc: Calling preprocessor...\n");
2005
2006       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2007
2008       if (preProcOnly) {
2009         if (my_system (buffer)) {
2010           exit (1);
2011         }
2012
2013         exit (0);
2014       }
2015
2016       yyin = my_popen (buffer);
2017       if (yyin == NULL) {
2018           perror ("Preproc file not found");
2019           exit (1);
2020       }
2021       addSetHead (&pipeSet, yyin);
2022     }
2023
2024   return 0;
2025 }
2026
2027 /* Set bin paths */
2028 static void
2029 setBinPaths(const char *argv0)
2030 {
2031   char *p;
2032   char buf[PATH_MAX];
2033
2034   /*
2035    * Search logic:
2036    *
2037    * 1. - $SDCCDIR/PREFIX2BIN_DIR
2038    * 2. - path(argv[0])
2039    * 3. - $PATH
2040    */
2041
2042   /* do it in reverse mode, so that addSetHead() can be used
2043      instead of slower addSet() */
2044
2045   if ((p = getBinPath(argv0)) != NULL)
2046     addSetHead(&binPathSet, Safe_strdup(p));
2047
2048   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2049     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2050     addSetHead(&binPathSet, Safe_strdup(buf));
2051   }
2052
2053 #if 0
2054   if (options.printSearchDirs) {
2055     printf("programs:\n");
2056     fputStrSet(stdout, binPathSet);
2057   }
2058 #endif
2059 }
2060
2061 /* Set system include path */
2062 static void
2063 setIncludePath(void)
2064 {
2065   char *p;
2066   char *p2=NULL;
2067   set *tempSet=NULL;
2068
2069   /*
2070    * Search logic:
2071    *
2072    * 1. - $SDCC_INCLUDE/target
2073    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2074    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2075    * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2076    * 5. - $SDCC_INCLUDE
2077    * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2078    * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2079    * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2080    */
2081
2082   if (options.nostdinc)
2083       return;
2084
2085   tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2086   includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2087   includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2088   mergeSets(&includeDirsSet, tempSet);
2089
2090   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2091   {
2092     addSetHead(&includeDirsSet, p);
2093     p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2094     if(p2!=NULL)
2095     {
2096         strcpy(p2, p);
2097         strcat(p2, DIR_SEPARATOR_STRING);
2098         strcat(p2, port->target);
2099         addSetHead(&includeDirsSet, p2);
2100     }
2101   }
2102
2103 #if 0
2104   if (options.printSearchDirs) {
2105     printf("includedir:\n");
2106     fputStrSet(stdout, includeDirsSet);
2107   }
2108 #endif
2109 }
2110
2111 /* Set system lib path */
2112 static void
2113 setLibPath(void)
2114 {
2115   char *p;
2116
2117   /*
2118    * Search logic:
2119    *
2120    * 1. - $SDCC_LIB
2121    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2122    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2123    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2124    */
2125
2126   if (options.nostdlib)
2127       return;
2128
2129   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2130
2131   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2132     addSetHead(&libDirsSet, p);
2133
2134 #if 0
2135   if (options.printSearchDirs) {
2136     printf("libdir:\n");
2137     fputStrSet(stdout, libDirsSet);
2138   }
2139 #endif
2140 }
2141
2142 /* Set data path */
2143 static void
2144 setDataPaths(const char *argv0)
2145 {
2146   char *p;
2147   char buf[PATH_MAX];
2148
2149   /*
2150    * Search logic:
2151    *
2152    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2153    * 2. - path(argv[0])/BIN2DATA_DIR
2154    * 3. - DATADIR (only on *nix)
2155    */
2156
2157   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2158     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2159     addSet(&dataDirsSet, Safe_strdup(buf));
2160   }
2161
2162   if ((p = getBinPath(argv0)) != NULL) {
2163     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2164     addSet(&dataDirsSet, Safe_strdup(buf));
2165   }
2166
2167 #ifdef _WIN32
2168   if (peekSet(dataDirsSet) == NULL) {
2169     /* this should never happen... */
2170     wassertl(0, "Can't get binary path");
2171   }
2172 #else
2173   addSet(&dataDirsSet, Safe_strdup(DATADIR));
2174 #endif
2175
2176 #if 0
2177   if (options.printSearchDirs) {
2178     printf("datadir:\n");
2179     fputStrSet(stdout, dataDirsSet);
2180   }
2181 #endif
2182
2183   setIncludePath();
2184   setLibPath();
2185 }
2186
2187 static void
2188 initValues (void)
2189 {
2190   populateMainValues (_baseValues);
2191   setMainValue ("port", port->target);
2192   setMainValue ("objext", port->linker.rel_ext);
2193   setMainValue ("asmext", port->assembler.file_ext);
2194
2195   setMainValue ("dstfilename", dstFileName);
2196   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2197
2198   if (options.cc_only && fullDstFileName)
2199     /* compile + assemble and -o given: -o specifies name of object file */
2200     {
2201       setMainValue ("objdstfilename", fullDstFileName);
2202     }
2203   else
2204     {
2205       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2206     }
2207   if (fullDstFileName)
2208     /* if we're linking, -o gives the final file name */
2209     {
2210       setMainValue ("linkdstfilename", fullDstFileName);
2211     }
2212   else
2213     {
2214       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2215     }
2216
2217 }
2218
2219 static void doPrintSearchDirs(void)
2220 {
2221     printf("programs:\n");
2222     fputStrSet(stdout, binPathSet);
2223
2224     printf("datadir:\n");
2225     fputStrSet(stdout, dataDirsSet);
2226
2227     printf("includedir:\n");
2228     fputStrSet(stdout, includeDirsSet);
2229
2230     printf("libdir:\n");
2231     fputStrSet(stdout, libDirsSet);
2232     fputStrSet(stdout, libPathsSet);
2233 }
2234
2235
2236 static void
2237 sig_handler (int signal)
2238 {
2239   char *sig_string;
2240
2241   switch (signal)
2242     {
2243     case SIGABRT:
2244       sig_string = "SIGABRT";
2245       break;
2246     case SIGTERM:
2247       sig_string = "SIGTERM";
2248       break;
2249     case SIGINT:
2250       sig_string = "SIGINT";
2251       break;
2252     case SIGSEGV:
2253       sig_string = "SIGSEGV";
2254       break;
2255     default:
2256       sig_string = "Unknown?";
2257       break;
2258     }
2259   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2260   exit (1);
2261 }
2262
2263 /*
2264  * main routine
2265  * initialises and calls the parser
2266  */
2267
2268 int
2269 main (int argc, char **argv, char **envp)
2270 {
2271   /* turn all optimizations off by default */
2272   memset (&optimize, 0, sizeof (struct optimize));
2273
2274   /*printVersionInfo (); */
2275
2276   if (NUM_PORTS==0) {
2277     fprintf (stderr, "Build error: no ports are enabled.\n");
2278     exit (1);
2279   }
2280
2281   /* install atexit handler */
2282   atexit(rm_tmpfiles);
2283
2284   /* install signal handler;
2285      it's only purpuse is to call exit() to remove temp files */
2286   if (!getenv("SDCC_LEAVE_SIGNALS"))
2287     {
2288       signal (SIGABRT, sig_handler);
2289       signal (SIGTERM, sig_handler);
2290       signal (SIGINT , sig_handler);
2291       signal (SIGSEGV, sig_handler);
2292     }
2293
2294   /* Before parsing the command line options, do a
2295    * search for the port and processor and initialize
2296    * them if they're found. (We can't gurantee that these
2297    * will be the first options specified).
2298    */
2299
2300   _findPort (argc, argv);
2301
2302 #ifdef JAMIN_DS390
2303   if (strcmp(port->target, "mcs51") == 0) {
2304     printf("DS390 jammed in A\n");
2305           _setPort ("ds390");
2306     ds390_jammed = 1;
2307   }
2308 #endif
2309
2310   _findProcessor (argc, argv);
2311
2312   /* Initalise the port. */
2313   if (port->init)
2314     port->init ();
2315
2316   setDefaultOptions ();
2317 #ifdef JAMIN_DS390
2318   if (ds390_jammed) {
2319     options.model = MODEL_SMALL;
2320     options.stack10bit=0;
2321   }
2322 #endif
2323   parseCmdLine (argc, argv);
2324
2325   initValues ();
2326
2327   setBinPaths(argv[0]);
2328   setDataPaths(argv[0]);
2329
2330   if(port->initPaths)
2331         port->initPaths();
2332
2333   if(options.printSearchDirs)
2334         doPrintSearchDirs();
2335
2336   /* if no input then printUsage & exit */
2337   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2338     if (!options.printSearchDirs)
2339       printUsage();
2340
2341     exit(0);
2342   }
2343
2344   /* initMem() is expensive, but
2345      initMem() must called before port->finaliseOptions ().
2346      And the z80 port needs port->finaliseOptions(),
2347      even if we're only linking. */
2348   initMem ();
2349   port->finaliseOptions ();
2350
2351   if (fullSrcFileName || options.c1mode)
2352     {
2353       preProcess (envp);
2354
2355       initSymt ();
2356       initiCode ();
2357       initCSupport ();
2358       initBuiltIns();
2359       initPeepHole ();
2360
2361       if (options.verbose)
2362         printf ("sdcc: Generating code...\n");
2363
2364       yyparse ();
2365
2366       if (pclose(yyin))
2367         fatalError = 1;
2368       deleteSetItem(&pipeSet, yyin);
2369
2370       if (fatalError) {
2371         exit (1);
2372       }
2373
2374       if (port->general.do_glue != NULL)
2375         (*port->general.do_glue)();
2376       else
2377         {
2378           /* this shouldn't happen */
2379           assert(FALSE);
2380           /* in case of NDEBUG */
2381           glue();
2382         }
2383
2384       if (fatalError) {
2385         exit (1);
2386       }
2387
2388       if (!options.c1mode && !noAssemble)
2389         {
2390           if (options.verbose)
2391             printf ("sdcc: Calling assembler...\n");
2392           assemble (envp);
2393         }
2394     }
2395   closeDumpFiles();
2396
2397   if (options.debug && debugFile)
2398     debugFile->closeFile();
2399
2400   if (!options.cc_only &&
2401       !fatalError &&
2402       !noAssemble &&
2403       !options.c1mode &&
2404       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2405     {
2406       if (port->linker.do_link)
2407         port->linker.do_link ();
2408       else
2409         linkEdit (envp);
2410     }
2411
2412   return 0;
2413 }