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