Cleaned up some bits and peaces
[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", "-I" SDCC_INCLUDE_DIR, "$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
1465       /* add port (processor information to processor */
1466       sprintf (procDef, "-DSDCC_%s", port->target);
1467       _addToList (preArgv, procDef);
1468       sprintf (procDef, "-D__%s", port->target);
1469       _addToList (preArgv, procDef);
1470
1471       if (!preProcOnly)
1472         preOutName = strdup (tmpnam (NULL));
1473
1474       if (options.verbose)
1475         printf ("sdcc: Calling preprocessor...\n");
1476
1477       buildCmdLine (buffer, _preCmd, fullSrcFileName,
1478                     preOutName, srcFileName, preArgv);
1479       if (my_system (buffer))
1480         {
1481           exit (1);
1482         }
1483
1484       if (preProcOnly)
1485         exit (0);
1486     }
1487   else
1488     {
1489       preOutName = fullSrcFileName;
1490     }
1491
1492   yyin = fopen (preOutName, "r");
1493   if (yyin == NULL)
1494     {
1495       perror ("Preproc file not found\n");
1496       exit (1);
1497     }
1498
1499   return 0;
1500 }
1501
1502 static void
1503 _findPort (int argc, char **argv)
1504 {
1505   _validatePorts ();
1506
1507   argc--;
1508   while (argc)
1509     {
1510       if (!strncmp (*argv, "-m", 2))
1511         {
1512           _setPort (*argv + 2);
1513           return;
1514         }
1515       argv++;
1516       argc--;
1517     }
1518   /* Use the first in the list */
1519   port = _ports[0];
1520 }
1521
1522 /*
1523  * main routine
1524  * initialises and calls the parser
1525  */
1526
1527 int
1528 main (int argc, char **argv, char **envp)
1529 {
1530   /* turn all optimizations off by default */
1531   memset (&optimize, 0, sizeof (struct optimize));
1532
1533   /*printVersionInfo (); */
1534
1535   _findPort (argc, argv);
1536   /* Initalise the port. */
1537   if (port->init)
1538     port->init ();
1539
1540   // Create a default exe search path from the path to the sdcc command
1541
1542
1543
1544   if (strchr (argv[0], DIR_SEPARATOR_CHAR))
1545     {
1546       strcpy (DefaultExePath, argv[0]);
1547       *(strrchr (DefaultExePath, DIR_SEPARATOR_CHAR)) = 0;
1548       try_dir[0] = DefaultExePath;
1549     }
1550
1551
1552   setDefaultOptions ();
1553   parseCmdLine (argc, argv);
1554
1555   initMem ();
1556
1557   port->finaliseOptions ();
1558
1559   /* if no input then printUsage & exit */
1560   if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name))
1561     {
1562       printUsage ();
1563       exit (0);
1564     }
1565
1566   if (srcFileName)
1567     {
1568       preProcess (envp);
1569
1570       initSymt ();
1571       initiCode ();
1572       initCSupport ();
1573       initPeepHole ();
1574
1575       if (options.verbose)
1576         printf ("sdcc: Generating code...\n");
1577
1578       yyparse ();
1579
1580       if (!fatalError)
1581         {
1582           if (IS_PIC14_PORT)
1583             /* TSD PIC port hack - if the PIC port option is enabled
1584                and SDCC is used to generate PIC code, then we will
1585                generate .asm files in gpasm's format instead of SDCC's
1586                assembler's format
1587             */
1588             pic14glue ();
1589           else
1590             glue ();
1591           if (fatalError)
1592             {
1593               return 1;
1594             }
1595           if (!options.c1mode)
1596             {
1597               if (options.verbose)
1598                 printf ("sdcc: Calling assembler...\n");
1599               assemble (envp);
1600             }
1601         }
1602       else
1603         {
1604           return 1;
1605         }
1606
1607     }
1608
1609   if (cdbFile)
1610     fclose (cdbFile);
1611
1612   if (!options.cc_only &&
1613       !fatalError &&
1614       !noAssemble &&
1615       !options.c1mode &&
1616       (srcFileName || nrelFiles))
1617     {
1618       if (port->linker.do_link)
1619         port->linker.do_link ();
1620       else
1621         linkEdit (envp);
1622     }
1623
1624   if (yyin && yyin != stdin)
1625     fclose (yyin);
1626
1627   if (preOutName && !options.c1mode)
1628     {
1629       unlink (preOutName);
1630       free (preOutName);
1631     }
1632
1633   return 0;
1634
1635 }