* src/SDCCmain.c (linkEdit): Added runtime path detection to the mcs51 port.
[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 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               /* linker options */
939               if (argv[i][2] == 'l')
940                 {
941                     parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
942                 }
943               else
944                 {
945                   /* assembler options */
946                   if (argv[i][2] == 'a')
947                     {
948                         parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
949                     }
950                   else
951                     {
952                       werror (W_UNKNOWN_OPTION, argv[i]);
953                     }
954                 }
955               break;
956
957             case 'v':
958               verifyShortOption(argv[i]);
959
960               printVersionInfo ();
961               exit (0);
962               break;
963
964               /* preprocessor options */
965             case 'M':
966               {
967                 preProcOnly = 1;
968                 addToList (preArgv, "-M");
969                 break;
970               }
971             case 'C':
972               {
973                 addToList (preArgv, "-C");
974                 break;
975               }
976             case 'd':
977             case 'D':
978             case 'I':
979             case 'A':
980             case 'U':
981               {
982                 char sOpt = argv[i][1];
983                 char *rest;
984
985                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
986                   {
987                     i++;
988                     if (i >= argc) 
989                       {
990                           /* No argument. */
991                           werror(E_ARGUMENT_MISSING, argv[i-1]);
992                           break;
993                       }
994                     else 
995                       {
996                           rest = argv[i];
997                       }
998                   }
999                 else
1000                   rest = &argv[i][2];
1001
1002                 if (sOpt == 'Y')
1003                   sOpt = 'I';
1004
1005                 sprintf (buffer, "-%c%s", sOpt, rest);
1006                 addToList (preArgv, buffer);
1007               }
1008               break;
1009
1010             default:
1011               if (!port->parseOption (&argc, argv, &i))
1012                 werror (W_UNKNOWN_OPTION, argv[i]);
1013             }
1014           continue;
1015         }
1016
1017       if (!port->parseOption (&argc, argv, &i))
1018         {
1019           /* no option must be a filename */
1020           if (options.c1mode)
1021             _processC1Arg (argv[i]);
1022           else
1023             processFile (argv[i]);
1024         }
1025     }
1026
1027   /* set up external stack location if not explicitly specified */
1028   if (!options.xstack_loc)
1029     options.xstack_loc = options.xdata_loc;
1030
1031   /* if debug option is set the open the cdbFile */
1032   if (options.debug && srcFileName)
1033     {
1034       sprintf (scratchFileName, "%s.cdb", srcFileName);
1035       if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1036         werror (E_FILE_OPEN_ERR, scratchFileName);
1037       else
1038         {
1039           /* add a module record */
1040           fprintf (cdbFile, "M:%s\n", moduleName);
1041         }
1042     }
1043   return 0;
1044 }
1045
1046 /*-----------------------------------------------------------------*/
1047 /* linkEdit : - calls the linkage editor  with options             */
1048 /*-----------------------------------------------------------------*/
1049 static void
1050 linkEdit (char **envp)
1051 {
1052   FILE *lnkfile;
1053   char *segName, *c;
1054
1055   int i;
1056   if (!srcFileName)
1057     srcFileName = "temp";
1058
1059   /* first we need to create the <filename>.lnk file */
1060   sprintf (scratchFileName, "%s.lnk", srcFileName);
1061   if (!(lnkfile = fopen (scratchFileName, "w")))
1062     {
1063       werror (E_FILE_OPEN_ERR, scratchFileName);
1064       exit (1);
1065     }
1066
1067   /* now write the options */
1068   fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1069
1070   /* if iram size specified */
1071   if (options.iram_size)
1072     fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1073
1074   if (options.debug)
1075     fprintf (lnkfile, "-z\n");
1076
1077 #define WRITE_SEG_LOC(N, L) \
1078     segName = Safe_strdup(N); \
1079     c = strtok(segName, " \t"); \
1080     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1081     if (segName) { Safe_free(segName); }
1082
1083   /* code segment start */
1084   WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1085
1086   /* data segment start */
1087   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1088
1089   /* xdata start */
1090   WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1091
1092   /* indirect data */
1093   WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1094
1095   /* bit segment start */
1096   WRITE_SEG_LOC (BIT_NAME, 0);
1097
1098   /* add the extra linker options */
1099   for (i = 0; linkOptions[i]; i++)
1100     fprintf (lnkfile, "%s\n", linkOptions[i]);
1101
1102   /* other library paths if specified */
1103   for (i = 0; i < nlibPaths; i++)
1104     fprintf (lnkfile, "-k %s\n", libPaths[i]);
1105
1106   /* standard library path */
1107   if (!options.nostdlib)
1108     {
1109 /****
1110       if (TARGET_IS_DS390)
1111         {
1112           c = "ds390";
1113         }
1114       else
1115 *****/
1116         {
1117           switch (options.model)
1118             {
1119             case MODEL_SMALL:
1120               c = "small";
1121               break;
1122             case MODEL_LARGE:
1123               c = "large";
1124               break;
1125             case MODEL_FLAT24:
1126               /* c = "flat24"; */
1127               c = "ds390";
1128               break;
1129             default:
1130               werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1131               c = "unknown";
1132               break;
1133             }
1134         }
1135       mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1136
1137       /* standard library files */
1138       /* if (strcmp (port->target, "ds390") == 0) */
1139       if (options.model == MODEL_FLAT24)
1140         {
1141           fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1142         }
1143       fprintf (lnkfile, "-l %s\n", STD_LIB);
1144       fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1145       fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1146       fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1147     }
1148
1149   /* additional libraries if any */
1150   for (i = 0; i < nlibFiles; i++)
1151     fprintf (lnkfile, "-l %s\n", libFiles[i]);
1152
1153   /* put in the object files */
1154   if (strcmp (srcFileName, "temp"))
1155     fprintf (lnkfile, "%s ", srcFileName);
1156
1157   for (i = 0; i < nrelFiles; i++)
1158     fprintf (lnkfile, "%s\n", relFiles[i]);
1159
1160   fprintf (lnkfile, "\n-e\n");
1161   fclose (lnkfile);
1162
1163   if (options.verbose)
1164     printf ("sdcc: Calling linker...\n");
1165
1166   if (port->linker.cmd)
1167     {
1168       char buffer2[PATH_MAX];
1169       buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1170       buildCmdLine2 (buffer, buffer2);
1171     }
1172   else
1173     {
1174       buildCmdLine2 (buffer, port->linker.mcmd);
1175     }
1176
1177   if (my_system (buffer))
1178     {
1179       exit (1);
1180     }
1181
1182   if (strcmp (srcFileName, "temp") == 0)
1183     {
1184       /* rename "temp.cdb" to "firstRelFile.cdb" */
1185       char *f = strtok (Safe_strdup (relFiles[0]), ".");
1186       f = strcat (f, ".cdb");
1187       rename ("temp.cdb", f);
1188       srcFileName = NULL;
1189     }
1190 }
1191
1192 /*-----------------------------------------------------------------*/
1193 /* assemble - spawns the assembler with arguments                  */
1194 /*-----------------------------------------------------------------*/
1195 static void
1196 assemble (char **envp)
1197 {
1198   if (port->assembler.cmd)
1199     {
1200       buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1201                     options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1202                     asmOptions);
1203     }
1204   else
1205     {
1206       buildCmdLine2 (buffer, port->assembler.mcmd);
1207     }
1208
1209   if (my_system (buffer))
1210     {
1211       /* either system() or the assembler itself has reported an error
1212          perror ("Cannot exec assembler");
1213        */
1214       exit (1);
1215     }
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* preProcess - spawns the preprocessor with arguments       */
1220 /*-----------------------------------------------------------------*/
1221 static int
1222 preProcess (char **envp)
1223 {
1224   preOutName = NULL;
1225
1226   if (!options.c1mode)
1227     {
1228       /* if using external stack define the macro */
1229       if (options.useXstack)
1230         addToList (preArgv, "-DSDCC_USE_XSTACK");
1231
1232       /* set the macro for stack autos  */
1233       if (options.stackAuto)
1234         addToList (preArgv, "-DSDCC_STACK_AUTO");
1235
1236       /* set the macro for stack autos  */
1237       if (options.stack10bit)
1238         addToList (preArgv, "-DSDCC_STACK_TENBIT");
1239
1240       /* set the macro for no overlay  */
1241       if (options.noOverlay)
1242         addToList (preArgv, "-DSDCC_NOOVERLAY");
1243
1244       /* set the macro for large model  */
1245       switch (options.model)
1246         {
1247         case MODEL_LARGE:
1248           addToList (preArgv, "-DSDCC_MODEL_LARGE");
1249           break;
1250         case MODEL_SMALL:
1251           addToList (preArgv, "-DSDCC_MODEL_SMALL");
1252           break;
1253         case MODEL_COMPACT:
1254           addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1255           break;
1256         case MODEL_MEDIUM:
1257           addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1258           break;
1259         case MODEL_FLAT24:
1260           addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1261           break;
1262         default:
1263           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1264           break;
1265         }
1266
1267       /* add port (processor information to processor */
1268       addToList (preArgv, "-DSDCC_{port}");
1269       addToList (preArgv, "-D__{port}");
1270
1271       /* standard include path */
1272       if (!options.nostdinc) {
1273         addToList (preArgv, "-I{includedir}");
1274       }
1275
1276       setMainValue ("cppextraopts", join(preArgv));
1277       
1278       if (!preProcOnly)
1279           preOutName = Safe_strdup (tempfilename ());
1280
1281       /* Have to set cppoutfilename to something, even if just pre-processing. */
1282       setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1283         
1284       if (options.verbose)
1285         printf ("sdcc: Calling preprocessor...\n");
1286
1287       buildCmdLine2 (buffer, _preCmd);
1288
1289       if (my_system (buffer))
1290         {
1291           // @FIX: Dario Vecchio 03-05-2001
1292           if (preOutName)
1293             {
1294               unlink (preOutName);
1295               Safe_free (preOutName);
1296             }
1297           // EndFix
1298           exit (1);
1299         }
1300
1301       if (preProcOnly)
1302       {
1303         exit (0);
1304       }
1305     }
1306   else
1307     {
1308       preOutName = fullSrcFileName;
1309     }
1310
1311   yyin = fopen (preOutName, "r");
1312   if (yyin == NULL)
1313     {
1314       perror ("Preproc file not found\n");
1315       exit (1);
1316     }
1317
1318   return 0;
1319 }
1320
1321 static bool
1322 _setPaths (const char *pprefix)
1323 {
1324   /* Logic:
1325       Given the prefix and how the directories were layed out at
1326       configure time, see if the library and include directories are
1327       where expected.  If so, set.
1328   */
1329   getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1330   strcpy (scratchFileName, pprefix);
1331   strcat (scratchFileName, buffer);
1332
1333   if (pathExists (scratchFileName))
1334     {
1335       setMainValue ("includedir", scratchFileName);
1336     }
1337   else
1338     {
1339       return FALSE;
1340     }
1341
1342   getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1343   strcpy (scratchFileName, pprefix);
1344   strcat (scratchFileName, buffer);
1345
1346   if (pathExists (scratchFileName))
1347     {
1348       setMainValue ("libdir", scratchFileName);
1349     }
1350   else
1351     {
1352       return FALSE;
1353     }
1354
1355   return TRUE;
1356 }
1357
1358 static void
1359 _discoverPaths (const char *argv0)
1360 {
1361   /* Logic:
1362       1.  Try the SDCCDIR environment variable.
1363       2.  If (1) fails, and if the argv[0] includes a path, attempt to find the include
1364       and library paths with respect to that.  Note that under win32
1365       argv[0] is always the full path to the program.
1366       3.  If (1) and (2) fail, fall back to the compile time defaults.
1367
1368       Detecting assumes the same layout as when configured.  If the
1369       directories have been further moved about then discovery will
1370       fail.
1371   */
1372
1373   /* Some input cases:
1374         "c:\fish\sdcc\bin\sdcc"
1375         "../bin/sdcc"
1376         "/home/fish/bin/sdcc"
1377
1378       Note that ./sdcc is explicitly not supported as there isn't
1379       enough information.
1380   */
1381   /* bindir is handled differently to the lib and include directories.
1382      It's rather unfortunate, but required due to the different
1383      install and development layouts.  Logic is different as well.
1384      Sigh.
1385    */
1386   if (strchr (argv0, DIR_SEPARATOR_CHAR))
1387     {
1388       strcpy (scratchFileName, argv0);
1389       *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1390       setMainValue ("bindir", scratchFileName);
1391       ExePathList[0] = Safe_strdup (scratchFileName);
1392     }
1393   else if (getenv (SDCCDIR_NAME) != NULL)
1394     {
1395       getPathDifference (buffer, PREFIX, BINDIR);
1396       strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1397       strcat (scratchFileName, buffer);
1398       setMainValue ("bindir", scratchFileName);
1399       ExePathList[0] = Safe_strdup (scratchFileName);
1400     }
1401   else
1402     {
1403       setMainValue ("bindir", BINDIR);
1404       ExePathList[0] = BINDIR;
1405     }
1406
1407   do 
1408     {
1409       /* Case 1 */
1410       if (getenv (SDCCDIR_NAME) != NULL)
1411         {
1412           if (_setPaths (getenv (SDCCDIR_NAME)))
1413             {
1414               /* Successfully set. */
1415               break;
1416             }
1417           else
1418             {
1419               /* Include and lib weren't where expected. */
1420             }
1421         }
1422       /* Case 2 */
1423       if (strchr (argv0, DIR_SEPARATOR_CHAR))
1424         {
1425           char *pbase = getPrefixFromBinPath (argv0);
1426
1427           if (pbase == NULL)
1428             {
1429               /* A bad path.  Skip. */
1430             }
1431           else
1432             {
1433               if (_setPaths (pbase))
1434                 {
1435                   /* Successfully set. */
1436                   break;
1437                 }
1438               else
1439                 {
1440                   /* Include and lib weren't where expected. */
1441                 }
1442             }
1443         }
1444       /* Case 3 */
1445       setMainValue ("includedir", SDCC_INCLUDE_DIR);
1446       setMainValue ("libdir", SDCC_LIB_DIR);
1447     } while (0);
1448 }
1449
1450 static void
1451 initValues (void)
1452 {
1453   populateMainValues (_baseValues);
1454   setMainValue ("port", port->target);
1455   setMainValue ("objext", port->linker.rel_ext);
1456   setMainValue ("asmext", port->assembler.file_ext);
1457
1458   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1459   setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1460 }
1461
1462 /*
1463  * main routine
1464  * initialises and calls the parser
1465  */
1466
1467 int
1468 main (int argc, char **argv, char **envp)
1469 {
1470   /* turn all optimizations off by default */
1471   memset (&optimize, 0, sizeof (struct optimize));
1472
1473   /*printVersionInfo (); */
1474
1475   if (NUM_PORTS==0) {
1476     fprintf (stderr, "Build error: no ports are enabled.\n");
1477     exit (1);
1478   }
1479
1480   _findPort (argc, argv);
1481 #ifdef JAMIN_DS390
1482   if (strcmp(port->target, "mcs51") == 0) {
1483     printf("DS390 jammed in A\n");
1484           _setPort ("ds390");
1485     ds390_jammed = 1;
1486   }
1487 #endif
1488   /* Initalise the port. */
1489   if (port->init)
1490     port->init ();
1491
1492   // Create a default exe search path from the path to the sdcc command
1493
1494
1495   setDefaultOptions ();
1496 #ifdef JAMIN_DS390
1497   if (ds390_jammed) {
1498     options.model = MODEL_SMALL;
1499     options.stack10bit=0;
1500   }
1501 #endif
1502   parseCmdLine (argc, argv);
1503
1504   /* if no input then printUsage & exit */
1505   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
1506       (options.c1mode && !srcFileName && !options.out_name))
1507     {
1508       printUsage ();
1509       exit (0);
1510     }
1511
1512   initValues ();
1513   _discoverPaths (argv[0]);
1514
1515   if (srcFileName)
1516     {
1517       preProcess (envp);
1518
1519       initMem ();
1520
1521       port->finaliseOptions ();
1522
1523       initSymt ();
1524       initiCode ();
1525       initCSupport ();
1526       initPeepHole ();
1527
1528       if (options.verbose)
1529         printf ("sdcc: Generating code...\n");
1530
1531       yyparse ();
1532
1533       if (!fatalError)
1534         {
1535           if (TARGET_IS_PIC) {
1536             /* TSD PIC port hack - if the PIC port option is enabled
1537                and SDCC is used to generate PIC code, then we will
1538                generate .asm files in gpasm's format instead of SDCC's
1539                assembler's format
1540             */
1541 #if !OPT_DISABLE_PIC
1542             picglue ();
1543 #endif
1544           } else {
1545             glue ();
1546           }
1547
1548           if (fatalError)
1549             {
1550               // @FIX: Dario Vecchio 03-05-2001
1551               if (preOutName)
1552                 {
1553                   if (yyin && yyin != stdin)
1554                     fclose (yyin);
1555                   unlink (preOutName);
1556                   Safe_free (preOutName);
1557                 }
1558               // EndFix
1559               return 1;
1560             }
1561           if (!options.c1mode && !noAssemble)
1562             {
1563               if (options.verbose)
1564                 printf ("sdcc: Calling assembler...\n");
1565               assemble (envp);
1566             }
1567         }
1568       else
1569         {
1570           // @FIX: Dario Vecchio 03-05-2001
1571           if (preOutName)
1572             {
1573               if (yyin && yyin != stdin)
1574                 fclose (yyin);
1575               unlink (preOutName);
1576               Safe_free (preOutName);
1577             }
1578           // EndFix
1579           #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1580           rm_tmpfiles();
1581           #endif
1582           return 1;
1583         }
1584
1585     }
1586
1587   closeDumpFiles();
1588
1589   if (cdbFile)
1590     fclose (cdbFile);
1591
1592   if (preOutName && !options.c1mode)
1593     {
1594       unlink (preOutName);
1595       Safe_free (preOutName);
1596     }
1597
1598   if (!options.cc_only &&
1599       !fatalError &&
1600       !noAssemble &&
1601       !options.c1mode &&
1602       (srcFileName || nrelFiles))
1603     {
1604       if (port->linker.do_link)
1605         port->linker.do_link ();
1606       else
1607         linkEdit (envp);
1608     }
1609
1610   if (yyin && yyin != stdin)
1611     fclose (yyin);
1612
1613   return 0;
1614
1615 }