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