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