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