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