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