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