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, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
194 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
195 { 0, "--peep-asm", &options.asmpeep, NULL },
196 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
197 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
198 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
199 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
200 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
201 { 0, "--help", NULL, "Display this help" },
202 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
203 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
204 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
205 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
206 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
207 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
208 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
209 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
210 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
211 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
212 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
213 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"}
216 /** Table of all unsupported options and help text to display when one
220 /** shortOpt as in OPTIONS. */
222 /** longOpt as in OPTIONS. */
224 /** Message to display inside W_UNSUPPORTED_OPT when this option
229 static const UNSUPPORTEDOPT
230 unsupportedOptTable[] = {
231 { 'a', NULL, "use --stack-auto instead." },
232 { 'g', NULL, "use --generic instead" },
233 { 'X', NULL, "use --xstack-loc instead" },
234 { 'x', NULL, "use --xstack instead" },
235 { 'p', NULL, "use --stack-loc instead" },
236 { 'P', NULL, "use --stack-loc instead" },
237 { 'i', NULL, "use --idata-loc instead" },
238 { 'r', NULL, "use --xdata-loc instead" },
239 { 's', NULL, "use --code-loc instead" },
240 { 'Y', NULL, "use -I instead" }
243 /** List of all default constant macros.
245 static const char *_baseValues[] = {
246 "cpp", "{bindir}{sep}sdcpp",
248 /* Path seperator character */
249 "sep", DIR_SEPARATOR_STRING,
253 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
257 static PORT *_ports[] =
259 #if !OPT_DISABLE_MCS51
262 #if !OPT_DISABLE_GBZ80
271 #if !OPT_DISABLE_DS390
277 #if !OPT_DISABLE_I186
280 #if !OPT_DISABLE_TLCS900H
283 #if !OPT_DISABLE_TININative
286 #if !OPT_DISABLE_XA51
291 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
294 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
296 extern void picglue ();
298 /** Sets the port to the one given by the command line option.
299 @param The name minus the option (eg 'mcs51')
300 @return 0 on success.
303 _setPort (const char *name)
306 for (i = 0; i < NUM_PORTS; i++)
308 if (!strcmp (_ports[i]->target, name))
314 /* Error - didnt find */
315 werror (E_UNKNOWN_TARGET, name);
320 _validatePorts (void)
323 for (i = 0; i < NUM_PORTS; i++)
325 if (_ports[i]->magic != PORT_MAGIC)
327 wassertl (0, "Port definition structure is incomplete");
333 _findPort (int argc, char **argv)
339 if (!strncmp (*argv, "-m", 2))
341 _setPort (*argv + 2);
346 /* Use the first in the list */
350 /*-----------------------------------------------------------------*/
351 /* printVersionInfo - prints the version info */
352 /*-----------------------------------------------------------------*/
360 for (i = 0; i < NUM_PORTS; i++)
361 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
363 fprintf (stderr, " %s"
364 #ifdef SDCC_SUB_VERSION_STR
365 "/" SDCC_SUB_VERSION_STR
374 #if defined(_MSC_VER)
386 /*-----------------------------------------------------------------*/
387 /* printUsage - prints command line syntax */
388 /*-----------------------------------------------------------------*/
395 "Usage : sdcc [options] filename\n"
399 for (i = 0; i < LENGTH(optionsTable); i++) {
400 fprintf(stdout, " %c%c %-20s %s\n",
401 optionsTable[i].shortOpt !=0 ? '-' : ' ',
402 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
403 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
404 optionsTable[i].help != NULL ? optionsTable[i].help : ""
410 /*-----------------------------------------------------------------*/
411 /* parseWithComma - separates string with comma */
412 /*-----------------------------------------------------------------*/
414 parseWithComma (char **dest, char *src)
418 strtok (src, "\r\n \t");
419 /* skip the initial white spaces */
420 while (isspace (*src))
437 /*-----------------------------------------------------------------*/
438 /* setDefaultOptions - sets the default options */
439 /*-----------------------------------------------------------------*/
445 for (i = 0; i < 128; i++)
446 preArgv[i] = asmOptions[i] =
447 linkOptions[i] = relFiles[i] = libFiles[i] =
450 /* first the options part */
451 options.stack_loc = 0; /* stack pointer initialised to 0 */
452 options.xstack_loc = 0; /* xternal stack starts at 0 */
453 options.code_loc = 0; /* code starts at 0 */
454 options.data_loc = 0x0030; /* data starts at 0x0030 */
455 options.xdata_loc = 0;
456 options.idata_loc = 0x80;
457 options.genericPtr = 1; /* default on */
459 options.model = port->general.default_model;
460 options.nostdlib = 0;
461 options.nostdinc = 0;
463 options.shortis8bits = 0;
465 options.stack10bit=0;
467 /* now for the optimizations */
468 /* turn on the everything */
469 optimize.global_cse = 1;
474 optimize.loopInvariant = 1;
475 optimize.loopInduction = 1;
477 /* now for the ports */
478 port->setDefaultOptions ();
481 /*-----------------------------------------------------------------*/
482 /* processFile - determines the type of file from the extension */
483 /*-----------------------------------------------------------------*/
485 processFile (char *s)
489 /* get the file extension */
490 fext = s + strlen (s);
491 while ((fext != s) && *fext != '.')
494 /* now if no '.' then we don't know what the file type is
495 so give a warning and return */
498 werror (W_UNKNOWN_FEXT, s);
502 /* otherwise depending on the file type */
503 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
505 /* source file name : not if we already have a
509 werror (W_TOO_MANY_SRC, s);
513 /* the only source file */
514 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
516 werror (E_FILE_OPEN_ERR, s);
520 /* copy the file name into the buffer */
523 /* get rid of the "."-extension */
525 /* is there a dot at all? */
526 if (strchr (buffer, '.') &&
527 /* is the dot in the filename, not in the path? */
528 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
529 strrchr (buffer, '\\') < strrchr (buffer, '.')))
530 *strrchr (buffer, '.') = '\0';
532 srcFileName = Safe_alloc ( strlen (buffer) + 1);
533 strcpy (srcFileName, buffer);
535 /* get rid of any path information
536 for the module name; do this by going
537 backwards till we get to either '/' or '\' or ':'
538 or start of buffer */
539 fext = buffer + strlen (buffer);
540 while (fext != buffer &&
541 *(fext - 1) != '\\' &&
542 *(fext - 1) != '/' &&
545 moduleName = Safe_alloc ( strlen (fext) + 1);
546 strcpy (moduleName, fext);
551 /* if the extention is type .rel or .r or .REL or .R
552 addtional object file will be passed to the linker */
553 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
554 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
555 strcmp (fext, port->linker.rel_ext) == 0)
557 relFiles[nrelFiles++] = s;
561 /* if .lib or .LIB */
562 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
564 libFiles[nlibFiles++] = s;
568 werror (W_UNKNOWN_FEXT, s);
573 _processC1Arg (char *s)
577 if (options.out_name)
579 werror (W_TOO_MANY_SRC, s);
582 options.out_name = Safe_strdup (s);
591 _setModel (int model, const char *sz)
593 if (port->general.supported_models & model)
594 options.model = model;
596 werror (W_UNSUPPORTED_MODEL, sz, port->target);
599 /** Gets the string argument to this option. If the option is '--opt'
600 then for input of '--optxyz' or '--opt xyz' returns xyz.
603 getStringArg(const char *szStart, char **argv, int *pi, int argc)
605 if (argv[*pi][strlen(szStart)])
607 return &argv[*pi][strlen(szStart)];
614 werror (E_ARGUMENT_MISSING, szStart);
615 /* Die here rather than checking for errors later. */
625 /** Gets the integer argument to this option using the same rules as
629 getIntArg(const char *szStart, char **argv, int *pi, int argc)
631 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
635 verifyShortOption(const char *opt)
637 if (strlen(opt) != 2)
639 werror (W_EXCESS_SHORT_OPTIONS, opt);
644 tryHandleUnsupportedOpt(char **argv, int *pi)
646 if (argv[*pi][0] == '-')
648 const char *longOpt = "";
652 if (argv[*pi][1] == '-')
659 shortOpt = argv[*pi][1];
661 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
663 if (unsupportedOptTable[i].shortOpt == shortOpt ||
664 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
665 // Found an unsupported opt.
667 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
668 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
672 // Didn't find in the table
677 // Not an option, so can't be unsupported :)
683 tryHandleSimpleOpt(char **argv, int *pi)
685 if (argv[*pi][0] == '-')
687 const char *longOpt = "";
691 if (argv[*pi][1] == '-')
698 shortOpt = argv[*pi][1];
701 for (i = 0; i < LENGTH(optionsTable); i++)
703 if (optionsTable[i].shortOpt == shortOpt ||
704 (longOpt && optionsTable[i].longOpt &&
705 strcmp(optionsTable[i].longOpt, longOpt) == 0))
708 // If it is a flag then we can handle it here
709 if (optionsTable[i].pparameter != NULL)
711 if (optionsTable[i].shortOpt == shortOpt)
713 verifyShortOption(argv[*pi]);
716 (*optionsTable[i].pparameter)++;
720 // Not a flag. Handled manually later.
725 // Didn't find in the table
730 // Not an option, so can't be handled.
735 /*-----------------------------------------------------------------*/
736 /* parseCmdLine - parses the command line and sets the options */
737 /*-----------------------------------------------------------------*/
739 parseCmdLine (int argc, char **argv)
743 /* go thru all whole command line */
744 for (i = 1; i < argc; i++)
749 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
754 if (tryHandleSimpleOpt(argv, &i) == TRUE)
760 if (argv[i][0] == '-' && argv[i][1] == '-')
762 if (strcmp (argv[i], OPTION_HELP) == 0)
768 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
770 options.stack10bit = 0;
774 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
780 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
782 _setModel (MODEL_LARGE, argv[i]);
786 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
788 _setModel (MODEL_MEDIUM, argv[i]);
792 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
794 _setModel (MODEL_SMALL, argv[i]);
798 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
800 _setModel (MODEL_FLAT24, argv[i]);
804 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
806 options.dump_rassgn =
812 options.dump_raw = 1;
816 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
818 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
822 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
824 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
828 if (strcmp (argv[i], OPTION_VERSION) == 0)
835 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
837 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
841 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
843 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
847 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
849 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
853 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
855 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
859 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
861 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
865 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
867 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
871 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
873 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
877 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
879 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
883 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
885 optimize.global_cse = 0;
889 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
891 optimize.loopInvariant = 0;
895 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
897 optimize.loopInduction = 0;
901 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
903 options.lessPedantic = 1;
904 setErrorLogLevel(ERROR_LEVEL_WARNING);
908 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
910 options.shortis8bits=1;
914 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
916 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
920 if (!port->parseOption (&argc, argv, &i))
922 werror (W_UNKNOWN_OPTION, argv[i]);
930 /* if preceded by '-' then option */
936 verifyShortOption(argv[i]);
943 /* Used to select the port */
944 _setPort (argv[i] + 2);
948 verifyShortOption(argv[i]);
954 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
958 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
962 /* pre-processer options */
963 if (argv[i][2] == 'p')
965 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
968 else if (argv[i][2] == 'l')
970 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
972 /* assembler options */
973 else if (argv[i][2] == 'a')
975 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
979 werror (W_UNKNOWN_OPTION, argv[i]);
984 verifyShortOption(argv[i]);
990 /* preprocessor options */
994 addToList (preArgv, "-M");
999 addToList (preArgv, "-C");
1008 char sOpt = argv[i][1];
1011 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1017 werror(E_ARGUMENT_MISSING, argv[i-1]);
1031 sprintf (buffer, "-%c%s", sOpt, rest);
1032 addToList (preArgv, buffer);
1037 if (!port->parseOption (&argc, argv, &i))
1038 werror (W_UNKNOWN_OPTION, argv[i]);
1043 if (!port->parseOption (&argc, argv, &i))
1045 /* no option must be a filename */
1047 _processC1Arg (argv[i]);
1049 processFile (argv[i]);
1053 /* set up external stack location if not explicitly specified */
1054 if (!options.xstack_loc)
1055 options.xstack_loc = options.xdata_loc;
1057 /* if debug option is set the open the cdbFile */
1058 if (options.debug && srcFileName)
1060 sprintf (scratchFileName, "%s.cdb", srcFileName);
1061 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1062 werror (E_FILE_OPEN_ERR, scratchFileName);
1065 /* add a module record */
1066 fprintf (cdbFile, "M:%s\n", moduleName);
1072 /*-----------------------------------------------------------------*/
1073 /* linkEdit : - calls the linkage editor with options */
1074 /*-----------------------------------------------------------------*/
1076 linkEdit (char **envp)
1083 srcFileName = "temp";
1085 /* first we need to create the <filename>.lnk file */
1086 sprintf (scratchFileName, "%s.lnk", srcFileName);
1087 if (!(lnkfile = fopen (scratchFileName, "w")))
1089 werror (E_FILE_OPEN_ERR, scratchFileName);
1093 /* now write the options */
1094 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1096 /* if iram size specified */
1097 if (options.iram_size)
1098 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1101 fprintf (lnkfile, "-z\n");
1103 #define WRITE_SEG_LOC(N, L) \
1104 segName = Safe_strdup(N); \
1105 c = strtok(segName, " \t"); \
1106 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1107 if (segName) { Safe_free(segName); }
1109 /* code segment start */
1110 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1112 /* data segment start */
1113 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1116 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1119 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1121 /* bit segment start */
1122 WRITE_SEG_LOC (BIT_NAME, 0);
1124 /* add the extra linker options */
1125 for (i = 0; linkOptions[i]; i++)
1126 fprintf (lnkfile, "%s\n", linkOptions[i]);
1128 /* other library paths if specified */
1129 for (i = 0; i < nlibPaths; i++)
1130 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1132 /* standard library path */
1133 if (!options.nostdlib)
1136 if (TARGET_IS_DS390)
1143 switch (options.model)
1156 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1161 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1163 /* standard library files */
1164 /* if (strcmp (port->target, "ds390") == 0) */
1165 if (options.model == MODEL_FLAT24)
1167 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1169 fprintf (lnkfile, "-l %s\n", STD_LIB);
1170 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1171 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1172 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1175 /* additional libraries if any */
1176 for (i = 0; i < nlibFiles; i++)
1177 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1179 /* put in the object files */
1180 if (strcmp (srcFileName, "temp"))
1181 fprintf (lnkfile, "%s ", srcFileName);
1183 for (i = 0; i < nrelFiles; i++)
1184 fprintf (lnkfile, "%s\n", relFiles[i]);
1186 fprintf (lnkfile, "\n-e\n");
1189 if (options.verbose)
1190 printf ("sdcc: Calling linker...\n");
1192 if (port->linker.cmd)
1194 char buffer2[PATH_MAX];
1195 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1196 buildCmdLine2 (buffer, buffer2);
1200 buildCmdLine2 (buffer, port->linker.mcmd);
1203 if (my_system (buffer))
1208 if (strcmp (srcFileName, "temp") == 0)
1210 /* rename "temp.cdb" to "firstRelFile.cdb" */
1211 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1212 f = strcat (f, ".cdb");
1213 rename ("temp.cdb", f);
1218 /*-----------------------------------------------------------------*/
1219 /* assemble - spawns the assembler with arguments */
1220 /*-----------------------------------------------------------------*/
1222 assemble (char **envp)
1224 if (port->assembler.do_assemble) {
1225 port->assembler.do_assemble(asmOptions);
1227 } else if (port->assembler.cmd) {
1228 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1229 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1232 buildCmdLine2 (buffer, port->assembler.mcmd);
1235 if (my_system (buffer)) {
1236 /* either system() or the assembler itself has reported an error
1237 perror ("Cannot exec assembler");
1243 /*-----------------------------------------------------------------*/
1244 /* preProcess - spawns the preprocessor with arguments */
1245 /*-----------------------------------------------------------------*/
1247 preProcess (char **envp)
1251 if (!options.c1mode)
1253 /* if using external stack define the macro */
1254 if (options.useXstack)
1255 addToList (preArgv, "-DSDCC_USE_XSTACK");
1257 /* set the macro for stack autos */
1258 if (options.stackAuto)
1259 addToList (preArgv, "-DSDCC_STACK_AUTO");
1261 /* set the macro for stack autos */
1262 if (options.stack10bit)
1263 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1265 /* set the macro for no overlay */
1266 if (options.noOverlay)
1267 addToList (preArgv, "-DSDCC_NOOVERLAY");
1269 /* set the macro for large model */
1270 switch (options.model)
1273 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1276 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1279 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1282 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1285 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1288 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1292 /* add port (processor information to processor */
1293 addToList (preArgv, "-DSDCC_{port}");
1294 addToList (preArgv, "-D__{port}");
1296 /* standard include path */
1297 if (!options.nostdinc) {
1298 addToList (preArgv, "-I{includedir}");
1301 setMainValue ("cppextraopts", join(preArgv));
1304 preOutName = Safe_strdup (tempfilename ());
1306 /* Have to set cppoutfilename to something, even if just pre-processing. */
1307 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1309 if (options.verbose)
1310 printf ("sdcc: Calling preprocessor...\n");
1312 buildCmdLine2 (buffer, _preCmd);
1314 if (my_system (buffer))
1316 // @FIX: Dario Vecchio 03-05-2001
1319 unlink (preOutName);
1320 Safe_free (preOutName);
1333 preOutName = fullSrcFileName;
1336 yyin = fopen (preOutName, "r");
1339 perror ("Preproc file not found\n");
1347 _setPaths (const char *pprefix)
1350 Given the prefix and how the directories were layed out at
1351 configure time, see if the library and include directories are
1352 where expected. If so, set.
1354 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1355 strcpy (scratchFileName, pprefix);
1356 strcat (scratchFileName, buffer);
1358 if (pathExists (scratchFileName))
1360 setMainValue ("includedir", scratchFileName);
1367 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1368 strcpy (scratchFileName, pprefix);
1369 strcat (scratchFileName, buffer);
1371 if (pathExists (scratchFileName))
1373 setMainValue ("libdir", scratchFileName);
1384 _discoverPaths (const char *argv0)
1387 1. Try the SDCCDIR environment variable.
1388 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1389 and library paths with respect to that. Note that under win32
1390 argv[0] is always the full path to the program.
1391 3. If (1) and (2) fail, fall back to the compile time defaults.
1393 Detecting assumes the same layout as when configured. If the
1394 directories have been further moved about then discovery will
1398 /* Some input cases:
1399 "c:\fish\sdcc\bin\sdcc"
1401 "/home/fish/bin/sdcc"
1403 Note that ./sdcc is explicitly not supported as there isn't
1406 /* bindir is handled differently to the lib and include directories.
1407 It's rather unfortunate, but required due to the different
1408 install and development layouts. Logic is different as well.
1411 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1413 strcpy (scratchFileName, argv0);
1414 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1415 setMainValue ("bindir", scratchFileName);
1416 ExePathList[0] = Safe_strdup (scratchFileName);
1418 else if (getenv (SDCCDIR_NAME) != NULL)
1420 getPathDifference (buffer, PREFIX, BINDIR);
1421 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1422 strcat (scratchFileName, buffer);
1423 setMainValue ("bindir", scratchFileName);
1424 ExePathList[0] = Safe_strdup (scratchFileName);
1428 setMainValue ("bindir", BINDIR);
1429 ExePathList[0] = BINDIR;
1435 if (getenv (SDCCDIR_NAME) != NULL)
1437 if (_setPaths (getenv (SDCCDIR_NAME)))
1439 /* Successfully set. */
1444 /* Include and lib weren't where expected. */
1448 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1450 char *pbase = getPrefixFromBinPath (argv0);
1454 /* A bad path. Skip. */
1458 if (_setPaths (pbase))
1460 /* Successfully set. */
1465 /* Include and lib weren't where expected. */
1470 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1471 setMainValue ("libdir", SDCC_LIB_DIR);
1478 populateMainValues (_baseValues);
1479 setMainValue ("port", port->target);
1480 setMainValue ("objext", port->linker.rel_ext);
1481 setMainValue ("asmext", port->assembler.file_ext);
1483 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1484 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1489 * initialises and calls the parser
1493 main (int argc, char **argv, char **envp)
1495 /* turn all optimizations off by default */
1496 memset (&optimize, 0, sizeof (struct optimize));
1498 /*printVersionInfo (); */
1501 fprintf (stderr, "Build error: no ports are enabled.\n");
1505 _findPort (argc, argv);
1507 if (strcmp(port->target, "mcs51") == 0) {
1508 printf("DS390 jammed in A\n");
1513 /* Initalise the port. */
1517 // Create a default exe search path from the path to the sdcc command
1520 setDefaultOptions ();
1523 options.model = MODEL_SMALL;
1524 options.stack10bit=0;
1527 parseCmdLine (argc, argv);
1529 /* if no input then printUsage & exit */
1530 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1531 (options.c1mode && !srcFileName && !options.out_name))
1538 _discoverPaths (argv[0]);
1546 port->finaliseOptions ();
1554 if (options.verbose)
1555 printf ("sdcc: Generating code...\n");
1561 if (TARGET_IS_PIC) {
1562 /* TSD PIC port hack - if the PIC port option is enabled
1563 and SDCC is used to generate PIC code, then we will
1564 generate .asm files in gpasm's format instead of SDCC's
1567 #if !OPT_DISABLE_PIC
1576 // @FIX: Dario Vecchio 03-05-2001
1579 if (yyin && yyin != stdin)
1581 unlink (preOutName);
1582 Safe_free (preOutName);
1587 if (!options.c1mode && !noAssemble)
1589 if (options.verbose)
1590 printf ("sdcc: Calling assembler...\n");
1596 // @FIX: Dario Vecchio 03-05-2001
1599 if (yyin && yyin != stdin)
1601 unlink (preOutName);
1602 Safe_free (preOutName);
1605 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1618 if (preOutName && !options.c1mode)
1620 unlink (preOutName);
1621 Safe_free (preOutName);
1624 if (!options.cc_only &&
1628 (srcFileName || nrelFiles))
1630 if (port->linker.do_link)
1631 port->linker.do_link ();
1636 if (yyin && yyin != stdin)