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;
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"},
215 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
216 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"}
219 /** Table of all unsupported options and help text to display when one
223 /** shortOpt as in OPTIONS. */
225 /** longOpt as in OPTIONS. */
227 /** Message to display inside W_UNSUPPORTED_OPT when this option
232 static const UNSUPPORTEDOPT
233 unsupportedOptTable[] = {
234 { 'a', NULL, "use --stack-auto instead." },
235 { 'g', NULL, "use --generic instead" },
236 { 'X', NULL, "use --xstack-loc instead" },
237 { 'x', NULL, "use --xstack instead" },
238 { 'p', NULL, "use --stack-loc instead" },
239 { 'P', NULL, "use --stack-loc instead" },
240 { 'i', NULL, "use --idata-loc instead" },
241 { 'r', NULL, "use --xdata-loc instead" },
242 { 's', NULL, "use --code-loc instead" },
243 { 'Y', NULL, "use -I instead" }
246 /** List of all default constant macros.
248 static const char *_baseValues[] = {
249 "cpp", "{bindir}{sep}sdcpp",
251 /* Path seperator character */
252 "sep", DIR_SEPARATOR_STRING,
256 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
260 static PORT *_ports[] =
262 #if !OPT_DISABLE_MCS51
265 #if !OPT_DISABLE_GBZ80
274 #if !OPT_DISABLE_DS390
280 #if !OPT_DISABLE_I186
283 #if !OPT_DISABLE_TLCS900H
286 #if !OPT_DISABLE_TININative
289 #if !OPT_DISABLE_XA51
294 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
297 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
299 extern void picglue ();
301 /** Sets the port to the one given by the command line option.
302 @param The name minus the option (eg 'mcs51')
303 @return 0 on success.
306 _setPort (const char *name)
309 for (i = 0; i < NUM_PORTS; i++)
311 if (!strcmp (_ports[i]->target, name))
317 /* Error - didnt find */
318 werror (E_UNKNOWN_TARGET, name);
323 _validatePorts (void)
326 for (i = 0; i < NUM_PORTS; i++)
328 if (_ports[i]->magic != PORT_MAGIC)
330 wassertl (0, "Port definition structure is incomplete");
336 _findPort (int argc, char **argv)
342 if (!strncmp (*argv, "-m", 2))
344 _setPort (*argv + 2);
349 /* Use the first in the list */
353 /*-----------------------------------------------------------------*/
354 /* printVersionInfo - prints the version info */
355 /*-----------------------------------------------------------------*/
363 for (i = 0; i < NUM_PORTS; i++)
364 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
366 fprintf (stderr, " %s"
367 #ifdef SDCC_SUB_VERSION_STR
368 "/" SDCC_SUB_VERSION_STR
377 #if defined(_MSC_VER)
389 /*-----------------------------------------------------------------*/
390 /* printUsage - prints command line syntax */
391 /*-----------------------------------------------------------------*/
398 "Usage : sdcc [options] filename\n"
402 for (i = 0; i < LENGTH(optionsTable); i++) {
403 fprintf(stdout, " %c%c %-20s %s\n",
404 optionsTable[i].shortOpt !=0 ? '-' : ' ',
405 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
406 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
407 optionsTable[i].help != NULL ? optionsTable[i].help : ""
413 /*-----------------------------------------------------------------*/
414 /* parseWithComma - separates string with comma */
415 /*-----------------------------------------------------------------*/
417 parseWithComma (char **dest, char *src)
421 strtok (src, "\r\n \t");
422 /* skip the initial white spaces */
423 while (isspace (*src))
440 /*-----------------------------------------------------------------*/
441 /* setDefaultOptions - sets the default options */
442 /*-----------------------------------------------------------------*/
448 for (i = 0; i < 128; i++)
449 preArgv[i] = asmOptions[i] =
450 linkOptions[i] = relFiles[i] = libFiles[i] =
453 /* first the options part */
454 options.stack_loc = 0; /* stack pointer initialised to 0 */
455 options.xstack_loc = 0; /* xternal stack starts at 0 */
456 options.code_loc = 0; /* code starts at 0 */
457 options.data_loc = 0x0030; /* data starts at 0x0030 */
458 options.xdata_loc = 0;
459 options.idata_loc = 0x80;
460 options.genericPtr = 1; /* default on */
462 options.model = port->general.default_model;
463 options.nostdlib = 0;
464 options.nostdinc = 0;
466 options.shortis8bits = 0;
468 options.stack10bit=0;
470 /* now for the optimizations */
471 /* turn on the everything */
472 optimize.global_cse = 1;
477 optimize.loopInvariant = 1;
478 optimize.loopInduction = 1;
480 /* now for the ports */
481 port->setDefaultOptions ();
484 /*-----------------------------------------------------------------*/
485 /* processFile - determines the type of file from the extension */
486 /*-----------------------------------------------------------------*/
488 processFile (char *s)
492 /* get the file extension */
493 fext = s + strlen (s);
494 while ((fext != s) && *fext != '.')
497 /* now if no '.' then we don't know what the file type is
498 so give a warning and return */
501 werror (W_UNKNOWN_FEXT, s);
505 /* otherwise depending on the file type */
506 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
508 /* source file name : not if we already have a
512 werror (W_TOO_MANY_SRC, s);
516 /* the only source file */
517 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
519 werror (E_FILE_OPEN_ERR, s);
523 /* copy the file name into the buffer */
526 /* get rid of the "."-extension */
528 /* is there a dot at all? */
529 if (strchr (buffer, '.') &&
530 /* is the dot in the filename, not in the path? */
531 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
532 strrchr (buffer, '\\') < strrchr (buffer, '.')))
533 *strrchr (buffer, '.') = '\0';
535 srcFileName = Safe_alloc ( strlen (buffer) + 1);
536 strcpy (srcFileName, buffer);
538 /* get rid of any path information
539 for the module name; do this by going
540 backwards till we get to either '/' or '\' or ':'
541 or start of buffer */
542 fext = buffer + strlen (buffer);
543 while (fext != buffer &&
544 *(fext - 1) != '\\' &&
545 *(fext - 1) != '/' &&
548 moduleName = Safe_alloc ( strlen (fext) + 1);
549 strcpy (moduleName, fext);
554 /* if the extention is type .rel or .r or .REL or .R
555 addtional object file will be passed to the linker */
556 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
557 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
558 strcmp (fext, port->linker.rel_ext) == 0)
560 relFiles[nrelFiles++] = s;
564 /* if .lib or .LIB */
565 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
567 libFiles[nlibFiles++] = s;
571 werror (W_UNKNOWN_FEXT, s);
576 _processC1Arg (char *s)
580 if (options.out_name)
582 werror (W_TOO_MANY_SRC, s);
585 options.out_name = Safe_strdup (s);
594 _setModel (int model, const char *sz)
596 if (port->general.supported_models & model)
597 options.model = model;
599 werror (W_UNSUPPORTED_MODEL, sz, port->target);
602 /** Gets the string argument to this option. If the option is '--opt'
603 then for input of '--optxyz' or '--opt xyz' returns xyz.
606 getStringArg(const char *szStart, char **argv, int *pi, int argc)
608 if (argv[*pi][strlen(szStart)])
610 return &argv[*pi][strlen(szStart)];
617 werror (E_ARGUMENT_MISSING, szStart);
618 /* Die here rather than checking for errors later. */
628 /** Gets the integer argument to this option using the same rules as
632 getIntArg(const char *szStart, char **argv, int *pi, int argc)
634 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
638 verifyShortOption(const char *opt)
640 if (strlen(opt) != 2)
642 werror (W_EXCESS_SHORT_OPTIONS, opt);
647 tryHandleUnsupportedOpt(char **argv, int *pi)
649 if (argv[*pi][0] == '-')
651 const char *longOpt = "";
655 if (argv[*pi][1] == '-')
662 shortOpt = argv[*pi][1];
664 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
666 if (unsupportedOptTable[i].shortOpt == shortOpt ||
667 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
668 // Found an unsupported opt.
670 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
671 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
675 // Didn't find in the table
680 // Not an option, so can't be unsupported :)
686 tryHandleSimpleOpt(char **argv, int *pi)
688 if (argv[*pi][0] == '-')
690 const char *longOpt = "";
694 if (argv[*pi][1] == '-')
701 shortOpt = argv[*pi][1];
704 for (i = 0; i < LENGTH(optionsTable); i++)
706 if (optionsTable[i].shortOpt == shortOpt ||
707 (longOpt && optionsTable[i].longOpt &&
708 strcmp(optionsTable[i].longOpt, longOpt) == 0))
711 // If it is a flag then we can handle it here
712 if (optionsTable[i].pparameter != NULL)
714 if (optionsTable[i].shortOpt == shortOpt)
716 verifyShortOption(argv[*pi]);
719 (*optionsTable[i].pparameter)++;
723 // Not a flag. Handled manually later.
728 // Didn't find in the table
733 // Not an option, so can't be handled.
738 /*-----------------------------------------------------------------*/
739 /* parseCmdLine - parses the command line and sets the options */
740 /*-----------------------------------------------------------------*/
742 parseCmdLine (int argc, char **argv)
746 /* go thru all whole command line */
747 for (i = 1; i < argc; i++)
752 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
757 if (tryHandleSimpleOpt(argv, &i) == TRUE)
763 if (argv[i][0] == '-' && argv[i][1] == '-')
765 if (strcmp (argv[i], OPTION_HELP) == 0)
771 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
773 options.stack10bit = 0;
777 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
783 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
785 _setModel (MODEL_LARGE, argv[i]);
789 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
791 _setModel (MODEL_MEDIUM, argv[i]);
795 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
797 _setModel (MODEL_SMALL, argv[i]);
801 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
803 _setModel (MODEL_FLAT24, argv[i]);
807 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
809 options.dump_rassgn =
815 options.dump_raw = 1;
819 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
821 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
825 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
827 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
831 if (strcmp (argv[i], OPTION_VERSION) == 0)
838 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
840 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
844 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
846 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
850 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
852 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
856 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
858 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
862 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
864 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
868 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
870 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
874 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
876 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
880 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
882 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
886 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
888 optimize.global_cse = 0;
892 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
894 optimize.loopInvariant = 0;
898 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
900 optimize.loopInduction = 0;
904 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
906 options.lessPedantic = 1;
907 setErrorLogLevel(ERROR_LEVEL_WARNING);
911 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
913 options.shortis8bits=1;
917 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
919 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
923 if (!port->parseOption (&argc, argv, &i))
925 werror (W_UNKNOWN_OPTION, argv[i]);
933 /* if preceded by '-' then option */
939 verifyShortOption(argv[i]);
946 /* Used to select the port */
947 _setPort (argv[i] + 2);
951 verifyShortOption(argv[i]);
957 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
961 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
965 /* pre-processer options */
966 if (argv[i][2] == 'p')
968 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
971 else if (argv[i][2] == 'l')
973 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
975 /* assembler options */
976 else if (argv[i][2] == 'a')
978 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
982 werror (W_UNKNOWN_OPTION, argv[i]);
987 verifyShortOption(argv[i]);
993 /* preprocessor options */
997 addToList (preArgv, "-M");
1002 addToList (preArgv, "-C");
1011 char sOpt = argv[i][1];
1014 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1020 werror(E_ARGUMENT_MISSING, argv[i-1]);
1034 sprintf (buffer, "-%c%s", sOpt, rest);
1035 addToList (preArgv, buffer);
1040 if (!port->parseOption (&argc, argv, &i))
1041 werror (W_UNKNOWN_OPTION, argv[i]);
1046 if (!port->parseOption (&argc, argv, &i))
1048 /* no option must be a filename */
1050 _processC1Arg (argv[i]);
1052 processFile (argv[i]);
1056 /* set up external stack location if not explicitly specified */
1057 if (!options.xstack_loc)
1058 options.xstack_loc = options.xdata_loc;
1060 /* if debug option is set the open the cdbFile */
1061 if (options.debug && srcFileName)
1063 sprintf (scratchFileName, "%s.cdb", srcFileName);
1064 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1065 werror (E_FILE_OPEN_ERR, scratchFileName);
1068 /* add a module record */
1069 fprintf (cdbFile, "M:%s\n", moduleName);
1075 /*-----------------------------------------------------------------*/
1076 /* linkEdit : - calls the linkage editor with options */
1077 /*-----------------------------------------------------------------*/
1079 linkEdit (char **envp)
1086 srcFileName = "temp";
1088 /* first we need to create the <filename>.lnk file */
1089 sprintf (scratchFileName, "%s.lnk", srcFileName);
1090 if (!(lnkfile = fopen (scratchFileName, "w")))
1092 werror (E_FILE_OPEN_ERR, scratchFileName);
1096 /* now write the options */
1097 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1099 /* if iram size specified */
1100 if (options.iram_size)
1101 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1104 fprintf (lnkfile, "-z\n");
1106 #define WRITE_SEG_LOC(N, L) \
1107 segName = Safe_strdup(N); \
1108 c = strtok(segName, " \t"); \
1109 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1110 if (segName) { Safe_free(segName); }
1112 /* code segment start */
1113 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1115 /* data segment start */
1116 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1119 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1123 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1126 /* bit segment start */
1127 WRITE_SEG_LOC (BIT_NAME, 0);
1129 /* add the extra linker options */
1130 for (i = 0; linkOptions[i]; i++)
1131 fprintf (lnkfile, "%s\n", linkOptions[i]);
1133 /* other library paths if specified */
1134 for (i = 0; i < nlibPaths; i++)
1135 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1137 /* standard library path */
1138 if (!options.nostdlib)
1140 switch (options.model)
1156 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1160 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1162 /* standard library files */
1163 #if !OPT_DISABLE_DS390
1164 if (options.model == MODEL_FLAT24)
1166 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1170 #if !OPT_DISABLE_XA51
1171 if (options.model == MODEL_PAGE0)
1173 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1176 fprintf (lnkfile, "-l %s\n", STD_LIB);
1177 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1178 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1179 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1182 /* additional libraries if any */
1183 for (i = 0; i < nlibFiles; i++)
1184 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1186 /* put in the object files */
1187 if (strcmp (srcFileName, "temp"))
1188 fprintf (lnkfile, "%s ", srcFileName);
1190 for (i = 0; i < nrelFiles; i++)
1191 fprintf (lnkfile, "%s\n", relFiles[i]);
1193 fprintf (lnkfile, "\n-e\n");
1196 if (options.verbose)
1197 printf ("sdcc: Calling linker...\n");
1199 if (port->linker.cmd)
1201 char buffer2[PATH_MAX];
1202 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1203 buildCmdLine2 (buffer, buffer2);
1207 buildCmdLine2 (buffer, port->linker.mcmd);
1210 if (my_system (buffer))
1215 if (strcmp (srcFileName, "temp") == 0)
1217 /* rename "temp.cdb" to "firstRelFile.cdb" */
1218 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1219 f = strcat (f, ".cdb");
1220 rename ("temp.cdb", f);
1225 /*-----------------------------------------------------------------*/
1226 /* assemble - spawns the assembler with arguments */
1227 /*-----------------------------------------------------------------*/
1229 assemble (char **envp)
1231 if (port->assembler.do_assemble) {
1232 port->assembler.do_assemble(asmOptions);
1234 } else if (port->assembler.cmd) {
1235 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1236 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1239 buildCmdLine2 (buffer, port->assembler.mcmd);
1242 if (my_system (buffer)) {
1243 /* either system() or the assembler itself has reported an error
1244 perror ("Cannot exec assembler");
1250 /*-----------------------------------------------------------------*/
1251 /* preProcess - spawns the preprocessor with arguments */
1252 /*-----------------------------------------------------------------*/
1254 preProcess (char **envp)
1258 if (!options.c1mode)
1260 /* if using external stack define the macro */
1261 if (options.useXstack)
1262 addToList (preArgv, "-DSDCC_USE_XSTACK");
1264 /* set the macro for stack autos */
1265 if (options.stackAuto)
1266 addToList (preArgv, "-DSDCC_STACK_AUTO");
1268 /* set the macro for stack autos */
1269 if (options.stack10bit)
1270 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1272 /* set the macro for no overlay */
1273 if (options.noOverlay)
1274 addToList (preArgv, "-DSDCC_NOOVERLAY");
1276 /* set the macro for large model */
1277 switch (options.model)
1280 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1283 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1286 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1289 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1292 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1295 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1298 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1302 /* add port (processor information to processor */
1303 addToList (preArgv, "-DSDCC_{port}");
1304 addToList (preArgv, "-D__{port}");
1306 /* standard include path */
1307 if (!options.nostdinc) {
1308 addToList (preArgv, "-I{includedir}");
1311 setMainValue ("cppextraopts", join(preArgv));
1314 preOutName = Safe_strdup (tempfilename ());
1316 /* Have to set cppoutfilename to something, even if just pre-processing. */
1317 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1319 if (options.verbose)
1320 printf ("sdcc: Calling preprocessor...\n");
1322 buildCmdLine2 (buffer, _preCmd);
1324 if (my_system (buffer))
1326 // @FIX: Dario Vecchio 03-05-2001
1329 unlink (preOutName);
1330 Safe_free (preOutName);
1343 preOutName = fullSrcFileName;
1346 yyin = fopen (preOutName, "r");
1349 perror ("Preproc file not found\n");
1357 _setPaths (const char *pprefix)
1360 Given the prefix and how the directories were layed out at
1361 configure time, see if the library and include directories are
1362 where expected. If so, set.
1364 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1365 strcpy (scratchFileName, pprefix);
1366 strcat (scratchFileName, buffer);
1368 if (pathExists (scratchFileName))
1370 setMainValue ("includedir", scratchFileName);
1377 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1378 strcpy (scratchFileName, pprefix);
1379 strcat (scratchFileName, buffer);
1381 if (pathExists (scratchFileName))
1383 setMainValue ("libdir", scratchFileName);
1394 _discoverPaths (const char *argv0)
1397 1. Try the SDCCDIR environment variable.
1398 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1399 and library paths with respect to that. Note that under win32
1400 argv[0] is always the full path to the program.
1401 3. If (1) and (2) fail, fall back to the compile time defaults.
1403 Detecting assumes the same layout as when configured. If the
1404 directories have been further moved about then discovery will
1408 /* Some input cases:
1409 "c:\fish\sdcc\bin\sdcc"
1411 "/home/fish/bin/sdcc"
1413 Note that ./sdcc is explicitly not supported as there isn't
1416 /* bindir is handled differently to the lib and include directories.
1417 It's rather unfortunate, but required due to the different
1418 install and development layouts. Logic is different as well.
1421 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1423 strcpy (scratchFileName, argv0);
1424 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1425 setMainValue ("bindir", scratchFileName);
1426 ExePathList[0] = Safe_strdup (scratchFileName);
1428 else if (getenv (SDCCDIR_NAME) != NULL)
1430 getPathDifference (buffer, PREFIX, BINDIR);
1431 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1432 strcat (scratchFileName, buffer);
1433 setMainValue ("bindir", scratchFileName);
1434 ExePathList[0] = Safe_strdup (scratchFileName);
1438 setMainValue ("bindir", BINDIR);
1439 ExePathList[0] = BINDIR;
1445 if (getenv (SDCCDIR_NAME) != NULL)
1447 if (_setPaths (getenv (SDCCDIR_NAME)))
1449 /* Successfully set. */
1454 /* Include and lib weren't where expected. */
1458 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1460 char *pbase = getPrefixFromBinPath (argv0);
1464 /* A bad path. Skip. */
1468 if (_setPaths (pbase))
1470 /* Successfully set. */
1475 /* Include and lib weren't where expected. */
1480 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1481 setMainValue ("libdir", SDCC_LIB_DIR);
1488 populateMainValues (_baseValues);
1489 setMainValue ("port", port->target);
1490 setMainValue ("objext", port->linker.rel_ext);
1491 setMainValue ("asmext", port->assembler.file_ext);
1493 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1494 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1499 * initialises and calls the parser
1503 main (int argc, char **argv, char **envp)
1505 /* turn all optimizations off by default */
1506 memset (&optimize, 0, sizeof (struct optimize));
1508 /*printVersionInfo (); */
1511 fprintf (stderr, "Build error: no ports are enabled.\n");
1515 _findPort (argc, argv);
1517 if (strcmp(port->target, "mcs51") == 0) {
1518 printf("DS390 jammed in A\n");
1523 /* Initalise the port. */
1527 // Create a default exe search path from the path to the sdcc command
1530 setDefaultOptions ();
1533 options.model = MODEL_SMALL;
1534 options.stack10bit=0;
1537 parseCmdLine (argc, argv);
1539 /* if no input then printUsage & exit */
1540 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1541 (options.c1mode && !srcFileName && !options.out_name))
1548 _discoverPaths (argv[0]);
1555 port->finaliseOptions ();
1564 if (options.verbose)
1565 printf ("sdcc: Generating code...\n");
1571 if (TARGET_IS_PIC) {
1572 /* TSD PIC port hack - if the PIC port option is enabled
1573 and SDCC is used to generate PIC code, then we will
1574 generate .asm files in gpasm's format instead of SDCC's
1577 #if !OPT_DISABLE_PIC
1586 // @FIX: Dario Vecchio 03-05-2001
1589 if (yyin && yyin != stdin)
1591 unlink (preOutName);
1592 Safe_free (preOutName);
1597 if (!options.c1mode && !noAssemble)
1599 if (options.verbose)
1600 printf ("sdcc: Calling assembler...\n");
1606 // @FIX: Dario Vecchio 03-05-2001
1609 if (yyin && yyin != stdin)
1611 unlink (preOutName);
1612 Safe_free (preOutName);
1615 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1628 if (preOutName && !options.c1mode)
1630 unlink (preOutName);
1631 Safe_free (preOutName);
1634 if (!options.cc_only &&
1638 (srcFileName || nrelFiles))
1640 if (port->linker.do_link)
1641 port->linker.do_link ();
1646 if (yyin && yyin != stdin)