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