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