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