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