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