* src/SDCCmain.c (linkEdit): do not test for PIC16 target since, PIC16
[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 -DSDCC=1 {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 port (processor information to processor */
2019       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
2020       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
2021
2022       /* standard include path */
2023       if (!options.nostdinc) {
2024         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
2025         mergeSets(&preArgvSet, inclList);
2026       }
2027
2028       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
2029       Safe_free((void *)s);
2030       if (inclList != NULL)
2031         deleteSet(&inclList);
2032
2033       if (preProcOnly && fullDstFileName)
2034         {
2035           /* -E and -o given */
2036           setMainValue ("cppoutfilename", fullDstFileName);
2037         }
2038       else
2039         {
2040           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2041           setMainValue ("cppoutfilename", NULL);
2042         }
2043
2044       if (options.verbose)
2045         printf ("sdcc: Calling preprocessor...\n");
2046       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2047
2048       if (preProcOnly) {
2049         if (my_system (buffer)) {
2050           exit (1);
2051         }
2052
2053         exit (0);
2054       }
2055
2056       yyin = my_popen (buffer);
2057       if (yyin == NULL) {
2058           perror ("Preproc file not found");
2059           exit (1);
2060       }
2061       addSetHead (&pipeSet, yyin);
2062     }
2063
2064   return 0;
2065 }
2066
2067 /* Set bin paths */
2068 static void
2069 setBinPaths(const char *argv0)
2070 {
2071   char *p;
2072   char buf[PATH_MAX];
2073
2074   /*
2075    * Search logic:
2076    *
2077    * 1. - $SDCCDIR/PREFIX2BIN_DIR
2078    * 2. - path(argv[0])
2079    * 3. - $PATH
2080    */
2081
2082   /* do it in reverse mode, so that addSetHead() can be used
2083      instead of slower addSet() */
2084
2085   if ((p = getBinPath(argv0)) != NULL)
2086     addSetHead(&binPathSet, Safe_strdup(p));
2087
2088   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2089     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2090     addSetHead(&binPathSet, Safe_strdup(buf));
2091   }
2092 }
2093
2094 /* Set system include path */
2095 static void
2096 setIncludePath(void)
2097 {
2098   char *p;
2099   char *p2=NULL;
2100   set *tempSet=NULL;
2101
2102   /*
2103    * Search logic:
2104    *
2105    * 1. - $SDCC_INCLUDE/target
2106    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2107    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2108    * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2109    * 5. - $SDCC_INCLUDE
2110    * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2111    * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2112    * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2113    */
2114
2115   if (options.nostdinc)
2116       return;
2117
2118   tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2119   includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2120   includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2121   mergeSets(&includeDirsSet, tempSet);
2122
2123   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2124   {
2125     addSetHead(&includeDirsSet, p);
2126     p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2127     if(p2!=NULL)
2128     {
2129         strcpy(p2, p);
2130         strcat(p2, DIR_SEPARATOR_STRING);
2131         strcat(p2, port->target);
2132         addSetHead(&includeDirsSet, p2);
2133     }
2134   }
2135 }
2136
2137 /* Set system lib path */
2138 static void
2139 setLibPath(void)
2140 {
2141   char *p;
2142
2143   /*
2144    * Search logic:
2145    *
2146    * 1. - $SDCC_LIB
2147    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2148    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2149    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2150    */
2151
2152   if (options.nostdlib)
2153       return;
2154
2155   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2156
2157   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2158     addSetHead(&libDirsSet, p);
2159 }
2160
2161 /* Set data path */
2162 static void
2163 setDataPaths(const char *argv0)
2164 {
2165   char *p;
2166   char buf[PATH_MAX];
2167
2168   /*
2169    * Search logic:
2170    *
2171    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2172    * 2. - path(argv[0])/BIN2DATA_DIR
2173    * 3. - DATADIR (only on *nix)
2174    */
2175
2176   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2177     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2178     addSet(&dataDirsSet, Safe_strdup(buf));
2179   }
2180
2181   if ((p = getBinPath(argv0)) != NULL) {
2182     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2183     addSet(&dataDirsSet, Safe_strdup(buf));
2184   }
2185
2186 #ifdef _WIN32
2187   if (peekSet(dataDirsSet) == NULL) {
2188     /* this should never happen... */
2189     wassertl(0, "Can't get binary path");
2190   }
2191 #else
2192   addSet(&dataDirsSet, Safe_strdup(DATADIR));
2193 #endif
2194
2195   setIncludePath();
2196   setLibPath();
2197 }
2198
2199 static void
2200 initValues (void)
2201 {
2202   populateMainValues (_baseValues);
2203   setMainValue ("port", port->target);
2204   setMainValue ("objext", port->linker.rel_ext);
2205   setMainValue ("asmext", port->assembler.file_ext);
2206
2207   setMainValue ("dstfilename", dstFileName);
2208   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2209
2210   if (options.cc_only && fullDstFileName)
2211     /* compile + assemble and -o given: -o specifies name of object file */
2212     {
2213       setMainValue ("objdstfilename", fullDstFileName);
2214     }
2215   else
2216     {
2217       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2218     }
2219   if (fullDstFileName)
2220     /* if we're linking, -o gives the final file name */
2221     {
2222       setMainValue ("linkdstfilename", fullDstFileName);
2223     }
2224   else
2225     {
2226       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2227     }
2228
2229 }
2230
2231 static void doPrintSearchDirs(void)
2232 {
2233     printf("programs:\n");
2234     fputStrSet(stdout, binPathSet);
2235
2236     printf("datadir:\n");
2237     fputStrSet(stdout, dataDirsSet);
2238
2239     printf("includedir:\n");
2240     fputStrSet(stdout, includeDirsSet);
2241
2242     printf("libdir:\n");
2243     fputStrSet(stdout, libDirsSet);
2244     fputStrSet(stdout, libPathsSet);
2245 }
2246
2247
2248 static void
2249 sig_handler (int signal)
2250 {
2251   char *sig_string;
2252
2253   switch (signal)
2254     {
2255     case SIGABRT:
2256       sig_string = "SIGABRT";
2257       break;
2258     case SIGTERM:
2259       sig_string = "SIGTERM";
2260       break;
2261     case SIGINT:
2262       sig_string = "SIGINT";
2263       break;
2264     case SIGSEGV:
2265       sig_string = "SIGSEGV";
2266       break;
2267     default:
2268       sig_string = "Unknown?";
2269       break;
2270     }
2271   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2272   exit (1);
2273 }
2274
2275 /*
2276  * main routine
2277  * initialises and calls the parser
2278  */
2279
2280 int
2281 main (int argc, char **argv, char **envp)
2282 {
2283   /* turn all optimizations off by default */
2284   memset (&optimize, 0, sizeof (struct optimize));
2285
2286   /*printVersionInfo (); */
2287
2288   if (NUM_PORTS==0) {
2289     fprintf (stderr, "Build error: no ports are enabled.\n");
2290     exit (1);
2291   }
2292
2293   /* install atexit handler */
2294   atexit(rm_tmpfiles);
2295
2296   /* install signal handler;
2297      it's only purpuse is to call exit() to remove temp files */
2298   if (!getenv("SDCC_LEAVE_SIGNALS"))
2299     {
2300       signal (SIGABRT, sig_handler);
2301       signal (SIGTERM, sig_handler);
2302       signal (SIGINT , sig_handler);
2303       signal (SIGSEGV, sig_handler);
2304     }
2305
2306   /* Before parsing the command line options, do a
2307    * search for the port and processor and initialize
2308    * them if they're found. (We can't gurantee that these
2309    * will be the first options specified).
2310    */
2311
2312   _findPort (argc, argv);
2313
2314 #ifdef JAMIN_DS390
2315   if (strcmp(port->target, "mcs51") == 0) {
2316     printf("DS390 jammed in A\n");
2317     _setPort ("ds390");
2318     ds390_jammed = 1;
2319   }
2320 #endif
2321
2322   _findProcessor (argc, argv);
2323
2324   /* Initalise the port. */
2325   if (port->init)
2326     port->init ();
2327
2328   setDefaultOptions ();
2329 #ifdef JAMIN_DS390
2330   if (ds390_jammed) {
2331     options.model = MODEL_SMALL;
2332     options.stack10bit=0;
2333   }
2334 #endif
2335
2336   parseCmdLine (argc, argv);
2337
2338   if (options.verbose && NULL != port->processor)
2339     printf("Processor: %s\n", port->processor);
2340
2341   initValues ();
2342
2343   setBinPaths(argv[0]);
2344   setDataPaths(argv[0]);
2345
2346   if(port->initPaths)
2347         port->initPaths();
2348
2349   if(options.printSearchDirs)
2350         doPrintSearchDirs();
2351
2352   /* if no input then printUsage & exit */
2353   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2354     if (!options.printSearchDirs)
2355       printUsage();
2356
2357     exit(0);
2358   }
2359
2360   /* initMem() is expensive, but
2361      initMem() must called before port->finaliseOptions ().
2362      And the z80 port needs port->finaliseOptions(),
2363      even if we're only linking. */
2364   initMem ();
2365   port->finaliseOptions ();
2366
2367   if (fullSrcFileName || options.c1mode)
2368     {
2369       preProcess (envp);
2370
2371       initSymt ();
2372       initiCode ();
2373       initCSupport ();
2374       initBuiltIns();
2375       initPeepHole ();
2376
2377       if (options.verbose)
2378         printf ("sdcc: Generating code...\n");
2379
2380       yyparse ();
2381
2382       if (pclose(yyin))
2383         fatalError = 1;
2384       deleteSetItem(&pipeSet, yyin);
2385
2386       if (fatalError) {
2387         exit (1);
2388       }
2389
2390       if (port->general.do_glue != NULL)
2391         (*port->general.do_glue)();
2392       else
2393         {
2394           /* this shouldn't happen */
2395           assert(FALSE);
2396           /* in case of NDEBUG */
2397           glue();
2398         }
2399
2400       if (fatalError) {
2401         exit (1);
2402       }
2403
2404       if (!options.c1mode && !noAssemble)
2405         {
2406           if (options.verbose)
2407             printf ("sdcc: Calling assembler...\n");
2408           assemble (envp);
2409         }
2410     }
2411   closeDumpFiles();
2412
2413   if (options.debug && debugFile)
2414     debugFile->closeFile();
2415
2416   if (!options.cc_only &&
2417       !fatalError &&
2418       !noAssemble &&
2419       !options.c1mode &&
2420       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2421     {
2422       if (options.verbose)
2423         printf ("sdcc: Calling linker...\n");
2424
2425       if (port->linker.do_link)
2426         port->linker.do_link ();
2427       else
2428         linkEdit (envp);
2429     }
2430
2431   return 0;
2432 }