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