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
266 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
267 { 0, OPTION_PACK_IRAM, NULL,"MCS51/DS390 - Tells the linker to pack variables in internal ram (default)"},
268 { 0, OPTION_NO_PACK_IRAM, &options.no_pack_iram,"MCS51/DS390 - Tells the linker not to pack variables in internal ram"},
275 /** Table of all unsupported options and help text to display when one
279 /** shortOpt as in OPTIONS. */
281 /** longOpt as in OPTIONS. */
283 /** Message to display inside W_UNSUPPORTED_OPT when this option
288 static const UNSUPPORTEDOPT
289 unsupportedOptTable[] = {
290 { 'X', NULL, "use --xstack-loc instead" },
291 { 'x', NULL, "use --xstack instead" },
292 { 'i', NULL, "use --idata-loc instead" },
293 { 'r', NULL, "use --xdata-loc instead" },
294 { 's', NULL, "use --code-loc instead" },
295 { 'Y', NULL, "use -I instead" }
298 /** List of all default constant macros.
300 static const char *_baseValues[] = {
303 /* Path seperator character */
304 "sep", DIR_SEPARATOR_STRING,
308 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
312 static PORT *_ports[] =
314 #if !OPT_DISABLE_MCS51
317 #if !OPT_DISABLE_GBZ80
326 #if !OPT_DISABLE_DS390
329 #if !OPT_DISABLE_PIC16
335 #if !OPT_DISABLE_TININative
338 #if !OPT_DISABLE_XA51
341 #if !OPT_DISABLE_DS400
344 #if !OPT_DISABLE_HC08
349 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
351 /** Sets the port to the one given by the command line option.
352 @param The name minus the option (eg 'mcs51')
353 @return 0 on success.
356 _setPort (const char *name)
359 for (i = 0; i < NUM_PORTS; i++)
361 if (!strcmp (_ports[i]->target, name))
367 /* Error - didnt find */
368 werror (E_UNKNOWN_TARGET, name);
372 /* Override the default processor with the one specified
373 * on the command line */
375 _setProcessor (char *_processor)
377 port->processor = _processor;
381 _validatePorts (void)
384 for (i = 0; i < NUM_PORTS; i++)
386 if (_ports[i]->magic != PORT_MAGIC)
388 /* Uncomment this line to debug which port is causing the problem
389 * (the target name is close to the beginning of the port struct
390 * and probably can be accessed just fine). */
391 fprintf(stderr,"%s :",_ports[i]->target);
392 wassertl (0, "Port definition structure is incomplete");
397 /* search through the command line options for the port */
399 _findPort (int argc, char **argv)
405 if (!strncmp (*argv, "-m", 2))
407 _setPort (*argv + 2);
413 /* Use the first in the list */
417 /* search through the command line options for the processor */
419 _findProcessor (int argc, char **argv)
423 if (!strncmp (*argv, "-p", 2))
425 _setProcessor (*argv + 2);
431 /* no error if processor was not specified. */
434 /*-----------------------------------------------------------------*/
435 /* printVersionInfo - prints the version info */
436 /*-----------------------------------------------------------------*/
438 printVersionInfo (FILE *stream)
444 for (i = 0; i < NUM_PORTS; i++)
445 fprintf (stream, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
447 fprintf (stream, " " SDCC_VERSION_STR
448 #ifdef SDCC_SUB_VERSION_STR
449 "/" SDCC_SUB_VERSION_STR
451 " #%s (" __DATE__ ")"
454 #elif defined __MINGW32__
456 #elif defined __DJGPP__
458 #elif defined(_MSC_VER)
460 #elif defined(__BORLANDC__)
465 , getBuildNumber() );
469 printOptions(const OPTION *optionsTable, FILE *stream)
473 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
474 || optionsTable[i].help != NULL;
477 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
478 && optionsTable[i].help)
480 fprintf (stream, "\n%s:\n", optionsTable[i].help);
484 fprintf(stream, " %c%c %-20s %s\n",
485 optionsTable[i].shortOpt !=0 ? '-' : ' ',
486 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
487 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
488 optionsTable[i].help != NULL ? optionsTable[i].help : ""
494 /*-----------------------------------------------------------------*/
495 /* printUsage - prints command line syntax */
496 /*-----------------------------------------------------------------*/
501 FILE *stream = stderr;
503 printVersionInfo (stream);
505 "Usage : sdcc [options] filename\n"
509 printOptions (optionsTable, stream);
511 for (i = 0; i < NUM_PORTS; i++)
513 if (_ports[i]->poptions != NULL)
515 fprintf (stream, "\nSpecial options for the %s port:\n", _ports[i]->target);
516 printOptions (_ports[i]->poptions, stream);
521 /*-----------------------------------------------------------------*/
522 /* setParseWithComma - separates string with comma to a set */
523 /*-----------------------------------------------------------------*/
525 setParseWithComma (set **dest, char *src)
530 /* skip the initial white spaces */
531 while (isspace((unsigned char)*src))
534 /* skip the trailing white spaces */
535 length = strlen(src);
536 while (length && isspace((unsigned char)src[length-1]))
537 src[--length] = '\0';
539 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
540 addSet(dest, Safe_strdup(p));
543 /*-----------------------------------------------------------------*/
544 /* setDefaultOptions - sets the default options */
545 /*-----------------------------------------------------------------*/
547 setDefaultOptions (void)
549 /* first the options part */
550 options.stack_loc = 0; /* stack pointer initialised to 0 */
551 options.xstack_loc = 0; /* xternal stack starts at 0 */
552 options.code_loc = 0; /* code starts at 0 */
553 options.data_loc = 0; /* JCF: By default let the linker locate data */
554 options.xdata_loc = 0;
555 options.idata_loc = 0x80;
557 options.model = port->general.default_model;
558 options.nostdlib = 0;
559 options.nostdinc = 0;
561 options.shortis8bits = 0;
562 options.std_sdcc = 1; /* enable SDCC language extensions */
563 options.std_c99 = 0; /* default to C89 until more C99 support */
564 options.code_seg = CODE_NAME; /* default to CSEG for generated code */
565 options.const_seg = CONST_NAME; /* default to CONST for generated code */
567 options.stack10bit=0;
569 /* now for the optimizations */
570 /* turn on the everything */
571 optimize.global_cse = 1;
576 optimize.loopInvariant = 1;
577 optimize.loopInduction = 1;
579 /* now for the ports */
580 port->setDefaultOptions ();
583 /*-----------------------------------------------------------------*/
584 /* processFile - determines the type of file from the extension */
585 /*-----------------------------------------------------------------*/
587 processFile (char *s)
591 /* get the file extension */
592 fext = s + strlen (s);
593 while ((fext != s) && *fext != '.')
596 /* now if no '.' then we don't know what the file type is
597 so give a warning and return */
600 werror (W_UNKNOWN_FEXT, s);
604 /* otherwise depending on the file type */
605 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
607 /* source file name : not if we already have a
611 werror (W_TOO_MANY_SRC, s);
615 /* the only source file */
617 if (!(srcFile = fopen (fullSrcFileName, "r")))
619 werror (E_FILE_OPEN_ERR, s);
623 /* copy the file name into the buffer */
624 strncpyz (buffer, s, sizeof(buffer));
626 /* get rid of the "."-extension */
628 /* is there a dot at all? */
629 if (strrchr (buffer, '.') &&
630 /* is the dot in the filename, not in the path? */
631 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
633 *strrchr (buffer, '.') = '\0';
636 /* get rid of any path information
637 for the module name; */
638 fext = buffer + strlen (buffer);
640 /* do this by going backwards till we
641 get '\' or ':' or start of buffer */
642 while (fext != buffer &&
643 *(fext - 1) != DIR_SEPARATOR_CHAR &&
649 /* do this by going backwards till we
650 get '/' or start of buffer */
651 while (fext != buffer &&
652 *(fext - 1) != DIR_SEPARATOR_CHAR)
657 moduleNameBase = Safe_strdup ( fext );
658 moduleName = Safe_strdup ( fext );
660 for (fext = moduleName; *fext; fext++)
661 if (!isalnum ((unsigned char)*fext))
666 /* if the extention is type .rel or .r or .REL or .R
667 addtional object file will be passed to the linker */
668 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
669 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
670 strcmp (fext, port->linker.rel_ext) == 0)
672 addSet(&relFilesSet, Safe_strdup(s));
676 /* if .lib or .LIB */
677 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
679 addSet(&libFilesSet, Safe_strdup(s));
683 werror (W_UNKNOWN_FEXT, s);
688 _setModel (int model, const char *sz)
690 if (port->general.supported_models & model)
691 options.model = model;
693 werror (W_UNSUPPORTED_MODEL, sz, port->target);
696 /** Gets the string argument to this option. If the option is '--opt'
697 then for input of '--optxyz' or '--opt xyz' returns xyz.
700 getStringArg(const char *szStart, char **argv, int *pi, int argc)
702 if (argv[*pi][strlen(szStart)])
704 return &argv[*pi][strlen(szStart)];
711 werror (E_ARGUMENT_MISSING, szStart);
712 /* Die here rather than checking for errors later. */
722 /** Gets the integer argument to this option using the same rules as
726 getIntArg(const char *szStart, char **argv, int *pi, int argc)
728 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
732 verifyShortOption(const char *opt)
734 if (strlen(opt) != 2)
736 werror (W_EXCESS_SHORT_OPTIONS, opt);
741 tryHandleUnsupportedOpt(char **argv, int *pi)
743 if (argv[*pi][0] == '-')
745 const char *longOpt = "";
749 if (argv[*pi][1] == '-')
756 shortOpt = argv[*pi][1];
758 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
760 if (unsupportedOptTable[i].shortOpt == shortOpt ||
761 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
762 /* Found an unsupported opt. */
764 SNPRINTF(buffer, sizeof(buffer),
766 longOpt ? longOpt : "",
767 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
768 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
772 /* Didn't find in the table */
777 /* Not an option, so can't be unsupported :) */
783 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
787 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
788 || optionsTable[i].help != NULL;
791 if (optionsTable[i].shortOpt == shortOpt ||
792 (longOpt && optionsTable[i].longOpt &&
793 strcmp(optionsTable[i].longOpt, longOpt) == 0))
796 /* If it is a flag then we can handle it here */
797 if (optionsTable[i].pparameter != NULL)
799 if (optionsTable[i].shortOpt == shortOpt)
801 verifyShortOption(argv[*pi]);
804 (*optionsTable[i].pparameter)++;
808 /* Not a flag. Handled manually later. */
813 /* Didn't find in the table */
818 tryHandleSimpleOpt(char **argv, int *pi)
820 if (argv[*pi][0] == '-')
822 const char *longOpt = "";
825 if (argv[*pi][1] == '-')
832 shortOpt = argv[*pi][1];
835 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
839 else if (port && port->poptions &&
840 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
851 /* Not an option, so can't be handled. */
856 /*-----------------------------------------------------------------*/
857 /* parseCmdLine - parses the command line and sets the options */
858 /*-----------------------------------------------------------------*/
860 parseCmdLine (int argc, char **argv)
864 /* go thru all whole command line */
865 for (i = 1; i < argc; i++)
870 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
875 if (tryHandleSimpleOpt(argv, &i) == TRUE)
881 if (argv[i][0] == '-' && argv[i][1] == '-')
883 if (strcmp (argv[i], OPTION_USE_STDOUT) == 0)
885 if (options.use_stdout == 0)
887 options.use_stdout = 1;
888 dup2(STDOUT_FILENO, STDERR_FILENO);
892 if (strcmp (argv[i], OPTION_HELP) == 0)
898 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
900 options.stack10bit = 0;
904 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
910 if (strcmp (argv[i], OPTION_OUT_FMT_S19) == 0)
916 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
918 _setModel (MODEL_LARGE, argv[i]);
922 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
924 _setModel (MODEL_MEDIUM, argv[i]);
928 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
930 _setModel (MODEL_SMALL, argv[i]);
934 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
936 _setModel (MODEL_FLAT24, argv[i]);
940 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
942 options.dump_rassgn =
948 options.dump_raw = 1;
952 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
954 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
958 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
960 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
964 if (strcmp (argv[i], OPTION_VERSION) == 0)
966 printVersionInfo (stdout);
971 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
973 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
977 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
979 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
983 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
985 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
989 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
991 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
995 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
997 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
1001 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
1003 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
1007 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
1009 options.xram_size = getIntArg(OPTION_XRAM_SIZE, argv, &i, argc);
1010 options.xram_size_set = TRUE;
1014 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
1016 options.code_size = getIntArg(OPTION_CODE_SIZE, argv, &i, argc);
1020 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
1022 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
1026 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
1028 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
1032 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1034 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1038 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1040 optimize.global_cse = 0;
1044 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1046 optimize.loopInvariant = 0;
1050 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1052 optimize.label4 = 0;
1056 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1058 optimize.loopInduction = 0;
1062 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1064 optimize.codeSpeed = 1;
1065 optimize.codeSize = 0;
1069 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1071 optimize.codeSpeed = 0;
1072 optimize.codeSize = 1;
1076 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1078 options.lessPedantic = 1;
1079 setErrorLogLevel(ERROR_LEVEL_WARNING);
1083 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1085 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1086 if (w < MAX_ERROR_WARNING)
1088 setWarningDisabled(w);
1093 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1095 options.shortis8bits=1;
1099 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1101 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1105 if (strcmp (argv[i], OPTION_STD_C89) == 0)
1107 options.std_c99 = 0;
1108 options.std_sdcc = 0;
1112 if (strcmp (argv[i], OPTION_STD_C99) == 0)
1114 options.std_c99 = 1;
1115 options.std_sdcc = 0;
1119 if (strcmp (argv[i], OPTION_STD_SDCC89) == 0)
1121 options.std_c99 = 0;
1122 options.std_sdcc = 1;
1126 if (strcmp (argv[i], OPTION_STD_SDCC99) == 0)
1128 options.std_c99 = 1;
1129 options.std_sdcc = 1;
1133 if (strcmp (argv[i], OPTION_CODE_SEG) == 0)
1135 options.code_seg = getStringArg(OPTION_CODE_SEG, argv, &i, argc);
1139 if (strcmp (argv[i], OPTION_CONST_SEG) == 0)
1141 options.const_seg = getStringArg(OPTION_CONST_SEG, argv, &i, argc);
1145 if (!port->parseOption (&argc, argv, &i))
1147 werror (W_UNKNOWN_OPTION, argv[i]);
1156 /* if preceded by '-' then option */
1157 if (*argv[i] == '-')
1162 verifyShortOption(argv[i]);
1165 exit (EXIT_SUCCESS);
1169 /* Used to select the port. But this has already been done. */
1173 /* Used to select the processor in port. But this has
1174 * already been done. */
1178 verifyShortOption(argv[i]);
1180 options.cc_only = 1;
1184 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1188 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1195 /* copy the file name into the buffer */
1196 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1198 /* point to last character */
1199 p = buffer + strlen (buffer) - 1;
1200 if (*p == DIR_SEPARATOR_CHAR)
1202 /* only output path specified */
1203 dstPath = Safe_strdup (buffer);
1204 fullDstFileName = NULL;
1208 fullDstFileName = Safe_strdup (buffer);
1210 /* get rid of the "."-extension */
1212 /* is there a dot at all? */
1213 if (strrchr (buffer, '.') &&
1214 /* is the dot in the filename, not in the path? */
1215 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1216 *strrchr (buffer, '.') = '\0';
1218 dstFileName = Safe_strdup (buffer);
1220 /* strip module name to get path */
1221 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1224 /* path with trailing / */
1226 dstPath = Safe_strdup (buffer);
1233 /* pre-processer options */
1234 if (argv[i][2] == 'p')
1236 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1238 /* linker options */
1239 else if (argv[i][2] == 'l')
1241 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1243 /* assembler options */
1244 else if (argv[i][2] == 'a')
1246 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1250 werror (W_UNKNOWN_OPTION, argv[i]);
1255 verifyShortOption(argv[i]);
1257 printVersionInfo (stdout);
1261 /* preprocessor options */
1265 if (argv[i][2] == 'M')
1266 addSet(&preArgvSet, Safe_strdup("-MM"));
1268 addSet(&preArgvSet, Safe_strdup("-M"));
1273 addSet(&preArgvSet, Safe_strdup("-C"));
1283 char sOpt = argv[i][1];
1286 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1292 werror(E_ARGUMENT_MISSING, argv[i-1]);
1306 SNPRINTF (buffer, sizeof(buffer),
1307 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1308 addSet(&preArgvSet, Safe_strdup(buffer));
1310 addSet(&includeDirsSet, Safe_strdup(rest));
1311 addSet(&userIncDirsSet, Safe_strdup(rest));
1317 if (!port->parseOption (&argc, argv, &i))
1318 werror (W_UNKNOWN_OPTION, argv[i]);
1323 if (!port->parseOption (&argc, argv, &i))
1325 /* no option must be a filename */
1328 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1332 processFile (argv[i]);
1337 /* some sanity checks in c1 mode */
1342 if (fullSrcFileName)
1345 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1347 fullSrcFileName = NULL;
1348 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1350 werror (W_NO_FILE_ARG_IN_C1, s);
1352 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1354 werror (W_NO_FILE_ARG_IN_C1, s);
1356 deleteSet(&relFilesSet);
1357 deleteSet(&libFilesSet);
1359 if (options.cc_only || noAssemble || preProcOnly)
1361 werror (W_ILLEGAL_OPT_COMBINATION);
1363 options.cc_only = noAssemble = preProcOnly = 0;
1366 werror (E_NEED_OPT_O_IN_C1);
1370 /* if no dstFileName given with -o, we've to find one: */
1375 /* use the modulename from the C-source */
1376 if (fullSrcFileName)
1378 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1380 dstFileName = Safe_alloc (bufSize);
1381 strncpyz (dstFileName, dstPath, bufSize);
1382 strncatz (dstFileName, moduleNameBase, bufSize);
1384 /* use the modulename from the first object file */
1385 else if ((s = peekSet(relFilesSet)) != NULL)
1390 strncpyz (buffer, s, sizeof(buffer));
1391 /* remove extension (it must be .rel) */
1392 *strrchr (buffer, '.') = '\0';
1394 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1401 objectName = buffer;
1403 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1404 dstFileName = Safe_alloc (bufSize);
1405 strncpyz (dstFileName, dstPath, bufSize);
1406 strncatz (dstFileName, objectName, bufSize);
1408 /* else no module given: help text is displayed */
1411 /* set int, long and float reentrancy based on stack-auto */
1412 if (options.stackAuto)
1414 options.intlong_rent++;
1415 options.float_rent++;
1418 /* mcs51 has an assembly coded float library that's always reentrant */
1419 if (TARGET_IS_MCS51)
1421 options.float_rent++;
1424 /* set up external stack location if not explicitly specified */
1425 if (!options.xstack_loc)
1426 options.xstack_loc = options.xdata_loc;
1428 /* if debug option is set then open the cdbFile */
1429 if (options.debug && fullSrcFileName)
1431 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1432 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1433 if(debugFile->openFile(scratchFileName))
1434 debugFile->writeModule(moduleName);
1436 werror (E_FILE_OPEN_ERR, scratchFileName);
1438 MSVC_style(options.vc_err_style);
1443 /*-----------------------------------------------------------------*/
1444 /* linkEdit : - calls the linkage editor with options */
1445 /*-----------------------------------------------------------------*/
1447 linkEdit (char **envp)
1453 char linkerScriptFileName[PATH_MAX];
1455 linkerScriptFileName[0] = 0;
1457 if(port->linker.needLinkerScript)
1461 switch (options.out_fmt)
1464 out_fmt = 'i'; /* Intel hex */
1467 out_fmt = 's'; /* Motorola S19 */
1470 out_fmt = 't'; /* Elf */
1476 /* first we need to create the <filename>.lnk file */
1477 SNPRINTF (linkerScriptFileName, sizeof(scratchFileName),
1478 "%s.lnk", dstFileName);
1479 if (!(lnkfile = fopen (linkerScriptFileName, "w")))
1481 werror (E_FILE_OPEN_ERR, linkerScriptFileName);
1485 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1487 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1488 out_fmt, dstFileName);
1490 else /*For all the other ports. Including pics???*/
1492 fprintf (lnkfile, "-myux%c\n", out_fmt);
1493 if(!options.no_pack_iram)
1494 fprintf (lnkfile, "-Y\n");
1497 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1499 /* if iram size specified */
1500 if (options.iram_size)
1501 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1503 /* if stack size specified*/
1504 if(options.stack_size)
1505 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1507 /* if xram size specified */
1508 if (options.xram_size_set)
1509 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1511 /* if code size specified */
1512 if (options.code_size)
1513 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1516 fprintf (lnkfile, "-z\n");
1519 #define WRITE_SEG_LOC(N, L) \
1520 segName = Safe_strdup(N); \
1521 c = strtok(segName, " \t"); \
1522 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1523 if (segName) { Safe_free(segName); }
1525 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1528 /* code segment start */
1529 WRITE_SEG_LOC (HOME_NAME, options.code_loc);
1531 /* data segment start. If zero, the linker chooses
1532 the best place for data */
1533 if(options.data_loc)
1535 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1538 /* xdata segment start. If zero, the linker chooses
1539 the best place for xdata */
1540 if(options.xdata_loc)
1542 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1548 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1551 /* bit segment start */
1552 WRITE_SEG_LOC (BIT_NAME, 0);
1555 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1558 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1561 else /*For the z80, gbz80*/
1563 WRITE_SEG_LOC ("_CODE", options.code_loc);
1564 WRITE_SEG_LOC ("_DATA", options.data_loc);
1567 /* If the port has any special linker area declarations, get 'em */
1568 if (port->extraAreas.genExtraAreaLinkOptions)
1570 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1573 /* add the extra linker options */
1574 fputStrSet(lnkfile, linkOptionsSet);
1576 /* command line defined library paths if specified */
1577 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1578 fprintf (lnkfile, "-k %s\n", s);
1580 /* standard library path */
1581 if (!options.nostdlib)
1583 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1585 switch (options.model)
1588 if (options.stackAuto)
1589 c = "small-stack-auto";
1594 if (options.stackAuto)
1595 c = "medium-stack-auto";
1600 if (options.stackAuto)
1601 c = "large-stack-auto";
1607 if (TARGET_IS_DS390)
1611 else if (TARGET_IS_DS400)
1618 "Add support for your FLAT24 target in %s @ line %d\n",
1619 __FILE__, __LINE__);
1627 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1632 else /*for the z80, gbz80*/
1636 else if (TARGET_IS_Z80)
1641 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1642 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1645 /* command line defined library files if specified */
1646 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1647 fprintf (lnkfile, "-l %s\n", s);
1649 /* standard library files */
1650 if (!options.nostdlib)
1652 #if !OPT_DISABLE_DS390
1653 if (options.model == MODEL_FLAT24)
1655 if (TARGET_IS_DS390)
1657 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1659 else if (TARGET_IS_DS400)
1661 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1666 "Add support for your FLAT24 target in %s @ line %d\n",
1667 __FILE__, __LINE__);
1673 #if !OPT_DISABLE_XA51
1675 if (options.model == MODEL_PAGE0)
1677 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1681 if (TARGET_IS_MCS51)
1683 fprintf (lnkfile, "-l mcs51\n");
1685 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1686 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1687 { /*Why the z80 port is not using the standard libraries?*/
1688 fprintf (lnkfile, "-l %s\n", STD_LIB);
1689 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1690 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1691 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1693 else if (TARGET_IS_HC08)
1695 fprintf (lnkfile, "-l hc08\n");
1697 else if (TARGET_IS_Z80)
1699 fprintf (lnkfile, "-l z80\n");
1701 else if (TARGET_IS_GBZ80)
1703 fprintf (lnkfile, "-l gbz80\n");
1707 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1708 It is very important for this file to be first on the linking proccess
1709 so the areas are set in the correct order, expecially _GSINIT*/
1710 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1711 !options.no_std_crt0) /*For the z80, gbz80*/
1713 char crt0path[PATH_MAX];
1717 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1718 tempSet = appendStrSet(tempSet, NULL, c);
1719 mergeSets(&tempSet, libPathsSet);
1721 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1723 sprintf (crt0path, "%s%scrt0.o",
1724 s, DIR_SEPARATOR_STRING);
1726 crt0fp=fopen(crt0path, "r");
1727 if(crt0fp!=NULL)/*Found it!*/
1732 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1733 windows paths, so convert them to the CYGWIN format*/
1734 char posix_path[PATH_MAX];
1735 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1736 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1737 strcpy(crt0path, posix_path);
1740 fprintf (lnkfile, "%s\n", crt0path);
1744 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1747 /* put in the object files */
1748 if (fullSrcFileName)
1749 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1751 fputStrSet(lnkfile, relFilesSet);
1753 fprintf (lnkfile, "\n-e\n");
1755 } /* if(port->linker.needLinkerScript) */
1757 if (options.verbose)
1758 printf ("sdcc: Calling linker...\n");
1760 /* build linker output filename */
1762 /* -o option overrides default name? */
1763 if (fullDstFileName)
1765 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1769 /* the linked file gets the name of the first modul */
1770 if (fullSrcFileName)
1772 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1776 s = peekSet(relFilesSet);
1780 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1781 /* strip ".rel" extension */
1782 *strrchr (scratchFileName, '.') = '\0';
1784 strncatz (scratchFileName,
1785 options.out_fmt ? ".S19" : ".ihx",
1786 sizeof(scratchFileName));
1789 if (port->linker.cmd)
1791 char buffer2[PATH_MAX];
1792 char buffer3[PATH_MAX];
1793 set *tempSet=NULL, *libSet=NULL;
1795 strcpy(buffer3, linkerScriptFileName);
1796 if(/*TARGET_IS_PIC16 ||*/ TARGET_IS_PIC) {
1798 /* use $l to set the linker include directories */
1799 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1800 mergeSets(&linkOptionsSet, tempSet);
1802 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1803 mergeSets(&linkOptionsSet, tempSet);
1805 /* use $3 for libraries from command line --> libSet */
1806 mergeSets(&libSet, libFilesSet);
1808 tempSet = appendStrSet(relFilesSet, "", "");
1809 mergeSets(&libSet, tempSet);
1810 // libSet = reverseSet(libSet);
1812 if(fullSrcFileName) {
1813 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1814 /* if it didn't work, revert to old behaviour */
1815 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1816 strcat(buffer3, port->linker.rel_ext);
1818 } else strcpy(buffer3, "");
1821 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1823 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1827 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1830 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1832 system_ret = my_system (buffer);
1833 /* TODO: most linker don't have a -o parameter */
1834 /* -o option overrides default name? */
1835 if (fullDstFileName)
1838 /* the linked file gets the name of the first modul */
1839 if (fullSrcFileName)
1841 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1842 p = strlen (scratchFileName) + scratchFileName;
1846 s = peekSet(relFilesSet);
1850 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1851 /* strip ".rel" extension */
1852 p = strrchr (scratchFileName, '.');
1858 strncatz (scratchFileName,
1859 options.out_fmt ? ".S19" : ".ihx",
1860 sizeof(scratchFileName));
1861 if (strcmp (fullDstFileName, scratchFileName))
1862 remove (fullDstFileName);
1863 rename (scratchFileName, fullDstFileName);
1865 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1866 q = strrchr (buffer, '.');
1869 /* no extension: append new extensions */
1870 q = strlen (buffer) + buffer;
1874 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1876 strncatz(buffer, ".map", sizeof(buffer));
1877 if (strcmp (scratchFileName, buffer))
1879 rename (scratchFileName, buffer);
1881 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1883 strncatz(buffer, ".mem", sizeof(buffer));
1884 if (strcmp (scratchFileName, buffer))
1886 rename (scratchFileName, buffer);
1890 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1892 strncatz(buffer, ".cdb", sizeof(buffer));
1893 if (strcmp (scratchFileName, buffer))
1895 rename (scratchFileName, buffer);
1896 /* and the OMF file without extension: */
1899 if (strcmp (scratchFileName, buffer))
1901 rename (scratchFileName, buffer);
1910 /*-----------------------------------------------------------------*/
1911 /* assemble - spawns the assembler with arguments */
1912 /*-----------------------------------------------------------------*/
1914 assemble (char **envp)
1916 /* build assembler output filename */
1918 /* -o option overrides default name? */
1919 if (options.cc_only && fullDstFileName) {
1920 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1922 /* the assembled file gets the name of the first modul */
1923 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1924 strncatz (scratchFileName, port->linker.rel_ext,
1925 sizeof(scratchFileName));
1928 if (port->assembler.do_assemble) {
1929 port->assembler.do_assemble(asmOptionsSet);
1931 } else if (port->assembler.cmd) {
1932 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1933 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1936 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1939 if (my_system (buffer)) {
1940 /* either system() or the assembler itself has reported an error
1941 perror ("Cannot exec assembler");
1945 /* TODO: most assembler don't have a -o parameter */
1946 /* -o option overrides default name? */
1947 if (options.cc_only && fullDstFileName) {
1948 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1949 strncatz (scratchFileName,
1950 port->linker.rel_ext,
1951 sizeof(scratchFileName));
1952 if (strcmp (scratchFileName, fullDstFileName))
1953 remove (fullDstFileName);
1954 rename (scratchFileName, fullDstFileName);
1958 /*-----------------------------------------------------------------*/
1959 /* preProcess - spawns the preprocessor with arguments */
1960 /*-----------------------------------------------------------------*/
1962 preProcess (char **envp)
1971 set *inclList = NULL;
1973 if (NULL != port->linker.rel_ext)
1975 #define OBJ_EXT_STR "-obj-ext="
1976 #define OBJ_EXT_LEN ((sizeof OBJ_EXT_STR) - 1)
1977 char *buf = Safe_alloc(strlen(port->linker.rel_ext) + (OBJ_EXT_LEN + 1));
1978 strcpy(buf, OBJ_EXT_STR);
1979 strcpy(&buf[OBJ_EXT_LEN], port->linker.rel_ext);
1980 addSet(&preArgvSet, buf);
1983 /* if using external stack define the macro */
1984 if (options.useXstack)
1985 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1987 /* set the macro for stack autos */
1988 if (options.stackAuto)
1989 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1991 /* set the macro for stack autos */
1992 if (options.stack10bit)
1993 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1995 /* set the macro for no overlay */
1996 if (options.noOverlay)
1997 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1999 /* set the macro for large model */
2000 switch (options.model)
2003 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
2006 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
2009 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
2012 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
2015 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
2018 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
2021 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
2025 /* add SDCC version number */
2028 SNPRINTF(buf, sizeof(buf), "-DSDCC=%d%d%d",
2029 SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2030 addSet(&preArgvSet, Safe_strdup(buf));
2033 /* add port (processor information to processor */
2034 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
2035 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
2037 if (port && port->processor && TARGET_IS_PIC) {
2039 SNPRINTF(&proc[0], 512, "-DSDCC_PROCESSOR=\"%s\"", port->processor);
2040 addSet(&preArgvSet, Safe_strdup(proc));
2043 /* standard include path */
2044 if (!options.nostdinc) {
2045 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
2046 mergeSets(&preArgvSet, inclList);
2049 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
2050 Safe_free((void *)s);
2051 if (inclList != NULL)
2052 deleteSet(&inclList);
2054 if (preProcOnly && fullDstFileName)
2056 /* -E and -o given */
2057 setMainValue ("cppoutfilename", fullDstFileName);
2061 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2062 setMainValue ("cppoutfilename", NULL);
2065 if (options.verbose)
2066 printf ("sdcc: Calling preprocessor...\n");
2067 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2070 if (my_system (buffer)) {
2077 yyin = my_popen (buffer);
2079 perror ("Preproc file not found");
2082 addSetHead (&pipeSet, yyin);
2090 setBinPaths(const char *argv0)
2098 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2099 * 2. - path(argv[0])
2103 /* do it in reverse mode, so that addSetHead() can be used
2104 instead of slower addSet() */
2106 if ((p = getBinPath(argv0)) != NULL)
2107 addSetHead(&binPathSet, Safe_strdup(p));
2109 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2110 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2111 addSetHead(&binPathSet, Safe_strdup(buf));
2115 /* Set system include path */
2117 setIncludePath(void)
2126 * 1. - $SDCC_INCLUDE/target
2127 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2128 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2129 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2130 * 5. - $SDCC_INCLUDE
2131 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2132 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2133 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2136 if (options.nostdinc)
2139 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2140 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2141 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2142 mergeSets(&includeDirsSet, tempSet);
2144 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2146 addSetHead(&includeDirsSet, p);
2147 p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2151 strcat(p2, DIR_SEPARATOR_STRING);
2152 strcat(p2, port->target);
2153 addSetHead(&includeDirsSet, p2);
2158 /* Set system lib path */
2168 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2169 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2170 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2173 if (options.nostdlib)
2176 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2178 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2179 addSetHead(&libDirsSet, p);
2184 setDataPaths(const char *argv0)
2192 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2193 * 2. - path(argv[0])/BIN2DATA_DIR
2194 * 3. - DATADIR (only on *nix)
2197 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2198 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2199 addSet(&dataDirsSet, Safe_strdup(buf));
2202 if ((p = getBinPath(argv0)) != NULL) {
2203 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2204 addSet(&dataDirsSet, Safe_strdup(buf));
2208 if (peekSet(dataDirsSet) == NULL) {
2209 /* this should never happen... */
2210 wassertl(0, "Can't get binary path");
2213 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2223 populateMainValues (_baseValues);
2224 setMainValue ("port", port->target);
2225 setMainValue ("objext", port->linker.rel_ext);
2226 setMainValue ("asmext", port->assembler.file_ext);
2228 setMainValue ("dstfilename", dstFileName);
2229 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2231 if (options.cc_only && fullDstFileName)
2232 /* compile + assemble and -o given: -o specifies name of object file */
2234 setMainValue ("objdstfilename", fullDstFileName);
2238 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2240 if (fullDstFileName)
2241 /* if we're linking, -o gives the final file name */
2243 setMainValue ("linkdstfilename", fullDstFileName);
2247 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2252 static void doPrintSearchDirs(void)
2254 printf("programs:\n");
2255 fputStrSet(stdout, binPathSet);
2257 printf("datadir:\n");
2258 fputStrSet(stdout, dataDirsSet);
2260 printf("includedir:\n");
2261 fputStrSet(stdout, includeDirsSet);
2263 printf("libdir:\n");
2264 fputStrSet(stdout, libDirsSet);
2265 fputStrSet(stdout, libPathsSet);
2270 sig_handler (int signal)
2277 sig_string = "SIGABRT";
2280 sig_string = "SIGTERM";
2283 sig_string = "SIGINT";
2286 sig_string = "SIGSEGV";
2289 sig_string = "Unknown?";
2292 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2298 * initialises and calls the parser
2302 main (int argc, char **argv, char **envp)
2304 /* turn all optimizations off by default */
2305 memset (&optimize, 0, sizeof (struct optimize));
2308 fprintf (stderr, "Build error: no ports are enabled.\n");
2312 /* install atexit handler */
2313 atexit(rm_tmpfiles);
2315 /* install signal handler;
2316 it's only purpose is to call exit() to remove temp files */
2317 if (!getenv("SDCC_LEAVE_SIGNALS"))
2319 signal (SIGABRT, sig_handler);
2320 signal (SIGTERM, sig_handler);
2321 signal (SIGINT , sig_handler);
2322 signal (SIGSEGV, sig_handler);
2325 /* Before parsing the command line options, do a
2326 * search for the port and processor and initialize
2327 * them if they're found. (We can't gurantee that these
2328 * will be the first options specified).
2331 _findPort (argc, argv);
2334 if (strcmp(port->target, "mcs51") == 0) {
2335 printf("DS390 jammed in A\n");
2341 _findProcessor (argc, argv);
2343 /* Initalise the port. */
2347 setDefaultOptions ();
2350 options.model = MODEL_SMALL;
2351 options.stack10bit=0;
2355 parseCmdLine (argc, argv);
2357 if (options.verbose && NULL != port->processor)
2358 printf("Processor: %s\n", port->processor);
2362 setBinPaths(argv[0]);
2363 setDataPaths(argv[0]);
2368 if(options.printSearchDirs)
2369 doPrintSearchDirs();
2371 /* if no input then printUsage & exit */
2372 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL)
2374 if (options.printSearchDirs)
2375 exit (EXIT_SUCCESS);
2377 exit (EXIT_FAILURE);
2380 /* initMem() is expensive, but
2381 initMem() must called before port->finaliseOptions ().
2382 And the z80 port needs port->finaliseOptions(),
2383 even if we're only linking. */
2385 port->finaliseOptions ();
2387 if (fullSrcFileName || options.c1mode)
2397 if (options.verbose)
2398 printf ("sdcc: Generating code...\n");
2404 deleteSetItem(&pipeSet, yyin);
2410 if (port->general.do_glue != NULL)
2411 (*port->general.do_glue)();
2414 /* this shouldn't happen */
2416 /* in case of NDEBUG */
2424 if (!options.c1mode && !noAssemble)
2426 if (options.verbose)
2427 printf ("sdcc: Calling assembler...\n");
2433 if (options.debug && debugFile)
2434 debugFile->closeFile();
2436 if (!options.cc_only &&
2440 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2442 if (options.verbose)
2443 printf ("sdcc: Calling linker...\n");
2445 if (port->linker.do_link)
2446 port->linker.do_link ();