Beautified. Although recommended, it's not my favourite style
[fw/sdcc] / src / SDCCmain.c
1 /*-------------------------------------------------------------------------
2   SDCCmain.c - main file
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #define USE_SYSTEM_SYSTEM_CALLS
26
27 #include "common.h"
28 #include <ctype.h>
29 #include "newalloc.h"
30 #include "SDCCerr.h"
31
32 #if NATIVE_WIN32
33 #include <process.h>
34 #else
35 #include "spawn.h"
36 #endif
37
38 // This is a bit messy because we define link ourself
39 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
40
41 #include <unistd.h>
42
43 #else
44 // No unistd.h in Borland C++
45 extern int access (const char *, int);
46 #define X_OK 1
47
48 #endif
49
50 //REMOVE ME!!!
51 extern int yyparse ();
52
53 FILE *srcFile;                  /* source file          */
54 FILE *cdbFile = NULL;           /* debugger information output file */
55 char *fullSrcFileName;          /* full name for the source file */
56 char *srcFileName;              /* source file name with the .c stripped */
57 char *moduleName;               /* module name is srcFilename stripped of any path */
58 const char *preArgv[128];       /* pre-processor arguments  */
59 int currRegBank = 0;
60 struct optimize optimize;
61 struct options options;
62 char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a" */ ;
63 short preProcOnly = 0;
64 short noAssemble = 0;
65 char *linkOptions[128];
66 const char *asmOptions[128];
67 char *libFiles[128];
68 int nlibFiles = 0;
69 char *libPaths[128];
70 int nlibPaths = 0;
71 char *relFiles[128];
72 int nrelFiles = 0;
73 bool verboseExec = FALSE;
74 char *preOutName;
75
76 // In MSC VC6 default search path for exe's to path for this
77
78 #if defined(_MSC_VER)
79
80 char DefaultExePath[_MAX_PATH];
81
82 #endif
83
84 /* Far functions, far data */
85 #define OPTION_LARGE_MODEL "-model-large"
86 /* Far functions, near data */
87 #define OPTION_MEDIUM_MODEL "-model-medium"
88 #define OPTION_SMALL_MODEL "-model-small"
89 #define OPTION_FLAT24_MODEL "-model-flat24"
90 #define OPTION_STACK_AUTO  "-stack-auto"
91 #define OPTION_STACK_10BIT "-stack-10bit"
92 #define OPTION_XSTACK      "-xstack"
93 #define OPTION_GENERIC     "-generic"
94 #define OPTION_NO_GCSE     "-nogcse"
95 #define OPTION_NO_LOOP_INV "-noinvariant"
96 #define OPTION_NO_LOOP_IND "-noinduction"
97 #define OPTION_NO_JTBOUND  "-nojtbound"
98 #define OPTION_NO_LOOPREV  "-noloopreverse"
99 #define OPTION_XREGS       "-regextend"
100 #define OPTION_COMP_ONLY   "-compile-only"
101 #define OPTION_DUMP_RAW    "-dumpraw"
102 #define OPTION_DUMP_GCSE   "-dumpgcse"
103 #define OPTION_DUMP_LOOP   "-dumploop"
104 #define OPTION_DUMP_KILL   "-dumpdeadcode"
105 #define OPTION_DUMP_RANGE  "-dumpliverange"
106 #define OPTION_DUMP_PACK   "-dumpregpack"
107 #define OPTION_DUMP_RASSGN "-dumpregassign"
108 #define OPTION_DUMP_ALL    "-dumpall"
109 #define OPTION_XRAM_LOC    "-xram-loc"
110 #define OPTION_IRAM_SIZE   "-iram-size"
111 #define OPTION_XSTACK_LOC  "-xstack-loc"
112 #define OPTION_CODE_LOC    "-code-loc"
113 #define OPTION_STACK_LOC   "-stack-loc"
114 #define OPTION_DATA_LOC    "-data-loc"
115 #define OPTION_IDATA_LOC   "-idata-loc"
116 #define OPTION_PEEP_FILE   "-peep-file"
117 #define OPTION_LIB_PATH    "-lib-path"
118 #define OPTION_INTLONG_RENT "-int-long-reent"
119 #define OPTION_FLOAT_RENT  "-float-reent"
120 #define OPTION_OUT_FMT_IHX "-out-fmt-ihx"
121 #define OPTION_OUT_FMT_S19 "-out-fmt-s19"
122 #define OPTION_CYCLOMATIC  "-cyclomatic"
123 #define OPTION_NOOVERLAY   "-nooverlay"
124 #define OPTION_MAINRETURN  "-main-return"
125 #define OPTION_NOPEEP      "-no-peep"
126 #define OPTION_ASMPEEP     "-peep-asm"
127 #define OPTION_DEBUG       "-debug"
128 #define OPTION_NODEBUG     "-nodebug"
129 #define OPTION_VERSION     "-version"
130 #define OPTION_STKAFTRDATA "-stack-after-data"
131 #define OPTION_PREPROC_ONLY "-preprocessonly"
132 #define OPTION_C1_MODE   "-c1mode"
133 #define OPTION_HELP         "-help"
134 #define OPTION_CALLEE_SAVES "-callee-saves"
135 #define OPTION_NOREGPARMS   "-noregparms"
136 #define OPTION_NOSTDLIB     "-nostdlib"
137 #define OPTION_NOSTDINC     "-nostdinc"
138 #define OPTION_VERBOSE      "-verbose"
139 #define OPTION_ANSIINT      "-ansiint"
140 static const char *_preCmd[] =
141 {
142   "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1",
143   "$l", "-I" SDCC_INCLUDE_DIR, "$1", "$2", NULL
144 };
145
146 PORT *port;
147
148 static PORT *_ports[] =
149 {
150 #if !OPT_DISABLE_MCS51
151   &mcs51_port,
152 #endif
153 #if !OPT_DISABLE_GBZ80
154   &gbz80_port,
155 #endif
156 #if !OPT_DISABLE_Z80
157   &z80_port,
158 #endif
159 #if !OPT_DISABLE_AVR
160   &avr_port,
161 #endif
162 #if !OPT_DISABLE_DS390
163   &ds390_port,
164 #endif
165 #if !OPT_DISABLE_PIC
166   &pic14_port,
167 #endif
168 #if !OPT_DISABLE_I186
169   &i186_port,
170 #endif
171 #if !OPT_DISABLE_TLCS900H
172   &tlcs900h_port,
173 #endif
174 };
175
176 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
177
178 /**
179    remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
180  */
181 extern void pic14glue ();
182
183 /** Sets the port to the one given by the command line option.
184     @param    The name minus the option (eg 'mcs51')
185     @return     0 on success.
186 */
187 static int 
188 _setPort (const char *name)
189 {
190   int i;
191   for (i = 0; i < NUM_PORTS; i++)
192     {
193       if (!strcmp (_ports[i]->target, name))
194         {
195           port = _ports[i];
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            " (UNIX) \n"
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 #if defined(_MSC_VER)
1268
1269 char *try_dir[] =
1270 {DefaultExePath, NULL};         // TODO : Fill in some default search list
1271
1272 #else
1273
1274 //char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
1275 char *try_dir[] =
1276 {NULL};
1277
1278 #endif
1279
1280 #ifdef USE_SYSTEM_SYSTEM_CALLS
1281 int 
1282 my_system (const char *cmd)
1283 {
1284   int argsStart, e, i = 0;
1285   char *cmdLine = NULL;
1286
1287   argsStart = strstr (cmd, " ") - cmd;
1288
1289   // try to find the command in predefined path's
1290   while (try_dir[i])
1291     {
1292       cmdLine = (char *) malloc (strlen (try_dir[i]) + strlen (cmd) + 10);
1293       strcpy (cmdLine, try_dir[i]);     // the path
1294
1295       strcat (cmdLine, "/");
1296       strncat (cmdLine, cmd, argsStart);        // the command
1297 #if NATIVE_WIN32
1298       strcat (cmdLine, ".exe");
1299       /* Mung slashes into backslashes to keep WIndoze happy. */
1300       {
1301         char *r = cmdLine;
1302         while (*r)
1303           {
1304             if (*r == '/')
1305               {
1306                 *r = '\\';
1307               }
1308             r++;
1309           }
1310       }
1311 #endif
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       exit (1);
1537     }
1538 #else
1539   buildCmdLine (buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1540   if (my_system (argv[0], argv))
1541     {
1542       perror ("Cannot exec linker");
1543       exit (1);
1544     }
1545
1546 #endif
1547
1548   if (strcmp (srcFileName, "temp") == 0)
1549     {
1550       /* rename "temp.cdb" to "firstRelFile.cdb" */
1551       char *f = strtok (strdup (relFiles[0]), ".");
1552       f = strcat (f, ".cdb");
1553       rename ("temp.cdb", f);
1554       srcFileName = NULL;
1555     }
1556 }
1557
1558 /*-----------------------------------------------------------------*/
1559 /* assemble - spawns the assembler with arguments                  */
1560 /*-----------------------------------------------------------------*/
1561 static void 
1562 assemble (char **envp)
1563 {
1564 #ifdef USE_SYSTEM_SYSTEM_CALLS
1565   buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1566   if (my_system (buffer))
1567     {
1568       exit (1);
1569     }
1570 #else
1571   char *argv[128];              /* assembler arguments */
1572
1573   buildCmdLine (buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1574
1575   if (my_system (argv[0], argv))
1576     {
1577       perror ("Cannot exec assembler");
1578       exit (1);
1579     }
1580 #endif
1581 }
1582
1583
1584
1585 /*-----------------------------------------------------------------*/
1586 /* preProcess - spawns the preprocessor with arguments       */
1587 /*-----------------------------------------------------------------*/
1588 static int 
1589 preProcess (char **envp)
1590 {
1591 #ifndef USE_SYSTEM_SYSTEM_CALLS
1592   char *argv[128];
1593 #endif
1594   char procDef[128];
1595
1596   preOutName = NULL;
1597
1598   if (!options.c1mode)
1599     {
1600       /* if using external stack define the macro */
1601       if (options.useXstack)
1602         _addToList (preArgv, "-DSDCC_USE_XSTACK");
1603
1604       /* set the macro for stack autos  */
1605       if (options.stackAuto)
1606         _addToList (preArgv, "-DSDCC_STACK_AUTO");
1607
1608       /* set the macro for stack autos  */
1609       if (options.stack10bit)
1610         _addToList (preArgv, "-DSDCC_STACK_TENBIT");
1611
1612       /* set the macro for large model  */
1613       switch (options.model)
1614         {
1615         case MODEL_LARGE:
1616           _addToList (preArgv, "-DSDCC_MODEL_LARGE");
1617           break;
1618         case MODEL_SMALL:
1619           _addToList (preArgv, "-DSDCC_MODEL_SMALL");
1620           break;
1621         case MODEL_COMPACT:
1622           _addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1623           break;
1624         case MODEL_MEDIUM:
1625           _addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1626           break;
1627         case MODEL_FLAT24:
1628           _addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1629           break;
1630         default:
1631           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1632           break;
1633         }
1634
1635
1636       /* add port (processor information to processor */
1637       sprintf (procDef, "-DSDCC_%s", port->target);
1638       _addToList (preArgv, procDef);
1639
1640       if (!preProcOnly)
1641         preOutName = strdup (tmpnam (NULL));
1642
1643       if (options.verbose)
1644         printf ("sdcc: Calling preprocessor...\n");
1645
1646 #ifdef USE_SYSTEM_SYSTEM_CALLS
1647       buildCmdLine (buffer, _preCmd, fullSrcFileName,
1648                     preOutName, srcFileName, preArgv);
1649       if (my_system (buffer))
1650         {
1651           exit (1);
1652         }
1653 #else
1654       buildCmdLine (buffer, argv, _preCmd, fullSrcFileName,
1655                     preOutName, srcFileName, preArgv);
1656
1657       if (my_system (argv[0], argv))
1658         {
1659           unlink (preOutName);
1660           perror ("Cannot exec Preprocessor");
1661           exit (1);
1662         }
1663
1664 #endif
1665       if (preProcOnly)
1666         exit (0);
1667     }
1668   else
1669     {
1670       preOutName = fullSrcFileName;
1671     }
1672
1673   yyin = fopen (preOutName, "r");
1674   if (yyin == NULL)
1675     {
1676       perror ("Preproc file not found\n");
1677       exit (1);
1678     }
1679
1680   return 0;
1681 }
1682
1683 static void 
1684 _findPort (int argc, char **argv)
1685 {
1686   _validatePorts ();
1687
1688   argc--;
1689   while (argc)
1690     {
1691       if (!strncmp (*argv, "-m", 2))
1692         {
1693           _setPort (*argv + 2);
1694           return;
1695         }
1696       argv++;
1697       argc--;
1698     }
1699   /* Use the first in the list */
1700   port = _ports[0];
1701 }
1702
1703 /*
1704  * main routine
1705  * initialises and calls the parser
1706  */
1707
1708 int 
1709 main (int argc, char **argv, char **envp)
1710 {
1711   /* turn all optimizations off by default */
1712   memset (&optimize, 0, sizeof (struct optimize));
1713
1714   /*printVersionInfo (); */
1715
1716   _findPort (argc, argv);
1717   /* Initalise the port. */
1718   if (port->init)
1719     port->init ();
1720
1721 #if defined(_MSC_VER)
1722
1723   {
1724     int i;
1725
1726     // Create a default exe search path from the path to the sdcc command
1727
1728     strcpy (DefaultExePath, argv[0]);
1729
1730     for (i = strlen (DefaultExePath); i > 0; i--)
1731       if (DefaultExePath[i] == '\\')
1732         {
1733           DefaultExePath[i] = '\0';
1734           break;
1735         }
1736
1737     if (i == 0)
1738       DefaultExePath[0] = '\0';
1739   }
1740
1741 #endif
1742
1743   setDefaultOptions ();
1744   parseCmdLine (argc, argv);
1745
1746   initMem ();
1747
1748   port->finaliseOptions ();
1749
1750   /* if no input then printUsage & exit */
1751   if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name))
1752     {
1753       printUsage ();
1754       exit (0);
1755     }
1756
1757   if (srcFileName)
1758     {
1759       preProcess (envp);
1760
1761       initSymt ();
1762       initiCode ();
1763       initCSupport ();
1764       initPeepHole ();
1765
1766       if (options.verbose)
1767         printf ("sdcc: Generating code...\n");
1768
1769       yyparse ();
1770
1771       if (!fatalError)
1772         {
1773 /* TSD PIC port hack - if the PIC port option is enabled
1774    and SDCC is used to generate PIC code, then we will
1775    generate .asm files in gpasm's format instead of SDCC's
1776    assembler's format
1777  */
1778 #if !OPT_DISABLE_PIC
1779           if (IS_PIC_PORT)
1780             pic14glue ();
1781           else
1782 #endif
1783             glue ();
1784           if (fatalError)
1785             {
1786               return 1;
1787             }
1788           if (!options.c1mode)
1789             {
1790               if (options.verbose)
1791                 printf ("sdcc: Calling assembler...\n");
1792
1793               assemble (envp);
1794             }
1795         }
1796       else
1797         {
1798           return 1;
1799         }
1800
1801     }
1802
1803   if (cdbFile)
1804     fclose (cdbFile);
1805
1806   if (!options.cc_only &&
1807       !fatalError &&
1808       !noAssemble &&
1809       !options.c1mode &&
1810       (srcFileName || nrelFiles))
1811     {
1812       if (port->linker.do_link)
1813         port->linker.do_link ();
1814       else
1815         linkEdit (envp);
1816     }
1817
1818   if (yyin && yyin != stdin)
1819     fclose (yyin);
1820
1821   if (preOutName && !options.c1mode)
1822     {
1823       unlink (preOutName);
1824       free (preOutName);
1825     }
1826
1827   return 0;
1828
1829 }