Minor changes to fix up path seperators.
[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 #include "common.h"
26 #include <ctype.h>
27 #include "newalloc.h"
28 #include "SDCCerr.h"
29 #include "BuildCmd.h"
30 #include "MySystem.h"
31 #include "SDCCmacro.h"
32 #include "SDCCutil.h"
33
34 #if NATIVE_WIN32
35 #include <process.h>
36 #else
37 #include "spawn.h"
38 #endif
39
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #endif
44
45 /** Name of the environment variable checked for other instalations. */
46 #define SDCCDIR_NAME "SDCCDIR"
47
48 //REMOVE ME!!!
49 extern int yyparse ();
50
51 FILE *srcFile;                  /* source file          */
52 FILE *cdbFile = NULL;           /* debugger information output file */
53 char *fullSrcFileName;          /* full name for the source file */
54 char *srcFileName;              /* source file name with the .c stripped */
55 char *moduleName;               /* module name is srcFilename stripped of any path */
56 const char *preArgv[128];       /* pre-processor arguments  */
57 int currRegBank = 0;
58 struct optimize optimize;
59 struct options options;
60 char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a" */ ;
61 int preProcOnly = 0;
62 int noAssemble = 0;
63 char *linkOptions[128];
64 const char *asmOptions[128];
65 char *libFiles[128];
66 int nlibFiles = 0;
67 char *libPaths[128];
68 int nlibPaths = 0;
69 char *relFiles[128];
70 int nrelFiles = 0;
71 bool verboseExec = FALSE;
72 char *preOutName;
73
74 /* uncomment JAMIN_DS390 to always override and use ds390 port
75   for mcs51 work.  This is temporary, for compatibility testing. */
76 /* #define JAMIN_DS390 */
77 #ifdef JAMIN_DS390
78 int ds390_jammed = 0;
79 #endif
80
81 // Globally accessible scratch buffer for file names.
82 char scratchFileName[FILENAME_MAX];
83 char buffer[FILENAME_MAX];
84
85 // In MSC VC6 default search path for exe's to path for this
86
87 char DefaultExePath[128];
88
89 #define OPTION_HELP     "-help"
90
91 #define LENGTH(_a)      (sizeof(_a)/sizeof(*(_a)))
92
93 #define OPTION_STACK_8BIT       "--stack-8bit"
94 #define OPTION_OUT_FMT_IHX      "--out-fmt-ihx"
95 #define OPTION_LARGE_MODEL      "--model-large"
96 #define OPTION_MEDIUM_MODEL     "--model-medium"
97 #define OPTION_SMALL_MODEL      "--model-small"
98 #define OPTION_FLAT24_MODEL     "--model-flat24"
99 #define OPTION_DUMP_ALL         "--dumpall"
100 #define OPTION_PEEP_FILE        "--peep-file"
101 #define OPTION_LIB_PATH         "--lib-path"
102 #define OPTION_XSTACK_LOC       "--xstack-loc"
103 #define OPTION_CALLEE_SAVES     "--callee-saves"
104 #define OPTION_STACK_LOC        "--stack-loc"
105 #define OPTION_XRAM_LOC         "--xram-loc"
106 #define OPTION_IRAM_SIZE        "--iram-size"
107 #define OPTION_VERSION          "--version"
108 #define OPTION_DATA_LOC         "--data-loc"
109 #define OPTION_CODE_LOC         "--code-loc"
110 #define OPTION_IDATA_LOC        "--idata-loc"
111 #define OPTION_NO_LOOP_INV      "--noinvariant"
112 #define OPTION_NO_LOOP_IND      "--noinduction"
113 #define OPTION_LESS_PEDANTIC    "--lesspedantic"
114 #define OPTION_NO_GCSE          "--nogcse"
115 #define OPTION_SHORT_IS_8BITS   "--short-is-8bits"
116
117 /** Table of all options supported by all ports.
118     This table provides:
119       * A reference for all options.
120       * An easy way to maintain help for the options.
121       * Automatic support for setting flags on simple options.
122 */
123 typedef struct {
124     /** The short option character e.g. 'h' for -h.  0 for none. */
125     char shortOpt;
126     /** Long option e.g. "--help".  Includes the -- prefix.  NULL for
127         none. */
128     const char *longOpt;
129     /** Pointer to an int that will be incremented every time the
130         option is encountered.  May be NULL.
131     */
132     int *pparameter;
133     /** Help text to go with this option.  May be NULL. */
134     const char *help;
135 } OPTION;
136
137 static const OPTION 
138 optionsTable[] = {
139     { 'm',  NULL,                   NULL, "Set the port to use e.g. -mz80." },
140     { 'd',  NULL,                   NULL, NULL },
141     { 'D',  NULL,                   NULL, "Define macro as in -Dmacro" },
142     { 'I',  NULL,                   NULL, "Add to the include (*.h) path, as in -Ipath" },
143     { 'A',  NULL,                   NULL, NULL },
144     { 'U',  NULL,                   NULL, NULL },
145     { 'C',  NULL,                   NULL, "Preprocessor option" },
146     { 'M',  NULL,                   NULL, "Preprocessor option" },
147     { 'V',  NULL,                   &verboseExec, "Execute verbosely.  Show sub commands as they are run" },
148     { 'S',  NULL,                   &noAssemble, "Compile only; do not assemble or link" },
149     { 'W',  NULL,                   NULL, "Pass through options to the assembler (a) or linker (l)" },
150     { 'L',  NULL,                   NULL, "Add the next field to the library search path" },
151     { 'l',  NULL,                   NULL, "Include the given library in the link" },
152     { 0,    OPTION_LARGE_MODEL,     NULL, "external data space is used" },
153     { 0,    OPTION_MEDIUM_MODEL,    NULL, "not supported" },
154     { 0,    OPTION_SMALL_MODEL,     NULL, "internal data space is used (default)" },
155     { 0,    OPTION_FLAT24_MODEL,    NULL, "use the flat24 model for the ds390 (default)" },
156     { 0,    "--stack-auto",         &options.stackAuto, "Stack automatic variables" },
157     { 0,    OPTION_STACK_8BIT,      NULL, "use the 8bit stack for the ds390 (not supported yet)" },
158     { 0,    "--stack-10bit",        &options.stack10bit, "use the 10bit stack for ds390 (default)" },
159     { 0,    "--xstack",             &options.useXstack, "Use external stack" },
160     { 0,    "--generic",            &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
161     { 0,    OPTION_NO_GCSE,         NULL, "Disable the GCSE optimisation" },
162     { 0,    OPTION_NO_LOOP_INV,     NULL, "Disable optimisation of invariants" },
163     { 0,    OPTION_NO_LOOP_IND,     NULL, NULL },
164     { 0,    "--nojtbound",          &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
165     { 0,    "--noloopreverse",      &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
166     { 'c',  "--compile-only",       &options.cc_only, "Compile and assemble, but do not link" },
167     { 0,    "--dumpraw",            &options.dump_raw, "Dump the internal structure after the initial parse" },
168     { 0,    "--dumpgcse",           &options.dump_gcse, NULL },
169     { 0,    "--dumploop",           &options.dump_loop, NULL },
170     { 0,    "--dumpdeadcode",       &options.dump_kill, NULL },
171     { 0,    "--dumpliverange",      &options.dump_range, NULL },
172     { 0,    "--dumpregpack",        &options.dump_pack, NULL },
173     { 0,    "--dumpregassign",      &options.dump_rassgn, NULL },
174     { 0,    OPTION_DUMP_ALL,        NULL, "Dump the internal structure at all stages" },
175     { 0,    OPTION_XRAM_LOC,        NULL, "<nnnn> External Ram start location" },
176     { 0,    OPTION_IRAM_SIZE,       NULL, "<nnnn> Internal Ram size" },
177     { 0,    OPTION_XSTACK_LOC,      NULL, "<nnnn> External Ram start location" },
178     { 0,    OPTION_CODE_LOC,        NULL, "<nnnn> Code Segment Location" },
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 floar 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,    "--no-peep",            &options.nopeep, "Disable the peephole assembly file optimisation" },
192     { 0,    "--no-reg-params",      &options.noRegParams, "On some ports, disable passing some parameters in registers" },
193     { 0,    "--peep-asm",           &options.asmpeep, NULL },
194     { 0,    "--debug",              &options.debug, "Enable debugging symbol output" },
195     { 'v',  OPTION_VERSION,         NULL, "Display sdcc's version" },
196     { 0,    "--stack-after-data",   &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
197     { 'E',  "--preprocessonly",     &preProcOnly, "Preprocess only, do not compile" },
198     { 0,    "--c1mode",             &options.c1mode, "Act in c1 mode.  The 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 };
208
209 /** Table of all unsupported options and help text to display when one
210     is used.
211 */
212 typedef struct {
213     /** shortOpt as in OPTIONS. */
214     char shortOpt;
215     /** longOpt as in OPTIONS. */
216     const char *longOpt;
217     /** Message to display inside W_UNSUPPORTED_OPT when this option
218         is used. */
219     const char *message;
220 } UNSUPPORTEDOPT;
221
222 static const UNSUPPORTEDOPT 
223 unsupportedOptTable[] = {
224     { 'a',  NULL,       "use --stack-auto instead." },
225     { 'g',  NULL,       "use --generic instead" },
226     { 'X',  NULL,       "use --xstack-loc instead" },
227     { 'x',  NULL,       "use --xstack instead" },
228     { 'p',  NULL,       "use --stack-loc instead" },
229     { 'P',  NULL,       "use --stack-loc instead" },
230     { 'i',  NULL,       "use --idata-loc instead" },
231     { 'r',  NULL,       "use --xdata-loc instead" },
232     { 's',  NULL,       "use --code-loc instead" },
233     { 'Y',  NULL,       "use -I instead" }
234 };
235
236 /** List of all default constant macros.
237  */
238 static const char *_baseValues[] = {
239   "cpp", "{bindir}{sep}sdcpp",
240   "cppextraopts", "",
241   /* Path seperator character */
242   "sep", DIR_SEPARATOR_STRING,
243   NULL
244 };
245
246 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
247
248 PORT *port;
249
250 static PORT *_ports[] =
251 {
252 #if !OPT_DISABLE_MCS51
253   &mcs51_port,
254 #endif
255 #if !OPT_DISABLE_GBZ80
256   &gbz80_port,
257 #endif
258 #if !OPT_DISABLE_Z80
259   &z80_port,
260 #endif
261 #if !OPT_DISABLE_AVR
262   &avr_port,
263 #endif
264 #if !OPT_DISABLE_DS390
265   &ds390_port,
266 #endif
267 #if !OPT_DISABLE_PIC
268   &pic_port,
269 #endif
270 #if !OPT_DISABLE_I186
271   &i186_port,
272 #endif
273 #if !OPT_DISABLE_TLCS900H
274   &tlcs900h_port,
275 #endif
276 };
277
278 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
279
280 /**
281    remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
282  */
283 extern void picglue ();
284
285 /** Sets the port to the one given by the command line option.
286     @param    The name minus the option (eg 'mcs51')
287     @return     0 on success.
288 */
289 static void
290 _setPort (const char *name)
291 {
292   int i;
293   for (i = 0; i < NUM_PORTS; i++)
294     {
295       if (!strcmp (_ports[i]->target, name))
296         {
297           port = _ports[i];
298           return;
299         }
300     }
301   /* Error - didnt find */
302   werror (E_UNKNOWN_TARGET, name);
303   exit (1);
304 }
305
306 static void
307 _validatePorts (void)
308 {
309   int i;
310   for (i = 0; i < NUM_PORTS; i++)
311     {
312       if (_ports[i]->magic != PORT_MAGIC)
313         {
314           wassertl (0, "Port definition structure is incomplete");
315         }
316     }
317 }
318
319 static void
320 _findPort (int argc, char **argv)
321 {
322   _validatePorts ();
323
324   while (argc--)
325     {
326       if (!strncmp (*argv, "-m", 2))
327         {
328           _setPort (*argv + 2);
329           return;
330         }
331       argv++;
332     }
333   /* Use the first in the list */
334   port = _ports[0];
335 }
336
337 /*-----------------------------------------------------------------*/
338 /* printVersionInfo - prints the version info        */
339 /*-----------------------------------------------------------------*/
340 void
341 printVersionInfo ()
342 {
343   int i;
344
345   fprintf (stderr,
346            "SDCC : ");
347   for (i = 0; i < NUM_PORTS; i++)
348     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
349
350   fprintf (stderr, " %s"
351 #ifdef SDCC_SUB_VERSION_STR
352            "/" SDCC_SUB_VERSION_STR
353 #endif
354            " (" __DATE__ ")"
355 #ifdef __CYGWIN__
356            " (CYGWIN)\n"
357 #else
358 #ifdef __DJGPP__
359            " (DJGPP) \n"
360 #else
361 #if defined(_MSC_VER)
362            " (WIN32) \n"
363 #else
364            " (UNIX) \n"
365 #endif
366 #endif
367 #endif
368
369            ,VersionString
370     );
371 }
372
373 /*-----------------------------------------------------------------*/
374 /* printUsage - prints command line syntax         */
375 /*-----------------------------------------------------------------*/
376 void
377 printUsage ()
378 {
379     int i;
380     printVersionInfo();
381     fprintf (stdout,
382              "Usage : sdcc [options] filename\n"
383              "Options :-\n"
384              );
385     
386     for (i = 0; i < LENGTH(optionsTable); i++) {
387         fprintf(stdout, "  %c%c  %-20s  %s\n", 
388                 optionsTable[i].shortOpt !=0 ? '-' : ' ',
389                 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
390                 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
391                 optionsTable[i].help != NULL ? optionsTable[i].help : ""
392                 );
393     }
394     exit (0);
395 }
396
397 /*-----------------------------------------------------------------*/
398 /* parseWithComma - separates string with comma                    */
399 /*-----------------------------------------------------------------*/
400 void
401 parseWithComma (char **dest, char *src)
402 {
403   int i = 0;
404
405   strtok (src, "\r\n \t");
406   /* skip the initial white spaces */
407   while (isspace (*src))
408     src++;
409   dest[i++] = src;
410   while (*src)
411     {
412       if (*src == ',')
413         {
414           *src = '\0';
415           src++;
416           if (*src)
417             dest[i++] = src;
418           continue;
419         }
420       src++;
421     }
422 }
423
424 /*-----------------------------------------------------------------*/
425 /* setDefaultOptions - sets the default options                    */
426 /*-----------------------------------------------------------------*/
427 static void
428 setDefaultOptions ()
429 {
430   int i;
431
432   for (i = 0; i < 128; i++)
433     preArgv[i] = asmOptions[i] =
434       linkOptions[i] = relFiles[i] = libFiles[i] =
435       libPaths[i] = NULL;
436
437   /* first the options part */
438   options.stack_loc = 0;        /* stack pointer initialised to 0 */
439   options.xstack_loc = 0;       /* xternal stack starts at 0 */
440   options.code_loc = 0;         /* code starts at 0 */
441   options.data_loc = 0x0030;    /* data starts at 0x0030 */
442   options.xdata_loc = 0;
443   options.idata_loc = 0x80;
444   options.genericPtr = 1;       /* default on */
445   options.nopeep = 0;
446   options.model = port->general.default_model;
447   options.nostdlib = 0;
448   options.nostdinc = 0;
449   options.verbose = 0;
450   options.shortis8bits = 0;
451
452   options.stack10bit=0;
453
454   /* now for the optimizations */
455   /* turn on the everything */
456   optimize.global_cse = 1;
457   optimize.label1 = 1;
458   optimize.label2 = 1;
459   optimize.label3 = 1;
460   optimize.label4 = 1;
461   optimize.loopInvariant = 1;
462   optimize.loopInduction = 1;
463
464   /* now for the ports */
465   port->setDefaultOptions ();
466 }
467
468 /*-----------------------------------------------------------------*/
469 /* processFile - determines the type of file from the extension    */
470 /*-----------------------------------------------------------------*/
471 static void
472 processFile (char *s)
473 {
474   char *fext = NULL;
475
476   /* get the file extension */
477   fext = s + strlen (s);
478   while ((fext != s) && *fext != '.')
479     fext--;
480
481   /* now if no '.' then we don't know what the file type is
482      so give a warning and return */
483   if (fext == s)
484     {
485       werror (W_UNKNOWN_FEXT, s);
486       return;
487     }
488
489   /* otherwise depending on the file type */
490   if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
491     {
492       /* source file name : not if we already have a
493          source file */
494       if (srcFileName)
495         {
496           werror (W_TOO_MANY_SRC, s);
497           return;
498         }
499
500       /* the only source file */
501       if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
502         {
503           werror (E_FILE_OPEN_ERR, s);
504           exit (1);
505         }
506
507       /* copy the file name into the buffer */
508       strcpy (buffer, s);
509
510       /* get rid of the "." */
511       strtok (buffer, ".");
512       srcFileName = Safe_calloc (1, strlen (buffer) + 1);
513       strcpy (srcFileName, buffer);
514
515       /* get rid of any path information
516          for the module name; do this by going
517          backwards till we get to either '/' or '\' or ':'
518          or start of buffer */
519       fext = buffer + strlen (buffer);
520       while (fext != buffer &&
521              *(fext - 1) != '\\' &&
522              *(fext - 1) != '/' &&
523              *(fext - 1) != ':')
524         fext--;
525       moduleName = Safe_calloc (1, strlen (fext) + 1);
526       strcpy (moduleName, fext);
527
528       return;
529     }
530
531   /* if the extention is type .rel or .r or .REL or .R
532      addtional object file will be passed to the linker */
533   if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
534       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
535       strcmp (fext, port->linker.rel_ext) == 0)
536     {
537       relFiles[nrelFiles++] = s;
538       return;
539     }
540
541   /* if .lib or .LIB */
542   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
543     {
544       libFiles[nlibFiles++] = s;
545       return;
546     }
547
548   werror (W_UNKNOWN_FEXT, s);
549
550 }
551
552 static void
553 _processC1Arg (char *s)
554 {
555   if (srcFileName)
556     {
557       if (options.out_name)
558         {
559           werror (W_TOO_MANY_SRC, s);
560           return;
561         }
562       options.out_name = strdup (s);
563     }
564   else
565     {
566       processFile (s);
567     }
568 }
569
570 static void
571 _setModel (int model, const char *sz)
572 {
573   if (port->general.supported_models & model)
574     options.model = model;
575   else
576     werror (W_UNSUPPORTED_MODEL, sz, port->target);
577 }
578
579 /** Gets the string argument to this option.  If the option is '--opt'
580     then for input of '--optxyz' or '--opt xyz' returns xyz.
581 */
582 static char *
583 getStringArg(const char *szStart, char **argv, int *pi, int argc)
584 {
585   if (argv[*pi][strlen(szStart)]) 
586     {
587       return &argv[*pi][strlen(szStart)];
588     }
589   else 
590     {
591       ++(*pi);
592       if (*pi >= argc) 
593         {
594           werror (E_ARGUMENT_MISSING, szStart);
595           /* Die here rather than checking for errors later. */
596           exit(-1);
597         }
598       else 
599         {
600           return argv[*pi];
601         }
602     }
603 }
604
605 /** Gets the integer argument to this option using the same rules as
606     getStringArg. 
607 */
608 static int
609 getIntArg(const char *szStart, char **argv, int *pi, int argc)
610 {
611     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
612 }
613
614 static void
615 verifyShortOption(const char *opt)
616 {
617   if (strlen(opt) != 2)
618     {
619       werror (W_EXCESS_SHORT_OPTIONS, opt);
620     }
621 }
622
623 static bool
624 tryHandleUnsupportedOpt(char **argv, int *pi)
625 {
626     if (argv[*pi][0] == '-') 
627         {
628             const char *longOpt = "";
629             char shortOpt = -1;
630             int i;
631
632             if (argv[*pi][1] == '-') 
633                 {
634                     // Long option.
635                     longOpt = argv[*pi];
636                 }
637             else 
638                 {
639                     shortOpt = argv[*pi][1];
640                 }
641             for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
642                 {
643                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
644                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
645                         // Found an unsupported opt.
646                         char buffer[100];
647                         sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
648                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
649                         return 1;
650                     }
651                 }
652             // Didn't find in the table
653             return 0;
654         }
655     else 
656         {
657             // Not an option, so can't be unsupported :)
658             return 0;
659     }
660 }
661
662 static bool
663 tryHandleSimpleOpt(char **argv, int *pi)
664 {
665     if (argv[*pi][0] == '-') 
666         {
667             const char *longOpt = "";
668             char shortOpt = -1;
669             int i;
670
671             if (argv[*pi][1] == '-') 
672                 {
673                     // Long option.
674                     longOpt = argv[*pi];
675                 }
676             else 
677                 {
678                     shortOpt = argv[*pi][1];
679                 }
680
681             for (i = 0; i < LENGTH(optionsTable); i++) 
682               {
683                 if (optionsTable[i].shortOpt == shortOpt ||
684                     (longOpt && optionsTable[i].longOpt && 
685                      strcmp(optionsTable[i].longOpt, longOpt) == 0))
686                   {
687
688                     // If it is a flag then we can handle it here
689                     if (optionsTable[i].pparameter != NULL) 
690                       {
691                         if (optionsTable[i].shortOpt == shortOpt)
692                           {
693                             verifyShortOption(argv[*pi]);
694                           }
695
696                         (*optionsTable[i].pparameter)++;
697                         return 1;
698                       }
699                     else {
700                       // Not a flag.  Handled manually later.
701                       return 0;
702                     }
703                   }
704               }
705             // Didn't find in the table
706             return 0;
707         }
708     else 
709         {
710             // Not an option, so can't be handled.
711             return 0;
712         }
713 }
714
715 /*-----------------------------------------------------------------*/
716 /* parseCmdLine - parses the command line and sets the options     */
717 /*-----------------------------------------------------------------*/
718 int
719 parseCmdLine (int argc, char **argv)
720 {
721   int i;
722
723   /* go thru all whole command line */
724   for (i = 1; i < argc; i++)
725     {
726       if (i >= argc)
727         break;
728
729       if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
730           {
731               continue;
732           }
733
734       if (tryHandleSimpleOpt(argv, &i) == TRUE)
735           {
736               continue;
737           }
738
739       /* options */
740       if (argv[i][0] == '-' && argv[i][1] == '-')
741         {
742           if (strcmp (argv[i], OPTION_HELP) == 0)
743             {
744               printUsage ();
745               exit (0);
746             }
747
748           if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
749             {
750               options.stack10bit = 0;
751               continue;
752             }
753
754           if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
755             {
756               options.out_fmt = 0;
757               continue;
758             }
759
760           if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
761             {
762               _setModel (MODEL_LARGE, argv[i]);
763               continue;
764             }
765
766           if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
767             {
768               _setModel (MODEL_MEDIUM, argv[i]);
769               continue;
770             }
771
772           if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
773             {
774               _setModel (MODEL_SMALL, argv[i]);
775               continue;
776             }
777
778           if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
779             {
780               _setModel (MODEL_FLAT24, argv[i]);
781               continue;
782             }
783
784           if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
785             {
786               options.dump_rassgn =
787                 options.dump_pack =
788                 options.dump_range =
789                 options.dump_kill =
790                 options.dump_loop =
791                 options.dump_gcse =
792                 options.dump_raw = 1;
793               continue;
794             }
795
796           if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
797             {
798                 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
799                 continue;
800             }
801
802           if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
803             {
804                 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
805                 continue;
806             }
807
808           if (strcmp (argv[i], OPTION_VERSION) == 0)
809             {
810               printVersionInfo ();
811               exit (0);
812               continue;
813             }
814
815           if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
816             {
817                 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
818                 continue;
819             }
820
821           if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
822             {
823                 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
824                 continue;
825             }
826
827           if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
828             {
829                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
830                 continue;
831             }
832
833           if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
834             {
835                 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
836                 continue;
837             }
838
839           if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
840             {
841                 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
842                 continue;
843             }
844
845           if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
846             {
847                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
848                 continue;
849             }
850
851           if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
852             {
853                 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
854                 continue;
855             }
856
857           if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
858             {
859                 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
860                 continue;
861             }
862
863           if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
864             {
865               optimize.global_cse = 0;
866               continue;
867             }
868
869           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
870             {
871               optimize.loopInvariant = 0;
872               continue;
873             }
874
875           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
876             {
877               optimize.loopInduction = 0;
878               continue;
879             }
880
881           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
882             {
883               options.lessPedantic = 1;
884               setErrorLogLevel(ERROR_LEVEL_WARNING);
885               continue;
886             }
887
888           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
889             {
890               options.shortis8bits=1;
891               continue;
892             }
893           
894           if (!port->parseOption (&argc, argv, &i))
895             {
896               werror (W_UNKNOWN_OPTION, argv[i]);
897             }
898           else
899             {
900               continue;
901             }
902         }
903
904       /* if preceded by  '-' then option */
905       if (*argv[i] == '-')
906         {
907           switch (argv[i][1])
908             {
909             case 'h':
910               verifyShortOption(argv[i]);
911
912               printUsage ();
913               exit (0);
914               break;
915
916             case 'm':
917               /* Used to select the port */
918               _setPort (argv[i] + 2);
919               break;
920
921             case 'c':
922               verifyShortOption(argv[i]);
923
924               options.cc_only = 1;
925               break;
926
927             case 'L':
928                 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
929                 break;
930
931             case 'l':
932                 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
933                 break;
934
935             case 'W':
936               /* linker options */
937               if (argv[i][2] == 'l')
938                 {
939                     parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
940                 }
941               else
942                 {
943                   /* assembler options */
944                   if (argv[i][2] == 'a')
945                     {
946                         parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
947                     }
948                   else
949                     {
950                       werror (W_UNKNOWN_OPTION, argv[i]);
951                     }
952                 }
953               break;
954
955             case 'v':
956               verifyShortOption(argv[i]);
957
958               printVersionInfo ();
959               exit (0);
960               break;
961
962               /* preprocessor options */
963             case 'M':
964               {
965                 preProcOnly = 1;
966                 addToList (preArgv, "-M");
967                 break;
968               }
969             case 'C':
970               {
971                 addToList (preArgv, "-C");
972                 break;
973               }
974             case 'd':
975             case 'D':
976             case 'I':
977             case 'A':
978             case 'U':
979               {
980                 char sOpt = argv[i][1];
981                 char *rest;
982
983                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
984                   {
985                     i++;
986                     if (i >= argc) 
987                       {
988                           /* No argument. */
989                           werror(E_ARGUMENT_MISSING, argv[i-1]);
990                           break;
991                       }
992                     else 
993                       {
994                           rest = argv[i];
995                       }
996                   }
997                 else
998                   rest = &argv[i][2];
999
1000                 if (sOpt == 'Y')
1001                   sOpt = 'I';
1002
1003                 sprintf (buffer, "-%c%s", sOpt, rest);
1004                 addToList (preArgv, buffer);
1005               }
1006               break;
1007
1008             default:
1009               if (!port->parseOption (&argc, argv, &i))
1010                 werror (W_UNKNOWN_OPTION, argv[i]);
1011             }
1012           continue;
1013         }
1014
1015       if (!port->parseOption (&argc, argv, &i))
1016         {
1017           /* no option must be a filename */
1018           if (options.c1mode)
1019             _processC1Arg (argv[i]);
1020           else
1021             processFile (argv[i]);
1022         }
1023     }
1024
1025   /* set up external stack location if not explicitly specified */
1026   if (!options.xstack_loc)
1027     options.xstack_loc = options.xdata_loc;
1028
1029   /* if debug option is set the open the cdbFile */
1030   if (options.debug && srcFileName)
1031     {
1032       sprintf (scratchFileName, "%s.cdb", srcFileName);
1033       if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1034         werror (E_FILE_OPEN_ERR, scratchFileName);
1035       else
1036         {
1037           /* add a module record */
1038           fprintf (cdbFile, "M:%s\n", moduleName);
1039         }
1040     }
1041   return 0;
1042 }
1043
1044 /*-----------------------------------------------------------------*/
1045 /* linkEdit : - calls the linkage editor  with options             */
1046 /*-----------------------------------------------------------------*/
1047 static void
1048 linkEdit (char **envp)
1049 {
1050   FILE *lnkfile;
1051   char *segName, *c;
1052
1053   int i;
1054   if (!srcFileName)
1055     srcFileName = "temp";
1056
1057   /* first we need to create the <filename>.lnk file */
1058   sprintf (scratchFileName, "%s.lnk", srcFileName);
1059   if (!(lnkfile = fopen (scratchFileName, "w")))
1060     {
1061       werror (E_FILE_OPEN_ERR, scratchFileName);
1062       exit (1);
1063     }
1064
1065   /* now write the options */
1066   fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1067
1068   /* if iram size specified */
1069   if (options.iram_size)
1070     fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1071
1072   if (options.debug)
1073     fprintf (lnkfile, "-z\n");
1074
1075 #define WRITE_SEG_LOC(N, L) \
1076     segName = strdup(N); \
1077     c = strtok(segName, " \t"); \
1078     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1079     if (segName) { free(segName); }
1080
1081   /* code segment start */
1082   WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1083
1084   /* data segment start */
1085   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1086
1087   /* xdata start */
1088   WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1089
1090   /* indirect data */
1091   WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1092
1093   /* bit segment start */
1094   WRITE_SEG_LOC (BIT_NAME, 0);
1095
1096   /* add the extra linker options */
1097   for (i = 0; linkOptions[i]; i++)
1098     fprintf (lnkfile, "%s\n", linkOptions[i]);
1099
1100   /* other library paths if specified */
1101   for (i = 0; i < nlibPaths; i++)
1102     fprintf (lnkfile, "-k %s\n", libPaths[i]);
1103
1104   /* standard library path */
1105   if (!options.nostdlib)
1106     {
1107 /****
1108       if (TARGET_IS_DS390)
1109         {
1110           c = "ds390";
1111         }
1112       else
1113 *****/
1114         {
1115           switch (options.model)
1116             {
1117             case MODEL_SMALL:
1118               c = "small";
1119               break;
1120             case MODEL_LARGE:
1121               c = "large";
1122               break;
1123             case MODEL_FLAT24:
1124               /* c = "flat24"; */
1125               c = "ds390";
1126               break;
1127             default:
1128               werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1129               c = "unknown";
1130               break;
1131             }
1132         }
1133       fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1134
1135       /* standard library files */
1136       /* if (strcmp (port->target, "ds390") == 0) */
1137       if (options.model == MODEL_FLAT24)
1138         {
1139           fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1140         }
1141       fprintf (lnkfile, "-l %s\n", STD_LIB);
1142       fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1143       fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1144       fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1145     }
1146
1147   /* additional libraries if any */
1148   for (i = 0; i < nlibFiles; i++)
1149     fprintf (lnkfile, "-l %s\n", libFiles[i]);
1150
1151   /* put in the object files */
1152   if (strcmp (srcFileName, "temp"))
1153     fprintf (lnkfile, "%s ", srcFileName);
1154
1155   for (i = 0; i < nrelFiles; i++)
1156     fprintf (lnkfile, "%s\n", relFiles[i]);
1157
1158   fprintf (lnkfile, "\n-e\n");
1159   fclose (lnkfile);
1160
1161   if (options.verbose)
1162     printf ("sdcc: Calling linker...\n");
1163
1164   if (port->linker.cmd)
1165     {
1166       buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1167     }
1168   else
1169     {
1170       buildCmdLine2 (buffer, port->linker.mcmd);
1171     }
1172
1173   if (my_system (buffer))
1174     {
1175       exit (1);
1176     }
1177
1178   if (strcmp (srcFileName, "temp") == 0)
1179     {
1180       /* rename "temp.cdb" to "firstRelFile.cdb" */
1181       char *f = strtok (strdup (relFiles[0]), ".");
1182       f = strcat (f, ".cdb");
1183       rename ("temp.cdb", f);
1184       srcFileName = NULL;
1185     }
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* assemble - spawns the assembler with arguments                  */
1190 /*-----------------------------------------------------------------*/
1191 static void
1192 assemble (char **envp)
1193 {
1194   if (port->assembler.cmd)
1195     {
1196       buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1197     }
1198   else
1199     {
1200       buildCmdLine2 (buffer, port->assembler.mcmd);
1201     }
1202
1203   if (my_system (buffer))
1204     {
1205       /* either system() or the assembler itself has reported an error
1206          perror ("Cannot exec assembler");
1207        */
1208       exit (1);
1209     }
1210 }
1211
1212 /*-----------------------------------------------------------------*/
1213 /* preProcess - spawns the preprocessor with arguments       */
1214 /*-----------------------------------------------------------------*/
1215 static int
1216 preProcess (char **envp)
1217 {
1218   preOutName = NULL;
1219
1220   if (!options.c1mode)
1221     {
1222       /* if using external stack define the macro */
1223       if (options.useXstack)
1224         addToList (preArgv, "-DSDCC_USE_XSTACK");
1225
1226       /* set the macro for stack autos  */
1227       if (options.stackAuto)
1228         addToList (preArgv, "-DSDCC_STACK_AUTO");
1229
1230       /* set the macro for stack autos  */
1231       if (options.stack10bit)
1232         addToList (preArgv, "-DSDCC_STACK_TENBIT");
1233
1234       /* set the macro for large model  */
1235       switch (options.model)
1236         {
1237         case MODEL_LARGE:
1238           addToList (preArgv, "-DSDCC_MODEL_LARGE");
1239           break;
1240         case MODEL_SMALL:
1241           addToList (preArgv, "-DSDCC_MODEL_SMALL");
1242           break;
1243         case MODEL_COMPACT:
1244           addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1245           break;
1246         case MODEL_MEDIUM:
1247           addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1248           break;
1249         case MODEL_FLAT24:
1250           addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1251           break;
1252         default:
1253           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1254           break;
1255         }
1256
1257       /* add port (processor information to processor */
1258       addToList (preArgv, "-DSDCC_{port}");
1259       addToList (preArgv, "-D__{port}");
1260
1261       /* standard include path */
1262       if (!options.nostdinc) {
1263         addToList (preArgv, "-I{includedir}");
1264       }
1265
1266       setMainValue ("cppextraopts", join(preArgv));
1267       
1268       if (!preProcOnly)
1269         preOutName = strdup (tmpnam (NULL));
1270
1271       setMainValue ("cppoutfilename", preOutName);
1272
1273       if (options.verbose)
1274         printf ("sdcc: Calling preprocessor...\n");
1275
1276       buildCmdLine2 (buffer, _preCmd);
1277
1278       if (my_system (buffer))
1279         {
1280           // @FIX: Dario Vecchio 03-05-2001
1281           if (preOutName)
1282             {
1283               unlink (preOutName);
1284               free (preOutName);
1285             }
1286           // EndFix
1287           exit (1);
1288         }
1289
1290       if (preProcOnly)
1291       {
1292         exit (0);
1293       }
1294     }
1295   else
1296     {
1297       preOutName = fullSrcFileName;
1298     }
1299
1300   yyin = fopen (preOutName, "r");
1301   if (yyin == NULL)
1302     {
1303       perror ("Preproc file not found\n");
1304       exit (1);
1305     }
1306
1307   return 0;
1308 }
1309
1310 static bool
1311 _setPaths (const char *pprefix)
1312 {
1313   /* Logic:
1314       Given the prefix and how the directories were layed out at
1315       configure time, see if the library and include directories are
1316       where expected.  If so, set.
1317   */
1318   getStringDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1319   strcpy (scratchFileName, pprefix);
1320   strcat (scratchFileName, buffer);
1321
1322   if (pathExists (scratchFileName))
1323     {
1324       setMainValue ("includedir", scratchFileName);
1325     }
1326   else
1327     {
1328       return FALSE;
1329     }
1330
1331   getStringDifference (buffer, PREFIX, SDCC_LIB_DIR);
1332   strcpy (scratchFileName, pprefix);
1333   strcat (scratchFileName, buffer);
1334
1335   if (pathExists (scratchFileName))
1336     {
1337       setMainValue ("libdir", scratchFileName);
1338     }
1339   else
1340     {
1341       return FALSE;
1342     }
1343
1344   return TRUE;
1345 }
1346
1347 static void
1348 _discoverPaths (const char *argv0)
1349 {
1350   /* Logic:
1351       1.  Try the SDCCDIR environment variable.
1352       2.  If (1) fails, and if the argv[0] includes a path, attempt to find the include
1353       and library paths with respect to that.  Note that under win32
1354       argv[0] is always the full path to the program.
1355       3.  If (1) and (2) fail, fall back to the compile time defaults.
1356
1357       Detecting assumes the same layout as when configured.  If the
1358       directories have been further moved about then discovery will
1359       fail.
1360   */
1361
1362   /* Some input cases:
1363         "c:\fish\sdcc\bin\sdcc"
1364         "../bin/sdcc"
1365         "/home/fish/bin/sdcc"
1366
1367       Note that ./sdcc is explicitly not supported as there isn't
1368       enough information.
1369   */
1370   /* bindir is handled differently to the lib and include directories.
1371      It's rather unfortunate, but required due to the different
1372      install and development layouts.  Logic is different as well.
1373      Sigh.
1374    */
1375   if (strchr (argv0, DIR_SEPARATOR_CHAR))
1376     {
1377       strcpy (scratchFileName, argv0);
1378       *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1379       setMainValue ("bindir", scratchFileName);
1380       ExePathList[0] = gc_strdup (scratchFileName);
1381     }
1382   else if (getenv (SDCCDIR_NAME) != NULL)
1383     {
1384       getStringDifference (buffer, PREFIX, BINDIR);
1385       strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1386       strcat (scratchFileName, buffer);
1387       setMainValue ("bindir", scratchFileName);
1388       ExePathList[0] = gc_strdup (scratchFileName);
1389     }
1390   else
1391     {
1392       setMainValue ("bindir", BINDIR);
1393       ExePathList[0] = BINDIR;
1394     }
1395
1396   do 
1397     {
1398       /* Case 1 */
1399       if (getenv (SDCCDIR_NAME) != NULL)
1400         {
1401           if (_setPaths (getenv (SDCCDIR_NAME)))
1402             {
1403               /* Successfully set. */
1404               break;
1405             }
1406           else
1407             {
1408               /* Include and lib wern't where expected. */
1409             }
1410         }
1411       /* Case 2 */
1412       if (strchr (argv0, DIR_SEPARATOR_CHAR))
1413         {
1414           char *pbase = getPrefixFromBinPath (argv0);
1415
1416           if (pbase == NULL)
1417             {
1418               /* A bad path.  Skip. */
1419             }
1420           else
1421             {
1422               if (_setPaths (pbase))
1423                 {
1424                   /* Successfully set. */
1425                   break;
1426                 }
1427               else
1428                 {
1429                   /* Include and lib weren't where expected. */
1430                 }
1431             }
1432         }
1433       /* Case 3 */
1434       setMainValue ("includedir", SDCC_INCLUDE_DIR);
1435       setMainValue ("libdir", SDCC_LIB_DIR);
1436     } while (0);
1437 }
1438
1439 static void
1440 initValues (void)
1441 {
1442   populateMainValues (_baseValues);
1443   setMainValue ("port", port->target);
1444   setMainValue ("fullsrcfilename", fullSrcFileName);
1445   setMainValue ("srcfilename", srcFileName);
1446   setMainValue ("objext", port->linker.rel_ext);
1447   setMainValue ("asmext", port->assembler.file_ext);
1448 }
1449
1450 /*
1451  * main routine
1452  * initialises and calls the parser
1453  */
1454
1455 int
1456 main (int argc, char **argv, char **envp)
1457 {
1458   /* turn all optimizations off by default */
1459   memset (&optimize, 0, sizeof (struct optimize));
1460
1461   /*printVersionInfo (); */
1462
1463   if (NUM_PORTS==0) {
1464     fprintf (stderr, "Build error: no ports are enabled.\n");
1465     exit (1);
1466   }
1467
1468   _findPort (argc, argv);
1469 #ifdef JAMIN_DS390
1470   if (strcmp(port->target, "mcs51") == 0) {
1471     printf("DS390 jammed in A\n");
1472           _setPort ("ds390");
1473     ds390_jammed = 1;
1474   }
1475 #endif
1476   /* Initalise the port. */
1477   if (port->init)
1478     port->init ();
1479
1480   // Create a default exe search path from the path to the sdcc command
1481
1482
1483   setDefaultOptions ();
1484 #ifdef JAMIN_DS390
1485   if (ds390_jammed) {
1486     options.model = MODEL_SMALL;
1487     options.stack10bit=0;
1488   }
1489 #endif
1490   parseCmdLine (argc, argv);
1491
1492   /* if no input then printUsage & exit */
1493   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
1494       (options.c1mode && !srcFileName && !options.out_name))
1495     {
1496       printUsage ();
1497       exit (0);
1498     }
1499
1500   if (srcFileName)
1501     {
1502       initValues ();
1503       _discoverPaths (argv[0]);
1504
1505       preProcess (envp);
1506
1507       initMem ();
1508
1509       port->finaliseOptions ();
1510
1511       initSymt ();
1512       initiCode ();
1513       initCSupport ();
1514       initPeepHole ();
1515
1516       if (options.verbose)
1517         printf ("sdcc: Generating code...\n");
1518
1519       yyparse ();
1520
1521       if (!fatalError)
1522         {
1523           if (TARGET_IS_PIC) {
1524             /* TSD PIC port hack - if the PIC port option is enabled
1525                and SDCC is used to generate PIC code, then we will
1526                generate .asm files in gpasm's format instead of SDCC's
1527                assembler's format
1528             */
1529 #if !OPT_DISABLE_PIC
1530             picglue ();
1531 #endif
1532           } else {
1533             glue ();
1534           }
1535
1536           if (fatalError)
1537             {
1538               // @FIX: Dario Vecchio 03-05-2001
1539               if (preOutName)
1540                 {
1541                   if (yyin && yyin != stdin)
1542                     fclose (yyin);
1543                   unlink (preOutName);
1544                   free (preOutName);
1545                 }
1546               // EndFix
1547               return 1;
1548             }
1549           if (!options.c1mode && !noAssemble)
1550             {
1551               if (options.verbose)
1552                 printf ("sdcc: Calling assembler...\n");
1553               assemble (envp);
1554             }
1555         }
1556       else
1557         {
1558           // @FIX: Dario Vecchio 03-05-2001
1559           if (preOutName)
1560             {
1561               if (yyin && yyin != stdin)
1562                 fclose (yyin);
1563               unlink (preOutName);
1564               free (preOutName);
1565             }
1566           // EndFix
1567           #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1568           rm_tmpfiles();
1569           #endif
1570           return 1;
1571         }
1572
1573     }
1574
1575   closeDumpFiles();
1576
1577   if (cdbFile)
1578     fclose (cdbFile);
1579
1580   if (preOutName && !options.c1mode)
1581     {
1582       unlink (preOutName);
1583       free (preOutName);
1584     }
1585
1586   if (!options.cc_only &&
1587       !fatalError &&
1588       !noAssemble &&
1589       !options.c1mode &&
1590       (srcFileName || nrelFiles))
1591     {
1592       if (port->linker.do_link)
1593         port->linker.do_link ();
1594       else
1595         linkEdit (envp);
1596     }
1597
1598   if (yyin && yyin != stdin)
1599     fclose (yyin);
1600
1601   return 0;
1602
1603 }