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