* device/include/string.h: applied Stas Sergeev's patch to make this
[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             }
1021           else
1022             {
1023               continue;
1024             }
1025         }
1026
1027       /* if preceded by  '-' then option */
1028       if (*argv[i] == '-')
1029         {
1030           switch (argv[i][1])
1031             {
1032             case 'h':
1033               verifyShortOption(argv[i]);
1034
1035               printUsage ();
1036               exit (0);
1037               break;
1038
1039             case 'm':
1040               /* Used to select the port. But this has already been done. */
1041               break;
1042
1043             case 'p':
1044               /* Used to select the processor in port. But this has
1045                * already been done. */
1046               break;
1047
1048             case 'c':
1049               verifyShortOption(argv[i]);
1050
1051               options.cc_only = 1;
1052               break;
1053
1054             case 'L':
1055                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1056                 break;
1057
1058             case 'l':
1059                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1060                 break;
1061             
1062             case 'o':
1063               {
1064                 char *p;
1065
1066                 /* copy the file name into the buffer */
1067                 strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
1068                          sizeof(buffer));
1069                 /* point to last character */
1070                 p = buffer + strlen (buffer) - 1;
1071                 if (*p == DIR_SEPARATOR_CHAR)
1072                   {
1073                     /* only output path specified */
1074                     dstPath = Safe_strdup (buffer);
1075                     fullDstFileName = NULL;
1076                   }
1077                 else
1078                   {
1079                     fullDstFileName = Safe_strdup (buffer);
1080
1081                     /* get rid of the "."-extension */
1082
1083                     /* is there a dot at all? */
1084                     if (strrchr (buffer, '.') &&
1085                         /* is the dot in the filename, not in the path? */
1086                         (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1087                       *strrchr (buffer, '.') = '\0';
1088
1089                     dstFileName = Safe_strdup (buffer);
1090
1091                     /* strip module name to get path */
1092                     p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1093                     if (p)
1094                       {
1095                         /* path with trailing / */
1096                         p[1] = '\0';
1097                         dstPath = Safe_strdup (buffer);
1098                       }
1099                   }
1100                 break;
1101               }
1102
1103             case 'W':
1104               /* pre-processer options */
1105               if (argv[i][2] == 'p')
1106                 {
1107                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1108                 }
1109               /* linker options */
1110               else if (argv[i][2] == 'l')
1111                 {
1112                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1113                 }
1114               /* assembler options */
1115               else if (argv[i][2] == 'a')
1116                 {
1117                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1118                 }
1119               else
1120                 {
1121                   werror (W_UNKNOWN_OPTION, argv[i]);
1122                 }
1123               break;
1124
1125             case 'v':
1126               verifyShortOption(argv[i]);
1127
1128               printVersionInfo ();
1129               exit (0);
1130               break;
1131
1132               /* preprocessor options */
1133             case 'M':
1134               {
1135                 preProcOnly = 1;
1136                 if (argv[i][2] == 'M')
1137                   addSet(&preArgvSet, Safe_strdup("-MM"));
1138                 else
1139                   addSet(&preArgvSet, Safe_strdup("-M"));
1140                 break;
1141               }
1142             case 'C':
1143               {
1144                 addSet(&preArgvSet, Safe_strdup("-C"));
1145                 break;
1146               }
1147
1148             case 'd':
1149             case 'D':
1150             case 'I':
1151             case 'A':
1152             case 'U':
1153               {
1154                 char sOpt = argv[i][1];
1155                 char *rest;
1156
1157                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1158                   {
1159                     i++;
1160                     if (i >= argc)
1161                       {
1162                           /* No argument. */
1163                           werror(E_ARGUMENT_MISSING, argv[i-1]);
1164                           break;
1165                       }
1166                     else
1167                       {
1168                           rest = argv[i];
1169                       }
1170                   }
1171                 else
1172                   rest = &argv[i][2];
1173
1174                 if (sOpt == 'Y')
1175                   sOpt = 'I';
1176
1177                 SNPRINTF (buffer, sizeof(buffer),
1178                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1179                 addSet(&preArgvSet, Safe_strdup(buffer));
1180               }
1181               break;
1182
1183             default:
1184               if (!port->parseOption (&argc, argv, &i))
1185                 werror (W_UNKNOWN_OPTION, argv[i]);
1186             }
1187           continue;
1188         }
1189
1190       if (!port->parseOption (&argc, argv, &i))
1191         {
1192            /* no option must be a filename */
1193            if (options.c1mode)
1194              {
1195                 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1196              }
1197          else
1198              {
1199                 processFile (argv[i]);
1200              }
1201         }
1202     }
1203
1204   /* some sanity checks in c1 mode */
1205   if (options.c1mode)
1206     {
1207       const char *s;
1208
1209       if (fullSrcFileName)
1210         {
1211           fclose (srcFile);
1212           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1213         }
1214       fullSrcFileName = NULL;
1215       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1216         {
1217           werror (W_NO_FILE_ARG_IN_C1, s);
1218         }
1219       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1220         {
1221           werror (W_NO_FILE_ARG_IN_C1, s);
1222         }
1223       deleteSet(&relFilesSet);
1224       deleteSet(&libFilesSet);
1225
1226         if (options.cc_only || noAssemble || preProcOnly)
1227         {
1228           werror (W_ILLEGAL_OPT_COMBINATION);
1229         }
1230       options.cc_only = noAssemble = preProcOnly = 0;
1231       if (!dstFileName)
1232         {
1233           werror (E_NEED_OPT_O_IN_C1);
1234           exit (1);
1235         }
1236     }
1237   /* if no dstFileName given with -o, we've to find one: */
1238   if (!dstFileName)
1239     {
1240       const char *s;
1241
1242       /* use the modulename from the C-source */
1243       if (fullSrcFileName)
1244         {
1245           size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1246
1247           dstFileName = Safe_alloc (bufSize);
1248           strncpyz (dstFileName, dstPath, bufSize);
1249           strncatz (dstFileName, moduleNameBase, bufSize);
1250         }
1251       /* use the modulename from the first object file */
1252       else if ((s = peekSet(relFilesSet)) != NULL)
1253         {
1254           char *objectName;
1255           size_t bufSize;
1256
1257           strncpyz (buffer, s, sizeof(buffer));
1258           /* remove extension (it must be .rel) */
1259           *strrchr (buffer, '.') = '\0';
1260           /* remove path */
1261           objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1262           if (objectName)
1263             {
1264               ++objectName;
1265             }
1266           else
1267             {
1268               objectName = buffer;
1269             }
1270           bufSize = strlen (dstPath) + strlen (objectName) + 1;  
1271           dstFileName = Safe_alloc (bufSize);
1272           strncpyz (dstFileName, dstPath, bufSize);
1273           strncatz (dstFileName, objectName, bufSize);
1274         }
1275       /* else no module given: help text is displayed */
1276     }
1277
1278   /* set up external stack location if not explicitly specified */
1279   if (!options.xstack_loc)
1280     options.xstack_loc = options.xdata_loc;
1281
1282   /* if debug option is set then open the cdbFile */
1283   if (options.debug && fullSrcFileName)
1284     {
1285       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1286                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1287       if(debugFile->openFile(scratchFileName))
1288         debugFile->writeModule(moduleName);
1289       else
1290         werror (E_FILE_OPEN_ERR, scratchFileName);
1291     }
1292   MSVC_style(options.vc_err_style);
1293   if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1294
1295   return 0;
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* linkEdit : - calls the linkage editor  with options             */
1300 /*-----------------------------------------------------------------*/
1301 static void
1302 linkEdit (char **envp)
1303 {
1304   FILE *lnkfile;
1305   char *segName, *c;
1306   int system_ret;
1307   const char *s;
1308
1309
1310   if(port->linker.needLinkerScript)
1311     {
1312       char out_fmt;
1313       
1314       switch (options.out_fmt)
1315         {
1316         case 0:
1317           out_fmt = 'i';        /* Intel hex */
1318           break;
1319         case 1:
1320           out_fmt = 's';        /* Motorola S19 */
1321           break;
1322         case 2:
1323           out_fmt = 't';        /* Elf */
1324           break;
1325         default:
1326           out_fmt = 'i';
1327         }
1328       
1329       /* first we need to create the <filename>.lnk file */
1330       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1331         "%s.lnk", dstFileName);
1332       if (!(lnkfile = fopen (scratchFileName, "w")))
1333         {
1334           werror (E_FILE_OPEN_ERR, scratchFileName);
1335           exit (1);
1336         }
1337
1338       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1339         {
1340           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1341             out_fmt, dstFileName);
1342         }
1343       else /*For all the other ports.  Including pics???*/
1344         {
1345           fprintf (lnkfile, "-myux%c\n", out_fmt);
1346           if(options.pack_iram)
1347               fprintf (lnkfile, "-Y\n");
1348         }
1349
1350       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1351         {
1352           /* if iram size specified */
1353           if (options.iram_size)
1354             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1355
1356           /* if stack size specified*/
1357           if(options.stack_size)
1358               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1359
1360           /* if xram size specified */
1361           if (options.xram_size_set)
1362             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1363
1364           /* if code size specified */
1365           if (options.code_size)
1366             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1367
1368           if (options.debug)
1369             fprintf (lnkfile, "-z\n");
1370         }
1371
1372 #define WRITE_SEG_LOC(N, L) \
1373   segName = Safe_strdup(N); \
1374   c = strtok(segName, " \t"); \
1375   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1376   if (segName) { Safe_free(segName); }
1377
1378       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1379         {
1380
1381           /* code segment start */
1382           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1383
1384           /* data segment start. If zero, the linker chooses
1385              the best place for data */
1386           if(options.data_loc)
1387             {
1388               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1389             }
1390
1391           /* xdata start */
1392           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1393
1394           /* indirect data */
1395           if (IDATA_NAME)
1396             {
1397               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1398             }
1399
1400             /* bit segment start */
1401             WRITE_SEG_LOC (BIT_NAME, 0);
1402
1403             /* stack start */
1404             if ( (options.stack_loc) && (options.stack_loc<0x100) )
1405               {
1406                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1407               }
1408         }
1409       else /*For the z80, gbz80*/
1410         {
1411           WRITE_SEG_LOC ("_CODE", options.code_loc);
1412           WRITE_SEG_LOC ("_DATA", options.data_loc);
1413         }
1414   
1415       /* If the port has any special linker area declarations, get 'em */
1416       if (port->extraAreas.genExtraAreaLinkOptions)
1417         {
1418           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1419         }
1420
1421       /* add the extra linker options */
1422       fputStrSet(lnkfile, linkOptionsSet);
1423
1424       /* command line defined library paths if specified */
1425       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1426         fprintf (lnkfile, "-k %s\n", s);
1427
1428       /* standard library path */
1429       if (!options.nostdlib)
1430         {
1431           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1432             {
1433               switch (options.model)
1434                 {
1435                   case MODEL_SMALL:
1436                   c = "small";
1437                   break;
1438                 case MODEL_LARGE:
1439                   c = "large";
1440                   break;
1441                 case MODEL_FLAT24:
1442                   /* c = "flat24"; */
1443                   if (TARGET_IS_DS390)
1444                     {
1445                       c = "ds390";
1446                     }
1447                   else if (TARGET_IS_DS400)
1448                     {
1449                       c = "ds400";
1450                     }
1451                   else
1452                     {
1453                       fprintf(stderr, 
1454                         "Add support for your FLAT24 target in %s @ line %d\n",
1455                         __FILE__, __LINE__);
1456                       exit(-1);
1457                     }
1458                   break;
1459                 case MODEL_PAGE0:
1460                   c = "xa51";
1461                   break;
1462                 default:
1463                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1464                   c = "unknown";
1465                   break;
1466                 }
1467             }
1468           else /*for the z80, gbz80*/
1469             {
1470               if (TARGET_IS_HC08)
1471                 c = "hc08";
1472               else if (TARGET_IS_Z80)
1473                 c = "z80";
1474               else
1475                 c = "gbz80";
1476             }
1477           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1478             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1479         }
1480
1481       /* command line defined library files if specified */
1482       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1483         fprintf (lnkfile, "-l %s\n", s);
1484
1485       /* standard library files */
1486       if (!options.nostdlib)
1487         {
1488 #if !OPT_DISABLE_DS390
1489           if (options.model == MODEL_FLAT24)
1490             {
1491               if (TARGET_IS_DS390)
1492                 {
1493                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1494                 }
1495               else if (TARGET_IS_DS400)
1496                 {
1497                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1498                 }
1499               else
1500                 {
1501                   fprintf(stderr, 
1502                     "Add support for your FLAT24 target in %s @ line %d\n",
1503                     __FILE__, __LINE__);
1504                   exit(-1);
1505                 }
1506               }
1507 #endif
1508
1509 #if !OPT_DISABLE_XA51 
1510 #ifdef STD_XA51_LIB
1511           if (options.model == MODEL_PAGE0)
1512             {
1513               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1514             }
1515 #endif
1516 #endif
1517           if (TARGET_IS_MCS51)
1518             {
1519               fprintf (lnkfile, "-l mcs51\n");
1520             }
1521           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1522             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1523             { /*Why the z80 port is not using the standard libraries?*/
1524               fprintf (lnkfile, "-l %s\n", STD_LIB);
1525               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1526               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1527               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1528             }
1529           else if (TARGET_IS_HC08)
1530             {
1531               fprintf (lnkfile, "-l hc08\n");
1532             }
1533           else if (TARGET_IS_Z80)
1534             {
1535               fprintf (lnkfile, "-l z80\n");
1536             }
1537           else if (TARGET_IS_GBZ80)
1538             {
1539               fprintf (lnkfile, "-l gbz80\n");
1540             }
1541         }
1542
1543       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1544       It is very important for this file to be first on the linking proccess
1545       so the areas are set in the correct order, expecially _GSINIT*/
1546       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1547         !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1548         {
1549           char crt0path[PATH_MAX];
1550           FILE * crt0fp;
1551           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1552             {
1553               sprintf (crt0path, "%s%s%s%scrt0.o",
1554                 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1555
1556               crt0fp=fopen(crt0path, "r");
1557               if(crt0fp!=NULL)/*Found it!*/
1558                 {
1559                   fclose(crt0fp);
1560                   #ifdef __CYGWIN__
1561                   {
1562                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1563                     windows paths, so convert them to the CYGWIN format*/
1564                     char posix_path[PATH_MAX];
1565                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1566                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1567                     strcpy(crt0path, posix_path);
1568                   }
1569                   #endif
1570                   fprintf (lnkfile, "%s\n", crt0path);
1571                   break;
1572                 }
1573             }
1574           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1575         }
1576
1577       /* put in the object files */
1578       if (fullSrcFileName)
1579         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1580
1581       fputStrSet(lnkfile, relFilesSet);
1582
1583       fprintf (lnkfile, "\n-e\n");
1584       fclose (lnkfile);
1585     } /* if(port->linker.needLinkerScript) */
1586
1587   if (options.verbose)
1588     printf ("sdcc: Calling linker...\n");
1589
1590   /* build linker output filename */
1591
1592   /* -o option overrides default name? */
1593   if (fullDstFileName)
1594     {
1595       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1596     }
1597   else
1598     {
1599       /* the linked file gets the name of the first modul */
1600       if (fullSrcFileName)
1601         {
1602           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1603         }
1604       else
1605         {
1606           s = peekSet(relFilesSet);
1607
1608           assert(s);
1609
1610           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1611           /* strip ".rel" extension */
1612           *strrchr (scratchFileName, '.') = '\0';
1613         }
1614       strncatz (scratchFileName, 
1615         options.out_fmt ? ".S19" : ".ihx",
1616         sizeof(scratchFileName));
1617     }
1618
1619   if (port->linker.cmd)
1620     {
1621       char buffer2[PATH_MAX];
1622       set *libSet=NULL;
1623
1624       if(TARGET_IS_PIC16) {
1625          /* use $3 to set the linker include directories */
1626          libSet = appendStrSet(libDirsSet, "-I\"", "\"");
1627
1628          /* now add the libraries from command line */
1629          mergeSets(&libSet, libFilesSet);
1630       }
1631       
1632       buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1633       if(libSet)deleteSet(&libSet);
1634
1635       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1636     }
1637   else
1638     {
1639       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1640     }
1641
1642   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1643
1644   system_ret = my_system (buffer);
1645   /* TODO: most linker don't have a -o parameter */
1646   /* -o option overrides default name? */
1647   if (fullDstFileName)
1648     {
1649       char *p, *q;
1650       /* the linked file gets the name of the first modul */
1651       if (fullSrcFileName)
1652         {
1653           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1654           p = strlen (scratchFileName) + scratchFileName;
1655         }
1656       else
1657         {
1658           s = peekSet(relFilesSet);
1659
1660           assert(s);
1661
1662           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1663           /* strip ".rel" extension */
1664           p = strrchr (scratchFileName, '.');
1665           if (p)
1666             {
1667               *p = 0;
1668             }
1669         }
1670       strncatz (scratchFileName,
1671         options.out_fmt ? ".S19" : ".ihx",
1672         sizeof(scratchFileName));
1673       if (strcmp (fullDstFileName, scratchFileName))
1674         unlink (fullDstFileName);
1675       rename (scratchFileName, fullDstFileName);
1676
1677       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1678       q = strrchr (buffer, '.');
1679       if (!q)
1680         {
1681           /* no extension: append new extensions */
1682           q = strlen (buffer) + buffer;
1683         }
1684
1685       *p = 0;
1686       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1687       *q = 0;
1688       strncatz(buffer, ".map", sizeof(buffer));
1689       if (strcmp (scratchFileName, buffer))
1690         unlink (buffer);
1691       rename (scratchFileName, buffer);
1692       *p = 0;
1693       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1694       *q = 0;
1695       strncatz(buffer, ".mem", sizeof(buffer));
1696       if (strcmp (scratchFileName, buffer))
1697         unlink (buffer);
1698       rename (scratchFileName, buffer);
1699       if (options.debug)
1700         {
1701           *p = 0;
1702           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1703           *q = 0;
1704           strncatz(buffer, ".cdb", sizeof(buffer));
1705           if (strcmp (scratchFileName, buffer))
1706             unlink (buffer);
1707           rename (scratchFileName, buffer);
1708           /* and the OMF file without extension: */
1709           *p = 0;
1710           *q = 0;
1711           if (strcmp (scratchFileName, buffer))
1712             unlink (buffer);
1713           rename (scratchFileName, buffer);
1714         }
1715     }
1716   if (system_ret)
1717     {
1718       exit (1);
1719     }
1720 }
1721
1722 /*-----------------------------------------------------------------*/
1723 /* assemble - spawns the assembler with arguments                  */
1724 /*-----------------------------------------------------------------*/
1725 static void
1726 assemble (char **envp)
1727 {
1728     /* build assembler output filename */
1729
1730     /* -o option overrides default name? */
1731     if (options.cc_only && fullDstFileName) {
1732         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1733     } else {
1734         /* the assembled file gets the name of the first modul */
1735         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1736         strncatz (scratchFileName, port->linker.rel_ext, 
1737                   sizeof(scratchFileName));
1738     }
1739
1740     if (port->assembler.do_assemble) {
1741         port->assembler.do_assemble(asmOptionsSet);
1742         return ;
1743     } else if (port->assembler.cmd) {
1744         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1745                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1746                       asmOptionsSet);
1747     } else {
1748         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1749     }
1750
1751     if (my_system (buffer)) {
1752         /* either system() or the assembler itself has reported an error
1753            perror ("Cannot exec assembler");
1754         */
1755         exit (1);
1756     }
1757     /* TODO: most assembler don't have a -o parameter */
1758     /* -o option overrides default name? */
1759     if (options.cc_only && fullDstFileName) {
1760         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1761         strncatz (scratchFileName, 
1762                   port->linker.rel_ext,
1763                   sizeof(scratchFileName));
1764         if (strcmp (scratchFileName, fullDstFileName))
1765           unlink (fullDstFileName);
1766         rename (scratchFileName, fullDstFileName);
1767     }
1768 }
1769
1770 /*-----------------------------------------------------------------*/
1771 /* preProcess - spawns the preprocessor with arguments       */
1772 /*-----------------------------------------------------------------*/
1773 static int
1774 preProcess (char **envp)
1775 {
1776   if (options.c1mode)
1777     {
1778       yyin = stdin;
1779     }
1780   else
1781     {
1782       const char *s;
1783       set *inclList = NULL;
1784
1785       /* if using external stack define the macro */
1786       if (options.useXstack)
1787         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1788
1789       /* set the macro for stack autos  */
1790       if (options.stackAuto)
1791         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1792
1793       /* set the macro for stack autos  */
1794       if (options.stack10bit)
1795         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1796
1797       /* set the macro for no overlay  */
1798       if (options.noOverlay)
1799         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1800
1801       /* set the macro for large model  */
1802       switch (options.model)
1803         {
1804         case MODEL_LARGE:
1805           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1806           break;
1807         case MODEL_SMALL:
1808           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1809           break;
1810         case MODEL_COMPACT:
1811           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1812           break;
1813         case MODEL_MEDIUM:
1814           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1815           break;
1816         case MODEL_FLAT24:
1817           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1818           break;
1819         case MODEL_PAGE0:
1820           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1821           break;
1822         default:
1823           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1824           break;
1825         }
1826
1827       /* add port (processor information to processor */
1828       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1829       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1830
1831       /* standard include path */
1832       if (!options.nostdinc) {
1833         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1834         mergeSets(&preArgvSet, inclList);
1835       }
1836
1837       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1838       Safe_free((void *)s);
1839       if (inclList != NULL)
1840         deleteSet(&inclList);
1841
1842       if (preProcOnly && fullDstFileName)
1843         {
1844           /* -E and -o given */
1845           setMainValue ("cppoutfilename", fullDstFileName);
1846         }
1847       else
1848         {
1849           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1850           setMainValue ("cppoutfilename", NULL);
1851         }
1852
1853       if (options.verbose)
1854         printf ("sdcc: Calling preprocessor...\n");
1855
1856       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1857
1858       if (preProcOnly) {
1859         if (my_system (buffer)) {
1860           exit (1);
1861         }
1862
1863         exit (0);
1864       }
1865
1866       yyin = my_popen (buffer);
1867       if (yyin == NULL) {
1868           perror ("Preproc file not found");
1869           exit (1);
1870       }
1871       addSetHead (&pipeSet, yyin);
1872     }
1873
1874   return 0;
1875 }
1876
1877 /* Set bin paths */
1878 static void
1879 setBinPaths(const char *argv0)
1880 {
1881   char *p;
1882   char buf[PATH_MAX];
1883
1884   /*
1885    * Search logic:
1886    *
1887    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1888    * 2. - path(argv[0])
1889    * 3. - $PATH
1890    */
1891
1892   /* do it in reverse mode, so that addSetHead() can be used
1893      instead of slower addSet() */
1894
1895   if ((p = getBinPath(argv0)) != NULL)
1896     addSetHead(&binPathSet, Safe_strdup(p));
1897
1898   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1899     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1900     addSetHead(&binPathSet, Safe_strdup(buf));
1901   }
1902
1903   if (options.printSearchDirs) {
1904     printf("programs:\n");
1905     fputStrSet(stdout, binPathSet);
1906   }
1907 }
1908
1909 /* Set system include path */
1910 static void
1911 setIncludePath(void)
1912 {
1913   char *p;
1914
1915   /*
1916    * Search logic:
1917    *
1918    * 1. - $SDCC_INCLUDE
1919    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1920    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1921    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1922    */
1923
1924   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1925
1926   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1927     addSetHead(&includeDirsSet, p);
1928
1929   if (options.printSearchDirs) {
1930     printf("includedir:\n");
1931     fputStrSet(stdout, includeDirsSet);
1932   }
1933 }
1934
1935 /* Set system lib path */
1936 static void
1937 setLibPath(void)
1938 {
1939   char *p;
1940
1941   /*
1942    * Search logic:
1943    *
1944    * 1. - $SDCC_LIB
1945    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1946    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1947    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1948    */
1949
1950   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1951
1952   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1953     addSetHead(&libDirsSet, p);
1954
1955   if (options.printSearchDirs) {
1956     printf("libdir:\n");
1957     fputStrSet(stdout, libDirsSet);
1958   }
1959 }
1960
1961 /* Set data path */
1962 static void
1963 setDataPaths(const char *argv0)
1964 {
1965   char *p;
1966   char buf[PATH_MAX];
1967
1968   /*
1969    * Search logic:
1970    *
1971    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1972    * 2. - path(argv[0])/BIN2DATA_DIR
1973    * 3. - DATADIR (only on *nix)
1974    */
1975
1976   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1977     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
1978     addSet(&dataDirsSet, Safe_strdup(buf));
1979   }
1980
1981   if ((p = getBinPath(argv0)) != NULL) {
1982     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
1983     addSet(&dataDirsSet, Safe_strdup(buf));
1984   }
1985
1986 #ifdef _WIN32
1987   if (peekSet(dataDirsSet) == NULL) {
1988     /* this should never happen... */
1989     wassertl(0, "Can't get binary path");
1990   }
1991 #else
1992   addSet(&dataDirsSet, Safe_strdup(DATADIR));
1993 #endif
1994
1995   if (options.printSearchDirs) {
1996     printf("datadir:\n");
1997     fputStrSet(stdout, dataDirsSet);
1998   }
1999
2000   setIncludePath();
2001   setLibPath();
2002 }
2003
2004 static void
2005 initValues (void)
2006 {
2007   populateMainValues (_baseValues);
2008   setMainValue ("port", port->target);
2009   setMainValue ("objext", port->linker.rel_ext);
2010   setMainValue ("asmext", port->assembler.file_ext);
2011
2012   setMainValue ("dstfilename", dstFileName);
2013   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2014
2015   if (options.cc_only && fullDstFileName)
2016     /* compile + assemble and -o given: -o specifies name of object file */
2017     {
2018       setMainValue ("objdstfilename", fullDstFileName);
2019     }
2020   else
2021     {
2022       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2023     }
2024   if (fullDstFileName)
2025     /* if we're linking, -o gives the final file name */
2026     {
2027       setMainValue ("linkdstfilename", fullDstFileName);
2028     }
2029   else
2030     {
2031       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2032     }
2033
2034 }
2035
2036 static void
2037 sig_handler (int signal)
2038 {
2039   char *sig_string;
2040
2041   switch (signal)
2042     {
2043     case SIGABRT:
2044       sig_string = "SIGABRT";
2045       break;
2046     case SIGTERM:
2047       sig_string = "SIGTERM";
2048       break;
2049     case SIGINT:
2050       sig_string = "SIGINT";
2051       break;
2052     case SIGSEGV:
2053       sig_string = "SIGSEGV";
2054       break;
2055     default:
2056       sig_string = "Unknown?";
2057       break;
2058     }
2059   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2060   exit (1);
2061 }
2062
2063 /*
2064  * main routine
2065  * initialises and calls the parser
2066  */
2067
2068 int
2069 main (int argc, char **argv, char **envp)
2070 {
2071   /* turn all optimizations off by default */
2072   memset (&optimize, 0, sizeof (struct optimize));
2073
2074   /*printVersionInfo (); */
2075
2076   if (NUM_PORTS==0) {
2077     fprintf (stderr, "Build error: no ports are enabled.\n");
2078     exit (1);
2079   }
2080
2081   /* install atexit handler */
2082   atexit(rm_tmpfiles);
2083
2084   /* install signal handler;
2085      it's only purpuse is to call exit() to remove temp files */
2086   if (!getenv("SDCC_LEAVE_SIGNALS"))
2087     {
2088       signal (SIGABRT, sig_handler);
2089       signal (SIGTERM, sig_handler);
2090       signal (SIGINT , sig_handler);
2091       signal (SIGSEGV, sig_handler);
2092     }
2093
2094   /* Before parsing the command line options, do a
2095    * search for the port and processor and initialize
2096    * them if they're found. (We can't gurantee that these
2097    * will be the first options specified).
2098    */
2099
2100   _findPort (argc, argv);
2101
2102 #ifdef JAMIN_DS390
2103   if (strcmp(port->target, "mcs51") == 0) {
2104     printf("DS390 jammed in A\n");
2105           _setPort ("ds390");
2106     ds390_jammed = 1;
2107   }
2108 #endif
2109
2110   _findProcessor (argc, argv);
2111
2112   /* Initalise the port. */
2113   if (port->init)
2114     port->init ();
2115
2116   setDefaultOptions ();
2117 #ifdef JAMIN_DS390
2118   if (ds390_jammed) {
2119     options.model = MODEL_SMALL;
2120     options.stack10bit=0;
2121   }
2122 #endif
2123   parseCmdLine (argc, argv);
2124
2125   initValues ();
2126   setBinPaths(argv[0]);
2127   setDataPaths(argv[0]);
2128
2129   /* if no input then printUsage & exit */
2130   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2131     if (!options.printSearchDirs)
2132       printUsage();
2133
2134     exit(0);
2135   }
2136
2137   /* initMem() is expensive, but
2138      initMem() must called before port->finaliseOptions ().
2139      And the z80 port needs port->finaliseOptions(),
2140      even if we're only linking. */
2141   initMem ();
2142   port->finaliseOptions ();
2143
2144   if (fullSrcFileName || options.c1mode)
2145     {
2146       preProcess (envp);
2147
2148       initSymt ();
2149       initiCode ();
2150       initCSupport ();
2151       initBuiltIns();
2152       initPeepHole ();
2153
2154       if (options.verbose)
2155         printf ("sdcc: Generating code...\n");
2156
2157       yyparse ();
2158
2159       if (pclose(yyin))
2160         fatalError = 1;
2161       deleteSetItem(&pipeSet, yyin);
2162
2163       if (fatalError) {
2164         exit (1);
2165       }
2166
2167       if (port->general.do_glue != NULL)
2168         (*port->general.do_glue)();
2169       else
2170         {
2171           /* this shouldn't happen */
2172           assert(FALSE);
2173           /* in case of NDEBUG */
2174           glue();
2175         }
2176
2177       if (fatalError) {
2178         exit (1);
2179       }
2180
2181       if (!options.c1mode && !noAssemble)
2182         {
2183           if (options.verbose)
2184             printf ("sdcc: Calling assembler...\n");
2185           assemble (envp);
2186         }
2187     }
2188   closeDumpFiles();
2189
2190   if (options.debug && debugFile)
2191     debugFile->closeFile();
2192
2193   if (!options.cc_only &&
2194       !fatalError &&
2195       !noAssemble &&
2196       !options.c1mode &&
2197       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2198     {
2199       if (port->linker.do_link)
2200         port->linker.do_link ();
2201       else
2202         linkEdit (envp);
2203     }
2204
2205   return 0;
2206 }