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