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 struct optimize optimize;
68 struct options options;
71 set *preArgvSet = NULL; /* pre-processor arguments */
72 set *asmOptionsSet = NULL; /* set of assembler options */
73 set *linkOptionsSet = NULL; /* set of linker options */
74 set *libFilesSet = NULL;
75 set *libPathsSet = NULL;
76 set *relFilesSet = NULL;
77 set *dataDirsSet = NULL; /* list of data search directories */
78 set *includeDirsSet = NULL; /* list of include search directories */
79 set *userIncDirsSet = NULL; /* list of user include directories */
80 set *libDirsSet = NULL; /* list of lib search directories */
82 /* uncomment JAMIN_DS390 to always override and use ds390 port
83 for mcs51 work. This is temporary, for compatibility testing. */
84 /* #define JAMIN_DS390 */
89 /* Globally accessible scratch buffer for file names. */
90 char scratchFileName[PATH_MAX];
91 char buffer[PATH_MAX * 2];
93 #define OPTION_HELP "-help"
95 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
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"
141 { 0, NULL, NULL, "General options" },
142 { 0, "--help", NULL, "Display this help" },
143 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
144 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
145 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
146 { 'd', NULL, NULL, NULL },
147 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
148 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
149 { 'A', NULL, NULL, NULL },
150 { 'U', NULL, NULL, NULL },
151 { 'C', NULL, NULL, "Preprocessor option" },
152 { 'M', NULL, NULL, "Preprocessor option" },
153 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
154 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
155 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
156 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
157 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
158 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
159 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
160 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
161 { 0, OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
162 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
163 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
164 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
165 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
166 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
167 { 0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions" },
169 { 0, NULL, NULL, "Code generation options"},
170 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
171 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
172 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
173 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
174 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
175 #if !OPT_DISABLE_DS390
176 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
177 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
178 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
180 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
181 { 0, "--xstack", &options.useXstack, "Use external stack" },
182 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
183 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
184 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
185 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
186 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
187 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
188 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
189 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
190 #if !OPT_DISABLE_DS390
191 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
193 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
194 #if !OPT_DISABLE_TININative
195 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
197 #if !OPT_DISABLE_DS390
198 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
200 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
201 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
203 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
204 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
205 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
206 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
207 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
209 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" },
211 { 0, NULL, NULL, "Optimization options"},
212 { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" },
213 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
214 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
215 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
216 { 0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction" },
217 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
218 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
219 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
220 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
221 { 0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly" },
222 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peephole file" },
223 { 0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size" },
224 { 0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed" },
226 { 0, NULL, NULL, "Internal debugging options"},
227 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
228 { 0, "--dumpgcse", &options.dump_gcse, NULL },
229 { 0, "--dumploop", &options.dump_loop, NULL },
230 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
231 { 0, "--dumpliverange", &options.dump_range, NULL },
232 { 0, "--dumpregpack", &options.dump_pack, NULL },
233 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
234 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
235 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
236 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
238 { 0, NULL, NULL, "Linker options" },
239 { 'l', NULL, NULL, "Include the given library in the link" },
240 { 'L', NULL, NULL, "Add the next field to the library search path" },
241 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
242 { 0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format" },
243 { 0, OPTION_OUT_FMT_S19, NULL, "Output in S19 hex format" },
244 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
245 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
246 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
247 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
248 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
249 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
250 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
251 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
252 { 0, OPTION_IDATA_LOC, NULL, NULL },
253 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
254 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
255 { 0, OPTION_PACK_IRAM, NULL,"MCS51/DS390 - Tells the linker to pack variables in internal ram (default)"},
256 { 0, OPTION_NO_PACK_IRAM, &options.no_pack_iram,"MCS51/DS390 - Tells the linker not to pack variables in internal ram"},
263 /** Table of all unsupported options and help text to display when one
267 /** shortOpt as in OPTIONS. */
269 /** longOpt as in OPTIONS. */
271 /** Message to display inside W_UNSUPPORTED_OPT when this option
276 static const UNSUPPORTEDOPT
277 unsupportedOptTable[] = {
278 { 'X', NULL, "use --xstack-loc instead" },
279 { 'x', NULL, "use --xstack instead" },
280 { 'i', NULL, "use --idata-loc instead" },
281 { 'r', NULL, "use --xdata-loc instead" },
282 { 's', NULL, "use --code-loc instead" },
283 { 'Y', NULL, "use -I instead" }
286 /** List of all default constant macros.
288 static const char *_baseValues[] = {
291 /* Path seperator character */
292 "sep", DIR_SEPARATOR_STRING,
296 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
300 static PORT *_ports[] =
302 #if !OPT_DISABLE_MCS51
305 #if !OPT_DISABLE_GBZ80
314 #if !OPT_DISABLE_DS390
317 #if !OPT_DISABLE_PIC16
323 #if !OPT_DISABLE_TININative
326 #if !OPT_DISABLE_XA51
329 #if !OPT_DISABLE_DS400
332 #if !OPT_DISABLE_HC08
337 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
339 /** Sets the port to the one given by the command line option.
340 @param The name minus the option (eg 'mcs51')
341 @return 0 on success.
344 _setPort (const char *name)
347 for (i = 0; i < NUM_PORTS; i++)
349 if (!strcmp (_ports[i]->target, name))
355 /* Error - didnt find */
356 werror (E_UNKNOWN_TARGET, name);
360 /* Override the default processor with the one specified
361 * on the command line */
363 _setProcessor (char *_processor)
365 port->processor = _processor;
366 fprintf(stderr,"Processor: %s\n",_processor);
370 _validatePorts (void)
373 for (i = 0; i < NUM_PORTS; i++)
375 if (_ports[i]->magic != PORT_MAGIC)
377 /* Uncomment this line to debug which port is causing the problem
378 * (the target name is close to the beginning of the port struct
379 * and probably can be accessed just fine). */
380 fprintf(stderr,"%s :",_ports[i]->target);
381 wassertl (0, "Port definition structure is incomplete");
386 /* search through the command line options for the port */
388 _findPort (int argc, char **argv)
394 if (!strncmp (*argv, "-m", 2))
396 _setPort (*argv + 2);
402 /* Use the first in the list */
406 /* search through the command line options for the processor */
408 _findProcessor (int argc, char **argv)
412 if (!strncmp (*argv, "-p", 2))
414 _setProcessor (*argv + 2);
420 /* no error if processor was not specified. */
423 /*-----------------------------------------------------------------*/
424 /* printVersionInfo - prints the version info */
425 /*-----------------------------------------------------------------*/
427 printVersionInfo (void)
433 for (i = 0; i < NUM_PORTS; i++)
434 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
436 fprintf (stderr, " " SDCC_VERSION_STR
437 #ifdef SDCC_SUB_VERSION_STR
438 "/" SDCC_SUB_VERSION_STR
440 " #%s (" __DATE__ ")"
443 #elif defined __MINGW32__
445 #elif defined __DJGPP__
447 #elif defined(_MSC_VER)
449 #elif defined(__BORLANDC__)
454 , getBuildNumber() );
458 printOptions(const OPTION *optionsTable)
462 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
463 || optionsTable[i].help != NULL;
466 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
467 && optionsTable[i].help)
469 fprintf (stdout, "\n%s:\n", optionsTable[i].help);
473 fprintf(stdout, " %c%c %-20s %s\n",
474 optionsTable[i].shortOpt !=0 ? '-' : ' ',
475 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
476 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
477 optionsTable[i].help != NULL ? optionsTable[i].help : ""
483 /*-----------------------------------------------------------------*/
484 /* printUsage - prints command line syntax */
485 /*-----------------------------------------------------------------*/
492 "Usage : sdcc [options] filename\n"
496 printOptions(optionsTable);
498 for (i = 0; i < NUM_PORTS; i++)
500 if (_ports[i]->poptions != NULL)
502 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
503 printOptions (_ports[i]->poptions);
510 /*-----------------------------------------------------------------*/
511 /* setParseWithComma - separates string with comma to a set */
512 /*-----------------------------------------------------------------*/
514 setParseWithComma (set **dest, char *src)
519 /* skip the initial white spaces */
520 while (isspace(*src))
523 /* skip the trailing white spaces */
524 length = strlen(src);
525 while (length && isspace(src[length-1]))
526 src[--length] = '\0';
528 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
529 addSet(dest, Safe_strdup(p));
532 /*-----------------------------------------------------------------*/
533 /* setDefaultOptions - sets the default options */
534 /*-----------------------------------------------------------------*/
536 setDefaultOptions (void)
538 /* first the options part */
539 options.stack_loc = 0; /* stack pointer initialised to 0 */
540 options.xstack_loc = 0; /* xternal stack starts at 0 */
541 options.code_loc = 0; /* code starts at 0 */
542 options.data_loc = 0; /* JCF: By default let the linker locate data */
543 options.xdata_loc = 0;
544 options.idata_loc = 0x80;
546 options.model = port->general.default_model;
547 options.nostdlib = 0;
548 options.nostdinc = 0;
550 options.shortis8bits = 0;
552 options.stack10bit=0;
554 /* now for the optimizations */
555 /* turn on the everything */
556 optimize.global_cse = 1;
561 optimize.loopInvariant = 1;
562 optimize.loopInduction = 1;
564 /* now for the ports */
565 port->setDefaultOptions ();
568 /*-----------------------------------------------------------------*/
569 /* processFile - determines the type of file from the extension */
570 /*-----------------------------------------------------------------*/
572 processFile (char *s)
576 /* get the file extension */
577 fext = s + strlen (s);
578 while ((fext != s) && *fext != '.')
581 /* now if no '.' then we don't know what the file type is
582 so give a warning and return */
585 werror (W_UNKNOWN_FEXT, s);
589 /* otherwise depending on the file type */
590 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
592 /* source file name : not if we already have a
596 werror (W_TOO_MANY_SRC, s);
600 /* the only source file */
602 if (!(srcFile = fopen (fullSrcFileName, "r")))
604 werror (E_FILE_OPEN_ERR, s);
608 /* copy the file name into the buffer */
609 strncpyz (buffer, s, sizeof(buffer));
611 /* get rid of the "."-extension */
613 /* is there a dot at all? */
614 if (strrchr (buffer, '.') &&
615 /* is the dot in the filename, not in the path? */
616 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
618 *strrchr (buffer, '.') = '\0';
621 /* get rid of any path information
622 for the module name; */
623 fext = buffer + strlen (buffer);
625 /* do this by going backwards till we
626 get '\' or ':' or start of buffer */
627 while (fext != buffer &&
628 *(fext - 1) != DIR_SEPARATOR_CHAR &&
634 /* do this by going backwards till we
635 get '/' or start of buffer */
636 while (fext != buffer &&
637 *(fext - 1) != DIR_SEPARATOR_CHAR)
642 moduleNameBase = Safe_strdup ( fext );
643 moduleName = Safe_strdup ( fext );
645 for (fext = moduleName; *fext; fext++)
646 if (!isalnum (*fext))
651 /* if the extention is type .rel or .r or .REL or .R
652 addtional object file will be passed to the linker */
653 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
654 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
655 strcmp (fext, port->linker.rel_ext) == 0)
657 addSet(&relFilesSet, Safe_strdup(s));
661 /* if .lib or .LIB */
662 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
664 addSet(&libFilesSet, Safe_strdup(s));
668 werror (W_UNKNOWN_FEXT, s);
673 _setModel (int model, const char *sz)
675 if (port->general.supported_models & model)
676 options.model = model;
678 werror (W_UNSUPPORTED_MODEL, sz, port->target);
681 /** Gets the string argument to this option. If the option is '--opt'
682 then for input of '--optxyz' or '--opt xyz' returns xyz.
685 getStringArg(const char *szStart, char **argv, int *pi, int argc)
687 if (argv[*pi][strlen(szStart)])
689 return &argv[*pi][strlen(szStart)];
696 werror (E_ARGUMENT_MISSING, szStart);
697 /* Die here rather than checking for errors later. */
707 /** Gets the integer argument to this option using the same rules as
711 getIntArg(const char *szStart, char **argv, int *pi, int argc)
713 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
717 verifyShortOption(const char *opt)
719 if (strlen(opt) != 2)
721 werror (W_EXCESS_SHORT_OPTIONS, opt);
726 tryHandleUnsupportedOpt(char **argv, int *pi)
728 if (argv[*pi][0] == '-')
730 const char *longOpt = "";
734 if (argv[*pi][1] == '-')
741 shortOpt = argv[*pi][1];
743 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
745 if (unsupportedOptTable[i].shortOpt == shortOpt ||
746 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
747 /* Found an unsupported opt. */
749 SNPRINTF(buffer, sizeof(buffer),
751 longOpt ? longOpt : "",
752 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
753 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
757 /* Didn't find in the table */
762 /* Not an option, so can't be unsupported :) */
768 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
772 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
773 || optionsTable[i].help != NULL;
776 if (optionsTable[i].shortOpt == shortOpt ||
777 (longOpt && optionsTable[i].longOpt &&
778 strcmp(optionsTable[i].longOpt, longOpt) == 0))
781 /* If it is a flag then we can handle it here */
782 if (optionsTable[i].pparameter != NULL)
784 if (optionsTable[i].shortOpt == shortOpt)
786 verifyShortOption(argv[*pi]);
789 (*optionsTable[i].pparameter)++;
793 /* Not a flag. Handled manually later. */
798 /* Didn't find in the table */
803 tryHandleSimpleOpt(char **argv, int *pi)
805 if (argv[*pi][0] == '-')
807 const char *longOpt = "";
810 if (argv[*pi][1] == '-')
817 shortOpt = argv[*pi][1];
820 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
824 else if (port && port->poptions &&
825 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
836 /* Not an option, so can't be handled. */
841 /*-----------------------------------------------------------------*/
842 /* parseCmdLine - parses the command line and sets the options */
843 /*-----------------------------------------------------------------*/
845 parseCmdLine (int argc, char **argv)
849 /* go thru all whole command line */
850 for (i = 1; i < argc; i++)
855 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
860 if (tryHandleSimpleOpt(argv, &i) == TRUE)
866 if (argv[i][0] == '-' && argv[i][1] == '-')
868 if (strcmp (argv[i], OPTION_HELP) == 0)
874 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
876 options.stack10bit = 0;
880 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
886 if (strcmp (argv[i], OPTION_OUT_FMT_S19) == 0)
892 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
894 _setModel (MODEL_LARGE, argv[i]);
898 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
900 _setModel (MODEL_MEDIUM, argv[i]);
904 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
906 _setModel (MODEL_SMALL, argv[i]);
910 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
912 _setModel (MODEL_FLAT24, argv[i]);
916 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
918 options.dump_rassgn =
924 options.dump_raw = 1;
928 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
930 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
934 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
936 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
940 if (strcmp (argv[i], OPTION_VERSION) == 0)
947 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
949 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
953 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
955 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
959 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
961 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
965 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
967 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
971 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
973 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
977 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
979 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
983 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
985 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
986 options.xram_size_set = TRUE;
990 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
992 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
996 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
998 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
1002 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
1004 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
1008 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1010 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1014 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1016 optimize.global_cse = 0;
1020 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1022 optimize.loopInvariant = 0;
1026 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1028 optimize.label4 = 0;
1032 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1034 optimize.loopInduction = 0;
1038 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1040 optimize.codeSpeed = 1;
1041 optimize.codeSize = 0;
1045 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1047 optimize.codeSpeed = 0;
1048 optimize.codeSize = 1;
1052 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1054 options.lessPedantic = 1;
1055 setErrorLogLevel(ERROR_LEVEL_WARNING);
1059 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1061 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1062 if (w < MAX_ERROR_WARNING)
1064 setWarningDisabled(w);
1069 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1071 options.shortis8bits=1;
1075 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1077 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1081 if (!port->parseOption (&argc, argv, &i))
1083 werror (W_UNKNOWN_OPTION, argv[i]);
1092 /* if preceded by '-' then option */
1093 if (*argv[i] == '-')
1098 verifyShortOption(argv[i]);
1105 /* Used to select the port. But this has already been done. */
1109 /* Used to select the processor in port. But this has
1110 * already been done. */
1114 verifyShortOption(argv[i]);
1116 options.cc_only = 1;
1120 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1124 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1131 /* copy the file name into the buffer */
1132 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1134 /* point to last character */
1135 p = buffer + strlen (buffer) - 1;
1136 if (*p == DIR_SEPARATOR_CHAR)
1138 /* only output path specified */
1139 dstPath = Safe_strdup (buffer);
1140 fullDstFileName = NULL;
1144 fullDstFileName = Safe_strdup (buffer);
1146 /* get rid of the "."-extension */
1148 /* is there a dot at all? */
1149 if (strrchr (buffer, '.') &&
1150 /* is the dot in the filename, not in the path? */
1151 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1152 *strrchr (buffer, '.') = '\0';
1154 dstFileName = Safe_strdup (buffer);
1156 /* strip module name to get path */
1157 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1160 /* path with trailing / */
1162 dstPath = Safe_strdup (buffer);
1169 /* pre-processer options */
1170 if (argv[i][2] == 'p')
1172 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1174 /* linker options */
1175 else if (argv[i][2] == 'l')
1177 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1179 /* assembler options */
1180 else if (argv[i][2] == 'a')
1182 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1186 werror (W_UNKNOWN_OPTION, argv[i]);
1191 verifyShortOption(argv[i]);
1193 printVersionInfo ();
1197 /* preprocessor options */
1201 if (argv[i][2] == 'M')
1202 addSet(&preArgvSet, Safe_strdup("-MM"));
1204 addSet(&preArgvSet, Safe_strdup("-M"));
1209 addSet(&preArgvSet, Safe_strdup("-C"));
1219 char sOpt = argv[i][1];
1222 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1228 werror(E_ARGUMENT_MISSING, argv[i-1]);
1242 SNPRINTF (buffer, sizeof(buffer),
1243 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1244 addSet(&preArgvSet, Safe_strdup(buffer));
1246 addSet(&includeDirsSet, Safe_strdup(rest));
1247 addSet(&userIncDirsSet, Safe_strdup(rest));
1253 if (!port->parseOption (&argc, argv, &i))
1254 werror (W_UNKNOWN_OPTION, argv[i]);
1259 if (!port->parseOption (&argc, argv, &i))
1261 /* no option must be a filename */
1264 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1268 processFile (argv[i]);
1273 /* some sanity checks in c1 mode */
1278 if (fullSrcFileName)
1281 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1283 fullSrcFileName = NULL;
1284 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1286 werror (W_NO_FILE_ARG_IN_C1, s);
1288 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1290 werror (W_NO_FILE_ARG_IN_C1, s);
1292 deleteSet(&relFilesSet);
1293 deleteSet(&libFilesSet);
1295 if (options.cc_only || noAssemble || preProcOnly)
1297 werror (W_ILLEGAL_OPT_COMBINATION);
1299 options.cc_only = noAssemble = preProcOnly = 0;
1302 werror (E_NEED_OPT_O_IN_C1);
1306 /* if no dstFileName given with -o, we've to find one: */
1311 /* use the modulename from the C-source */
1312 if (fullSrcFileName)
1314 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1316 dstFileName = Safe_alloc (bufSize);
1317 strncpyz (dstFileName, dstPath, bufSize);
1318 strncatz (dstFileName, moduleNameBase, bufSize);
1320 /* use the modulename from the first object file */
1321 else if ((s = peekSet(relFilesSet)) != NULL)
1326 strncpyz (buffer, s, sizeof(buffer));
1327 /* remove extension (it must be .rel) */
1328 *strrchr (buffer, '.') = '\0';
1330 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1337 objectName = buffer;
1339 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1340 dstFileName = Safe_alloc (bufSize);
1341 strncpyz (dstFileName, dstPath, bufSize);
1342 strncatz (dstFileName, objectName, bufSize);
1344 /* else no module given: help text is displayed */
1347 /* set int, long and float reentrancy based on stack-auto */
1348 if (options.stackAuto)
1350 options.intlong_rent++;
1351 options.float_rent++;
1354 /* set up external stack location if not explicitly specified */
1355 if (!options.xstack_loc)
1356 options.xstack_loc = options.xdata_loc;
1358 /* if debug option is set then open the cdbFile */
1359 if (options.debug && fullSrcFileName)
1361 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1362 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1363 if(debugFile->openFile(scratchFileName))
1364 debugFile->writeModule(moduleName);
1366 werror (E_FILE_OPEN_ERR, scratchFileName);
1368 MSVC_style(options.vc_err_style);
1369 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1374 /*-----------------------------------------------------------------*/
1375 /* linkEdit : - calls the linkage editor with options */
1376 /*-----------------------------------------------------------------*/
1378 linkEdit (char **envp)
1386 if(port->linker.needLinkerScript)
1390 switch (options.out_fmt)
1393 out_fmt = 'i'; /* Intel hex */
1396 out_fmt = 's'; /* Motorola S19 */
1399 out_fmt = 't'; /* Elf */
1405 /* first we need to create the <filename>.lnk file */
1406 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1407 "%s.lnk", dstFileName);
1408 if (!(lnkfile = fopen (scratchFileName, "w")))
1410 werror (E_FILE_OPEN_ERR, scratchFileName);
1414 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1416 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1417 out_fmt, dstFileName);
1419 else /*For all the other ports. Including pics???*/
1421 fprintf (lnkfile, "-myux%c\n", out_fmt);
1422 if(!options.no_pack_iram)
1423 fprintf (lnkfile, "-Y\n");
1426 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1428 /* if iram size specified */
1429 if (options.iram_size)
1430 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1432 /* if stack size specified*/
1433 if(options.stack_size)
1434 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1436 /* if xram size specified */
1437 if (options.xram_size_set)
1438 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1440 /* if code size specified */
1441 if (options.code_size)
1442 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1445 fprintf (lnkfile, "-z\n");
1448 #define WRITE_SEG_LOC(N, L) \
1449 segName = Safe_strdup(N); \
1450 c = strtok(segName, " \t"); \
1451 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1452 if (segName) { Safe_free(segName); }
1454 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1457 /* code segment start */
1458 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1460 /* data segment start. If zero, the linker chooses
1461 the best place for data */
1462 if(options.data_loc)
1464 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1467 /* xdata segment start. If zero, the linker chooses
1468 the best place for xdata */
1469 if(options.xdata_loc)
1471 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1477 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1480 /* bit segment start */
1481 WRITE_SEG_LOC (BIT_NAME, 0);
1484 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1487 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1490 else /*For the z80, gbz80*/
1492 WRITE_SEG_LOC ("_CODE", options.code_loc);
1493 WRITE_SEG_LOC ("_DATA", options.data_loc);
1496 /* If the port has any special linker area declarations, get 'em */
1497 if (port->extraAreas.genExtraAreaLinkOptions)
1499 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1502 /* add the extra linker options */
1503 fputStrSet(lnkfile, linkOptionsSet);
1505 /* command line defined library paths if specified */
1506 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1507 fprintf (lnkfile, "-k %s\n", s);
1509 /* standard library path */
1510 if (!options.nostdlib)
1512 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1514 switch (options.model)
1524 if (TARGET_IS_DS390)
1528 else if (TARGET_IS_DS400)
1535 "Add support for your FLAT24 target in %s @ line %d\n",
1536 __FILE__, __LINE__);
1544 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1549 else /*for the z80, gbz80*/
1553 else if (TARGET_IS_Z80)
1558 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1559 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1562 /* command line defined library files if specified */
1563 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1564 fprintf (lnkfile, "-l %s\n", s);
1566 /* standard library files */
1567 if (!options.nostdlib)
1569 #if !OPT_DISABLE_DS390
1570 if (options.model == MODEL_FLAT24)
1572 if (TARGET_IS_DS390)
1574 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1576 else if (TARGET_IS_DS400)
1578 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1583 "Add support for your FLAT24 target in %s @ line %d\n",
1584 __FILE__, __LINE__);
1590 #if !OPT_DISABLE_XA51
1592 if (options.model == MODEL_PAGE0)
1594 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1598 if (TARGET_IS_MCS51)
1600 fprintf (lnkfile, "-l mcs51\n");
1602 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1603 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1604 { /*Why the z80 port is not using the standard libraries?*/
1605 fprintf (lnkfile, "-l %s\n", STD_LIB);
1606 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1607 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1608 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1610 else if (TARGET_IS_HC08)
1612 fprintf (lnkfile, "-l hc08\n");
1614 else if (TARGET_IS_Z80)
1616 fprintf (lnkfile, "-l z80\n");
1618 else if (TARGET_IS_GBZ80)
1620 fprintf (lnkfile, "-l gbz80\n");
1624 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1625 It is very important for this file to be first on the linking proccess
1626 so the areas are set in the correct order, expecially _GSINIT*/
1627 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1628 !options.no_std_crt0) /*For the z80, gbz80*/
1630 char crt0path[PATH_MAX];
1634 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1635 tempSet = appendStrSet(libDirsSet, NULL, c);
1636 mergeSets(&tempSet, libPathsSet);
1638 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1640 sprintf (crt0path, "%s%scrt0.o",
1641 s, DIR_SEPARATOR_STRING);
1643 crt0fp=fopen(crt0path, "r");
1644 if(crt0fp!=NULL)/*Found it!*/
1649 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1650 windows paths, so convert them to the CYGWIN format*/
1651 char posix_path[PATH_MAX];
1652 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1653 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1654 strcpy(crt0path, posix_path);
1657 fprintf (lnkfile, "%s\n", crt0path);
1661 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1664 /* put in the object files */
1665 if (fullSrcFileName)
1666 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1668 fputStrSet(lnkfile, relFilesSet);
1670 fprintf (lnkfile, "\n-e\n");
1672 } /* if(port->linker.needLinkerScript) */
1674 if (options.verbose)
1675 printf ("sdcc: Calling linker...\n");
1677 /* build linker output filename */
1679 /* -o option overrides default name? */
1680 if (fullDstFileName)
1682 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1686 /* the linked file gets the name of the first modul */
1687 if (fullSrcFileName)
1689 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1693 s = peekSet(relFilesSet);
1697 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1698 /* strip ".rel" extension */
1699 *strrchr (scratchFileName, '.') = '\0';
1701 strncatz (scratchFileName,
1702 options.out_fmt ? ".S19" : ".ihx",
1703 sizeof(scratchFileName));
1706 if (port->linker.cmd)
1708 char buffer2[PATH_MAX];
1709 char buffer3[PATH_MAX];
1710 set *tempSet=NULL, *libSet=NULL;
1712 strcpy(buffer3, dstFileName);
1713 if(TARGET_IS_PIC16) {
1715 /* use $l to set the linker include directories */
1716 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1717 mergeSets(&linkOptionsSet, tempSet);
1719 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1720 mergeSets(&linkOptionsSet, tempSet);
1722 /* use $3 for libraries from command line --> libSet */
1723 mergeSets(&libSet, libFilesSet);
1725 tempSet = appendStrSet(relFilesSet, "", "");
1726 mergeSets(&libSet, tempSet);
1727 // libSet = reverseSet(libSet);
1729 if(fullSrcFileName) {
1730 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1731 /* if it didn't work, revert to old behaviour */
1732 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1733 strcat(buffer3, port->linker.rel_ext);
1735 } else strcpy(buffer3, "");
1738 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1740 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1744 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1747 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1749 system_ret = my_system (buffer);
1750 /* TODO: most linker don't have a -o parameter */
1751 /* -o option overrides default name? */
1752 if (fullDstFileName)
1755 /* the linked file gets the name of the first modul */
1756 if (fullSrcFileName)
1758 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1759 p = strlen (scratchFileName) + scratchFileName;
1763 s = peekSet(relFilesSet);
1767 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1768 /* strip ".rel" extension */
1769 p = strrchr (scratchFileName, '.');
1775 strncatz (scratchFileName,
1776 options.out_fmt ? ".S19" : ".ihx",
1777 sizeof(scratchFileName));
1778 if (strcmp (fullDstFileName, scratchFileName))
1779 unlink (fullDstFileName);
1780 rename (scratchFileName, fullDstFileName);
1782 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1783 q = strrchr (buffer, '.');
1786 /* no extension: append new extensions */
1787 q = strlen (buffer) + buffer;
1791 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1793 strncatz(buffer, ".map", sizeof(buffer));
1794 if (strcmp (scratchFileName, buffer))
1796 rename (scratchFileName, buffer);
1798 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1800 strncatz(buffer, ".mem", sizeof(buffer));
1801 if (strcmp (scratchFileName, buffer))
1803 rename (scratchFileName, buffer);
1807 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1809 strncatz(buffer, ".cdb", sizeof(buffer));
1810 if (strcmp (scratchFileName, buffer))
1812 rename (scratchFileName, buffer);
1813 /* and the OMF file without extension: */
1816 if (strcmp (scratchFileName, buffer))
1818 rename (scratchFileName, buffer);
1827 /*-----------------------------------------------------------------*/
1828 /* assemble - spawns the assembler with arguments */
1829 /*-----------------------------------------------------------------*/
1831 assemble (char **envp)
1833 /* build assembler output filename */
1835 /* -o option overrides default name? */
1836 if (options.cc_only && fullDstFileName) {
1837 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1839 /* the assembled file gets the name of the first modul */
1840 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1841 strncatz (scratchFileName, port->linker.rel_ext,
1842 sizeof(scratchFileName));
1845 if (port->assembler.do_assemble) {
1846 port->assembler.do_assemble(asmOptionsSet);
1848 } else if (port->assembler.cmd) {
1849 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1850 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1853 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1856 if (my_system (buffer)) {
1857 /* either system() or the assembler itself has reported an error
1858 perror ("Cannot exec assembler");
1862 /* TODO: most assembler don't have a -o parameter */
1863 /* -o option overrides default name? */
1864 if (options.cc_only && fullDstFileName) {
1865 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1866 strncatz (scratchFileName,
1867 port->linker.rel_ext,
1868 sizeof(scratchFileName));
1869 if (strcmp (scratchFileName, fullDstFileName))
1870 unlink (fullDstFileName);
1871 rename (scratchFileName, fullDstFileName);
1875 /*-----------------------------------------------------------------*/
1876 /* preProcess - spawns the preprocessor with arguments */
1877 /*-----------------------------------------------------------------*/
1879 preProcess (char **envp)
1888 set *inclList = NULL;
1890 /* if using external stack define the macro */
1891 if (options.useXstack)
1892 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1894 /* set the macro for stack autos */
1895 if (options.stackAuto)
1896 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1898 /* set the macro for stack autos */
1899 if (options.stack10bit)
1900 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1902 /* set the macro for no overlay */
1903 if (options.noOverlay)
1904 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1906 /* set the macro for large model */
1907 switch (options.model)
1910 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1913 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1916 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1919 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1922 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1925 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1928 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1932 /* add port (processor information to processor */
1933 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1934 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1936 /* standard include path */
1937 if (!options.nostdinc) {
1938 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1939 mergeSets(&preArgvSet, inclList);
1942 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1943 Safe_free((void *)s);
1944 if (inclList != NULL)
1945 deleteSet(&inclList);
1947 if (preProcOnly && fullDstFileName)
1949 /* -E and -o given */
1950 setMainValue ("cppoutfilename", fullDstFileName);
1954 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1955 setMainValue ("cppoutfilename", NULL);
1958 if (options.verbose)
1959 printf ("sdcc: Calling preprocessor...\n");
1961 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1964 if (my_system (buffer)) {
1971 yyin = my_popen (buffer);
1973 perror ("Preproc file not found");
1976 addSetHead (&pipeSet, yyin);
1984 setBinPaths(const char *argv0)
1992 * 1. - $SDCCDIR/PREFIX2BIN_DIR
1993 * 2. - path(argv[0])
1997 /* do it in reverse mode, so that addSetHead() can be used
1998 instead of slower addSet() */
2000 if ((p = getBinPath(argv0)) != NULL)
2001 addSetHead(&binPathSet, Safe_strdup(p));
2003 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2004 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2005 addSetHead(&binPathSet, Safe_strdup(buf));
2009 if (options.printSearchDirs) {
2010 printf("programs:\n");
2011 fputStrSet(stdout, binPathSet);
2016 /* Set system include path */
2018 setIncludePath(void)
2026 * 1. - $SDCC_INCLUDE/target
2027 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2028 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2029 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2030 * 5. - $SDCC_INCLUDE
2031 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2032 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2033 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2036 if (options.nostdinc)
2039 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2040 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2041 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2042 mergeSets(&includeDirsSet, tempSet);
2044 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2045 addSetHead(&includeDirsSet, p);
2048 if (options.printSearchDirs) {
2049 printf("includedir:\n");
2050 fputStrSet(stdout, includeDirsSet);
2055 /* Set system lib path */
2065 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2066 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2067 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2070 if (options.nostdlib)
2073 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2075 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2076 addSetHead(&libDirsSet, p);
2079 if (options.printSearchDirs) {
2080 printf("libdir:\n");
2081 fputStrSet(stdout, libDirsSet);
2088 setDataPaths(const char *argv0)
2096 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2097 * 2. - path(argv[0])/BIN2DATA_DIR
2098 * 3. - DATADIR (only on *nix)
2101 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2102 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2103 addSet(&dataDirsSet, Safe_strdup(buf));
2106 if ((p = getBinPath(argv0)) != NULL) {
2107 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2108 addSet(&dataDirsSet, Safe_strdup(buf));
2112 if (peekSet(dataDirsSet) == NULL) {
2113 /* this should never happen... */
2114 wassertl(0, "Can't get binary path");
2117 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2121 if (options.printSearchDirs) {
2122 printf("datadir:\n");
2123 fputStrSet(stdout, dataDirsSet);
2134 populateMainValues (_baseValues);
2135 setMainValue ("port", port->target);
2136 setMainValue ("objext", port->linker.rel_ext);
2137 setMainValue ("asmext", port->assembler.file_ext);
2139 setMainValue ("dstfilename", dstFileName);
2140 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2142 if (options.cc_only && fullDstFileName)
2143 /* compile + assemble and -o given: -o specifies name of object file */
2145 setMainValue ("objdstfilename", fullDstFileName);
2149 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2151 if (fullDstFileName)
2152 /* if we're linking, -o gives the final file name */
2154 setMainValue ("linkdstfilename", fullDstFileName);
2158 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2163 static void doPrintSearchDirs(void)
2165 printf("programs:\n");
2166 fputStrSet(stdout, binPathSet);
2168 printf("datadir:\n");
2169 fputStrSet(stdout, dataDirsSet);
2171 printf("includedir:\n");
2172 fputStrSet(stdout, includeDirsSet);
2174 printf("libdir:\n");
2175 fputStrSet(stdout, libDirsSet);
2176 fputStrSet(stdout, libPathsSet);
2181 sig_handler (int signal)
2188 sig_string = "SIGABRT";
2191 sig_string = "SIGTERM";
2194 sig_string = "SIGINT";
2197 sig_string = "SIGSEGV";
2200 sig_string = "Unknown?";
2203 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2209 * initialises and calls the parser
2213 main (int argc, char **argv, char **envp)
2215 /* turn all optimizations off by default */
2216 memset (&optimize, 0, sizeof (struct optimize));
2218 /*printVersionInfo (); */
2221 fprintf (stderr, "Build error: no ports are enabled.\n");
2225 /* install atexit handler */
2226 atexit(rm_tmpfiles);
2228 /* install signal handler;
2229 it's only purpuse is to call exit() to remove temp files */
2230 if (!getenv("SDCC_LEAVE_SIGNALS"))
2232 signal (SIGABRT, sig_handler);
2233 signal (SIGTERM, sig_handler);
2234 signal (SIGINT , sig_handler);
2235 signal (SIGSEGV, sig_handler);
2238 /* Before parsing the command line options, do a
2239 * search for the port and processor and initialize
2240 * them if they're found. (We can't gurantee that these
2241 * will be the first options specified).
2244 _findPort (argc, argv);
2247 if (strcmp(port->target, "mcs51") == 0) {
2248 printf("DS390 jammed in A\n");
2254 _findProcessor (argc, argv);
2256 /* Initalise the port. */
2260 setDefaultOptions ();
2263 options.model = MODEL_SMALL;
2264 options.stack10bit=0;
2267 parseCmdLine (argc, argv);
2271 setBinPaths(argv[0]);
2272 setDataPaths(argv[0]);
2277 if(options.printSearchDirs)
2278 doPrintSearchDirs();
2280 /* if no input then printUsage & exit */
2281 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2282 if (!options.printSearchDirs)
2288 /* initMem() is expensive, but
2289 initMem() must called before port->finaliseOptions ().
2290 And the z80 port needs port->finaliseOptions(),
2291 even if we're only linking. */
2293 port->finaliseOptions ();
2295 if (fullSrcFileName || options.c1mode)
2305 if (options.verbose)
2306 printf ("sdcc: Generating code...\n");
2312 deleteSetItem(&pipeSet, yyin);
2318 if (port->general.do_glue != NULL)
2319 (*port->general.do_glue)();
2322 /* this shouldn't happen */
2324 /* in case of NDEBUG */
2332 if (!options.c1mode && !noAssemble)
2334 if (options.verbose)
2335 printf ("sdcc: Calling assembler...\n");
2341 if (options.debug && debugFile)
2342 debugFile->closeFile();
2344 if (!options.cc_only &&
2348 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2350 if (port->linker.do_link)
2351 port->linker.do_link ();