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