* src/SDCCmain.c (linkEdit): modifications only for pic16 port,
[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 #ifdef _WIN32
26 #include <io.h>
27 #else
28 #include <unistd.h>
29 #endif
30
31 #include <signal.h>
32 #include "common.h"
33 #include <ctype.h>
34 #include "newalloc.h"
35 #include "SDCCerr.h"
36 #include "BuildCmd.h"
37 #include "MySystem.h"
38 #include "SDCCmacro.h"
39 #include "SDCCutil.h"
40 #include "SDCCdebug.h"
41 #include "SDCCargs.h"
42
43 #ifdef _WIN32
44 #include <process.h>
45 #else
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #endif
49
50 /* REMOVE ME!!! */
51 extern int yyparse (void);
52
53 FILE *srcFile;                  /* source file          */
54 char *fullSrcFileName;          /* full name for the source file; */
55                                 /* can be NULL while c1mode or linking without compiling */
56 char *fullDstFileName;          /* full name for the output file; */
57                                 /* only given by -o, otherwise NULL */
58 char *dstFileName;              /* destination file name without extension */
59 char *dstPath = "";             /* path for the output files; */
60                                 /* "" is equivalent with cwd */
61 char *moduleNameBase;           /* module name base is source file without path and extension */
62                                 /* can be NULL while linking without compiling */
63 char *moduleName;               /* module name is same as module name base, but with all */
64                                 /* non-alphanumeric characters replaced with underscore */
65 int currRegBank = 0;
66 int RegBankUsed[4] = {1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
67 struct optimize optimize;
68 struct options options;
69 int preProcOnly = 0;
70 int noAssemble = 0;
71 set *preArgvSet = NULL;         /* pre-processor arguments  */
72 set *asmOptionsSet = NULL;      /* set of assembler options */
73 set *linkOptionsSet = NULL;     /* set of linker options */
74 set *libFilesSet = NULL;
75 set *libPathsSet = NULL;
76 set *relFilesSet = NULL;
77 set *dataDirsSet = NULL;        /* list of data search directories */
78 set *includeDirsSet = NULL;     /* list of include search directories */
79 set *libDirsSet = NULL;         /* list of lib search directories */
80
81 /* uncomment JAMIN_DS390 to always override and use ds390 port
82   for mcs51 work.  This is temporary, for compatibility testing. */
83 /* #define JAMIN_DS390 */
84 #ifdef JAMIN_DS390
85 int ds390_jammed = 0;
86 #endif
87
88 /* Globally accessible scratch buffer for file names. */
89 char scratchFileName[PATH_MAX];
90 char buffer[PATH_MAX * 2];
91
92 #define OPTION_HELP     "-help"
93
94 #define LENGTH(_a)      (sizeof(_a)/sizeof(*(_a)))
95
96 #define OPTION_STACK_8BIT       "--stack-8bit"
97 #define OPTION_OUT_FMT_IHX      "--out-fmt-ihx"
98 #define OPTION_LARGE_MODEL      "--model-large"
99 #define OPTION_MEDIUM_MODEL     "--model-medium"
100 #define OPTION_SMALL_MODEL      "--model-small"
101 #define OPTION_FLAT24_MODEL     "--model-flat24"
102 #define OPTION_DUMP_ALL         "--dumpall"
103 #define OPTION_PEEP_FILE        "--peep-file"
104 #define OPTION_LIB_PATH         "--lib-path"
105 #define OPTION_XSTACK_LOC       "--xstack-loc"
106 #define OPTION_CALLEE_SAVES     "--callee-saves"
107 #define OPTION_STACK_LOC        "--stack-loc"
108 #define OPTION_XRAM_LOC         "--xram-loc"
109 #define OPTION_IRAM_SIZE        "--iram-size"
110 #define OPTION_VERSION          "--version"
111 #define OPTION_DATA_LOC         "--data-loc"
112 #define OPTION_CODE_LOC         "--code-loc"
113 #define OPTION_IDATA_LOC        "--idata-loc"
114 #define OPTION_NO_LABEL_OPT     "--nolabelopt"
115 #define OPTION_NO_LOOP_INV      "--noinvariant"
116 #define OPTION_NO_LOOP_IND      "--noinduction"
117 #define OPTION_LESS_PEDANTIC    "--less-pedantic"
118 #define OPTION_NO_GCSE          "--nogcse"
119 #define OPTION_SHORT_IS_8BITS   "--short-is-8bits"
120 #define OPTION_TINI_LIBID       "--tini-libid"
121 #define OPTION_NO_XINIT_OPT     "--no-xinit-opt"
122 #define OPTION_XRAM_SIZE        "--xram-size"
123 #define OPTION_CODE_SIZE        "--code-size"
124 #define OPTION_NO_CCODE_IN_ASM  "--no-c-code-in-asm"
125 #define OPTION_ICODE_IN_ASM     "--i-code-in-asm"
126 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
127 #define OPTION_MSVC_ERROR_STYLE "--vc"
128 #define OPTION_USE_STDOUT       "--use-stdout"
129 #define OPTION_STACK_SIZE       "--stack-size"
130 #define OPTION_PACK_IRAM        "--pack-iram"
131 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
132
133 static const OPTION
134 optionsTable[] = {
135     { 'm',  NULL,                   NULL, "Set the port to use e.g. -mz80." },
136     { 'p',  NULL,                   NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
137     { 'd',  NULL,                   NULL, NULL },
138     { 'D',  NULL,                   NULL, "Define macro as in -Dmacro" },
139     { 'I',  NULL,                   NULL, "Add to the include (*.h) path, as in -Ipath" },
140     { 'A',  NULL,                   NULL, NULL },
141     { 'U',  NULL,                   NULL, NULL },
142     { 'C',  NULL,                   NULL, "Preprocessor option" },
143     { 'M',  NULL,                   NULL, "Preprocessor option" },
144     { 'V',  NULL,                   &options.verboseExec, "Execute verbosely.  Show sub commands as they are run" },
145     { 'S',  NULL,                   &noAssemble, "Compile only; do not assemble or link" },
146     { 'W',  NULL,                   NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
147     { 'L',  NULL,                   NULL, "Add the next field to the library search path" },
148     { 'l',  NULL,                   NULL, "Include the given library in the link" },
149     { 0,    OPTION_LARGE_MODEL,     NULL, "external data space is used" },
150     { 0,    OPTION_MEDIUM_MODEL,    NULL, "not supported" },
151     { 0,    OPTION_SMALL_MODEL,     NULL, "internal data space is used (default)" },
152 #if !OPT_DISABLE_DS390
153     { 0,    OPTION_FLAT24_MODEL,    NULL, "use the flat24 model for the ds390 (default)" },
154 #endif
155     { 0,    "--stack-auto",         &options.stackAuto, "Stack automatic variables" },
156 #if !OPT_DISABLE_DS390
157     { 0,    OPTION_STACK_8BIT,      NULL, "use the 8bit stack for the ds390 (not supported yet)" },
158     { 0,    "--stack-10bit",        &options.stack10bit, "use the 10bit stack for ds390 (default)" },
159 #endif
160     { 0,    "--xstack",             &options.useXstack, "Use external stack" },
161     { 0,    OPTION_NO_GCSE,         NULL, "Disable the GCSE optimisation" },
162     { 0,    OPTION_NO_LABEL_OPT,    NULL, "Disable label optimisation" },
163     { 0,    OPTION_NO_LOOP_INV,     NULL, "Disable optimisation of invariants" },
164     { 0,    OPTION_NO_LOOP_IND,     NULL, NULL },
165     { 0,    "--nojtbound",          &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
166     { 0,    "--noloopreverse",      &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
167     { 'c',  "--compile-only",       &options.cc_only, "Compile and assemble, but do not link" },
168     { 'o',  NULL,                   NULL, "Place the output into the given path resp. file" },
169     { 0,    "--dumpraw",            &options.dump_raw, "Dump the internal structure after the initial parse" },
170     { 0,    "--dumpgcse",           &options.dump_gcse, NULL },
171     { 0,    "--dumploop",           &options.dump_loop, NULL },
172     { 0,    "--dumpdeadcode",       &options.dump_kill, NULL },
173     { 0,    "--dumpliverange",      &options.dump_range, NULL },
174     { 0,    "--dumpregpack",        &options.dump_pack, NULL },
175     { 0,    "--dumpregassign",      &options.dump_rassgn, NULL },
176     { 0,    "--dumptree",           &options.dump_tree, "dump front-end AST before generating iCode" },
177     { 0,    OPTION_DUMP_ALL,        NULL, "Dump the internal structure at all stages" },
178     { 0,    OPTION_XRAM_LOC,        NULL, "<nnnn> External Ram start location" },
179     { 0,    OPTION_XRAM_SIZE,       NULL, "<nnnn> External Ram size" },
180     { 0,    OPTION_IRAM_SIZE,       NULL, "<nnnn> Internal Ram size" },
181     { 0,    OPTION_XSTACK_LOC,      NULL, "<nnnn> External Ram start location" },
182     { 0,    OPTION_CODE_LOC,        NULL, "<nnnn> Code Segment Location" },
183     { 0,    OPTION_CODE_SIZE,       NULL, "<nnnn> Code Segment size" },
184     { 0,    OPTION_STACK_LOC,       NULL, "<nnnn> Stack pointer initial value" },
185     { 0,    OPTION_DATA_LOC,        NULL, "<nnnn> Direct data start location" },
186     { 0,    OPTION_IDATA_LOC,       NULL, NULL },
187     { 0,    OPTION_PEEP_FILE,       NULL, "<file> use this extra peep-hole file" },
188     { 0,    OPTION_LIB_PATH,        NULL, "<path> use this path to search for libraries" },
189     { 0,    "--int-long-reent",     &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
190     { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the float support functions" },
191     { 0,    OPTION_OUT_FMT_IHX,     NULL, NULL },
192     { 0,    "--out-fmt-s19",        &options.out_fmt, NULL },
193     { 0,    "--cyclomatic",         &options.cyclomatic, NULL },
194     { 0,    "--nooverlay",          &options.noOverlay, NULL },
195     { 0,    "--main-return",        &options.mainreturn, "Issue a return after main()" },
196     { 0,    "--xram-movc",          &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
197     { 0,    "--no-peep",            &options.nopeep, "Disable the peephole assembly file optimisation" },
198     { 0,    "--no-reg-params",      &options.noRegParams, "On some ports, disable passing some parameters in registers" },
199     { 0,    "--peep-asm",           &options.asmpeep, NULL },
200     { 0,    "--debug",              &options.debug, "Enable debugging symbol output" },
201     { 'v',  OPTION_VERSION,         NULL, "Display sdcc's version" },
202     { 'E',  "--preprocessonly",     &preProcOnly, "Preprocess only, do not compile" },
203     { 0,    "--c1mode",             &options.c1mode, "Act in c1 mode.  The standard input is preprocessed code, the output is assembly code." },
204     { 0,    "--help",               NULL, "Display this help" },
205     { 0,    OPTION_CALLEE_SAVES,    NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
206     { 0,    "--nostdlib",           &options.nostdlib, "Do not include the standard library directory in the search path" },
207     { 0,    "--nostdinc",           &options.nostdinc, "Do not include the standard include directory in the search path" },
208     { 0,    "--verbose",            &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
209     { 0,    OPTION_LESS_PEDANTIC,   NULL, "Disable some of the more pedantic warnings" },
210     { 0,    OPTION_SHORT_IS_8BITS,   NULL, "Make short 8bits (for old times sake)" },
211     { 0,    "--profile",            &options.profile, "On supported ports, generate extra profiling information" },
212     { 0,    "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
213     { 0,    "--all-callee-saves",   &options.all_callee_saves, "callee will always save registers used" },
214 #if !OPT_DISABLE_DS390
215     { 0,    "--use-accelerator",    &options.useAccelerator,"generate code for  DS390 Arithmetic Accelerator"},
216 #endif
217     { 0,    "--stack-probe",        &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
218 #if !OPT_DISABLE_TININative
219     { 0,    "--tini-libid",         NULL,"<nnnn> LibraryID used in -mTININative"},
220 #endif
221 #if !OPT_DISABLE_DS390
222     { 0,    "--protect-sp-update",  &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
223 #endif
224 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
225     { 0,    "--parms-in-bank1",     &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
226     { 0,    OPTION_STACK_SIZE,      NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
227     { 0,    OPTION_PACK_IRAM,       &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
228 #endif
229     { 0,    OPTION_NO_XINIT_OPT,    &options.noXinitOpt, "don't memcpy initialized xram from code"},
230     { 0,    OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
231     { 0,    OPTION_ICODE_IN_ASM,    &options.iCodeInAsm, "include i-code as comments in the asm file"},
232     { 0,    OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
233     { 0,    OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
234     { 0,    OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
235     { 0,    OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
236 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
237     { 0,    "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
238 #endif
239     /* End of options */
240     { 0,    NULL }
241 };
242
243 /** Table of all unsupported options and help text to display when one
244     is used.
245 */
246 typedef struct {
247     /** shortOpt as in OPTIONS. */
248     char shortOpt;
249     /** longOpt as in OPTIONS. */
250     const char *longOpt;
251     /** Message to display inside W_UNSUPPORTED_OPT when this option
252         is used. */
253     const char *message;
254 } UNSUPPORTEDOPT;
255
256 static const UNSUPPORTEDOPT 
257 unsupportedOptTable[] = {
258     { 'X',  NULL,       "use --xstack-loc instead" },
259     { 'x',  NULL,       "use --xstack instead" },
260     { 'i',  NULL,       "use --idata-loc instead" },
261     { 'r',  NULL,       "use --xdata-loc instead" },
262     { 's',  NULL,       "use --code-loc instead" },
263     { 'Y',  NULL,       "use -I instead" }
264 };
265
266 /** List of all default constant macros.
267  */
268 static const char *_baseValues[] = {
269   "cpp", "sdcpp",
270   "cppextraopts", "",
271   /* Path seperator character */
272   "sep", DIR_SEPARATOR_STRING,
273   NULL
274 };
275
276 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
277
278 PORT *port;
279
280 static PORT *_ports[] =
281 {
282 #if !OPT_DISABLE_MCS51
283   &mcs51_port,
284 #endif
285 #if !OPT_DISABLE_GBZ80
286   &gbz80_port,
287 #endif
288 #if !OPT_DISABLE_Z80
289   &z80_port,
290 #endif
291 #if !OPT_DISABLE_AVR
292   &avr_port,
293 #endif
294 #if !OPT_DISABLE_DS390
295   &ds390_port,
296 #endif
297 #if !OPT_DISABLE_PIC16
298   &pic16_port,
299 #endif
300 #if !OPT_DISABLE_PIC
301   &pic_port,
302 #endif
303 #if !OPT_DISABLE_TININative
304   &tininative_port,
305 #endif
306 #if !OPT_DISABLE_XA51
307   &xa51_port,
308 #endif
309 #if !OPT_DISABLE_DS400
310   &ds400_port,  
311 #endif
312 #if !OPT_DISABLE_HC08
313   &hc08_port,
314 #endif
315 };
316
317 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
318
319 /** Sets the port to the one given by the command line option.
320     @param    The name minus the option (eg 'mcs51')
321     @return     0 on success.
322 */
323 static void
324 _setPort (const char *name)
325 {
326   int i;
327   for (i = 0; i < NUM_PORTS; i++)
328     {
329       if (!strcmp (_ports[i]->target, name))
330         {
331           port = _ports[i];
332           return;
333         }
334     }
335   /* Error - didnt find */
336   werror (E_UNKNOWN_TARGET, name);
337   exit (1);
338 }
339
340 /* Override the default processor with the one specified 
341  * on the command line */
342 static void
343 _setProcessor (char *_processor)
344 {
345   port->processor = _processor;
346   fprintf(stderr,"Processor: %s\n",_processor);
347 }
348
349 static void
350 _validatePorts (void)
351 {
352   int i;
353   for (i = 0; i < NUM_PORTS; i++)
354     {
355       if (_ports[i]->magic != PORT_MAGIC)
356         {
357           /* Uncomment this line to debug which port is causing the problem
358            * (the target name is close to the beginning of the port struct 
359            * and probably can be accessed just fine). */
360           fprintf(stderr,"%s :",_ports[i]->target);
361           wassertl (0, "Port definition structure is incomplete");
362         }
363     }
364 }
365
366 /* search through the command line options for the port */
367 static void
368 _findPort (int argc, char **argv)
369 {
370   _validatePorts ();
371
372   while (argc--)
373     {
374       if (!strncmp (*argv, "-m", 2))
375         {
376           _setPort (*argv + 2);
377           return;
378         }
379       argv++;
380     }
381
382   /* Use the first in the list */
383         port = _ports[0];
384 }
385
386 /* search through the command line options for the processor */
387 static void
388 _findProcessor (int argc, char **argv)
389 {
390   while (argc--)
391     {
392       if (!strncmp (*argv, "-p", 2))
393         {
394           _setProcessor (*argv + 2);
395           return;
396         }
397       argv++;
398     }
399
400   /* no error if processor was not specified. */
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* printVersionInfo - prints the version info        */
405 /*-----------------------------------------------------------------*/
406 void
407 printVersionInfo (void)
408 {
409   int i;
410
411   fprintf (stderr,
412            "SDCC : ");
413   for (i = 0; i < NUM_PORTS; i++)
414     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
415   
416   fprintf (stderr, " " SDCC_VERSION_STR
417 #ifdef SDCC_SUB_VERSION_STR
418            "/" SDCC_SUB_VERSION_STR
419 #endif
420            " (" __DATE__ ")"
421 #ifdef __CYGWIN__
422            " (CYGWIN)\n"
423 #elif defined __MINGW32__
424            " (MINGW32)\n"
425 #elif defined __DJGPP__
426            " (DJGPP)\n"
427 #elif defined(_MSC_VER)
428            " (MSVC)\n"
429 #elif defined(__BORLANDC__)
430            " (BORLANDC)\n"
431 #else
432            " (UNIX) \n"
433 #endif
434     );
435 }
436
437 static void
438 printOptions(const OPTION *optionsTable)
439 {
440   int i;
441   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++) 
442     {
443       fprintf(stdout, "  %c%c  %-20s  %s\n", 
444               optionsTable[i].shortOpt !=0 ? '-' : ' ',
445               optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
446               optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
447               optionsTable[i].help != NULL ? optionsTable[i].help : ""
448               );
449     }
450 }
451
452 /*-----------------------------------------------------------------*/
453 /* printUsage - prints command line syntax         */
454 /*-----------------------------------------------------------------*/
455 void
456 printUsage (void)
457 {
458     int i;
459     printVersionInfo();
460     fprintf (stdout,
461              "Usage : sdcc [options] filename\n"
462              "Options :-\n"
463              );
464
465     printOptions(optionsTable);
466
467     for (i = 0; i < NUM_PORTS; i++)
468       {
469         if (_ports[i]->poptions != NULL)
470           {
471             fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
472             printOptions (_ports[i]->poptions);
473           }
474       }
475
476     exit (0);
477 }
478
479 /*-----------------------------------------------------------------*/
480 /* setParseWithComma - separates string with comma to a set        */
481 /*-----------------------------------------------------------------*/
482 void
483 setParseWithComma (set **dest, char *src)
484 {
485   char *p;
486   int length;
487
488   /* skip the initial white spaces */
489   while (isspace(*src))
490     src++;
491   
492   /* skip the trailing white spaces */
493   length = strlen(src);
494   while (length && isspace(src[length-1]))
495     src[--length] = '\0';
496
497   for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
498     addSet(dest, Safe_strdup(p));
499 }
500
501 /*-----------------------------------------------------------------*/
502 /* setDefaultOptions - sets the default options                    */
503 /*-----------------------------------------------------------------*/
504 static void
505 setDefaultOptions (void)
506 {
507   /* first the options part */
508   options.stack_loc = 0;        /* stack pointer initialised to 0 */
509   options.xstack_loc = 0;       /* xternal stack starts at 0 */
510   options.code_loc = 0;         /* code starts at 0 */
511   options.data_loc = 0;         /* JCF: By default let the linker locate data */
512   options.xdata_loc = 0;
513   options.idata_loc = 0x80;
514   options.nopeep = 0;
515   options.model = port->general.default_model;
516   options.nostdlib = 0;
517   options.nostdinc = 0;
518   options.verbose = 0;
519   options.shortis8bits = 0;
520
521   options.stack10bit=0;
522
523   /* now for the optimizations */
524   /* turn on the everything */
525   optimize.global_cse = 1;
526   optimize.label1 = 1;
527   optimize.label2 = 1;
528   optimize.label3 = 1;
529   optimize.label4 = 1;
530   optimize.loopInvariant = 1;
531   optimize.loopInduction = 1;
532
533   /* now for the ports */
534   port->setDefaultOptions ();
535 }
536
537 /*-----------------------------------------------------------------*/
538 /* processFile - determines the type of file from the extension    */
539 /*-----------------------------------------------------------------*/
540 static void
541 processFile (char *s)
542 {
543   char *fext = NULL;
544
545   /* get the file extension */
546   fext = s + strlen (s);
547   while ((fext != s) && *fext != '.')
548     fext--;
549
550   /* now if no '.' then we don't know what the file type is
551      so give a warning and return */
552   if (fext == s)
553     {
554       werror (W_UNKNOWN_FEXT, s);
555       return;
556     }
557
558   /* otherwise depending on the file type */
559   if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
560     {
561       /* source file name : not if we already have a
562          source file */
563       if (fullSrcFileName)
564         {
565           werror (W_TOO_MANY_SRC, s);
566           return;
567         }
568
569       /* the only source file */
570       fullSrcFileName = s;
571       if (!(srcFile = fopen (fullSrcFileName, "r")))
572         {
573           werror (E_FILE_OPEN_ERR, s);
574           exit (1);
575         }
576
577       /* copy the file name into the buffer */
578       strncpyz (buffer, s, sizeof(buffer));
579
580       /* get rid of the "."-extension */
581
582       /* is there a dot at all? */
583       if (strrchr (buffer, '.') &&
584           /* is the dot in the filename, not in the path? */
585           (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
586         {
587         *strrchr (buffer, '.') = '\0';
588         }
589
590       /* get rid of any path information
591          for the module name; */
592       fext = buffer + strlen (buffer);
593 #if NATIVE_WIN32
594       /* do this by going backwards till we
595          get '\' or ':' or start of buffer */
596       while (fext != buffer &&
597              *(fext - 1) != DIR_SEPARATOR_CHAR &&
598              *(fext - 1) != ':')
599         {
600         fext--;
601         }
602 #else
603       /* do this by going backwards till we
604          get '/' or start of buffer */
605       while (fext != buffer &&
606              *(fext - 1) != DIR_SEPARATOR_CHAR)
607         {
608           fext--;
609         }
610 #endif
611       moduleNameBase = Safe_strdup ( fext );
612       moduleName = Safe_strdup ( fext );
613       
614       for (fext = moduleName; *fext; fext++)
615         if (!isalnum (*fext))
616           *fext = '_';
617       return;
618     }
619
620   /* if the extention is type .rel or .r or .REL or .R
621      addtional object file will be passed to the linker */
622   if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
623       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
624       strcmp (fext, port->linker.rel_ext) == 0)
625     {
626       addSet(&relFilesSet, Safe_strdup(s));
627       return;
628     }
629
630   /* if .lib or .LIB */
631   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
632     {
633       addSet(&libFilesSet, Safe_strdup(s));
634       return;
635     }
636
637   werror (W_UNKNOWN_FEXT, s);
638
639 }
640
641 static void
642 _setModel (int model, const char *sz)
643 {
644   if (port->general.supported_models & model)
645     options.model = model;
646   else
647     werror (W_UNSUPPORTED_MODEL, sz, port->target);
648 }
649
650 /** Gets the string argument to this option.  If the option is '--opt'
651     then for input of '--optxyz' or '--opt xyz' returns xyz.
652 */
653 char *
654 getStringArg(const char *szStart, char **argv, int *pi, int argc)
655 {
656   if (argv[*pi][strlen(szStart)])
657     {
658       return &argv[*pi][strlen(szStart)];
659     }
660   else
661     {
662       ++(*pi);
663       if (*pi >= argc)
664         {
665           werror (E_ARGUMENT_MISSING, szStart);
666           /* Die here rather than checking for errors later. */
667           exit(-1);
668         }
669       else
670         {
671           return argv[*pi];
672         }
673     }
674 }
675
676 /** Gets the integer argument to this option using the same rules as
677     getStringArg.
678 */
679 int
680 getIntArg(const char *szStart, char **argv, int *pi, int argc)
681 {
682     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
683 }
684
685 static void
686 verifyShortOption(const char *opt)
687 {
688   if (strlen(opt) != 2)
689     {
690       werror (W_EXCESS_SHORT_OPTIONS, opt);
691     }
692 }
693
694 static bool
695 tryHandleUnsupportedOpt(char **argv, int *pi)
696 {
697     if (argv[*pi][0] == '-') 
698         {
699             const char *longOpt = "";
700             char shortOpt = -1;
701             int i;
702
703             if (argv[*pi][1] == '-') 
704                 {
705                     /* Long option. */
706                     longOpt = argv[*pi];
707                 }
708             else 
709                 {
710                     shortOpt = argv[*pi][1];
711                 }
712             for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
713                 {
714                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
715                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
716                         /* Found an unsupported opt. */
717                         char buffer[100];
718                         SNPRINTF(buffer, sizeof(buffer), 
719                                  "%s%c%c", 
720                                  longOpt ? longOpt : "", 
721                                  shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
722                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
723                         return 1;
724                     }
725                 }
726             /* Didn't find in the table */
727             return 0;
728         }
729     else 
730         {
731             /* Not an option, so can't be unsupported :) */
732             return 0;
733     }
734 }
735
736 static bool
737 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
738 {
739   int i;
740   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
741     {
742       if (optionsTable[i].shortOpt == shortOpt ||
743           (longOpt && optionsTable[i].longOpt && 
744            strcmp(optionsTable[i].longOpt, longOpt) == 0))
745         {
746
747           /* If it is a flag then we can handle it here */
748           if (optionsTable[i].pparameter != NULL) 
749             {
750               if (optionsTable[i].shortOpt == shortOpt)
751                 {
752                   verifyShortOption(argv[*pi]);
753                 }
754
755               (*optionsTable[i].pparameter)++;
756               return 1;
757             }
758           else {
759             /* Not a flag.  Handled manually later. */
760             return 0;
761           }
762         }
763     }
764   /* Didn't find in the table */
765   return 0;
766 }
767
768 static bool
769 tryHandleSimpleOpt(char **argv, int *pi)
770 {
771     if (argv[*pi][0] == '-') 
772         {
773             const char *longOpt = "";
774             char shortOpt = -1;
775
776             if (argv[*pi][1] == '-') 
777                 {
778                     /* Long option. */
779                     longOpt = argv[*pi];
780                 }
781             else 
782                 {
783                     shortOpt = argv[*pi][1];
784                 }
785
786             if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
787               {
788                 return 1;
789               }
790             else if (port && port->poptions &&
791                      scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
792               {
793                 return 1;
794               }
795             else
796               {
797                 return 0;
798               }
799         }
800     else 
801         {
802             /* Not an option, so can't be handled. */
803             return 0;
804         }
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* parseCmdLine - parses the command line and sets the options     */
809 /*-----------------------------------------------------------------*/
810 static int
811 parseCmdLine (int argc, char **argv)
812 {
813   int i;
814
815   /* go thru all whole command line */
816   for (i = 1; i < argc; i++)
817     {
818       if (i >= argc)
819         break;
820
821       if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
822           {
823               continue;
824           }
825
826       if (tryHandleSimpleOpt(argv, &i) == TRUE)
827           {
828               continue;
829           }
830
831       /* options */
832       if (argv[i][0] == '-' && argv[i][1] == '-')
833         {
834           if (strcmp (argv[i], OPTION_HELP) == 0)
835             {
836               printUsage ();
837               exit (0);
838             }
839
840           if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
841             {
842               options.stack10bit = 0;
843               continue;
844             }
845
846           if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
847             {
848               options.out_fmt = 0;
849               continue;
850             }
851
852           if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
853             {
854               _setModel (MODEL_LARGE, argv[i]);
855               continue;
856             }
857
858           if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
859             {
860               _setModel (MODEL_MEDIUM, argv[i]);
861               continue;
862             }
863
864           if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
865             {
866               _setModel (MODEL_SMALL, argv[i]);
867               continue;
868             }
869
870           if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
871             {
872               _setModel (MODEL_FLAT24, argv[i]);
873               continue;
874             }
875
876           if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
877             {
878               options.dump_rassgn =
879                 options.dump_pack =
880                 options.dump_range =
881                 options.dump_kill =
882                 options.dump_loop =
883                 options.dump_gcse =
884                 options.dump_raw = 1;
885               continue;
886             }
887
888           if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
889             {
890                 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
891                 continue;
892             }
893
894           if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
895             {
896                 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
897                 continue;
898             }
899
900           if (strcmp (argv[i], OPTION_VERSION) == 0)
901             {
902               printVersionInfo ();
903               exit (0);
904               continue;
905             }
906
907           if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
908             {
909                 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
910                 continue;
911             }
912
913           if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
914             {
915                 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
916                 continue;
917             }
918
919           if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
920             {
921                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
922                 continue;
923             }
924           
925       if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
926             {
927                 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
928                 continue;
929             }
930
931           if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
932             {
933                 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
934                 continue;
935             }
936
937           if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
938             {
939                 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
940                 continue;
941             }
942
943           if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
944             {
945                 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
946                 options.xram_size_set = TRUE;
947                 continue;
948             }
949
950           if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
951             {
952                 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
953                 continue;
954             }
955
956           if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
957             {
958                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
959                 continue;
960             }
961
962           if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
963             {
964                 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
965                 continue;
966             }
967
968           if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
969             {
970                 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
971                 continue;
972             }
973
974           if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
975             {
976               optimize.global_cse = 0;
977               continue;
978             }
979
980           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
981             {
982               optimize.loopInvariant = 0;
983               continue;
984             }
985
986           if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
987             {
988               optimize.label4 = 0;
989               continue;
990             }
991
992           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
993             {
994               optimize.loopInduction = 0;
995               continue;
996             }
997
998           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
999             {
1000               options.lessPedantic = 1;
1001               setErrorLogLevel(ERROR_LEVEL_WARNING);
1002               continue;
1003             }
1004
1005           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
1006             {
1007               options.shortis8bits=1;
1008               continue;
1009             }
1010
1011           if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1012             {
1013                 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1014                 continue;
1015             }
1016           
1017           if (!port->parseOption (&argc, argv, &i))
1018             {
1019               werror (W_UNKNOWN_OPTION, argv[i]);
1020               continue;
1021             }
1022           else
1023             {
1024               continue;
1025             }
1026         }
1027
1028       /* if preceded by  '-' then option */
1029       if (*argv[i] == '-')
1030         {
1031           switch (argv[i][1])
1032             {
1033             case 'h':
1034               verifyShortOption(argv[i]);
1035
1036               printUsage ();
1037               exit (0);
1038               break;
1039
1040             case 'm':
1041               /* Used to select the port. But this has already been done. */
1042               break;
1043
1044             case 'p':
1045               /* Used to select the processor in port. But this has
1046                * already been done. */
1047               break;
1048
1049             case 'c':
1050               verifyShortOption(argv[i]);
1051
1052               options.cc_only = 1;
1053               break;
1054
1055             case 'L':
1056                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1057                 break;
1058
1059             case 'l':
1060                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1061                 break;
1062             
1063             case 'o':
1064               {
1065                 char *p;
1066
1067                 /* copy the file name into the buffer */
1068                 strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
1069                          sizeof(buffer));
1070                 /* point to last character */
1071                 p = buffer + strlen (buffer) - 1;
1072                 if (*p == DIR_SEPARATOR_CHAR)
1073                   {
1074                     /* only output path specified */
1075                     dstPath = Safe_strdup (buffer);
1076                     fullDstFileName = NULL;
1077                   }
1078                 else
1079                   {
1080                     fullDstFileName = Safe_strdup (buffer);
1081
1082                     /* get rid of the "."-extension */
1083
1084                     /* is there a dot at all? */
1085                     if (strrchr (buffer, '.') &&
1086                         /* is the dot in the filename, not in the path? */
1087                         (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1088                       *strrchr (buffer, '.') = '\0';
1089
1090                     dstFileName = Safe_strdup (buffer);
1091
1092                     /* strip module name to get path */
1093                     p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1094                     if (p)
1095                       {
1096                         /* path with trailing / */
1097                         p[1] = '\0';
1098                         dstPath = Safe_strdup (buffer);
1099                       }
1100                   }
1101                 break;
1102               }
1103
1104             case 'W':
1105               /* pre-processer options */
1106               if (argv[i][2] == 'p')
1107                 {
1108                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1109                 }
1110               /* linker options */
1111               else if (argv[i][2] == 'l')
1112                 {
1113                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1114                 }
1115               /* assembler options */
1116               else if (argv[i][2] == 'a')
1117                 {
1118                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1119                 }
1120               else
1121                 {
1122                   werror (W_UNKNOWN_OPTION, argv[i]);
1123                 }
1124               break;
1125
1126             case 'v':
1127               verifyShortOption(argv[i]);
1128
1129               printVersionInfo ();
1130               exit (0);
1131               break;
1132
1133               /* preprocessor options */
1134             case 'M':
1135               {
1136                 preProcOnly = 1;
1137                 if (argv[i][2] == 'M')
1138                   addSet(&preArgvSet, Safe_strdup("-MM"));
1139                 else
1140                   addSet(&preArgvSet, Safe_strdup("-M"));
1141                 break;
1142               }
1143             case 'C':
1144               {
1145                 addSet(&preArgvSet, Safe_strdup("-C"));
1146                 break;
1147               }
1148
1149             case 'd':
1150             case 'D':
1151             case 'I':
1152             case 'A':
1153             case 'U':
1154               {
1155                 char sOpt = argv[i][1];
1156                 char *rest;
1157
1158                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1159                   {
1160                     i++;
1161                     if (i >= argc)
1162                       {
1163                           /* No argument. */
1164                           werror(E_ARGUMENT_MISSING, argv[i-1]);
1165                           break;
1166                       }
1167                     else
1168                       {
1169                           rest = argv[i];
1170                       }
1171                   }
1172                 else
1173                   rest = &argv[i][2];
1174
1175                 if (sOpt == 'Y')
1176                   sOpt = 'I';
1177
1178                 SNPRINTF (buffer, sizeof(buffer),
1179                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1180                 addSet(&preArgvSet, Safe_strdup(buffer));
1181               }
1182               break;
1183
1184             default:
1185               if (!port->parseOption (&argc, argv, &i))
1186                 werror (W_UNKNOWN_OPTION, argv[i]);
1187             }
1188           continue;
1189         }
1190
1191       if (!port->parseOption (&argc, argv, &i))
1192         {
1193            /* no option must be a filename */
1194            if (options.c1mode)
1195              {
1196                 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1197              }
1198          else
1199              {
1200                 processFile (argv[i]);
1201              }
1202         }
1203     }
1204
1205   /* some sanity checks in c1 mode */
1206   if (options.c1mode)
1207     {
1208       const char *s;
1209
1210       if (fullSrcFileName)
1211         {
1212           fclose (srcFile);
1213           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1214         }
1215       fullSrcFileName = NULL;
1216       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1217         {
1218           werror (W_NO_FILE_ARG_IN_C1, s);
1219         }
1220       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1221         {
1222           werror (W_NO_FILE_ARG_IN_C1, s);
1223         }
1224       deleteSet(&relFilesSet);
1225       deleteSet(&libFilesSet);
1226
1227         if (options.cc_only || noAssemble || preProcOnly)
1228         {
1229           werror (W_ILLEGAL_OPT_COMBINATION);
1230         }
1231       options.cc_only = noAssemble = preProcOnly = 0;
1232       if (!dstFileName)
1233         {
1234           werror (E_NEED_OPT_O_IN_C1);
1235           exit (1);
1236         }
1237     }
1238   /* if no dstFileName given with -o, we've to find one: */
1239   if (!dstFileName)
1240     {
1241       const char *s;
1242
1243       /* use the modulename from the C-source */
1244       if (fullSrcFileName)
1245         {
1246           size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1247
1248           dstFileName = Safe_alloc (bufSize);
1249           strncpyz (dstFileName, dstPath, bufSize);
1250           strncatz (dstFileName, moduleNameBase, bufSize);
1251         }
1252       /* use the modulename from the first object file */
1253       else if ((s = peekSet(relFilesSet)) != NULL)
1254         {
1255           char *objectName;
1256           size_t bufSize;
1257
1258           strncpyz (buffer, s, sizeof(buffer));
1259           /* remove extension (it must be .rel) */
1260           *strrchr (buffer, '.') = '\0';
1261           /* remove path */
1262           objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1263           if (objectName)
1264             {
1265               ++objectName;
1266             }
1267           else
1268             {
1269               objectName = buffer;
1270             }
1271           bufSize = strlen (dstPath) + strlen (objectName) + 1;  
1272           dstFileName = Safe_alloc (bufSize);
1273           strncpyz (dstFileName, dstPath, bufSize);
1274           strncatz (dstFileName, objectName, bufSize);
1275         }
1276       /* else no module given: help text is displayed */
1277     }
1278
1279   /* set up external stack location if not explicitly specified */
1280   if (!options.xstack_loc)
1281     options.xstack_loc = options.xdata_loc;
1282
1283   /* if debug option is set then open the cdbFile */
1284   if (options.debug && fullSrcFileName)
1285     {
1286       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1287                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1288       if(debugFile->openFile(scratchFileName))
1289         debugFile->writeModule(moduleName);
1290       else
1291         werror (E_FILE_OPEN_ERR, scratchFileName);
1292     }
1293   MSVC_style(options.vc_err_style);
1294   if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1295
1296   return 0;
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* linkEdit : - calls the linkage editor  with options             */
1301 /*-----------------------------------------------------------------*/
1302 static void
1303 linkEdit (char **envp)
1304 {
1305   FILE *lnkfile;
1306   char *segName, *c;
1307   int system_ret;
1308   const char *s;
1309
1310
1311   if(port->linker.needLinkerScript)
1312     {
1313       char out_fmt;
1314       
1315       switch (options.out_fmt)
1316         {
1317         case 0:
1318           out_fmt = 'i';        /* Intel hex */
1319           break;
1320         case 1:
1321           out_fmt = 's';        /* Motorola S19 */
1322           break;
1323         case 2:
1324           out_fmt = 't';        /* Elf */
1325           break;
1326         default:
1327           out_fmt = 'i';
1328         }
1329       
1330       /* first we need to create the <filename>.lnk file */
1331       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1332         "%s.lnk", dstFileName);
1333       if (!(lnkfile = fopen (scratchFileName, "w")))
1334         {
1335           werror (E_FILE_OPEN_ERR, scratchFileName);
1336           exit (1);
1337         }
1338
1339       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1340         {
1341           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1342             out_fmt, dstFileName);
1343         }
1344       else /*For all the other ports.  Including pics???*/
1345         {
1346           fprintf (lnkfile, "-myux%c\n", out_fmt);
1347           if(options.pack_iram)
1348               fprintf (lnkfile, "-Y\n");
1349         }
1350
1351       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1352         {
1353           /* if iram size specified */
1354           if (options.iram_size)
1355             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1356
1357           /* if stack size specified*/
1358           if(options.stack_size)
1359               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1360
1361           /* if xram size specified */
1362           if (options.xram_size_set)
1363             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1364
1365           /* if code size specified */
1366           if (options.code_size)
1367             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1368
1369           if (options.debug)
1370             fprintf (lnkfile, "-z\n");
1371         }
1372
1373 #define WRITE_SEG_LOC(N, L) \
1374   segName = Safe_strdup(N); \
1375   c = strtok(segName, " \t"); \
1376   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1377   if (segName) { Safe_free(segName); }
1378
1379       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1380         {
1381
1382           /* code segment start */
1383           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1384
1385           /* data segment start. If zero, the linker chooses
1386              the best place for data */
1387           if(options.data_loc)
1388             {
1389               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1390             }
1391
1392           /* xdata start */
1393           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1394
1395           /* indirect data */
1396           if (IDATA_NAME)
1397             {
1398               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1399             }
1400
1401             /* bit segment start */
1402             WRITE_SEG_LOC (BIT_NAME, 0);
1403
1404             /* stack start */
1405             if ( (options.stack_loc) && (options.stack_loc<0x100) )
1406               {
1407                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1408               }
1409         }
1410       else /*For the z80, gbz80*/
1411         {
1412           WRITE_SEG_LOC ("_CODE", options.code_loc);
1413           WRITE_SEG_LOC ("_DATA", options.data_loc);
1414         }
1415   
1416       /* If the port has any special linker area declarations, get 'em */
1417       if (port->extraAreas.genExtraAreaLinkOptions)
1418         {
1419           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1420         }
1421
1422       /* add the extra linker options */
1423       fputStrSet(lnkfile, linkOptionsSet);
1424
1425       /* command line defined library paths if specified */
1426       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1427         fprintf (lnkfile, "-k %s\n", s);
1428
1429       /* standard library path */
1430       if (!options.nostdlib)
1431         {
1432           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1433             {
1434               switch (options.model)
1435                 {
1436                   case MODEL_SMALL:
1437                   c = "small";
1438                   break;
1439                 case MODEL_LARGE:
1440                   c = "large";
1441                   break;
1442                 case MODEL_FLAT24:
1443                   /* c = "flat24"; */
1444                   if (TARGET_IS_DS390)
1445                     {
1446                       c = "ds390";
1447                     }
1448                   else if (TARGET_IS_DS400)
1449                     {
1450                       c = "ds400";
1451                     }
1452                   else
1453                     {
1454                       fprintf(stderr, 
1455                         "Add support for your FLAT24 target in %s @ line %d\n",
1456                         __FILE__, __LINE__);
1457                       exit(-1);
1458                     }
1459                   break;
1460                 case MODEL_PAGE0:
1461                   c = "xa51";
1462                   break;
1463                 default:
1464                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1465                   c = "unknown";
1466                   break;
1467                 }
1468             }
1469           else /*for the z80, gbz80*/
1470             {
1471               if (TARGET_IS_HC08)
1472                 c = "hc08";
1473               else if (TARGET_IS_Z80)
1474                 c = "z80";
1475               else
1476                 c = "gbz80";
1477             }
1478           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1479             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1480         }
1481
1482       /* command line defined library files if specified */
1483       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1484         fprintf (lnkfile, "-l %s\n", s);
1485
1486       /* standard library files */
1487       if (!options.nostdlib)
1488         {
1489 #if !OPT_DISABLE_DS390
1490           if (options.model == MODEL_FLAT24)
1491             {
1492               if (TARGET_IS_DS390)
1493                 {
1494                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1495                 }
1496               else if (TARGET_IS_DS400)
1497                 {
1498                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1499                 }
1500               else
1501                 {
1502                   fprintf(stderr, 
1503                     "Add support for your FLAT24 target in %s @ line %d\n",
1504                     __FILE__, __LINE__);
1505                   exit(-1);
1506                 }
1507               }
1508 #endif
1509
1510 #if !OPT_DISABLE_XA51 
1511 #ifdef STD_XA51_LIB
1512           if (options.model == MODEL_PAGE0)
1513             {
1514               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1515             }
1516 #endif
1517 #endif
1518           if (TARGET_IS_MCS51)
1519             {
1520               fprintf (lnkfile, "-l mcs51\n");
1521             }
1522           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1523             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1524             { /*Why the z80 port is not using the standard libraries?*/
1525               fprintf (lnkfile, "-l %s\n", STD_LIB);
1526               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1527               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1528               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1529             }
1530           else if (TARGET_IS_HC08)
1531             {
1532               fprintf (lnkfile, "-l hc08\n");
1533             }
1534           else if (TARGET_IS_Z80)
1535             {
1536               fprintf (lnkfile, "-l z80\n");
1537             }
1538           else if (TARGET_IS_GBZ80)
1539             {
1540               fprintf (lnkfile, "-l gbz80\n");
1541             }
1542         }
1543
1544       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1545       It is very important for this file to be first on the linking proccess
1546       so the areas are set in the correct order, expecially _GSINIT*/
1547       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1548         !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1549         {
1550           char crt0path[PATH_MAX];
1551           FILE * crt0fp;
1552           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1553             {
1554               sprintf (crt0path, "%s%s%s%scrt0.o",
1555                 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1556
1557               crt0fp=fopen(crt0path, "r");
1558               if(crt0fp!=NULL)/*Found it!*/
1559                 {
1560                   fclose(crt0fp);
1561                   #ifdef __CYGWIN__
1562                   {
1563                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1564                     windows paths, so convert them to the CYGWIN format*/
1565                     char posix_path[PATH_MAX];
1566                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1567                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1568                     strcpy(crt0path, posix_path);
1569                   }
1570                   #endif
1571                   fprintf (lnkfile, "%s\n", crt0path);
1572                   break;
1573                 }
1574             }
1575           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1576         }
1577
1578       /* put in the object files */
1579       if (fullSrcFileName)
1580         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1581
1582       fputStrSet(lnkfile, relFilesSet);
1583
1584       fprintf (lnkfile, "\n-e\n");
1585       fclose (lnkfile);
1586     } /* if(port->linker.needLinkerScript) */
1587
1588   if (options.verbose)
1589     printf ("sdcc: Calling linker...\n");
1590
1591   /* build linker output filename */
1592
1593   /* -o option overrides default name? */
1594   if (fullDstFileName)
1595     {
1596       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1597     }
1598   else
1599     {
1600       /* the linked file gets the name of the first modul */
1601       if (fullSrcFileName)
1602         {
1603           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1604         }
1605       else
1606         {
1607           s = peekSet(relFilesSet);
1608
1609           assert(s);
1610
1611           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1612           /* strip ".rel" extension */
1613           *strrchr (scratchFileName, '.') = '\0';
1614         }
1615       strncatz (scratchFileName, 
1616         options.out_fmt ? ".S19" : ".ihx",
1617         sizeof(scratchFileName));
1618     }
1619
1620   if (port->linker.cmd)
1621     {
1622       char buffer2[PATH_MAX];
1623       char buffer3[PATH_MAX];
1624       set *tempSet=NULL, *libSet=NULL;
1625
1626       strcpy(buffer3, dstFileName);
1627       if(TARGET_IS_PIC16) {
1628         
1629          /* use $l to set the linker include directories */
1630          tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1631          mergeSets(&linkOptionsSet, tempSet);
1632          
1633          tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1634          mergeSets(&linkOptionsSet, tempSet);
1635
1636          /* use $3 for libraries from command line --> libSet */
1637          mergeSets(&libSet, libFilesSet);
1638
1639          tempSet = appendStrSet(relFilesSet, "", "");
1640          mergeSets(&libSet, tempSet);
1641 //         libSet = reverseSet(libSet);
1642
1643         if(fullSrcFileName) {
1644 //              strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1645                 /* if it didn't work, revert to old behaviour */
1646                 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1647                 strcat(buffer3, port->linker.rel_ext);
1648                 
1649         } else strcpy(buffer3, "");
1650       }
1651       
1652       buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1653
1654       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1655     }
1656   else
1657     {
1658       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1659     }
1660
1661   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1662
1663   system_ret = my_system (buffer);
1664   /* TODO: most linker don't have a -o parameter */
1665   /* -o option overrides default name? */
1666   if (fullDstFileName)
1667     {
1668       char *p, *q;
1669       /* the linked file gets the name of the first modul */
1670       if (fullSrcFileName)
1671         {
1672           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1673           p = strlen (scratchFileName) + scratchFileName;
1674         }
1675       else
1676         {
1677           s = peekSet(relFilesSet);
1678
1679           assert(s);
1680
1681           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1682           /* strip ".rel" extension */
1683           p = strrchr (scratchFileName, '.');
1684           if (p)
1685             {
1686               *p = 0;
1687             }
1688         }
1689       strncatz (scratchFileName,
1690         options.out_fmt ? ".S19" : ".ihx",
1691         sizeof(scratchFileName));
1692       if (strcmp (fullDstFileName, scratchFileName))
1693         unlink (fullDstFileName);
1694       rename (scratchFileName, fullDstFileName);
1695
1696       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1697       q = strrchr (buffer, '.');
1698       if (!q)
1699         {
1700           /* no extension: append new extensions */
1701           q = strlen (buffer) + buffer;
1702         }
1703
1704       *p = 0;
1705       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1706       *q = 0;
1707       strncatz(buffer, ".map", sizeof(buffer));
1708       if (strcmp (scratchFileName, buffer))
1709         unlink (buffer);
1710       rename (scratchFileName, buffer);
1711       *p = 0;
1712       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1713       *q = 0;
1714       strncatz(buffer, ".mem", sizeof(buffer));
1715       if (strcmp (scratchFileName, buffer))
1716         unlink (buffer);
1717       rename (scratchFileName, buffer);
1718       if (options.debug)
1719         {
1720           *p = 0;
1721           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1722           *q = 0;
1723           strncatz(buffer, ".cdb", sizeof(buffer));
1724           if (strcmp (scratchFileName, buffer))
1725             unlink (buffer);
1726           rename (scratchFileName, buffer);
1727           /* and the OMF file without extension: */
1728           *p = 0;
1729           *q = 0;
1730           if (strcmp (scratchFileName, buffer))
1731             unlink (buffer);
1732           rename (scratchFileName, buffer);
1733         }
1734     }
1735   if (system_ret)
1736     {
1737       exit (1);
1738     }
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* assemble - spawns the assembler with arguments                  */
1743 /*-----------------------------------------------------------------*/
1744 static void
1745 assemble (char **envp)
1746 {
1747     /* build assembler output filename */
1748
1749     /* -o option overrides default name? */
1750     if (options.cc_only && fullDstFileName) {
1751         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1752     } else {
1753         /* the assembled file gets the name of the first modul */
1754         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1755         strncatz (scratchFileName, port->linker.rel_ext, 
1756                   sizeof(scratchFileName));
1757     }
1758
1759     if (port->assembler.do_assemble) {
1760         port->assembler.do_assemble(asmOptionsSet);
1761         return ;
1762     } else if (port->assembler.cmd) {
1763         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1764                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1765                       asmOptionsSet);
1766     } else {
1767         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1768     }
1769
1770     if (my_system (buffer)) {
1771         /* either system() or the assembler itself has reported an error
1772            perror ("Cannot exec assembler");
1773         */
1774         exit (1);
1775     }
1776     /* TODO: most assembler don't have a -o parameter */
1777     /* -o option overrides default name? */
1778     if (options.cc_only && fullDstFileName) {
1779         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1780         strncatz (scratchFileName, 
1781                   port->linker.rel_ext,
1782                   sizeof(scratchFileName));
1783         if (strcmp (scratchFileName, fullDstFileName))
1784           unlink (fullDstFileName);
1785         rename (scratchFileName, fullDstFileName);
1786     }
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* preProcess - spawns the preprocessor with arguments       */
1791 /*-----------------------------------------------------------------*/
1792 static int
1793 preProcess (char **envp)
1794 {
1795   if (options.c1mode)
1796     {
1797       yyin = stdin;
1798     }
1799   else
1800     {
1801       const char *s;
1802       set *inclList = NULL;
1803
1804       /* if using external stack define the macro */
1805       if (options.useXstack)
1806         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1807
1808       /* set the macro for stack autos  */
1809       if (options.stackAuto)
1810         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1811
1812       /* set the macro for stack autos  */
1813       if (options.stack10bit)
1814         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1815
1816       /* set the macro for no overlay  */
1817       if (options.noOverlay)
1818         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1819
1820       /* set the macro for large model  */
1821       switch (options.model)
1822         {
1823         case MODEL_LARGE:
1824           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1825           break;
1826         case MODEL_SMALL:
1827           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1828           break;
1829         case MODEL_COMPACT:
1830           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1831           break;
1832         case MODEL_MEDIUM:
1833           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1834           break;
1835         case MODEL_FLAT24:
1836           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1837           break;
1838         case MODEL_PAGE0:
1839           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1840           break;
1841         default:
1842           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1843           break;
1844         }
1845
1846       /* add port (processor information to processor */
1847       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1848       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1849
1850       /* standard include path */
1851       if (!options.nostdinc) {
1852         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1853         mergeSets(&preArgvSet, inclList);
1854       }
1855
1856       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1857       Safe_free((void *)s);
1858       if (inclList != NULL)
1859         deleteSet(&inclList);
1860
1861       if (preProcOnly && fullDstFileName)
1862         {
1863           /* -E and -o given */
1864           setMainValue ("cppoutfilename", fullDstFileName);
1865         }
1866       else
1867         {
1868           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1869           setMainValue ("cppoutfilename", NULL);
1870         }
1871
1872       if (options.verbose)
1873         printf ("sdcc: Calling preprocessor...\n");
1874
1875       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1876
1877       if (preProcOnly) {
1878         if (my_system (buffer)) {
1879           exit (1);
1880         }
1881
1882         exit (0);
1883       }
1884
1885       yyin = my_popen (buffer);
1886       if (yyin == NULL) {
1887           perror ("Preproc file not found");
1888           exit (1);
1889       }
1890       addSetHead (&pipeSet, yyin);
1891     }
1892
1893   return 0;
1894 }
1895
1896 /* Set bin paths */
1897 static void
1898 setBinPaths(const char *argv0)
1899 {
1900   char *p;
1901   char buf[PATH_MAX];
1902
1903   /*
1904    * Search logic:
1905    *
1906    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1907    * 2. - path(argv[0])
1908    * 3. - $PATH
1909    */
1910
1911   /* do it in reverse mode, so that addSetHead() can be used
1912      instead of slower addSet() */
1913
1914   if ((p = getBinPath(argv0)) != NULL)
1915     addSetHead(&binPathSet, Safe_strdup(p));
1916
1917   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1918     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1919     addSetHead(&binPathSet, Safe_strdup(buf));
1920   }
1921
1922 #if 0
1923   if (options.printSearchDirs) {
1924     printf("programs:\n");
1925     fputStrSet(stdout, binPathSet);
1926   }
1927 #endif
1928 }
1929
1930 /* Set system include path */
1931 static void
1932 setIncludePath(void)
1933 {
1934   char *p;
1935
1936   /*
1937    * Search logic:
1938    *
1939    * 1. - $SDCC_INCLUDE
1940    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1941    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1942    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1943    */
1944
1945   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1946
1947   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1948     addSetHead(&includeDirsSet, p);
1949
1950 #if 0
1951   if (options.printSearchDirs) {
1952     printf("includedir:\n");
1953     fputStrSet(stdout, includeDirsSet);
1954   }
1955 #endif
1956 }
1957
1958 /* Set system lib path */
1959 static void
1960 setLibPath(void)
1961 {
1962   char *p;
1963
1964   /*
1965    * Search logic:
1966    *
1967    * 1. - $SDCC_LIB
1968    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1969    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1970    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1971    */
1972
1973   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1974
1975   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1976     addSetHead(&libDirsSet, p);
1977
1978 #if 0
1979   if (options.printSearchDirs) {
1980     printf("libdir:\n");
1981     fputStrSet(stdout, libDirsSet);
1982   }
1983 #endif
1984 }
1985
1986 /* Set data path */
1987 static void
1988 setDataPaths(const char *argv0)
1989 {
1990   char *p;
1991   char buf[PATH_MAX];
1992
1993   /*
1994    * Search logic:
1995    *
1996    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1997    * 2. - path(argv[0])/BIN2DATA_DIR
1998    * 3. - DATADIR (only on *nix)
1999    */
2000
2001   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2002     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2003     addSet(&dataDirsSet, Safe_strdup(buf));
2004   }
2005
2006   if ((p = getBinPath(argv0)) != NULL) {
2007     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2008     addSet(&dataDirsSet, Safe_strdup(buf));
2009   }
2010
2011 #ifdef _WIN32
2012   if (peekSet(dataDirsSet) == NULL) {
2013     /* this should never happen... */
2014     wassertl(0, "Can't get binary path");
2015   }
2016 #else
2017   addSet(&dataDirsSet, Safe_strdup(DATADIR));
2018 #endif
2019
2020 #if 0
2021   if (options.printSearchDirs) {
2022     printf("datadir:\n");
2023     fputStrSet(stdout, dataDirsSet);
2024   }
2025 #endif
2026
2027   setIncludePath();
2028   setLibPath();
2029 }
2030
2031 static void
2032 initValues (void)
2033 {
2034   populateMainValues (_baseValues);
2035   setMainValue ("port", port->target);
2036   setMainValue ("objext", port->linker.rel_ext);
2037   setMainValue ("asmext", port->assembler.file_ext);
2038
2039   setMainValue ("dstfilename", dstFileName);
2040   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2041
2042   if (options.cc_only && fullDstFileName)
2043     /* compile + assemble and -o given: -o specifies name of object file */
2044     {
2045       setMainValue ("objdstfilename", fullDstFileName);
2046     }
2047   else
2048     {
2049       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2050     }
2051   if (fullDstFileName)
2052     /* if we're linking, -o gives the final file name */
2053     {
2054       setMainValue ("linkdstfilename", fullDstFileName);
2055     }
2056   else
2057     {
2058       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2059     }
2060
2061 }
2062
2063 static void doPrintSearchDirs(void)
2064 {
2065     printf("programs:\n");
2066     fputStrSet(stdout, binPathSet);
2067
2068     printf("datadir:\n");
2069     fputStrSet(stdout, dataDirsSet);
2070
2071     printf("includedir:\n");
2072     fputStrSet(stdout, includeDirsSet);
2073
2074     printf("libdir:\n");
2075     fputStrSet(stdout, libDirsSet);
2076     fputStrSet(stdout, libPathsSet);
2077 }
2078
2079
2080 static void
2081 sig_handler (int signal)
2082 {
2083   char *sig_string;
2084
2085   switch (signal)
2086     {
2087     case SIGABRT:
2088       sig_string = "SIGABRT";
2089       break;
2090     case SIGTERM:
2091       sig_string = "SIGTERM";
2092       break;
2093     case SIGINT:
2094       sig_string = "SIGINT";
2095       break;
2096     case SIGSEGV:
2097       sig_string = "SIGSEGV";
2098       break;
2099     default:
2100       sig_string = "Unknown?";
2101       break;
2102     }
2103   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2104   exit (1);
2105 }
2106
2107 /*
2108  * main routine
2109  * initialises and calls the parser
2110  */
2111
2112 int
2113 main (int argc, char **argv, char **envp)
2114 {
2115   /* turn all optimizations off by default */
2116   memset (&optimize, 0, sizeof (struct optimize));
2117
2118   /*printVersionInfo (); */
2119
2120   if (NUM_PORTS==0) {
2121     fprintf (stderr, "Build error: no ports are enabled.\n");
2122     exit (1);
2123   }
2124
2125   /* install atexit handler */
2126   atexit(rm_tmpfiles);
2127
2128   /* install signal handler;
2129      it's only purpuse is to call exit() to remove temp files */
2130   if (!getenv("SDCC_LEAVE_SIGNALS"))
2131     {
2132       signal (SIGABRT, sig_handler);
2133       signal (SIGTERM, sig_handler);
2134       signal (SIGINT , sig_handler);
2135       signal (SIGSEGV, sig_handler);
2136     }
2137
2138   /* Before parsing the command line options, do a
2139    * search for the port and processor and initialize
2140    * them if they're found. (We can't gurantee that these
2141    * will be the first options specified).
2142    */
2143
2144   _findPort (argc, argv);
2145
2146 #ifdef JAMIN_DS390
2147   if (strcmp(port->target, "mcs51") == 0) {
2148     printf("DS390 jammed in A\n");
2149           _setPort ("ds390");
2150     ds390_jammed = 1;
2151   }
2152 #endif
2153
2154   _findProcessor (argc, argv);
2155
2156   /* Initalise the port. */
2157   if (port->init)
2158     port->init ();
2159
2160   setDefaultOptions ();
2161 #ifdef JAMIN_DS390
2162   if (ds390_jammed) {
2163     options.model = MODEL_SMALL;
2164     options.stack10bit=0;
2165   }
2166 #endif
2167   parseCmdLine (argc, argv);
2168
2169   initValues ();
2170   setBinPaths(argv[0]);
2171   setDataPaths(argv[0]);
2172
2173   if(port->initPaths)
2174         port->initPaths();
2175   
2176   if(options.printSearchDirs)
2177         doPrintSearchDirs();
2178
2179   /* if no input then printUsage & exit */
2180   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2181     if (!options.printSearchDirs)
2182       printUsage();
2183
2184     exit(0);
2185   }
2186
2187   /* initMem() is expensive, but
2188      initMem() must called before port->finaliseOptions ().
2189      And the z80 port needs port->finaliseOptions(),
2190      even if we're only linking. */
2191   initMem ();
2192   port->finaliseOptions ();
2193
2194   if (fullSrcFileName || options.c1mode)
2195     {
2196       preProcess (envp);
2197
2198       initSymt ();
2199       initiCode ();
2200       initCSupport ();
2201       initBuiltIns();
2202       initPeepHole ();
2203
2204       if (options.verbose)
2205         printf ("sdcc: Generating code...\n");
2206
2207       yyparse ();
2208
2209       if (pclose(yyin))
2210         fatalError = 1;
2211       deleteSetItem(&pipeSet, yyin);
2212
2213       if (fatalError) {
2214         exit (1);
2215       }
2216
2217       if (port->general.do_glue != NULL)
2218         (*port->general.do_glue)();
2219       else
2220         {
2221           /* this shouldn't happen */
2222           assert(FALSE);
2223           /* in case of NDEBUG */
2224           glue();
2225         }
2226
2227       if (fatalError) {
2228         exit (1);
2229       }
2230
2231       if (!options.c1mode && !noAssemble)
2232         {
2233           if (options.verbose)
2234             printf ("sdcc: Calling assembler...\n");
2235           assemble (envp);
2236         }
2237     }
2238   closeDumpFiles();
2239
2240   if (options.debug && debugFile)
2241     debugFile->closeFile();
2242
2243   if (!options.cc_only &&
2244       !fatalError &&
2245       !noAssemble &&
2246       !options.c1mode &&
2247       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2248     {
2249       if (port->linker.do_link)
2250         port->linker.do_link ();
2251       else
2252         linkEdit (envp);
2253     }
2254
2255   return 0;
2256 }