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 *libDirsSet = NULL; /* list of lib search directories */
81 /* uncomment JAMIN_DS390 to always override and use ds390 port
82 for mcs51 work. This is temporary, for compatibility testing. */
83 /* #define JAMIN_DS390 */
88 /* Globally accessible scratch buffer for file names. */
89 char scratchFileName[PATH_MAX];
90 char buffer[PATH_MAX * 2];
92 #define OPTION_HELP "-help"
94 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
96 #define OPTION_STACK_8BIT "--stack-8bit"
97 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
98 #define OPTION_LARGE_MODEL "--model-large"
99 #define OPTION_MEDIUM_MODEL "--model-medium"
100 #define OPTION_SMALL_MODEL "--model-small"
101 #define OPTION_FLAT24_MODEL "--model-flat24"
102 #define OPTION_DUMP_ALL "--dumpall"
103 #define OPTION_PEEP_FILE "--peep-file"
104 #define OPTION_LIB_PATH "--lib-path"
105 #define OPTION_XSTACK_LOC "--xstack-loc"
106 #define OPTION_CALLEE_SAVES "--callee-saves"
107 #define OPTION_STACK_LOC "--stack-loc"
108 #define OPTION_XRAM_LOC "--xram-loc"
109 #define OPTION_IRAM_SIZE "--iram-size"
110 #define OPTION_VERSION "--version"
111 #define OPTION_DATA_LOC "--data-loc"
112 #define OPTION_CODE_LOC "--code-loc"
113 #define OPTION_IDATA_LOC "--idata-loc"
114 #define OPTION_NO_LABEL_OPT "--nolabelopt"
115 #define OPTION_NO_LOOP_INV "--noinvariant"
116 #define OPTION_NO_LOOP_IND "--noinduction"
117 #define OPTION_LESS_PEDANTIC "--less-pedantic"
118 #define OPTION_DISABLE_WARNING "--disable-warning"
119 #define OPTION_NO_GCSE "--nogcse"
120 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
121 #define OPTION_TINI_LIBID "--tini-libid"
122 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
123 #define OPTION_XRAM_SIZE "--xram-size"
124 #define OPTION_CODE_SIZE "--code-size"
125 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
126 #define OPTION_ICODE_IN_ASM "--i-code-in-asm"
127 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
128 #define OPTION_MSVC_ERROR_STYLE "--vc"
129 #define OPTION_USE_STDOUT "--use-stdout"
130 #define OPTION_STACK_SIZE "--stack-size"
131 #define OPTION_PACK_IRAM "--pack-iram"
132 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
133 #define OPTION_OPT_CODE_SPEED "--opt-code-speed"
134 #define OPTION_OPT_CODE_SIZE "--opt-code-size"
138 { 0, NULL, NULL, "General options" },
139 { 0, "--help", NULL, "Display this help" },
140 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
141 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
142 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
143 { 'd', NULL, NULL, NULL },
144 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
145 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
146 { 'A', NULL, NULL, NULL },
147 { 'U', NULL, NULL, NULL },
148 { 'C', NULL, NULL, "Preprocessor option" },
149 { 'M', NULL, NULL, "Preprocessor option" },
150 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
151 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
152 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
153 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
154 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
155 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
156 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
157 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
158 { 0, OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
159 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
160 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
161 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
162 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
163 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
164 { 0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions" },
166 { 0, NULL, NULL, "Code generation options"},
167 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
168 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
169 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
170 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
171 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
172 #if !OPT_DISABLE_DS390
173 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
175 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
176 #if !OPT_DISABLE_DS390
177 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
178 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
180 { 0, "--xstack", &options.useXstack, "Use external stack" },
181 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
182 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
183 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
184 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
185 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
186 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
187 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
188 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
189 #if !OPT_DISABLE_DS390
190 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
192 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
193 #if !OPT_DISABLE_TININative
194 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
196 #if !OPT_DISABLE_DS390
197 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
199 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
200 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
202 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
203 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
204 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
205 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
206 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
208 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" },
210 { 0, NULL, NULL, "Optimization options"},
211 { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" },
212 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
213 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
214 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
215 { 0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction" },
216 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
217 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
218 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
219 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
220 { 0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly" },
221 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peephole file" },
222 { 0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size" },
223 { 0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed" },
225 { 0, NULL, NULL, "Internal debugging options"},
226 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
227 { 0, "--dumpgcse", &options.dump_gcse, NULL },
228 { 0, "--dumploop", &options.dump_loop, NULL },
229 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
230 { 0, "--dumpliverange", &options.dump_range, NULL },
231 { 0, "--dumpregpack", &options.dump_pack, NULL },
232 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
233 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
234 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
235 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
237 { 0, NULL, NULL, "Linker options" },
238 { 'l', NULL, NULL, "Include the given library in the link" },
239 { 'L', NULL, NULL, "Add the next field to the library search path" },
240 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
241 { 0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format" },
242 { 0, "--out-fmt-s19", &options.out_fmt, "Output in S19 hex format" },
243 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
244 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
245 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
246 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
247 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
248 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
249 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
250 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
251 { 0, OPTION_IDATA_LOC, NULL, NULL },
252 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
253 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
254 { 0, OPTION_PACK_IRAM, &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
261 /** Table of all unsupported options and help text to display when one
265 /** shortOpt as in OPTIONS. */
267 /** longOpt as in OPTIONS. */
269 /** Message to display inside W_UNSUPPORTED_OPT when this option
274 static const UNSUPPORTEDOPT
275 unsupportedOptTable[] = {
276 { 'X', NULL, "use --xstack-loc instead" },
277 { 'x', NULL, "use --xstack instead" },
278 { 'i', NULL, "use --idata-loc instead" },
279 { 'r', NULL, "use --xdata-loc instead" },
280 { 's', NULL, "use --code-loc instead" },
281 { 'Y', NULL, "use -I instead" }
284 /** List of all default constant macros.
286 static const char *_baseValues[] = {
289 /* Path seperator character */
290 "sep", DIR_SEPARATOR_STRING,
294 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
298 static PORT *_ports[] =
300 #if !OPT_DISABLE_MCS51
303 #if !OPT_DISABLE_GBZ80
312 #if !OPT_DISABLE_DS390
315 #if !OPT_DISABLE_PIC16
321 #if !OPT_DISABLE_TININative
324 #if !OPT_DISABLE_XA51
327 #if !OPT_DISABLE_DS400
330 #if !OPT_DISABLE_HC08
335 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
337 /** Sets the port to the one given by the command line option.
338 @param The name minus the option (eg 'mcs51')
339 @return 0 on success.
342 _setPort (const char *name)
345 for (i = 0; i < NUM_PORTS; i++)
347 if (!strcmp (_ports[i]->target, name))
353 /* Error - didnt find */
354 werror (E_UNKNOWN_TARGET, name);
358 /* Override the default processor with the one specified
359 * on the command line */
361 _setProcessor (char *_processor)
363 port->processor = _processor;
364 fprintf(stderr,"Processor: %s\n",_processor);
368 _validatePorts (void)
371 for (i = 0; i < NUM_PORTS; i++)
373 if (_ports[i]->magic != PORT_MAGIC)
375 /* Uncomment this line to debug which port is causing the problem
376 * (the target name is close to the beginning of the port struct
377 * and probably can be accessed just fine). */
378 fprintf(stderr,"%s :",_ports[i]->target);
379 wassertl (0, "Port definition structure is incomplete");
384 /* search through the command line options for the port */
386 _findPort (int argc, char **argv)
392 if (!strncmp (*argv, "-m", 2))
394 _setPort (*argv + 2);
400 /* Use the first in the list */
404 /* search through the command line options for the processor */
406 _findProcessor (int argc, char **argv)
410 if (!strncmp (*argv, "-p", 2))
412 _setProcessor (*argv + 2);
418 /* no error if processor was not specified. */
421 /*-----------------------------------------------------------------*/
422 /* printVersionInfo - prints the version info */
423 /*-----------------------------------------------------------------*/
425 printVersionInfo (void)
431 for (i = 0; i < NUM_PORTS; i++)
432 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
434 fprintf (stderr, " " SDCC_VERSION_STR
435 #ifdef SDCC_SUB_VERSION_STR
436 "/" SDCC_SUB_VERSION_STR
438 " #%s (" __DATE__ ")"
441 #elif defined __MINGW32__
443 #elif defined __DJGPP__
445 #elif defined(_MSC_VER)
447 #elif defined(__BORLANDC__)
452 , getBuildNumber() );
456 printOptions(const OPTION *optionsTable)
460 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
461 || optionsTable[i].help != NULL;
464 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt
465 && optionsTable[i].help)
467 fprintf (stdout, "\n%s:\n", optionsTable[i].help);
471 fprintf(stdout, " %c%c %-20s %s\n",
472 optionsTable[i].shortOpt !=0 ? '-' : ' ',
473 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
474 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
475 optionsTable[i].help != NULL ? optionsTable[i].help : ""
481 /*-----------------------------------------------------------------*/
482 /* printUsage - prints command line syntax */
483 /*-----------------------------------------------------------------*/
490 "Usage : sdcc [options] filename\n"
494 printOptions(optionsTable);
496 for (i = 0; i < NUM_PORTS; i++)
498 if (_ports[i]->poptions != NULL)
500 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
501 printOptions (_ports[i]->poptions);
508 /*-----------------------------------------------------------------*/
509 /* setParseWithComma - separates string with comma to a set */
510 /*-----------------------------------------------------------------*/
512 setParseWithComma (set **dest, char *src)
517 /* skip the initial white spaces */
518 while (isspace(*src))
521 /* skip the trailing white spaces */
522 length = strlen(src);
523 while (length && isspace(src[length-1]))
524 src[--length] = '\0';
526 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
527 addSet(dest, Safe_strdup(p));
530 /*-----------------------------------------------------------------*/
531 /* setDefaultOptions - sets the default options */
532 /*-----------------------------------------------------------------*/
534 setDefaultOptions (void)
536 /* first the options part */
537 options.stack_loc = 0; /* stack pointer initialised to 0 */
538 options.xstack_loc = 0; /* xternal stack starts at 0 */
539 options.code_loc = 0; /* code starts at 0 */
540 options.data_loc = 0; /* JCF: By default let the linker locate data */
541 options.xdata_loc = 0;
542 options.idata_loc = 0x80;
544 options.model = port->general.default_model;
545 options.nostdlib = 0;
546 options.nostdinc = 0;
548 options.shortis8bits = 0;
550 options.stack10bit=0;
552 /* now for the optimizations */
553 /* turn on the everything */
554 optimize.global_cse = 1;
559 optimize.loopInvariant = 1;
560 optimize.loopInduction = 1;
562 /* now for the ports */
563 port->setDefaultOptions ();
566 /*-----------------------------------------------------------------*/
567 /* processFile - determines the type of file from the extension */
568 /*-----------------------------------------------------------------*/
570 processFile (char *s)
574 /* get the file extension */
575 fext = s + strlen (s);
576 while ((fext != s) && *fext != '.')
579 /* now if no '.' then we don't know what the file type is
580 so give a warning and return */
583 werror (W_UNKNOWN_FEXT, s);
587 /* otherwise depending on the file type */
588 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
590 /* source file name : not if we already have a
594 werror (W_TOO_MANY_SRC, s);
598 /* the only source file */
600 if (!(srcFile = fopen (fullSrcFileName, "r")))
602 werror (E_FILE_OPEN_ERR, s);
606 /* copy the file name into the buffer */
607 strncpyz (buffer, s, sizeof(buffer));
609 /* get rid of the "."-extension */
611 /* is there a dot at all? */
612 if (strrchr (buffer, '.') &&
613 /* is the dot in the filename, not in the path? */
614 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
616 *strrchr (buffer, '.') = '\0';
619 /* get rid of any path information
620 for the module name; */
621 fext = buffer + strlen (buffer);
623 /* do this by going backwards till we
624 get '\' or ':' or start of buffer */
625 while (fext != buffer &&
626 *(fext - 1) != DIR_SEPARATOR_CHAR &&
632 /* do this by going backwards till we
633 get '/' or start of buffer */
634 while (fext != buffer &&
635 *(fext - 1) != DIR_SEPARATOR_CHAR)
640 moduleNameBase = Safe_strdup ( fext );
641 moduleName = Safe_strdup ( fext );
643 for (fext = moduleName; *fext; fext++)
644 if (!isalnum (*fext))
649 /* if the extention is type .rel or .r or .REL or .R
650 addtional object file will be passed to the linker */
651 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
652 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
653 strcmp (fext, port->linker.rel_ext) == 0)
655 addSet(&relFilesSet, Safe_strdup(s));
659 /* if .lib or .LIB */
660 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
662 addSet(&libFilesSet, Safe_strdup(s));
666 werror (W_UNKNOWN_FEXT, s);
671 _setModel (int model, const char *sz)
673 if (port->general.supported_models & model)
674 options.model = model;
676 werror (W_UNSUPPORTED_MODEL, sz, port->target);
679 /** Gets the string argument to this option. If the option is '--opt'
680 then for input of '--optxyz' or '--opt xyz' returns xyz.
683 getStringArg(const char *szStart, char **argv, int *pi, int argc)
685 if (argv[*pi][strlen(szStart)])
687 return &argv[*pi][strlen(szStart)];
694 werror (E_ARGUMENT_MISSING, szStart);
695 /* Die here rather than checking for errors later. */
705 /** Gets the integer argument to this option using the same rules as
709 getIntArg(const char *szStart, char **argv, int *pi, int argc)
711 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
715 verifyShortOption(const char *opt)
717 if (strlen(opt) != 2)
719 werror (W_EXCESS_SHORT_OPTIONS, opt);
724 tryHandleUnsupportedOpt(char **argv, int *pi)
726 if (argv[*pi][0] == '-')
728 const char *longOpt = "";
732 if (argv[*pi][1] == '-')
739 shortOpt = argv[*pi][1];
741 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
743 if (unsupportedOptTable[i].shortOpt == shortOpt ||
744 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
745 /* Found an unsupported opt. */
747 SNPRINTF(buffer, sizeof(buffer),
749 longOpt ? longOpt : "",
750 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
751 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
755 /* Didn't find in the table */
760 /* Not an option, so can't be unsupported :) */
766 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
770 optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL
771 || optionsTable[i].help != NULL;
774 if (optionsTable[i].shortOpt == shortOpt ||
775 (longOpt && optionsTable[i].longOpt &&
776 strcmp(optionsTable[i].longOpt, longOpt) == 0))
779 /* If it is a flag then we can handle it here */
780 if (optionsTable[i].pparameter != NULL)
782 if (optionsTable[i].shortOpt == shortOpt)
784 verifyShortOption(argv[*pi]);
787 (*optionsTable[i].pparameter)++;
791 /* Not a flag. Handled manually later. */
796 /* Didn't find in the table */
801 tryHandleSimpleOpt(char **argv, int *pi)
803 if (argv[*pi][0] == '-')
805 const char *longOpt = "";
808 if (argv[*pi][1] == '-')
815 shortOpt = argv[*pi][1];
818 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
822 else if (port && port->poptions &&
823 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
834 /* Not an option, so can't be handled. */
839 /*-----------------------------------------------------------------*/
840 /* parseCmdLine - parses the command line and sets the options */
841 /*-----------------------------------------------------------------*/
843 parseCmdLine (int argc, char **argv)
847 /* go thru all whole command line */
848 for (i = 1; i < argc; i++)
853 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
858 if (tryHandleSimpleOpt(argv, &i) == TRUE)
864 if (argv[i][0] == '-' && argv[i][1] == '-')
866 if (strcmp (argv[i], OPTION_HELP) == 0)
872 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
874 options.stack10bit = 0;
878 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
884 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
886 _setModel (MODEL_LARGE, argv[i]);
890 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
892 _setModel (MODEL_MEDIUM, argv[i]);
896 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
898 _setModel (MODEL_SMALL, argv[i]);
902 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
904 _setModel (MODEL_FLAT24, argv[i]);
908 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
910 options.dump_rassgn =
916 options.dump_raw = 1;
920 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
922 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
926 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
928 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
932 if (strcmp (argv[i], OPTION_VERSION) == 0)
939 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
941 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
945 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
947 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
951 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
953 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
957 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
959 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
963 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
965 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
969 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
971 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
975 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
977 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
978 options.xram_size_set = TRUE;
982 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
984 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
988 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
990 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
994 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
996 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
1000 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
1002 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
1006 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1008 optimize.global_cse = 0;
1012 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1014 optimize.loopInvariant = 0;
1018 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1020 optimize.label4 = 0;
1024 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1026 optimize.loopInduction = 0;
1030 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1032 optimize.codeSpeed = 1;
1033 optimize.codeSize = 0;
1037 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1039 optimize.codeSpeed = 0;
1040 optimize.codeSize = 1;
1044 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1046 options.lessPedantic = 1;
1047 setErrorLogLevel(ERROR_LEVEL_WARNING);
1051 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1053 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1054 if (w < MAX_ERROR_WARNING)
1056 setWarningDisabled(w);
1061 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1063 options.shortis8bits=1;
1067 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1069 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1073 if (!port->parseOption (&argc, argv, &i))
1075 werror (W_UNKNOWN_OPTION, argv[i]);
1084 /* if preceded by '-' then option */
1085 if (*argv[i] == '-')
1090 verifyShortOption(argv[i]);
1097 /* Used to select the port. But this has already been done. */
1101 /* Used to select the processor in port. But this has
1102 * already been done. */
1106 verifyShortOption(argv[i]);
1108 options.cc_only = 1;
1112 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1116 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1123 /* copy the file name into the buffer */
1124 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1126 /* point to last character */
1127 p = buffer + strlen (buffer) - 1;
1128 if (*p == DIR_SEPARATOR_CHAR)
1130 /* only output path specified */
1131 dstPath = Safe_strdup (buffer);
1132 fullDstFileName = NULL;
1136 fullDstFileName = Safe_strdup (buffer);
1138 /* get rid of the "."-extension */
1140 /* is there a dot at all? */
1141 if (strrchr (buffer, '.') &&
1142 /* is the dot in the filename, not in the path? */
1143 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1144 *strrchr (buffer, '.') = '\0';
1146 dstFileName = Safe_strdup (buffer);
1148 /* strip module name to get path */
1149 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1152 /* path with trailing / */
1154 dstPath = Safe_strdup (buffer);
1161 /* pre-processer options */
1162 if (argv[i][2] == 'p')
1164 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1166 /* linker options */
1167 else if (argv[i][2] == 'l')
1169 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1171 /* assembler options */
1172 else if (argv[i][2] == 'a')
1174 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1178 werror (W_UNKNOWN_OPTION, argv[i]);
1183 verifyShortOption(argv[i]);
1185 printVersionInfo ();
1189 /* preprocessor options */
1193 if (argv[i][2] == 'M')
1194 addSet(&preArgvSet, Safe_strdup("-MM"));
1196 addSet(&preArgvSet, Safe_strdup("-M"));
1201 addSet(&preArgvSet, Safe_strdup("-C"));
1211 char sOpt = argv[i][1];
1214 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1220 werror(E_ARGUMENT_MISSING, argv[i-1]);
1234 SNPRINTF (buffer, sizeof(buffer),
1235 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1236 addSet(&preArgvSet, Safe_strdup(buffer));
1237 if(sOpt == 'I')addSet(&includeDirsSet, Safe_strdup(rest));
1242 if (!port->parseOption (&argc, argv, &i))
1243 werror (W_UNKNOWN_OPTION, argv[i]);
1248 if (!port->parseOption (&argc, argv, &i))
1250 /* no option must be a filename */
1253 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1257 processFile (argv[i]);
1262 /* some sanity checks in c1 mode */
1267 if (fullSrcFileName)
1270 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1272 fullSrcFileName = NULL;
1273 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1275 werror (W_NO_FILE_ARG_IN_C1, s);
1277 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1279 werror (W_NO_FILE_ARG_IN_C1, s);
1281 deleteSet(&relFilesSet);
1282 deleteSet(&libFilesSet);
1284 if (options.cc_only || noAssemble || preProcOnly)
1286 werror (W_ILLEGAL_OPT_COMBINATION);
1288 options.cc_only = noAssemble = preProcOnly = 0;
1291 werror (E_NEED_OPT_O_IN_C1);
1295 /* if no dstFileName given with -o, we've to find one: */
1300 /* use the modulename from the C-source */
1301 if (fullSrcFileName)
1303 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1305 dstFileName = Safe_alloc (bufSize);
1306 strncpyz (dstFileName, dstPath, bufSize);
1307 strncatz (dstFileName, moduleNameBase, bufSize);
1309 /* use the modulename from the first object file */
1310 else if ((s = peekSet(relFilesSet)) != NULL)
1315 strncpyz (buffer, s, sizeof(buffer));
1316 /* remove extension (it must be .rel) */
1317 *strrchr (buffer, '.') = '\0';
1319 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1326 objectName = buffer;
1328 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1329 dstFileName = Safe_alloc (bufSize);
1330 strncpyz (dstFileName, dstPath, bufSize);
1331 strncatz (dstFileName, objectName, bufSize);
1333 /* else no module given: help text is displayed */
1336 /* set up external stack location if not explicitly specified */
1337 if (!options.xstack_loc)
1338 options.xstack_loc = options.xdata_loc;
1340 /* if debug option is set then open the cdbFile */
1341 if (options.debug && fullSrcFileName)
1343 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1344 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1345 if(debugFile->openFile(scratchFileName))
1346 debugFile->writeModule(moduleName);
1348 werror (E_FILE_OPEN_ERR, scratchFileName);
1350 MSVC_style(options.vc_err_style);
1351 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1356 /*-----------------------------------------------------------------*/
1357 /* linkEdit : - calls the linkage editor with options */
1358 /*-----------------------------------------------------------------*/
1360 linkEdit (char **envp)
1368 if(port->linker.needLinkerScript)
1372 switch (options.out_fmt)
1375 out_fmt = 'i'; /* Intel hex */
1378 out_fmt = 's'; /* Motorola S19 */
1381 out_fmt = 't'; /* Elf */
1387 /* first we need to create the <filename>.lnk file */
1388 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1389 "%s.lnk", dstFileName);
1390 if (!(lnkfile = fopen (scratchFileName, "w")))
1392 werror (E_FILE_OPEN_ERR, scratchFileName);
1396 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1398 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1399 out_fmt, dstFileName);
1401 else /*For all the other ports. Including pics???*/
1403 fprintf (lnkfile, "-myux%c\n", out_fmt);
1404 if(options.pack_iram)
1405 fprintf (lnkfile, "-Y\n");
1408 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1410 /* if iram size specified */
1411 if (options.iram_size)
1412 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1414 /* if stack size specified*/
1415 if(options.stack_size)
1416 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1418 /* if xram size specified */
1419 if (options.xram_size_set)
1420 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1422 /* if code size specified */
1423 if (options.code_size)
1424 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1427 fprintf (lnkfile, "-z\n");
1430 #define WRITE_SEG_LOC(N, L) \
1431 segName = Safe_strdup(N); \
1432 c = strtok(segName, " \t"); \
1433 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1434 if (segName) { Safe_free(segName); }
1436 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1439 /* code segment start */
1440 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1442 /* data segment start. If zero, the linker chooses
1443 the best place for data */
1444 if(options.data_loc)
1446 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1450 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1455 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1458 /* bit segment start */
1459 WRITE_SEG_LOC (BIT_NAME, 0);
1462 if ( (options.stack_loc) && (options.stack_loc<0x100) )
1464 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1467 else /*For the z80, gbz80*/
1469 WRITE_SEG_LOC ("_CODE", options.code_loc);
1470 WRITE_SEG_LOC ("_DATA", options.data_loc);
1473 /* If the port has any special linker area declarations, get 'em */
1474 if (port->extraAreas.genExtraAreaLinkOptions)
1476 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1479 /* add the extra linker options */
1480 fputStrSet(lnkfile, linkOptionsSet);
1482 /* command line defined library paths if specified */
1483 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1484 fprintf (lnkfile, "-k %s\n", s);
1486 /* standard library path */
1487 if (!options.nostdlib)
1489 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1491 switch (options.model)
1501 if (TARGET_IS_DS390)
1505 else if (TARGET_IS_DS400)
1512 "Add support for your FLAT24 target in %s @ line %d\n",
1513 __FILE__, __LINE__);
1521 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1526 else /*for the z80, gbz80*/
1530 else if (TARGET_IS_Z80)
1535 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1536 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1539 /* command line defined library files if specified */
1540 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1541 fprintf (lnkfile, "-l %s\n", s);
1543 /* standard library files */
1544 if (!options.nostdlib)
1546 #if !OPT_DISABLE_DS390
1547 if (options.model == MODEL_FLAT24)
1549 if (TARGET_IS_DS390)
1551 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1553 else if (TARGET_IS_DS400)
1555 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1560 "Add support for your FLAT24 target in %s @ line %d\n",
1561 __FILE__, __LINE__);
1567 #if !OPT_DISABLE_XA51
1569 if (options.model == MODEL_PAGE0)
1571 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1575 if (TARGET_IS_MCS51)
1577 fprintf (lnkfile, "-l mcs51\n");
1579 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1580 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1581 { /*Why the z80 port is not using the standard libraries?*/
1582 fprintf (lnkfile, "-l %s\n", STD_LIB);
1583 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1584 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1585 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1587 else if (TARGET_IS_HC08)
1589 fprintf (lnkfile, "-l hc08\n");
1591 else if (TARGET_IS_Z80)
1593 fprintf (lnkfile, "-l z80\n");
1595 else if (TARGET_IS_GBZ80)
1597 fprintf (lnkfile, "-l gbz80\n");
1601 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1602 It is very important for this file to be first on the linking proccess
1603 so the areas are set in the correct order, expecially _GSINIT*/
1604 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1605 !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1607 char crt0path[PATH_MAX];
1609 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1611 sprintf (crt0path, "%s%s%s%scrt0.o",
1612 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1614 crt0fp=fopen(crt0path, "r");
1615 if(crt0fp!=NULL)/*Found it!*/
1620 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1621 windows paths, so convert them to the CYGWIN format*/
1622 char posix_path[PATH_MAX];
1623 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1624 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1625 strcpy(crt0path, posix_path);
1628 fprintf (lnkfile, "%s\n", crt0path);
1632 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1635 /* put in the object files */
1636 if (fullSrcFileName)
1637 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1639 fputStrSet(lnkfile, relFilesSet);
1641 fprintf (lnkfile, "\n-e\n");
1643 } /* if(port->linker.needLinkerScript) */
1645 if (options.verbose)
1646 printf ("sdcc: Calling linker...\n");
1648 /* build linker output filename */
1650 /* -o option overrides default name? */
1651 if (fullDstFileName)
1653 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1657 /* the linked file gets the name of the first modul */
1658 if (fullSrcFileName)
1660 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1664 s = peekSet(relFilesSet);
1668 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1669 /* strip ".rel" extension */
1670 *strrchr (scratchFileName, '.') = '\0';
1672 strncatz (scratchFileName,
1673 options.out_fmt ? ".S19" : ".ihx",
1674 sizeof(scratchFileName));
1677 if (port->linker.cmd)
1679 char buffer2[PATH_MAX];
1680 char buffer3[PATH_MAX];
1681 set *tempSet=NULL, *libSet=NULL;
1683 strcpy(buffer3, dstFileName);
1684 if(TARGET_IS_PIC16) {
1686 /* use $l to set the linker include directories */
1687 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1688 mergeSets(&linkOptionsSet, tempSet);
1690 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1691 mergeSets(&linkOptionsSet, tempSet);
1693 /* use $3 for libraries from command line --> libSet */
1694 mergeSets(&libSet, libFilesSet);
1696 tempSet = appendStrSet(relFilesSet, "", "");
1697 mergeSets(&libSet, tempSet);
1698 // libSet = reverseSet(libSet);
1700 if(fullSrcFileName) {
1701 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1702 /* if it didn't work, revert to old behaviour */
1703 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1704 strcat(buffer3, port->linker.rel_ext);
1706 } else strcpy(buffer3, "");
1709 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1711 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1715 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1718 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1720 system_ret = my_system (buffer);
1721 /* TODO: most linker don't have a -o parameter */
1722 /* -o option overrides default name? */
1723 if (fullDstFileName)
1726 /* the linked file gets the name of the first modul */
1727 if (fullSrcFileName)
1729 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1730 p = strlen (scratchFileName) + scratchFileName;
1734 s = peekSet(relFilesSet);
1738 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1739 /* strip ".rel" extension */
1740 p = strrchr (scratchFileName, '.');
1746 strncatz (scratchFileName,
1747 options.out_fmt ? ".S19" : ".ihx",
1748 sizeof(scratchFileName));
1749 if (strcmp (fullDstFileName, scratchFileName))
1750 unlink (fullDstFileName);
1751 rename (scratchFileName, fullDstFileName);
1753 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1754 q = strrchr (buffer, '.');
1757 /* no extension: append new extensions */
1758 q = strlen (buffer) + buffer;
1762 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1764 strncatz(buffer, ".map", sizeof(buffer));
1765 if (strcmp (scratchFileName, buffer))
1767 rename (scratchFileName, buffer);
1769 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1771 strncatz(buffer, ".mem", sizeof(buffer));
1772 if (strcmp (scratchFileName, buffer))
1774 rename (scratchFileName, buffer);
1778 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1780 strncatz(buffer, ".cdb", sizeof(buffer));
1781 if (strcmp (scratchFileName, buffer))
1783 rename (scratchFileName, buffer);
1784 /* and the OMF file without extension: */
1787 if (strcmp (scratchFileName, buffer))
1789 rename (scratchFileName, buffer);
1798 /*-----------------------------------------------------------------*/
1799 /* assemble - spawns the assembler with arguments */
1800 /*-----------------------------------------------------------------*/
1802 assemble (char **envp)
1804 /* build assembler output filename */
1806 /* -o option overrides default name? */
1807 if (options.cc_only && fullDstFileName) {
1808 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1810 /* the assembled file gets the name of the first modul */
1811 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1812 strncatz (scratchFileName, port->linker.rel_ext,
1813 sizeof(scratchFileName));
1816 if (port->assembler.do_assemble) {
1817 port->assembler.do_assemble(asmOptionsSet);
1819 } else if (port->assembler.cmd) {
1820 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1821 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1824 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1827 if (my_system (buffer)) {
1828 /* either system() or the assembler itself has reported an error
1829 perror ("Cannot exec assembler");
1833 /* TODO: most assembler don't have a -o parameter */
1834 /* -o option overrides default name? */
1835 if (options.cc_only && fullDstFileName) {
1836 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1837 strncatz (scratchFileName,
1838 port->linker.rel_ext,
1839 sizeof(scratchFileName));
1840 if (strcmp (scratchFileName, fullDstFileName))
1841 unlink (fullDstFileName);
1842 rename (scratchFileName, fullDstFileName);
1846 /*-----------------------------------------------------------------*/
1847 /* preProcess - spawns the preprocessor with arguments */
1848 /*-----------------------------------------------------------------*/
1850 preProcess (char **envp)
1859 set *inclList = NULL;
1861 /* if using external stack define the macro */
1862 if (options.useXstack)
1863 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1865 /* set the macro for stack autos */
1866 if (options.stackAuto)
1867 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1869 /* set the macro for stack autos */
1870 if (options.stack10bit)
1871 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1873 /* set the macro for no overlay */
1874 if (options.noOverlay)
1875 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1877 /* set the macro for large model */
1878 switch (options.model)
1881 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1884 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1887 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1890 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1893 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1896 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1899 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1903 /* add port (processor information to processor */
1904 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1905 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1907 /* standard include path */
1908 if (!options.nostdinc) {
1909 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1910 mergeSets(&preArgvSet, inclList);
1913 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1914 Safe_free((void *)s);
1915 if (inclList != NULL)
1916 deleteSet(&inclList);
1918 if (preProcOnly && fullDstFileName)
1920 /* -E and -o given */
1921 setMainValue ("cppoutfilename", fullDstFileName);
1925 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1926 setMainValue ("cppoutfilename", NULL);
1929 if (options.verbose)
1930 printf ("sdcc: Calling preprocessor...\n");
1932 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1935 if (my_system (buffer)) {
1942 yyin = my_popen (buffer);
1944 perror ("Preproc file not found");
1947 addSetHead (&pipeSet, yyin);
1955 setBinPaths(const char *argv0)
1963 * 1. - $SDCCDIR/PREFIX2BIN_DIR
1964 * 2. - path(argv[0])
1968 /* do it in reverse mode, so that addSetHead() can be used
1969 instead of slower addSet() */
1971 if ((p = getBinPath(argv0)) != NULL)
1972 addSetHead(&binPathSet, Safe_strdup(p));
1974 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1975 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1976 addSetHead(&binPathSet, Safe_strdup(buf));
1980 if (options.printSearchDirs) {
1981 printf("programs:\n");
1982 fputStrSet(stdout, binPathSet);
1987 /* Set system include path */
1989 setIncludePath(void)
1996 * 1. - $SDCC_INCLUDE
1997 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1998 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1999 * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2002 includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
2004 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
2005 addSetHead(&includeDirsSet, p);
2008 if (options.printSearchDirs) {
2009 printf("includedir:\n");
2010 fputStrSet(stdout, includeDirsSet);
2015 /* Set system lib path */
2025 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2026 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2027 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2030 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
2032 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
2033 addSetHead(&libDirsSet, p);
2036 if (options.printSearchDirs) {
2037 printf("libdir:\n");
2038 fputStrSet(stdout, libDirsSet);
2045 setDataPaths(const char *argv0)
2053 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2054 * 2. - path(argv[0])/BIN2DATA_DIR
2055 * 3. - DATADIR (only on *nix)
2058 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2059 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2060 addSet(&dataDirsSet, Safe_strdup(buf));
2063 if ((p = getBinPath(argv0)) != NULL) {
2064 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2065 addSet(&dataDirsSet, Safe_strdup(buf));
2069 if (peekSet(dataDirsSet) == NULL) {
2070 /* this should never happen... */
2071 wassertl(0, "Can't get binary path");
2074 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2078 if (options.printSearchDirs) {
2079 printf("datadir:\n");
2080 fputStrSet(stdout, dataDirsSet);
2091 populateMainValues (_baseValues);
2092 setMainValue ("port", port->target);
2093 setMainValue ("objext", port->linker.rel_ext);
2094 setMainValue ("asmext", port->assembler.file_ext);
2096 setMainValue ("dstfilename", dstFileName);
2097 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2099 if (options.cc_only && fullDstFileName)
2100 /* compile + assemble and -o given: -o specifies name of object file */
2102 setMainValue ("objdstfilename", fullDstFileName);
2106 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2108 if (fullDstFileName)
2109 /* if we're linking, -o gives the final file name */
2111 setMainValue ("linkdstfilename", fullDstFileName);
2115 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2120 static void doPrintSearchDirs(void)
2122 printf("programs:\n");
2123 fputStrSet(stdout, binPathSet);
2125 printf("datadir:\n");
2126 fputStrSet(stdout, dataDirsSet);
2128 printf("includedir:\n");
2129 fputStrSet(stdout, includeDirsSet);
2131 printf("libdir:\n");
2132 fputStrSet(stdout, libDirsSet);
2133 fputStrSet(stdout, libPathsSet);
2138 sig_handler (int signal)
2145 sig_string = "SIGABRT";
2148 sig_string = "SIGTERM";
2151 sig_string = "SIGINT";
2154 sig_string = "SIGSEGV";
2157 sig_string = "Unknown?";
2160 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2166 * initialises and calls the parser
2170 main (int argc, char **argv, char **envp)
2172 /* turn all optimizations off by default */
2173 memset (&optimize, 0, sizeof (struct optimize));
2175 /*printVersionInfo (); */
2178 fprintf (stderr, "Build error: no ports are enabled.\n");
2182 /* install atexit handler */
2183 atexit(rm_tmpfiles);
2185 /* install signal handler;
2186 it's only purpuse is to call exit() to remove temp files */
2187 if (!getenv("SDCC_LEAVE_SIGNALS"))
2189 signal (SIGABRT, sig_handler);
2190 signal (SIGTERM, sig_handler);
2191 signal (SIGINT , sig_handler);
2192 signal (SIGSEGV, sig_handler);
2195 /* Before parsing the command line options, do a
2196 * search for the port and processor and initialize
2197 * them if they're found. (We can't gurantee that these
2198 * will be the first options specified).
2201 _findPort (argc, argv);
2204 if (strcmp(port->target, "mcs51") == 0) {
2205 printf("DS390 jammed in A\n");
2211 _findProcessor (argc, argv);
2213 /* Initalise the port. */
2217 setDefaultOptions ();
2220 options.model = MODEL_SMALL;
2221 options.stack10bit=0;
2224 parseCmdLine (argc, argv);
2227 setBinPaths(argv[0]);
2228 setDataPaths(argv[0]);
2233 if(options.printSearchDirs)
2234 doPrintSearchDirs();
2236 /* if no input then printUsage & exit */
2237 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2238 if (!options.printSearchDirs)
2244 /* initMem() is expensive, but
2245 initMem() must called before port->finaliseOptions ().
2246 And the z80 port needs port->finaliseOptions(),
2247 even if we're only linking. */
2249 port->finaliseOptions ();
2251 if (fullSrcFileName || options.c1mode)
2261 if (options.verbose)
2262 printf ("sdcc: Generating code...\n");
2268 deleteSetItem(&pipeSet, yyin);
2274 if (port->general.do_glue != NULL)
2275 (*port->general.do_glue)();
2278 /* this shouldn't happen */
2280 /* in case of NDEBUG */
2288 if (!options.c1mode && !noAssemble)
2290 if (options.verbose)
2291 printf ("sdcc: Calling assembler...\n");
2297 if (options.debug && debugFile)
2298 debugFile->closeFile();
2300 if (!options.cc_only &&
2304 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2306 if (port->linker.do_link)
2307 port->linker.do_link ();