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