Changed it so each target can have their own command line.
[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", "-version", "-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(asmOptions,&argv[i][3]);
856                         else
857                             parseWithComma(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
1087     preOutName = NULL;
1088
1089     /* if using external stack define the macro */
1090     if ( options.useXstack )
1091         _addToList(preArgv, "-DSDCC_USE_XSTACK");
1092     
1093     /* set the macro for stack autos    */
1094     if ( options.stackAuto )
1095         _addToList(preArgv, "-DSDCC_STACK_AUTO");
1096     
1097     /* set the macro for large model    */
1098     if ( options.model )
1099         _addToList(preArgv, "-DSDCC_MODEL_LARGE");
1100     else
1101         _addToList(preArgv, "-DSDCC_MODEL_SMALL");
1102     
1103     if (!preProcOnly)
1104         preOutName = strdup(tmpnam(NULL));
1105
1106     _buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
1107                   preOutName, srcFileName, preArgv);
1108
1109     if (my_system(argv[0], argv)) {
1110         unlink (preOutName);
1111         perror("Cannot exec Preprocessor");
1112         exit(1);
1113     }
1114
1115     if (preProcOnly)
1116         exit(0);
1117
1118     yyin = fopen(preOutName,"r");
1119     if (yyin == NULL) {
1120         perror("Preproc file not found\n");
1121         exit(1);
1122     }
1123     
1124     return 0;
1125 }
1126
1127 static void _findPort(int argc, char **argv)
1128 {
1129     argc--;
1130     while (argc) {
1131         if (!strncmp(*argv, "-m", 2)) {
1132             _setPort(*argv + 2);
1133             return;
1134         }
1135         argv++;
1136         argc--;
1137     }
1138     /* Use the first in the list */
1139     port = _ports[0];
1140 }
1141
1142 /* 
1143  * main routine
1144  * initialises and calls the parser
1145  */
1146
1147 int main ( int argc, char **argv , char **envp)
1148 {
1149     /* turn all optimizations off by default */
1150     memset(&optimize,0,sizeof(struct optimize));
1151     
1152     /*printVersionInfo ();*/
1153
1154     _findPort(argc, argv);
1155     setDefaultOptions();
1156     parseCmdLine(argc,argv);
1157
1158     /* if no input then printUsage & exit */
1159     if (!srcFileName && !nrelFiles) {
1160         printUsage();
1161         exit(0);
1162     }
1163         
1164     if (srcFileName)
1165         preProcess(envp) ;
1166
1167     if (srcFileName) {
1168
1169         initSymt();
1170         initMem();                  
1171         initiCode();
1172         initCSupport ();
1173         initPeepHole();
1174         yyparse();
1175
1176         if (!fatalError) {
1177             glue();
1178             assemble(envp);
1179         }
1180         
1181     }
1182     
1183     if (cdbFile)
1184         fclose(cdbFile);
1185
1186     if (!options.cc_only && 
1187         !fatalError      &&
1188         !noAssemble      &&
1189         (srcFileName || nrelFiles))
1190         linkEdit (envp);
1191
1192     if (yyin && yyin != stdin)
1193         fclose(yyin);
1194
1195     if (preOutName) {
1196         unlink(preOutName);
1197         free(preOutName);
1198     }
1199     return 0;
1200     
1201 }