pic16 progress by Vangelis
[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) && !options.no_std_crt0) /*For the z80, gbz80*/
1487   {
1488       char crt0path[PATH_MAX];
1489       FILE * crt0fp;
1490       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1491       {
1492           sprintf (crt0path, "%s%s%s%scrt0.o",
1493              s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1494           
1495           crt0fp=fopen(crt0path, "r");
1496           if(crt0fp!=NULL)/*Found it!*/
1497           {
1498               fclose(crt0fp);
1499               #ifdef __CYGWIN__
1500               {
1501                  /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1502                  windows paths, so convert them to the CYGWIN format*/
1503                  char posix_path[PATH_MAX];
1504                  void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1505                  cygwin_conv_to_full_posix_path(crt0path, posix_path);
1506                  strcpy(crt0path, posix_path);
1507               }
1508               #endif
1509               fprintf (lnkfile, "%s\n", crt0path);
1510               break;
1511           }
1512       }
1513       if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1514   }
1515
1516   /* put in the object files */
1517   if (fullSrcFileName)
1518     fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1519
1520   fputStrSet(lnkfile, relFilesSet);
1521
1522   fprintf (lnkfile, "\n-e\n");
1523   fclose (lnkfile);
1524
1525   if (options.verbose)
1526     printf ("sdcc: Calling linker...\n");
1527
1528   /* build linker output filename */
1529
1530   /* -o option overrides default name? */
1531   if (fullDstFileName)
1532     {
1533       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1534     }
1535   else
1536     {
1537       /* the linked file gets the name of the first modul */
1538       if (fullSrcFileName)
1539         {
1540           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1541         }
1542       else
1543         {
1544           s = peekSet(relFilesSet);
1545
1546           assert(s);
1547
1548           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1549           /* strip ".rel" extension */
1550           *strrchr (scratchFileName, '.') = '\0';
1551         }
1552       strncatz (scratchFileName, 
1553                 options.out_fmt ? ".S19" : ".ihx",
1554                 sizeof(scratchFileName));
1555     }
1556
1557   if (port->linker.cmd)
1558     {
1559       char buffer2[PATH_MAX];
1560
1561         /* VR 030517 - gplink needs linker options to set the linker script,*/
1562         buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, linkOptionsSet);
1563
1564         buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1565     }
1566   else
1567     {
1568       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1569     }
1570
1571 /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1572
1573   system_ret = my_system (buffer);
1574   /* TODO: most linker don't have a -o parameter */
1575   /* -o option overrides default name? */
1576   if (fullDstFileName)
1577     {
1578       char *p, *q;
1579       /* the linked file gets the name of the first modul */
1580       if (fullSrcFileName)
1581         {
1582           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1583           p = strlen (scratchFileName) + scratchFileName;
1584         }
1585       else
1586         {
1587           s = peekSet(relFilesSet);
1588
1589           assert(s);
1590
1591           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1592           /* strip ".rel" extension */
1593           p = strrchr (scratchFileName, '.');
1594           if (p)
1595             {
1596               *p = 0;
1597             }
1598         }
1599       strncatz (scratchFileName,
1600                 options.out_fmt ? ".S19" : ".ihx",
1601                 sizeof(scratchFileName));
1602       rename (scratchFileName, fullDstFileName);
1603
1604       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1605       q = strrchr (buffer, '.');
1606       if (!q)
1607         {
1608           /* no extension: append new extensions */
1609           q = strlen (buffer) + buffer;
1610         }
1611
1612       *p = 0;
1613       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1614       *q = 0;
1615       strncatz(buffer, ".map", sizeof(buffer));
1616       rename (scratchFileName, buffer);
1617       *p = 0;
1618       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1619       *q = 0;
1620       strncatz(buffer, ".mem", sizeof(buffer));
1621       rename (scratchFileName, buffer);
1622     }
1623   if (system_ret)
1624     {
1625       exit (1);
1626     }
1627 }
1628
1629 /*-----------------------------------------------------------------*/
1630 /* assemble - spawns the assembler with arguments                  */
1631 /*-----------------------------------------------------------------*/
1632 static void
1633 assemble (char **envp)
1634 {
1635     /* build assembler output filename */
1636
1637     /* -o option overrides default name? */
1638     if (options.cc_only && fullDstFileName) {
1639         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1640     } else {
1641         /* the assembled file gets the name of the first modul */
1642         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1643         strncatz (scratchFileName, port->linker.rel_ext, 
1644                   sizeof(scratchFileName));
1645     }
1646
1647     if (port->assembler.do_assemble) {
1648         port->assembler.do_assemble(asmOptionsSet);
1649         return ;
1650     } else if (port->assembler.cmd) {
1651         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1652                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1653                       asmOptionsSet);
1654     } else {
1655         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1656     }
1657
1658     if (my_system (buffer)) {
1659         /* either system() or the assembler itself has reported an error
1660            perror ("Cannot exec assembler");
1661         */
1662         exit (1);
1663     }
1664     /* TODO: most assembler don't have a -o parameter */
1665     /* -o option overrides default name? */
1666     if (options.cc_only && fullDstFileName) {
1667         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1668         strncatz (scratchFileName, 
1669                   port->linker.rel_ext,
1670                   sizeof(scratchFileName));
1671         rename (scratchFileName, fullDstFileName);
1672     }
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* preProcess - spawns the preprocessor with arguments       */
1677 /*-----------------------------------------------------------------*/
1678 static int
1679 preProcess (char **envp)
1680 {
1681   if (options.c1mode)
1682     {
1683       yyin = stdin;
1684     }
1685   else
1686     {
1687       const char *s;
1688       set *inclList = NULL;
1689
1690       /* if using external stack define the macro */
1691       if (options.useXstack)
1692         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1693
1694       /* set the macro for stack autos  */
1695       if (options.stackAuto)
1696         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1697
1698       /* set the macro for stack autos  */
1699       if (options.stack10bit)
1700         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1701
1702       /* set the macro for no overlay  */
1703       if (options.noOverlay)
1704         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1705
1706       /* set the macro for large model  */
1707       switch (options.model)
1708         {
1709         case MODEL_LARGE:
1710           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1711           break;
1712         case MODEL_SMALL:
1713           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1714           break;
1715         case MODEL_COMPACT:
1716           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1717           break;
1718         case MODEL_MEDIUM:
1719           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1720           break;
1721         case MODEL_FLAT24:
1722           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1723           break;
1724         case MODEL_PAGE0:
1725           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1726           break;
1727         default:
1728           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1729           break;
1730         }
1731
1732       /* add port (processor information to processor */
1733       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1734       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1735
1736       /* standard include path */
1737       if (!options.nostdinc) {
1738         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1739         mergeSets(&preArgvSet, inclList);
1740       }
1741
1742       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1743       Safe_free((void *)s);
1744       if (inclList != NULL)
1745         deleteSet(&inclList);
1746
1747       if (preProcOnly && fullDstFileName)
1748         {
1749           /* -E and -o given */
1750           setMainValue ("cppoutfilename", fullDstFileName);
1751         }
1752       else
1753         {
1754           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1755           setMainValue ("cppoutfilename", NULL);
1756         }
1757
1758       if (options.verbose)
1759         printf ("sdcc: Calling preprocessor...\n");
1760
1761       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1762
1763       if (preProcOnly) {
1764         if (my_system (buffer)) {
1765           exit (1);
1766         }
1767
1768         exit (0);
1769       }
1770
1771       yyin = my_popen (buffer);
1772       if (yyin == NULL) {
1773           perror ("Preproc file not found");
1774           exit (1);
1775       }
1776       addSetHead (&pipeSet, yyin);
1777     }
1778
1779   return 0;
1780 }
1781
1782 /* Set bin paths */
1783 static void
1784 setBinPaths(const char *argv0)
1785 {
1786   char *p;
1787   char buf[PATH_MAX];
1788
1789   /*
1790    * Search logic:
1791    *
1792    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1793    * 2. - path(argv[0])
1794    * 3. - $PATH
1795    */
1796
1797   /* do it in reverse mode, so that addSetHead() can be used
1798      instead of slower addSet() */
1799
1800   if ((p = getBinPath(argv0)) != NULL)
1801     addSetHead(&binPathSet, Safe_strdup(p));
1802
1803   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1804     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1805     addSetHead(&binPathSet, Safe_strdup(buf));
1806   }
1807
1808   if (options.printSearchDirs) {
1809     printf("programs:\n");
1810     fputStrSet(stdout, binPathSet);
1811   }
1812 }
1813
1814 /* Set system include path */
1815 static void
1816 setIncludePath(void)
1817 {
1818   char *p;
1819
1820   /*
1821    * Search logic:
1822    *
1823    * 1. - $SDCC_INCLUDE
1824    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1825    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1826    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1827    */
1828
1829   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1830
1831   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1832     addSetHead(&includeDirsSet, p);
1833
1834   if (options.printSearchDirs) {
1835     printf("includedir:\n");
1836     fputStrSet(stdout, includeDirsSet);
1837   }
1838 }
1839
1840 /* Set system lib path */
1841 static void
1842 setLibPath(void)
1843 {
1844   char *p;
1845
1846   /*
1847    * Search logic:
1848    *
1849    * 1. - $SDCC_LIB
1850    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1851    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1852    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1853    */
1854
1855   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1856
1857   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1858     addSetHead(&libDirsSet, p);
1859
1860   if (options.printSearchDirs) {
1861     printf("libdir:\n");
1862     fputStrSet(stdout, libDirsSet);
1863   }
1864 }
1865
1866 /* Set data path */
1867 static void
1868 setDataPaths(const char *argv0)
1869 {
1870   char *p;
1871   char buf[PATH_MAX];
1872
1873   /*
1874    * Search logic:
1875    *
1876    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1877    * 2. - path(argv[0])/BIN2DATA_DIR
1878    * 3. - DATADIR (only on *nix)
1879    */
1880
1881   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1882     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1883     addSet(&dataDirsSet, Safe_strdup(buf));
1884   }
1885
1886   if ((p = getBinPath(argv0)) != NULL) {
1887     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1888     addSet(&dataDirsSet, Safe_strdup(buf));
1889   }
1890
1891 #ifdef _WIN32
1892   if (peekSet(dataDirsSet) == NULL) {
1893     /* this should never happen... */
1894     wassertl(0, "Can't get binary path");
1895   }
1896 #else
1897   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1898 #endif
1899
1900   if (options.printSearchDirs) {
1901     printf("datadir:\n");
1902     fputStrSet(stdout, dataDirsSet);
1903   }
1904
1905   setIncludePath();
1906   setLibPath();
1907 }
1908
1909 static void
1910 initValues (void)
1911 {
1912   populateMainValues (_baseValues);
1913   setMainValue ("port", port->target);
1914   setMainValue ("objext", port->linker.rel_ext);
1915   setMainValue ("asmext", port->assembler.file_ext);
1916
1917   setMainValue ("dstfilename", dstFileName);
1918   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1919
1920   if (options.cc_only && fullDstFileName)
1921     /* compile + assemble and -o given: -o specifies name of object file */
1922     {
1923       setMainValue ("objdstfilename", fullDstFileName);
1924     }
1925   else
1926     {
1927       setMainValue ("objdstfilename", "{stdobjdstfilename}");
1928     }
1929   if (fullDstFileName)
1930     /* if we're linking, -o gives the final file name */
1931     {
1932       setMainValue ("linkdstfilename", fullDstFileName);
1933     }
1934   else
1935     {
1936       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
1937     }
1938
1939 }
1940
1941 static void
1942 sig_handler (int signal)
1943 {
1944   char *sig_string;
1945
1946   switch (signal)
1947     {
1948     case SIGABRT:
1949       sig_string = "SIGABRT";
1950       break;
1951     case SIGTERM:
1952       sig_string = "SIGTERM";
1953       break;
1954     case SIGINT:
1955       sig_string = "SIGINT";
1956       break;
1957     case SIGSEGV:
1958       sig_string = "SIGSEGV";
1959       break;
1960     default:
1961       sig_string = "Unknown?";
1962       break;
1963     }
1964   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
1965   exit (1);
1966 }
1967
1968 /*
1969  * main routine
1970  * initialises and calls the parser
1971  */
1972
1973 int
1974 main (int argc, char **argv, char **envp)
1975 {
1976   /* turn all optimizations off by default */
1977   memset (&optimize, 0, sizeof (struct optimize));
1978
1979   /*printVersionInfo (); */
1980
1981   if (NUM_PORTS==0) {
1982     fprintf (stderr, "Build error: no ports are enabled.\n");
1983     exit (1);
1984   }
1985
1986   /* install atexit handler */
1987   atexit(rm_tmpfiles);
1988
1989   /* install signal handler;
1990      it's only purpuse is to call exit() to remove temp files */
1991   if (!getenv("SDCC_LEAVE_SIGNALS"))
1992     {
1993       signal (SIGABRT, sig_handler);
1994       signal (SIGTERM, sig_handler);
1995       signal (SIGINT , sig_handler);
1996       signal (SIGSEGV, sig_handler);
1997     }
1998
1999   /* Before parsing the command line options, do a
2000    * search for the port and processor and initialize
2001    * them if they're found. (We can't gurantee that these
2002    * will be the first options specified).
2003    */
2004
2005   _findPort (argc, argv);
2006
2007 #ifdef JAMIN_DS390
2008   if (strcmp(port->target, "mcs51") == 0) {
2009     printf("DS390 jammed in A\n");
2010           _setPort ("ds390");
2011     ds390_jammed = 1;
2012   }
2013 #endif
2014
2015   _findProcessor (argc, argv);
2016
2017   /* Initalise the port. */
2018   if (port->init)
2019     port->init ();
2020
2021   setDefaultOptions ();
2022 #ifdef JAMIN_DS390
2023   if (ds390_jammed) {
2024     options.model = MODEL_SMALL;
2025     options.stack10bit=0;
2026   }
2027 #endif
2028   parseCmdLine (argc, argv);
2029
2030   initValues ();
2031   setBinPaths(argv[0]);
2032   setDataPaths(argv[0]);
2033
2034   /* if no input then printUsage & exit */
2035   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2036     if (!options.printSearchDirs)
2037       printUsage();
2038
2039     exit(0);
2040   }
2041
2042   /* initMem() is expensive, but
2043      initMem() must called before port->finaliseOptions ().
2044      And the z80 port needs port->finaliseOptions(),
2045      even if we're only linking. */
2046   initMem ();
2047   port->finaliseOptions ();
2048
2049   if (fullSrcFileName || options.c1mode)
2050     {
2051       preProcess (envp);
2052
2053       initSymt ();
2054       initiCode ();
2055       initCSupport ();
2056       initBuiltIns();
2057       initPeepHole ();
2058
2059       if (options.verbose)
2060         printf ("sdcc: Generating code...\n");
2061
2062       yyparse ();
2063
2064       pclose(yyin);
2065       deleteSetItem(&pipeSet, yyin);
2066
2067       if (fatalError) {
2068         exit (1);
2069       }
2070
2071       if (port->general.do_glue != NULL)
2072         (*port->general.do_glue)();
2073       else
2074         {
2075           /* this shouldn't happen */
2076           assert(FALSE);
2077           /* in case of NDEBUG */
2078           glue();
2079         }
2080
2081       if (!options.c1mode && !noAssemble)
2082         {
2083           if (options.verbose)
2084             printf ("sdcc: Calling assembler...\n");
2085           assemble (envp);
2086         }
2087     }
2088   closeDumpFiles();
2089
2090   if (options.debug && debugFile)
2091     debugFile->closeFile();
2092
2093   if (!options.cc_only &&
2094       !fatalError &&
2095       !noAssemble &&
2096       !options.c1mode &&
2097       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2098     {
2099       if (port->linker.do_link)
2100         port->linker.do_link ();
2101       else
2102         linkEdit (envp);
2103     }
2104
2105   return 0;
2106 }