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