Fixed bugs involving static variables in z80 port; added --lesspedantic option
[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_NOSTDLIB     "-nostdlib"
131 #define OPTION_NOSTDINC     "-nostdinc"
132 #define OPTION_VERBOSE      "-verbose"
133 #define OPTION_LESS_PEDANTIC "-lesspedantic"
134
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_PEEP_FILE) == 0)
758             {
759               if (argv[i][1 + strlen (OPTION_PEEP_FILE)])
760                 options.peep_file =
761                   &argv[i][1 + strlen (OPTION_PEEP_FILE)];
762               else
763                 options.peep_file = argv[++i];
764               continue;
765             }
766
767           if (strcmp (&argv[i][1], OPTION_LIB_PATH) == 0)
768             {
769               if (argv[i][1 + strlen (OPTION_LIB_PATH)])
770                 libPaths[nlibPaths++] =
771                   &argv[i][1 + strlen (OPTION_PEEP_FILE)];
772               else
773                 libPaths[nlibPaths++] = argv[++i];
774               continue;
775             }
776
777           if (strcmp (&argv[i][1], OPTION_XSTACK_LOC) == 0)
778             {
779
780               if (argv[i][1 + strlen (OPTION_XSTACK_LOC)])
781                 options.xstack_loc =
782                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_XSTACK_LOC)]));
783               else
784                 options.xstack_loc =
785                   (int) floatFromVal (constVal (argv[++i]));
786               continue;
787             }
788
789           if (strcmp (&argv[i][1], OPTION_XSTACK) == 0)
790             {
791               options.useXstack = 1;
792               continue;
793             }
794
795           if (strcmp (&argv[i][1], OPTION_MAINRETURN) == 0)
796             {
797               options.mainreturn = 1;
798               continue;
799             }
800
801           if (strcmp (&argv[i][1], OPTION_CALLEE_SAVES) == 0)
802             {
803               if (argv[i][1 + strlen (OPTION_CALLEE_SAVES)])
804                 parseWithComma (options.calleeSaves
805                                 ,&argv[i][1 + strlen (OPTION_CALLEE_SAVES)]);
806               else
807                 parseWithComma (options.calleeSaves, argv[++i]);
808               continue;
809             }
810
811           if (strcmp (&argv[i][1], OPTION_STACK_LOC) == 0)
812             {
813
814               if (argv[i][1 + strlen (OPTION_STACK_LOC)])
815                 options.stack_loc =
816                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_STACK_LOC)]));
817               else
818                 options.stack_loc =
819                   (int) floatFromVal (constVal (argv[++i]));
820               continue;
821             }
822
823           if (strcmp (&argv[i][1], OPTION_XRAM_LOC) == 0)
824             {
825
826               if (argv[i][1 + strlen (OPTION_XRAM_LOC)])
827                 options.xdata_loc =
828                   (unsigned int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_XRAM_LOC)]));
829               else
830                 options.xdata_loc =
831                   (unsigned int) floatFromVal (constVal (argv[++i]));
832               continue;
833             }
834
835           if (strcmp (&argv[i][1], OPTION_IRAM_SIZE) == 0)
836             {
837
838               if (argv[i][1 + strlen (OPTION_IRAM_SIZE)])
839                 options.iram_size =
840                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_IRAM_SIZE)]));
841               else
842                 options.iram_size =
843                   (int) floatFromVal (constVal (argv[++i]));
844               continue;
845             }
846
847           if (strcmp (&argv[i][1], OPTION_VERSION) == 0)
848             {
849               printVersionInfo ();
850               exit (0);
851               continue;
852             }
853
854           if (strcmp (&argv[i][1], OPTION_DATA_LOC) == 0)
855             {
856
857               if (argv[i][1 + strlen (OPTION_DATA_LOC)])
858                 options.data_loc =
859                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_DATA_LOC)]));
860               else
861                 options.data_loc =
862                   (int) floatFromVal (constVal (argv[++i]));
863               continue;
864             }
865
866           if (strcmp (&argv[i][1], OPTION_IDATA_LOC) == 0)
867             {
868
869               if (argv[i][1 + strlen (OPTION_IDATA_LOC)])
870                 options.idata_loc =
871                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_IDATA_LOC)]));
872               else
873                 options.idata_loc =
874                   (int) floatFromVal (constVal (argv[++i]));
875               continue;
876             }
877
878           if (strcmp (&argv[i][1], OPTION_CODE_LOC) == 0)
879             {
880
881               if (argv[i][1 + strlen (OPTION_CODE_LOC)])
882                 options.code_loc =
883                   (int) floatFromVal (constVal (&argv[i][1 + strlen (OPTION_CODE_LOC)]));
884               else
885                 options.code_loc =
886                   (int) floatFromVal (constVal (argv[++i]));
887               continue;
888             }
889
890
891           if (strcmp (&argv[i][1], OPTION_NO_JTBOUND) == 0)
892             {
893               optimize.noJTabBoundary = 1;
894               continue;
895             }
896
897           if (strcmp (&argv[i][1], OPTION_NO_GCSE) == 0)
898             {
899               optimize.global_cse = 0;
900               continue;
901             }
902
903           if (strcmp (&argv[i][1], OPTION_NO_LOOP_INV) == 0)
904             {
905               optimize.loopInvariant = 0;
906               continue;
907             }
908
909           if (strcmp (&argv[i][1], OPTION_NO_LOOP_IND) == 0)
910             {
911               optimize.loopInduction = 0;
912               continue;
913             }
914
915           if (strcmp (&argv[i][1], OPTION_NO_LOOPREV) == 0)
916             {
917               optimize.noLoopReverse = 1;
918               continue;
919             }
920
921           if (strcmp (&argv[i][1], OPTION_NOSTDLIB) == 0)
922             {
923               options.nostdlib = 1;
924               continue;
925             }
926
927           if (strcmp (&argv[i][1], OPTION_NOSTDINC) == 0)
928             {
929               options.nostdinc = 1;
930               continue;
931             }
932
933           if (strcmp (&argv[i][1], OPTION_VERBOSE) == 0)
934             {
935               options.verbose = 1;
936               continue;
937             }
938           
939           if (strcmp (argv[i] +1, OPTION_LESS_PEDANTIC) == 0) 
940               {
941                   setErrorLogLevel(ERROR_LEVEL_WARNINGS);
942                   continue;
943               }
944
945           if (!port->parseOption (&argc, argv, &i))
946             {
947               werror (W_UNKNOWN_OPTION, argv[i]);
948             }
949           else
950             {
951               continue;
952             }
953         }
954
955
956       /* if preceded by  '-' then option */
957       if (*argv[i] == '-')
958         {
959           switch (argv[i][1])
960             {
961             case 'h':
962               printUsage ();
963               exit (0);
964               break;
965
966             case 'E':
967               preProcOnly = 1;
968               break;
969
970             case 'm':
971               /* Used to select the port */
972               _setPort (argv[i] + 2);
973               break;
974
975             case 'a':
976               werror (W_UNSUPP_OPTION, "-a", "use --stack-auto instead");
977               break;
978
979             case 'g':
980               werror (W_UNSUPP_OPTION, "-g", "use --generic instead");
981               break;
982
983             case 'X':           /* use external stack   */
984               werror (W_UNSUPP_OPTION, "-X", "use --xstack-loc instead");
985               break;
986
987             case 'x':
988               werror (W_UNSUPP_OPTION, "-x", "use --xstack instead");
989               break;
990
991             case 'p':           /* stack pointer intial value */
992             case 'P':
993               werror (W_UNSUPP_OPTION, "-p", "use --stack-loc instead");
994               break;
995
996             case 'i':
997               werror (W_UNSUPP_OPTION, "-i", "use --idata-loc instead");
998               break;
999
1000             case 'r':
1001               werror (W_UNSUPP_OPTION, "-r", "use --xdata-loc instead");
1002               break;
1003
1004             case 's':
1005               werror (W_UNSUPP_OPTION, "-s", "use --code-loc instead");
1006               break;
1007
1008             case 'c':
1009               options.cc_only = 1;
1010               break;
1011
1012             case 'Y':
1013               werror (W_UNSUPP_OPTION, "-Y", "use -I instead");
1014               break;
1015
1016             case 'L':
1017               if (argv[i][2])
1018                 libPaths[nlibPaths++] = &argv[i][2];
1019               else
1020                 libPaths[nlibPaths++] = argv[++i];
1021               break;
1022
1023             case 'W':
1024               /* linker options */
1025               if (argv[i][2] == 'l')
1026                 {
1027                   if (argv[i][3])
1028                     parseWithComma (linkOptions, &argv[i][3]);
1029                   else
1030                     parseWithComma (linkOptions, argv[++i]);
1031                 }
1032               else
1033                 {
1034                   /* assembler options */
1035                   if (argv[i][2] == 'a')
1036                     {
1037                       if (argv[i][3])
1038                         parseWithComma ((char **) asmOptions, &argv[i][3]);
1039                       else
1040                         parseWithComma ((char **) asmOptions, argv[++i]);
1041
1042                     }
1043                   else
1044                     {
1045                       werror (W_UNKNOWN_OPTION, argv[i]);
1046                     }
1047                 }
1048               break;
1049             case 'S':
1050               noAssemble = 1;
1051               break;
1052
1053             case 'V':
1054               verboseExec = TRUE;
1055               break;
1056
1057             case 'v':
1058               printVersionInfo ();
1059               exit (0);
1060               break;
1061
1062               /* preprocessor options */
1063             case 'M':
1064               {
1065                 preProcOnly = 1;
1066                 _addToList (preArgv, "-M");
1067                 break;
1068               }
1069             case 'C':
1070               {
1071                 _addToList (preArgv, "-C");
1072                 break;
1073               }
1074             case 'd':
1075             case 'D':
1076             case 'I':
1077             case 'A':
1078             case 'U':
1079               {
1080                 char sOpt = argv[i][1];
1081                 char *rest;
1082
1083                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1084                   {
1085                     i++;
1086                     rest = argv[i];
1087                   }
1088                 else
1089                   rest = &argv[i][2];
1090
1091                 if (argv[i][1] == 'Y')
1092                   argv[i][1] = 'I';
1093
1094                 sprintf (buffer, "-%c%s", sOpt, rest);
1095                 _addToList (preArgv, buffer);
1096               }
1097               break;
1098
1099             default:
1100               if (!port->parseOption (&argc, argv, &i))
1101                 werror (W_UNKNOWN_OPTION, argv[i]);
1102             }
1103           continue;
1104         }
1105
1106       if (!port->parseOption (&argc, argv, &i))
1107         {
1108           /* no option must be a filename */
1109           if (options.c1mode)
1110             _processC1Arg (argv[i]);
1111           else
1112             processFile (argv[i]);
1113         }
1114     }
1115
1116   /* set up external stack location if not explicitly specified */
1117   if (!options.xstack_loc)
1118     options.xstack_loc = options.xdata_loc;
1119
1120   /* if debug option is set the open the cdbFile */
1121   if (!options.nodebug && srcFileName)
1122     {
1123       sprintf (cdbfnbuf, "%s.cdb", srcFileName);
1124       if ((cdbFile = fopen (cdbfnbuf, "w")) == NULL)
1125         werror (E_FILE_OPEN_ERR, cdbfnbuf);
1126       else
1127         {
1128           /* add a module record */
1129           fprintf (cdbFile, "M:%s\n", moduleName);
1130         }
1131     }
1132   return 0;
1133 }
1134
1135 /*-----------------------------------------------------------------*/
1136 /* my_system - will call a program with arguments                  */
1137 /*-----------------------------------------------------------------*/
1138
1139
1140
1141
1142 //char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
1143 char *try_dir[] =
1144 {NULL, NULL};                   /* First entry may be overwritten, so use two. */
1145
1146
1147 int
1148 my_system (const char *cmd)
1149 {
1150   int argsStart, e, i = 0;
1151   char *cmdLine = NULL;
1152
1153   argsStart = strstr (cmd, " ") - cmd;
1154
1155   // try to find the command in predefined path's
1156   while (try_dir[i])
1157     {
1158       cmdLine = (char *) Safe_malloc (strlen (try_dir[i]) + strlen (cmd) + 10);
1159       strcpy (cmdLine, try_dir[i]);     // the path
1160
1161       strcat (cmdLine, DIR_SEPARATOR_STRING);
1162       strncat (cmdLine, cmd, argsStart);        // the command
1163
1164 #if NATIVE_WIN32
1165       strcat (cmdLine, ".exe");
1166 #endif
1167
1168       if (access (cmdLine, X_OK) == 0)
1169         {
1170           // the arguments
1171           strcat (cmdLine, cmd + argsStart);
1172           break;
1173         }
1174       free (cmdLine);
1175       cmdLine = NULL;
1176       i++;
1177     }
1178
1179   if (verboseExec)
1180     {
1181       printf ("+ %s\n", cmdLine ? cmdLine : cmd);
1182     }
1183
1184   if (cmdLine)
1185     {
1186       // command found in predefined path
1187       e = system (cmdLine);
1188       free (cmdLine);
1189     }
1190   else
1191     {
1192       // trust on $PATH
1193       e = system (cmd);
1194     }
1195   return e;
1196 }
1197
1198
1199 /*-----------------------------------------------------------------*/
1200 /* linkEdit : - calls the linkage editor  with options             */
1201 /*-----------------------------------------------------------------*/
1202 static void
1203 linkEdit (char **envp)
1204 {
1205   FILE *lnkfile;
1206   char *segName, *c;
1207
1208   int i;
1209   if (!srcFileName)
1210     srcFileName = "temp";
1211
1212   /* first we need to create the <filename>.lnk file */
1213   sprintf (buffer, "%s.lnk", srcFileName);
1214   if (!(lnkfile = fopen (buffer, "w")))
1215     {
1216       werror (E_FILE_OPEN_ERR, buffer);
1217       exit (1);
1218     }
1219
1220   /* now write the options */
1221   fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1222
1223   /* if iram size specified */
1224   if (options.iram_size)
1225     fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1226
1227   /*if (options.debug) */
1228   fprintf (lnkfile, "-z\n");
1229
1230 #define WRITE_SEG_LOC(N, L) \
1231     segName = strdup(N); \
1232     c = strtok(segName, " \t"); \
1233     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1234     if (segName) { free(segName); }
1235
1236   /* code segment start */
1237   WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1238
1239   /* data segment start */
1240   WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1241
1242   /* xdata start */
1243   WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1244
1245   /* indirect data */
1246   WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1247
1248   /* bit segment start */
1249   WRITE_SEG_LOC (BIT_NAME, 0);
1250
1251   /* add the extra linker options */
1252   for (i = 0; linkOptions[i]; i++)
1253     fprintf (lnkfile, "%s\n", linkOptions[i]);
1254
1255   /* other library paths if specified */
1256   for (i = 0; i < nlibPaths; i++)
1257     fprintf (lnkfile, "-k %s\n", libPaths[i]);
1258
1259   /* standard library path */
1260   if (!options.nostdlib)
1261     {
1262       if (TARGET_IS_DS390)
1263         {
1264           c = "ds390";
1265         }
1266       else
1267         {
1268           switch (options.model)
1269             {
1270             case MODEL_SMALL:
1271               c = "small";
1272               break;
1273             case MODEL_LARGE:
1274               c = "large";
1275               break;
1276             case MODEL_FLAT24:
1277               c = "flat24";
1278               break;
1279             default:
1280               werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1281               c = "unknown";
1282               break;
1283             }
1284         }
1285       fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1286
1287       /* standard library files */
1288       if (strcmp (port->target, "ds390") == 0)
1289         {
1290           fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1291         }
1292       fprintf (lnkfile, "-l %s\n", STD_LIB);
1293       fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1294       fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1295       fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1296     }
1297
1298   /* additional libraries if any */
1299   for (i = 0; i < nlibFiles; i++)
1300     fprintf (lnkfile, "-l %s\n", libFiles[i]);
1301
1302   /* put in the object files */
1303   if (strcmp (srcFileName, "temp"))
1304     fprintf (lnkfile, "%s ", srcFileName);
1305
1306   for (i = 0; i < nrelFiles; i++)
1307     fprintf (lnkfile, "%s\n", relFiles[i]);
1308
1309   fprintf (lnkfile, "\n-e\n");
1310   fclose (lnkfile);
1311
1312   if (options.verbose)
1313     printf ("sdcc: Calling linker...\n");
1314
1315   buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1316   if (my_system (buffer))
1317     {
1318       exit (1);
1319     }
1320
1321   if (strcmp (srcFileName, "temp") == 0)
1322     {
1323       /* rename "temp.cdb" to "firstRelFile.cdb" */
1324       char *f = strtok (strdup (relFiles[0]), ".");
1325       f = strcat (f, ".cdb");
1326       rename ("temp.cdb", f);
1327       srcFileName = NULL;
1328     }
1329 }
1330
1331 /*-----------------------------------------------------------------*/
1332 /* assemble - spawns the assembler with arguments                  */
1333 /*-----------------------------------------------------------------*/
1334 static void
1335 assemble (char **envp)
1336 {
1337   buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1338   if (my_system (buffer))
1339     {
1340       /* either system() or the assembler itself has reported an error
1341          perror ("Cannot exec assembler");
1342        */
1343       exit (1);
1344     }
1345 }
1346
1347
1348
1349 /*-----------------------------------------------------------------*/
1350 /* preProcess - spawns the preprocessor with arguments       */
1351 /*-----------------------------------------------------------------*/
1352 static int
1353 preProcess (char **envp)
1354 {
1355   char procDef[128];
1356
1357   preOutName = NULL;
1358
1359   if (!options.c1mode)
1360     {
1361       /* if using external stack define the macro */
1362       if (options.useXstack)
1363         _addToList (preArgv, "-DSDCC_USE_XSTACK");
1364
1365       /* set the macro for stack autos  */
1366       if (options.stackAuto)
1367         _addToList (preArgv, "-DSDCC_STACK_AUTO");
1368
1369       /* set the macro for stack autos  */
1370       if (options.stack10bit)
1371         _addToList (preArgv, "-DSDCC_STACK_TENBIT");
1372
1373       /* set the macro for large model  */
1374       switch (options.model)
1375         {
1376         case MODEL_LARGE:
1377           _addToList (preArgv, "-DSDCC_MODEL_LARGE");
1378           break;
1379         case MODEL_SMALL:
1380           _addToList (preArgv, "-DSDCC_MODEL_SMALL");
1381           break;
1382         case MODEL_COMPACT:
1383           _addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1384           break;
1385         case MODEL_MEDIUM:
1386           _addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1387           break;
1388         case MODEL_FLAT24:
1389           _addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1390           break;
1391         default:
1392           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1393           break;
1394         }
1395
1396       /* standard include path */
1397       if (!options.nostdinc) {
1398         _addToList (preArgv, "-I" SDCC_INCLUDE_DIR);
1399       }
1400
1401       /* add port (processor information to processor */
1402       sprintf (procDef, "-DSDCC_%s", port->target);
1403       _addToList (preArgv, procDef);
1404       sprintf (procDef, "-D__%s", port->target);
1405       _addToList (preArgv, procDef);
1406
1407       if (!preProcOnly)
1408         preOutName = strdup (tmpnam (NULL));
1409
1410       if (options.verbose)
1411         printf ("sdcc: Calling preprocessor...\n");
1412
1413       buildCmdLine (buffer, _preCmd, fullSrcFileName,
1414                     preOutName, srcFileName, preArgv);
1415       if (my_system (buffer))
1416         {
1417           // @FIX: Dario Vecchio 03-05-2001
1418           if (preOutName)
1419             {
1420               unlink (preOutName);
1421               free (preOutName);
1422             }
1423           // EndFix
1424           exit (1);
1425         }
1426
1427       if (preProcOnly)
1428         exit (0);
1429     }
1430   else
1431     {
1432       preOutName = fullSrcFileName;
1433     }
1434
1435   yyin = fopen (preOutName, "r");
1436   if (yyin == NULL)
1437     {
1438       perror ("Preproc file not found\n");
1439       exit (1);
1440     }
1441
1442   return 0;
1443 }
1444
1445 static void
1446 _findPort (int argc, char **argv)
1447 {
1448   _validatePorts ();
1449
1450   argc--;
1451   while (argc)
1452     {
1453       if (!strncmp (*argv, "-m", 2))
1454         {
1455           _setPort (*argv + 2);
1456           return;
1457         }
1458       argv++;
1459       argc--;
1460     }
1461   /* Use the first in the list */
1462   port = _ports[0];
1463 }
1464
1465 /*
1466  * main routine
1467  * initialises and calls the parser
1468  */
1469
1470 int
1471 main (int argc, char **argv, char **envp)
1472 {
1473   /* turn all optimizations off by default */
1474   memset (&optimize, 0, sizeof (struct optimize));
1475
1476   /*printVersionInfo (); */
1477
1478   if (NUM_PORTS==0) {
1479     fprintf (stderr, "Build error: no ports are enabled.\n");
1480     exit (1);
1481   }
1482
1483   _findPort (argc, argv);
1484   /* Initalise the port. */
1485   if (port->init)
1486     port->init ();
1487
1488   // Create a default exe search path from the path to the sdcc command
1489
1490
1491
1492   if (strchr (argv[0], DIR_SEPARATOR_CHAR))
1493     {
1494       strcpy (DefaultExePath, argv[0]);
1495       *(strrchr (DefaultExePath, DIR_SEPARATOR_CHAR)) = 0;
1496       try_dir[0] = DefaultExePath;
1497     }
1498
1499
1500   setDefaultOptions ();
1501   parseCmdLine (argc, argv);
1502
1503   initMem ();
1504
1505   port->finaliseOptions ();
1506
1507   /* if no input then printUsage & exit */
1508   if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name))
1509     {
1510       printUsage ();
1511       exit (0);
1512     }
1513
1514   if (srcFileName)
1515     {
1516       preProcess (envp);
1517
1518       initSymt ();
1519       initiCode ();
1520       initCSupport ();
1521       initPeepHole ();
1522
1523       if (options.verbose)
1524         printf ("sdcc: Generating code...\n");
1525
1526       yyparse ();
1527
1528       if (!fatalError)
1529         {
1530           if (TARGET_IS_PIC) {
1531             /* TSD PIC port hack - if the PIC port option is enabled
1532                and SDCC is used to generate PIC code, then we will
1533                generate .asm files in gpasm's format instead of SDCC's
1534                assembler's format
1535             */
1536 #if !OPT_DISABLE_PIC
1537             picglue ();
1538 #endif
1539           } else {
1540             glue ();
1541           }
1542
1543           if (fatalError)
1544             {
1545               // @FIX: Dario Vecchio 03-05-2001
1546               if (preOutName)
1547                 {
1548                   if (yyin && yyin != stdin)
1549                     fclose (yyin);
1550                   unlink (preOutName);
1551                   free (preOutName);
1552                 }
1553               // EndFix
1554               return 1;
1555             }
1556           if (!options.c1mode)
1557             {
1558               if (options.verbose)
1559                 printf ("sdcc: Calling assembler...\n");
1560               assemble (envp);
1561             }
1562         }
1563       else
1564         {
1565           // @FIX: Dario Vecchio 03-05-2001
1566           if (preOutName)
1567             {
1568               if (yyin && yyin != stdin)
1569                 fclose (yyin);
1570               unlink (preOutName);
1571               free (preOutName);
1572             }
1573           // EndFix
1574           return 1;
1575         }
1576
1577     }
1578
1579   if (cdbFile)
1580     fclose (cdbFile);
1581
1582   if (!options.cc_only &&
1583       !fatalError &&
1584       !noAssemble &&
1585       !options.c1mode &&
1586       (srcFileName || nrelFiles))
1587     {
1588       if (port->linker.do_link)
1589         port->linker.do_link ();
1590       else
1591         linkEdit (envp);
1592     }
1593
1594   if (yyin && yyin != stdin)
1595     fclose (yyin);
1596
1597   if (preOutName && !options.c1mode)
1598     {
1599       unlink (preOutName);
1600       free (preOutName);
1601     }
1602
1603   return 0;
1604
1605 }