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