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)
1430 if(port->linker.needLinkerScript)
1434 switch (options.out_fmt)
1437 out_fmt = 'i'; /* Intel hex */
1440 out_fmt = 's'; /* Motorola S19 */
1443 out_fmt = 't'; /* Elf */
1449 /* first we need to create the <filename>.lnk file */
1450 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1451 "%s.lnk", dstFileName);
1452 if (!(lnkfile = fopen (scratchFileName, "w")))
1454 werror (E_FILE_OPEN_ERR, scratchFileName);
1458 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1460 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1461 out_fmt, dstFileName);
1463 else /*For all the other ports. Including pics???*/
1465 fprintf (lnkfile, "-myux%c\n", out_fmt);
1466 if(!options.no_pack_iram)
1467 fprintf (lnkfile, "-Y\n");
1470 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1472 /* if iram size specified */
1473 if (options.iram_size)
1474 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1476 /* if stack size specified*/
1477 if(options.stack_size)
1478 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1480 /* if xram size specified */
1481 if (options.xram_size_set)
1482 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1484 /* if code size specified */
1485 if (options.code_size)
1486 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1489 fprintf (lnkfile, "-z\n");
1492 #define WRITE_SEG_LOC(N, L) \
1493 segName = Safe_strdup(N); \
1494 c = strtok(segName, " \t"); \
1495 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1496 if (segName) { Safe_free(segName); }
1498 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1501 /* code segment start */
1502 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1504 /* data segment start. If zero, the linker chooses
1505 the best place for data */
1506 if(options.data_loc)
1508 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1511 /* xdata segment start. If zero, the linker chooses
1512 the best place for xdata */
1513 if(options.xdata_loc)
1515 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1521 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1524 /* bit segment start */
1525 WRITE_SEG_LOC (BIT_NAME, 0);
1528 if ( (options.stack_loc) && (options.stack_loc<0x100) &&
1531 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1534 else /*For the z80, gbz80*/
1536 WRITE_SEG_LOC ("_CODE", options.code_loc);
1537 WRITE_SEG_LOC ("_DATA", options.data_loc);
1540 /* If the port has any special linker area declarations, get 'em */
1541 if (port->extraAreas.genExtraAreaLinkOptions)
1543 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1546 /* add the extra linker options */
1547 fputStrSet(lnkfile, linkOptionsSet);
1549 /* command line defined library paths if specified */
1550 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1551 fprintf (lnkfile, "-k %s\n", s);
1553 /* standard library path */
1554 if (!options.nostdlib)
1556 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1558 switch (options.model)
1568 if (TARGET_IS_DS390)
1572 else if (TARGET_IS_DS400)
1579 "Add support for your FLAT24 target in %s @ line %d\n",
1580 __FILE__, __LINE__);
1588 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1593 else /*for the z80, gbz80*/
1597 else if (TARGET_IS_Z80)
1602 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1603 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1606 /* command line defined library files if specified */
1607 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1608 fprintf (lnkfile, "-l %s\n", s);
1610 /* standard library files */
1611 if (!options.nostdlib)
1613 #if !OPT_DISABLE_DS390
1614 if (options.model == MODEL_FLAT24)
1616 if (TARGET_IS_DS390)
1618 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1620 else if (TARGET_IS_DS400)
1622 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1627 "Add support for your FLAT24 target in %s @ line %d\n",
1628 __FILE__, __LINE__);
1634 #if !OPT_DISABLE_XA51
1636 if (options.model == MODEL_PAGE0)
1638 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1642 if (TARGET_IS_MCS51)
1644 fprintf (lnkfile, "-l mcs51\n");
1646 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1647 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1648 { /*Why the z80 port is not using the standard libraries?*/
1649 fprintf (lnkfile, "-l %s\n", STD_LIB);
1650 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1651 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1652 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1654 else if (TARGET_IS_HC08)
1656 fprintf (lnkfile, "-l hc08\n");
1658 else if (TARGET_IS_Z80)
1660 fprintf (lnkfile, "-l z80\n");
1662 else if (TARGET_IS_GBZ80)
1664 fprintf (lnkfile, "-l gbz80\n");
1668 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1669 It is very important for this file to be first on the linking proccess
1670 so the areas are set in the correct order, expecially _GSINIT*/
1671 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1672 !options.no_std_crt0) /*For the z80, gbz80*/
1674 char crt0path[PATH_MAX];
1678 tempSet = appendStrSet(libDirsSet, NULL, DIR_SEPARATOR_STRING);
1679 tempSet = appendStrSet(tempSet, NULL, c);
1680 mergeSets(&tempSet, libPathsSet);
1682 for (s = setFirstItem(tempSet); s != NULL; s = setNextItem(tempSet))
1684 sprintf (crt0path, "%s%scrt0.o",
1685 s, DIR_SEPARATOR_STRING);
1687 crt0fp=fopen(crt0path, "r");
1688 if(crt0fp!=NULL)/*Found it!*/
1693 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1694 windows paths, so convert them to the CYGWIN format*/
1695 char posix_path[PATH_MAX];
1696 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1697 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1698 strcpy(crt0path, posix_path);
1701 fprintf (lnkfile, "%s\n", crt0path);
1705 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1708 /* put in the object files */
1709 if (fullSrcFileName)
1710 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1712 fputStrSet(lnkfile, relFilesSet);
1714 fprintf (lnkfile, "\n-e\n");
1716 } /* if(port->linker.needLinkerScript) */
1718 if (options.verbose)
1719 printf ("sdcc: Calling linker...\n");
1721 /* build linker output filename */
1723 /* -o option overrides default name? */
1724 if (fullDstFileName)
1726 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1730 /* the linked file gets the name of the first modul */
1731 if (fullSrcFileName)
1733 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1737 s = peekSet(relFilesSet);
1741 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1742 /* strip ".rel" extension */
1743 *strrchr (scratchFileName, '.') = '\0';
1745 strncatz (scratchFileName,
1746 options.out_fmt ? ".S19" : ".ihx",
1747 sizeof(scratchFileName));
1750 if (port->linker.cmd)
1752 char buffer2[PATH_MAX];
1753 char buffer3[PATH_MAX];
1754 set *tempSet=NULL, *libSet=NULL;
1756 strcpy(buffer3, dstFileName);
1757 if(TARGET_IS_PIC16) {
1759 /* use $l to set the linker include directories */
1760 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1761 mergeSets(&linkOptionsSet, tempSet);
1763 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1764 mergeSets(&linkOptionsSet, tempSet);
1766 /* use $3 for libraries from command line --> libSet */
1767 mergeSets(&libSet, libFilesSet);
1769 tempSet = appendStrSet(relFilesSet, "", "");
1770 mergeSets(&libSet, tempSet);
1771 // libSet = reverseSet(libSet);
1773 if(fullSrcFileName) {
1774 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1775 /* if it didn't work, revert to old behaviour */
1776 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1777 strcat(buffer3, port->linker.rel_ext);
1779 } else strcpy(buffer3, "");
1782 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1784 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1788 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1791 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1793 system_ret = my_system (buffer);
1794 /* TODO: most linker don't have a -o parameter */
1795 /* -o option overrides default name? */
1796 if (fullDstFileName)
1799 /* the linked file gets the name of the first modul */
1800 if (fullSrcFileName)
1802 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1803 p = strlen (scratchFileName) + scratchFileName;
1807 s = peekSet(relFilesSet);
1811 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1812 /* strip ".rel" extension */
1813 p = strrchr (scratchFileName, '.');
1819 strncatz (scratchFileName,
1820 options.out_fmt ? ".S19" : ".ihx",
1821 sizeof(scratchFileName));
1822 if (strcmp (fullDstFileName, scratchFileName))
1823 unlink (fullDstFileName);
1824 rename (scratchFileName, fullDstFileName);
1826 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1827 q = strrchr (buffer, '.');
1830 /* no extension: append new extensions */
1831 q = strlen (buffer) + buffer;
1835 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1837 strncatz(buffer, ".map", sizeof(buffer));
1838 if (strcmp (scratchFileName, buffer))
1840 rename (scratchFileName, buffer);
1842 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1844 strncatz(buffer, ".mem", sizeof(buffer));
1845 if (strcmp (scratchFileName, buffer))
1847 rename (scratchFileName, buffer);
1851 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1853 strncatz(buffer, ".cdb", sizeof(buffer));
1854 if (strcmp (scratchFileName, buffer))
1856 rename (scratchFileName, buffer);
1857 /* and the OMF file without extension: */
1860 if (strcmp (scratchFileName, buffer))
1862 rename (scratchFileName, buffer);
1871 /*-----------------------------------------------------------------*/
1872 /* assemble - spawns the assembler with arguments */
1873 /*-----------------------------------------------------------------*/
1875 assemble (char **envp)
1877 /* build assembler output filename */
1879 /* -o option overrides default name? */
1880 if (options.cc_only && fullDstFileName) {
1881 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1883 /* the assembled file gets the name of the first modul */
1884 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1885 strncatz (scratchFileName, port->linker.rel_ext,
1886 sizeof(scratchFileName));
1889 if (port->assembler.do_assemble) {
1890 port->assembler.do_assemble(asmOptionsSet);
1892 } else if (port->assembler.cmd) {
1893 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1894 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1897 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1900 if (my_system (buffer)) {
1901 /* either system() or the assembler itself has reported an error
1902 perror ("Cannot exec assembler");
1906 /* TODO: most assembler don't have a -o parameter */
1907 /* -o option overrides default name? */
1908 if (options.cc_only && fullDstFileName) {
1909 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1910 strncatz (scratchFileName,
1911 port->linker.rel_ext,
1912 sizeof(scratchFileName));
1913 if (strcmp (scratchFileName, fullDstFileName))
1914 unlink (fullDstFileName);
1915 rename (scratchFileName, fullDstFileName);
1919 /*-----------------------------------------------------------------*/
1920 /* preProcess - spawns the preprocessor with arguments */
1921 /*-----------------------------------------------------------------*/
1923 preProcess (char **envp)
1932 set *inclList = NULL;
1934 /* if using external stack define the macro */
1935 if (options.useXstack)
1936 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1938 /* set the macro for stack autos */
1939 if (options.stackAuto)
1940 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1942 /* set the macro for stack autos */
1943 if (options.stack10bit)
1944 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1946 /* set the macro for no overlay */
1947 if (options.noOverlay)
1948 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1950 /* set the macro for large model */
1951 switch (options.model)
1954 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1957 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1960 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1963 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1966 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1969 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1972 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1976 /* add port (processor information to processor */
1977 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1978 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1980 /* standard include path */
1981 if (!options.nostdinc) {
1982 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1983 mergeSets(&preArgvSet, inclList);
1986 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1987 Safe_free((void *)s);
1988 if (inclList != NULL)
1989 deleteSet(&inclList);
1991 if (preProcOnly && fullDstFileName)
1993 /* -E and -o given */
1994 setMainValue ("cppoutfilename", fullDstFileName);
1998 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1999 setMainValue ("cppoutfilename", NULL);
2002 if (options.verbose)
2003 printf ("sdcc: Calling preprocessor...\n");
2005 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
2008 if (my_system (buffer)) {
2015 yyin = my_popen (buffer);
2017 perror ("Preproc file not found");
2020 addSetHead (&pipeSet, yyin);
2028 setBinPaths(const char *argv0)
2036 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2037 * 2. - path(argv[0])
2041 /* do it in reverse mode, so that addSetHead() can be used
2042 instead of slower addSet() */
2044 if ((p = getBinPath(argv0)) != NULL)
2045 addSetHead(&binPathSet, Safe_strdup(p));
2047 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2048 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
2049 addSetHead(&binPathSet, Safe_strdup(buf));
2053 if (options.printSearchDirs) {
2054 printf("programs:\n");
2055 fputStrSet(stdout, binPathSet);
2060 /* Set system include path */
2062 setIncludePath(void)
2070 * 1. - $SDCC_INCLUDE/target
2071 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2072 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2073 * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2074 * 5. - $SDCC_INCLUDE
2075 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2076 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2077 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2080 if (options.nostdinc)
2083 tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2084 includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
2085 includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
2086 mergeSets(&includeDirsSet, tempSet);
2088 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2089 addSetHead(&includeDirsSet, p);
2092 if (options.printSearchDirs) {
2093 printf("includedir:\n");
2094 fputStrSet(stdout, includeDirsSet);
2099 /* Set system lib path */
2109 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2110 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2111 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2114 if (options.nostdlib)
2117 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2119 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2120 addSetHead(&libDirsSet, p);
2123 if (options.printSearchDirs) {
2124 printf("libdir:\n");
2125 fputStrSet(stdout, libDirsSet);
2132 setDataPaths(const char *argv0)
2140 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2141 * 2. - path(argv[0])/BIN2DATA_DIR
2142 * 3. - DATADIR (only on *nix)
2145 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2146 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2147 addSet(&dataDirsSet, Safe_strdup(buf));
2150 if ((p = getBinPath(argv0)) != NULL) {
2151 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2152 addSet(&dataDirsSet, Safe_strdup(buf));
2156 if (peekSet(dataDirsSet) == NULL) {
2157 /* this should never happen... */
2158 wassertl(0, "Can't get binary path");
2161 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2165 if (options.printSearchDirs) {
2166 printf("datadir:\n");
2167 fputStrSet(stdout, dataDirsSet);
2178 populateMainValues (_baseValues);
2179 setMainValue ("port", port->target);
2180 setMainValue ("objext", port->linker.rel_ext);
2181 setMainValue ("asmext", port->assembler.file_ext);
2183 setMainValue ("dstfilename", dstFileName);
2184 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2186 if (options.cc_only && fullDstFileName)
2187 /* compile + assemble and -o given: -o specifies name of object file */
2189 setMainValue ("objdstfilename", fullDstFileName);
2193 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2195 if (fullDstFileName)
2196 /* if we're linking, -o gives the final file name */
2198 setMainValue ("linkdstfilename", fullDstFileName);
2202 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2207 static void doPrintSearchDirs(void)
2209 printf("programs:\n");
2210 fputStrSet(stdout, binPathSet);
2212 printf("datadir:\n");
2213 fputStrSet(stdout, dataDirsSet);
2215 printf("includedir:\n");
2216 fputStrSet(stdout, includeDirsSet);
2218 printf("libdir:\n");
2219 fputStrSet(stdout, libDirsSet);
2220 fputStrSet(stdout, libPathsSet);
2225 sig_handler (int signal)
2232 sig_string = "SIGABRT";
2235 sig_string = "SIGTERM";
2238 sig_string = "SIGINT";
2241 sig_string = "SIGSEGV";
2244 sig_string = "Unknown?";
2247 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2253 * initialises and calls the parser
2257 main (int argc, char **argv, char **envp)
2259 /* turn all optimizations off by default */
2260 memset (&optimize, 0, sizeof (struct optimize));
2262 /*printVersionInfo (); */
2265 fprintf (stderr, "Build error: no ports are enabled.\n");
2269 /* install atexit handler */
2270 atexit(rm_tmpfiles);
2272 /* install signal handler;
2273 it's only purpuse is to call exit() to remove temp files */
2274 if (!getenv("SDCC_LEAVE_SIGNALS"))
2276 signal (SIGABRT, sig_handler);
2277 signal (SIGTERM, sig_handler);
2278 signal (SIGINT , sig_handler);
2279 signal (SIGSEGV, sig_handler);
2282 /* Before parsing the command line options, do a
2283 * search for the port and processor and initialize
2284 * them if they're found. (We can't gurantee that these
2285 * will be the first options specified).
2288 _findPort (argc, argv);
2291 if (strcmp(port->target, "mcs51") == 0) {
2292 printf("DS390 jammed in A\n");
2298 _findProcessor (argc, argv);
2300 /* Initalise the port. */
2304 setDefaultOptions ();
2307 options.model = MODEL_SMALL;
2308 options.stack10bit=0;
2311 parseCmdLine (argc, argv);
2315 setBinPaths(argv[0]);
2316 setDataPaths(argv[0]);
2321 if(options.printSearchDirs)
2322 doPrintSearchDirs();
2324 /* if no input then printUsage & exit */
2325 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2326 if (!options.printSearchDirs)
2332 /* initMem() is expensive, but
2333 initMem() must called before port->finaliseOptions ().
2334 And the z80 port needs port->finaliseOptions(),
2335 even if we're only linking. */
2337 port->finaliseOptions ();
2339 if (fullSrcFileName || options.c1mode)
2349 if (options.verbose)
2350 printf ("sdcc: Generating code...\n");
2356 deleteSetItem(&pipeSet, yyin);
2362 if (port->general.do_glue != NULL)
2363 (*port->general.do_glue)();
2366 /* this shouldn't happen */
2368 /* in case of NDEBUG */
2376 if (!options.c1mode && !noAssemble)
2378 if (options.verbose)
2379 printf ("sdcc: Calling assembler...\n");
2385 if (options.debug && debugFile)
2386 debugFile->closeFile();
2388 if (!options.cc_only &&
2392 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2394 if (port->linker.do_link)
2395 port->linker.do_link ();