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