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