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