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