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