* src/SDCCmain.c (parseCmdLine): when sOpt is 'I' add rest in
[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 /*-----------------------------------------------------------------*/
405 /* printVersionInfo - prints the version info        */
406 /*-----------------------------------------------------------------*/
407 void
408 printVersionInfo (void)
409 {
410   int i;
411
412   fprintf (stderr,
413            "SDCC : ");
414   for (i = 0; i < NUM_PORTS; i++)
415     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
416   
417   fprintf (stderr, " " SDCC_VERSION_STR
418 #ifdef SDCC_SUB_VERSION_STR
419            "/" SDCC_SUB_VERSION_STR
420 #endif
421            " #%s (" __DATE__ ")"
422 #ifdef __CYGWIN__
423            " (CYGWIN)\n"
424 #elif defined __MINGW32__
425            " (MINGW32)\n"
426 #elif defined __DJGPP__
427            " (DJGPP)\n"
428 #elif defined(_MSC_VER)
429            " (MSVC)\n"
430 #elif defined(__BORLANDC__)
431            " (BORLANDC)\n"
432 #else
433            " (UNIX) \n"
434 #endif
435     , getBuildNumber() );
436 }
437
438 static void
439 printOptions(const OPTION *optionsTable)
440 {
441   int i;
442   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++) 
443     {
444       fprintf(stdout, "  %c%c  %-20s  %s\n", 
445               optionsTable[i].shortOpt !=0 ? '-' : ' ',
446               optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
447               optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
448               optionsTable[i].help != NULL ? optionsTable[i].help : ""
449               );
450     }
451 }
452
453 /*-----------------------------------------------------------------*/
454 /* printUsage - prints command line syntax         */
455 /*-----------------------------------------------------------------*/
456 void
457 printUsage (void)
458 {
459     int i;
460     printVersionInfo();
461     fprintf (stdout,
462              "Usage : sdcc [options] filename\n"
463              "Options :-\n"
464              );
465
466     printOptions(optionsTable);
467
468     for (i = 0; i < NUM_PORTS; i++)
469       {
470         if (_ports[i]->poptions != NULL)
471           {
472             fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
473             printOptions (_ports[i]->poptions);
474           }
475       }
476
477     exit (0);
478 }
479
480 /*-----------------------------------------------------------------*/
481 /* setParseWithComma - separates string with comma to a set        */
482 /*-----------------------------------------------------------------*/
483 void
484 setParseWithComma (set **dest, char *src)
485 {
486   char *p;
487   int length;
488
489   /* skip the initial white spaces */
490   while (isspace(*src))
491     src++;
492   
493   /* skip the trailing white spaces */
494   length = strlen(src);
495   while (length && isspace(src[length-1]))
496     src[--length] = '\0';
497
498   for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
499     addSet(dest, Safe_strdup(p));
500 }
501
502 /*-----------------------------------------------------------------*/
503 /* setDefaultOptions - sets the default options                    */
504 /*-----------------------------------------------------------------*/
505 static void
506 setDefaultOptions (void)
507 {
508   /* first the options part */
509   options.stack_loc = 0;        /* stack pointer initialised to 0 */
510   options.xstack_loc = 0;       /* xternal stack starts at 0 */
511   options.code_loc = 0;         /* code starts at 0 */
512   options.data_loc = 0;         /* JCF: By default let the linker locate data */
513   options.xdata_loc = 0;
514   options.idata_loc = 0x80;
515   options.nopeep = 0;
516   options.model = port->general.default_model;
517   options.nostdlib = 0;
518   options.nostdinc = 0;
519   options.verbose = 0;
520   options.shortis8bits = 0;
521
522   options.stack10bit=0;
523
524   /* now for the optimizations */
525   /* turn on the everything */
526   optimize.global_cse = 1;
527   optimize.label1 = 1;
528   optimize.label2 = 1;
529   optimize.label3 = 1;
530   optimize.label4 = 1;
531   optimize.loopInvariant = 1;
532   optimize.loopInduction = 1;
533
534   /* now for the ports */
535   port->setDefaultOptions ();
536 }
537
538 /*-----------------------------------------------------------------*/
539 /* processFile - determines the type of file from the extension    */
540 /*-----------------------------------------------------------------*/
541 static void
542 processFile (char *s)
543 {
544   char *fext = NULL;
545
546   /* get the file extension */
547   fext = s + strlen (s);
548   while ((fext != s) && *fext != '.')
549     fext--;
550
551   /* now if no '.' then we don't know what the file type is
552      so give a warning and return */
553   if (fext == s)
554     {
555       werror (W_UNKNOWN_FEXT, s);
556       return;
557     }
558
559   /* otherwise depending on the file type */
560   if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
561     {
562       /* source file name : not if we already have a
563          source file */
564       if (fullSrcFileName)
565         {
566           werror (W_TOO_MANY_SRC, s);
567           return;
568         }
569
570       /* the only source file */
571       fullSrcFileName = s;
572       if (!(srcFile = fopen (fullSrcFileName, "r")))
573         {
574           werror (E_FILE_OPEN_ERR, s);
575           exit (1);
576         }
577
578       /* copy the file name into the buffer */
579       strncpyz (buffer, s, sizeof(buffer));
580
581       /* get rid of the "."-extension */
582
583       /* is there a dot at all? */
584       if (strrchr (buffer, '.') &&
585           /* is the dot in the filename, not in the path? */
586           (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
587         {
588         *strrchr (buffer, '.') = '\0';
589         }
590
591       /* get rid of any path information
592          for the module name; */
593       fext = buffer + strlen (buffer);
594 #if NATIVE_WIN32
595       /* do this by going backwards till we
596          get '\' or ':' or start of buffer */
597       while (fext != buffer &&
598              *(fext - 1) != DIR_SEPARATOR_CHAR &&
599              *(fext - 1) != ':')
600         {
601         fext--;
602         }
603 #else
604       /* do this by going backwards till we
605          get '/' or start of buffer */
606       while (fext != buffer &&
607              *(fext - 1) != DIR_SEPARATOR_CHAR)
608         {
609           fext--;
610         }
611 #endif
612       moduleNameBase = Safe_strdup ( fext );
613       moduleName = Safe_strdup ( fext );
614       
615       for (fext = moduleName; *fext; fext++)
616         if (!isalnum (*fext))
617           *fext = '_';
618       return;
619     }
620
621   /* if the extention is type .rel or .r or .REL or .R
622      addtional object file will be passed to the linker */
623   if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
624       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
625       strcmp (fext, port->linker.rel_ext) == 0)
626     {
627       addSet(&relFilesSet, Safe_strdup(s));
628       return;
629     }
630
631   /* if .lib or .LIB */
632   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
633     {
634       addSet(&libFilesSet, Safe_strdup(s));
635       return;
636     }
637
638   werror (W_UNKNOWN_FEXT, s);
639
640 }
641
642 static void
643 _setModel (int model, const char *sz)
644 {
645   if (port->general.supported_models & model)
646     options.model = model;
647   else
648     werror (W_UNSUPPORTED_MODEL, sz, port->target);
649 }
650
651 /** Gets the string argument to this option.  If the option is '--opt'
652     then for input of '--optxyz' or '--opt xyz' returns xyz.
653 */
654 char *
655 getStringArg(const char *szStart, char **argv, int *pi, int argc)
656 {
657   if (argv[*pi][strlen(szStart)])
658     {
659       return &argv[*pi][strlen(szStart)];
660     }
661   else
662     {
663       ++(*pi);
664       if (*pi >= argc)
665         {
666           werror (E_ARGUMENT_MISSING, szStart);
667           /* Die here rather than checking for errors later. */
668           exit(-1);
669         }
670       else
671         {
672           return argv[*pi];
673         }
674     }
675 }
676
677 /** Gets the integer argument to this option using the same rules as
678     getStringArg.
679 */
680 int
681 getIntArg(const char *szStart, char **argv, int *pi, int argc)
682 {
683     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
684 }
685
686 static void
687 verifyShortOption(const char *opt)
688 {
689   if (strlen(opt) != 2)
690     {
691       werror (W_EXCESS_SHORT_OPTIONS, opt);
692     }
693 }
694
695 static bool
696 tryHandleUnsupportedOpt(char **argv, int *pi)
697 {
698     if (argv[*pi][0] == '-') 
699         {
700             const char *longOpt = "";
701             char shortOpt = -1;
702             int i;
703
704             if (argv[*pi][1] == '-') 
705                 {
706                     /* Long option. */
707                     longOpt = argv[*pi];
708                 }
709             else 
710                 {
711                     shortOpt = argv[*pi][1];
712                 }
713             for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
714                 {
715                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
716                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
717                         /* Found an unsupported opt. */
718                         char buffer[100];
719                         SNPRINTF(buffer, sizeof(buffer), 
720                                  "%s%c%c", 
721                                  longOpt ? longOpt : "", 
722                                  shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
723                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
724                         return 1;
725                     }
726                 }
727             /* Didn't find in the table */
728             return 0;
729         }
730     else 
731         {
732             /* Not an option, so can't be unsupported :) */
733             return 0;
734     }
735 }
736
737 static bool
738 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
739 {
740   int i;
741   for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
742     {
743       if (optionsTable[i].shortOpt == shortOpt ||
744           (longOpt && optionsTable[i].longOpt && 
745            strcmp(optionsTable[i].longOpt, longOpt) == 0))
746         {
747
748           /* If it is a flag then we can handle it here */
749           if (optionsTable[i].pparameter != NULL) 
750             {
751               if (optionsTable[i].shortOpt == shortOpt)
752                 {
753                   verifyShortOption(argv[*pi]);
754                 }
755
756               (*optionsTable[i].pparameter)++;
757               return 1;
758             }
759           else {
760             /* Not a flag.  Handled manually later. */
761             return 0;
762           }
763         }
764     }
765   /* Didn't find in the table */
766   return 0;
767 }
768
769 static bool
770 tryHandleSimpleOpt(char **argv, int *pi)
771 {
772     if (argv[*pi][0] == '-') 
773         {
774             const char *longOpt = "";
775             char shortOpt = -1;
776
777             if (argv[*pi][1] == '-') 
778                 {
779                     /* Long option. */
780                     longOpt = argv[*pi];
781                 }
782             else 
783                 {
784                     shortOpt = argv[*pi][1];
785                 }
786
787             if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
788               {
789                 return 1;
790               }
791             else if (port && port->poptions &&
792                      scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
793               {
794                 return 1;
795               }
796             else
797               {
798                 return 0;
799               }
800         }
801     else 
802         {
803             /* Not an option, so can't be handled. */
804             return 0;
805         }
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* parseCmdLine - parses the command line and sets the options     */
810 /*-----------------------------------------------------------------*/
811 static int
812 parseCmdLine (int argc, char **argv)
813 {
814   int i;
815
816   /* go thru all whole command line */
817   for (i = 1; i < argc; i++)
818     {
819       if (i >= argc)
820         break;
821
822       if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
823           {
824               continue;
825           }
826
827       if (tryHandleSimpleOpt(argv, &i) == TRUE)
828           {
829               continue;
830           }
831
832       /* options */
833       if (argv[i][0] == '-' && argv[i][1] == '-')
834         {
835           if (strcmp (argv[i], OPTION_HELP) == 0)
836             {
837               printUsage ();
838               exit (0);
839             }
840
841           if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
842             {
843               options.stack10bit = 0;
844               continue;
845             }
846
847           if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
848             {
849               options.out_fmt = 0;
850               continue;
851             }
852
853           if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
854             {
855               _setModel (MODEL_LARGE, argv[i]);
856               continue;
857             }
858
859           if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
860             {
861               _setModel (MODEL_MEDIUM, argv[i]);
862               continue;
863             }
864
865           if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
866             {
867               _setModel (MODEL_SMALL, argv[i]);
868               continue;
869             }
870
871           if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
872             {
873               _setModel (MODEL_FLAT24, argv[i]);
874               continue;
875             }
876
877           if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
878             {
879               options.dump_rassgn =
880                 options.dump_pack =
881                 options.dump_range =
882                 options.dump_kill =
883                 options.dump_loop =
884                 options.dump_gcse =
885                 options.dump_raw = 1;
886               continue;
887             }
888
889           if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
890             {
891                 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
892                 continue;
893             }
894
895           if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
896             {
897                 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
898                 continue;
899             }
900
901           if (strcmp (argv[i], OPTION_VERSION) == 0)
902             {
903               printVersionInfo ();
904               exit (0);
905               continue;
906             }
907
908           if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
909             {
910                 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
911                 continue;
912             }
913
914           if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
915             {
916                 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
917                 continue;
918             }
919
920           if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
921             {
922                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
923                 continue;
924             }
925           
926       if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
927             {
928                 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
929                 continue;
930             }
931
932           if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
933             {
934                 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
935                 continue;
936             }
937
938           if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
939             {
940                 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
941                 continue;
942             }
943
944           if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
945             {
946                 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
947                 options.xram_size_set = TRUE;
948                 continue;
949             }
950
951           if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
952             {
953                 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
954                 continue;
955             }
956
957           if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
958             {
959                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
960                 continue;
961             }
962
963           if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
964             {
965                 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
966                 continue;
967             }
968
969           if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
970             {
971                 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
972                 continue;
973             }
974
975           if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
976             {
977               optimize.global_cse = 0;
978               continue;
979             }
980
981           if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
982             {
983               optimize.loopInvariant = 0;
984               continue;
985             }
986
987           if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
988             {
989               optimize.label4 = 0;
990               continue;
991             }
992
993           if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
994             {
995               optimize.loopInduction = 0;
996               continue;
997             }
998
999           if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
1000             {
1001               options.lessPedantic = 1;
1002               setErrorLogLevel(ERROR_LEVEL_WARNING);
1003               continue;
1004             }
1005
1006           if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
1007             {
1008               options.shortis8bits=1;
1009               continue;
1010             }
1011
1012           if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1013             {
1014                 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1015                 continue;
1016             }
1017           
1018           if (!port->parseOption (&argc, argv, &i))
1019             {
1020               werror (W_UNKNOWN_OPTION, argv[i]);
1021               continue;
1022             }
1023           else
1024             {
1025               continue;
1026             }
1027         }
1028
1029       /* if preceded by  '-' then option */
1030       if (*argv[i] == '-')
1031         {
1032           switch (argv[i][1])
1033             {
1034             case 'h':
1035               verifyShortOption(argv[i]);
1036
1037               printUsage ();
1038               exit (0);
1039               break;
1040
1041             case 'm':
1042               /* Used to select the port. But this has already been done. */
1043               break;
1044
1045             case 'p':
1046               /* Used to select the processor in port. But this has
1047                * already been done. */
1048               break;
1049
1050             case 'c':
1051               verifyShortOption(argv[i]);
1052
1053               options.cc_only = 1;
1054               break;
1055
1056             case 'L':
1057                 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1058                 break;
1059
1060             case 'l':
1061                 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1062                 break;
1063             
1064             case 'o':
1065               {
1066                 char *p;
1067
1068                 /* copy the file name into the buffer */
1069                 strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
1070                          sizeof(buffer));
1071                 /* point to last character */
1072                 p = buffer + strlen (buffer) - 1;
1073                 if (*p == DIR_SEPARATOR_CHAR)
1074                   {
1075                     /* only output path specified */
1076                     dstPath = Safe_strdup (buffer);
1077                     fullDstFileName = NULL;
1078                   }
1079                 else
1080                   {
1081                     fullDstFileName = Safe_strdup (buffer);
1082
1083                     /* get rid of the "."-extension */
1084
1085                     /* is there a dot at all? */
1086                     if (strrchr (buffer, '.') &&
1087                         /* is the dot in the filename, not in the path? */
1088                         (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1089                       *strrchr (buffer, '.') = '\0';
1090
1091                     dstFileName = Safe_strdup (buffer);
1092
1093                     /* strip module name to get path */
1094                     p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1095                     if (p)
1096                       {
1097                         /* path with trailing / */
1098                         p[1] = '\0';
1099                         dstPath = Safe_strdup (buffer);
1100                       }
1101                   }
1102                 break;
1103               }
1104
1105             case 'W':
1106               /* pre-processer options */
1107               if (argv[i][2] == 'p')
1108                 {
1109                   setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1110                 }
1111               /* linker options */
1112               else if (argv[i][2] == 'l')
1113                 {
1114                   setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1115                 }
1116               /* assembler options */
1117               else if (argv[i][2] == 'a')
1118                 {
1119                   setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1120                 }
1121               else
1122                 {
1123                   werror (W_UNKNOWN_OPTION, argv[i]);
1124                 }
1125               break;
1126
1127             case 'v':
1128               verifyShortOption(argv[i]);
1129
1130               printVersionInfo ();
1131               exit (0);
1132               break;
1133
1134               /* preprocessor options */
1135             case 'M':
1136               {
1137                 preProcOnly = 1;
1138                 if (argv[i][2] == 'M')
1139                   addSet(&preArgvSet, Safe_strdup("-MM"));
1140                 else
1141                   addSet(&preArgvSet, Safe_strdup("-M"));
1142                 break;
1143               }
1144             case 'C':
1145               {
1146                 addSet(&preArgvSet, Safe_strdup("-C"));
1147                 break;
1148               }
1149
1150             case 'd':
1151             case 'D':
1152             case 'I':
1153             case 'A':
1154             case 'U':
1155               {
1156                 char sOpt = argv[i][1];
1157                 char *rest;
1158
1159                 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1160                   {
1161                     i++;
1162                     if (i >= argc)
1163                       {
1164                           /* No argument. */
1165                           werror(E_ARGUMENT_MISSING, argv[i-1]);
1166                           break;
1167                       }
1168                     else
1169                       {
1170                           rest = argv[i];
1171                       }
1172                   }
1173                 else
1174                   rest = &argv[i][2];
1175
1176                 if (sOpt == 'Y')
1177                   sOpt = 'I';
1178
1179                 SNPRINTF (buffer, sizeof(buffer),
1180                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1181                 addSet(&preArgvSet, Safe_strdup(buffer));
1182                 if(sOpt == 'I')addSet(&includeDirsSet, Safe_strdup(rest));
1183               }
1184               break;
1185
1186             default:
1187               if (!port->parseOption (&argc, argv, &i))
1188                 werror (W_UNKNOWN_OPTION, argv[i]);
1189             }
1190           continue;
1191         }
1192
1193       if (!port->parseOption (&argc, argv, &i))
1194         {
1195            /* no option must be a filename */
1196            if (options.c1mode)
1197              {
1198                 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1199              }
1200          else
1201              {
1202                 processFile (argv[i]);
1203              }
1204         }
1205     }
1206
1207   /* some sanity checks in c1 mode */
1208   if (options.c1mode)
1209     {
1210       const char *s;
1211
1212       if (fullSrcFileName)
1213         {
1214           fclose (srcFile);
1215           werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1216         }
1217       fullSrcFileName = NULL;
1218       for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1219         {
1220           werror (W_NO_FILE_ARG_IN_C1, s);
1221         }
1222       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1223         {
1224           werror (W_NO_FILE_ARG_IN_C1, s);
1225         }
1226       deleteSet(&relFilesSet);
1227       deleteSet(&libFilesSet);
1228
1229         if (options.cc_only || noAssemble || preProcOnly)
1230         {
1231           werror (W_ILLEGAL_OPT_COMBINATION);
1232         }
1233       options.cc_only = noAssemble = preProcOnly = 0;
1234       if (!dstFileName)
1235         {
1236           werror (E_NEED_OPT_O_IN_C1);
1237           exit (1);
1238         }
1239     }
1240   /* if no dstFileName given with -o, we've to find one: */
1241   if (!dstFileName)
1242     {
1243       const char *s;
1244
1245       /* use the modulename from the C-source */
1246       if (fullSrcFileName)
1247         {
1248           size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1249
1250           dstFileName = Safe_alloc (bufSize);
1251           strncpyz (dstFileName, dstPath, bufSize);
1252           strncatz (dstFileName, moduleNameBase, bufSize);
1253         }
1254       /* use the modulename from the first object file */
1255       else if ((s = peekSet(relFilesSet)) != NULL)
1256         {
1257           char *objectName;
1258           size_t bufSize;
1259
1260           strncpyz (buffer, s, sizeof(buffer));
1261           /* remove extension (it must be .rel) */
1262           *strrchr (buffer, '.') = '\0';
1263           /* remove path */
1264           objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1265           if (objectName)
1266             {
1267               ++objectName;
1268             }
1269           else
1270             {
1271               objectName = buffer;
1272             }
1273           bufSize = strlen (dstPath) + strlen (objectName) + 1;  
1274           dstFileName = Safe_alloc (bufSize);
1275           strncpyz (dstFileName, dstPath, bufSize);
1276           strncatz (dstFileName, objectName, bufSize);
1277         }
1278       /* else no module given: help text is displayed */
1279     }
1280
1281   /* set up external stack location if not explicitly specified */
1282   if (!options.xstack_loc)
1283     options.xstack_loc = options.xdata_loc;
1284
1285   /* if debug option is set then open the cdbFile */
1286   if (options.debug && fullSrcFileName)
1287     {
1288       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1289                 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1290       if(debugFile->openFile(scratchFileName))
1291         debugFile->writeModule(moduleName);
1292       else
1293         werror (E_FILE_OPEN_ERR, scratchFileName);
1294     }
1295   MSVC_style(options.vc_err_style);
1296   if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1297
1298   return 0;
1299 }
1300
1301 /*-----------------------------------------------------------------*/
1302 /* linkEdit : - calls the linkage editor  with options             */
1303 /*-----------------------------------------------------------------*/
1304 static void
1305 linkEdit (char **envp)
1306 {
1307   FILE *lnkfile;
1308   char *segName, *c;
1309   int system_ret;
1310   const char *s;
1311
1312
1313   if(port->linker.needLinkerScript)
1314     {
1315       char out_fmt;
1316       
1317       switch (options.out_fmt)
1318         {
1319         case 0:
1320           out_fmt = 'i';        /* Intel hex */
1321           break;
1322         case 1:
1323           out_fmt = 's';        /* Motorola S19 */
1324           break;
1325         case 2:
1326           out_fmt = 't';        /* Elf */
1327           break;
1328         default:
1329           out_fmt = 'i';
1330         }
1331       
1332       /* first we need to create the <filename>.lnk file */
1333       SNPRINTF (scratchFileName, sizeof(scratchFileName),
1334         "%s.lnk", dstFileName);
1335       if (!(lnkfile = fopen (scratchFileName, "w")))
1336         {
1337           werror (E_FILE_OPEN_ERR, scratchFileName);
1338           exit (1);
1339         }
1340
1341       if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1342         {
1343           fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1344             out_fmt, dstFileName);
1345         }
1346       else /*For all the other ports.  Including pics???*/
1347         {
1348           fprintf (lnkfile, "-myux%c\n", out_fmt);
1349           if(options.pack_iram)
1350               fprintf (lnkfile, "-Y\n");
1351         }
1352
1353       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1354         {
1355           /* if iram size specified */
1356           if (options.iram_size)
1357             fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1358
1359           /* if stack size specified*/
1360           if(options.stack_size)
1361               fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1362
1363           /* if xram size specified */
1364           if (options.xram_size_set)
1365             fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1366
1367           /* if code size specified */
1368           if (options.code_size)
1369             fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1370
1371           if (options.debug)
1372             fprintf (lnkfile, "-z\n");
1373         }
1374
1375 #define WRITE_SEG_LOC(N, L) \
1376   segName = Safe_strdup(N); \
1377   c = strtok(segName, " \t"); \
1378   fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1379   if (segName) { Safe_free(segName); }
1380
1381       if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1382         {
1383
1384           /* code segment start */
1385           WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1386
1387           /* data segment start. If zero, the linker chooses
1388              the best place for data */
1389           if(options.data_loc)
1390             {
1391               WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1392             }
1393
1394           /* xdata start */
1395           WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1396
1397           /* indirect data */
1398           if (IDATA_NAME)
1399             {
1400               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1401             }
1402
1403             /* bit segment start */
1404             WRITE_SEG_LOC (BIT_NAME, 0);
1405
1406             /* stack start */
1407             if ( (options.stack_loc) && (options.stack_loc<0x100) )
1408               {
1409                 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1410               }
1411         }
1412       else /*For the z80, gbz80*/
1413         {
1414           WRITE_SEG_LOC ("_CODE", options.code_loc);
1415           WRITE_SEG_LOC ("_DATA", options.data_loc);
1416         }
1417   
1418       /* If the port has any special linker area declarations, get 'em */
1419       if (port->extraAreas.genExtraAreaLinkOptions)
1420         {
1421           port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1422         }
1423
1424       /* add the extra linker options */
1425       fputStrSet(lnkfile, linkOptionsSet);
1426
1427       /* command line defined library paths if specified */
1428       for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1429         fprintf (lnkfile, "-k %s\n", s);
1430
1431       /* standard library path */
1432       if (!options.nostdlib)
1433         {
1434           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1435             {
1436               switch (options.model)
1437                 {
1438                   case MODEL_SMALL:
1439                   c = "small";
1440                   break;
1441                 case MODEL_LARGE:
1442                   c = "large";
1443                   break;
1444                 case MODEL_FLAT24:
1445                   /* c = "flat24"; */
1446                   if (TARGET_IS_DS390)
1447                     {
1448                       c = "ds390";
1449                     }
1450                   else if (TARGET_IS_DS400)
1451                     {
1452                       c = "ds400";
1453                     }
1454                   else
1455                     {
1456                       fprintf(stderr, 
1457                         "Add support for your FLAT24 target in %s @ line %d\n",
1458                         __FILE__, __LINE__);
1459                       exit(-1);
1460                     }
1461                   break;
1462                 case MODEL_PAGE0:
1463                   c = "xa51";
1464                   break;
1465                 default:
1466                   werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1467                   c = "unknown";
1468                   break;
1469                 }
1470             }
1471           else /*for the z80, gbz80*/
1472             {
1473               if (TARGET_IS_HC08)
1474                 c = "hc08";
1475               else if (TARGET_IS_Z80)
1476                 c = "z80";
1477               else
1478                 c = "gbz80";
1479             }
1480           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1481             mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1482         }
1483
1484       /* command line defined library files if specified */
1485       for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1486         fprintf (lnkfile, "-l %s\n", s);
1487
1488       /* standard library files */
1489       if (!options.nostdlib)
1490         {
1491 #if !OPT_DISABLE_DS390
1492           if (options.model == MODEL_FLAT24)
1493             {
1494               if (TARGET_IS_DS390)
1495                 {
1496                   fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1497                 }
1498               else if (TARGET_IS_DS400)
1499                 {
1500                   fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1501                 }
1502               else
1503                 {
1504                   fprintf(stderr, 
1505                     "Add support for your FLAT24 target in %s @ line %d\n",
1506                     __FILE__, __LINE__);
1507                   exit(-1);
1508                 }
1509               }
1510 #endif
1511
1512 #if !OPT_DISABLE_XA51 
1513 #ifdef STD_XA51_LIB
1514           if (options.model == MODEL_PAGE0)
1515             {
1516               fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1517             }
1518 #endif
1519 #endif
1520           if (TARGET_IS_MCS51)
1521             {
1522               fprintf (lnkfile, "-l mcs51\n");
1523             }
1524           if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1525             || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1526             { /*Why the z80 port is not using the standard libraries?*/
1527               fprintf (lnkfile, "-l %s\n", STD_LIB);
1528               fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1529               fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1530               fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1531             }
1532           else if (TARGET_IS_HC08)
1533             {
1534               fprintf (lnkfile, "-l hc08\n");
1535             }
1536           else if (TARGET_IS_Z80)
1537             {
1538               fprintf (lnkfile, "-l z80\n");
1539             }
1540           else if (TARGET_IS_GBZ80)
1541             {
1542               fprintf (lnkfile, "-l gbz80\n");
1543             }
1544         }
1545
1546       /*For the z80 and gbz80 ports, try to find where crt0.o is...
1547       It is very important for this file to be first on the linking proccess
1548       so the areas are set in the correct order, expecially _GSINIT*/
1549       if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1550         !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1551         {
1552           char crt0path[PATH_MAX];
1553           FILE * crt0fp;
1554           for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1555             {
1556               sprintf (crt0path, "%s%s%s%scrt0.o",
1557                 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1558
1559               crt0fp=fopen(crt0path, "r");
1560               if(crt0fp!=NULL)/*Found it!*/
1561                 {
1562                   fclose(crt0fp);
1563                   #ifdef __CYGWIN__
1564                   {
1565                     /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1566                     windows paths, so convert them to the CYGWIN format*/
1567                     char posix_path[PATH_MAX];
1568                     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1569                     cygwin_conv_to_full_posix_path(crt0path, posix_path);
1570                     strcpy(crt0path, posix_path);
1571                   }
1572                   #endif
1573                   fprintf (lnkfile, "%s\n", crt0path);
1574                   break;
1575                 }
1576             }
1577           if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1578         }
1579
1580       /* put in the object files */
1581       if (fullSrcFileName)
1582         fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1583
1584       fputStrSet(lnkfile, relFilesSet);
1585
1586       fprintf (lnkfile, "\n-e\n");
1587       fclose (lnkfile);
1588     } /* if(port->linker.needLinkerScript) */
1589
1590   if (options.verbose)
1591     printf ("sdcc: Calling linker...\n");
1592
1593   /* build linker output filename */
1594
1595   /* -o option overrides default name? */
1596   if (fullDstFileName)
1597     {
1598       strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1599     }
1600   else
1601     {
1602       /* the linked file gets the name of the first modul */
1603       if (fullSrcFileName)
1604         {
1605           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1606         }
1607       else
1608         {
1609           s = peekSet(relFilesSet);
1610
1611           assert(s);
1612
1613           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1614           /* strip ".rel" extension */
1615           *strrchr (scratchFileName, '.') = '\0';
1616         }
1617       strncatz (scratchFileName, 
1618         options.out_fmt ? ".S19" : ".ihx",
1619         sizeof(scratchFileName));
1620     }
1621
1622   if (port->linker.cmd)
1623     {
1624       char buffer2[PATH_MAX];
1625       char buffer3[PATH_MAX];
1626       set *tempSet=NULL, *libSet=NULL;
1627
1628       strcpy(buffer3, dstFileName);
1629       if(TARGET_IS_PIC16) {
1630         
1631          /* use $l to set the linker include directories */
1632          tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1633          mergeSets(&linkOptionsSet, tempSet);
1634          
1635          tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1636          mergeSets(&linkOptionsSet, tempSet);
1637
1638          /* use $3 for libraries from command line --> libSet */
1639          mergeSets(&libSet, libFilesSet);
1640
1641          tempSet = appendStrSet(relFilesSet, "", "");
1642          mergeSets(&libSet, tempSet);
1643 //         libSet = reverseSet(libSet);
1644
1645         if(fullSrcFileName) {
1646 //              strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1647                 /* if it didn't work, revert to old behaviour */
1648                 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1649                 strcat(buffer3, port->linker.rel_ext);
1650                 
1651         } else strcpy(buffer3, "");
1652       }
1653       
1654       buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1655
1656       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1657     }
1658   else
1659     {
1660       buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1661     }
1662
1663   /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1664
1665   system_ret = my_system (buffer);
1666   /* TODO: most linker don't have a -o parameter */
1667   /* -o option overrides default name? */
1668   if (fullDstFileName)
1669     {
1670       char *p, *q;
1671       /* the linked file gets the name of the first modul */
1672       if (fullSrcFileName)
1673         {
1674           strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1675           p = strlen (scratchFileName) + scratchFileName;
1676         }
1677       else
1678         {
1679           s = peekSet(relFilesSet);
1680
1681           assert(s);
1682
1683           strncpyz (scratchFileName, s, sizeof(scratchFileName));
1684           /* strip ".rel" extension */
1685           p = strrchr (scratchFileName, '.');
1686           if (p)
1687             {
1688               *p = 0;
1689             }
1690         }
1691       strncatz (scratchFileName,
1692         options.out_fmt ? ".S19" : ".ihx",
1693         sizeof(scratchFileName));
1694       if (strcmp (fullDstFileName, scratchFileName))
1695         unlink (fullDstFileName);
1696       rename (scratchFileName, fullDstFileName);
1697
1698       strncpyz (buffer, fullDstFileName, sizeof(buffer));
1699       q = strrchr (buffer, '.');
1700       if (!q)
1701         {
1702           /* no extension: append new extensions */
1703           q = strlen (buffer) + buffer;
1704         }
1705
1706       *p = 0;
1707       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1708       *q = 0;
1709       strncatz(buffer, ".map", sizeof(buffer));
1710       if (strcmp (scratchFileName, buffer))
1711         unlink (buffer);
1712       rename (scratchFileName, buffer);
1713       *p = 0;
1714       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1715       *q = 0;
1716       strncatz(buffer, ".mem", sizeof(buffer));
1717       if (strcmp (scratchFileName, buffer))
1718         unlink (buffer);
1719       rename (scratchFileName, buffer);
1720       if (options.debug)
1721         {
1722           *p = 0;
1723           strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1724           *q = 0;
1725           strncatz(buffer, ".cdb", sizeof(buffer));
1726           if (strcmp (scratchFileName, buffer))
1727             unlink (buffer);
1728           rename (scratchFileName, buffer);
1729           /* and the OMF file without extension: */
1730           *p = 0;
1731           *q = 0;
1732           if (strcmp (scratchFileName, buffer))
1733             unlink (buffer);
1734           rename (scratchFileName, buffer);
1735         }
1736     }
1737   if (system_ret)
1738     {
1739       exit (1);
1740     }
1741 }
1742
1743 /*-----------------------------------------------------------------*/
1744 /* assemble - spawns the assembler with arguments                  */
1745 /*-----------------------------------------------------------------*/
1746 static void
1747 assemble (char **envp)
1748 {
1749     /* build assembler output filename */
1750
1751     /* -o option overrides default name? */
1752     if (options.cc_only && fullDstFileName) {
1753         strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1754     } else {
1755         /* the assembled file gets the name of the first modul */
1756         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1757         strncatz (scratchFileName, port->linker.rel_ext, 
1758                   sizeof(scratchFileName));
1759     }
1760
1761     if (port->assembler.do_assemble) {
1762         port->assembler.do_assemble(asmOptionsSet);
1763         return ;
1764     } else if (port->assembler.cmd) {
1765         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1766                       options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1767                       asmOptionsSet);
1768     } else {
1769         buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1770     }
1771
1772     if (my_system (buffer)) {
1773         /* either system() or the assembler itself has reported an error
1774            perror ("Cannot exec assembler");
1775         */
1776         exit (1);
1777     }
1778     /* TODO: most assembler don't have a -o parameter */
1779     /* -o option overrides default name? */
1780     if (options.cc_only && fullDstFileName) {
1781         strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1782         strncatz (scratchFileName, 
1783                   port->linker.rel_ext,
1784                   sizeof(scratchFileName));
1785         if (strcmp (scratchFileName, fullDstFileName))
1786           unlink (fullDstFileName);
1787         rename (scratchFileName, fullDstFileName);
1788     }
1789 }
1790
1791 /*-----------------------------------------------------------------*/
1792 /* preProcess - spawns the preprocessor with arguments       */
1793 /*-----------------------------------------------------------------*/
1794 static int
1795 preProcess (char **envp)
1796 {
1797   if (options.c1mode)
1798     {
1799       yyin = stdin;
1800     }
1801   else
1802     {
1803       const char *s;
1804       set *inclList = NULL;
1805
1806       /* if using external stack define the macro */
1807       if (options.useXstack)
1808         addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1809
1810       /* set the macro for stack autos  */
1811       if (options.stackAuto)
1812         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1813
1814       /* set the macro for stack autos  */
1815       if (options.stack10bit)
1816         addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1817
1818       /* set the macro for no overlay  */
1819       if (options.noOverlay)
1820         addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1821
1822       /* set the macro for large model  */
1823       switch (options.model)
1824         {
1825         case MODEL_LARGE:
1826           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1827           break;
1828         case MODEL_SMALL:
1829           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1830           break;
1831         case MODEL_COMPACT:
1832           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1833           break;
1834         case MODEL_MEDIUM:
1835           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1836           break;
1837         case MODEL_FLAT24:
1838           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1839           break;
1840         case MODEL_PAGE0:
1841           addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1842           break;
1843         default:
1844           werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1845           break;
1846         }
1847
1848       /* add port (processor information to processor */
1849       addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1850       addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1851
1852       /* standard include path */
1853       if (!options.nostdinc) {
1854         inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1855         mergeSets(&preArgvSet, inclList);
1856       }
1857
1858       setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1859       Safe_free((void *)s);
1860       if (inclList != NULL)
1861         deleteSet(&inclList);
1862
1863       if (preProcOnly && fullDstFileName)
1864         {
1865           /* -E and -o given */
1866           setMainValue ("cppoutfilename", fullDstFileName);
1867         }
1868       else
1869         {
1870           /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1871           setMainValue ("cppoutfilename", NULL);
1872         }
1873
1874       if (options.verbose)
1875         printf ("sdcc: Calling preprocessor...\n");
1876
1877       buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1878
1879       if (preProcOnly) {
1880         if (my_system (buffer)) {
1881           exit (1);
1882         }
1883
1884         exit (0);
1885       }
1886
1887       yyin = my_popen (buffer);
1888       if (yyin == NULL) {
1889           perror ("Preproc file not found");
1890           exit (1);
1891       }
1892       addSetHead (&pipeSet, yyin);
1893     }
1894
1895   return 0;
1896 }
1897
1898 /* Set bin paths */
1899 static void
1900 setBinPaths(const char *argv0)
1901 {
1902   char *p;
1903   char buf[PATH_MAX];
1904
1905   /*
1906    * Search logic:
1907    *
1908    * 1. - $SDCCDIR/PREFIX2BIN_DIR
1909    * 2. - path(argv[0])
1910    * 3. - $PATH
1911    */
1912
1913   /* do it in reverse mode, so that addSetHead() can be used
1914      instead of slower addSet() */
1915
1916   if ((p = getBinPath(argv0)) != NULL)
1917     addSetHead(&binPathSet, Safe_strdup(p));
1918
1919   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1920     SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1921     addSetHead(&binPathSet, Safe_strdup(buf));
1922   }
1923
1924 #if 0
1925   if (options.printSearchDirs) {
1926     printf("programs:\n");
1927     fputStrSet(stdout, binPathSet);
1928   }
1929 #endif
1930 }
1931
1932 /* Set system include path */
1933 static void
1934 setIncludePath(void)
1935 {
1936   char *p;
1937
1938   /*
1939    * Search logic:
1940    *
1941    * 1. - $SDCC_INCLUDE
1942    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1943    * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1944    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1945    */
1946
1947   includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1948
1949   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1950     addSetHead(&includeDirsSet, p);
1951
1952 #if 0
1953   if (options.printSearchDirs) {
1954     printf("includedir:\n");
1955     fputStrSet(stdout, includeDirsSet);
1956   }
1957 #endif
1958 }
1959
1960 /* Set system lib path */
1961 static void
1962 setLibPath(void)
1963 {
1964   char *p;
1965
1966   /*
1967    * Search logic:
1968    *
1969    * 1. - $SDCC_LIB
1970    * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1971    * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1972    * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1973    */
1974
1975   libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1976
1977   if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1978     addSetHead(&libDirsSet, p);
1979
1980 #if 0
1981   if (options.printSearchDirs) {
1982     printf("libdir:\n");
1983     fputStrSet(stdout, libDirsSet);
1984   }
1985 #endif
1986 }
1987
1988 /* Set data path */
1989 static void
1990 setDataPaths(const char *argv0)
1991 {
1992   char *p;
1993   char buf[PATH_MAX];
1994
1995   /*
1996    * Search logic:
1997    *
1998    * 1. - $SDCC_HOME/PREFIX2DATA_DIR
1999    * 2. - path(argv[0])/BIN2DATA_DIR
2000    * 3. - DATADIR (only on *nix)
2001    */
2002
2003   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2004     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2005     addSet(&dataDirsSet, Safe_strdup(buf));
2006   }
2007
2008   if ((p = getBinPath(argv0)) != NULL) {
2009     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2010     addSet(&dataDirsSet, Safe_strdup(buf));
2011   }
2012
2013 #ifdef _WIN32
2014   if (peekSet(dataDirsSet) == NULL) {
2015     /* this should never happen... */
2016     wassertl(0, "Can't get binary path");
2017   }
2018 #else
2019   addSet(&dataDirsSet, Safe_strdup(DATADIR));
2020 #endif
2021
2022 #if 0
2023   if (options.printSearchDirs) {
2024     printf("datadir:\n");
2025     fputStrSet(stdout, dataDirsSet);
2026   }
2027 #endif
2028
2029   setIncludePath();
2030   setLibPath();
2031 }
2032
2033 static void
2034 initValues (void)
2035 {
2036   populateMainValues (_baseValues);
2037   setMainValue ("port", port->target);
2038   setMainValue ("objext", port->linker.rel_ext);
2039   setMainValue ("asmext", port->assembler.file_ext);
2040
2041   setMainValue ("dstfilename", dstFileName);
2042   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2043
2044   if (options.cc_only && fullDstFileName)
2045     /* compile + assemble and -o given: -o specifies name of object file */
2046     {
2047       setMainValue ("objdstfilename", fullDstFileName);
2048     }
2049   else
2050     {
2051       setMainValue ("objdstfilename", "{stdobjdstfilename}");
2052     }
2053   if (fullDstFileName)
2054     /* if we're linking, -o gives the final file name */
2055     {
2056       setMainValue ("linkdstfilename", fullDstFileName);
2057     }
2058   else
2059     {
2060       setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2061     }
2062
2063 }
2064
2065 static void doPrintSearchDirs(void)
2066 {
2067     printf("programs:\n");
2068     fputStrSet(stdout, binPathSet);
2069
2070     printf("datadir:\n");
2071     fputStrSet(stdout, dataDirsSet);
2072
2073     printf("includedir:\n");
2074     fputStrSet(stdout, includeDirsSet);
2075
2076     printf("libdir:\n");
2077     fputStrSet(stdout, libDirsSet);
2078     fputStrSet(stdout, libPathsSet);
2079 }
2080
2081
2082 static void
2083 sig_handler (int signal)
2084 {
2085   char *sig_string;
2086
2087   switch (signal)
2088     {
2089     case SIGABRT:
2090       sig_string = "SIGABRT";
2091       break;
2092     case SIGTERM:
2093       sig_string = "SIGTERM";
2094       break;
2095     case SIGINT:
2096       sig_string = "SIGINT";
2097       break;
2098     case SIGSEGV:
2099       sig_string = "SIGSEGV";
2100       break;
2101     default:
2102       sig_string = "Unknown?";
2103       break;
2104     }
2105   fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2106   exit (1);
2107 }
2108
2109 /*
2110  * main routine
2111  * initialises and calls the parser
2112  */
2113
2114 int
2115 main (int argc, char **argv, char **envp)
2116 {
2117   /* turn all optimizations off by default */
2118   memset (&optimize, 0, sizeof (struct optimize));
2119
2120   /*printVersionInfo (); */
2121
2122   if (NUM_PORTS==0) {
2123     fprintf (stderr, "Build error: no ports are enabled.\n");
2124     exit (1);
2125   }
2126
2127   /* install atexit handler */
2128   atexit(rm_tmpfiles);
2129
2130   /* install signal handler;
2131      it's only purpuse is to call exit() to remove temp files */
2132   if (!getenv("SDCC_LEAVE_SIGNALS"))
2133     {
2134       signal (SIGABRT, sig_handler);
2135       signal (SIGTERM, sig_handler);
2136       signal (SIGINT , sig_handler);
2137       signal (SIGSEGV, sig_handler);
2138     }
2139
2140   /* Before parsing the command line options, do a
2141    * search for the port and processor and initialize
2142    * them if they're found. (We can't gurantee that these
2143    * will be the first options specified).
2144    */
2145
2146   _findPort (argc, argv);
2147
2148 #ifdef JAMIN_DS390
2149   if (strcmp(port->target, "mcs51") == 0) {
2150     printf("DS390 jammed in A\n");
2151           _setPort ("ds390");
2152     ds390_jammed = 1;
2153   }
2154 #endif
2155
2156   _findProcessor (argc, argv);
2157
2158   /* Initalise the port. */
2159   if (port->init)
2160     port->init ();
2161
2162   setDefaultOptions ();
2163 #ifdef JAMIN_DS390
2164   if (ds390_jammed) {
2165     options.model = MODEL_SMALL;
2166     options.stack10bit=0;
2167   }
2168 #endif
2169   parseCmdLine (argc, argv);
2170
2171   initValues ();
2172   setBinPaths(argv[0]);
2173   setDataPaths(argv[0]);
2174
2175   if(port->initPaths)
2176         port->initPaths();
2177   
2178   if(options.printSearchDirs)
2179         doPrintSearchDirs();
2180
2181   /* if no input then printUsage & exit */
2182   if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2183     if (!options.printSearchDirs)
2184       printUsage();
2185
2186     exit(0);
2187   }
2188
2189   /* initMem() is expensive, but
2190      initMem() must called before port->finaliseOptions ().
2191      And the z80 port needs port->finaliseOptions(),
2192      even if we're only linking. */
2193   initMem ();
2194   port->finaliseOptions ();
2195
2196   if (fullSrcFileName || options.c1mode)
2197     {
2198       preProcess (envp);
2199
2200       initSymt ();
2201       initiCode ();
2202       initCSupport ();
2203       initBuiltIns();
2204       initPeepHole ();
2205
2206       if (options.verbose)
2207         printf ("sdcc: Generating code...\n");
2208
2209       yyparse ();
2210
2211       if (pclose(yyin))
2212         fatalError = 1;
2213       deleteSetItem(&pipeSet, yyin);
2214
2215       if (fatalError) {
2216         exit (1);
2217       }
2218
2219       if (port->general.do_glue != NULL)
2220         (*port->general.do_glue)();
2221       else
2222         {
2223           /* this shouldn't happen */
2224           assert(FALSE);
2225           /* in case of NDEBUG */
2226           glue();
2227         }
2228
2229       if (fatalError) {
2230         exit (1);
2231       }
2232
2233       if (!options.c1mode && !noAssemble)
2234         {
2235           if (options.verbose)
2236             printf ("sdcc: Calling assembler...\n");
2237           assemble (envp);
2238         }
2239     }
2240   closeDumpFiles();
2241
2242   if (options.debug && debugFile)
2243     debugFile->closeFile();
2244
2245   if (!options.cc_only &&
2246       !fatalError &&
2247       !noAssemble &&
2248       !options.c1mode &&
2249       (fullSrcFileName || peekSet(relFilesSet) != NULL))
2250     {
2251       if (port->linker.do_link)
2252         port->linker.do_link ();
2253       else
2254         linkEdit (envp);
2255     }
2256
2257   return 0;
2258 }