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 -------------------------------------------------------------------------*/
31 #include "SDCCmacro.h"
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 /** Name of the environment variable checked for other instalations. */
46 #define SDCCDIR_NAME "SDCCDIR"
49 extern int yyparse ();
51 FILE *srcFile; /* source file */
52 FILE *cdbFile = NULL; /* debugger information output file */
53 char *fullSrcFileName; /* full name for the source file */
54 char *srcFileName; /* source file name with the .c stripped */
55 char *moduleName; /* module name is srcFilename stripped of any path */
56 const char *preArgv[128]; /* pre-processor arguments */
58 struct optimize optimize;
59 struct options options;
60 char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a" */ ;
63 char *linkOptions[128];
64 const char *asmOptions[128];
71 bool verboseExec = FALSE;
74 /* uncomment JAMIN_DS390 to always override and use ds390 port
75 for mcs51 work. This is temporary, for compatibility testing. */
76 /* #define JAMIN_DS390 */
81 // Globally accessible scratch buffer for file names.
82 char scratchFileName[PATH_MAX];
83 char buffer[PATH_MAX];
85 // In MSC VC6 default search path for exe's to path for this
87 char DefaultExePath[128];
89 #define OPTION_HELP "-help"
91 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
93 #define OPTION_STACK_8BIT "--stack-8bit"
94 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
95 #define OPTION_LARGE_MODEL "--model-large"
96 #define OPTION_MEDIUM_MODEL "--model-medium"
97 #define OPTION_SMALL_MODEL "--model-small"
98 #define OPTION_FLAT24_MODEL "--model-flat24"
99 #define OPTION_DUMP_ALL "--dumpall"
100 #define OPTION_PEEP_FILE "--peep-file"
101 #define OPTION_LIB_PATH "--lib-path"
102 #define OPTION_XSTACK_LOC "--xstack-loc"
103 #define OPTION_CALLEE_SAVES "--callee-saves"
104 #define OPTION_STACK_LOC "--stack-loc"
105 #define OPTION_XRAM_LOC "--xram-loc"
106 #define OPTION_IRAM_SIZE "--iram-size"
107 #define OPTION_VERSION "--version"
108 #define OPTION_DATA_LOC "--data-loc"
109 #define OPTION_CODE_LOC "--code-loc"
110 #define OPTION_IDATA_LOC "--idata-loc"
111 #define OPTION_NO_LOOP_INV "--noinvariant"
112 #define OPTION_NO_LOOP_IND "--noinduction"
113 #define OPTION_LESS_PEDANTIC "--lesspedantic"
114 #define OPTION_NO_GCSE "--nogcse"
115 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
116 #define OPTION_TINI_LIBID "--tini-libid"
118 /** Table of all options supported by all ports.
120 * A reference for all options.
121 * An easy way to maintain help for the options.
122 * Automatic support for setting flags on simple options.
125 /** The short option character e.g. 'h' for -h. 0 for none. */
127 /** Long option e.g. "--help". Includes the -- prefix. NULL for
130 /** Pointer to an int that will be incremented every time the
131 option is encountered. May be NULL.
134 /** Help text to go with this option. May be NULL. */
140 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
141 { 'd', NULL, NULL, NULL },
142 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
143 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
144 { 'A', NULL, NULL, NULL },
145 { 'U', NULL, NULL, NULL },
146 { 'C', NULL, NULL, "Preprocessor option" },
147 { 'M', NULL, NULL, "Preprocessor option" },
148 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
149 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
150 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
151 { 'L', NULL, NULL, "Add the next field to the library search path" },
152 { 'l', NULL, NULL, "Include the given library in the link" },
153 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
154 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
155 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
156 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
157 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
158 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
159 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
160 { 0, "--xstack", &options.useXstack, "Use external stack" },
161 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
162 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
163 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
164 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
165 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
166 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
167 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
168 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
169 { 0, "--dumpgcse", &options.dump_gcse, NULL },
170 { 0, "--dumploop", &options.dump_loop, NULL },
171 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
172 { 0, "--dumpliverange", &options.dump_range, NULL },
173 { 0, "--dumpregpack", &options.dump_pack, NULL },
174 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
175 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
176 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
177 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
178 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
179 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
180 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
181 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
182 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
183 { 0, OPTION_IDATA_LOC, NULL, NULL },
184 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
185 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
186 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
187 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
188 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
189 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
190 { 0, "--cyclomatic", &options.cyclomatic, NULL },
191 { 0, "--nooverlay", &options.noOverlay, NULL },
192 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
193 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
194 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
195 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
196 { 0, "--peep-asm", &options.asmpeep, NULL },
197 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
198 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
199 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
200 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
201 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
202 { 0, "--help", NULL, "Display this help" },
203 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
204 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
205 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
206 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
207 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
208 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
209 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
210 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
211 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
212 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
213 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
214 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"}
217 /** Table of all unsupported options and help text to display when one
221 /** shortOpt as in OPTIONS. */
223 /** longOpt as in OPTIONS. */
225 /** Message to display inside W_UNSUPPORTED_OPT when this option
230 static const UNSUPPORTEDOPT
231 unsupportedOptTable[] = {
232 { 'a', NULL, "use --stack-auto instead." },
233 { 'g', NULL, "use --generic instead" },
234 { 'X', NULL, "use --xstack-loc instead" },
235 { 'x', NULL, "use --xstack instead" },
236 { 'p', NULL, "use --stack-loc instead" },
237 { 'P', NULL, "use --stack-loc instead" },
238 { 'i', NULL, "use --idata-loc instead" },
239 { 'r', NULL, "use --xdata-loc instead" },
240 { 's', NULL, "use --code-loc instead" },
241 { 'Y', NULL, "use -I instead" }
244 /** List of all default constant macros.
246 static const char *_baseValues[] = {
247 "cpp", "{bindir}{sep}sdcpp",
249 /* Path seperator character */
250 "sep", DIR_SEPARATOR_STRING,
254 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
258 static PORT *_ports[] =
260 #if !OPT_DISABLE_MCS51
263 #if !OPT_DISABLE_GBZ80
272 #if !OPT_DISABLE_DS390
278 #if !OPT_DISABLE_I186
281 #if !OPT_DISABLE_TLCS900H
284 #if !OPT_DISABLE_TININative
287 #if !OPT_DISABLE_XA51
292 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
295 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
297 extern void picglue ();
299 /** Sets the port to the one given by the command line option.
300 @param The name minus the option (eg 'mcs51')
301 @return 0 on success.
304 _setPort (const char *name)
307 for (i = 0; i < NUM_PORTS; i++)
309 if (!strcmp (_ports[i]->target, name))
315 /* Error - didnt find */
316 werror (E_UNKNOWN_TARGET, name);
321 _validatePorts (void)
324 for (i = 0; i < NUM_PORTS; i++)
326 if (_ports[i]->magic != PORT_MAGIC)
328 wassertl (0, "Port definition structure is incomplete");
334 _findPort (int argc, char **argv)
340 if (!strncmp (*argv, "-m", 2))
342 _setPort (*argv + 2);
347 /* Use the first in the list */
351 /*-----------------------------------------------------------------*/
352 /* printVersionInfo - prints the version info */
353 /*-----------------------------------------------------------------*/
361 for (i = 0; i < NUM_PORTS; i++)
362 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
364 fprintf (stderr, " %s"
365 #ifdef SDCC_SUB_VERSION_STR
366 "/" SDCC_SUB_VERSION_STR
375 #if defined(_MSC_VER)
387 /*-----------------------------------------------------------------*/
388 /* printUsage - prints command line syntax */
389 /*-----------------------------------------------------------------*/
396 "Usage : sdcc [options] filename\n"
400 for (i = 0; i < LENGTH(optionsTable); i++) {
401 fprintf(stdout, " %c%c %-20s %s\n",
402 optionsTable[i].shortOpt !=0 ? '-' : ' ',
403 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
404 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
405 optionsTable[i].help != NULL ? optionsTable[i].help : ""
411 /*-----------------------------------------------------------------*/
412 /* parseWithComma - separates string with comma */
413 /*-----------------------------------------------------------------*/
415 parseWithComma (char **dest, char *src)
419 strtok (src, "\r\n \t");
420 /* skip the initial white spaces */
421 while (isspace (*src))
438 /*-----------------------------------------------------------------*/
439 /* setDefaultOptions - sets the default options */
440 /*-----------------------------------------------------------------*/
446 for (i = 0; i < 128; i++)
447 preArgv[i] = asmOptions[i] =
448 linkOptions[i] = relFiles[i] = libFiles[i] =
451 /* first the options part */
452 options.stack_loc = 0; /* stack pointer initialised to 0 */
453 options.xstack_loc = 0; /* xternal stack starts at 0 */
454 options.code_loc = 0; /* code starts at 0 */
455 options.data_loc = 0x0030; /* data starts at 0x0030 */
456 options.xdata_loc = 0;
457 options.idata_loc = 0x80;
458 options.genericPtr = 1; /* default on */
460 options.model = port->general.default_model;
461 options.nostdlib = 0;
462 options.nostdinc = 0;
464 options.shortis8bits = 0;
466 options.stack10bit=0;
468 /* now for the optimizations */
469 /* turn on the everything */
470 optimize.global_cse = 1;
475 optimize.loopInvariant = 1;
476 optimize.loopInduction = 1;
478 /* now for the ports */
479 port->setDefaultOptions ();
482 /*-----------------------------------------------------------------*/
483 /* processFile - determines the type of file from the extension */
484 /*-----------------------------------------------------------------*/
486 processFile (char *s)
490 /* get the file extension */
491 fext = s + strlen (s);
492 while ((fext != s) && *fext != '.')
495 /* now if no '.' then we don't know what the file type is
496 so give a warning and return */
499 werror (W_UNKNOWN_FEXT, s);
503 /* otherwise depending on the file type */
504 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
506 /* source file name : not if we already have a
510 werror (W_TOO_MANY_SRC, s);
514 /* the only source file */
515 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
517 werror (E_FILE_OPEN_ERR, s);
521 /* copy the file name into the buffer */
524 /* get rid of the "."-extension */
526 /* is there a dot at all? */
527 if (strchr (buffer, '.') &&
528 /* is the dot in the filename, not in the path? */
529 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
530 strrchr (buffer, '\\') < strrchr (buffer, '.')))
531 *strrchr (buffer, '.') = '\0';
533 srcFileName = Safe_alloc ( strlen (buffer) + 1);
534 strcpy (srcFileName, buffer);
536 /* get rid of any path information
537 for the module name; do this by going
538 backwards till we get to either '/' or '\' or ':'
539 or start of buffer */
540 fext = buffer + strlen (buffer);
541 while (fext != buffer &&
542 *(fext - 1) != '\\' &&
543 *(fext - 1) != '/' &&
546 moduleName = Safe_alloc ( strlen (fext) + 1);
547 strcpy (moduleName, fext);
552 /* if the extention is type .rel or .r or .REL or .R
553 addtional object file will be passed to the linker */
554 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
555 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
556 strcmp (fext, port->linker.rel_ext) == 0)
558 relFiles[nrelFiles++] = s;
562 /* if .lib or .LIB */
563 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
565 libFiles[nlibFiles++] = s;
569 werror (W_UNKNOWN_FEXT, s);
574 _processC1Arg (char *s)
578 if (options.out_name)
580 werror (W_TOO_MANY_SRC, s);
583 options.out_name = Safe_strdup (s);
592 _setModel (int model, const char *sz)
594 if (port->general.supported_models & model)
595 options.model = model;
597 werror (W_UNSUPPORTED_MODEL, sz, port->target);
600 /** Gets the string argument to this option. If the option is '--opt'
601 then for input of '--optxyz' or '--opt xyz' returns xyz.
604 getStringArg(const char *szStart, char **argv, int *pi, int argc)
606 if (argv[*pi][strlen(szStart)])
608 return &argv[*pi][strlen(szStart)];
615 werror (E_ARGUMENT_MISSING, szStart);
616 /* Die here rather than checking for errors later. */
626 /** Gets the integer argument to this option using the same rules as
630 getIntArg(const char *szStart, char **argv, int *pi, int argc)
632 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
636 verifyShortOption(const char *opt)
638 if (strlen(opt) != 2)
640 werror (W_EXCESS_SHORT_OPTIONS, opt);
645 tryHandleUnsupportedOpt(char **argv, int *pi)
647 if (argv[*pi][0] == '-')
649 const char *longOpt = "";
653 if (argv[*pi][1] == '-')
660 shortOpt = argv[*pi][1];
662 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
664 if (unsupportedOptTable[i].shortOpt == shortOpt ||
665 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
666 // Found an unsupported opt.
668 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
669 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
673 // Didn't find in the table
678 // Not an option, so can't be unsupported :)
684 tryHandleSimpleOpt(char **argv, int *pi)
686 if (argv[*pi][0] == '-')
688 const char *longOpt = "";
692 if (argv[*pi][1] == '-')
699 shortOpt = argv[*pi][1];
702 for (i = 0; i < LENGTH(optionsTable); i++)
704 if (optionsTable[i].shortOpt == shortOpt ||
705 (longOpt && optionsTable[i].longOpt &&
706 strcmp(optionsTable[i].longOpt, longOpt) == 0))
709 // If it is a flag then we can handle it here
710 if (optionsTable[i].pparameter != NULL)
712 if (optionsTable[i].shortOpt == shortOpt)
714 verifyShortOption(argv[*pi]);
717 (*optionsTable[i].pparameter)++;
721 // Not a flag. Handled manually later.
726 // Didn't find in the table
731 // Not an option, so can't be handled.
736 /*-----------------------------------------------------------------*/
737 /* parseCmdLine - parses the command line and sets the options */
738 /*-----------------------------------------------------------------*/
740 parseCmdLine (int argc, char **argv)
744 /* go thru all whole command line */
745 for (i = 1; i < argc; i++)
750 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
755 if (tryHandleSimpleOpt(argv, &i) == TRUE)
761 if (argv[i][0] == '-' && argv[i][1] == '-')
763 if (strcmp (argv[i], OPTION_HELP) == 0)
769 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
771 options.stack10bit = 0;
775 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
781 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
783 _setModel (MODEL_LARGE, argv[i]);
787 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
789 _setModel (MODEL_MEDIUM, argv[i]);
793 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
795 _setModel (MODEL_SMALL, argv[i]);
799 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
801 _setModel (MODEL_FLAT24, argv[i]);
805 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
807 options.dump_rassgn =
813 options.dump_raw = 1;
817 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
819 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
823 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
825 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
829 if (strcmp (argv[i], OPTION_VERSION) == 0)
836 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
838 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
842 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
844 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
848 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
850 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
854 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
856 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
860 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
862 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
866 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
868 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
872 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
874 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
878 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
880 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
884 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
886 optimize.global_cse = 0;
890 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
892 optimize.loopInvariant = 0;
896 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
898 optimize.loopInduction = 0;
902 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
904 options.lessPedantic = 1;
905 setErrorLogLevel(ERROR_LEVEL_WARNING);
909 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
911 options.shortis8bits=1;
915 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
917 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
921 if (!port->parseOption (&argc, argv, &i))
923 werror (W_UNKNOWN_OPTION, argv[i]);
931 /* if preceded by '-' then option */
937 verifyShortOption(argv[i]);
944 /* Used to select the port */
945 _setPort (argv[i] + 2);
949 verifyShortOption(argv[i]);
955 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
959 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
963 /* pre-processer options */
964 if (argv[i][2] == 'p')
966 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
969 else if (argv[i][2] == 'l')
971 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
973 /* assembler options */
974 else if (argv[i][2] == 'a')
976 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
980 werror (W_UNKNOWN_OPTION, argv[i]);
985 verifyShortOption(argv[i]);
991 /* preprocessor options */
995 addToList (preArgv, "-M");
1000 addToList (preArgv, "-C");
1009 char sOpt = argv[i][1];
1012 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1018 werror(E_ARGUMENT_MISSING, argv[i-1]);
1032 sprintf (buffer, "-%c%s", sOpt, rest);
1033 addToList (preArgv, buffer);
1038 if (!port->parseOption (&argc, argv, &i))
1039 werror (W_UNKNOWN_OPTION, argv[i]);
1044 if (!port->parseOption (&argc, argv, &i))
1046 /* no option must be a filename */
1048 _processC1Arg (argv[i]);
1050 processFile (argv[i]);
1054 /* set up external stack location if not explicitly specified */
1055 if (!options.xstack_loc)
1056 options.xstack_loc = options.xdata_loc;
1058 /* if debug option is set the open the cdbFile */
1059 if (options.debug && srcFileName)
1061 sprintf (scratchFileName, "%s.cdb", srcFileName);
1062 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1063 werror (E_FILE_OPEN_ERR, scratchFileName);
1066 /* add a module record */
1067 fprintf (cdbFile, "M:%s\n", moduleName);
1073 /*-----------------------------------------------------------------*/
1074 /* linkEdit : - calls the linkage editor with options */
1075 /*-----------------------------------------------------------------*/
1077 linkEdit (char **envp)
1084 srcFileName = "temp";
1086 /* first we need to create the <filename>.lnk file */
1087 sprintf (scratchFileName, "%s.lnk", srcFileName);
1088 if (!(lnkfile = fopen (scratchFileName, "w")))
1090 werror (E_FILE_OPEN_ERR, scratchFileName);
1094 /* now write the options */
1095 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1097 /* if iram size specified */
1098 if (options.iram_size)
1099 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1102 fprintf (lnkfile, "-z\n");
1104 #define WRITE_SEG_LOC(N, L) \
1105 segName = Safe_strdup(N); \
1106 c = strtok(segName, " \t"); \
1107 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1108 if (segName) { Safe_free(segName); }
1110 /* code segment start */
1111 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1113 /* data segment start */
1114 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1117 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1120 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1122 /* bit segment start */
1123 WRITE_SEG_LOC (BIT_NAME, 0);
1125 /* add the extra linker options */
1126 for (i = 0; linkOptions[i]; i++)
1127 fprintf (lnkfile, "%s\n", linkOptions[i]);
1129 /* other library paths if specified */
1130 for (i = 0; i < nlibPaths; i++)
1131 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1133 /* standard library path */
1134 if (!options.nostdlib)
1137 if (TARGET_IS_DS390)
1144 switch (options.model)
1157 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1162 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1164 /* standard library files */
1165 /* if (strcmp (port->target, "ds390") == 0) */
1166 if (options.model == MODEL_FLAT24)
1168 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1170 fprintf (lnkfile, "-l %s\n", STD_LIB);
1171 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1172 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1173 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1176 /* additional libraries if any */
1177 for (i = 0; i < nlibFiles; i++)
1178 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1180 /* put in the object files */
1181 if (strcmp (srcFileName, "temp"))
1182 fprintf (lnkfile, "%s ", srcFileName);
1184 for (i = 0; i < nrelFiles; i++)
1185 fprintf (lnkfile, "%s\n", relFiles[i]);
1187 fprintf (lnkfile, "\n-e\n");
1190 if (options.verbose)
1191 printf ("sdcc: Calling linker...\n");
1193 if (port->linker.cmd)
1195 char buffer2[PATH_MAX];
1196 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1197 buildCmdLine2 (buffer, buffer2);
1201 buildCmdLine2 (buffer, port->linker.mcmd);
1204 if (my_system (buffer))
1209 if (strcmp (srcFileName, "temp") == 0)
1211 /* rename "temp.cdb" to "firstRelFile.cdb" */
1212 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1213 f = strcat (f, ".cdb");
1214 rename ("temp.cdb", f);
1219 /*-----------------------------------------------------------------*/
1220 /* assemble - spawns the assembler with arguments */
1221 /*-----------------------------------------------------------------*/
1223 assemble (char **envp)
1225 if (port->assembler.do_assemble) {
1226 port->assembler.do_assemble(asmOptions);
1228 } else if (port->assembler.cmd) {
1229 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1230 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1233 buildCmdLine2 (buffer, port->assembler.mcmd);
1236 if (my_system (buffer)) {
1237 /* either system() or the assembler itself has reported an error
1238 perror ("Cannot exec assembler");
1244 /*-----------------------------------------------------------------*/
1245 /* preProcess - spawns the preprocessor with arguments */
1246 /*-----------------------------------------------------------------*/
1248 preProcess (char **envp)
1252 if (!options.c1mode)
1254 /* if using external stack define the macro */
1255 if (options.useXstack)
1256 addToList (preArgv, "-DSDCC_USE_XSTACK");
1258 /* set the macro for stack autos */
1259 if (options.stackAuto)
1260 addToList (preArgv, "-DSDCC_STACK_AUTO");
1262 /* set the macro for stack autos */
1263 if (options.stack10bit)
1264 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1266 /* set the macro for no overlay */
1267 if (options.noOverlay)
1268 addToList (preArgv, "-DSDCC_NOOVERLAY");
1270 /* set the macro for large model */
1271 switch (options.model)
1274 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1277 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1280 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1283 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1286 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1289 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1293 /* add port (processor information to processor */
1294 addToList (preArgv, "-DSDCC_{port}");
1295 addToList (preArgv, "-D__{port}");
1297 /* standard include path */
1298 if (!options.nostdinc) {
1299 addToList (preArgv, "-I{includedir}");
1302 setMainValue ("cppextraopts", join(preArgv));
1305 preOutName = Safe_strdup (tempfilename ());
1307 /* Have to set cppoutfilename to something, even if just pre-processing. */
1308 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1310 if (options.verbose)
1311 printf ("sdcc: Calling preprocessor...\n");
1313 buildCmdLine2 (buffer, _preCmd);
1315 if (my_system (buffer))
1317 // @FIX: Dario Vecchio 03-05-2001
1320 unlink (preOutName);
1321 Safe_free (preOutName);
1334 preOutName = fullSrcFileName;
1337 yyin = fopen (preOutName, "r");
1340 perror ("Preproc file not found\n");
1348 _setPaths (const char *pprefix)
1351 Given the prefix and how the directories were layed out at
1352 configure time, see if the library and include directories are
1353 where expected. If so, set.
1355 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1356 strcpy (scratchFileName, pprefix);
1357 strcat (scratchFileName, buffer);
1359 if (pathExists (scratchFileName))
1361 setMainValue ("includedir", scratchFileName);
1368 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1369 strcpy (scratchFileName, pprefix);
1370 strcat (scratchFileName, buffer);
1372 if (pathExists (scratchFileName))
1374 setMainValue ("libdir", scratchFileName);
1385 _discoverPaths (const char *argv0)
1388 1. Try the SDCCDIR environment variable.
1389 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1390 and library paths with respect to that. Note that under win32
1391 argv[0] is always the full path to the program.
1392 3. If (1) and (2) fail, fall back to the compile time defaults.
1394 Detecting assumes the same layout as when configured. If the
1395 directories have been further moved about then discovery will
1399 /* Some input cases:
1400 "c:\fish\sdcc\bin\sdcc"
1402 "/home/fish/bin/sdcc"
1404 Note that ./sdcc is explicitly not supported as there isn't
1407 /* bindir is handled differently to the lib and include directories.
1408 It's rather unfortunate, but required due to the different
1409 install and development layouts. Logic is different as well.
1412 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1414 strcpy (scratchFileName, argv0);
1415 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1416 setMainValue ("bindir", scratchFileName);
1417 ExePathList[0] = Safe_strdup (scratchFileName);
1419 else if (getenv (SDCCDIR_NAME) != NULL)
1421 getPathDifference (buffer, PREFIX, BINDIR);
1422 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1423 strcat (scratchFileName, buffer);
1424 setMainValue ("bindir", scratchFileName);
1425 ExePathList[0] = Safe_strdup (scratchFileName);
1429 setMainValue ("bindir", BINDIR);
1430 ExePathList[0] = BINDIR;
1436 if (getenv (SDCCDIR_NAME) != NULL)
1438 if (_setPaths (getenv (SDCCDIR_NAME)))
1440 /* Successfully set. */
1445 /* Include and lib weren't where expected. */
1449 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1451 char *pbase = getPrefixFromBinPath (argv0);
1455 /* A bad path. Skip. */
1459 if (_setPaths (pbase))
1461 /* Successfully set. */
1466 /* Include and lib weren't where expected. */
1471 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1472 setMainValue ("libdir", SDCC_LIB_DIR);
1479 populateMainValues (_baseValues);
1480 setMainValue ("port", port->target);
1481 setMainValue ("objext", port->linker.rel_ext);
1482 setMainValue ("asmext", port->assembler.file_ext);
1484 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1485 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1490 * initialises and calls the parser
1494 main (int argc, char **argv, char **envp)
1496 /* turn all optimizations off by default */
1497 memset (&optimize, 0, sizeof (struct optimize));
1499 /*printVersionInfo (); */
1502 fprintf (stderr, "Build error: no ports are enabled.\n");
1506 _findPort (argc, argv);
1508 if (strcmp(port->target, "mcs51") == 0) {
1509 printf("DS390 jammed in A\n");
1514 /* Initalise the port. */
1518 // Create a default exe search path from the path to the sdcc command
1521 setDefaultOptions ();
1524 options.model = MODEL_SMALL;
1525 options.stack10bit=0;
1528 parseCmdLine (argc, argv);
1530 /* if no input then printUsage & exit */
1531 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1532 (options.c1mode && !srcFileName && !options.out_name))
1539 _discoverPaths (argv[0]);
1547 port->finaliseOptions ();
1555 if (options.verbose)
1556 printf ("sdcc: Generating code...\n");
1562 if (TARGET_IS_PIC) {
1563 /* TSD PIC port hack - if the PIC port option is enabled
1564 and SDCC is used to generate PIC code, then we will
1565 generate .asm files in gpasm's format instead of SDCC's
1568 #if !OPT_DISABLE_PIC
1577 // @FIX: Dario Vecchio 03-05-2001
1580 if (yyin && yyin != stdin)
1582 unlink (preOutName);
1583 Safe_free (preOutName);
1588 if (!options.c1mode && !noAssemble)
1590 if (options.verbose)
1591 printf ("sdcc: Calling assembler...\n");
1597 // @FIX: Dario Vecchio 03-05-2001
1600 if (yyin && yyin != stdin)
1602 unlink (preOutName);
1603 Safe_free (preOutName);
1606 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1619 if (preOutName && !options.c1mode)
1621 unlink (preOutName);
1622 Safe_free (preOutName);
1625 if (!options.cc_only &&
1629 (srcFileName || nrelFiles))
1631 if (port->linker.do_link)
1632 port->linker.do_link ();
1637 if (yyin && yyin != stdin)