"Fix" of compiler crash
[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       {
1270         preOutName = strdup (tmpnam (NULL));
1271
1272         setMainValue ("cppoutfilename", preOutName);
1273       }
1274       else
1275         setMainValue ("cppoutfilename", "notexistent_fixme");   // Fix me!
1276         
1277       if (options.verbose)
1278         printf ("sdcc: Calling preprocessor...\n");
1279
1280       buildCmdLine2 (buffer, _preCmd);
1281
1282       if (my_system (buffer))
1283         {
1284           // @FIX: Dario Vecchio 03-05-2001
1285           if (preOutName)
1286             {
1287               unlink (preOutName);
1288               free (preOutName);
1289             }
1290           // EndFix
1291           exit (1);
1292         }
1293
1294       if (preProcOnly)
1295       {
1296         exit (0);
1297       }
1298     }
1299   else
1300     {
1301       preOutName = fullSrcFileName;
1302     }
1303
1304   yyin = fopen (preOutName, "r");
1305   if (yyin == NULL)
1306     {
1307       perror ("Preproc file not found\n");
1308       exit (1);
1309     }
1310
1311   return 0;
1312 }
1313
1314 static bool
1315 _setPaths (const char *pprefix)
1316 {
1317   /* Logic:
1318       Given the prefix and how the directories were layed out at
1319       configure time, see if the library and include directories are
1320       where expected.  If so, set.
1321   */
1322   getStringDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1323   strcpy (scratchFileName, pprefix);
1324   strcat (scratchFileName, buffer);
1325
1326   if (pathExists (scratchFileName))
1327     {
1328       setMainValue ("includedir", scratchFileName);
1329     }
1330   else
1331     {
1332       return FALSE;
1333     }
1334
1335   getStringDifference (buffer, PREFIX, SDCC_LIB_DIR);
1336   strcpy (scratchFileName, pprefix);
1337   strcat (scratchFileName, buffer);
1338
1339   if (pathExists (scratchFileName))
1340     {
1341       setMainValue ("libdir", scratchFileName);
1342     }
1343   else
1344     {
1345       return FALSE;
1346     }
1347
1348   return TRUE;
1349 }
1350
1351 static void
1352 _discoverPaths (const char *argv0)
1353 {
1354   /* Logic:
1355       1.  Try the SDCCDIR environment variable.
1356       2.  If (1) fails, and if the argv[0] includes a path, attempt to find the include
1357       and library paths with respect to that.  Note that under win32
1358       argv[0] is always the full path to the program.
1359       3.  If (1) and (2) fail, fall back to the compile time defaults.
1360
1361       Detecting assumes the same layout as when configured.  If the
1362       directories have been further moved about then discovery will
1363       fail.
1364   */
1365
1366   /* Some input cases:
1367         "c:\fish\sdcc\bin\sdcc"
1368         "../bin/sdcc"
1369         "/home/fish/bin/sdcc"
1370
1371       Note that ./sdcc is explicitly not supported as there isn't
1372       enough information.
1373   */
1374   /* bindir is handled differently to the lib and include directories.
1375      It's rather unfortunate, but required due to the different
1376      install and development layouts.  Logic is different as well.
1377      Sigh.
1378    */
1379   if (strchr (argv0, DIR_SEPARATOR_CHAR))
1380     {
1381       strcpy (scratchFileName, argv0);
1382       *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1383       setMainValue ("bindir", scratchFileName);
1384       ExePathList[0] = gc_strdup (scratchFileName);
1385     }
1386   else if (getenv (SDCCDIR_NAME) != NULL)
1387     {
1388       getStringDifference (buffer, PREFIX, BINDIR);
1389       strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1390       strcat (scratchFileName, buffer);
1391       setMainValue ("bindir", scratchFileName);
1392       ExePathList[0] = gc_strdup (scratchFileName);
1393     }
1394   else
1395     {
1396       setMainValue ("bindir", BINDIR);
1397       ExePathList[0] = BINDIR;
1398     }
1399
1400   do 
1401     {
1402       /* Case 1 */
1403       if (getenv (SDCCDIR_NAME) != NULL)
1404         {
1405           if (_setPaths (getenv (SDCCDIR_NAME)))
1406             {
1407               /* Successfully set. */
1408               break;
1409             }
1410           else
1411             {
1412               /* Include and lib wern't where expected. */
1413             }
1414         }
1415       /* Case 2 */
1416       if (strchr (argv0, DIR_SEPARATOR_CHAR))
1417         {
1418           char *pbase = getPrefixFromBinPath (argv0);
1419
1420           if (pbase == NULL)
1421             {
1422               /* A bad path.  Skip. */
1423             }
1424           else
1425             {
1426               if (_setPaths (pbase))
1427                 {
1428                   /* Successfully set. */
1429                   break;
1430                 }
1431               else
1432                 {
1433                   /* Include and lib weren't where expected. */
1434                 }
1435             }
1436         }
1437       /* Case 3 */
1438       setMainValue ("includedir", SDCC_INCLUDE_DIR);
1439       setMainValue ("libdir", SDCC_LIB_DIR);
1440     } while (0);
1441 }
1442
1443 static void
1444 initValues (void)
1445 {
1446   populateMainValues (_baseValues);
1447   setMainValue ("port", port->target);
1448   setMainValue ("fullsrcfilename", fullSrcFileName);
1449   setMainValue ("srcfilename", srcFileName);
1450   setMainValue ("objext", port->linker.rel_ext);
1451   setMainValue ("asmext", port->assembler.file_ext);
1452 }
1453
1454 /*
1455  * main routine
1456  * initialises and calls the parser
1457  */
1458
1459 int
1460 main (int argc, char **argv, char **envp)
1461 {
1462   /* turn all optimizations off by default */
1463   memset (&optimize, 0, sizeof (struct optimize));
1464
1465   /*printVersionInfo (); */
1466
1467   if (NUM_PORTS==0) {
1468     fprintf (stderr, "Build error: no ports are enabled.\n");
1469     exit (1);
1470   }
1471
1472   _findPort (argc, argv);
1473 #ifdef JAMIN_DS390
1474   if (strcmp(port->target, "mcs51") == 0) {
1475     printf("DS390 jammed in A\n");
1476           _setPort ("ds390");
1477     ds390_jammed = 1;
1478   }
1479 #endif
1480   /* Initalise the port. */
1481   if (port->init)
1482     port->init ();
1483
1484   // Create a default exe search path from the path to the sdcc command
1485
1486
1487   setDefaultOptions ();
1488 #ifdef JAMIN_DS390
1489   if (ds390_jammed) {
1490     options.model = MODEL_SMALL;
1491     options.stack10bit=0;
1492   }
1493 #endif
1494   parseCmdLine (argc, argv);
1495
1496   /* if no input then printUsage & exit */
1497   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
1498       (options.c1mode && !srcFileName && !options.out_name))
1499     {
1500       printUsage ();
1501       exit (0);
1502     }
1503
1504   if (srcFileName)
1505     {
1506       initValues ();
1507       _discoverPaths (argv[0]);
1508
1509       preProcess (envp);
1510
1511       initMem ();
1512
1513       port->finaliseOptions ();
1514
1515       initSymt ();
1516       initiCode ();
1517       initCSupport ();
1518       initPeepHole ();
1519
1520       if (options.verbose)
1521         printf ("sdcc: Generating code...\n");
1522
1523       yyparse ();
1524
1525       if (!fatalError)
1526         {
1527           if (TARGET_IS_PIC) {
1528             /* TSD PIC port hack - if the PIC port option is enabled
1529                and SDCC is used to generate PIC code, then we will
1530                generate .asm files in gpasm's format instead of SDCC's
1531                assembler's format
1532             */
1533 #if !OPT_DISABLE_PIC
1534             picglue ();
1535 #endif
1536           } else {
1537             glue ();
1538           }
1539
1540           if (fatalError)
1541             {
1542               // @FIX: Dario Vecchio 03-05-2001
1543               if (preOutName)
1544                 {
1545                   if (yyin && yyin != stdin)
1546                     fclose (yyin);
1547                   unlink (preOutName);
1548                   free (preOutName);
1549                 }
1550               // EndFix
1551               return 1;
1552             }
1553           if (!options.c1mode && !noAssemble)
1554             {
1555               if (options.verbose)
1556                 printf ("sdcc: Calling assembler...\n");
1557               assemble (envp);
1558             }
1559         }
1560       else
1561         {
1562           // @FIX: Dario Vecchio 03-05-2001
1563           if (preOutName)
1564             {
1565               if (yyin && yyin != stdin)
1566                 fclose (yyin);
1567               unlink (preOutName);
1568               free (preOutName);
1569             }
1570           // EndFix
1571           #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1572           rm_tmpfiles();
1573           #endif
1574           return 1;
1575         }
1576
1577     }
1578
1579   closeDumpFiles();
1580
1581   if (cdbFile)
1582     fclose (cdbFile);
1583
1584   if (preOutName && !options.c1mode)
1585     {
1586       unlink (preOutName);
1587       free (preOutName);
1588     }
1589
1590   if (!options.cc_only &&
1591       !fatalError &&
1592       !noAssemble &&
1593       !options.c1mode &&
1594       (srcFileName || nrelFiles))
1595     {
1596       if (port->linker.do_link)
1597         port->linker.do_link ();
1598       else
1599         linkEdit (envp);
1600     }
1601
1602   if (yyin && yyin != stdin)
1603     fclose (yyin);
1604
1605   return 0;
1606
1607 }