1 /*-------------------------------------------------------------------------
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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
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.
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.
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 -------------------------------------------------------------------------*/
38 #include "SDCCmacro.h"
40 #include "SDCCdebug.h"
51 extern int yyparse (void);
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 */
66 int RegBankUsed[4] = {1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
67 int BitBankUsed; /* MB: overlayable bit bank */
68 struct optimize optimize;
69 struct options options;
72 set *preArgvSet = NULL; /* pre-processor arguments */
73 set *asmOptionsSet = NULL; /* set of assembler options */
74 set *linkOptionsSet = NULL; /* set of linker options */
75 set *libFilesSet = NULL;
76 set *libPathsSet = NULL;
77 set *relFilesSet = NULL;
78 set *dataDirsSet = NULL; /* list of data search directories */
79 set *includeDirsSet = NULL; /* list of include search directories */
80 set *userIncDirsSet = NULL; /* list of user include directories */
81 set *libDirsSet = NULL; /* list of lib search directories */
83 /* uncomment JAMIN_DS390 to always override and use ds390 port
84 for mcs51 work. This is temporary, for compatibility testing. */
85 /* #define JAMIN_DS390 */
90 /* Globally accessible scratch buffer for file names. */
91 char scratchFileName[PATH_MAX];
92 char buffer[PATH_MAX * 2];
94 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
96 #define OPTION_HELP "--help"
97 #define OPTION_STACK_8BIT "--stack-8bit"
98 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
99 #define OPTION_OUT_FMT_S19 "--out-fmt-s19"
100 #define OPTION_LARGE_MODEL "--model-large"
101 #define OPTION_MEDIUM_MODEL "--model-medium"
102 #define OPTION_SMALL_MODEL "--model-small"
103 #define OPTION_FLAT24_MODEL "--model-flat24"
104 #define OPTION_DUMP_ALL "--dumpall"
105 #define OPTION_PEEP_FILE "--peep-file"
106 #define OPTION_LIB_PATH "--lib-path"
107 #define OPTION_CALLEE_SAVES "--callee-saves"
108 #define OPTION_STACK_LOC "--stack-loc"
109 #define OPTION_XSTACK_LOC "--xstack-loc"
110 #define OPTION_DATA_LOC "--data-loc"
111 #define OPTION_IDATA_LOC "--idata-loc"
112 #define OPTION_XRAM_LOC "--xram-loc"
113 #define OPTION_CODE_LOC "--code-loc"
114 #define OPTION_STACK_SIZE "--stack-size"
115 #define OPTION_IRAM_SIZE "--iram-size"
116 #define OPTION_XRAM_SIZE "--xram-size"
117 #define OPTION_CODE_SIZE "--code-size"
118 #define OPTION_VERSION "--version"
119 #define OPTION_NO_LABEL_OPT "--nolabelopt"
120 #define OPTION_NO_LOOP_INV "--noinvariant"
121 #define OPTION_NO_LOOP_IND "--noinduction"
122 #define OPTION_LESS_PEDANTIC "--less-pedantic"
123 #define OPTION_DISABLE_WARNING "--disable-warning"
124 #define OPTION_NO_GCSE "--nogcse"
125 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
126 #define OPTION_TINI_LIBID "--tini-libid"
127 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
128 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
129 #define OPTION_ICODE_IN_ASM "--i-code-in-asm"
130 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
131 #define OPTION_MSVC_ERROR_STYLE "--vc"
132 #define OPTION_USE_STDOUT "--use-stdout"
133 #define OPTION_PACK_IRAM "--pack-iram"
134 #define OPTION_NO_PACK_IRAM "--no-pack-iram"
135 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
136 #define OPTION_OPT_CODE_SPEED "--opt-code-speed"
137 #define OPTION_OPT_CODE_SIZE "--opt-code-size"
138 #define OPTION_STD_C89 "--std-c89"
139 #define OPTION_STD_C99 "--std-c99"
140 #define OPTION_STD_SDCC89 "--std-sdcc89"
141 #define OPTION_STD_SDCC99 "--std-sdcc99"
142 #define OPTION_CODE_SEG "--codeseg"
143 #define OPTION_CONST_SEG "--constseg"
147 { 0, NULL, NULL, "General options" },
148 { 0, OPTION_HELP, NULL, "Display this help" },
149 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
150 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
151 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
152 { 'd', NULL, NULL, NULL },
153 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
154 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
155 { 'A', NULL, NULL, NULL },
156 { 'U', NULL, NULL, NULL },
157 { 'C', NULL, NULL, "Preprocessor option" },
158 { 'M', NULL, NULL, "Preprocessor option" },
159 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
160 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
161 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
162 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
163 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
164 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
165 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
166 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
167 { 0, OPTION_USE_STDOUT, NULL, "send errors to stdout instead of stderr"},
168 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
169 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
170 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
171 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
172 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
173 { 0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions" },
174 { 0, OPTION_STD_C89, NULL, "Use C89 standard only" },
175 { 0, OPTION_STD_SDCC89, NULL, "Use C89 standard with SDCC extensions (default)" },
176 { 0, OPTION_STD_C99, NULL, "Use C99 standard only (incomplete)" },
177 { 0, OPTION_STD_SDCC99, NULL, "Use C99 standard with SDCC extensions (incomplete)" },
179 { 0, NULL, NULL, "Code generation options"},
180 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
181 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
182 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
183 { 0, OPTION_MEDIUM_MODEL, NULL, "external paged data space is used" },
184 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
185 #if !OPT_DISABLE_DS390
186 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
187 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
188 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
190 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
191 { 0, "--xstack", &options.useXstack, "Use external stack" },
192 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
193 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
194 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
195 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
196 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
197 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
198 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
199 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
200 #if !OPT_DISABLE_DS390
201 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
203 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
204 #if !OPT_DISABLE_TININative
205 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
207 #if !OPT_DISABLE_DS390
208 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
210 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
211 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
213 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
214 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
215 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
216 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
217 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
219 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" },
220 { 0, OPTION_CODE_SEG, NULL, "<name> use this name for the code segment" },
221 { 0, OPTION_CONST_SEG, NULL, "<name> use this name for the const segment" },
223 { 0, NULL, NULL, "Optimization options"},
224 { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" },
225 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
226 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
227 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
228 { 0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction" },
229 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
230 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
231 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
232 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
233 { 0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly" },
234 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peephole file" },
235 { 0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size" },
236 { 0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed" },
238 { 0, NULL, NULL, "Internal debugging options"},
239 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
240 { 0, "--dumpgcse", &options.dump_gcse, NULL },
241 { 0, "--dumploop", &options.dump_loop, NULL },
242 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
243 { 0, "--dumpliverange", &options.dump_range, NULL },
244 { 0, "--dumpregpack", &options.dump_pack, NULL },
245 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
246 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
247 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
248 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
250 { 0, NULL, NULL, "Linker options" },
251 { 'l', NULL, NULL, "Include the given library in the link" },
252 { 'L', NULL, NULL, "Add the next field to the library search path" },
253 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
254 { 0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format" },
255 { 0, OPTION_OUT_FMT_S19, NULL, "Output in S19 hex format" },
256 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
257 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
258 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
259 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
260 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
261 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
262 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
263 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
264 { 0, OPTION_IDATA_LOC, NULL, NULL },
265 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51 || !OPT_DISABLE_PIC
266 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390/PIC - Tells the linker to allocate this space for stack"},
268 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
269 { 0, OPTION_PACK_IRAM, NULL,"MCS51/DS390 - Tells the linker to pack variables in internal ram (default)"},
270 { 0, OPTION_NO_PACK_IRAM, &options.no_pack_iram,"MCS51/DS390 - Tells the linker not to pack variables in internal ram"},
277 /** Table of all unsupported options and help text to display when one
281 /** shortOpt as in OPTIONS. */
283 /** longOpt as in OPTIONS. */
285 /** Message to display inside W_UNSUPPORTED_OPT when this option
290 static const UNSUPPORTEDOPT
291 unsupportedOptTable[] = {
292 { 'X', NULL, "use --xstack-loc instead" },
293 { 'x', NULL, "use --xstack instead" },
294 { 'i', NULL, "use --idata-loc instead" },
295 { 'r', NULL, "use --xdata-loc instead" },
296 { 's', NULL, "use --code-loc instead" },
297 { 'Y', NULL, "use -I instead" }
300 /** List of all default constant macros.
302 static const char *_baseValues[] = {
305 /* Path seperator character */
306 "sep", DIR_SEPARATOR_STRING,
310 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
314 static PORT *_ports[] =
316 #if !OPT_DISABLE_MCS51
319 #if !OPT_DISABLE_GBZ80
328 #if !OPT_DISABLE_DS390
331 #if !OPT_DISABLE_PIC16
337 #if !OPT_DISABLE_TININative
340 #if !OPT_DISABLE_XA51
343 #if !OPT_DISABLE_DS400
346 #if !OPT_DISABLE_HC08
351 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
353 /** Sets the port to the one given by the command line option.
354 @param The name minus the option (eg 'mcs51')
355 @return 0 on success.
358 _setPort (const char *name)
361 for (i = 0; i < NUM_PORTS; i++)
363 if (!strcmp (_ports[i]->target, name))
369 /* Error - didnt find */
370 werror (E_UNKNOWN_TARGET, name);
374 /* Override the default processor with the one specified
375 * on the command line */
377 _setProcessor (char *_processor)
379 port->processor = _processor;
383 _validatePorts (void)
386 for (i = 0; i < NUM_PORTS; i++)
388 if (_ports[i]->magic != PORT_MAGIC)
390 /* Uncomment this line to debug which port is causing the problem
391 * (the target name is close to the beginning of the port struct
392 * and probably can be accessed just fine). */
393 fprintf(stderr,"%s :",_ports[i]->target);
394 wassertl (0, "Port definition structure is incomplete");
399 /* search through the command line options for the port */
401 _findPort (int argc, char **argv)
407 if (!strncmp (*argv, "-m", 2))
409 _setPort (*argv + 2);
415 /* Use the first in the list */
419 /* search through the command line options for the processor */
421 _findProcessor (int argc, char **argv)
425 if (!strncmp (*argv, "-p", 2))
427 _setProcessor (*argv + 2);
433 /* no error if processor was not specified. */
436 /*-----------------------------------------------------------------*/
437 /* printVersionInfo - prints the version info */
438 /*-----------------------------------------------------------------*/
440 printVersionInfo (FILE *stream)
446 for (i = 0; i < NUM_PORTS; i++)
447 fprintf (stream, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
449 fprintf (stream, " " SDCC_VERSION_STR
450 #ifdef SDCC_SUB_VERSION_STR
451 "/" SDCC_SUB_VERSION_STR
453 " #%s (" __DATE__ ")"
456 #elif defined __MINGW32__
458 #elif defined __DJGPP__
460 #elif defined(_MSC_VER)
462 #elif defined(__BORLANDC__)
467 , getBuildNumber() );
471 printOptions(const OPTION *optionsTable, FILE *stream)
475 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
476 || optionsTable[i].help != NULL;
479 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
480 && optionsTable[i].help)
482 fprintf (stream, "\n%s:\n", optionsTable[i].help);
486 fprintf(stream, " %c%c %-20s %s\n",
487 optionsTable[i].shortOpt !=0 ? '-' : ' ',
488 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
489 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
490 optionsTable[i].help != NULL ? optionsTable[i].help : ""
496 /*-----------------------------------------------------------------*/
497 /* printUsage - prints command line syntax */
498 /*-----------------------------------------------------------------*/
503 FILE *stream = stderr;
505 printVersionInfo (stream);
507 "Usage : sdcc [options] filename\n"
511 printOptions (optionsTable, stream);
513 for (i = 0; i < NUM_PORTS; i++)
515 if (_ports[i]->poptions != NULL)
517 fprintf (stream, "\nSpecial options for the %s port:\n", _ports[i]->target);
518 printOptions (_ports[i]->poptions, stream);
523 /*-----------------------------------------------------------------*/
524 /* setParseWithComma - separates string with comma to a set */
525 /*-----------------------------------------------------------------*/
527 setParseWithComma (set **dest, const char *src)
532 /* skip the initial white spaces */
533 while (isspace((unsigned char)*src))
536 /* skip the trailing white spaces */
537 end = &src[strlen(src) - 1];
538 while (end >= src && isspace((unsigned char)*end))
542 dbuf_init(&dbuf, 16);
547 while (p < end && ',' != *p)
549 dbuf_append(&dbuf, src, p - src);
550 addSet(dest, Safe_strdup(dbuf_c_str(&dbuf)));
551 dbuf_set_size(&dbuf, 0);
558 /*-----------------------------------------------------------------*/
559 /* setDefaultOptions - sets the default options */
560 /*-----------------------------------------------------------------*/
562 setDefaultOptions (void)
564 /* first the options part */
565 options.stack_loc = 0; /* stack pointer initialised to 0 */
566 options.xstack_loc = 0; /* xternal stack starts at 0 */
567 options.code_loc = 0; /* code starts at 0 */
568 options.data_loc = 0; /* JCF: By default let the linker locate data */
569 options.xdata_loc = 0;
570 options.idata_loc = 0; /* MB: No need to limit idata to 0x80-0xFF */
572 options.model = port->general.default_model;
573 options.nostdlib = 0;
574 options.nostdinc = 0;
576 options.shortis8bits = 0;
577 options.std_sdcc = 1; /* enable SDCC language extensions */
578 options.std_c99 = 0; /* default to C89 until more C99 support */
579 options.code_seg = CODE_NAME; /* default to CSEG for generated code */
580 options.const_seg = CONST_NAME; /* default to CONST for generated code */
582 options.stack10bit=0;
584 /* now for the optimizations */
585 /* turn on the everything */
586 optimize.global_cse = 1;
591 optimize.loopInvariant = 1;
592 optimize.loopInduction = 1;
594 /* now for the ports */
595 port->setDefaultOptions ();
598 /*-----------------------------------------------------------------*/
599 /* processFile - determines the type of file from the extension */
600 /*-----------------------------------------------------------------*/
602 processFile (char *s)
606 /* get the file extension */
607 fext = s + strlen (s);
608 while ((fext != s) && *fext != '.')
611 /* now if no '.' then we don't know what the file type is
612 so give a warning and return */
615 werror (W_UNKNOWN_FEXT, s);
619 /* otherwise depending on the file type */
620 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
622 /* source file name : not if we already have a
626 werror (W_TOO_MANY_SRC, s);
630 /* the only source file */
632 if (!(srcFile = fopen (fullSrcFileName, "r")))
634 werror (E_FILE_OPEN_ERR, s);
638 /* copy the file name into the buffer */
639 strncpyz (buffer, s, sizeof(buffer));
641 /* get rid of the "."-extension */
643 /* is there a dot at all? */
644 if (strrchr (buffer, '.') &&
645 /* is the dot in the filename, not in the path? */
646 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
648 *strrchr (buffer, '.') = '\0';
651 /* get rid of any path information
652 for the module name; */
653 fext = buffer + strlen (buffer);
655 /* do this by going backwards till we
656 get '\' or ':' or start of buffer */
657 while (fext != buffer &&
658 *(fext - 1) != DIR_SEPARATOR_CHAR &&
664 /* do this by going backwards till we
665 get '/' or start of buffer */
666 while (fext != buffer &&
667 *(fext - 1) != DIR_SEPARATOR_CHAR)
672 moduleNameBase = Safe_strdup ( fext );
673 moduleName = Safe_strdup ( fext );
675 for (fext = moduleName; *fext; fext++)
676 if (!isalnum ((unsigned char)*fext))
681 /* if the extention is type .rel or .r or .REL or .R
682 additional object file will be passed to the linker */
683 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
684 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
685 strcmp (fext, port->linker.rel_ext) == 0)
687 addSet(&relFilesSet, Safe_strdup(s));
691 /* if .lib or .LIB */
692 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
694 addSet(&libFilesSet, Safe_strdup(s));
698 werror (W_UNKNOWN_FEXT, s);
703 _setModel (int model, const char *sz)
705 if (port->general.supported_models & model)
706 options.model = model;
708 werror (W_UNSUPPORTED_MODEL, sz, port->target);
711 /** Gets the string argument to this option. If the option is '--opt'
712 then for input of '--optxyz' or '--opt xyz' returns xyz.
715 getStringArg(const char *szStart, char **argv, int *pi, int argc)
717 if (argv[*pi][strlen(szStart)])
719 return &argv[*pi][strlen(szStart)];
726 werror (E_ARGUMENT_MISSING, szStart);
727 /* Die here rather than checking for errors later. */
737 /** Gets the integer argument to this option using the same rules as
741 getIntArg(const char *szStart, char **argv, int *pi, int argc)
743 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
747 verifyShortOption(const char *opt)
749 if (strlen(opt) != 2)
751 werror (W_EXCESS_SHORT_OPTIONS, opt);
756 tryHandleUnsupportedOpt(char **argv, int *pi)
758 if (argv[*pi][0] == '-')
760 const char *longOpt = "";
764 if (argv[*pi][1] == '-')
771 shortOpt = argv[*pi][1];
773 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
775 if (unsupportedOptTable[i].shortOpt == shortOpt ||
776 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
777 /* Found an unsupported opt. */
779 SNPRINTF(buffer, sizeof(buffer),
781 longOpt ? longOpt : "",
782 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
783 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
787 /* Didn't find in the table */
792 /* Not an option, so can't be unsupported :) */
798 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
802 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
803 || optionsTable[i].help != NULL;
806 if (optionsTable[i].shortOpt == shortOpt ||
807 (longOpt && optionsTable[i].longOpt &&
808 strcmp(optionsTable[i].longOpt, longOpt) == 0))
811 /* If it is a flag then we can handle it here */
812 if (optionsTable[i].pparameter != NULL)
814 if (optionsTable[i].shortOpt == shortOpt)
816 verifyShortOption(argv[*pi]);
819 (*optionsTable[i].pparameter)++;
823 /* Not a flag. Handled manually later. */
828 /* Didn't find in the table */
833 tryHandleSimpleOpt(char **argv, int *pi)
835 if (argv[*pi][0] == '-')
837 const char *longOpt = "";
840 if (argv[*pi][1] == '-')
847 shortOpt = argv[*pi][1];
850 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
854 else if (port && port->poptions &&
855 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
866 /* Not an option, so can't be handled. */
871 /*-----------------------------------------------------------------*/
872 /* parseCmdLine - parses the command line and sets the options */
873 /*-----------------------------------------------------------------*/
875 parseCmdLine (int argc, char **argv)
879 /* go thru all whole command line */
880 for (i = 1; i < argc; i++)
885 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
890 if (tryHandleSimpleOpt(argv, &i) == TRUE)
896 if (argv[i][0] == '-' && argv[i][1] == '-')
898 if (strcmp (argv[i], OPTION_USE_STDOUT) == 0)
900 if (options.use_stdout == 0)
902 options.use_stdout = 1;
903 dup2(STDOUT_FILENO, STDERR_FILENO);
907 if (strcmp (argv[i], OPTION_HELP) == 0)
913 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
915 options.stack10bit = 0;
919 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
925 if (strcmp (argv[i], OPTION_OUT_FMT_S19) == 0)
931 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
933 _setModel (MODEL_LARGE, argv[i]);
937 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
939 _setModel (MODEL_MEDIUM, argv[i]);
943 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
945 _setModel (MODEL_SMALL, argv[i]);
949 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
951 _setModel (MODEL_FLAT24, argv[i]);
955 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
957 options.dump_rassgn =
963 options.dump_raw = 1;
967 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
969 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
973 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
975 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
979 if (strcmp (argv[i], OPTION_VERSION) == 0)
981 printVersionInfo (stdout);
986 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
988 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
992 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
994 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
998 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
1000 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
1004 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
1006 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
1010 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
1012 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
1016 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
1018 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
1022 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
1024 options.xram_size = getIntArg(OPTION_XRAM_SIZE, argv, &i, argc);
1025 options.xram_size_set = TRUE;
1029 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
1031 options.code_size = getIntArg(OPTION_CODE_SIZE, argv, &i, argc);
1035 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
1037 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
1041 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
1043 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
1047 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1049 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1053 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1055 optimize.global_cse = 0;
1059 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1061 optimize.loopInvariant = 0;
1065 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1067 optimize.label4 = 0;
1071 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1073 optimize.loopInduction = 0;
1077 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1079 optimize.codeSpeed = 1;
1080 optimize.codeSize = 0;
1084 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1086 optimize.codeSpeed = 0;
1087 optimize.codeSize = 1;
1091 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1093 options.lessPedantic = 1;
1094 setErrorLogLevel(ERROR_LEVEL_WARNING);
1098 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1100 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1101 if (w < MAX_ERROR_WARNING)
1103 setWarningDisabled(w);
1108 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1110 options.shortis8bits=1;
1114 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1116 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1120 if (strcmp (argv[i], OPTION_STD_C89) == 0)
1122 options.std_c99 = 0;
1123 options.std_sdcc = 0;
1127 if (strcmp (argv[i], OPTION_STD_C99) == 0)
1129 options.std_c99 = 1;
1130 options.std_sdcc = 0;
1134 if (strcmp (argv[i], OPTION_STD_SDCC89) == 0)
1136 options.std_c99 = 0;
1137 options.std_sdcc = 1;
1141 if (strcmp (argv[i], OPTION_STD_SDCC99) == 0)
1143 options.std_c99 = 1;
1144 options.std_sdcc = 1;
1148 if (strcmp (argv[i], OPTION_CODE_SEG) == 0)
1150 options.code_seg = getStringArg(OPTION_CODE_SEG, argv, &i, argc);
1154 if (strcmp (argv[i], OPTION_CONST_SEG) == 0)
1156 options.const_seg = getStringArg(OPTION_CONST_SEG, argv, &i, argc);
1160 if (!port->parseOption (&argc, argv, &i))
1162 werror (W_UNKNOWN_OPTION, argv[i]);
1171 /* if preceded by '-' then option */
1172 if (*argv[i] == '-')
1177 verifyShortOption(argv[i]);
1180 exit (EXIT_SUCCESS);
1184 /* Used to select the port. But this has already been done. */
1188 /* Used to select the processor in port. But this has
1189 * already been done. */
1193 verifyShortOption(argv[i]);
1195 options.cc_only = 1;
1199 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1203 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1210 /* copy the file name into the buffer */
1211 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1213 /* point to last character */
1214 p = buffer + strlen (buffer) - 1;
1215 if (*p == DIR_SEPARATOR_CHAR)
1217 /* only output path specified */
1218 dstPath = Safe_strdup (buffer);
1219 fullDstFileName = NULL;
1223 fullDstFileName = Safe_strdup (buffer);
1225 /* get rid of the "."-extension */
1227 /* is there a dot at all? */
1228 if (strrchr (buffer, '.') &&
1229 /* is the dot in the filename, not in the path? */
1230 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1231 *strrchr (buffer, '.') = '\0';
1233 dstFileName = Safe_strdup (buffer);
1235 /* strip module name to get path */
1236 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1239 /* path with trailing / */
1241 dstPath = Safe_strdup (buffer);
1248 /* pre-processer options */
1249 if (argv[i][2] == 'p')
1251 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1253 /* linker options */
1254 else if (argv[i][2] == 'l')
1256 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1258 /* assembler options */
1259 else if (argv[i][2] == 'a')
1261 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1265 werror (W_UNKNOWN_OPTION, argv[i]);
1270 verifyShortOption(argv[i]);
1272 printVersionInfo (stdout);
1276 /* preprocessor options */
1280 if (argv[i][2] == 'M')
1281 addSet(&preArgvSet, Safe_strdup("-MM"));
1283 addSet(&preArgvSet, Safe_strdup("-M"));
1288 addSet(&preArgvSet, Safe_strdup("-C"));
1298 char sOpt = argv[i][1];
1301 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1307 werror(E_ARGUMENT_MISSING, argv[i-1]);
1321 SNPRINTF (buffer, sizeof(buffer),
1322 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1323 addSet(&preArgvSet, Safe_strdup(buffer));
1325 addSet(&includeDirsSet, Safe_strdup(rest));
1326 addSet(&userIncDirsSet, Safe_strdup(rest));
1332 if (!port->parseOption (&argc, argv, &i))
1333 werror (W_UNKNOWN_OPTION, argv[i]);
1338 if (!port->parseOption (&argc, argv, &i))
1340 /* no option must be a filename */
1343 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1347 processFile (argv[i]);
1352 /* some sanity checks in c1 mode */
1357 if (fullSrcFileName)
1360 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1362 fullSrcFileName = NULL;
1363 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1365 werror (W_NO_FILE_ARG_IN_C1, s);
1367 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1369 werror (W_NO_FILE_ARG_IN_C1, s);
1371 deleteSet(&relFilesSet);
1372 deleteSet(&libFilesSet);
1374 if (options.cc_only || noAssemble || preProcOnly)
1376 werror (W_ILLEGAL_OPT_COMBINATION);
1378 options.cc_only = noAssemble = preProcOnly = 0;
1381 werror (E_NEED_OPT_O_IN_C1);
1385 /* if no dstFileName given with -o, we've to find one: */
1390 /* use the modulename from the C-source */
1391 if (fullSrcFileName)
1393 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1395 dstFileName = Safe_alloc (bufSize);
1396 strncpyz (dstFileName, dstPath, bufSize);
1397 strncatz (dstFileName, moduleNameBase, bufSize);
1399 /* use the modulename from the first object file */
1400 else if ((s = peekSet(relFilesSet)) != NULL)
1405 strncpyz (buffer, s, sizeof(buffer));
1406 /* remove extension (it must be .rel) */
1407 *strrchr (buffer, '.') = '\0';
1409 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1416 objectName = buffer;
1418 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1419 dstFileName = Safe_alloc (bufSize);
1420 strncpyz (dstFileName, dstPath, bufSize);
1421 strncatz (dstFileName, objectName, bufSize);
1423 /* else no module given: help text is displayed */
1426 /* set int, long and float reentrancy based on stack-auto */
1427 if (options.stackAuto)
1429 options.intlong_rent++;
1430 options.float_rent++;
1433 /* mcs51 has an assembly coded float library that's always reentrant */
1434 if (TARGET_IS_MCS51)
1436 options.float_rent++;
1439 /* set up external stack location if not explicitly specified */
1440 if (!options.xstack_loc)
1441 options.xstack_loc = options.xdata_loc;
1443 /* if debug option is set then open the cdbFile */
1444 if (options.debug && fullSrcFileName)
1446 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1447 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1448 if(debugFile->openFile(scratchFileName))
1449 debugFile->writeModule(moduleName);
1451 werror (E_FILE_OPEN_ERR, scratchFileName);
1453 MSVC_style(options.vc_err_style);
1458 /*-----------------------------------------------------------------*/
1459 /* linkEdit : - calls the linkage editor with options */
1460 /*-----------------------------------------------------------------*/
1462 linkEdit (char **envp)
1468 char linkerScriptFileName[PATH_MAX];
1470 linkerScriptFileName[0] = 0;
1472 if(port->linker.needLinkerScript)
1476 switch (options.out_fmt)
1479 out_fmt = 'i'; /* Intel hex */
1482 out_fmt = 's'; /* Motorola S19 */
1485 out_fmt = 't'; /* Elf */
1491 /* first we need to create the <filename>.lnk file */
1492 SNPRINTF (linkerScriptFileName, sizeof(scratchFileName),
1493 "%s.lnk", dstFileName);
1494 if (!(lnkfile = fopen (linkerScriptFileName, "w")))
1496 werror (E_FILE_OPEN_ERR, linkerScriptFileName);
1500 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1502 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1503 out_fmt, dstFileName);
1505 else /*For all the other ports. Including pics???*/
1507 fprintf (lnkfile, "-myux%c\n", out_fmt);
1508 if(!options.no_pack_iram)
1509 fprintf (lnkfile, "-Y\n");
1512 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1514 /* if iram size specified */
1515 if (options.iram_size)
1516 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1518 /* if stack size specified*/
1519 if(options.stack_size)
1520 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1522 /* if xram size specified */
1523 if (options.xram_size_set)
1524 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1526 /* if code size specified */
1527 if (options.code_size)
1528 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1531 fprintf (lnkfile, "-z\n");
1534 #define WRITE_SEG_LOC(N, L) \
1535 segName = Safe_strdup(N); \
1536 c = strtok(segName, " \t"); \
1537 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1538 if (segName) { Safe_free(segName); }
1540 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1543 /* code segment start */
1544 WRITE_SEG_LOC (HOME_NAME, options.code_loc);
1546 /* data segment start. If zero, the linker chooses
1547 the best place for data */
1548 if (options.data_loc)
1550 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1553 /* xdata segment start. If zero, the linker chooses
1554 the best place for xdata */
1555 if (options.xdata_loc)
1557 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1563 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1566 /* bit segment start */
1567 WRITE_SEG_LOC (BIT_NAME, 0);
1570 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1573 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1576 else /*For the z80, gbz80*/
1578 WRITE_SEG_LOC ("_CODE", options.code_loc);
1579 WRITE_SEG_LOC ("_DATA", options.data_loc);
1582 /* If the port has any special linker area declarations, get 'em */
1583 if (port->extraAreas.genExtraAreaLinkOptions)
1585 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1588 /* add the extra linker options */
1589 fputStrSet(lnkfile, linkOptionsSet);
1591 /* command line defined library paths if specified */
1592 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1593 fprintf (lnkfile, "-k %s\n", s);
1595 /* standard library path */
1596 if (!options.nostdlib)
1598 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1600 switch (options.model)
1603 if (options.stackAuto)
1604 c = "small-stack-auto";
1609 if (options.stackAuto)
1610 c = "medium-stack-auto";
1615 if (options.stackAuto)
1616 c = "large-stack-auto";
1622 if (TARGET_IS_DS390)
1626 else if (TARGET_IS_DS400)
1633 "Add support for your FLAT24 target in %s @ line %d\n",
1634 __FILE__, __LINE__);
1642 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1647 else /*for the z80, gbz80*/
1651 else if (TARGET_IS_Z80)
1656 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1657 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1660 /* command line defined library files if specified */
1661 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1662 fprintf (lnkfile, "-l %s\n", s);
1664 /* standard library files */
1665 if (!options.nostdlib)
1667 #if !OPT_DISABLE_DS390
1668 if (options.model == MODEL_FLAT24)
1670 if (TARGET_IS_DS390)
1672 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1674 else if (TARGET_IS_DS400)
1676 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1681 "Add support for your FLAT24 target in %s @ line %d\n",
1682 __FILE__, __LINE__);
1688 #if !OPT_DISABLE_XA51
1690 if (options.model == MODEL_PAGE0)
1692 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1696 if (TARGET_IS_MCS51)
1698 fprintf (lnkfile, "-l mcs51\n");
1700 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1701 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1702 { /*Why the z80 port is not using the standard libraries?*/
1703 fprintf (lnkfile, "-l %s\n", STD_LIB);
1704 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1705 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1706 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1708 else if (TARGET_IS_HC08)
1710 fprintf (lnkfile, "-l hc08\n");
1712 else if (TARGET_IS_Z80)
1714 fprintf (lnkfile, "-l z80\n");
1716 else if (TARGET_IS_GBZ80)
1718 fprintf (lnkfile, "-l gbz80\n");
1722 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1723 It is very important for this file to be first on the linking proccess
1724 so the areas are set in the correct order, expecially _GSINIT*/
1725 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1726 !options.no_std_crt0) /*For the z80, gbz80*/
1728 char crt0path[PATH_MAX];
1732 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1733 tempSet = appendStrSet(tempSet, NULL, c);
1734 mergeSets(&tempSet, libPathsSet);
1736 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1738 sprintf (crt0path, "%s%scrt0.o",
1739 s, DIR_SEPARATOR_STRING);
1741 crt0fp=fopen(crt0path, "r");
1742 if(crt0fp!=NULL)/*Found it!*/
1747 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1748 windows paths, so convert them to the CYGWIN format*/
1749 char posix_path[PATH_MAX];
1750 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1751 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1752 strcpy(crt0path, posix_path);
1755 fprintf (lnkfile, "%s\n", crt0path);
1759 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1762 /* put in the object files */
1763 if (fullSrcFileName)
1764 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1766 fputStrSet(lnkfile, relFilesSet);
1768 fprintf (lnkfile, "\n-e\n");
1770 } /* if(port->linker.needLinkerScript) */
1772 if (options.verbose)
1773 printf ("sdcc: Calling linker...\n");
1775 /* build linker output filename */
1777 /* -o option overrides default name? */
1778 if (fullDstFileName)
1780 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1784 /* the linked file gets the name of the first modul */
1785 if (fullSrcFileName)
1787 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1791 s = peekSet(relFilesSet);
1795 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1796 /* strip ".rel" extension */
1797 *strrchr (scratchFileName, '.') = '\0';
1799 strncatz (scratchFileName,
1800 options.out_fmt ? ".S19" : ".ihx",
1801 sizeof(scratchFileName));
1804 if (port->linker.cmd)
1806 char buffer2[PATH_MAX];
1807 char buffer3[PATH_MAX];
1808 set *tempSet=NULL, *libSet=NULL;
1810 strcpy(buffer3, linkerScriptFileName);
1811 if(/*TARGET_IS_PIC16 ||*/ TARGET_IS_PIC) {
1813 /* use $l to set the linker include directories */
1814 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1815 mergeSets(&linkOptionsSet, tempSet);
1817 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1818 mergeSets(&linkOptionsSet, tempSet);
1820 /* use $3 for libraries from command line --> libSet */
1821 mergeSets(&libSet, libFilesSet);
1823 tempSet = appendStrSet(relFilesSet, "", "");
1824 mergeSets(&libSet, tempSet);
1825 // libSet = reverseSet(libSet);
1827 if(fullSrcFileName) {
1828 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1829 /* if it didn't work, revert to old behaviour */
1830 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1831 strcat(buffer3, port->linker.rel_ext);
1833 } else strcpy(buffer3, "");
1836 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1838 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1842 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1845 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1847 system_ret = my_system (buffer);
1850 #define STRCMP stricmp
1852 #define STRCMP strcmp
1855 /* TODO: most linker don't have a -o parameter */
1856 /* -o option overrides default name? */
1857 if (fullDstFileName)
1860 /* the linked file gets the name of the first modul */
1861 if (fullSrcFileName)
1863 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1864 p = strlen (scratchFileName) + scratchFileName;
1868 s = peekSet(relFilesSet);
1872 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1873 /* strip ".rel" extension */
1874 p = strrchr (scratchFileName, '.');
1880 strncatz (scratchFileName,
1881 options.out_fmt ? ".S19" : ".ihx",
1882 sizeof(scratchFileName));
1883 if (STRCMP (fullDstFileName, scratchFileName))
1884 remove (fullDstFileName);
1885 rename (scratchFileName, fullDstFileName);
1887 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1888 q = strrchr (buffer, '.');
1891 /* no extension: append new extensions */
1892 q = strlen (buffer) + buffer;
1896 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1898 strncatz(buffer, ".map", sizeof(buffer));
1899 if (STRCMP (scratchFileName, buffer))
1901 rename (scratchFileName, buffer);
1903 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1905 strncatz(buffer, ".mem", sizeof(buffer));
1906 if (STRCMP (scratchFileName, buffer))
1908 rename (scratchFileName, buffer);
1912 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1914 strncatz(buffer, ".cdb", sizeof(buffer));
1915 if (STRCMP (scratchFileName, buffer))
1917 rename (scratchFileName, buffer);
1918 /* and the OMF file without extension: */
1921 if (STRCMP (scratchFileName, buffer))
1923 rename (scratchFileName, buffer);
1932 /*-----------------------------------------------------------------*/
1933 /* assemble - spawns the assembler with arguments */
1934 /*-----------------------------------------------------------------*/
1936 assemble (char **envp)
1938 /* build assembler output filename */
1940 /* -o option overrides default name? */
1941 if (options.cc_only && fullDstFileName) {
1942 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1944 /* the assembled file gets the name of the first modul */
1945 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1946 strncatz (scratchFileName, port->linker.rel_ext,
1947 sizeof(scratchFileName));
1950 if (port->assembler.do_assemble) {
1951 port->assembler.do_assemble(asmOptionsSet);
1953 } else if (port->assembler.cmd) {
1954 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1955 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1958 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1961 if (my_system (buffer)) {
1962 /* either system() or the assembler itself has reported an error
1963 perror ("Cannot exec assembler");
1967 /* TODO: most assembler don't have a -o parameter */
1968 /* -o option overrides default name? */
1969 if (options.cc_only && fullDstFileName) {
1970 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1971 strncatz (scratchFileName,
1972 port->linker.rel_ext,
1973 sizeof(scratchFileName));
1974 if (strcmp (scratchFileName, fullDstFileName))
1975 remove (fullDstFileName);
1976 rename (scratchFileName, fullDstFileName);
1980 /*-----------------------------------------------------------------*/
1981 /* preProcess - spawns the preprocessor with arguments */
1982 /*-----------------------------------------------------------------*/
1984 preProcess (char **envp)
1993 set *inclList = NULL;
1995 if (NULL != port->linker.rel_ext)
1997 #define OBJ_EXT_STR "-obj-ext="
1998 #define OBJ_EXT_LEN ((sizeof OBJ_EXT_STR) - 1)
1999 char *buf = Safe_alloc(strlen(port->linker.rel_ext) + (OBJ_EXT_LEN + 1));
2000 strcpy(buf, OBJ_EXT_STR);
2001 strcpy(&buf[OBJ_EXT_LEN], port->linker.rel_ext);
2002 addSet(&preArgvSet, buf);
2005 /* if using external stack define the macro */
2006 if (options.useXstack)
2007 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
2009 /* set the macro for stack autos */
2010 if (options.stackAuto)
2011 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
2013 /* set the macro for stack autos */
2014 if (options.stack10bit)
2015 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
2017 /* set the macro for no overlay */
2018 if (options.noOverlay)
2019 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
2021 /* set the macro for large model */
2022 switch (options.model)
2025 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
2028 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
2031 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
2034 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
2037 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
2040 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
2043 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
2047 /* add SDCC version number */
2050 SNPRINTF(buf, sizeof(buf), "-DSDCC=%d%d%d",
2051 SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2052 addSet(&preArgvSet, Safe_strdup(buf));
2055 /* add port (processor information to processor */
2056 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
2057 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
2059 if (port && port->processor && TARGET_IS_PIC) {
2061 SNPRINTF(&proc[0], 512, "-DSDCC_PROCESSOR=\"%s\"", port->processor);
2062 addSet(&preArgvSet, Safe_strdup(proc));
2065 /* standard include path */
2066 if (!options.nostdinc) {
2067 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
2068 mergeSets(&preArgvSet, inclList);
2071 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
2072 Safe_free((void *)s);
2073 if (inclList != NULL)
2074 deleteSet(&inclList);
2076 if (preProcOnly && fullDstFileName)
2078 /* -E and -o given */
2079 setMainValue ("cppoutfilename", fullDstFileName);
2083 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2084 setMainValue ("cppoutfilename", NULL);
2087 if (options.verbose)
2088 printf ("sdcc: Calling preprocessor...\n");
2089 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2092 if (my_system (buffer)) {
2099 yyin = my_popen (buffer);
2101 perror ("Preproc file not found");
2104 addSetHead (&pipeSet, yyin);
2112 setBinPaths(const char *argv0)
2120 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2121 * 2. - path(argv[0])
2125 /* do it in reverse mode, so that addSetHead() can be used
2126 instead of slower addSet() */
2128 if ((p = getBinPath(argv0)) != NULL)
2129 addSetHead(&binPathSet, Safe_strdup(p));
2131 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2132 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2133 addSetHead(&binPathSet, Safe_strdup(buf));
2137 /* Set system include path */
2139 setIncludePath(void)
2148 * 1. - $SDCC_INCLUDE/target
2149 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2150 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2151 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2152 * 5. - $SDCC_INCLUDE
2153 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2154 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2155 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2158 if (options.nostdinc)
2161 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2162 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2163 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2164 mergeSets(&includeDirsSet, tempSet);
2166 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2168 addSetHead(&includeDirsSet, p);
2169 p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2173 strcat(p2, DIR_SEPARATOR_STRING);
2174 strcat(p2, port->target);
2175 addSetHead(&includeDirsSet, p2);
2180 /* Set system lib path */
2190 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2191 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2192 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2195 if (options.nostdlib)
2198 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2200 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2201 addSetHead(&libDirsSet, p);
2206 setDataPaths(const char *argv0)
2214 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2215 * 2. - path(argv[0])/BIN2DATA_DIR
2216 * 3. - DATADIR (only on *nix)
2219 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2220 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2221 addSet(&dataDirsSet, Safe_strdup(buf));
2224 if ((p = getBinPath(argv0)) != NULL) {
2225 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2226 addSet(&dataDirsSet, Safe_strdup(buf));
2230 if (peekSet(dataDirsSet) == NULL) {
2231 /* this should never happen... */
2232 wassertl(0, "Can't get binary path");
2235 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2245 populateMainValues (_baseValues);
2246 setMainValue ("port", port->target);
2247 setMainValue ("objext", port->linker.rel_ext);
2248 setMainValue ("asmext", port->assembler.file_ext);
2250 setMainValue ("dstfilename", dstFileName);
2251 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2253 if (options.cc_only && fullDstFileName)
2254 /* compile + assemble and -o given: -o specifies name of object file */
2256 setMainValue ("objdstfilename", fullDstFileName);
2260 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2262 if (fullDstFileName)
2263 /* if we're linking, -o gives the final file name */
2265 setMainValue ("linkdstfilename", fullDstFileName);
2269 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2274 static void doPrintSearchDirs(void)
2276 printf("programs:\n");
2277 fputStrSet(stdout, binPathSet);
2279 printf("datadir:\n");
2280 fputStrSet(stdout, dataDirsSet);
2282 printf("includedir:\n");
2283 fputStrSet(stdout, includeDirsSet);
2285 printf("libdir:\n");
2286 fputStrSet(stdout, libDirsSet);
2287 fputStrSet(stdout, libPathsSet);
2292 sig_handler (int signal)
2299 sig_string = "SIGABRT";
2302 sig_string = "SIGTERM";
2305 sig_string = "SIGINT";
2308 sig_string = "SIGSEGV";
2311 sig_string = "Unknown?";
2314 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2320 * initialises and calls the parser
2324 main (int argc, char **argv, char **envp)
2326 /* turn all optimizations off by default */
2327 memset (&optimize, 0, sizeof (struct optimize));
2330 fprintf (stderr, "Build error: no ports are enabled.\n");
2334 /* install atexit handler */
2335 atexit(rm_tmpfiles);
2337 /* install signal handler;
2338 it's only purpose is to call exit() to remove temp files */
2339 if (!getenv("SDCC_LEAVE_SIGNALS"))
2341 signal (SIGABRT, sig_handler);
2342 signal (SIGTERM, sig_handler);
2343 signal (SIGINT , sig_handler);
2344 signal (SIGSEGV, sig_handler);
2347 /* Before parsing the command line options, do a
2348 * search for the port and processor and initialize
2349 * them if they're found. (We can't gurantee that these
2350 * will be the first options specified).
2353 _findPort (argc, argv);
2356 if (strcmp(port->target, "mcs51") == 0) {
2357 printf("DS390 jammed in A\n");
2363 _findProcessor (argc, argv);
2365 /* Initalise the port. */
2369 setDefaultOptions ();
2372 options.model = MODEL_SMALL;
2373 options.stack10bit=0;
2377 parseCmdLine (argc, argv);
2379 if (options.verbose && NULL != port->processor)
2380 printf("Processor: %s\n", port->processor);
2384 setBinPaths(argv[0]);
2385 setDataPaths(argv[0]);
2390 if(options.printSearchDirs)
2391 doPrintSearchDirs();
2393 /* if no input then printUsage & exit */
2394 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL)
2396 if (options.printSearchDirs)
2397 exit (EXIT_SUCCESS);
2399 exit (EXIT_FAILURE);
2402 /* initMem() is expensive, but
2403 initMem() must called before port->finaliseOptions ().
2404 And the z80 port needs port->finaliseOptions(),
2405 even if we're only linking. */
2407 port->finaliseOptions ();
2409 if (fullSrcFileName || options.c1mode)
2419 if (options.verbose)
2420 printf ("sdcc: Generating code...\n");
2426 deleteSetItem(&pipeSet, yyin);
2432 if (port->general.do_glue != NULL)
2433 (*port->general.do_glue)();
2436 /* this shouldn't happen */
2438 /* in case of NDEBUG */
2446 if (!options.c1mode && !noAssemble)
2448 if (options.verbose)
2449 printf ("sdcc: Calling assembler...\n");
2455 if (options.debug && debugFile)
2456 debugFile->closeFile();
2458 if (!options.cc_only &&
2462 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2464 if (options.verbose)
2465 printf ("sdcc: Calling linker...\n");
2467 if (port->linker.do_link)
2468 port->linker.do_link ();