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"
138 #define OPTION_STD_C89 "--std-c89"
139 #define OPTION_STD_C99 "--std-c99"
140 #define OPTION_STD_SDCC89 "--std-sdcc89"
141 #define OPTION_STD_SDCC99 "--std-sdcc99"
145 { 0, NULL, NULL, "General options" },
146 { 0, "--help", NULL, "Display this help" },
147 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
148 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
149 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
150 { 'd', NULL, NULL, NULL },
151 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
152 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
153 { 'A', NULL, NULL, NULL },
154 { 'U', NULL, NULL, NULL },
155 { 'C', NULL, NULL, "Preprocessor option" },
156 { 'M', NULL, NULL, "Preprocessor option" },
157 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
158 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
159 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
160 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
161 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
162 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
163 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
164 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
165 { 0, OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
166 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
167 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
168 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
169 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
170 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
171 { 0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions" },
172 { 0, OPTION_STD_C89, NULL, "Use C89 standard only" },
173 { 0, OPTION_STD_SDCC89, NULL, "Use C89 standard with SDCC extensions (default)" },
174 { 0, OPTION_STD_C99, NULL, "Use C99 standard only (incomplete)" },
175 { 0, OPTION_STD_SDCC99, NULL, "Use C99 standard with SDCC extensions (incomplete)" },
177 { 0, NULL, NULL, "Code generation options"},
178 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
179 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
180 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
181 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
182 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
183 #if !OPT_DISABLE_DS390
184 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
185 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
186 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
188 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
189 { 0, "--xstack", &options.useXstack, "Use external stack" },
190 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
191 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
192 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
193 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
194 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
195 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
196 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
197 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
198 #if !OPT_DISABLE_DS390
199 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
201 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
202 #if !OPT_DISABLE_TININative
203 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
205 #if !OPT_DISABLE_DS390
206 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
208 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
209 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
211 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
212 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
213 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
214 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
215 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
217 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" },
219 { 0, NULL, NULL, "Optimization options"},
220 { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" },
221 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
222 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
223 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
224 { 0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction" },
225 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
226 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
227 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
228 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
229 { 0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly" },
230 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peephole file" },
231 { 0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size" },
232 { 0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed" },
234 { 0, NULL, NULL, "Internal debugging options"},
235 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
236 { 0, "--dumpgcse", &options.dump_gcse, NULL },
237 { 0, "--dumploop", &options.dump_loop, NULL },
238 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
239 { 0, "--dumpliverange", &options.dump_range, NULL },
240 { 0, "--dumpregpack", &options.dump_pack, NULL },
241 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
242 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
243 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
244 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
246 { 0, NULL, NULL, "Linker options" },
247 { 'l', NULL, NULL, "Include the given library in the link" },
248 { 'L', NULL, NULL, "Add the next field to the library search path" },
249 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
250 { 0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format" },
251 { 0, OPTION_OUT_FMT_S19, NULL, "Output in S19 hex format" },
252 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
253 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
254 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
255 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
256 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
257 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
258 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
259 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
260 { 0, OPTION_IDATA_LOC, NULL, NULL },
261 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
262 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
263 { 0, OPTION_PACK_IRAM, NULL,"MCS51/DS390 - Tells the linker to pack variables in internal ram (default)"},
264 { 0, OPTION_NO_PACK_IRAM, &options.no_pack_iram,"MCS51/DS390 - Tells the linker not to pack variables in internal ram"},
271 /** Table of all unsupported options and help text to display when one
275 /** shortOpt as in OPTIONS. */
277 /** longOpt as in OPTIONS. */
279 /** Message to display inside W_UNSUPPORTED_OPT when this option
284 static const UNSUPPORTEDOPT
285 unsupportedOptTable[] = {
286 { 'X', NULL, "use --xstack-loc instead" },
287 { 'x', NULL, "use --xstack instead" },
288 { 'i', NULL, "use --idata-loc instead" },
289 { 'r', NULL, "use --xdata-loc instead" },
290 { 's', NULL, "use --code-loc instead" },
291 { 'Y', NULL, "use -I instead" }
294 /** List of all default constant macros.
296 static const char *_baseValues[] = {
299 /* Path seperator character */
300 "sep", DIR_SEPARATOR_STRING,
304 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
308 static PORT *_ports[] =
310 #if !OPT_DISABLE_MCS51
313 #if !OPT_DISABLE_GBZ80
322 #if !OPT_DISABLE_DS390
325 #if !OPT_DISABLE_PIC16
331 #if !OPT_DISABLE_TININative
334 #if !OPT_DISABLE_XA51
337 #if !OPT_DISABLE_DS400
340 #if !OPT_DISABLE_HC08
345 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
347 /** Sets the port to the one given by the command line option.
348 @param The name minus the option (eg 'mcs51')
349 @return 0 on success.
352 _setPort (const char *name)
355 for (i = 0; i < NUM_PORTS; i++)
357 if (!strcmp (_ports[i]->target, name))
363 /* Error - didnt find */
364 werror (E_UNKNOWN_TARGET, name);
368 /* Override the default processor with the one specified
369 * on the command line */
371 _setProcessor (char *_processor)
373 port->processor = _processor;
374 fprintf(stderr,"Processor: %s\n",_processor);
378 _validatePorts (void)
381 for (i = 0; i < NUM_PORTS; i++)
383 if (_ports[i]->magic != PORT_MAGIC)
385 /* Uncomment this line to debug which port is causing the problem
386 * (the target name is close to the beginning of the port struct
387 * and probably can be accessed just fine). */
388 fprintf(stderr,"%s :",_ports[i]->target);
389 wassertl (0, "Port definition structure is incomplete");
394 /* search through the command line options for the port */
396 _findPort (int argc, char **argv)
402 if (!strncmp (*argv, "-m", 2))
404 _setPort (*argv + 2);
410 /* Use the first in the list */
414 /* search through the command line options for the processor */
416 _findProcessor (int argc, char **argv)
420 if (!strncmp (*argv, "-p", 2))
422 _setProcessor (*argv + 2);
428 /* no error if processor was not specified. */
431 /*-----------------------------------------------------------------*/
432 /* printVersionInfo - prints the version info */
433 /*-----------------------------------------------------------------*/
435 printVersionInfo (void)
441 for (i = 0; i < NUM_PORTS; i++)
442 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
444 fprintf (stderr, " " SDCC_VERSION_STR
445 #ifdef SDCC_SUB_VERSION_STR
446 "/" SDCC_SUB_VERSION_STR
448 " #%s (" __DATE__ ")"
451 #elif defined __MINGW32__
453 #elif defined __DJGPP__
455 #elif defined(_MSC_VER)
457 #elif defined(__BORLANDC__)
462 , getBuildNumber() );
466 printOptions(const OPTION *optionsTable)
470 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
471 || optionsTable[i].help != NULL;
474 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
475 && optionsTable[i].help)
477 fprintf (stdout, "\n%s:\n", optionsTable[i].help);
481 fprintf(stdout, " %c%c %-20s %s\n",
482 optionsTable[i].shortOpt !=0 ? '-' : ' ',
483 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
484 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
485 optionsTable[i].help != NULL ? optionsTable[i].help : ""
491 /*-----------------------------------------------------------------*/
492 /* printUsage - prints command line syntax */
493 /*-----------------------------------------------------------------*/
500 "Usage : sdcc [options] filename\n"
504 printOptions(optionsTable);
506 for (i = 0; i < NUM_PORTS; i++)
508 if (_ports[i]->poptions != NULL)
510 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
511 printOptions (_ports[i]->poptions);
518 /*-----------------------------------------------------------------*/
519 /* setParseWithComma - separates string with comma to a set */
520 /*-----------------------------------------------------------------*/
522 setParseWithComma (set **dest, char *src)
527 /* skip the initial white spaces */
528 while (isspace(*src))
531 /* skip the trailing white spaces */
532 length = strlen(src);
533 while (length && isspace(src[length-1]))
534 src[--length] = '\0';
536 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
537 addSet(dest, Safe_strdup(p));
540 /*-----------------------------------------------------------------*/
541 /* setDefaultOptions - sets the default options */
542 /*-----------------------------------------------------------------*/
544 setDefaultOptions (void)
546 /* first the options part */
547 options.stack_loc = 0; /* stack pointer initialised to 0 */
548 options.xstack_loc = 0; /* xternal stack starts at 0 */
549 options.code_loc = 0; /* code starts at 0 */
550 options.data_loc = 0; /* JCF: By default let the linker locate data */
551 options.xdata_loc = 0;
552 options.idata_loc = 0x80;
554 options.model = port->general.default_model;
555 options.nostdlib = 0;
556 options.nostdinc = 0;
558 options.shortis8bits = 0;
559 options.std_sdcc = 1; /* enable SDCC language extensions */
560 options.std_c99 = 0; /* default to C89 until more C99 support */
562 options.stack10bit=0;
564 /* now for the optimizations */
565 /* turn on the everything */
566 optimize.global_cse = 1;
571 optimize.loopInvariant = 1;
572 optimize.loopInduction = 1;
574 /* now for the ports */
575 port->setDefaultOptions ();
578 /*-----------------------------------------------------------------*/
579 /* processFile - determines the type of file from the extension */
580 /*-----------------------------------------------------------------*/
582 processFile (char *s)
586 /* get the file extension */
587 fext = s + strlen (s);
588 while ((fext != s) && *fext != '.')
591 /* now if no '.' then we don't know what the file type is
592 so give a warning and return */
595 werror (W_UNKNOWN_FEXT, s);
599 /* otherwise depending on the file type */
600 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
602 /* source file name : not if we already have a
606 werror (W_TOO_MANY_SRC, s);
610 /* the only source file */
612 if (!(srcFile = fopen (fullSrcFileName, "r")))
614 werror (E_FILE_OPEN_ERR, s);
618 /* copy the file name into the buffer */
619 strncpyz (buffer, s, sizeof(buffer));
621 /* get rid of the "."-extension */
623 /* is there a dot at all? */
624 if (strrchr (buffer, '.') &&
625 /* is the dot in the filename, not in the path? */
626 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
628 *strrchr (buffer, '.') = '\0';
631 /* get rid of any path information
632 for the module name; */
633 fext = buffer + strlen (buffer);
635 /* do this by going backwards till we
636 get '\' or ':' or start of buffer */
637 while (fext != buffer &&
638 *(fext - 1) != DIR_SEPARATOR_CHAR &&
644 /* do this by going backwards till we
645 get '/' or start of buffer */
646 while (fext != buffer &&
647 *(fext - 1) != DIR_SEPARATOR_CHAR)
652 moduleNameBase = Safe_strdup ( fext );
653 moduleName = Safe_strdup ( fext );
655 for (fext = moduleName; *fext; fext++)
656 if (!isalnum (*fext))
661 /* if the extention is type .rel or .r or .REL or .R
662 addtional object file will be passed to the linker */
663 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
664 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
665 strcmp (fext, port->linker.rel_ext) == 0)
667 addSet(&relFilesSet, Safe_strdup(s));
671 /* if .lib or .LIB */
672 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
674 addSet(&libFilesSet, Safe_strdup(s));
678 werror (W_UNKNOWN_FEXT, s);
683 _setModel (int model, const char *sz)
685 if (port->general.supported_models & model)
686 options.model = model;
688 werror (W_UNSUPPORTED_MODEL, sz, port->target);
691 /** Gets the string argument to this option. If the option is '--opt'
692 then for input of '--optxyz' or '--opt xyz' returns xyz.
695 getStringArg(const char *szStart, char **argv, int *pi, int argc)
697 if (argv[*pi][strlen(szStart)])
699 return &argv[*pi][strlen(szStart)];
706 werror (E_ARGUMENT_MISSING, szStart);
707 /* Die here rather than checking for errors later. */
717 /** Gets the integer argument to this option using the same rules as
721 getIntArg(const char *szStart, char **argv, int *pi, int argc)
723 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
727 verifyShortOption(const char *opt)
729 if (strlen(opt) != 2)
731 werror (W_EXCESS_SHORT_OPTIONS, opt);
736 tryHandleUnsupportedOpt(char **argv, int *pi)
738 if (argv[*pi][0] == '-')
740 const char *longOpt = "";
744 if (argv[*pi][1] == '-')
751 shortOpt = argv[*pi][1];
753 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
755 if (unsupportedOptTable[i].shortOpt == shortOpt ||
756 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
757 /* Found an unsupported opt. */
759 SNPRINTF(buffer, sizeof(buffer),
761 longOpt ? longOpt : "",
762 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
763 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
767 /* Didn't find in the table */
772 /* Not an option, so can't be unsupported :) */
778 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
782 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
783 || optionsTable[i].help != NULL;
786 if (optionsTable[i].shortOpt == shortOpt ||
787 (longOpt && optionsTable[i].longOpt &&
788 strcmp(optionsTable[i].longOpt, longOpt) == 0))
791 /* If it is a flag then we can handle it here */
792 if (optionsTable[i].pparameter != NULL)
794 if (optionsTable[i].shortOpt == shortOpt)
796 verifyShortOption(argv[*pi]);
799 (*optionsTable[i].pparameter)++;
803 /* Not a flag. Handled manually later. */
808 /* Didn't find in the table */
813 tryHandleSimpleOpt(char **argv, int *pi)
815 if (argv[*pi][0] == '-')
817 const char *longOpt = "";
820 if (argv[*pi][1] == '-')
827 shortOpt = argv[*pi][1];
830 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
834 else if (port && port->poptions &&
835 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
846 /* Not an option, so can't be handled. */
851 /*-----------------------------------------------------------------*/
852 /* parseCmdLine - parses the command line and sets the options */
853 /*-----------------------------------------------------------------*/
855 parseCmdLine (int argc, char **argv)
859 /* go thru all whole command line */
860 for (i = 1; i < argc; i++)
865 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
870 if (tryHandleSimpleOpt(argv, &i) == TRUE)
876 if (argv[i][0] == '-' && argv[i][1] == '-')
878 if (strcmp (argv[i], OPTION_HELP) == 0)
884 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
886 options.stack10bit = 0;
890 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
896 if (strcmp (argv[i], OPTION_OUT_FMT_S19) == 0)
902 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
904 _setModel (MODEL_LARGE, argv[i]);
908 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
910 _setModel (MODEL_MEDIUM, argv[i]);
914 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
916 _setModel (MODEL_SMALL, argv[i]);
920 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
922 _setModel (MODEL_FLAT24, argv[i]);
926 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
928 options.dump_rassgn =
934 options.dump_raw = 1;
938 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
940 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
944 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
946 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
950 if (strcmp (argv[i], OPTION_VERSION) == 0)
957 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
959 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
963 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
965 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
969 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
971 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
975 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
977 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
981 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
983 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
987 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
989 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
993 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
995 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
996 options.xram_size_set = TRUE;
1000 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
1002 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
1006 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
1008 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
1012 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
1014 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
1018 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1020 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1024 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1026 optimize.global_cse = 0;
1030 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1032 optimize.loopInvariant = 0;
1036 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1038 optimize.label4 = 0;
1042 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1044 optimize.loopInduction = 0;
1048 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1050 optimize.codeSpeed = 1;
1051 optimize.codeSize = 0;
1055 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1057 optimize.codeSpeed = 0;
1058 optimize.codeSize = 1;
1062 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1064 options.lessPedantic = 1;
1065 setErrorLogLevel(ERROR_LEVEL_WARNING);
1069 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1071 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1072 if (w < MAX_ERROR_WARNING)
1074 setWarningDisabled(w);
1079 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1081 options.shortis8bits=1;
1085 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1087 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1091 if (strcmp (argv[i], OPTION_STD_C89) == 0)
1093 options.std_c99 = 0;
1094 options.std_sdcc = 0;
1098 if (strcmp (argv[i], OPTION_STD_C99) == 0)
1100 options.std_c99 = 1;
1101 options.std_sdcc = 0;
1105 if (strcmp (argv[i], OPTION_STD_SDCC89) == 0)
1107 options.std_c99 = 0;
1108 options.std_sdcc = 1;
1112 if (strcmp (argv[i], OPTION_STD_SDCC99) == 0)
1114 options.std_c99 = 1;
1115 options.std_sdcc = 1;
1119 if (!port->parseOption (&argc, argv, &i))
1121 werror (W_UNKNOWN_OPTION, argv[i]);
1130 /* if preceded by '-' then option */
1131 if (*argv[i] == '-')
1136 verifyShortOption(argv[i]);
1143 /* Used to select the port. But this has already been done. */
1147 /* Used to select the processor in port. But this has
1148 * already been done. */
1152 verifyShortOption(argv[i]);
1154 options.cc_only = 1;
1158 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1162 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1169 /* copy the file name into the buffer */
1170 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1172 /* point to last character */
1173 p = buffer + strlen (buffer) - 1;
1174 if (*p == DIR_SEPARATOR_CHAR)
1176 /* only output path specified */
1177 dstPath = Safe_strdup (buffer);
1178 fullDstFileName = NULL;
1182 fullDstFileName = Safe_strdup (buffer);
1184 /* get rid of the "."-extension */
1186 /* is there a dot at all? */
1187 if (strrchr (buffer, '.') &&
1188 /* is the dot in the filename, not in the path? */
1189 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1190 *strrchr (buffer, '.') = '\0';
1192 dstFileName = Safe_strdup (buffer);
1194 /* strip module name to get path */
1195 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1198 /* path with trailing / */
1200 dstPath = Safe_strdup (buffer);
1207 /* pre-processer options */
1208 if (argv[i][2] == 'p')
1210 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1212 /* linker options */
1213 else if (argv[i][2] == 'l')
1215 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1217 /* assembler options */
1218 else if (argv[i][2] == 'a')
1220 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1224 werror (W_UNKNOWN_OPTION, argv[i]);
1229 verifyShortOption(argv[i]);
1231 printVersionInfo ();
1235 /* preprocessor options */
1239 if (argv[i][2] == 'M')
1240 addSet(&preArgvSet, Safe_strdup("-MM"));
1242 addSet(&preArgvSet, Safe_strdup("-M"));
1247 addSet(&preArgvSet, Safe_strdup("-C"));
1257 char sOpt = argv[i][1];
1260 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1266 werror(E_ARGUMENT_MISSING, argv[i-1]);
1280 SNPRINTF (buffer, sizeof(buffer),
1281 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1282 addSet(&preArgvSet, Safe_strdup(buffer));
1284 addSet(&includeDirsSet, Safe_strdup(rest));
1285 addSet(&userIncDirsSet, Safe_strdup(rest));
1291 if (!port->parseOption (&argc, argv, &i))
1292 werror (W_UNKNOWN_OPTION, argv[i]);
1297 if (!port->parseOption (&argc, argv, &i))
1299 /* no option must be a filename */
1302 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1306 processFile (argv[i]);
1311 /* some sanity checks in c1 mode */
1316 if (fullSrcFileName)
1319 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1321 fullSrcFileName = NULL;
1322 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1324 werror (W_NO_FILE_ARG_IN_C1, s);
1326 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1328 werror (W_NO_FILE_ARG_IN_C1, s);
1330 deleteSet(&relFilesSet);
1331 deleteSet(&libFilesSet);
1333 if (options.cc_only || noAssemble || preProcOnly)
1335 werror (W_ILLEGAL_OPT_COMBINATION);
1337 options.cc_only = noAssemble = preProcOnly = 0;
1340 werror (E_NEED_OPT_O_IN_C1);
1344 /* if no dstFileName given with -o, we've to find one: */
1349 /* use the modulename from the C-source */
1350 if (fullSrcFileName)
1352 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1354 dstFileName = Safe_alloc (bufSize);
1355 strncpyz (dstFileName, dstPath, bufSize);
1356 strncatz (dstFileName, moduleNameBase, bufSize);
1358 /* use the modulename from the first object file */
1359 else if ((s = peekSet(relFilesSet)) != NULL)
1364 strncpyz (buffer, s, sizeof(buffer));
1365 /* remove extension (it must be .rel) */
1366 *strrchr (buffer, '.') = '\0';
1368 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1375 objectName = buffer;
1377 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1378 dstFileName = Safe_alloc (bufSize);
1379 strncpyz (dstFileName, dstPath, bufSize);
1380 strncatz (dstFileName, objectName, bufSize);
1382 /* else no module given: help text is displayed */
1385 /* set int, long and float reentrancy based on stack-auto */
1386 if (options.stackAuto)
1388 options.intlong_rent++;
1389 options.float_rent++;
1392 /* mcs51 has an assembly coded float library that's always reentrant */
1393 if (TARGET_IS_MCS51)
1395 options.float_rent++;
1398 /* set up external stack location if not explicitly specified */
1399 if (!options.xstack_loc)
1400 options.xstack_loc = options.xdata_loc;
1402 /* if debug option is set then open the cdbFile */
1403 if (options.debug && fullSrcFileName)
1405 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1406 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1407 if(debugFile->openFile(scratchFileName))
1408 debugFile->writeModule(moduleName);
1410 werror (E_FILE_OPEN_ERR, scratchFileName);
1412 MSVC_style(options.vc_err_style);
1413 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1418 /*-----------------------------------------------------------------*/
1419 /* linkEdit : - calls the linkage editor with options */
1420 /*-----------------------------------------------------------------*/
1422 linkEdit (char **envp)
1428 char linkerScriptFileName[PATH_MAX];
1431 if(port->linker.needLinkerScript)
1435 switch (options.out_fmt)
1438 out_fmt = 'i'; /* Intel hex */
1441 out_fmt = 's'; /* Motorola S19 */
1444 out_fmt = 't'; /* Elf */
1450 /* first we need to create the <filename>.lnk file */
1451 SNPRINTF (linkerScriptFileName, sizeof(scratchFileName),
1452 "%s.lnk", dstFileName);
1453 if (!(lnkfile = fopen (linkerScriptFileName, "w")))
1455 werror (E_FILE_OPEN_ERR, linkerScriptFileName);
1459 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1461 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1462 out_fmt, dstFileName);
1464 else /*For all the other ports. Including pics???*/
1466 fprintf (lnkfile, "-myux%c\n", out_fmt);
1467 if(!options.no_pack_iram)
1468 fprintf (lnkfile, "-Y\n");
1471 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1473 /* if iram size specified */
1474 if (options.iram_size)
1475 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1477 /* if stack size specified*/
1478 if(options.stack_size)
1479 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1481 /* if xram size specified */
1482 if (options.xram_size_set)
1483 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1485 /* if code size specified */
1486 if (options.code_size)
1487 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1490 fprintf (lnkfile, "-z\n");
1493 #define WRITE_SEG_LOC(N, L) \
1494 segName = Safe_strdup(N); \
1495 c = strtok(segName, " \t"); \
1496 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1497 if (segName) { Safe_free(segName); }
1499 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1502 /* code segment start */
1503 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1505 /* data segment start. If zero, the linker chooses
1506 the best place for data */
1507 if(options.data_loc)
1509 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1512 /* xdata segment start. If zero, the linker chooses
1513 the best place for xdata */
1514 if(options.xdata_loc)
1516 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1522 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1525 /* bit segment start */
1526 WRITE_SEG_LOC (BIT_NAME, 0);
1529 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1532 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1535 else /*For the z80, gbz80*/
1537 WRITE_SEG_LOC ("_CODE", options.code_loc);
1538 WRITE_SEG_LOC ("_DATA", options.data_loc);
1541 /* If the port has any special linker area declarations, get 'em */
1542 if (port->extraAreas.genExtraAreaLinkOptions)
1544 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1547 /* add the extra linker options */
1548 fputStrSet(lnkfile, linkOptionsSet);
1550 /* command line defined library paths if specified */
1551 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1552 fprintf (lnkfile, "-k %s\n", s);
1554 /* standard library path */
1555 if (!options.nostdlib)
1557 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1559 switch (options.model)
1569 if (TARGET_IS_DS390)
1573 else if (TARGET_IS_DS400)
1580 "Add support for your FLAT24 target in %s @ line %d\n",
1581 __FILE__, __LINE__);
1589 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1594 else /*for the z80, gbz80*/
1598 else if (TARGET_IS_Z80)
1603 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1604 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1607 /* command line defined library files if specified */
1608 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1609 fprintf (lnkfile, "-l %s\n", s);
1611 /* standard library files */
1612 if (!options.nostdlib)
1614 #if !OPT_DISABLE_DS390
1615 if (options.model == MODEL_FLAT24)
1617 if (TARGET_IS_DS390)
1619 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1621 else if (TARGET_IS_DS400)
1623 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1628 "Add support for your FLAT24 target in %s @ line %d\n",
1629 __FILE__, __LINE__);
1635 #if !OPT_DISABLE_XA51
1637 if (options.model == MODEL_PAGE0)
1639 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1643 if (TARGET_IS_MCS51)
1645 fprintf (lnkfile, "-l mcs51\n");
1647 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1648 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1649 { /*Why the z80 port is not using the standard libraries?*/
1650 fprintf (lnkfile, "-l %s\n", STD_LIB);
1651 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1652 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1653 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1655 else if (TARGET_IS_HC08)
1657 fprintf (lnkfile, "-l hc08\n");
1659 else if (TARGET_IS_Z80)
1661 fprintf (lnkfile, "-l z80\n");
1663 else if (TARGET_IS_GBZ80)
1665 fprintf (lnkfile, "-l gbz80\n");
1669 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1670 It is very important for this file to be first on the linking proccess
1671 so the areas are set in the correct order, expecially _GSINIT*/
1672 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1673 !options.no_std_crt0) /*For the z80, gbz80*/
1675 char crt0path[PATH_MAX];
1679 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1680 tempSet = appendStrSet(tempSet, NULL, c);
1681 mergeSets(&tempSet, libPathsSet);
1683 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1685 sprintf (crt0path, "%s%scrt0.o",
1686 s, DIR_SEPARATOR_STRING);
1688 crt0fp=fopen(crt0path, "r");
1689 if(crt0fp!=NULL)/*Found it!*/
1694 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1695 windows paths, so convert them to the CYGWIN format*/
1696 char posix_path[PATH_MAX];
1697 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1698 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1699 strcpy(crt0path, posix_path);
1702 fprintf (lnkfile, "%s\n", crt0path);
1706 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1709 /* put in the object files */
1710 if (fullSrcFileName)
1711 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1713 fputStrSet(lnkfile, relFilesSet);
1715 fprintf (lnkfile, "\n-e\n");
1717 } /* if(port->linker.needLinkerScript) */
1719 if (options.verbose)
1720 printf ("sdcc: Calling linker...\n");
1722 /* build linker output filename */
1724 /* -o option overrides default name? */
1725 if (fullDstFileName)
1727 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1731 /* the linked file gets the name of the first modul */
1732 if (fullSrcFileName)
1734 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1738 s = peekSet(relFilesSet);
1742 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1743 /* strip ".rel" extension */
1744 *strrchr (scratchFileName, '.') = '\0';
1746 strncatz (scratchFileName,
1747 options.out_fmt ? ".S19" : ".ihx",
1748 sizeof(scratchFileName));
1751 if (port->linker.cmd)
1753 char buffer2[PATH_MAX];
1754 char buffer3[PATH_MAX];
1755 set *tempSet=NULL, *libSet=NULL;
1757 strcpy(buffer3, linkerScriptFileName);
1758 if(TARGET_IS_PIC16) {
1760 /* use $l to set the linker include directories */
1761 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1762 mergeSets(&linkOptionsSet, tempSet);
1764 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1765 mergeSets(&linkOptionsSet, tempSet);
1767 /* use $3 for libraries from command line --> libSet */
1768 mergeSets(&libSet, libFilesSet);
1770 tempSet = appendStrSet(relFilesSet, "", "");
1771 mergeSets(&libSet, tempSet);
1772 // libSet = reverseSet(libSet);
1774 if(fullSrcFileName) {
1775 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1776 /* if it didn't work, revert to old behaviour */
1777 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1778 strcat(buffer3, port->linker.rel_ext);
1780 } else strcpy(buffer3, "");
1783 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1785 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1789 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1792 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1794 system_ret = my_system (buffer);
1795 /* TODO: most linker don't have a -o parameter */
1796 /* -o option overrides default name? */
1797 if (fullDstFileName)
1800 /* the linked file gets the name of the first modul */
1801 if (fullSrcFileName)
1803 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1804 p = strlen (scratchFileName) + scratchFileName;
1808 s = peekSet(relFilesSet);
1812 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1813 /* strip ".rel" extension */
1814 p = strrchr (scratchFileName, '.');
1820 strncatz (scratchFileName,
1821 options.out_fmt ? ".S19" : ".ihx",
1822 sizeof(scratchFileName));
1823 if (strcmp (fullDstFileName, scratchFileName))
1824 unlink (fullDstFileName);
1825 rename (scratchFileName, fullDstFileName);
1827 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1828 q = strrchr (buffer, '.');
1831 /* no extension: append new extensions */
1832 q = strlen (buffer) + buffer;
1836 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1838 strncatz(buffer, ".map", sizeof(buffer));
1839 if (strcmp (scratchFileName, buffer))
1841 rename (scratchFileName, buffer);
1843 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1845 strncatz(buffer, ".mem", sizeof(buffer));
1846 if (strcmp (scratchFileName, buffer))
1848 rename (scratchFileName, buffer);
1852 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1854 strncatz(buffer, ".cdb", sizeof(buffer));
1855 if (strcmp (scratchFileName, buffer))
1857 rename (scratchFileName, buffer);
1858 /* and the OMF file without extension: */
1861 if (strcmp (scratchFileName, buffer))
1863 rename (scratchFileName, buffer);
1872 /*-----------------------------------------------------------------*/
1873 /* assemble - spawns the assembler with arguments */
1874 /*-----------------------------------------------------------------*/
1876 assemble (char **envp)
1878 /* build assembler output filename */
1880 /* -o option overrides default name? */
1881 if (options.cc_only && fullDstFileName) {
1882 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1884 /* the assembled file gets the name of the first modul */
1885 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1886 strncatz (scratchFileName, port->linker.rel_ext,
1887 sizeof(scratchFileName));
1890 if (port->assembler.do_assemble) {
1891 port->assembler.do_assemble(asmOptionsSet);
1893 } else if (port->assembler.cmd) {
1894 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1895 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1898 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1901 if (my_system (buffer)) {
1902 /* either system() or the assembler itself has reported an error
1903 perror ("Cannot exec assembler");
1907 /* TODO: most assembler don't have a -o parameter */
1908 /* -o option overrides default name? */
1909 if (options.cc_only && fullDstFileName) {
1910 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1911 strncatz (scratchFileName,
1912 port->linker.rel_ext,
1913 sizeof(scratchFileName));
1914 if (strcmp (scratchFileName, fullDstFileName))
1915 unlink (fullDstFileName);
1916 rename (scratchFileName, fullDstFileName);
1920 /*-----------------------------------------------------------------*/
1921 /* preProcess - spawns the preprocessor with arguments */
1922 /*-----------------------------------------------------------------*/
1924 preProcess (char **envp)
1933 set *inclList = NULL;
1935 /* if using external stack define the macro */
1936 if (options.useXstack)
1937 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1939 /* set the macro for stack autos */
1940 if (options.stackAuto)
1941 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1943 /* set the macro for stack autos */
1944 if (options.stack10bit)
1945 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1947 /* set the macro for no overlay */
1948 if (options.noOverlay)
1949 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1951 /* set the macro for large model */
1952 switch (options.model)
1955 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1958 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1961 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1964 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1967 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1970 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1973 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1977 /* add port (processor information to processor */
1978 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1979 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1981 /* standard include path */
1982 if (!options.nostdinc) {
1983 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1984 mergeSets(&preArgvSet, inclList);
1987 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1988 Safe_free((void *)s);
1989 if (inclList != NULL)
1990 deleteSet(&inclList);
1992 if (preProcOnly && fullDstFileName)
1994 /* -E and -o given */
1995 setMainValue ("cppoutfilename", fullDstFileName);
1999 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2000 setMainValue ("cppoutfilename", NULL);
2003 if (options.verbose)
2004 printf ("sdcc: Calling preprocessor...\n");
2006 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2009 if (my_system (buffer)) {
2016 yyin = my_popen (buffer);
2018 perror ("Preproc file not found");
2021 addSetHead (&pipeSet, yyin);
2029 setBinPaths(const char *argv0)
2037 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2038 * 2. - path(argv[0])
2042 /* do it in reverse mode, so that addSetHead() can be used
2043 instead of slower addSet() */
2045 if ((p = getBinPath(argv0)) != NULL)
2046 addSetHead(&binPathSet, Safe_strdup(p));
2048 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2049 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2050 addSetHead(&binPathSet, Safe_strdup(buf));
2054 if (options.printSearchDirs) {
2055 printf("programs:\n");
2056 fputStrSet(stdout, binPathSet);
2061 /* Set system include path */
2063 setIncludePath(void)
2072 * 1. - $SDCC_INCLUDE/target
2073 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2074 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2075 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2076 * 5. - $SDCC_INCLUDE
2077 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2078 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2079 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2082 if (options.nostdinc)
2085 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2086 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2087 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2088 mergeSets(&includeDirsSet, tempSet);
2090 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2092 addSetHead(&includeDirsSet, p);
2093 p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen(port->target)+1);
2097 strcat(p2, DIR_SEPARATOR_STRING);
2098 strcat(p2, port->target);
2099 addSetHead(&includeDirsSet, p2);
2104 if (options.printSearchDirs) {
2105 printf("includedir:\n");
2106 fputStrSet(stdout, includeDirsSet);
2111 /* Set system lib path */
2121 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2122 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2123 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2126 if (options.nostdlib)
2129 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2131 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2132 addSetHead(&libDirsSet, p);
2135 if (options.printSearchDirs) {
2136 printf("libdir:\n");
2137 fputStrSet(stdout, libDirsSet);
2144 setDataPaths(const char *argv0)
2152 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2153 * 2. - path(argv[0])/BIN2DATA_DIR
2154 * 3. - DATADIR (only on *nix)
2157 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2158 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2159 addSet(&dataDirsSet, Safe_strdup(buf));
2162 if ((p = getBinPath(argv0)) != NULL) {
2163 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2164 addSet(&dataDirsSet, Safe_strdup(buf));
2168 if (peekSet(dataDirsSet) == NULL) {
2169 /* this should never happen... */
2170 wassertl(0, "Can't get binary path");
2173 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2177 if (options.printSearchDirs) {
2178 printf("datadir:\n");
2179 fputStrSet(stdout, dataDirsSet);
2190 populateMainValues (_baseValues);
2191 setMainValue ("port", port->target);
2192 setMainValue ("objext", port->linker.rel_ext);
2193 setMainValue ("asmext", port->assembler.file_ext);
2195 setMainValue ("dstfilename", dstFileName);
2196 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2198 if (options.cc_only && fullDstFileName)
2199 /* compile + assemble and -o given: -o specifies name of object file */
2201 setMainValue ("objdstfilename", fullDstFileName);
2205 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2207 if (fullDstFileName)
2208 /* if we're linking, -o gives the final file name */
2210 setMainValue ("linkdstfilename", fullDstFileName);
2214 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2219 static void doPrintSearchDirs(void)
2221 printf("programs:\n");
2222 fputStrSet(stdout, binPathSet);
2224 printf("datadir:\n");
2225 fputStrSet(stdout, dataDirsSet);
2227 printf("includedir:\n");
2228 fputStrSet(stdout, includeDirsSet);
2230 printf("libdir:\n");
2231 fputStrSet(stdout, libDirsSet);
2232 fputStrSet(stdout, libPathsSet);
2237 sig_handler (int signal)
2244 sig_string = "SIGABRT";
2247 sig_string = "SIGTERM";
2250 sig_string = "SIGINT";
2253 sig_string = "SIGSEGV";
2256 sig_string = "Unknown?";
2259 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2265 * initialises and calls the parser
2269 main (int argc, char **argv, char **envp)
2271 /* turn all optimizations off by default */
2272 memset (&optimize, 0, sizeof (struct optimize));
2274 /*printVersionInfo (); */
2277 fprintf (stderr, "Build error: no ports are enabled.\n");
2281 /* install atexit handler */
2282 atexit(rm_tmpfiles);
2284 /* install signal handler;
2285 it's only purpuse is to call exit() to remove temp files */
2286 if (!getenv("SDCC_LEAVE_SIGNALS"))
2288 signal (SIGABRT, sig_handler);
2289 signal (SIGTERM, sig_handler);
2290 signal (SIGINT , sig_handler);
2291 signal (SIGSEGV, sig_handler);
2294 /* Before parsing the command line options, do a
2295 * search for the port and processor and initialize
2296 * them if they're found. (We can't gurantee that these
2297 * will be the first options specified).
2300 _findPort (argc, argv);
2303 if (strcmp(port->target, "mcs51") == 0) {
2304 printf("DS390 jammed in A\n");
2310 _findProcessor (argc, argv);
2312 /* Initalise the port. */
2316 setDefaultOptions ();
2319 options.model = MODEL_SMALL;
2320 options.stack10bit=0;
2323 parseCmdLine (argc, argv);
2327 setBinPaths(argv[0]);
2328 setDataPaths(argv[0]);
2333 if(options.printSearchDirs)
2334 doPrintSearchDirs();
2336 /* if no input then printUsage & exit */
2337 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2338 if (!options.printSearchDirs)
2344 /* initMem() is expensive, but
2345 initMem() must called before port->finaliseOptions ().
2346 And the z80 port needs port->finaliseOptions(),
2347 even if we're only linking. */
2349 port->finaliseOptions ();
2351 if (fullSrcFileName || options.c1mode)
2361 if (options.verbose)
2362 printf ("sdcc: Generating code...\n");
2368 deleteSetItem(&pipeSet, yyin);
2374 if (port->general.do_glue != NULL)
2375 (*port->general.do_glue)();
2378 /* this shouldn't happen */
2380 /* in case of NDEBUG */
2388 if (!options.c1mode && !noAssemble)
2390 if (options.verbose)
2391 printf ("sdcc: Calling assembler...\n");
2397 if (options.debug && debugFile)
2398 debugFile->closeFile();
2400 if (!options.cc_only &&
2404 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2406 if (port->linker.do_link)
2407 port->linker.do_link ();