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