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 /* mcs51 has an assembly coded float library that's always reentrant */
1355 if (TARGET_IS_MCS51)
1357 options.float_rent++;
1360 /* set up external stack location if not explicitly specified */
1361 if (!options.xstack_loc)
1362 options.xstack_loc = options.xdata_loc;
1364 /* if debug option is set then open the cdbFile */
1365 if (options.debug && fullSrcFileName)
1367 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1368 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1369 if(debugFile->openFile(scratchFileName))
1370 debugFile->writeModule(moduleName);
1372 werror (E_FILE_OPEN_ERR, scratchFileName);
1374 MSVC_style(options.vc_err_style);
1375 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1380 /*-----------------------------------------------------------------*/
1381 /* linkEdit : - calls the linkage editor with options */
1382 /*-----------------------------------------------------------------*/
1384 linkEdit (char **envp)
1392 if(port->linker.needLinkerScript)
1396 switch (options.out_fmt)
1399 out_fmt = 'i'; /* Intel hex */
1402 out_fmt = 's'; /* Motorola S19 */
1405 out_fmt = 't'; /* Elf */
1411 /* first we need to create the <filename>.lnk file */
1412 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1413 "%s.lnk", dstFileName);
1414 if (!(lnkfile = fopen (scratchFileName, "w")))
1416 werror (E_FILE_OPEN_ERR, scratchFileName);
1420 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1422 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1423 out_fmt, dstFileName);
1425 else /*For all the other ports. Including pics???*/
1427 fprintf (lnkfile, "-myux%c\n", out_fmt);
1428 if(!options.no_pack_iram)
1429 fprintf (lnkfile, "-Y\n");
1432 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1434 /* if iram size specified */
1435 if (options.iram_size)
1436 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1438 /* if stack size specified*/
1439 if(options.stack_size)
1440 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1442 /* if xram size specified */
1443 if (options.xram_size_set)
1444 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1446 /* if code size specified */
1447 if (options.code_size)
1448 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1451 fprintf (lnkfile, "-z\n");
1454 #define WRITE_SEG_LOC(N, L) \
1455 segName = Safe_strdup(N); \
1456 c = strtok(segName, " \t"); \
1457 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1458 if (segName) { Safe_free(segName); }
1460 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1463 /* code segment start */
1464 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1466 /* data segment start. If zero, the linker chooses
1467 the best place for data */
1468 if(options.data_loc)
1470 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1473 /* xdata segment start. If zero, the linker chooses
1474 the best place for xdata */
1475 if(options.xdata_loc)
1477 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1483 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1486 /* bit segment start */
1487 WRITE_SEG_LOC (BIT_NAME, 0);
1490 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1493 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1496 else /*For the z80, gbz80*/
1498 WRITE_SEG_LOC ("_CODE", options.code_loc);
1499 WRITE_SEG_LOC ("_DATA", options.data_loc);
1502 /* If the port has any special linker area declarations, get 'em */
1503 if (port->extraAreas.genExtraAreaLinkOptions)
1505 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1508 /* add the extra linker options */
1509 fputStrSet(lnkfile, linkOptionsSet);
1511 /* command line defined library paths if specified */
1512 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1513 fprintf (lnkfile, "-k %s\n", s);
1515 /* standard library path */
1516 if (!options.nostdlib)
1518 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1520 switch (options.model)
1530 if (TARGET_IS_DS390)
1534 else if (TARGET_IS_DS400)
1541 "Add support for your FLAT24 target in %s @ line %d\n",
1542 __FILE__, __LINE__);
1550 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1555 else /*for the z80, gbz80*/
1559 else if (TARGET_IS_Z80)
1564 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1565 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1568 /* command line defined library files if specified */
1569 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1570 fprintf (lnkfile, "-l %s\n", s);
1572 /* standard library files */
1573 if (!options.nostdlib)
1575 #if !OPT_DISABLE_DS390
1576 if (options.model == MODEL_FLAT24)
1578 if (TARGET_IS_DS390)
1580 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1582 else if (TARGET_IS_DS400)
1584 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1589 "Add support for your FLAT24 target in %s @ line %d\n",
1590 __FILE__, __LINE__);
1596 #if !OPT_DISABLE_XA51
1598 if (options.model == MODEL_PAGE0)
1600 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1604 if (TARGET_IS_MCS51)
1606 fprintf (lnkfile, "-l mcs51\n");
1608 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1609 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1610 { /*Why the z80 port is not using the standard libraries?*/
1611 fprintf (lnkfile, "-l %s\n", STD_LIB);
1612 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1613 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1614 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1616 else if (TARGET_IS_HC08)
1618 fprintf (lnkfile, "-l hc08\n");
1620 else if (TARGET_IS_Z80)
1622 fprintf (lnkfile, "-l z80\n");
1624 else if (TARGET_IS_GBZ80)
1626 fprintf (lnkfile, "-l gbz80\n");
1630 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1631 It is very important for this file to be first on the linking proccess
1632 so the areas are set in the correct order, expecially _GSINIT*/
1633 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1634 !options.no_std_crt0) /*For the z80, gbz80*/
1636 char crt0path[PATH_MAX];
1640 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1641 tempSet = appendStrSet(libDirsSet, NULL, c);
1642 mergeSets(&tempSet, libPathsSet);
1644 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1646 sprintf (crt0path, "%s%scrt0.o",
1647 s, DIR_SEPARATOR_STRING);
1649 crt0fp=fopen(crt0path, "r");
1650 if(crt0fp!=NULL)/*Found it!*/
1655 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1656 windows paths, so convert them to the CYGWIN format*/
1657 char posix_path[PATH_MAX];
1658 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1659 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1660 strcpy(crt0path, posix_path);
1663 fprintf (lnkfile, "%s\n", crt0path);
1667 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1670 /* put in the object files */
1671 if (fullSrcFileName)
1672 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1674 fputStrSet(lnkfile, relFilesSet);
1676 fprintf (lnkfile, "\n-e\n");
1678 } /* if(port->linker.needLinkerScript) */
1680 if (options.verbose)
1681 printf ("sdcc: Calling linker...\n");
1683 /* build linker output filename */
1685 /* -o option overrides default name? */
1686 if (fullDstFileName)
1688 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1692 /* the linked file gets the name of the first modul */
1693 if (fullSrcFileName)
1695 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1699 s = peekSet(relFilesSet);
1703 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1704 /* strip ".rel" extension */
1705 *strrchr (scratchFileName, '.') = '\0';
1707 strncatz (scratchFileName,
1708 options.out_fmt ? ".S19" : ".ihx",
1709 sizeof(scratchFileName));
1712 if (port->linker.cmd)
1714 char buffer2[PATH_MAX];
1715 char buffer3[PATH_MAX];
1716 set *tempSet=NULL, *libSet=NULL;
1718 strcpy(buffer3, dstFileName);
1719 if(TARGET_IS_PIC16) {
1721 /* use $l to set the linker include directories */
1722 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1723 mergeSets(&linkOptionsSet, tempSet);
1725 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1726 mergeSets(&linkOptionsSet, tempSet);
1728 /* use $3 for libraries from command line --> libSet */
1729 mergeSets(&libSet, libFilesSet);
1731 tempSet = appendStrSet(relFilesSet, "", "");
1732 mergeSets(&libSet, tempSet);
1733 // libSet = reverseSet(libSet);
1735 if(fullSrcFileName) {
1736 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1737 /* if it didn't work, revert to old behaviour */
1738 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1739 strcat(buffer3, port->linker.rel_ext);
1741 } else strcpy(buffer3, "");
1744 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1746 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1750 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1753 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1755 system_ret = my_system (buffer);
1756 /* TODO: most linker don't have a -o parameter */
1757 /* -o option overrides default name? */
1758 if (fullDstFileName)
1761 /* the linked file gets the name of the first modul */
1762 if (fullSrcFileName)
1764 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1765 p = strlen (scratchFileName) + scratchFileName;
1769 s = peekSet(relFilesSet);
1773 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1774 /* strip ".rel" extension */
1775 p = strrchr (scratchFileName, '.');
1781 strncatz (scratchFileName,
1782 options.out_fmt ? ".S19" : ".ihx",
1783 sizeof(scratchFileName));
1784 if (strcmp (fullDstFileName, scratchFileName))
1785 unlink (fullDstFileName);
1786 rename (scratchFileName, fullDstFileName);
1788 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1789 q = strrchr (buffer, '.');
1792 /* no extension: append new extensions */
1793 q = strlen (buffer) + buffer;
1797 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1799 strncatz(buffer, ".map", sizeof(buffer));
1800 if (strcmp (scratchFileName, buffer))
1802 rename (scratchFileName, buffer);
1804 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1806 strncatz(buffer, ".mem", sizeof(buffer));
1807 if (strcmp (scratchFileName, buffer))
1809 rename (scratchFileName, buffer);
1813 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1815 strncatz(buffer, ".cdb", sizeof(buffer));
1816 if (strcmp (scratchFileName, buffer))
1818 rename (scratchFileName, buffer);
1819 /* and the OMF file without extension: */
1822 if (strcmp (scratchFileName, buffer))
1824 rename (scratchFileName, buffer);
1833 /*-----------------------------------------------------------------*/
1834 /* assemble - spawns the assembler with arguments */
1835 /*-----------------------------------------------------------------*/
1837 assemble (char **envp)
1839 /* build assembler output filename */
1841 /* -o option overrides default name? */
1842 if (options.cc_only && fullDstFileName) {
1843 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1845 /* the assembled file gets the name of the first modul */
1846 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1847 strncatz (scratchFileName, port->linker.rel_ext,
1848 sizeof(scratchFileName));
1851 if (port->assembler.do_assemble) {
1852 port->assembler.do_assemble(asmOptionsSet);
1854 } else if (port->assembler.cmd) {
1855 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1856 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1859 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1862 if (my_system (buffer)) {
1863 /* either system() or the assembler itself has reported an error
1864 perror ("Cannot exec assembler");
1868 /* TODO: most assembler don't have a -o parameter */
1869 /* -o option overrides default name? */
1870 if (options.cc_only && fullDstFileName) {
1871 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1872 strncatz (scratchFileName,
1873 port->linker.rel_ext,
1874 sizeof(scratchFileName));
1875 if (strcmp (scratchFileName, fullDstFileName))
1876 unlink (fullDstFileName);
1877 rename (scratchFileName, fullDstFileName);
1881 /*-----------------------------------------------------------------*/
1882 /* preProcess - spawns the preprocessor with arguments */
1883 /*-----------------------------------------------------------------*/
1885 preProcess (char **envp)
1894 set *inclList = NULL;
1896 /* if using external stack define the macro */
1897 if (options.useXstack)
1898 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1900 /* set the macro for stack autos */
1901 if (options.stackAuto)
1902 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1904 /* set the macro for stack autos */
1905 if (options.stack10bit)
1906 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1908 /* set the macro for no overlay */
1909 if (options.noOverlay)
1910 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1912 /* set the macro for large model */
1913 switch (options.model)
1916 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1919 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1922 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1925 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1928 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1931 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1934 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1938 /* add port (processor information to processor */
1939 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1940 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1942 /* standard include path */
1943 if (!options.nostdinc) {
1944 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1945 mergeSets(&preArgvSet, inclList);
1948 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1949 Safe_free((void *)s);
1950 if (inclList != NULL)
1951 deleteSet(&inclList);
1953 if (preProcOnly && fullDstFileName)
1955 /* -E and -o given */
1956 setMainValue ("cppoutfilename", fullDstFileName);
1960 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1961 setMainValue ("cppoutfilename", NULL);
1964 if (options.verbose)
1965 printf ("sdcc: Calling preprocessor...\n");
1967 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1970 if (my_system (buffer)) {
1977 yyin = my_popen (buffer);
1979 perror ("Preproc file not found");
1982 addSetHead (&pipeSet, yyin);
1990 setBinPaths(const char *argv0)
1998 * 1. - $SDCCDIR/PREFIX2BIN_DIR
1999 * 2. - path(argv[0])
2003 /* do it in reverse mode, so that addSetHead() can be used
2004 instead of slower addSet() */
2006 if ((p = getBinPath(argv0)) != NULL)
2007 addSetHead(&binPathSet, Safe_strdup(p));
2009 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2010 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2011 addSetHead(&binPathSet, Safe_strdup(buf));
2015 if (options.printSearchDirs) {
2016 printf("programs:\n");
2017 fputStrSet(stdout, binPathSet);
2022 /* Set system include path */
2024 setIncludePath(void)
2032 * 1. - $SDCC_INCLUDE/target
2033 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2034 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2035 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2036 * 5. - $SDCC_INCLUDE
2037 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2038 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2039 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2042 if (options.nostdinc)
2045 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2046 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2047 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2048 mergeSets(&includeDirsSet, tempSet);
2050 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2051 addSetHead(&includeDirsSet, p);
2054 if (options.printSearchDirs) {
2055 printf("includedir:\n");
2056 fputStrSet(stdout, includeDirsSet);
2061 /* Set system lib path */
2071 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2072 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2073 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2076 if (options.nostdlib)
2079 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2081 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2082 addSetHead(&libDirsSet, p);
2085 if (options.printSearchDirs) {
2086 printf("libdir:\n");
2087 fputStrSet(stdout, libDirsSet);
2094 setDataPaths(const char *argv0)
2102 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2103 * 2. - path(argv[0])/BIN2DATA_DIR
2104 * 3. - DATADIR (only on *nix)
2107 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2108 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2109 addSet(&dataDirsSet, Safe_strdup(buf));
2112 if ((p = getBinPath(argv0)) != NULL) {
2113 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2114 addSet(&dataDirsSet, Safe_strdup(buf));
2118 if (peekSet(dataDirsSet) == NULL) {
2119 /* this should never happen... */
2120 wassertl(0, "Can't get binary path");
2123 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2127 if (options.printSearchDirs) {
2128 printf("datadir:\n");
2129 fputStrSet(stdout, dataDirsSet);
2140 populateMainValues (_baseValues);
2141 setMainValue ("port", port->target);
2142 setMainValue ("objext", port->linker.rel_ext);
2143 setMainValue ("asmext", port->assembler.file_ext);
2145 setMainValue ("dstfilename", dstFileName);
2146 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2148 if (options.cc_only && fullDstFileName)
2149 /* compile + assemble and -o given: -o specifies name of object file */
2151 setMainValue ("objdstfilename", fullDstFileName);
2155 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2157 if (fullDstFileName)
2158 /* if we're linking, -o gives the final file name */
2160 setMainValue ("linkdstfilename", fullDstFileName);
2164 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2169 static void doPrintSearchDirs(void)
2171 printf("programs:\n");
2172 fputStrSet(stdout, binPathSet);
2174 printf("datadir:\n");
2175 fputStrSet(stdout, dataDirsSet);
2177 printf("includedir:\n");
2178 fputStrSet(stdout, includeDirsSet);
2180 printf("libdir:\n");
2181 fputStrSet(stdout, libDirsSet);
2182 fputStrSet(stdout, libPathsSet);
2187 sig_handler (int signal)
2194 sig_string = "SIGABRT";
2197 sig_string = "SIGTERM";
2200 sig_string = "SIGINT";
2203 sig_string = "SIGSEGV";
2206 sig_string = "Unknown?";
2209 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2215 * initialises and calls the parser
2219 main (int argc, char **argv, char **envp)
2221 /* turn all optimizations off by default */
2222 memset (&optimize, 0, sizeof (struct optimize));
2224 /*printVersionInfo (); */
2227 fprintf (stderr, "Build error: no ports are enabled.\n");
2231 /* install atexit handler */
2232 atexit(rm_tmpfiles);
2234 /* install signal handler;
2235 it's only purpuse is to call exit() to remove temp files */
2236 if (!getenv("SDCC_LEAVE_SIGNALS"))
2238 signal (SIGABRT, sig_handler);
2239 signal (SIGTERM, sig_handler);
2240 signal (SIGINT , sig_handler);
2241 signal (SIGSEGV, sig_handler);
2244 /* Before parsing the command line options, do a
2245 * search for the port and processor and initialize
2246 * them if they're found. (We can't gurantee that these
2247 * will be the first options specified).
2250 _findPort (argc, argv);
2253 if (strcmp(port->target, "mcs51") == 0) {
2254 printf("DS390 jammed in A\n");
2260 _findProcessor (argc, argv);
2262 /* Initalise the port. */
2266 setDefaultOptions ();
2269 options.model = MODEL_SMALL;
2270 options.stack10bit=0;
2273 parseCmdLine (argc, argv);
2277 setBinPaths(argv[0]);
2278 setDataPaths(argv[0]);
2283 if(options.printSearchDirs)
2284 doPrintSearchDirs();
2286 /* if no input then printUsage & exit */
2287 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2288 if (!options.printSearchDirs)
2294 /* initMem() is expensive, but
2295 initMem() must called before port->finaliseOptions ().
2296 And the z80 port needs port->finaliseOptions(),
2297 even if we're only linking. */
2299 port->finaliseOptions ();
2301 if (fullSrcFileName || options.c1mode)
2311 if (options.verbose)
2312 printf ("sdcc: Generating code...\n");
2318 deleteSetItem(&pipeSet, yyin);
2324 if (port->general.do_glue != NULL)
2325 (*port->general.do_glue)();
2328 /* this shouldn't happen */
2330 /* in case of NDEBUG */
2338 if (!options.c1mode && !noAssemble)
2340 if (options.verbose)
2341 printf ("sdcc: Calling assembler...\n");
2347 if (options.debug && debugFile)
2348 debugFile->closeFile();
2350 if (!options.cc_only &&
2354 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2356 if (port->linker.do_link)
2357 port->linker.do_link ();