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