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