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_LARGE_MODEL "--model-large"
100 #define OPTION_MEDIUM_MODEL "--model-medium"
101 #define OPTION_SMALL_MODEL "--model-small"
102 #define OPTION_FLAT24_MODEL "--model-flat24"
103 #define OPTION_DUMP_ALL "--dumpall"
104 #define OPTION_PEEP_FILE "--peep-file"
105 #define OPTION_LIB_PATH "--lib-path"
106 #define OPTION_CALLEE_SAVES "--callee-saves"
107 #define OPTION_STACK_LOC "--stack-loc"
108 #define OPTION_XSTACK_LOC "--xstack-loc"
109 #define OPTION_DATA_LOC "--data-loc"
110 #define OPTION_IDATA_LOC "--idata-loc"
111 #define OPTION_XRAM_LOC "--xram-loc"
112 #define OPTION_CODE_LOC "--code-loc"
113 #define OPTION_STACK_SIZE "--stack-size"
114 #define OPTION_IRAM_SIZE "--iram-size"
115 #define OPTION_XRAM_SIZE "--xram-size"
116 #define OPTION_CODE_SIZE "--code-size"
117 #define OPTION_VERSION "--version"
118 #define OPTION_NO_LABEL_OPT "--nolabelopt"
119 #define OPTION_NO_LOOP_INV "--noinvariant"
120 #define OPTION_NO_LOOP_IND "--noinduction"
121 #define OPTION_LESS_PEDANTIC "--less-pedantic"
122 #define OPTION_DISABLE_WARNING "--disable-warning"
123 #define OPTION_NO_GCSE "--nogcse"
124 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
125 #define OPTION_TINI_LIBID "--tini-libid"
126 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
127 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
128 #define OPTION_ICODE_IN_ASM "--i-code-in-asm"
129 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
130 #define OPTION_MSVC_ERROR_STYLE "--vc"
131 #define OPTION_USE_STDOUT "--use-stdout"
132 #define OPTION_PACK_IRAM "--pack-iram"
133 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
134 #define OPTION_OPT_CODE_SPEED "--opt-code-speed"
135 #define OPTION_OPT_CODE_SIZE "--opt-code-size"
139 { 0, NULL, NULL, "General options" },
140 { 0, "--help", NULL, "Display this help" },
141 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
142 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
143 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
144 { 'd', NULL, NULL, NULL },
145 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
146 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
147 { 'A', NULL, NULL, NULL },
148 { 'U', NULL, NULL, NULL },
149 { 'C', NULL, NULL, "Preprocessor option" },
150 { 'M', NULL, NULL, "Preprocessor option" },
151 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
152 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
153 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
154 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
155 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
156 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
157 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
158 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
159 { 0, OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
160 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
161 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
162 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
163 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
164 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
165 { 0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions" },
167 { 0, NULL, NULL, "Code generation options"},
168 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
169 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
170 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
171 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
172 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
173 #if !OPT_DISABLE_DS390
174 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
175 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
176 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
178 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
179 { 0, "--xstack", &options.useXstack, "Use external stack" },
180 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
181 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
182 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
183 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
184 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
185 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
186 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
187 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
188 #if !OPT_DISABLE_DS390
189 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
191 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
192 #if !OPT_DISABLE_TININative
193 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
195 #if !OPT_DISABLE_DS390
196 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
198 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
199 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
201 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
202 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
203 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
204 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
205 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
207 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" },
209 { 0, NULL, NULL, "Optimization options"},
210 { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" },
211 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
212 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
213 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
214 { 0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction" },
215 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
216 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
217 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
218 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
219 { 0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly" },
220 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peephole file" },
221 { 0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size" },
222 { 0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed" },
224 { 0, NULL, NULL, "Internal debugging options"},
225 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
226 { 0, "--dumpgcse", &options.dump_gcse, NULL },
227 { 0, "--dumploop", &options.dump_loop, NULL },
228 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
229 { 0, "--dumpliverange", &options.dump_range, NULL },
230 { 0, "--dumpregpack", &options.dump_pack, NULL },
231 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
232 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
233 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
234 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
236 { 0, NULL, NULL, "Linker options" },
237 { 'l', NULL, NULL, "Include the given library in the link" },
238 { 'L', NULL, NULL, "Add the next field to the library search path" },
239 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
240 { 0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format" },
241 { 0, "--out-fmt-s19", &options.out_fmt, "Output in S19 hex format" },
242 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
243 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
244 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
245 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
246 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
247 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
248 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
249 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
250 { 0, OPTION_IDATA_LOC, NULL, NULL },
251 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
252 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
253 { 0, OPTION_PACK_IRAM, &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
260 /** Table of all unsupported options and help text to display when one
264 /** shortOpt as in OPTIONS. */
266 /** longOpt as in OPTIONS. */
268 /** Message to display inside W_UNSUPPORTED_OPT when this option
273 static const UNSUPPORTEDOPT
274 unsupportedOptTable[] = {
275 { 'X', NULL, "use --xstack-loc instead" },
276 { 'x', NULL, "use --xstack instead" },
277 { 'i', NULL, "use --idata-loc instead" },
278 { 'r', NULL, "use --xdata-loc instead" },
279 { 's', NULL, "use --code-loc instead" },
280 { 'Y', NULL, "use -I instead" }
283 /** List of all default constant macros.
285 static const char *_baseValues[] = {
288 /* Path seperator character */
289 "sep", DIR_SEPARATOR_STRING,
293 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
297 static PORT *_ports[] =
299 #if !OPT_DISABLE_MCS51
302 #if !OPT_DISABLE_GBZ80
311 #if !OPT_DISABLE_DS390
314 #if !OPT_DISABLE_PIC16
320 #if !OPT_DISABLE_TININative
323 #if !OPT_DISABLE_XA51
326 #if !OPT_DISABLE_DS400
329 #if !OPT_DISABLE_HC08
334 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
336 /** Sets the port to the one given by the command line option.
337 @param The name minus the option (eg 'mcs51')
338 @return 0 on success.
341 _setPort (const char *name)
344 for (i = 0; i < NUM_PORTS; i++)
346 if (!strcmp (_ports[i]->target, name))
352 /* Error - didnt find */
353 werror (E_UNKNOWN_TARGET, name);
357 /* Override the default processor with the one specified
358 * on the command line */
360 _setProcessor (char *_processor)
362 port->processor = _processor;
363 fprintf(stderr,"Processor: %s\n",_processor);
367 _validatePorts (void)
370 for (i = 0; i < NUM_PORTS; i++)
372 if (_ports[i]->magic != PORT_MAGIC)
374 /* Uncomment this line to debug which port is causing the problem
375 * (the target name is close to the beginning of the port struct
376 * and probably can be accessed just fine). */
377 fprintf(stderr,"%s :",_ports[i]->target);
378 wassertl (0, "Port definition structure is incomplete");
383 /* search through the command line options for the port */
385 _findPort (int argc, char **argv)
391 if (!strncmp (*argv, "-m", 2))
393 _setPort (*argv + 2);
399 /* Use the first in the list */
403 /* search through the command line options for the processor */
405 _findProcessor (int argc, char **argv)
409 if (!strncmp (*argv, "-p", 2))
411 _setProcessor (*argv + 2);
417 /* no error if processor was not specified. */
420 /*-----------------------------------------------------------------*/
421 /* printVersionInfo - prints the version info */
422 /*-----------------------------------------------------------------*/
424 printVersionInfo (void)
430 for (i = 0; i < NUM_PORTS; i++)
431 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
433 fprintf (stderr, " " SDCC_VERSION_STR
434 #ifdef SDCC_SUB_VERSION_STR
435 "/" SDCC_SUB_VERSION_STR
437 " #%s (" __DATE__ ")"
440 #elif defined __MINGW32__
442 #elif defined __DJGPP__
444 #elif defined(_MSC_VER)
446 #elif defined(__BORLANDC__)
451 , getBuildNumber() );
455 printOptions(const OPTION *optionsTable)
459 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
460 || optionsTable[i].help != NULL;
463 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
464 && optionsTable[i].help)
466 fprintf (stdout, "\n%s:\n", optionsTable[i].help);
470 fprintf(stdout, " %c%c %-20s %s\n",
471 optionsTable[i].shortOpt !=0 ? '-' : ' ',
472 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
473 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
474 optionsTable[i].help != NULL ? optionsTable[i].help : ""
480 /*-----------------------------------------------------------------*/
481 /* printUsage - prints command line syntax */
482 /*-----------------------------------------------------------------*/
489 "Usage : sdcc [options] filename\n"
493 printOptions(optionsTable);
495 for (i = 0; i < NUM_PORTS; i++)
497 if (_ports[i]->poptions != NULL)
499 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
500 printOptions (_ports[i]->poptions);
507 /*-----------------------------------------------------------------*/
508 /* setParseWithComma - separates string with comma to a set */
509 /*-----------------------------------------------------------------*/
511 setParseWithComma (set **dest, char *src)
516 /* skip the initial white spaces */
517 while (isspace(*src))
520 /* skip the trailing white spaces */
521 length = strlen(src);
522 while (length && isspace(src[length-1]))
523 src[--length] = '\0';
525 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
526 addSet(dest, Safe_strdup(p));
529 /*-----------------------------------------------------------------*/
530 /* setDefaultOptions - sets the default options */
531 /*-----------------------------------------------------------------*/
533 setDefaultOptions (void)
535 /* first the options part */
536 options.stack_loc = 0; /* stack pointer initialised to 0 */
537 options.xstack_loc = 0; /* xternal stack starts at 0 */
538 options.code_loc = 0; /* code starts at 0 */
539 options.data_loc = 0; /* JCF: By default let the linker locate data */
540 options.xdata_loc = 0;
541 options.idata_loc = 0x80;
543 options.model = port->general.default_model;
544 options.nostdlib = 0;
545 options.nostdinc = 0;
547 options.shortis8bits = 0;
549 options.stack10bit=0;
551 /* now for the optimizations */
552 /* turn on the everything */
553 optimize.global_cse = 1;
558 optimize.loopInvariant = 1;
559 optimize.loopInduction = 1;
561 /* now for the ports */
562 port->setDefaultOptions ();
565 /*-----------------------------------------------------------------*/
566 /* processFile - determines the type of file from the extension */
567 /*-----------------------------------------------------------------*/
569 processFile (char *s)
573 /* get the file extension */
574 fext = s + strlen (s);
575 while ((fext != s) && *fext != '.')
578 /* now if no '.' then we don't know what the file type is
579 so give a warning and return */
582 werror (W_UNKNOWN_FEXT, s);
586 /* otherwise depending on the file type */
587 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
589 /* source file name : not if we already have a
593 werror (W_TOO_MANY_SRC, s);
597 /* the only source file */
599 if (!(srcFile = fopen (fullSrcFileName, "r")))
601 werror (E_FILE_OPEN_ERR, s);
605 /* copy the file name into the buffer */
606 strncpyz (buffer, s, sizeof(buffer));
608 /* get rid of the "."-extension */
610 /* is there a dot at all? */
611 if (strrchr (buffer, '.') &&
612 /* is the dot in the filename, not in the path? */
613 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
615 *strrchr (buffer, '.') = '\0';
618 /* get rid of any path information
619 for the module name; */
620 fext = buffer + strlen (buffer);
622 /* do this by going backwards till we
623 get '\' or ':' or start of buffer */
624 while (fext != buffer &&
625 *(fext - 1) != DIR_SEPARATOR_CHAR &&
631 /* do this by going backwards till we
632 get '/' or start of buffer */
633 while (fext != buffer &&
634 *(fext - 1) != DIR_SEPARATOR_CHAR)
639 moduleNameBase = Safe_strdup ( fext );
640 moduleName = Safe_strdup ( fext );
642 for (fext = moduleName; *fext; fext++)
643 if (!isalnum (*fext))
648 /* if the extention is type .rel or .r or .REL or .R
649 addtional object file will be passed to the linker */
650 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
651 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
652 strcmp (fext, port->linker.rel_ext) == 0)
654 addSet(&relFilesSet, Safe_strdup(s));
658 /* if .lib or .LIB */
659 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
661 addSet(&libFilesSet, Safe_strdup(s));
665 werror (W_UNKNOWN_FEXT, s);
670 _setModel (int model, const char *sz)
672 if (port->general.supported_models & model)
673 options.model = model;
675 werror (W_UNSUPPORTED_MODEL, sz, port->target);
678 /** Gets the string argument to this option. If the option is '--opt'
679 then for input of '--optxyz' or '--opt xyz' returns xyz.
682 getStringArg(const char *szStart, char **argv, int *pi, int argc)
684 if (argv[*pi][strlen(szStart)])
686 return &argv[*pi][strlen(szStart)];
693 werror (E_ARGUMENT_MISSING, szStart);
694 /* Die here rather than checking for errors later. */
704 /** Gets the integer argument to this option using the same rules as
708 getIntArg(const char *szStart, char **argv, int *pi, int argc)
710 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
714 verifyShortOption(const char *opt)
716 if (strlen(opt) != 2)
718 werror (W_EXCESS_SHORT_OPTIONS, opt);
723 tryHandleUnsupportedOpt(char **argv, int *pi)
725 if (argv[*pi][0] == '-')
727 const char *longOpt = "";
731 if (argv[*pi][1] == '-')
738 shortOpt = argv[*pi][1];
740 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
742 if (unsupportedOptTable[i].shortOpt == shortOpt ||
743 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
744 /* Found an unsupported opt. */
746 SNPRINTF(buffer, sizeof(buffer),
748 longOpt ? longOpt : "",
749 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
750 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
754 /* Didn't find in the table */
759 /* Not an option, so can't be unsupported :) */
765 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
769 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
770 || optionsTable[i].help != NULL;
773 if (optionsTable[i].shortOpt == shortOpt ||
774 (longOpt && optionsTable[i].longOpt &&
775 strcmp(optionsTable[i].longOpt, longOpt) == 0))
778 /* If it is a flag then we can handle it here */
779 if (optionsTable[i].pparameter != NULL)
781 if (optionsTable[i].shortOpt == shortOpt)
783 verifyShortOption(argv[*pi]);
786 (*optionsTable[i].pparameter)++;
790 /* Not a flag. Handled manually later. */
795 /* Didn't find in the table */
800 tryHandleSimpleOpt(char **argv, int *pi)
802 if (argv[*pi][0] == '-')
804 const char *longOpt = "";
807 if (argv[*pi][1] == '-')
814 shortOpt = argv[*pi][1];
817 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
821 else if (port && port->poptions &&
822 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
833 /* Not an option, so can't be handled. */
838 /*-----------------------------------------------------------------*/
839 /* parseCmdLine - parses the command line and sets the options */
840 /*-----------------------------------------------------------------*/
842 parseCmdLine (int argc, char **argv)
846 /* go thru all whole command line */
847 for (i = 1; i < argc; i++)
852 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
857 if (tryHandleSimpleOpt(argv, &i) == TRUE)
863 if (argv[i][0] == '-' && argv[i][1] == '-')
865 if (strcmp (argv[i], OPTION_HELP) == 0)
871 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
873 options.stack10bit = 0;
877 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
883 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
885 _setModel (MODEL_LARGE, argv[i]);
889 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
891 _setModel (MODEL_MEDIUM, argv[i]);
895 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
897 _setModel (MODEL_SMALL, argv[i]);
901 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
903 _setModel (MODEL_FLAT24, argv[i]);
907 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
909 options.dump_rassgn =
915 options.dump_raw = 1;
919 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
921 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
925 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
927 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
931 if (strcmp (argv[i], OPTION_VERSION) == 0)
938 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
940 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
944 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
946 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
950 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
952 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
956 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
958 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
962 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
964 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
968 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
970 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
974 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
976 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
977 options.xram_size_set = TRUE;
981 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
983 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
987 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
989 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
993 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
995 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
999 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1001 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1005 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1007 optimize.global_cse = 0;
1011 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1013 optimize.loopInvariant = 0;
1017 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1019 optimize.label4 = 0;
1023 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1025 optimize.loopInduction = 0;
1029 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1031 optimize.codeSpeed = 1;
1032 optimize.codeSize = 0;
1036 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1038 optimize.codeSpeed = 0;
1039 optimize.codeSize = 1;
1043 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1045 options.lessPedantic = 1;
1046 setErrorLogLevel(ERROR_LEVEL_WARNING);
1050 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1052 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1053 if (w < MAX_ERROR_WARNING)
1055 setWarningDisabled(w);
1060 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1062 options.shortis8bits=1;
1066 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1068 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1072 if (!port->parseOption (&argc, argv, &i))
1074 werror (W_UNKNOWN_OPTION, argv[i]);
1083 /* if preceded by '-' then option */
1084 if (*argv[i] == '-')
1089 verifyShortOption(argv[i]);
1096 /* Used to select the port. But this has already been done. */
1100 /* Used to select the processor in port. But this has
1101 * already been done. */
1105 verifyShortOption(argv[i]);
1107 options.cc_only = 1;
1111 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1115 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1122 /* copy the file name into the buffer */
1123 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1125 /* point to last character */
1126 p = buffer + strlen (buffer) - 1;
1127 if (*p == DIR_SEPARATOR_CHAR)
1129 /* only output path specified */
1130 dstPath = Safe_strdup (buffer);
1131 fullDstFileName = NULL;
1135 fullDstFileName = Safe_strdup (buffer);
1137 /* get rid of the "."-extension */
1139 /* is there a dot at all? */
1140 if (strrchr (buffer, '.') &&
1141 /* is the dot in the filename, not in the path? */
1142 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1143 *strrchr (buffer, '.') = '\0';
1145 dstFileName = Safe_strdup (buffer);
1147 /* strip module name to get path */
1148 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1151 /* path with trailing / */
1153 dstPath = Safe_strdup (buffer);
1160 /* pre-processer options */
1161 if (argv[i][2] == 'p')
1163 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1165 /* linker options */
1166 else if (argv[i][2] == 'l')
1168 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1170 /* assembler options */
1171 else if (argv[i][2] == 'a')
1173 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1177 werror (W_UNKNOWN_OPTION, argv[i]);
1182 verifyShortOption(argv[i]);
1184 printVersionInfo ();
1188 /* preprocessor options */
1192 if (argv[i][2] == 'M')
1193 addSet(&preArgvSet, Safe_strdup("-MM"));
1195 addSet(&preArgvSet, Safe_strdup("-M"));
1200 addSet(&preArgvSet, Safe_strdup("-C"));
1210 char sOpt = argv[i][1];
1213 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1219 werror(E_ARGUMENT_MISSING, argv[i-1]);
1233 SNPRINTF (buffer, sizeof(buffer),
1234 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1235 addSet(&preArgvSet, Safe_strdup(buffer));
1237 addSet(&includeDirsSet, Safe_strdup(rest));
1238 addSet(&userIncDirsSet, Safe_strdup(rest));
1244 if (!port->parseOption (&argc, argv, &i))
1245 werror (W_UNKNOWN_OPTION, argv[i]);
1250 if (!port->parseOption (&argc, argv, &i))
1252 /* no option must be a filename */
1255 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1259 processFile (argv[i]);
1264 /* some sanity checks in c1 mode */
1269 if (fullSrcFileName)
1272 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1274 fullSrcFileName = NULL;
1275 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1277 werror (W_NO_FILE_ARG_IN_C1, s);
1279 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1281 werror (W_NO_FILE_ARG_IN_C1, s);
1283 deleteSet(&relFilesSet);
1284 deleteSet(&libFilesSet);
1286 if (options.cc_only || noAssemble || preProcOnly)
1288 werror (W_ILLEGAL_OPT_COMBINATION);
1290 options.cc_only = noAssemble = preProcOnly = 0;
1293 werror (E_NEED_OPT_O_IN_C1);
1297 /* if no dstFileName given with -o, we've to find one: */
1302 /* use the modulename from the C-source */
1303 if (fullSrcFileName)
1305 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1307 dstFileName = Safe_alloc (bufSize);
1308 strncpyz (dstFileName, dstPath, bufSize);
1309 strncatz (dstFileName, moduleNameBase, bufSize);
1311 /* use the modulename from the first object file */
1312 else if ((s = peekSet(relFilesSet)) != NULL)
1317 strncpyz (buffer, s, sizeof(buffer));
1318 /* remove extension (it must be .rel) */
1319 *strrchr (buffer, '.') = '\0';
1321 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1328 objectName = buffer;
1330 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1331 dstFileName = Safe_alloc (bufSize);
1332 strncpyz (dstFileName, dstPath, bufSize);
1333 strncatz (dstFileName, objectName, bufSize);
1335 /* else no module given: help text is displayed */
1338 /* set int, long and float reentrancy based on stack-auto */
1339 if (options.stackAuto)
1341 options.intlong_rent++;
1342 options.float_rent++;
1345 /* set up external stack location if not explicitly specified */
1346 if (!options.xstack_loc)
1347 options.xstack_loc = options.xdata_loc;
1349 /* if debug option is set then open the cdbFile */
1350 if (options.debug && fullSrcFileName)
1352 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1353 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1354 if(debugFile->openFile(scratchFileName))
1355 debugFile->writeModule(moduleName);
1357 werror (E_FILE_OPEN_ERR, scratchFileName);
1359 MSVC_style(options.vc_err_style);
1360 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1365 /*-----------------------------------------------------------------*/
1366 /* linkEdit : - calls the linkage editor with options */
1367 /*-----------------------------------------------------------------*/
1369 linkEdit (char **envp)
1377 if(port->linker.needLinkerScript)
1381 switch (options.out_fmt)
1384 out_fmt = 'i'; /* Intel hex */
1387 out_fmt = 's'; /* Motorola S19 */
1390 out_fmt = 't'; /* Elf */
1396 /* first we need to create the <filename>.lnk file */
1397 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1398 "%s.lnk", dstFileName);
1399 if (!(lnkfile = fopen (scratchFileName, "w")))
1401 werror (E_FILE_OPEN_ERR, scratchFileName);
1405 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1407 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1408 out_fmt, dstFileName);
1410 else /*For all the other ports. Including pics???*/
1412 fprintf (lnkfile, "-myux%c\n", out_fmt);
1413 if(options.pack_iram)
1414 fprintf (lnkfile, "-Y\n");
1417 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1419 /* if iram size specified */
1420 if (options.iram_size)
1421 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1423 /* if stack size specified*/
1424 if(options.stack_size)
1425 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1427 /* if xram size specified */
1428 if (options.xram_size_set)
1429 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1431 /* if code size specified */
1432 if (options.code_size)
1433 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1436 fprintf (lnkfile, "-z\n");
1439 #define WRITE_SEG_LOC(N, L) \
1440 segName = Safe_strdup(N); \
1441 c = strtok(segName, " \t"); \
1442 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1443 if (segName) { Safe_free(segName); }
1445 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1448 /* code segment start */
1449 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1451 /* data segment start. If zero, the linker chooses
1452 the best place for data */
1453 if(options.data_loc)
1455 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1458 /* xdata segment start. If zero, the linker chooses
1459 the best place for xdata */
1460 if(options.xdata_loc)
1462 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1468 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1471 /* bit segment start */
1472 WRITE_SEG_LOC (BIT_NAME, 0);
1475 if ( (options.stack_loc) && (options.stack_loc<0x100) )
1477 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1480 else /*For the z80, gbz80*/
1482 WRITE_SEG_LOC ("_CODE", options.code_loc);
1483 WRITE_SEG_LOC ("_DATA", options.data_loc);
1486 /* If the port has any special linker area declarations, get 'em */
1487 if (port->extraAreas.genExtraAreaLinkOptions)
1489 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1492 /* add the extra linker options */
1493 fputStrSet(lnkfile, linkOptionsSet);
1495 /* command line defined library paths if specified */
1496 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1497 fprintf (lnkfile, "-k %s\n", s);
1499 /* standard library path */
1500 if (!options.nostdlib)
1502 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1504 switch (options.model)
1514 if (TARGET_IS_DS390)
1518 else if (TARGET_IS_DS400)
1525 "Add support for your FLAT24 target in %s @ line %d\n",
1526 __FILE__, __LINE__);
1534 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1539 else /*for the z80, gbz80*/
1543 else if (TARGET_IS_Z80)
1548 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1549 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1552 /* command line defined library files if specified */
1553 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1554 fprintf (lnkfile, "-l %s\n", s);
1556 /* standard library files */
1557 if (!options.nostdlib)
1559 #if !OPT_DISABLE_DS390
1560 if (options.model == MODEL_FLAT24)
1562 if (TARGET_IS_DS390)
1564 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1566 else if (TARGET_IS_DS400)
1568 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1573 "Add support for your FLAT24 target in %s @ line %d\n",
1574 __FILE__, __LINE__);
1580 #if !OPT_DISABLE_XA51
1582 if (options.model == MODEL_PAGE0)
1584 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1588 if (TARGET_IS_MCS51)
1590 fprintf (lnkfile, "-l mcs51\n");
1592 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1593 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1594 { /*Why the z80 port is not using the standard libraries?*/
1595 fprintf (lnkfile, "-l %s\n", STD_LIB);
1596 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1597 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1598 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1600 else if (TARGET_IS_HC08)
1602 fprintf (lnkfile, "-l hc08\n");
1604 else if (TARGET_IS_Z80)
1606 fprintf (lnkfile, "-l z80\n");
1608 else if (TARGET_IS_GBZ80)
1610 fprintf (lnkfile, "-l gbz80\n");
1614 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1615 It is very important for this file to be first on the linking proccess
1616 so the areas are set in the correct order, expecially _GSINIT*/
1617 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1618 !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1620 char crt0path[PATH_MAX];
1622 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1624 sprintf (crt0path, "%s%s%s%scrt0.o",
1625 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1627 crt0fp=fopen(crt0path, "r");
1628 if(crt0fp!=NULL)/*Found it!*/
1633 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1634 windows paths, so convert them to the CYGWIN format*/
1635 char posix_path[PATH_MAX];
1636 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1637 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1638 strcpy(crt0path, posix_path);
1641 fprintf (lnkfile, "%s\n", crt0path);
1645 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1648 /* put in the object files */
1649 if (fullSrcFileName)
1650 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1652 fputStrSet(lnkfile, relFilesSet);
1654 fprintf (lnkfile, "\n-e\n");
1656 } /* if(port->linker.needLinkerScript) */
1658 if (options.verbose)
1659 printf ("sdcc: Calling linker...\n");
1661 /* build linker output filename */
1663 /* -o option overrides default name? */
1664 if (fullDstFileName)
1666 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1670 /* the linked file gets the name of the first modul */
1671 if (fullSrcFileName)
1673 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1677 s = peekSet(relFilesSet);
1681 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1682 /* strip ".rel" extension */
1683 *strrchr (scratchFileName, '.') = '\0';
1685 strncatz (scratchFileName,
1686 options.out_fmt ? ".S19" : ".ihx",
1687 sizeof(scratchFileName));
1690 if (port->linker.cmd)
1692 char buffer2[PATH_MAX];
1693 char buffer3[PATH_MAX];
1694 set *tempSet=NULL, *libSet=NULL;
1696 strcpy(buffer3, dstFileName);
1697 if(TARGET_IS_PIC16) {
1699 /* use $l to set the linker include directories */
1700 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1701 mergeSets(&linkOptionsSet, tempSet);
1703 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1704 mergeSets(&linkOptionsSet, tempSet);
1706 /* use $3 for libraries from command line --> libSet */
1707 mergeSets(&libSet, libFilesSet);
1709 tempSet = appendStrSet(relFilesSet, "", "");
1710 mergeSets(&libSet, tempSet);
1711 // libSet = reverseSet(libSet);
1713 if(fullSrcFileName) {
1714 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1715 /* if it didn't work, revert to old behaviour */
1716 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1717 strcat(buffer3, port->linker.rel_ext);
1719 } else strcpy(buffer3, "");
1722 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1724 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1728 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1731 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1733 system_ret = my_system (buffer);
1734 /* TODO: most linker don't have a -o parameter */
1735 /* -o option overrides default name? */
1736 if (fullDstFileName)
1739 /* the linked file gets the name of the first modul */
1740 if (fullSrcFileName)
1742 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1743 p = strlen (scratchFileName) + scratchFileName;
1747 s = peekSet(relFilesSet);
1751 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1752 /* strip ".rel" extension */
1753 p = strrchr (scratchFileName, '.');
1759 strncatz (scratchFileName,
1760 options.out_fmt ? ".S19" : ".ihx",
1761 sizeof(scratchFileName));
1762 if (strcmp (fullDstFileName, scratchFileName))
1763 unlink (fullDstFileName);
1764 rename (scratchFileName, fullDstFileName);
1766 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1767 q = strrchr (buffer, '.');
1770 /* no extension: append new extensions */
1771 q = strlen (buffer) + buffer;
1775 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1777 strncatz(buffer, ".map", sizeof(buffer));
1778 if (strcmp (scratchFileName, buffer))
1780 rename (scratchFileName, buffer);
1782 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1784 strncatz(buffer, ".mem", sizeof(buffer));
1785 if (strcmp (scratchFileName, buffer))
1787 rename (scratchFileName, buffer);
1791 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1793 strncatz(buffer, ".cdb", sizeof(buffer));
1794 if (strcmp (scratchFileName, buffer))
1796 rename (scratchFileName, buffer);
1797 /* and the OMF file without extension: */
1800 if (strcmp (scratchFileName, buffer))
1802 rename (scratchFileName, buffer);
1811 /*-----------------------------------------------------------------*/
1812 /* assemble - spawns the assembler with arguments */
1813 /*-----------------------------------------------------------------*/
1815 assemble (char **envp)
1817 /* build assembler output filename */
1819 /* -o option overrides default name? */
1820 if (options.cc_only && fullDstFileName) {
1821 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1823 /* the assembled file gets the name of the first modul */
1824 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1825 strncatz (scratchFileName, port->linker.rel_ext,
1826 sizeof(scratchFileName));
1829 if (port->assembler.do_assemble) {
1830 port->assembler.do_assemble(asmOptionsSet);
1832 } else if (port->assembler.cmd) {
1833 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1834 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1837 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1840 if (my_system (buffer)) {
1841 /* either system() or the assembler itself has reported an error
1842 perror ("Cannot exec assembler");
1846 /* TODO: most assembler don't have a -o parameter */
1847 /* -o option overrides default name? */
1848 if (options.cc_only && fullDstFileName) {
1849 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1850 strncatz (scratchFileName,
1851 port->linker.rel_ext,
1852 sizeof(scratchFileName));
1853 if (strcmp (scratchFileName, fullDstFileName))
1854 unlink (fullDstFileName);
1855 rename (scratchFileName, fullDstFileName);
1859 /*-----------------------------------------------------------------*/
1860 /* preProcess - spawns the preprocessor with arguments */
1861 /*-----------------------------------------------------------------*/
1863 preProcess (char **envp)
1872 set *inclList = NULL;
1874 /* if using external stack define the macro */
1875 if (options.useXstack)
1876 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1878 /* set the macro for stack autos */
1879 if (options.stackAuto)
1880 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1882 /* set the macro for stack autos */
1883 if (options.stack10bit)
1884 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1886 /* set the macro for no overlay */
1887 if (options.noOverlay)
1888 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1890 /* set the macro for large model */
1891 switch (options.model)
1894 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1897 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1900 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1903 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1906 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1909 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1912 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1916 /* add port (processor information to processor */
1917 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1918 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1920 /* standard include path */
1921 if (!options.nostdinc) {
1922 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1923 mergeSets(&preArgvSet, inclList);
1926 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1927 Safe_free((void *)s);
1928 if (inclList != NULL)
1929 deleteSet(&inclList);
1931 if (preProcOnly && fullDstFileName)
1933 /* -E and -o given */
1934 setMainValue ("cppoutfilename", fullDstFileName);
1938 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1939 setMainValue ("cppoutfilename", NULL);
1942 if (options.verbose)
1943 printf ("sdcc: Calling preprocessor...\n");
1945 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1948 if (my_system (buffer)) {
1955 yyin = my_popen (buffer);
1957 perror ("Preproc file not found");
1960 addSetHead (&pipeSet, yyin);
1968 setBinPaths(const char *argv0)
1976 * 1. - $SDCCDIR/PREFIX2BIN_DIR
1977 * 2. - path(argv[0])
1981 /* do it in reverse mode, so that addSetHead() can be used
1982 instead of slower addSet() */
1984 if ((p = getBinPath(argv0)) != NULL)
1985 addSetHead(&binPathSet, Safe_strdup(p));
1987 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1988 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1989 addSetHead(&binPathSet, Safe_strdup(buf));
1993 if (options.printSearchDirs) {
1994 printf("programs:\n");
1995 fputStrSet(stdout, binPathSet);
2000 /* Set system include path */
2002 setIncludePath(void)
2009 * 1. - $SDCC_INCLUDE
2010 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2011 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2012 * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2015 includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2017 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2018 addSetHead(&includeDirsSet, p);
2021 if (options.printSearchDirs) {
2022 printf("includedir:\n");
2023 fputStrSet(stdout, includeDirsSet);
2028 /* Set system lib path */
2038 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2039 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2040 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2043 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2045 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2046 addSetHead(&libDirsSet, p);
2049 if (options.printSearchDirs) {
2050 printf("libdir:\n");
2051 fputStrSet(stdout, libDirsSet);
2058 setDataPaths(const char *argv0)
2066 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2067 * 2. - path(argv[0])/BIN2DATA_DIR
2068 * 3. - DATADIR (only on *nix)
2071 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2072 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2073 addSet(&dataDirsSet, Safe_strdup(buf));
2076 if ((p = getBinPath(argv0)) != NULL) {
2077 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2078 addSet(&dataDirsSet, Safe_strdup(buf));
2082 if (peekSet(dataDirsSet) == NULL) {
2083 /* this should never happen... */
2084 wassertl(0, "Can't get binary path");
2087 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2091 if (options.printSearchDirs) {
2092 printf("datadir:\n");
2093 fputStrSet(stdout, dataDirsSet);
2104 populateMainValues (_baseValues);
2105 setMainValue ("port", port->target);
2106 setMainValue ("objext", port->linker.rel_ext);
2107 setMainValue ("asmext", port->assembler.file_ext);
2109 setMainValue ("dstfilename", dstFileName);
2110 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2112 if (options.cc_only && fullDstFileName)
2113 /* compile + assemble and -o given: -o specifies name of object file */
2115 setMainValue ("objdstfilename", fullDstFileName);
2119 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2121 if (fullDstFileName)
2122 /* if we're linking, -o gives the final file name */
2124 setMainValue ("linkdstfilename", fullDstFileName);
2128 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2133 static void doPrintSearchDirs(void)
2135 printf("programs:\n");
2136 fputStrSet(stdout, binPathSet);
2138 printf("datadir:\n");
2139 fputStrSet(stdout, dataDirsSet);
2141 printf("includedir:\n");
2142 fputStrSet(stdout, includeDirsSet);
2144 printf("libdir:\n");
2145 fputStrSet(stdout, libDirsSet);
2146 fputStrSet(stdout, libPathsSet);
2151 sig_handler (int signal)
2158 sig_string = "SIGABRT";
2161 sig_string = "SIGTERM";
2164 sig_string = "SIGINT";
2167 sig_string = "SIGSEGV";
2170 sig_string = "Unknown?";
2173 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2179 * initialises and calls the parser
2183 main (int argc, char **argv, char **envp)
2185 /* turn all optimizations off by default */
2186 memset (&optimize, 0, sizeof (struct optimize));
2188 /*printVersionInfo (); */
2191 fprintf (stderr, "Build error: no ports are enabled.\n");
2195 /* install atexit handler */
2196 atexit(rm_tmpfiles);
2198 /* install signal handler;
2199 it's only purpuse is to call exit() to remove temp files */
2200 if (!getenv("SDCC_LEAVE_SIGNALS"))
2202 signal (SIGABRT, sig_handler);
2203 signal (SIGTERM, sig_handler);
2204 signal (SIGINT , sig_handler);
2205 signal (SIGSEGV, sig_handler);
2208 /* Before parsing the command line options, do a
2209 * search for the port and processor and initialize
2210 * them if they're found. (We can't gurantee that these
2211 * will be the first options specified).
2214 _findPort (argc, argv);
2217 if (strcmp(port->target, "mcs51") == 0) {
2218 printf("DS390 jammed in A\n");
2224 _findProcessor (argc, argv);
2226 /* Initalise the port. */
2230 setDefaultOptions ();
2233 options.model = MODEL_SMALL;
2234 options.stack10bit=0;
2237 parseCmdLine (argc, argv);
2241 setBinPaths(argv[0]);
2242 setDataPaths(argv[0]);
2247 if(options.printSearchDirs)
2248 doPrintSearchDirs();
2250 /* if no input then printUsage & exit */
2251 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2252 if (!options.printSearchDirs)
2258 /* initMem() is expensive, but
2259 initMem() must called before port->finaliseOptions ().
2260 And the z80 port needs port->finaliseOptions(),
2261 even if we're only linking. */
2263 port->finaliseOptions ();
2265 if (fullSrcFileName || options.c1mode)
2275 if (options.verbose)
2276 printf ("sdcc: Generating code...\n");
2282 deleteSetItem(&pipeSet, yyin);
2288 if (port->general.do_glue != NULL)
2289 (*port->general.do_glue)();
2292 /* this shouldn't happen */
2294 /* in case of NDEBUG */
2302 if (!options.c1mode && !noAssemble)
2304 if (options.verbose)
2305 printf ("sdcc: Calling assembler...\n");
2311 if (options.debug && debugFile)
2312 debugFile->closeFile();
2314 if (!options.cc_only &&
2318 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2320 if (port->linker.do_link)
2321 port->linker.do_link ();