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