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