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