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