* support/Util/NewAlloc.c (freeTrace): Changed free for the gc case to not free...
[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_alloc ( 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_alloc ( 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 = Safe_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 = Safe_strdup(N); \
1077     c = strtok(segName, " \t"); \
1078     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1079     if (segName) { Safe_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 (Safe_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,
1197                     options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1198                     asmOptions);
1199     }
1200   else
1201     {
1202       buildCmdLine2 (buffer, port->assembler.mcmd);
1203     }
1204
1205   if (my_system (buffer))
1206     {
1207       /* either system() or the assembler itself has reported an error
1208          perror ("Cannot exec assembler");
1209        */
1210       exit (1);
1211     }
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* preProcess - spawns the preprocessor with arguments       */
1216 /*-----------------------------------------------------------------*/
1217 static int
1218 preProcess (char **envp)
1219 {
1220   preOutName = NULL;
1221
1222   if (!options.c1mode)
1223     {
1224       /* if using external stack define the macro */
1225       if (options.useXstack)
1226         addToList (preArgv, "-DSDCC_USE_XSTACK");
1227
1228       /* set the macro for stack autos  */
1229       if (options.stackAuto)
1230         addToList (preArgv, "-DSDCC_STACK_AUTO");
1231
1232       /* set the macro for stack autos  */
1233       if (options.stack10bit)
1234         addToList (preArgv, "-DSDCC_STACK_TENBIT");
1235
1236       /* set the macro for large model  */
1237       switch (options.model)
1238         {
1239         case MODEL_LARGE:
1240           addToList (preArgv, "-DSDCC_MODEL_LARGE");
1241           break;
1242         case MODEL_SMALL:
1243           addToList (preArgv, "-DSDCC_MODEL_SMALL");
1244           break;
1245         case MODEL_COMPACT:
1246           addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1247           break;
1248         case MODEL_MEDIUM:
1249           addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1250           break;
1251         case MODEL_FLAT24:
1252           addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1253           break;
1254         default:
1255           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1256           break;
1257         }
1258
1259       /* add port (processor information to processor */
1260       addToList (preArgv, "-DSDCC_{port}");
1261       addToList (preArgv, "-D__{port}");
1262
1263       /* standard include path */
1264       if (!options.nostdinc) {
1265         addToList (preArgv, "-I{includedir}");
1266       }
1267
1268       setMainValue ("cppextraopts", join(preArgv));
1269       
1270       if (!preProcOnly)
1271           preOutName = Safe_strdup (tempfilename ());
1272
1273       /* Have to set cppoutfilename to something, even if just pre-processing. */
1274       setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1275         
1276       if (options.verbose)
1277         printf ("sdcc: Calling preprocessor...\n");
1278
1279       buildCmdLine2 (buffer, _preCmd);
1280
1281       if (my_system (buffer))
1282         {
1283           // @FIX: Dario Vecchio 03-05-2001
1284           if (preOutName)
1285             {
1286               unlink (preOutName);
1287               Safe_free (preOutName);
1288             }
1289           // EndFix
1290           exit (1);
1291         }
1292
1293       if (preProcOnly)
1294       {
1295         exit (0);
1296       }
1297     }
1298   else
1299     {
1300       preOutName = fullSrcFileName;
1301     }
1302
1303   yyin = fopen (preOutName, "r");
1304   if (yyin == NULL)
1305     {
1306       perror ("Preproc file not found\n");
1307       exit (1);
1308     }
1309
1310   return 0;
1311 }
1312
1313 static bool
1314 _setPaths (const char *pprefix)
1315 {
1316   /* Logic:
1317       Given the prefix and how the directories were layed out at
1318       configure time, see if the library and include directories are
1319       where expected.  If so, set.
1320   */
1321   getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1322   strcpy (scratchFileName, pprefix);
1323   strcat (scratchFileName, buffer);
1324
1325   if (pathExists (scratchFileName))
1326     {
1327       setMainValue ("includedir", scratchFileName);
1328     }
1329   else
1330     {
1331       return FALSE;
1332     }
1333
1334   getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1335   strcpy (scratchFileName, pprefix);
1336   strcat (scratchFileName, buffer);
1337
1338   if (pathExists (scratchFileName))
1339     {
1340       setMainValue ("libdir", scratchFileName);
1341     }
1342   else
1343     {
1344       return FALSE;
1345     }
1346
1347   return TRUE;
1348 }
1349
1350 static void
1351 _discoverPaths (const char *argv0)
1352 {
1353   /* Logic:
1354       1.  Try the SDCCDIR environment variable.
1355       2.  If (1) fails, and if the argv[0] includes a path, attempt to find the include
1356       and library paths with respect to that.  Note that under win32
1357       argv[0] is always the full path to the program.
1358       3.  If (1) and (2) fail, fall back to the compile time defaults.
1359
1360       Detecting assumes the same layout as when configured.  If the
1361       directories have been further moved about then discovery will
1362       fail.
1363   */
1364
1365   /* Some input cases:
1366         "c:\fish\sdcc\bin\sdcc"
1367         "../bin/sdcc"
1368         "/home/fish/bin/sdcc"
1369
1370       Note that ./sdcc is explicitly not supported as there isn't
1371       enough information.
1372   */
1373   /* bindir is handled differently to the lib and include directories.
1374      It's rather unfortunate, but required due to the different
1375      install and development layouts.  Logic is different as well.
1376      Sigh.
1377    */
1378   if (strchr (argv0, DIR_SEPARATOR_CHAR))
1379     {
1380       strcpy (scratchFileName, argv0);
1381       *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1382       setMainValue ("bindir", scratchFileName);
1383       ExePathList[0] = Safe_strdup (scratchFileName);
1384     }
1385   else if (getenv (SDCCDIR_NAME) != NULL)
1386     {
1387       getPathDifference (buffer, PREFIX, BINDIR);
1388       strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1389       strcat (scratchFileName, buffer);
1390       setMainValue ("bindir", scratchFileName);
1391       ExePathList[0] = Safe_strdup (scratchFileName);
1392     }
1393   else
1394     {
1395       setMainValue ("bindir", BINDIR);
1396       ExePathList[0] = BINDIR;
1397     }
1398
1399   do 
1400     {
1401       /* Case 1 */
1402       if (getenv (SDCCDIR_NAME) != NULL)
1403         {
1404           if (_setPaths (getenv (SDCCDIR_NAME)))
1405             {
1406               /* Successfully set. */
1407               break;
1408             }
1409           else
1410             {
1411               /* Include and lib weren't where expected. */
1412             }
1413         }
1414       /* Case 2 */
1415       if (strchr (argv0, DIR_SEPARATOR_CHAR))
1416         {
1417           char *pbase = getPrefixFromBinPath (argv0);
1418
1419           if (pbase == NULL)
1420             {
1421               /* A bad path.  Skip. */
1422             }
1423           else
1424             {
1425               if (_setPaths (pbase))
1426                 {
1427                   /* Successfully set. */
1428                   break;
1429                 }
1430               else
1431                 {
1432                   /* Include and lib weren't where expected. */
1433                 }
1434             }
1435         }
1436       /* Case 3 */
1437       setMainValue ("includedir", SDCC_INCLUDE_DIR);
1438       setMainValue ("libdir", SDCC_LIB_DIR);
1439     } while (0);
1440 }
1441
1442 static void
1443 initValues (void)
1444 {
1445   populateMainValues (_baseValues);
1446   setMainValue ("port", port->target);
1447   setMainValue ("fullsrcfilename", fullSrcFileName);
1448   setMainValue ("srcfilename", srcFileName);
1449   setMainValue ("objext", port->linker.rel_ext);
1450   setMainValue ("asmext", port->assembler.file_ext);
1451 }
1452
1453 /*
1454  * main routine
1455  * initialises and calls the parser
1456  */
1457
1458 int
1459 main (int argc, char **argv, char **envp)
1460 {
1461   /* turn all optimizations off by default */
1462   memset (&optimize, 0, sizeof (struct optimize));
1463
1464   /*printVersionInfo (); */
1465
1466   if (NUM_PORTS==0) {
1467     fprintf (stderr, "Build error: no ports are enabled.\n");
1468     exit (1);
1469   }
1470
1471   _findPort (argc, argv);
1472 #ifdef JAMIN_DS390
1473   if (strcmp(port->target, "mcs51") == 0) {
1474     printf("DS390 jammed in A\n");
1475           _setPort ("ds390");
1476     ds390_jammed = 1;
1477   }
1478 #endif
1479   /* Initalise the port. */
1480   if (port->init)
1481     port->init ();
1482
1483   // Create a default exe search path from the path to the sdcc command
1484
1485
1486   setDefaultOptions ();
1487 #ifdef JAMIN_DS390
1488   if (ds390_jammed) {
1489     options.model = MODEL_SMALL;
1490     options.stack10bit=0;
1491   }
1492 #endif
1493   parseCmdLine (argc, argv);
1494
1495   /* if no input then printUsage & exit */
1496   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
1497       (options.c1mode && !srcFileName && !options.out_name))
1498     {
1499       printUsage ();
1500       exit (0);
1501     }
1502
1503   if (srcFileName)
1504     {
1505       initValues ();
1506       _discoverPaths (argv[0]);
1507
1508       preProcess (envp);
1509
1510       initMem ();
1511
1512       port->finaliseOptions ();
1513
1514       initSymt ();
1515       initiCode ();
1516       initCSupport ();
1517       initPeepHole ();
1518
1519       if (options.verbose)
1520         printf ("sdcc: Generating code...\n");
1521
1522       yyparse ();
1523
1524       if (!fatalError)
1525         {
1526           if (TARGET_IS_PIC) {
1527             /* TSD PIC port hack - if the PIC port option is enabled
1528                and SDCC is used to generate PIC code, then we will
1529                generate .asm files in gpasm's format instead of SDCC's
1530                assembler's format
1531             */
1532 #if !OPT_DISABLE_PIC
1533             picglue ();
1534 #endif
1535           } else {
1536             glue ();
1537           }
1538
1539           if (fatalError)
1540             {
1541               // @FIX: Dario Vecchio 03-05-2001
1542               if (preOutName)
1543                 {
1544                   if (yyin && yyin != stdin)
1545                     fclose (yyin);
1546                   unlink (preOutName);
1547                   Safe_free (preOutName);
1548                 }
1549               // EndFix
1550               return 1;
1551             }
1552           if (!options.c1mode && !noAssemble)
1553             {
1554               if (options.verbose)
1555                 printf ("sdcc: Calling assembler...\n");
1556               assemble (envp);
1557             }
1558         }
1559       else
1560         {
1561           // @FIX: Dario Vecchio 03-05-2001
1562           if (preOutName)
1563             {
1564               if (yyin && yyin != stdin)
1565                 fclose (yyin);
1566               unlink (preOutName);
1567               Safe_free (preOutName);
1568             }
1569           // EndFix
1570           #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1571           rm_tmpfiles();
1572           #endif
1573           return 1;
1574         }
1575
1576     }
1577
1578   closeDumpFiles();
1579
1580   if (cdbFile)
1581     fclose (cdbFile);
1582
1583   if (preOutName && !options.c1mode)
1584     {
1585       unlink (preOutName);
1586       Safe_free (preOutName);
1587     }
1588
1589   if (!options.cc_only &&
1590       !fatalError &&
1591       !noAssemble &&
1592       !options.c1mode &&
1593       (srcFileName || nrelFiles))
1594     {
1595       if (port->linker.do_link)
1596         port->linker.do_link ();
1597       else
1598         linkEdit (envp);
1599     }
1600
1601   if (yyin && yyin != stdin)
1602     fclose (yyin);
1603
1604   return 0;
1605
1606 }