6ac338a433de2db8aebda684befc647847371f41
[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   int length;
489
490   /* skip the initial white spaces */
491   while (isspace(*src))
492     src++;
493
494   /* skip the trailing white spaces */
495   length = strlen(src);
496   while (length && isspace(src[length-1]))
497     src[--length] = '\0';
498
499   for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
500     addSet(dest, Safe_strdup(p));
501 }
502
503 /*-----------------------------------------------------------------*/
504 /* setDefaultOptions - sets the default options                    */
505 /*-----------------------------------------------------------------*/
506 static void
507 setDefaultOptions (void)
508 {
509   /* first the options part */
510   options.stack_loc = 0;        /* stack pointer initialised to 0 */
511   options.xstack_loc = 0;       /* xternal stack starts at 0 */
512   options.code_loc = 0;         /* code starts at 0 */
513   options.data_loc = 0;         /* JCF: By default let the linker locate data */
514   options.xdata_loc = 0;
515   options.idata_loc = 0x80;
516   options.nopeep = 0;
517   options.model = port->general.default_model;
518   options.nostdlib = 0;
519   options.nostdinc = 0;
520   options.verbose = 0;
521   options.shortis8bits = 0;
522
523   options.stack10bit=0;
524
525   /* now for the optimizations */
526   /* turn on the everything */
527   optimize.global_cse = 1;
528   optimize.label1 = 1;
529   optimize.label2 = 1;
530   optimize.label3 = 1;
531   optimize.label4 = 1;
532   optimize.loopInvariant = 1;
533   optimize.loopInduction = 1;
534
535   /* now for the ports */
536   port->setDefaultOptions ();
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* processFile - determines the type of file from the extension    */
541 /*-----------------------------------------------------------------*/
542 static void
543 processFile (char *s)
544 {
545   char *fext = NULL;
546
547   /* get the file extension */
548   fext = s + strlen (s);
549   while ((fext != s) && *fext != '.')
550     fext--;
551
552   /* now if no '.' then we don't know what the file type is
553      so give a warning and return */
554   if (fext == s)
555     {
556       werror (W_UNKNOWN_FEXT, s);
557       return;
558     }
559
560   /* otherwise depending on the file type */
561   if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
562     {
563       /* source file name : not if we already have a
564          source file */
565       if (fullSrcFileName)
566         {
567           werror (W_TOO_MANY_SRC, s);
568           return;
569         }
570
571       /* the only source file */
572       fullSrcFileName = s;
573       if (!(srcFile = fopen (fullSrcFileName, "r")))
574         {
575           werror (E_FILE_OPEN_ERR, s);
576           exit (1);
577         }
578
579       /* copy the file name into the buffer */
580       strncpyz (buffer, s, sizeof(buffer));
581
582       /* get rid of the "."-extension */
583
584       /* is there a dot at all? */
585       if (strrchr (buffer, '.') &&
586           /* is the dot in the filename, not in the path? */
587           (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
588         {
589         *strrchr (buffer, '.') = '\0';
590         }
591
592       /* get rid of any path information
593          for the module name; */
594       fext = buffer + strlen (buffer);
595 #if NATIVE_WIN32
596       /* do this by going backwards till we
597          get '\' or ':' or start of buffer */
598       while (fext != buffer &&
599              *(fext - 1) != DIR_SEPARATOR_CHAR &&
600              *(fext - 1) != ':')
601         {
602         fext--;
603         }
604 #else
605       /* do this by going backwards till we
606          get '/' or start of buffer */
607       while (fext != buffer &&
608              *(fext - 1) != DIR_SEPARATOR_CHAR)
609         {
610           fext--;
611         }
612 #endif
613       moduleName = Safe_strdup ( fext );
614       return;
615     }
616
617   /* if the extention is type .rel or .r or .REL or .R
618      addtional object file will be passed to the linker */
619   if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
620       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
621       strcmp (fext, port->linker.rel_ext) == 0)
622     {
623       addSet(&relFilesSet, Safe_strdup(s));
624       return;
625     }
626
627   /* if .lib or .LIB */
628   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
629     {
630       addSet(&libFilesSet, Safe_strdup(s));
631       return;
632     }
633
634   werror (W_UNKNOWN_FEXT, s);
635
636 }
637
638 static void
639 _setModel (int model, const char *sz)
640 {
641   if (port->general.supported_models & model)
642     options.model = model;
643   else
644     werror (W_UNSUPPORTED_MODEL, sz, port->target);
645 }
646
647 /** Gets the string argument to this option.  If the option is '--opt'
648     then for input of '--optxyz' or '--opt xyz' returns xyz.
649 */
650 static char *
651 getStringArg(const char *szStart, char **argv, int *pi, int argc)
652 {
653   if (argv[*pi][strlen(szStart)])
654     {
655       return &argv[*pi][strlen(szStart)];
656     }
657   else
658     {
659       ++(*pi);
660       if (*pi >= argc)
661         {
662           werror (E_ARGUMENT_MISSING, szStart);
663           /* Die here rather than checking for errors later. */
664           exit(-1);
665         }
666       else
667         {
668           return argv[*pi];
669         }
670     }
671 }
672
673 /** Gets the integer argument to this option using the same rules as
674     getStringArg.
675 */
676 static int
677 getIntArg(const char *szStart, char **argv, int *pi, int argc)
678 {
679     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
680 }
681
682 static void
683 verifyShortOption(const char *opt)
684 {
685   if (strlen(opt) != 2)
686     {
687       werror (W_EXCESS_SHORT_OPTIONS, opt);
688     }
689 }
690
691 static bool
692 tryHandleUnsupportedOpt(char **argv, int *pi)
693 {
694     if (argv[*pi][0] == '-') 
695         {
696             const char *longOpt = "";
697             char shortOpt = -1;
698             int i;
699
700             if (argv[*pi][1] == '-') 
701                 {
702                     /* Long option. */
703                     longOpt = argv[*pi];
704                 }
705             else 
706                 {
707                     shortOpt = argv[*pi][1];
708                 }
709             for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
710                 {
711                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
712                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
713                         /* Found an unsupported opt. */
714                         char buffer[100];
715                         SNPRINTF(buffer, sizeof(buffer), 
716                                  "%s%c%c", 
717                                  longOpt ? longOpt : "", 
718                                  shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
719                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
720                         return 1;
721                     }
722                 }
723             /* Didn't find in the table */
724             return 0;
725         }
726     else 
727         {
728             /* Not an option, so can't be unsupported :) */
729             return 0;
730     }
731 }
732
733 static bool
734 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
735 {
736   int i;
737   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
738     {
739       if (optionsTable[i].shortOpt == shortOpt ||
740           (longOpt && optionsTable[i].longOpt && 
741            strcmp(optionsTable[i].longOpt, longOpt) == 0))
742         {
743
744           /* If it is a flag then we can handle it here */
745           if (optionsTable[i].pparameter != NULL) 
746             {
747               if (optionsTable[i].shortOpt == shortOpt)
748                 {
749                   verifyShortOption(argv[*pi]);
750                 }
751
752               (*optionsTable[i].pparameter)++;
753               return 1;
754             }
755           else {
756             /* Not a flag.  Handled manually later. */
757             return 0;
758           }
759         }
760     }
761   /* Didn't find in the table */
762   return 0;
763 }
764
765 static bool
766 tryHandleSimpleOpt(char **argv, int *pi)
767 {
768     if (argv[*pi][0] == '-') 
769         {
770             const char *longOpt = "";
771             char shortOpt = -1;
772
773             if (argv[*pi][1] == '-') 
774                 {
775                     /* Long option. */
776                     longOpt = argv[*pi];
777                 }
778             else 
779                 {
780                     shortOpt = argv[*pi][1];
781                 }
782
783             if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
784               {
785                 return 1;
786               }
787             else if (port && port->poptions &&
788                      scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
789               {
790                 return 1;
791               }
792             else
793               {
794                 return 0;
795               }
796         }
797     else 
798         {
799             /* Not an option, so can't be handled. */
800             return 0;
801         }
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* parseCmdLine - parses the command line and sets the options     */
806 /*-----------------------------------------------------------------*/
807 static int
808 parseCmdLine (int argc, char **argv)
809 {
810   int i;
811
812   /* go thru all whole command line */
813   for (i = 1; i < argc; i++)
814     {
815       if (i >= argc)
816         break;
817
818       if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
819           {
820               continue;
821           }
822
823       if (tryHandleSimpleOpt(argv, &i) == TRUE)
824           {
825               continue;
826           }
827
828       /* options */
829       if (argv[i][0] == '-' && argv[i][1] == '-')
830         {
831           if (strcmp (argv[i], OPTION_HELP) == 0)
832             {
833               printUsage ();
834               exit (0);
835             }
836
837           if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
838             {
839               options.stack10bit = 0;
840               continue;
841             }
842
843           if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
844             {
845               options.out_fmt = 0;
846               continue;
847             }
848
849           if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
850             {
851               _setModel (MODEL_LARGE, argv[i]);
852               continue;
853             }
854
855           if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
856             {
857               _setModel (MODEL_MEDIUM, argv[i]);
858               continue;
859             }
860
861           if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
862             {
863               _setModel (MODEL_SMALL, argv[i]);
864               continue;
865             }
866
867           if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
868             {
869               _setModel (MODEL_FLAT24, argv[i]);
870               continue;
871             }
872
873           if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
874             {
875               options.dump_rassgn =
876                 options.dump_pack =
877                 options.dump_range =
878                 options.dump_kill =
879                 options.dump_loop =
880                 options.dump_gcse =
881                 options.dump_raw = 1;
882               continue;
883             }
884
885           if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
886             {
887                 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
888                 continue;
889             }
890
891           if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
892             {
893                 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
894                 continue;
895             }
896
897           if (strcmp (argv[i], OPTION_VERSION) == 0)
898             {
899               printVersionInfo ();
900               exit (0);
901               continue;
902             }
903
904           if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
905             {
906                 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
907                 continue;
908             }
909
910           if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
911             {
912                 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
913                 continue;
914             }
915
916           if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
917             {
918                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
919                 continue;
920             }
921
922           if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
923             {
924                 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
925                 continue;
926             }
927
928           if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
929             {
930                 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
931                 continue;
932             }
933
934           if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
935             {
936                 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
937                 options.xram_size_set = TRUE;
938                 continue;
939             }
940
941           if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
942             {
943                 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
944                 continue;
945             }
946
947           if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
948             {
949                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
950                 continue;
951             }
952
953           if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
954             {
955                 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
956                 continue;
957             }
958
959           if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
960             {
961                 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
962                 continue;
963             }
964
965           if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
966             {
967               optimize.global_cse = 0;
968               continue;
969             }
970
971           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
972             {
973               optimize.loopInvariant = 0;
974               continue;
975             }
976
977           if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
978             {
979               optimize.label4 = 0;
980               continue;
981             }
982
983           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
984             {
985               optimize.loopInduction = 0;
986               continue;
987             }
988
989           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
990             {
991               options.lessPedantic = 1;
992               setErrorLogLevel(ERROR_LEVEL_WARNING);
993               continue;
994             }
995
996           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
997             {
998               options.shortis8bits=1;
999               continue;
1000             }
1001
1002           if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1003             {
1004                 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1005                 continue;
1006             }
1007           
1008           if (!port->parseOption (&argc, argv, &i))
1009             {
1010               werror (W_UNKNOWN_OPTION, argv[i]);
1011             }
1012           else
1013             {
1014               continue;
1015             }
1016         }
1017
1018       /* if preceded by  '-' then option */
1019       if (*argv[i] == '-')
1020         {
1021           switch (argv[i][1])
1022             {
1023             case 'h':
1024               verifyShortOption(argv[i]);
1025
1026               printUsage ();
1027               exit (0);
1028               break;
1029
1030             case 'm':
1031               /* Used to select the port. But this has already been done. */
1032               break;
1033
1034             case 'p':
1035               /* Used to select the processor in port. But this has
1036                * already been done. */
1037               break;
1038
1039             case 'c':
1040               verifyShortOption(argv[i]);
1041
1042               options.cc_only = 1;
1043               break;
1044
1045             case 'L':
1046                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1047                 break;
1048
1049             case 'l':
1050                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1051                 break;
1052             
1053             case 'o':
1054               {
1055                 char *p;
1056
1057                 /* copy the file name into the buffer */
1058                 strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
1059                          sizeof(buffer));
1060                 /* point to last character */
1061                 p = buffer + strlen (buffer) - 1;
1062                 if (*p == DIR_SEPARATOR_CHAR)
1063                   {
1064                     /* only output path specified */
1065                     dstPath = Safe_strdup (buffer);
1066                     fullDstFileName = NULL;
1067                   }
1068                 else
1069                   {
1070                     fullDstFileName = Safe_strdup (buffer);
1071
1072                     /* get rid of the "."-extension */
1073
1074                     /* is there a dot at all? */
1075                     if (strrchr (buffer, '.') &&
1076                         /* is the dot in the filename, not in the path? */
1077                         (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1078                       *strrchr (buffer, '.') = '\0';
1079
1080                     dstFileName = Safe_strdup (buffer);
1081
1082                     /* strip module name to get path */
1083                     p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1084                     if (p)
1085                       {
1086                         /* path with trailing / */
1087                         p[1] = '\0';
1088                         dstPath = Safe_strdup (buffer);
1089                       }
1090                   }
1091                 break;
1092               }
1093
1094             case 'W':
1095               /* pre-processer options */
1096               if (argv[i][2] == 'p')
1097                 {
1098                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1099                 }
1100               /* linker options */
1101               else if (argv[i][2] == 'l')
1102                 {
1103                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1104                 }
1105               /* assembler options */
1106               else if (argv[i][2] == 'a')
1107                 {
1108                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1109                 }
1110               else
1111                 {
1112                   werror (W_UNKNOWN_OPTION, argv[i]);
1113                 }
1114               break;
1115
1116             case 'v':
1117               verifyShortOption(argv[i]);
1118
1119               printVersionInfo ();
1120               exit (0);
1121               break;
1122
1123               /* preprocessor options */
1124             case 'M':
1125               {
1126                 preProcOnly = 1;
1127                 addSet(&preArgvSet, Safe_strdup("-M"));
1128                 break;
1129               }
1130             case 'C':
1131               {
1132                 addSet(&preArgvSet, Safe_strdup("-C"));
1133                 break;
1134               }
1135
1136             case 'd':
1137             case 'D':
1138             case 'I':
1139             case 'A':
1140             case 'U':
1141               {
1142                 char sOpt = argv[i][1];
1143                 char *rest;
1144
1145                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1146                   {
1147                     i++;
1148                     if (i >= argc)
1149                       {
1150                           /* No argument. */
1151                           werror(E_ARGUMENT_MISSING, argv[i-1]);
1152                           break;
1153                       }
1154                     else
1155                       {
1156                           rest = argv[i];
1157                       }
1158                   }
1159                 else
1160                   rest = &argv[i][2];
1161
1162                 if (sOpt == 'Y')
1163                   sOpt = 'I';
1164
1165                 SNPRINTF (buffer, sizeof(buffer),
1166                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1167                 addSet(&preArgvSet, Safe_strdup(buffer));
1168               }
1169               break;
1170
1171             default:
1172               if (!port->parseOption (&argc, argv, &i))
1173                 werror (W_UNKNOWN_OPTION, argv[i]);
1174             }
1175           continue;
1176         }
1177
1178       if (!port->parseOption (&argc, argv, &i))
1179         {
1180            /* no option must be a filename */
1181            if (options.c1mode)
1182              {
1183                 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1184              }
1185          else
1186              {
1187                 processFile (argv[i]);
1188              }
1189         }
1190     }
1191
1192   /* some sanity checks in c1 mode */
1193   if (options.c1mode)
1194     {
1195       const char *s;
1196
1197       if (fullSrcFileName)
1198         {
1199           fclose (srcFile);
1200           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1201         }
1202       fullSrcFileName = NULL;
1203       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1204         {
1205           werror (W_NO_FILE_ARG_IN_C1, s);
1206         }
1207       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1208         {
1209           werror (W_NO_FILE_ARG_IN_C1, s);
1210         }
1211       deleteSet(&relFilesSet);
1212       deleteSet(&libFilesSet);
1213
1214         if (options.cc_only || noAssemble || preProcOnly)
1215         {
1216           werror (W_ILLEGAL_OPT_COMBINATION);
1217         }
1218       options.cc_only = noAssemble = preProcOnly = 0;
1219       if (!dstFileName)
1220         {
1221           werror (E_NEED_OPT_O_IN_C1);
1222           exit (1);
1223         }
1224     }
1225   /* if no dstFileName given with -o, we've to find one: */
1226   if (!dstFileName)
1227     {
1228       const char *s;
1229
1230       /* use the modulename from the C-source */
1231       if (fullSrcFileName)
1232         {
1233           size_t bufSize = strlen (dstPath) + strlen (moduleName) + 1;
1234
1235           dstFileName = Safe_alloc (bufSize);
1236           strncpyz (dstFileName, dstPath, bufSize);
1237           strncatz (dstFileName, moduleName, bufSize);
1238         }
1239       /* use the modulename from the first object file */
1240       else if ((s = peekSet(relFilesSet)) != NULL)
1241         {
1242           char *objectName;
1243           size_t bufSize;
1244
1245           strncpyz (buffer, s, sizeof(buffer));
1246           /* remove extension (it must be .rel) */
1247           *strrchr (buffer, '.') = '\0';
1248           /* remove path */
1249           objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1250           if (objectName)
1251             {
1252               ++objectName;
1253             }
1254           else
1255             {
1256               objectName = buffer;
1257             }
1258           bufSize = strlen (dstPath) + strlen (objectName) + 1;  
1259           dstFileName = Safe_alloc (bufSize);
1260           strncpyz (dstFileName, dstPath, bufSize);
1261           strncatz (dstFileName, objectName, bufSize);
1262         }
1263       /* else no module given: help text is displayed */
1264     }
1265
1266   /* set up external stack location if not explicitly specified */
1267   if (!options.xstack_loc)
1268     options.xstack_loc = options.xdata_loc;
1269
1270   /* if debug option is set then open the cdbFile */
1271   if (options.debug && fullSrcFileName)
1272     {
1273       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1274                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1275       if(debugFile->openFile(scratchFileName))
1276         debugFile->writeModule(moduleName);
1277       else
1278         werror (E_FILE_OPEN_ERR, scratchFileName);
1279     }
1280   MSVC_style(options.vc_err_style);
1281   if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1282
1283   return 0;
1284 }
1285
1286 /*-----------------------------------------------------------------*/
1287 /* linkEdit : - calls the linkage editor  with options             */
1288 /*-----------------------------------------------------------------*/
1289 static void
1290 linkEdit (char **envp)
1291 {
1292   FILE *lnkfile;
1293   char *segName, *c;
1294   int system_ret;
1295   const char *s;
1296
1297   /* first we need to create the <filename>.lnk file */
1298   SNPRINTF (scratchFileName, sizeof(scratchFileName),
1299             "%s.lnk", dstFileName);
1300   if (!(lnkfile = fopen (scratchFileName, "w")))
1301     {
1302       werror (E_FILE_OPEN_ERR, scratchFileName);
1303       exit (1);
1304     }
1305
1306    if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1307    {
1308           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1309           (options.out_fmt ? 's' : 'i'), dstFileName);
1310    }
1311    else /*For all the other ports.  Including pics???*/
1312    {
1313           fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1314    }
1315
1316    if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1317    {
1318           /* if iram size specified */
1319           if (options.iram_size)
1320                 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1321
1322           /* if xram size specified */
1323           if (options.xram_size_set)
1324                 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1325
1326           /* if code size specified */
1327           if (options.code_size)
1328                 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1329
1330           if (options.debug)
1331                 fprintf (lnkfile, "-z\n");
1332    }
1333
1334 #define WRITE_SEG_LOC(N, L) \
1335     segName = Safe_strdup(N); \
1336     c = strtok(segName, " \t"); \
1337     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1338     if (segName) { Safe_free(segName); }
1339
1340    if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1341    {
1342
1343           /* code segment start */
1344           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1345
1346           /* data segment start. If zero, the linker chooses
1347       the best place for data*/
1348           if(options.data_loc){
1349                   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1350           }
1351
1352           /* xdata start */
1353           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1354
1355           /* indirect data */
1356           if (IDATA_NAME) {
1357                 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1358           }
1359
1360           /* bit segment start */
1361           WRITE_SEG_LOC (BIT_NAME, 0);
1362
1363           /* stack start */
1364           if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
1365                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1366           }
1367    }
1368    else /*For the z80, gbz80*/
1369    {
1370        WRITE_SEG_LOC ("_CODE", options.code_loc);
1371        WRITE_SEG_LOC ("_DATA", options.data_loc);
1372    }
1373   
1374   /* If the port has any special linker area declarations, get 'em */
1375   if (port->extraAreas.genExtraAreaLinkOptions)
1376   {
1377         port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1378   }
1379
1380   /* add the extra linker options */
1381   fputStrSet(lnkfile, linkOptionsSet);
1382
1383   /* other library paths if specified */
1384   for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1385     fprintf (lnkfile, "-k %s\n", s);
1386   
1387   /* standard library path */
1388     if (!options.nostdlib)
1389     {
1390         if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1391         {
1392             switch (options.model)
1393             {
1394                 case MODEL_SMALL:
1395                     c = "small";
1396                     break;
1397                 case MODEL_LARGE:
1398                     c = "large";
1399                     break;
1400                 case MODEL_FLAT24:
1401                     /* c = "flat24"; */
1402                     if (TARGET_IS_DS390)
1403                     {
1404                         c = "ds390";
1405                     }
1406                     else if (TARGET_IS_DS400)
1407                     {
1408                         c = "ds400";
1409                     }
1410                     else
1411                     {
1412                         fprintf(stderr, 
1413                                 "Add support for your FLAT24 target in %s @ line %d\n",
1414                                 __FILE__, __LINE__);
1415                         exit(-1);
1416                     }
1417                         break;
1418                     case MODEL_PAGE0:
1419                         c = "xa51";
1420                         break;
1421                     default:
1422                         werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1423                         c = "unknown";
1424                         break;
1425                 }
1426         }
1427         else /*for the z80, gbz80*/
1428         {
1429             if (TARGET_IS_Z80)
1430                 c = "z80";
1431             else
1432                 c = "gbz80";
1433         }
1434         for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1435             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1436
1437
1438       /* standard library files */
1439 #if !OPT_DISABLE_DS390
1440         if (options.model == MODEL_FLAT24)
1441         {
1442             if (TARGET_IS_DS390)
1443             {
1444                 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1445             }
1446             else if (TARGET_IS_DS400)
1447             {
1448                 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1449             }
1450             else
1451             {
1452                 fprintf(stderr, 
1453                     "Add support for your FLAT24 target in %s @ line %d\n",
1454                     __FILE__, __LINE__);
1455                 exit(-1);
1456             }
1457         }
1458 #endif
1459
1460 #if !OPT_DISABLE_XA51 
1461 #ifdef STD_XA51_LIB
1462         if (options.model == MODEL_PAGE0)
1463         {
1464             fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1465         }
1466 #endif
1467 #endif
1468         if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1469         { /*Why the z80 port is not using the standard libraries?*/
1470             fprintf (lnkfile, "-l %s\n", STD_LIB);
1471             fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1472             fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1473             fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1474         }
1475         else if (TARGET_IS_Z80)
1476         {
1477             fprintf (lnkfile, "-l z80\n");
1478         }
1479         else if (TARGET_IS_GBZ80)
1480         {
1481             fprintf (lnkfile, "-l gbz80\n");
1482         }
1483     }
1484
1485   /* additional libraries if any */
1486   for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1487     fprintf (lnkfile, "-l %s\n", s);
1488
1489   /*For the z80 and gbz80 ports, try to find where crt0.o is...
1490   It is very important for this file to be first on the linking proccess
1491   so the areas are set in the correct order, expecially _GSINIT*/
1492   if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1493       !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1494   {
1495       char crt0path[PATH_MAX];
1496       FILE * crt0fp;
1497       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1498       {
1499           sprintf (crt0path, "%s%s%s%scrt0.o",
1500              s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1501           
1502           crt0fp=fopen(crt0path, "r");
1503           if(crt0fp!=NULL)/*Found it!*/
1504           {
1505               fclose(crt0fp);
1506               #ifdef __CYGWIN__
1507               {
1508                  /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1509                  windows paths, so convert them to the CYGWIN format*/
1510                  char posix_path[PATH_MAX];
1511                  void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1512                  cygwin_conv_to_full_posix_path(crt0path, posix_path);
1513                  strcpy(crt0path, posix_path);
1514               }
1515               #endif
1516               fprintf (lnkfile, "%s\n", crt0path);
1517               break;
1518           }
1519       }
1520       if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1521   }
1522
1523   /* put in the object files */
1524   if (fullSrcFileName)
1525     fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1526
1527   fputStrSet(lnkfile, relFilesSet);
1528
1529   fprintf (lnkfile, "\n-e\n");
1530   fclose (lnkfile);
1531
1532   if (options.verbose)
1533     printf ("sdcc: Calling linker...\n");
1534
1535   /* build linker output filename */
1536
1537   /* -o option overrides default name? */
1538   if (fullDstFileName)
1539     {
1540       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1541     }
1542   else
1543     {
1544       /* the linked file gets the name of the first modul */
1545       if (fullSrcFileName)
1546         {
1547           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1548         }
1549       else
1550         {
1551           s = peekSet(relFilesSet);
1552
1553           assert(s);
1554
1555           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1556           /* strip ".rel" extension */
1557           *strrchr (scratchFileName, '.') = '\0';
1558         }
1559       strncatz (scratchFileName, 
1560                 options.out_fmt ? ".S19" : ".ihx",
1561                 sizeof(scratchFileName));
1562     }
1563
1564   if (port->linker.cmd)
1565     {
1566       char buffer2[PATH_MAX];
1567
1568         /* VR 030517 - gplink needs linker options to set the linker script,*/
1569         buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, linkOptionsSet);
1570
1571         buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1572     }
1573   else
1574     {
1575       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1576     }
1577
1578 /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1579
1580   system_ret = my_system (buffer);
1581   /* TODO: most linker don't have a -o parameter */
1582   /* -o option overrides default name? */
1583   if (fullDstFileName)
1584     {
1585       char *p, *q;
1586       /* the linked file gets the name of the first modul */
1587       if (fullSrcFileName)
1588         {
1589           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1590           p = strlen (scratchFileName) + scratchFileName;
1591         }
1592       else
1593         {
1594           s = peekSet(relFilesSet);
1595
1596           assert(s);
1597
1598           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1599           /* strip ".rel" extension */
1600           p = strrchr (scratchFileName, '.');
1601           if (p)
1602             {
1603               *p = 0;
1604             }
1605         }
1606       strncatz (scratchFileName,
1607                 options.out_fmt ? ".S19" : ".ihx",
1608                 sizeof(scratchFileName));
1609       rename (scratchFileName, fullDstFileName);
1610
1611       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1612       q = strrchr (buffer, '.');
1613       if (!q)
1614         {
1615           /* no extension: append new extensions */
1616           q = strlen (buffer) + buffer;
1617         }
1618
1619       *p = 0;
1620       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1621       *q = 0;
1622       strncatz(buffer, ".map", sizeof(buffer));
1623       rename (scratchFileName, buffer);
1624       *p = 0;
1625       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1626       *q = 0;
1627       strncatz(buffer, ".mem", sizeof(buffer));
1628       rename (scratchFileName, buffer);
1629     }
1630   if (system_ret)
1631     {
1632       exit (1);
1633     }
1634 }
1635
1636 /*-----------------------------------------------------------------*/
1637 /* assemble - spawns the assembler with arguments                  */
1638 /*-----------------------------------------------------------------*/
1639 static void
1640 assemble (char **envp)
1641 {
1642     /* build assembler output filename */
1643
1644     /* -o option overrides default name? */
1645     if (options.cc_only && fullDstFileName) {
1646         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1647     } else {
1648         /* the assembled file gets the name of the first modul */
1649         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1650         strncatz (scratchFileName, port->linker.rel_ext, 
1651                   sizeof(scratchFileName));
1652     }
1653
1654     if (port->assembler.do_assemble) {
1655         port->assembler.do_assemble(asmOptionsSet);
1656         return ;
1657     } else if (port->assembler.cmd) {
1658         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1659                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1660                       asmOptionsSet);
1661     } else {
1662         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1663     }
1664
1665     if (my_system (buffer)) {
1666         /* either system() or the assembler itself has reported an error
1667            perror ("Cannot exec assembler");
1668         */
1669         exit (1);
1670     }
1671     /* TODO: most assembler don't have a -o parameter */
1672     /* -o option overrides default name? */
1673     if (options.cc_only && fullDstFileName) {
1674         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1675         strncatz (scratchFileName, 
1676                   port->linker.rel_ext,
1677                   sizeof(scratchFileName));
1678         rename (scratchFileName, fullDstFileName);
1679     }
1680 }
1681
1682 /*-----------------------------------------------------------------*/
1683 /* preProcess - spawns the preprocessor with arguments       */
1684 /*-----------------------------------------------------------------*/
1685 static int
1686 preProcess (char **envp)
1687 {
1688   if (options.c1mode)
1689     {
1690       yyin = stdin;
1691     }
1692   else
1693     {
1694       const char *s;
1695       set *inclList = NULL;
1696
1697       /* if using external stack define the macro */
1698       if (options.useXstack)
1699         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1700
1701       /* set the macro for stack autos  */
1702       if (options.stackAuto)
1703         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1704
1705       /* set the macro for stack autos  */
1706       if (options.stack10bit)
1707         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1708
1709       /* set the macro for no overlay  */
1710       if (options.noOverlay)
1711         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1712
1713       /* set the macro for large model  */
1714       switch (options.model)
1715         {
1716         case MODEL_LARGE:
1717           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1718           break;
1719         case MODEL_SMALL:
1720           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1721           break;
1722         case MODEL_COMPACT:
1723           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1724           break;
1725         case MODEL_MEDIUM:
1726           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1727           break;
1728         case MODEL_FLAT24:
1729           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1730           break;
1731         case MODEL_PAGE0:
1732           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1733           break;
1734         default:
1735           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1736           break;
1737         }
1738
1739       /* add port (processor information to processor */
1740       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1741       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1742
1743       /* standard include path */
1744       if (!options.nostdinc) {
1745         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1746         mergeSets(&preArgvSet, inclList);
1747       }
1748
1749       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1750       Safe_free((void *)s);
1751       if (inclList != NULL)
1752         deleteSet(&inclList);
1753
1754       if (preProcOnly && fullDstFileName)
1755         {
1756           /* -E and -o given */
1757           setMainValue ("cppoutfilename", fullDstFileName);
1758         }
1759       else
1760         {
1761           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1762           setMainValue ("cppoutfilename", NULL);
1763         }
1764
1765       if (options.verbose)
1766         printf ("sdcc: Calling preprocessor...\n");
1767
1768       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1769
1770       if (preProcOnly) {
1771         if (my_system (buffer)) {
1772           exit (1);
1773         }
1774
1775         exit (0);
1776       }
1777
1778       yyin = my_popen (buffer);
1779       if (yyin == NULL) {
1780           perror ("Preproc file not found");
1781           exit (1);
1782       }
1783       addSetHead (&pipeSet, yyin);
1784     }
1785
1786   return 0;
1787 }
1788
1789 /* Set bin paths */
1790 static void
1791 setBinPaths(const char *argv0)
1792 {
1793   char *p;
1794   char buf[PATH_MAX];
1795
1796   /*
1797    * Search logic:
1798    *
1799    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1800    * 2. - path(argv[0])
1801    * 3. - $PATH
1802    */
1803
1804   /* do it in reverse mode, so that addSetHead() can be used
1805      instead of slower addSet() */
1806
1807   if ((p = getBinPath(argv0)) != NULL)
1808     addSetHead(&binPathSet, Safe_strdup(p));
1809
1810   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1811     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1812     addSetHead(&binPathSet, Safe_strdup(buf));
1813   }
1814
1815   if (options.printSearchDirs) {
1816     printf("programs:\n");
1817     fputStrSet(stdout, binPathSet);
1818   }
1819 }
1820
1821 /* Set system include path */
1822 static void
1823 setIncludePath(void)
1824 {
1825   char *p;
1826
1827   /*
1828    * Search logic:
1829    *
1830    * 1. - $SDCC_INCLUDE
1831    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1832    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1833    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1834    */
1835
1836   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1837
1838   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1839     addSetHead(&includeDirsSet, p);
1840
1841   if (options.printSearchDirs) {
1842     printf("includedir:\n");
1843     fputStrSet(stdout, includeDirsSet);
1844   }
1845 }
1846
1847 /* Set system lib path */
1848 static void
1849 setLibPath(void)
1850 {
1851   char *p;
1852
1853   /*
1854    * Search logic:
1855    *
1856    * 1. - $SDCC_LIB
1857    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1858    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1859    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1860    */
1861
1862   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1863
1864   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1865     addSetHead(&libDirsSet, p);
1866
1867   if (options.printSearchDirs) {
1868     printf("libdir:\n");
1869     fputStrSet(stdout, libDirsSet);
1870   }
1871 }
1872
1873 /* Set data path */
1874 static void
1875 setDataPaths(const char *argv0)
1876 {
1877   char *p;
1878   char buf[PATH_MAX];
1879
1880   /*
1881    * Search logic:
1882    *
1883    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1884    * 2. - path(argv[0])/BIN2DATA_DIR
1885    * 3. - DATADIR (only on *nix)
1886    */
1887
1888   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1889     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1890     addSet(&dataDirsSet, Safe_strdup(buf));
1891   }
1892
1893   if ((p = getBinPath(argv0)) != NULL) {
1894     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1895     addSet(&dataDirsSet, Safe_strdup(buf));
1896   }
1897
1898 #ifdef _WIN32
1899   if (peekSet(dataDirsSet) == NULL) {
1900     /* this should never happen... */
1901     wassertl(0, "Can't get binary path");
1902   }
1903 #else
1904   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1905 #endif
1906
1907   if (options.printSearchDirs) {
1908     printf("datadir:\n");
1909     fputStrSet(stdout, dataDirsSet);
1910   }
1911
1912   setIncludePath();
1913   setLibPath();
1914 }
1915
1916 static void
1917 initValues (void)
1918 {
1919   populateMainValues (_baseValues);
1920   setMainValue ("port", port->target);
1921   setMainValue ("objext", port->linker.rel_ext);
1922   setMainValue ("asmext", port->assembler.file_ext);
1923
1924   setMainValue ("dstfilename", dstFileName);
1925   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1926
1927   if (options.cc_only && fullDstFileName)
1928     /* compile + assemble and -o given: -o specifies name of object file */
1929     {
1930       setMainValue ("objdstfilename", fullDstFileName);
1931     }
1932   else
1933     {
1934       setMainValue ("objdstfilename", "{stdobjdstfilename}");
1935     }
1936   if (fullDstFileName)
1937     /* if we're linking, -o gives the final file name */
1938     {
1939       setMainValue ("linkdstfilename", fullDstFileName);
1940     }
1941   else
1942     {
1943       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
1944     }
1945
1946 }
1947
1948 static void
1949 sig_handler (int signal)
1950 {
1951   char *sig_string;
1952
1953   switch (signal)
1954     {
1955     case SIGABRT:
1956       sig_string = "SIGABRT";
1957       break;
1958     case SIGTERM:
1959       sig_string = "SIGTERM";
1960       break;
1961     case SIGINT:
1962       sig_string = "SIGINT";
1963       break;
1964     case SIGSEGV:
1965       sig_string = "SIGSEGV";
1966       break;
1967     default:
1968       sig_string = "Unknown?";
1969       break;
1970     }
1971   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
1972   exit (1);
1973 }
1974
1975 /*
1976  * main routine
1977  * initialises and calls the parser
1978  */
1979
1980 int
1981 main (int argc, char **argv, char **envp)
1982 {
1983   /* turn all optimizations off by default */
1984   memset (&optimize, 0, sizeof (struct optimize));
1985
1986   /*printVersionInfo (); */
1987
1988   if (NUM_PORTS==0) {
1989     fprintf (stderr, "Build error: no ports are enabled.\n");
1990     exit (1);
1991   }
1992
1993   /* install atexit handler */
1994   atexit(rm_tmpfiles);
1995
1996   /* install signal handler;
1997      it's only purpuse is to call exit() to remove temp files */
1998   if (!getenv("SDCC_LEAVE_SIGNALS"))
1999     {
2000       signal (SIGABRT, sig_handler);
2001       signal (SIGTERM, sig_handler);
2002       signal (SIGINT , sig_handler);
2003       signal (SIGSEGV, sig_handler);
2004     }
2005
2006   /* Before parsing the command line options, do a
2007    * search for the port and processor and initialize
2008    * them if they're found. (We can't gurantee that these
2009    * will be the first options specified).
2010    */
2011
2012   _findPort (argc, argv);
2013
2014 #ifdef JAMIN_DS390
2015   if (strcmp(port->target, "mcs51") == 0) {
2016     printf("DS390 jammed in A\n");
2017           _setPort ("ds390");
2018     ds390_jammed = 1;
2019   }
2020 #endif
2021
2022   _findProcessor (argc, argv);
2023
2024   /* Initalise the port. */
2025   if (port->init)
2026     port->init ();
2027
2028   setDefaultOptions ();
2029 #ifdef JAMIN_DS390
2030   if (ds390_jammed) {
2031     options.model = MODEL_SMALL;
2032     options.stack10bit=0;
2033   }
2034 #endif
2035   parseCmdLine (argc, argv);
2036
2037   initValues ();
2038   setBinPaths(argv[0]);
2039   setDataPaths(argv[0]);
2040
2041   /* if no input then printUsage & exit */
2042   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2043     if (!options.printSearchDirs)
2044       printUsage();
2045
2046     exit(0);
2047   }
2048
2049   /* initMem() is expensive, but
2050      initMem() must called before port->finaliseOptions ().
2051      And the z80 port needs port->finaliseOptions(),
2052      even if we're only linking. */
2053   initMem ();
2054   port->finaliseOptions ();
2055
2056   if (fullSrcFileName || options.c1mode)
2057     {
2058       preProcess (envp);
2059
2060       initSymt ();
2061       initiCode ();
2062       initCSupport ();
2063       initBuiltIns();
2064       initPeepHole ();
2065
2066       if (options.verbose)
2067         printf ("sdcc: Generating code...\n");
2068
2069       yyparse ();
2070
2071       pclose(yyin);
2072       deleteSetItem(&pipeSet, yyin);
2073
2074       if (fatalError) {
2075         exit (1);
2076       }
2077
2078       if (port->general.do_glue != NULL)
2079         (*port->general.do_glue)();
2080       else
2081         {
2082           /* this shouldn't happen */
2083           assert(FALSE);
2084           /* in case of NDEBUG */
2085           glue();
2086         }
2087
2088       if (!options.c1mode && !noAssemble)
2089         {
2090           if (options.verbose)
2091             printf ("sdcc: Calling assembler...\n");
2092           assemble (envp);
2093         }
2094     }
2095   closeDumpFiles();
2096
2097   if (options.debug && debugFile)
2098     debugFile->closeFile();
2099
2100   if (!options.cc_only &&
2101       !fatalError &&
2102       !noAssemble &&
2103       !options.c1mode &&
2104       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2105     {
2106       if (port->linker.do_link)
2107         port->linker.do_link ();
2108       else
2109         linkEdit (envp);
2110     }
2111
2112   return 0;
2113 }