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