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