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