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