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 Stack 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_Z80_LIKE)
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_Z80_LIKE)) /*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_Z80_LIKE)) /*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);
1560 /* pdata/xstack segment start. If zero, the linker
1561 chooses the best place for them */
1562 if (options.xstack_loc)
1564 WRITE_SEG_LOC (PDATA_NAME, options.xstack_loc);
1570 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1573 /* bit segment start */
1574 WRITE_SEG_LOC (BIT_NAME, 0);
1577 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1580 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1583 else /*For the z80, gbz80*/
1585 WRITE_SEG_LOC ("_CODE", options.code_loc);
1586 WRITE_SEG_LOC ("_DATA", options.data_loc);
1589 /* If the port has any special linker area declarations, get 'em */
1590 if (port->extraAreas.genExtraAreaLinkOptions)
1592 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1595 /* add the extra linker options */
1596 fputStrSet(lnkfile, linkOptionsSet);
1598 /* command line defined library paths if specified */
1599 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1600 fprintf (lnkfile, "-k %s\n", s);
1602 /* standard library path */
1603 if (!options.nostdlib)
1605 if (!(TARGET_Z80_LIKE || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1607 switch (options.model)
1610 if (options.stackAuto)
1611 c = "small-stack-auto";
1616 if (options.stackAuto)
1617 c = "medium-stack-auto";
1622 if (options.stackAuto)
1623 c = "large-stack-auto";
1629 if (TARGET_IS_DS390)
1633 else if (TARGET_IS_DS400)
1640 "Add support for your FLAT24 target in %s @ line %d\n",
1641 __FILE__, __LINE__);
1649 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1654 else /*for the z80, gbz80*/
1658 else if (TARGET_IS_Z80)
1663 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1664 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1667 /* command line defined library files if specified */
1668 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1669 fprintf (lnkfile, "-l %s\n", s);
1671 /* standard library files */
1672 if (!options.nostdlib)
1674 #if !OPT_DISABLE_DS390
1675 if (options.model == MODEL_FLAT24)
1677 if (TARGET_IS_DS390)
1679 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1681 else if (TARGET_IS_DS400)
1683 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1688 "Add support for your FLAT24 target in %s @ line %d\n",
1689 __FILE__, __LINE__);
1695 #if !OPT_DISABLE_XA51
1697 if (options.model == MODEL_PAGE0)
1699 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1703 if (TARGET_IS_MCS51)
1705 fprintf (lnkfile, "-l mcs51\n");
1707 if (!(TARGET_Z80_LIKE || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1708 { /*Why the z80 port is not using the standard libraries?*/
1709 fprintf (lnkfile, "-l %s\n", STD_LIB);
1710 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1711 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1712 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1714 else if (TARGET_IS_HC08)
1716 fprintf (lnkfile, "-l hc08\n");
1718 else if (TARGET_IS_Z80)
1720 fprintf (lnkfile, "-l z80\n");
1722 else if (TARGET_IS_GBZ80)
1724 fprintf (lnkfile, "-l gbz80\n");
1728 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1729 It is very important for this file to be first on the linking proccess
1730 so the areas are set in the correct order, expecially _GSINIT*/
1731 if ((TARGET_Z80_LIKE) && !options.no_std_crt0) /*For the z80, gbz80*/
1733 char crt0path[PATH_MAX];
1737 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1738 tempSet = appendStrSet(tempSet, NULL, c);
1739 mergeSets(&tempSet, libPathsSet);
1741 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1743 sprintf (crt0path, "%s%scrt0.o",
1744 s, DIR_SEPARATOR_STRING);
1746 crt0fp=fopen(crt0path, "r");
1747 if(crt0fp!=NULL)/*Found it!*/
1752 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1753 windows paths, so convert them to the CYGWIN format*/
1754 char posix_path[PATH_MAX];
1755 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1756 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1757 strcpy(crt0path, posix_path);
1760 fprintf (lnkfile, "%s\n", crt0path);
1764 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1767 /* put in the object files */
1768 if (fullSrcFileName)
1769 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1771 fputStrSet(lnkfile, relFilesSet);
1773 fprintf (lnkfile, "\n-e\n");
1775 } /* if(port->linker.needLinkerScript) */
1777 if (options.verbose)
1778 printf ("sdcc: Calling linker...\n");
1780 /* build linker output filename */
1782 /* -o option overrides default name? */
1783 if (fullDstFileName)
1785 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1789 /* the linked file gets the name of the first modul */
1790 if (fullSrcFileName)
1792 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1796 s = peekSet(relFilesSet);
1800 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1801 /* strip ".rel" extension */
1802 *strrchr (scratchFileName, '.') = '\0';
1804 strncatz (scratchFileName,
1805 options.out_fmt ? ".S19" : ".ihx",
1806 sizeof(scratchFileName));
1809 if (port->linker.cmd)
1811 char buffer2[PATH_MAX];
1812 char buffer3[PATH_MAX];
1813 set *tempSet=NULL, *libSet=NULL;
1815 strcpy(buffer3, linkerScriptFileName);
1816 if(/*TARGET_IS_PIC16 ||*/ TARGET_IS_PIC) {
1818 /* use $l to set the linker include directories */
1819 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1820 mergeSets(&linkOptionsSet, tempSet);
1822 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1823 mergeSets(&linkOptionsSet, tempSet);
1825 /* use $3 for libraries from command line --> libSet */
1826 mergeSets(&libSet, libFilesSet);
1828 tempSet = appendStrSet(relFilesSet, "", "");
1829 mergeSets(&libSet, tempSet);
1830 // libSet = reverseSet(libSet);
1832 if(fullSrcFileName) {
1833 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1834 /* if it didn't work, revert to old behaviour */
1835 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1836 strcat(buffer3, port->linker.rel_ext);
1838 } else strcpy(buffer3, "");
1841 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1843 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1847 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1850 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1852 system_ret = my_system (buffer);
1855 #define STRCMP stricmp
1857 #define STRCMP strcmp
1860 /* TODO: most linker don't have a -o parameter */
1861 /* -o option overrides default name? */
1862 if (fullDstFileName)
1865 /* the linked file gets the name of the first modul */
1866 if (fullSrcFileName)
1868 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1869 p = strlen (scratchFileName) + scratchFileName;
1873 s = peekSet(relFilesSet);
1877 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1878 /* strip ".rel" extension */
1879 p = strrchr (scratchFileName, '.');
1885 strncatz (scratchFileName,
1886 options.out_fmt ? ".S19" : ".ihx",
1887 sizeof(scratchFileName));
1888 if (STRCMP (fullDstFileName, scratchFileName))
1889 remove (fullDstFileName);
1890 rename (scratchFileName, fullDstFileName);
1892 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1893 q = strrchr (buffer, '.');
1896 /* no extension: append new extensions */
1897 q = strlen (buffer) + buffer;
1901 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1903 strncatz(buffer, ".map", sizeof(buffer));
1904 if (STRCMP (scratchFileName, buffer))
1906 rename (scratchFileName, buffer);
1908 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1910 strncatz(buffer, ".mem", sizeof(buffer));
1911 if (STRCMP (scratchFileName, buffer))
1913 rename (scratchFileName, buffer);
1917 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1919 strncatz(buffer, ".cdb", sizeof(buffer));
1920 if (STRCMP (scratchFileName, buffer))
1922 rename (scratchFileName, buffer);
1923 /* and the OMF file without extension: */
1926 if (STRCMP (scratchFileName, buffer))
1928 rename (scratchFileName, buffer);
1937 /*-----------------------------------------------------------------*/
1938 /* assemble - spawns the assembler with arguments */
1939 /*-----------------------------------------------------------------*/
1941 assemble (char **envp)
1943 /* build assembler output filename */
1945 /* -o option overrides default name? */
1946 if (options.cc_only && fullDstFileName) {
1947 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1949 /* the assembled file gets the name of the first modul */
1950 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1951 strncatz (scratchFileName, port->linker.rel_ext,
1952 sizeof(scratchFileName));
1955 if (port->assembler.do_assemble) {
1956 port->assembler.do_assemble(asmOptionsSet);
1958 } else if (port->assembler.cmd) {
1959 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1960 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1963 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1966 if (my_system (buffer)) {
1967 /* either system() or the assembler itself has reported an error
1968 perror ("Cannot exec assembler");
1972 /* TODO: most assembler don't have a -o parameter */
1973 /* -o option overrides default name? */
1974 if (options.cc_only && fullDstFileName) {
1975 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1976 strncatz (scratchFileName,
1977 port->linker.rel_ext,
1978 sizeof(scratchFileName));
1979 if (strcmp (scratchFileName, fullDstFileName))
1980 remove (fullDstFileName);
1981 rename (scratchFileName, fullDstFileName);
1985 /*-----------------------------------------------------------------*/
1986 /* preProcess - spawns the preprocessor with arguments */
1987 /*-----------------------------------------------------------------*/
1989 preProcess (char **envp)
1998 set *inclList = NULL;
2000 if (NULL != port->linker.rel_ext)
2002 #define OBJ_EXT_STR "-obj-ext="
2003 #define OBJ_EXT_LEN ((sizeof OBJ_EXT_STR) - 1)
2004 char *buf = Safe_alloc(strlen(port->linker.rel_ext) + (OBJ_EXT_LEN + 1));
2005 strcpy(buf, OBJ_EXT_STR);
2006 strcpy(&buf[OBJ_EXT_LEN], port->linker.rel_ext);
2007 addSet(&preArgvSet, buf);
2010 /* if using external stack define the macro */
2011 if (options.useXstack)
2012 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
2014 /* set the macro for stack autos */
2015 if (options.stackAuto)
2016 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
2018 /* set the macro for stack autos */
2019 if (options.stack10bit)
2020 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
2022 /* set the macro for no overlay */
2023 if (options.noOverlay)
2024 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
2026 /* set the macro for large model */
2027 switch (options.model)
2030 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
2033 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
2036 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
2039 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
2042 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
2045 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
2048 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
2052 /* add SDCC version number */
2055 SNPRINTF(buf, sizeof(buf), "-DSDCC=%d%d%d",
2056 SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2057 addSet(&preArgvSet, Safe_strdup(buf));
2060 /* add port (processor information to processor */
2061 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
2062 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
2064 if (port && port->processor && TARGET_IS_PIC) {
2066 SNPRINTF(&proc[0], 512, "-DSDCC_PROCESSOR=\"%s\"", port->processor);
2067 addSet(&preArgvSet, Safe_strdup(proc));
2070 /* standard include path */
2071 if (!options.nostdinc) {
2072 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
2073 mergeSets(&preArgvSet, inclList);
2076 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
2077 Safe_free((void *)s);
2078 if (inclList != NULL)
2079 deleteSet(&inclList);
2081 if (preProcOnly && fullDstFileName)
2083 /* -E and -o given */
2084 setMainValue ("cppoutfilename", fullDstFileName);
2088 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2089 setMainValue ("cppoutfilename", NULL);
2092 if (options.verbose)
2093 printf ("sdcc: Calling preprocessor...\n");
2094 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2097 if (my_system (buffer)) {
2104 yyin = my_popen (buffer);
2106 perror ("Preproc file not found");
2109 addSetHead (&pipeSet, yyin);
2117 setBinPaths(const char *argv0)
2125 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2126 * 2. - path(argv[0])
2130 /* do it in reverse mode, so that addSetHead() can be used
2131 instead of slower addSet() */
2133 if ((p = getBinPath(argv0)) != NULL)
2134 addSetHead(&binPathSet, Safe_strdup(p));
2136 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2137 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2138 addSetHead(&binPathSet, Safe_strdup(buf));
2142 /* Set system include path */
2144 setIncludePath(void)
2153 * 1. - $SDCC_INCLUDE/target
2154 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2155 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2156 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2157 * 5. - $SDCC_INCLUDE
2158 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2159 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2160 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2163 if (options.nostdinc)
2166 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2167 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2168 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2169 mergeSets(&includeDirsSet, tempSet);
2171 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2173 addSetHead(&includeDirsSet, p);
2174 p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2178 strcat(p2, DIR_SEPARATOR_STRING);
2179 strcat(p2, port->target);
2180 addSetHead(&includeDirsSet, p2);
2185 /* Set system lib path */
2195 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2196 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2197 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2200 if (options.nostdlib)
2203 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2205 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2206 addSetHead(&libDirsSet, p);
2211 setDataPaths(const char *argv0)
2219 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2220 * 2. - path(argv[0])/BIN2DATA_DIR
2221 * 3. - DATADIR (only on *nix)
2224 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2225 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2226 addSet(&dataDirsSet, Safe_strdup(buf));
2229 if ((p = getBinPath(argv0)) != NULL) {
2230 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2231 addSet(&dataDirsSet, Safe_strdup(buf));
2235 if (peekSet(dataDirsSet) == NULL) {
2236 /* this should never happen... */
2237 wassertl(0, "Can't get binary path");
2240 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2250 populateMainValues (_baseValues);
2251 setMainValue ("port", port->target);
2252 setMainValue ("objext", port->linker.rel_ext);
2253 setMainValue ("asmext", port->assembler.file_ext);
2255 setMainValue ("dstfilename", dstFileName);
2256 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2258 if (options.cc_only && fullDstFileName)
2259 /* compile + assemble and -o given: -o specifies name of object file */
2261 setMainValue ("objdstfilename", fullDstFileName);
2265 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2267 if (fullDstFileName)
2268 /* if we're linking, -o gives the final file name */
2270 setMainValue ("linkdstfilename", fullDstFileName);
2274 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2279 static void doPrintSearchDirs(void)
2281 printf("programs:\n");
2282 fputStrSet(stdout, binPathSet);
2284 printf("datadir:\n");
2285 fputStrSet(stdout, dataDirsSet);
2287 printf("includedir:\n");
2288 fputStrSet(stdout, includeDirsSet);
2290 printf("libdir:\n");
2291 fputStrSet(stdout, libDirsSet);
2292 fputStrSet(stdout, libPathsSet);
2297 sig_handler (int signal)
2304 sig_string = "SIGABRT";
2307 sig_string = "SIGTERM";
2310 sig_string = "SIGINT";
2313 sig_string = "SIGSEGV";
2316 sig_string = "Unknown?";
2319 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2325 * initialises and calls the parser
2329 main (int argc, char **argv, char **envp)
2331 /* turn all optimizations off by default */
2332 memset (&optimize, 0, sizeof (struct optimize));
2335 fprintf (stderr, "Build error: no ports are enabled.\n");
2339 /* install atexit handler */
2340 atexit(rm_tmpfiles);
2342 /* install signal handler;
2343 it's only purpose is to call exit() to remove temp files */
2344 if (!getenv("SDCC_LEAVE_SIGNALS"))
2346 signal (SIGABRT, sig_handler);
2347 signal (SIGTERM, sig_handler);
2348 signal (SIGINT , sig_handler);
2349 signal (SIGSEGV, sig_handler);
2352 /* Before parsing the command line options, do a
2353 * search for the port and processor and initialize
2354 * them if they're found. (We can't gurantee that these
2355 * will be the first options specified).
2358 _findPort (argc, argv);
2361 if (strcmp(port->target, "mcs51") == 0) {
2362 printf("DS390 jammed in A\n");
2368 _findProcessor (argc, argv);
2370 /* Initalise the port. */
2374 setDefaultOptions ();
2377 options.model = MODEL_SMALL;
2378 options.stack10bit=0;
2382 parseCmdLine (argc, argv);
2384 if (options.verbose && NULL != port->processor)
2385 printf("Processor: %s\n", port->processor);
2389 setBinPaths(argv[0]);
2390 setDataPaths(argv[0]);
2395 if(options.printSearchDirs)
2396 doPrintSearchDirs();
2398 /* if no input then printUsage & exit */
2399 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL)
2401 if (options.printSearchDirs)
2402 exit (EXIT_SUCCESS);
2404 exit (EXIT_FAILURE);
2407 /* initMem() is expensive, but
2408 initMem() must called before port->finaliseOptions ().
2409 And the z80 port needs port->finaliseOptions(),
2410 even if we're only linking. */
2412 port->finaliseOptions ();
2414 if (fullSrcFileName || options.c1mode)
2424 if (options.verbose)
2425 printf ("sdcc: Generating code...\n");
2431 deleteSetItem(&pipeSet, yyin);
2437 if (port->general.do_glue != NULL)
2438 (*port->general.do_glue)();
2441 /* this shouldn't happen */
2443 /* in case of NDEBUG */
2451 if (!options.c1mode && !noAssemble)
2453 if (options.verbose)
2454 printf ("sdcc: Calling assembler...\n");
2460 if (options.debug && debugFile)
2461 debugFile->closeFile();
2463 if (!options.cc_only &&
2467 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2469 if (options.verbose)
2470 printf ("sdcc: Calling linker...\n");
2472 if (port->linker.do_link)
2473 port->linker.do_link ();