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