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