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