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