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