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