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