Fix TARGET_IS_PIC error
[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   &pic_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 picglue ();
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 void
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;
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
287   fprintf (stderr, " %s"
288 #ifdef SDCC_SUB_VERSION_STR
289            "/" SDCC_SUB_VERSION_STR
290 #endif
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               _setPort (argv[i] + 2);
1038               break;
1039
1040             case 'a':
1041               werror (W_UNSUPP_OPTION, "-a", "use --stack-auto instead");
1042               break;
1043
1044             case 'g':
1045               werror (W_UNSUPP_OPTION, "-g", "use --generic instead");
1046               break;
1047
1048             case 'X':           /* use external stack   */
1049               werror (W_UNSUPP_OPTION, "-X", "use --xstack-loc instead");
1050               break;
1051
1052             case 'x':
1053               werror (W_UNSUPP_OPTION, "-x", "use --xstack instead");
1054               break;
1055
1056             case 'p':           /* stack pointer intial value */
1057             case 'P':
1058               werror (W_UNSUPP_OPTION, "-p", "use --stack-loc instead");
1059               break;
1060
1061             case 'i':
1062               werror (W_UNSUPP_OPTION, "-i", "use --idata-loc instead");
1063               break;
1064
1065             case 'r':
1066               werror (W_UNSUPP_OPTION, "-r", "use --xdata-loc instead");
1067               break;
1068
1069             case 's':
1070               werror (W_UNSUPP_OPTION, "-s", "use --code-loc instead");
1071               break;
1072
1073             case 'c':
1074               options.cc_only = 1;
1075               break;
1076
1077             case 'Y':
1078               werror (W_UNSUPP_OPTION, "-Y", "use -I instead");
1079               break;
1080
1081             case 'L':
1082               if (argv[i][2])
1083                 libPaths[nlibPaths++] = &argv[i][2];
1084               else
1085                 libPaths[nlibPaths++] = argv[++i];
1086               break;
1087
1088             case 'W':
1089               /* linker options */
1090               if (argv[i][2] == 'l')
1091                 {
1092                   if (argv[i][3])
1093                     parseWithComma (linkOptions, &argv[i][3]);
1094                   else
1095                     parseWithComma (linkOptions, argv[++i]);
1096                 }
1097               else
1098                 {
1099                   /* assembler options */
1100                   if (argv[i][2] == 'a')
1101                     {
1102                       if (argv[i][3])
1103                         parseWithComma ((char **) asmOptions, &argv[i][3]);
1104                       else
1105                         parseWithComma ((char **) asmOptions, argv[++i]);
1106
1107                     }
1108                   else
1109                     {
1110                       werror (W_UNKNOWN_OPTION, argv[i]);
1111                     }
1112                 }
1113               break;
1114             case 'S':
1115               noAssemble = 1;
1116               break;
1117
1118             case 'V':
1119               verboseExec = TRUE;
1120               break;
1121
1122             case 'v':
1123               printVersionInfo ();
1124               exit (0);
1125               break;
1126
1127               /* preprocessor options */
1128             case 'M':
1129               {
1130                 preProcOnly = 1;
1131                 _addToList (preArgv, "-M");
1132                 break;
1133               }
1134             case 'C':
1135               {
1136                 _addToList (preArgv, "-C");
1137                 break;
1138               }
1139             case 'd':
1140             case 'D':
1141             case 'I':
1142             case 'A':
1143             case 'U':
1144               {
1145                 char sOpt = argv[i][1];
1146                 char *rest;
1147
1148                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1149                   {
1150                     i++;
1151                     rest = argv[i];
1152                   }
1153                 else
1154                   rest = &argv[i][2];
1155
1156                 if (argv[i][1] == 'Y')
1157                   argv[i][1] = 'I';
1158
1159                 sprintf (buffer, "-%c%s", sOpt, rest);
1160                 _addToList (preArgv, buffer);
1161               }
1162               break;
1163
1164             default:
1165               if (!port->parseOption (&argc, argv, &i))
1166                 werror (W_UNKNOWN_OPTION, argv[i]);
1167             }
1168           continue;
1169         }
1170
1171       if (!port->parseOption (&argc, argv, &i))
1172         {
1173           /* no option must be a filename */
1174           if (options.c1mode)
1175             _processC1Arg (argv[i]);
1176           else
1177             processFile (argv[i]);
1178         }
1179     }
1180
1181   /* set up external stack location if not explicitly specified */
1182   if (!options.xstack_loc)
1183     options.xstack_loc = options.xdata_loc;
1184
1185   /* if debug option is set the open the cdbFile */
1186   if (!options.nodebug && srcFileName)
1187     {
1188       sprintf (cdbfnbuf, "%s.cdb", srcFileName);
1189       if ((cdbFile = fopen (cdbfnbuf, "w")) == NULL)
1190         werror (E_FILE_OPEN_ERR, cdbfnbuf);
1191       else
1192         {
1193           /* add a module record */
1194           fprintf (cdbFile, "M:%s\n", moduleName);
1195         }
1196     }
1197   return 0;
1198 }
1199
1200 /*-----------------------------------------------------------------*/
1201 /* my_system - will call a program with arguments                  */
1202 /*-----------------------------------------------------------------*/
1203
1204
1205
1206
1207 //char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
1208 char *try_dir[] =
1209 {NULL, NULL};                   /* First entry may be overwritten, so use two. */
1210
1211
1212 int
1213 my_system (const char *cmd)
1214 {
1215   int argsStart, e, i = 0;
1216   char *cmdLine = NULL;
1217
1218   argsStart = strstr (cmd, " ") - cmd;
1219
1220   // try to find the command in predefined path's
1221   while (try_dir[i])
1222     {
1223       cmdLine = (char *) Safe_malloc (strlen (try_dir[i]) + strlen (cmd) + 10);
1224       strcpy (cmdLine, try_dir[i]);     // the path
1225
1226       strcat (cmdLine, DIR_SEPARATOR_STRING);
1227       strncat (cmdLine, cmd, argsStart);        // the command
1228
1229 #if NATIVE_WIN32
1230       strcat (cmdLine, ".exe");
1231 #endif
1232
1233       if (access (cmdLine, X_OK) == 0)
1234         {
1235           // the arguments
1236           strcat (cmdLine, cmd + argsStart);
1237           break;
1238         }
1239       free (cmdLine);
1240       cmdLine = NULL;
1241       i++;
1242     }
1243
1244   if (verboseExec)
1245     {
1246       printf ("+ %s\n", cmdLine ? cmdLine : cmd);
1247     }
1248
1249   if (cmdLine)
1250     {
1251       // command found in predefined path
1252       e = system (cmdLine);
1253       free (cmdLine);
1254     }
1255   else
1256     {
1257       // trust on $PATH
1258       e = system (cmd);
1259     }
1260   return e;
1261 }
1262
1263
1264 /*-----------------------------------------------------------------*/
1265 /* linkEdit : - calls the linkage editor  with options             */
1266 /*-----------------------------------------------------------------*/
1267 static void
1268 linkEdit (char **envp)
1269 {
1270   FILE *lnkfile;
1271   char *segName, *c;
1272
1273   int i;
1274   if (!srcFileName)
1275     srcFileName = "temp";
1276
1277   /* first we need to create the <filename>.lnk file */
1278   sprintf (buffer, "%s.lnk", srcFileName);
1279   if (!(lnkfile = fopen (buffer, "w")))
1280     {
1281       werror (E_FILE_OPEN_ERR, buffer);
1282       exit (1);
1283     }
1284
1285   /* now write the options */
1286   fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1287
1288   /* if iram size specified */
1289   if (options.iram_size)
1290     fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1291
1292   /*if (options.debug) */
1293   fprintf (lnkfile, "-z\n");
1294
1295 #define WRITE_SEG_LOC(N, L) \
1296     segName = strdup(N); \
1297     c = strtok(segName, " \t"); \
1298     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1299     if (segName) { free(segName); }
1300
1301   /* code segment start */
1302   WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1303
1304   /* data segment start */
1305   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1306
1307   /* xdata start */
1308   WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1309
1310   /* indirect data */
1311   WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1312
1313   /* bit segment start */
1314   WRITE_SEG_LOC (BIT_NAME, 0);
1315
1316   /* add the extra linker options */
1317   for (i = 0; linkOptions[i]; i++)
1318     fprintf (lnkfile, "%s\n", linkOptions[i]);
1319
1320   /* other library paths if specified */
1321   for (i = 0; i < nlibPaths; i++)
1322     fprintf (lnkfile, "-k %s\n", libPaths[i]);
1323
1324   /* standard library path */
1325   if (!options.nostdlib)
1326     {
1327       if (TARGET_IS_DS390)
1328         {
1329           c = "ds390";
1330         }
1331       else
1332         {
1333           switch (options.model)
1334             {
1335             case MODEL_SMALL:
1336               c = "small";
1337               break;
1338             case MODEL_LARGE:
1339               c = "large";
1340               break;
1341             case MODEL_FLAT24:
1342               c = "flat24";
1343               break;
1344             default:
1345               werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1346               c = "unknown";
1347               break;
1348             }
1349         }
1350       fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1351
1352       /* standard library files */
1353       if (strcmp (port->target, "ds390") == 0)
1354         {
1355           fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1356         }
1357       fprintf (lnkfile, "-l %s\n", STD_LIB);
1358       fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1359       fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1360       fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1361     }
1362
1363   /* additional libraries if any */
1364   for (i = 0; i < nlibFiles; i++)
1365     fprintf (lnkfile, "-l %s\n", libFiles[i]);
1366
1367   /* put in the object files */
1368   if (strcmp (srcFileName, "temp"))
1369     fprintf (lnkfile, "%s ", srcFileName);
1370
1371   for (i = 0; i < nrelFiles; i++)
1372     fprintf (lnkfile, "%s\n", relFiles[i]);
1373
1374   fprintf (lnkfile, "\n-e\n");
1375   fclose (lnkfile);
1376
1377   if (options.verbose)
1378     printf ("sdcc: Calling linker...\n");
1379
1380   buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1381   if (my_system (buffer))
1382     {
1383       exit (1);
1384     }
1385
1386   if (strcmp (srcFileName, "temp") == 0)
1387     {
1388       /* rename "temp.cdb" to "firstRelFile.cdb" */
1389       char *f = strtok (strdup (relFiles[0]), ".");
1390       f = strcat (f, ".cdb");
1391       rename ("temp.cdb", f);
1392       srcFileName = NULL;
1393     }
1394 }
1395
1396 /*-----------------------------------------------------------------*/
1397 /* assemble - spawns the assembler with arguments                  */
1398 /*-----------------------------------------------------------------*/
1399 static void
1400 assemble (char **envp)
1401 {
1402   buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1403   if (my_system (buffer))
1404     {
1405       /* either system() or the assembler itself has reported an error
1406          perror ("Cannot exec assembler");
1407        */
1408       exit (1);
1409     }
1410 }
1411
1412
1413
1414 /*-----------------------------------------------------------------*/
1415 /* preProcess - spawns the preprocessor with arguments       */
1416 /*-----------------------------------------------------------------*/
1417 static int
1418 preProcess (char **envp)
1419 {
1420   char procDef[128];
1421
1422   preOutName = NULL;
1423
1424   if (!options.c1mode)
1425     {
1426       /* if using external stack define the macro */
1427       if (options.useXstack)
1428         _addToList (preArgv, "-DSDCC_USE_XSTACK");
1429
1430       /* set the macro for stack autos  */
1431       if (options.stackAuto)
1432         _addToList (preArgv, "-DSDCC_STACK_AUTO");
1433
1434       /* set the macro for stack autos  */
1435       if (options.stack10bit)
1436         _addToList (preArgv, "-DSDCC_STACK_TENBIT");
1437
1438       /* set the macro for large model  */
1439       switch (options.model)
1440         {
1441         case MODEL_LARGE:
1442           _addToList (preArgv, "-DSDCC_MODEL_LARGE");
1443           break;
1444         case MODEL_SMALL:
1445           _addToList (preArgv, "-DSDCC_MODEL_SMALL");
1446           break;
1447         case MODEL_COMPACT:
1448           _addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1449           break;
1450         case MODEL_MEDIUM:
1451           _addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1452           break;
1453         case MODEL_FLAT24:
1454           _addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1455           break;
1456         default:
1457           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1458           break;
1459         }
1460
1461       /* standard include path */
1462       if (!options.nostdinc) {
1463         _addToList (preArgv, "-I" SDCC_INCLUDE_DIR);
1464       }
1465
1466       /* add port (processor information to processor */
1467       sprintf (procDef, "-DSDCC_%s", port->target);
1468       _addToList (preArgv, procDef);
1469       sprintf (procDef, "-D__%s", port->target);
1470       _addToList (preArgv, procDef);
1471
1472       if (!preProcOnly)
1473         preOutName = strdup (tmpnam (NULL));
1474
1475       if (options.verbose)
1476         printf ("sdcc: Calling preprocessor...\n");
1477
1478       buildCmdLine (buffer, _preCmd, fullSrcFileName,
1479                     preOutName, srcFileName, preArgv);
1480       if (my_system (buffer))
1481         {
1482           exit (1);
1483         }
1484
1485       if (preProcOnly)
1486         exit (0);
1487     }
1488   else
1489     {
1490       preOutName = fullSrcFileName;
1491     }
1492
1493   yyin = fopen (preOutName, "r");
1494   if (yyin == NULL)
1495     {
1496       perror ("Preproc file not found\n");
1497       exit (1);
1498     }
1499
1500   return 0;
1501 }
1502
1503 static void
1504 _findPort (int argc, char **argv)
1505 {
1506   _validatePorts ();
1507
1508   argc--;
1509   while (argc)
1510     {
1511       if (!strncmp (*argv, "-m", 2))
1512         {
1513           _setPort (*argv + 2);
1514           return;
1515         }
1516       argv++;
1517       argc--;
1518     }
1519   /* Use the first in the list */
1520   port = _ports[0];
1521 }
1522
1523 /*
1524  * main routine
1525  * initialises and calls the parser
1526  */
1527
1528 int
1529 main (int argc, char **argv, char **envp)
1530 {
1531   /* turn all optimizations off by default */
1532   memset (&optimize, 0, sizeof (struct optimize));
1533
1534   /*printVersionInfo (); */
1535
1536   if (NUM_PORTS==0) {
1537     fprintf (stderr, "Build error: no ports are enabled.\n");
1538     exit (1);
1539   }
1540
1541   _findPort (argc, argv);
1542   /* Initalise the port. */
1543   if (port->init)
1544     port->init ();
1545
1546   // Create a default exe search path from the path to the sdcc command
1547
1548
1549
1550   if (strchr (argv[0], DIR_SEPARATOR_CHAR))
1551     {
1552       strcpy (DefaultExePath, argv[0]);
1553       *(strrchr (DefaultExePath, DIR_SEPARATOR_CHAR)) = 0;
1554       try_dir[0] = DefaultExePath;
1555     }
1556
1557
1558   setDefaultOptions ();
1559   parseCmdLine (argc, argv);
1560
1561   initMem ();
1562
1563   port->finaliseOptions ();
1564
1565   /* if no input then printUsage & exit */
1566   if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name))
1567     {
1568       printUsage ();
1569       exit (0);
1570     }
1571
1572   if (srcFileName)
1573     {
1574       preProcess (envp);
1575
1576       initSymt ();
1577       initiCode ();
1578       initCSupport ();
1579       initPeepHole ();
1580
1581       if (options.verbose)
1582         printf ("sdcc: Generating code...\n");
1583
1584       yyparse ();
1585
1586       if (!fatalError)
1587         {
1588           if (TARGET_IS_PIC) {
1589             /* TSD PIC port hack - if the PIC port option is enabled
1590                and SDCC is used to generate PIC code, then we will
1591                generate .asm files in gpasm's format instead of SDCC's
1592                assembler's format
1593             */
1594             picglue ();
1595           }
1596           else
1597             glue ();
1598           if (fatalError)
1599             {
1600               return 1;
1601             }
1602           if (!options.c1mode)
1603             {
1604               if (options.verbose)
1605                 printf ("sdcc: Calling assembler...\n");
1606               assemble (envp);
1607             }
1608         }
1609       else
1610         {
1611           return 1;
1612         }
1613
1614     }
1615
1616   if (cdbFile)
1617     fclose (cdbFile);
1618
1619   if (!options.cc_only &&
1620       !fatalError &&
1621       !noAssemble &&
1622       !options.c1mode &&
1623       (srcFileName || nrelFiles))
1624     {
1625       if (port->linker.do_link)
1626         port->linker.do_link ();
1627       else
1628         linkEdit (envp);
1629     }
1630
1631   if (yyin && yyin != stdin)
1632     fclose (yyin);
1633
1634   if (preOutName && !options.c1mode)
1635     {
1636       unlink (preOutName);
1637       free (preOutName);
1638     }
1639
1640   return 0;
1641
1642 }