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