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