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