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