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