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