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