2004-01-08 Vangelis Rokas <vrokas@otenet.gr>
[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   /* first we need to create the <filename>.lnk file */
1293   SNPRINTF (scratchFileName, sizeof(scratchFileName),
1294             "%s.lnk", dstFileName);
1295   if (!(lnkfile = fopen (scratchFileName, "w")))
1296     {
1297       werror (E_FILE_OPEN_ERR, scratchFileName);
1298       exit (1);
1299     }
1300
1301    if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1302    {
1303           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1304           (options.out_fmt ? 's' : 'i'), dstFileName);
1305    }
1306    else /*For all the other ports.  Including pics???*/
1307    {
1308           fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1309    }
1310
1311    if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1312    {
1313           /* if iram size specified */
1314           if (options.iram_size)
1315                 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1316
1317           /* if xram size specified */
1318           if (options.xram_size_set)
1319                 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1320
1321           /* if code size specified */
1322           if (options.code_size)
1323                 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1324
1325           if (options.debug)
1326                 fprintf (lnkfile, "-z\n");
1327    }
1328
1329 #define WRITE_SEG_LOC(N, L) \
1330     segName = Safe_strdup(N); \
1331     c = strtok(segName, " \t"); \
1332     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1333     if (segName) { Safe_free(segName); }
1334
1335    if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1336    {
1337
1338           /* code segment start */
1339           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1340
1341           /* data segment start. If zero, the linker chooses
1342       the best place for data*/
1343           if(options.data_loc){
1344                   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1345           }
1346
1347           /* xdata start */
1348           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1349
1350           /* indirect data */
1351           if (IDATA_NAME) {
1352                 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1353           }
1354
1355           /* bit segment start */
1356           WRITE_SEG_LOC (BIT_NAME, 0);
1357
1358           /* stack start */
1359           if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
1360                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1361           }
1362    }
1363    else /*For the z80, gbz80*/
1364    {
1365        WRITE_SEG_LOC ("_CODE", options.code_loc);
1366        WRITE_SEG_LOC ("_DATA", options.data_loc);
1367    }
1368   
1369   /* If the port has any special linker area declarations, get 'em */
1370   if (port->extraAreas.genExtraAreaLinkOptions)
1371   {
1372         port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1373   }
1374
1375   /* add the extra linker options */
1376   fputStrSet(lnkfile, linkOptionsSet);
1377
1378   /* other library paths if specified */
1379   for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1380     fprintf (lnkfile, "-k %s\n", s);
1381   
1382   /* standard library path */
1383     if (!options.nostdlib)
1384     {
1385         if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1386         {
1387             switch (options.model)
1388             {
1389                 case MODEL_SMALL:
1390                     c = "small";
1391                     break;
1392                 case MODEL_LARGE:
1393                     c = "large";
1394                     break;
1395                 case MODEL_FLAT24:
1396                     /* c = "flat24"; */
1397                     if (TARGET_IS_DS390)
1398                     {
1399                         c = "ds390";
1400                     }
1401                     else if (TARGET_IS_DS400)
1402                     {
1403                         c = "ds400";
1404                     }
1405                     else
1406                     {
1407                         fprintf(stderr, 
1408                                 "Add support for your FLAT24 target in %s @ line %d\n",
1409                                 __FILE__, __LINE__);
1410                         exit(-1);
1411                     }
1412                         break;
1413                     case MODEL_PAGE0:
1414                         c = "xa51";
1415                         break;
1416                     default:
1417                         werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1418                         c = "unknown";
1419                         break;
1420                 }
1421         }
1422         else /*for the z80, gbz80*/
1423         {
1424             if (TARGET_IS_HC08)
1425                 c = "hc08";
1426             else if (TARGET_IS_Z80)
1427                 c = "z80";
1428             else
1429                 c = "gbz80";
1430         }
1431         for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1432             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1433
1434
1435       /* standard library files */
1436 #if !OPT_DISABLE_DS390
1437         if (options.model == MODEL_FLAT24)
1438         {
1439             if (TARGET_IS_DS390)
1440             {
1441                 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1442             }
1443             else if (TARGET_IS_DS400)
1444             {
1445                 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1446             }
1447             else
1448             {
1449                 fprintf(stderr, 
1450                     "Add support for your FLAT24 target in %s @ line %d\n",
1451                     __FILE__, __LINE__);
1452                 exit(-1);
1453             }
1454         }
1455 #endif
1456
1457 #if !OPT_DISABLE_XA51 
1458 #ifdef STD_XA51_LIB
1459         if (options.model == MODEL_PAGE0)
1460         {
1461             fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1462         }
1463 #endif
1464 #endif
1465         if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1466               || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1467         { /*Why the z80 port is not using the standard libraries?*/
1468             fprintf (lnkfile, "-l %s\n", STD_LIB);
1469             fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1470             fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1471             fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1472         }
1473         else if (TARGET_IS_HC08)
1474         {
1475             fprintf (lnkfile, "-l hc08\n");
1476         }
1477         else if (TARGET_IS_Z80)
1478         {
1479             fprintf (lnkfile, "-l z80\n");
1480         }
1481         else if (TARGET_IS_GBZ80)
1482         {
1483             fprintf (lnkfile, "-l gbz80\n");
1484         }
1485     }
1486
1487   /* additional libraries if any */
1488   for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1489     fprintf (lnkfile, "-l %s\n", s);
1490
1491   /*For the z80 and gbz80 ports, try to find where crt0.o is...
1492   It is very important for this file to be first on the linking proccess
1493   so the areas are set in the correct order, expecially _GSINIT*/
1494   if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1495       !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1496   {
1497       char crt0path[PATH_MAX];
1498       FILE * crt0fp;
1499       for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1500       {
1501           sprintf (crt0path, "%s%s%s%scrt0.o",
1502              s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1503           
1504           crt0fp=fopen(crt0path, "r");
1505           if(crt0fp!=NULL)/*Found it!*/
1506           {
1507               fclose(crt0fp);
1508               #ifdef __CYGWIN__
1509               {
1510                  /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1511                  windows paths, so convert them to the CYGWIN format*/
1512                  char posix_path[PATH_MAX];
1513                  void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1514                  cygwin_conv_to_full_posix_path(crt0path, posix_path);
1515                  strcpy(crt0path, posix_path);
1516               }
1517               #endif
1518               fprintf (lnkfile, "%s\n", crt0path);
1519               break;
1520           }
1521       }
1522       if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1523   }
1524
1525   /* put in the object files */
1526   if (fullSrcFileName)
1527     fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1528
1529   fputStrSet(lnkfile, relFilesSet);
1530
1531   fprintf (lnkfile, "\n-e\n");
1532   fclose (lnkfile);
1533   }     /* if(port->linker.needLinkerScript) */
1534
1535   if (options.verbose)
1536     printf ("sdcc: Calling linker...\n");
1537
1538   /* build linker output filename */
1539
1540   /* -o option overrides default name? */
1541   if (fullDstFileName)
1542     {
1543       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1544     }
1545   else
1546     {
1547       /* the linked file gets the name of the first modul */
1548       if (fullSrcFileName)
1549         {
1550           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1551         }
1552       else
1553         {
1554           s = peekSet(relFilesSet);
1555
1556           assert(s);
1557
1558           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1559           /* strip ".rel" extension */
1560           *strrchr (scratchFileName, '.') = '\0';
1561         }
1562       strncatz (scratchFileName, 
1563                 options.out_fmt ? ".S19" : ".ihx",
1564                 sizeof(scratchFileName));
1565     }
1566
1567   if (port->linker.cmd)
1568     {
1569       char buffer2[PATH_MAX];
1570
1571         /* VR 030517 - gplink needs linker options to set the linker script,*/
1572         buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, linkOptionsSet);
1573
1574         buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1575     }
1576   else
1577     {
1578       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1579     }
1580
1581 /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1582
1583   system_ret = my_system (buffer);
1584   /* TODO: most linker don't have a -o parameter */
1585   /* -o option overrides default name? */
1586   if (fullDstFileName)
1587     {
1588       char *p, *q;
1589       /* the linked file gets the name of the first modul */
1590       if (fullSrcFileName)
1591         {
1592           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1593           p = strlen (scratchFileName) + scratchFileName;
1594         }
1595       else
1596         {
1597           s = peekSet(relFilesSet);
1598
1599           assert(s);
1600
1601           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1602           /* strip ".rel" extension */
1603           p = strrchr (scratchFileName, '.');
1604           if (p)
1605             {
1606               *p = 0;
1607             }
1608         }
1609       strncatz (scratchFileName,
1610                 options.out_fmt ? ".S19" : ".ihx",
1611                 sizeof(scratchFileName));
1612       if (strcmp (fullDstFileName, scratchFileName))
1613         unlink (fullDstFileName);
1614       rename (scratchFileName, fullDstFileName);
1615
1616       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1617       q = strrchr (buffer, '.');
1618       if (!q)
1619         {
1620           /* no extension: append new extensions */
1621           q = strlen (buffer) + buffer;
1622         }
1623
1624       *p = 0;
1625       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1626       *q = 0;
1627       strncatz(buffer, ".map", sizeof(buffer));
1628       if (strcmp (scratchFileName, buffer))
1629         unlink (buffer);
1630       rename (scratchFileName, buffer);
1631       *p = 0;
1632       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1633       *q = 0;
1634       strncatz(buffer, ".mem", sizeof(buffer));
1635       if (strcmp (scratchFileName, buffer))
1636         unlink (buffer);
1637       rename (scratchFileName, buffer);
1638       if (options.debug)
1639         {
1640           *p = 0;
1641           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1642           *q = 0;
1643           strncatz(buffer, ".cdb", sizeof(buffer));
1644           if (strcmp (scratchFileName, buffer))
1645             unlink (buffer);
1646           rename (scratchFileName, buffer);
1647           /* and the OMF file without extension: */
1648           *p = 0;
1649           *q = 0;
1650           if (strcmp (scratchFileName, buffer))
1651             unlink (buffer);
1652           rename (scratchFileName, buffer);
1653         }
1654     }
1655   if (system_ret)
1656     {
1657       exit (1);
1658     }
1659 }
1660
1661 /*-----------------------------------------------------------------*/
1662 /* assemble - spawns the assembler with arguments                  */
1663 /*-----------------------------------------------------------------*/
1664 static void
1665 assemble (char **envp)
1666 {
1667     /* build assembler output filename */
1668
1669     /* -o option overrides default name? */
1670     if (options.cc_only && fullDstFileName) {
1671         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1672     } else {
1673         /* the assembled file gets the name of the first modul */
1674         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1675         strncatz (scratchFileName, port->linker.rel_ext, 
1676                   sizeof(scratchFileName));
1677     }
1678
1679     if (port->assembler.do_assemble) {
1680         port->assembler.do_assemble(asmOptionsSet);
1681         return ;
1682     } else if (port->assembler.cmd) {
1683         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1684                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1685                       asmOptionsSet);
1686     } else {
1687         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1688     }
1689
1690     if (my_system (buffer)) {
1691         /* either system() or the assembler itself has reported an error
1692            perror ("Cannot exec assembler");
1693         */
1694         exit (1);
1695     }
1696     /* TODO: most assembler don't have a -o parameter */
1697     /* -o option overrides default name? */
1698     if (options.cc_only && fullDstFileName) {
1699         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1700         strncatz (scratchFileName, 
1701                   port->linker.rel_ext,
1702                   sizeof(scratchFileName));
1703         if (strcmp (scratchFileName, fullDstFileName))
1704           unlink (fullDstFileName);
1705         rename (scratchFileName, fullDstFileName);
1706     }
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* preProcess - spawns the preprocessor with arguments       */
1711 /*-----------------------------------------------------------------*/
1712 static int
1713 preProcess (char **envp)
1714 {
1715   if (options.c1mode)
1716     {
1717       yyin = stdin;
1718     }
1719   else
1720     {
1721       const char *s;
1722       set *inclList = NULL;
1723
1724       /* if using external stack define the macro */
1725       if (options.useXstack)
1726         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1727
1728       /* set the macro for stack autos  */
1729       if (options.stackAuto)
1730         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1731
1732       /* set the macro for stack autos  */
1733       if (options.stack10bit)
1734         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1735
1736       /* set the macro for no overlay  */
1737       if (options.noOverlay)
1738         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1739
1740       /* set the macro for large model  */
1741       switch (options.model)
1742         {
1743         case MODEL_LARGE:
1744           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1745           break;
1746         case MODEL_SMALL:
1747           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1748           break;
1749         case MODEL_COMPACT:
1750           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1751           break;
1752         case MODEL_MEDIUM:
1753           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1754           break;
1755         case MODEL_FLAT24:
1756           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1757           break;
1758         case MODEL_PAGE0:
1759           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1760           break;
1761         default:
1762           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1763           break;
1764         }
1765
1766       /* add port (processor information to processor */
1767       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1768       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1769
1770       /* standard include path */
1771       if (!options.nostdinc) {
1772         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1773         mergeSets(&preArgvSet, inclList);
1774       }
1775
1776       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1777       Safe_free((void *)s);
1778       if (inclList != NULL)
1779         deleteSet(&inclList);
1780
1781       if (preProcOnly && fullDstFileName)
1782         {
1783           /* -E and -o given */
1784           setMainValue ("cppoutfilename", fullDstFileName);
1785         }
1786       else
1787         {
1788           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1789           setMainValue ("cppoutfilename", NULL);
1790         }
1791
1792       if (options.verbose)
1793         printf ("sdcc: Calling preprocessor...\n");
1794
1795       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1796
1797       if (preProcOnly) {
1798         if (my_system (buffer)) {
1799           exit (1);
1800         }
1801
1802         exit (0);
1803       }
1804
1805       yyin = my_popen (buffer);
1806       if (yyin == NULL) {
1807           perror ("Preproc file not found");
1808           exit (1);
1809       }
1810       addSetHead (&pipeSet, yyin);
1811     }
1812
1813   return 0;
1814 }
1815
1816 /* Set bin paths */
1817 static void
1818 setBinPaths(const char *argv0)
1819 {
1820   char *p;
1821   char buf[PATH_MAX];
1822
1823   /*
1824    * Search logic:
1825    *
1826    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1827    * 2. - path(argv[0])
1828    * 3. - $PATH
1829    */
1830
1831   /* do it in reverse mode, so that addSetHead() can be used
1832      instead of slower addSet() */
1833
1834   if ((p = getBinPath(argv0)) != NULL)
1835     addSetHead(&binPathSet, Safe_strdup(p));
1836
1837   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1838     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1839     addSetHead(&binPathSet, Safe_strdup(buf));
1840   }
1841
1842   if (options.printSearchDirs) {
1843     printf("programs:\n");
1844     fputStrSet(stdout, binPathSet);
1845   }
1846 }
1847
1848 /* Set system include path */
1849 static void
1850 setIncludePath(void)
1851 {
1852   char *p;
1853
1854   /*
1855    * Search logic:
1856    *
1857    * 1. - $SDCC_INCLUDE
1858    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1859    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1860    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1861    */
1862
1863   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1864
1865   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1866     addSetHead(&includeDirsSet, p);
1867
1868   if (options.printSearchDirs) {
1869     printf("includedir:\n");
1870     fputStrSet(stdout, includeDirsSet);
1871   }
1872 }
1873
1874 /* Set system lib path */
1875 static void
1876 setLibPath(void)
1877 {
1878   char *p;
1879
1880   /*
1881    * Search logic:
1882    *
1883    * 1. - $SDCC_LIB
1884    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1885    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1886    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1887    */
1888
1889   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1890
1891   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1892     addSetHead(&libDirsSet, p);
1893
1894   if (options.printSearchDirs) {
1895     printf("libdir:\n");
1896     fputStrSet(stdout, libDirsSet);
1897   }
1898 }
1899
1900 /* Set data path */
1901 static void
1902 setDataPaths(const char *argv0)
1903 {
1904   char *p;
1905   char buf[PATH_MAX];
1906
1907   /*
1908    * Search logic:
1909    *
1910    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1911    * 2. - path(argv[0])/BIN2DATA_DIR
1912    * 3. - DATADIR (only on *nix)
1913    */
1914
1915   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1916     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1917     addSet(&dataDirsSet, Safe_strdup(buf));
1918   }
1919
1920   if ((p = getBinPath(argv0)) != NULL) {
1921     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1922     addSet(&dataDirsSet, Safe_strdup(buf));
1923   }
1924
1925 #ifdef _WIN32
1926   if (peekSet(dataDirsSet) == NULL) {
1927     /* this should never happen... */
1928     wassertl(0, "Can't get binary path");
1929   }
1930 #else
1931   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1932 #endif
1933
1934   if (options.printSearchDirs) {
1935     printf("datadir:\n");
1936     fputStrSet(stdout, dataDirsSet);
1937   }
1938
1939   setIncludePath();
1940   setLibPath();
1941 }
1942
1943 static void
1944 initValues (void)
1945 {
1946   populateMainValues (_baseValues);
1947   setMainValue ("port", port->target);
1948   setMainValue ("objext", port->linker.rel_ext);
1949   setMainValue ("asmext", port->assembler.file_ext);
1950
1951   setMainValue ("dstfilename", dstFileName);
1952   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1953
1954   if (options.cc_only && fullDstFileName)
1955     /* compile + assemble and -o given: -o specifies name of object file */
1956     {
1957       setMainValue ("objdstfilename", fullDstFileName);
1958     }
1959   else
1960     {
1961       setMainValue ("objdstfilename", "{stdobjdstfilename}");
1962     }
1963   if (fullDstFileName)
1964     /* if we're linking, -o gives the final file name */
1965     {
1966       setMainValue ("linkdstfilename", fullDstFileName);
1967     }
1968   else
1969     {
1970       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
1971     }
1972
1973 }
1974
1975 static void
1976 sig_handler (int signal)
1977 {
1978   char *sig_string;
1979
1980   switch (signal)
1981     {
1982     case SIGABRT:
1983       sig_string = "SIGABRT";
1984       break;
1985     case SIGTERM:
1986       sig_string = "SIGTERM";
1987       break;
1988     case SIGINT:
1989       sig_string = "SIGINT";
1990       break;
1991     case SIGSEGV:
1992       sig_string = "SIGSEGV";
1993       break;
1994     default:
1995       sig_string = "Unknown?";
1996       break;
1997     }
1998   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
1999   exit (1);
2000 }
2001
2002 /*
2003  * main routine
2004  * initialises and calls the parser
2005  */
2006
2007 int
2008 main (int argc, char **argv, char **envp)
2009 {
2010   /* turn all optimizations off by default */
2011   memset (&optimize, 0, sizeof (struct optimize));
2012
2013   /*printVersionInfo (); */
2014
2015   if (NUM_PORTS==0) {
2016     fprintf (stderr, "Build error: no ports are enabled.\n");
2017     exit (1);
2018   }
2019
2020   /* install atexit handler */
2021   atexit(rm_tmpfiles);
2022
2023   /* install signal handler;
2024      it's only purpuse is to call exit() to remove temp files */
2025   if (!getenv("SDCC_LEAVE_SIGNALS"))
2026     {
2027       signal (SIGABRT, sig_handler);
2028       signal (SIGTERM, sig_handler);
2029       signal (SIGINT , sig_handler);
2030       signal (SIGSEGV, sig_handler);
2031     }
2032
2033   /* Before parsing the command line options, do a
2034    * search for the port and processor and initialize
2035    * them if they're found. (We can't gurantee that these
2036    * will be the first options specified).
2037    */
2038
2039   _findPort (argc, argv);
2040
2041 #ifdef JAMIN_DS390
2042   if (strcmp(port->target, "mcs51") == 0) {
2043     printf("DS390 jammed in A\n");
2044           _setPort ("ds390");
2045     ds390_jammed = 1;
2046   }
2047 #endif
2048
2049   _findProcessor (argc, argv);
2050
2051   /* Initalise the port. */
2052   if (port->init)
2053     port->init ();
2054
2055   setDefaultOptions ();
2056 #ifdef JAMIN_DS390
2057   if (ds390_jammed) {
2058     options.model = MODEL_SMALL;
2059     options.stack10bit=0;
2060   }
2061 #endif
2062   parseCmdLine (argc, argv);
2063
2064   initValues ();
2065   setBinPaths(argv[0]);
2066   setDataPaths(argv[0]);
2067
2068   /* if no input then printUsage & exit */
2069   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2070     if (!options.printSearchDirs)
2071       printUsage();
2072
2073     exit(0);
2074   }
2075
2076   /* initMem() is expensive, but
2077      initMem() must called before port->finaliseOptions ().
2078      And the z80 port needs port->finaliseOptions(),
2079      even if we're only linking. */
2080   initMem ();
2081   port->finaliseOptions ();
2082
2083   if (fullSrcFileName || options.c1mode)
2084     {
2085       preProcess (envp);
2086
2087       initSymt ();
2088       initiCode ();
2089       initCSupport ();
2090       initBuiltIns();
2091       initPeepHole ();
2092
2093       if (options.verbose)
2094         printf ("sdcc: Generating code...\n");
2095
2096       yyparse ();
2097
2098       pclose(yyin);
2099       deleteSetItem(&pipeSet, yyin);
2100
2101       if (fatalError) {
2102         exit (1);
2103       }
2104
2105       if (port->general.do_glue != NULL)
2106         (*port->general.do_glue)();
2107       else
2108         {
2109           /* this shouldn't happen */
2110           assert(FALSE);
2111           /* in case of NDEBUG */
2112           glue();
2113         }
2114
2115       if (fatalError) {
2116         exit (1);
2117       }
2118
2119       if (!options.c1mode && !noAssemble)
2120         {
2121           if (options.verbose)
2122             printf ("sdcc: Calling assembler...\n");
2123           assemble (envp);
2124         }
2125     }
2126   closeDumpFiles();
2127
2128   if (options.debug && debugFile)
2129     debugFile->closeFile();
2130
2131   if (!options.cc_only &&
2132       !fatalError &&
2133       !noAssemble &&
2134       !options.c1mode &&
2135       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2136     {
2137       if (port->linker.do_link)
2138         port->linker.do_link ();
2139       else
2140         linkEdit (envp);
2141     }
2142
2143   return 0;
2144 }