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"
117 /** Table of all options supported by all ports.
119 * A reference for all options.
120 * An easy way to maintain help for the options.
121 * Automatic support for setting flags on simple options.
124 /** The short option character e.g. 'h' for -h. 0 for none. */
126 /** Long option e.g. "--help". Includes the -- prefix. NULL for
129 /** Pointer to an int that will be incremented every time the
130 option is encountered. May be NULL.
133 /** Help text to go with this option. May be NULL. */
139 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
140 { 'd', NULL, NULL, NULL },
141 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
142 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
143 { 'A', NULL, NULL, NULL },
144 { 'U', NULL, NULL, NULL },
145 { 'C', NULL, NULL, "Preprocessor option" },
146 { 'M', NULL, NULL, "Preprocessor option" },
147 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
148 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
149 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
150 { 'L', NULL, NULL, "Add the next field to the library search path" },
151 { 'l', NULL, NULL, "Include the given library in the link" },
152 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
153 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
154 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
155 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
156 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
157 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
158 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
159 { 0, "--xstack", &options.useXstack, "Use external stack" },
160 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
161 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
162 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
163 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
164 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
165 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
166 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
167 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
168 { 0, "--dumpgcse", &options.dump_gcse, NULL },
169 { 0, "--dumploop", &options.dump_loop, NULL },
170 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
171 { 0, "--dumpliverange", &options.dump_range, NULL },
172 { 0, "--dumpregpack", &options.dump_pack, NULL },
173 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
174 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
175 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
176 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
177 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
178 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
179 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
180 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
181 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
182 { 0, OPTION_IDATA_LOC, NULL, NULL },
183 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
184 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
185 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
186 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
187 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
188 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
189 { 0, "--cyclomatic", &options.cyclomatic, NULL },
190 { 0, "--nooverlay", &options.noOverlay, NULL },
191 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
192 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
193 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
194 { 0, "--peep-asm", &options.asmpeep, NULL },
195 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
196 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
197 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
198 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
199 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
200 { 0, "--help", NULL, "Display this help" },
201 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
202 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
203 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
204 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
205 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
206 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
207 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
208 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
209 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"}
212 /** Table of all unsupported options and help text to display when one
216 /** shortOpt as in OPTIONS. */
218 /** longOpt as in OPTIONS. */
220 /** Message to display inside W_UNSUPPORTED_OPT when this option
225 static const UNSUPPORTEDOPT
226 unsupportedOptTable[] = {
227 { 'a', NULL, "use --stack-auto instead." },
228 { 'g', NULL, "use --generic instead" },
229 { 'X', NULL, "use --xstack-loc instead" },
230 { 'x', NULL, "use --xstack instead" },
231 { 'p', NULL, "use --stack-loc instead" },
232 { 'P', NULL, "use --stack-loc instead" },
233 { 'i', NULL, "use --idata-loc instead" },
234 { 'r', NULL, "use --xdata-loc instead" },
235 { 's', NULL, "use --code-loc instead" },
236 { 'Y', NULL, "use -I instead" }
239 /** List of all default constant macros.
241 static const char *_baseValues[] = {
242 "cpp", "{bindir}{sep}sdcpp",
244 /* Path seperator character */
245 "sep", DIR_SEPARATOR_STRING,
249 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
253 static PORT *_ports[] =
255 #if !OPT_DISABLE_MCS51
258 #if !OPT_DISABLE_GBZ80
267 #if !OPT_DISABLE_DS390
273 #if !OPT_DISABLE_I186
276 #if !OPT_DISABLE_TLCS900H
281 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
284 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
286 extern void picglue ();
288 /** Sets the port to the one given by the command line option.
289 @param The name minus the option (eg 'mcs51')
290 @return 0 on success.
293 _setPort (const char *name)
296 for (i = 0; i < NUM_PORTS; i++)
298 if (!strcmp (_ports[i]->target, name))
304 /* Error - didnt find */
305 werror (E_UNKNOWN_TARGET, name);
310 _validatePorts (void)
313 for (i = 0; i < NUM_PORTS; i++)
315 if (_ports[i]->magic != PORT_MAGIC)
317 wassertl (0, "Port definition structure is incomplete");
323 _findPort (int argc, char **argv)
329 if (!strncmp (*argv, "-m", 2))
331 _setPort (*argv + 2);
336 /* Use the first in the list */
340 /*-----------------------------------------------------------------*/
341 /* printVersionInfo - prints the version info */
342 /*-----------------------------------------------------------------*/
350 for (i = 0; i < NUM_PORTS; i++)
351 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
353 fprintf (stderr, " %s"
354 #ifdef SDCC_SUB_VERSION_STR
355 "/" SDCC_SUB_VERSION_STR
364 #if defined(_MSC_VER)
376 /*-----------------------------------------------------------------*/
377 /* printUsage - prints command line syntax */
378 /*-----------------------------------------------------------------*/
385 "Usage : sdcc [options] filename\n"
389 for (i = 0; i < LENGTH(optionsTable); i++) {
390 fprintf(stdout, " %c%c %-20s %s\n",
391 optionsTable[i].shortOpt !=0 ? '-' : ' ',
392 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
393 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
394 optionsTable[i].help != NULL ? optionsTable[i].help : ""
400 /*-----------------------------------------------------------------*/
401 /* parseWithComma - separates string with comma */
402 /*-----------------------------------------------------------------*/
404 parseWithComma (char **dest, char *src)
408 strtok (src, "\r\n \t");
409 /* skip the initial white spaces */
410 while (isspace (*src))
427 /*-----------------------------------------------------------------*/
428 /* setDefaultOptions - sets the default options */
429 /*-----------------------------------------------------------------*/
435 for (i = 0; i < 128; i++)
436 preArgv[i] = asmOptions[i] =
437 linkOptions[i] = relFiles[i] = libFiles[i] =
440 /* first the options part */
441 options.stack_loc = 0; /* stack pointer initialised to 0 */
442 options.xstack_loc = 0; /* xternal stack starts at 0 */
443 options.code_loc = 0; /* code starts at 0 */
444 options.data_loc = 0x0030; /* data starts at 0x0030 */
445 options.xdata_loc = 0;
446 options.idata_loc = 0x80;
447 options.genericPtr = 1; /* default on */
449 options.model = port->general.default_model;
450 options.nostdlib = 0;
451 options.nostdinc = 0;
453 options.shortis8bits = 0;
455 options.stack10bit=0;
457 /* now for the optimizations */
458 /* turn on the everything */
459 optimize.global_cse = 1;
464 optimize.loopInvariant = 1;
465 optimize.loopInduction = 1;
467 /* now for the ports */
468 port->setDefaultOptions ();
471 /*-----------------------------------------------------------------*/
472 /* processFile - determines the type of file from the extension */
473 /*-----------------------------------------------------------------*/
475 processFile (char *s)
479 /* get the file extension */
480 fext = s + strlen (s);
481 while ((fext != s) && *fext != '.')
484 /* now if no '.' then we don't know what the file type is
485 so give a warning and return */
488 werror (W_UNKNOWN_FEXT, s);
492 /* otherwise depending on the file type */
493 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
495 /* source file name : not if we already have a
499 werror (W_TOO_MANY_SRC, s);
503 /* the only source file */
504 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
506 werror (E_FILE_OPEN_ERR, s);
510 /* copy the file name into the buffer */
513 /* get rid of the "." */
514 strtok (buffer, ".");
515 srcFileName = Safe_alloc ( strlen (buffer) + 1);
516 strcpy (srcFileName, buffer);
518 /* get rid of any path information
519 for the module name; do this by going
520 backwards till we get to either '/' or '\' or ':'
521 or start of buffer */
522 fext = buffer + strlen (buffer);
523 while (fext != buffer &&
524 *(fext - 1) != '\\' &&
525 *(fext - 1) != '/' &&
528 moduleName = Safe_alloc ( strlen (fext) + 1);
529 strcpy (moduleName, fext);
534 /* if the extention is type .rel or .r or .REL or .R
535 addtional object file will be passed to the linker */
536 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
537 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
538 strcmp (fext, port->linker.rel_ext) == 0)
540 relFiles[nrelFiles++] = s;
544 /* if .lib or .LIB */
545 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
547 libFiles[nlibFiles++] = s;
551 werror (W_UNKNOWN_FEXT, s);
556 _processC1Arg (char *s)
560 if (options.out_name)
562 werror (W_TOO_MANY_SRC, s);
565 options.out_name = Safe_strdup (s);
574 _setModel (int model, const char *sz)
576 if (port->general.supported_models & model)
577 options.model = model;
579 werror (W_UNSUPPORTED_MODEL, sz, port->target);
582 /** Gets the string argument to this option. If the option is '--opt'
583 then for input of '--optxyz' or '--opt xyz' returns xyz.
586 getStringArg(const char *szStart, char **argv, int *pi, int argc)
588 if (argv[*pi][strlen(szStart)])
590 return &argv[*pi][strlen(szStart)];
597 werror (E_ARGUMENT_MISSING, szStart);
598 /* Die here rather than checking for errors later. */
608 /** Gets the integer argument to this option using the same rules as
612 getIntArg(const char *szStart, char **argv, int *pi, int argc)
614 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
618 verifyShortOption(const char *opt)
620 if (strlen(opt) != 2)
622 werror (W_EXCESS_SHORT_OPTIONS, opt);
627 tryHandleUnsupportedOpt(char **argv, int *pi)
629 if (argv[*pi][0] == '-')
631 const char *longOpt = "";
635 if (argv[*pi][1] == '-')
642 shortOpt = argv[*pi][1];
644 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
646 if (unsupportedOptTable[i].shortOpt == shortOpt ||
647 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
648 // Found an unsupported opt.
650 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
651 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
655 // Didn't find in the table
660 // Not an option, so can't be unsupported :)
666 tryHandleSimpleOpt(char **argv, int *pi)
668 if (argv[*pi][0] == '-')
670 const char *longOpt = "";
674 if (argv[*pi][1] == '-')
681 shortOpt = argv[*pi][1];
684 for (i = 0; i < LENGTH(optionsTable); i++)
686 if (optionsTable[i].shortOpt == shortOpt ||
687 (longOpt && optionsTable[i].longOpt &&
688 strcmp(optionsTable[i].longOpt, longOpt) == 0))
691 // If it is a flag then we can handle it here
692 if (optionsTable[i].pparameter != NULL)
694 if (optionsTable[i].shortOpt == shortOpt)
696 verifyShortOption(argv[*pi]);
699 (*optionsTable[i].pparameter)++;
703 // Not a flag. Handled manually later.
708 // Didn't find in the table
713 // Not an option, so can't be handled.
718 /*-----------------------------------------------------------------*/
719 /* parseCmdLine - parses the command line and sets the options */
720 /*-----------------------------------------------------------------*/
722 parseCmdLine (int argc, char **argv)
726 /* go thru all whole command line */
727 for (i = 1; i < argc; i++)
732 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
737 if (tryHandleSimpleOpt(argv, &i) == TRUE)
743 if (argv[i][0] == '-' && argv[i][1] == '-')
745 if (strcmp (argv[i], OPTION_HELP) == 0)
751 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
753 options.stack10bit = 0;
757 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
763 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
765 _setModel (MODEL_LARGE, argv[i]);
769 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
771 _setModel (MODEL_MEDIUM, argv[i]);
775 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
777 _setModel (MODEL_SMALL, argv[i]);
781 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
783 _setModel (MODEL_FLAT24, argv[i]);
787 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
789 options.dump_rassgn =
795 options.dump_raw = 1;
799 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
801 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
805 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
807 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
811 if (strcmp (argv[i], OPTION_VERSION) == 0)
818 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
820 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
824 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
826 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
830 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
832 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
836 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
838 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
842 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
844 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
848 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
850 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
854 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
856 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
860 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
862 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
866 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
868 optimize.global_cse = 0;
872 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
874 optimize.loopInvariant = 0;
878 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
880 optimize.loopInduction = 0;
884 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
886 options.lessPedantic = 1;
887 setErrorLogLevel(ERROR_LEVEL_WARNING);
891 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
893 options.shortis8bits=1;
897 if (!port->parseOption (&argc, argv, &i))
899 werror (W_UNKNOWN_OPTION, argv[i]);
907 /* if preceded by '-' then option */
913 verifyShortOption(argv[i]);
920 /* Used to select the port */
921 _setPort (argv[i] + 2);
925 verifyShortOption(argv[i]);
931 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
935 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
939 /* pre-processer options */
940 if (argv[i][2] == 'p')
942 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
945 else if (argv[i][2] == 'l')
947 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
949 /* assembler options */
950 else if (argv[i][2] == 'a')
952 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
956 werror (W_UNKNOWN_OPTION, argv[i]);
961 verifyShortOption(argv[i]);
967 /* preprocessor options */
971 addToList (preArgv, "-M");
976 addToList (preArgv, "-C");
985 char sOpt = argv[i][1];
988 if (argv[i][2] == ' ' || argv[i][2] == '\0')
994 werror(E_ARGUMENT_MISSING, argv[i-1]);
1008 sprintf (buffer, "-%c%s", sOpt, rest);
1009 addToList (preArgv, buffer);
1014 if (!port->parseOption (&argc, argv, &i))
1015 werror (W_UNKNOWN_OPTION, argv[i]);
1020 if (!port->parseOption (&argc, argv, &i))
1022 /* no option must be a filename */
1024 _processC1Arg (argv[i]);
1026 processFile (argv[i]);
1030 /* set up external stack location if not explicitly specified */
1031 if (!options.xstack_loc)
1032 options.xstack_loc = options.xdata_loc;
1034 /* if debug option is set the open the cdbFile */
1035 if (options.debug && srcFileName)
1037 sprintf (scratchFileName, "%s.cdb", srcFileName);
1038 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1039 werror (E_FILE_OPEN_ERR, scratchFileName);
1042 /* add a module record */
1043 fprintf (cdbFile, "M:%s\n", moduleName);
1049 /*-----------------------------------------------------------------*/
1050 /* linkEdit : - calls the linkage editor with options */
1051 /*-----------------------------------------------------------------*/
1053 linkEdit (char **envp)
1060 srcFileName = "temp";
1062 /* first we need to create the <filename>.lnk file */
1063 sprintf (scratchFileName, "%s.lnk", srcFileName);
1064 if (!(lnkfile = fopen (scratchFileName, "w")))
1066 werror (E_FILE_OPEN_ERR, scratchFileName);
1070 /* now write the options */
1071 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1073 /* if iram size specified */
1074 if (options.iram_size)
1075 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1078 fprintf (lnkfile, "-z\n");
1080 #define WRITE_SEG_LOC(N, L) \
1081 segName = Safe_strdup(N); \
1082 c = strtok(segName, " \t"); \
1083 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1084 if (segName) { Safe_free(segName); }
1086 /* code segment start */
1087 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1089 /* data segment start */
1090 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1093 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1096 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1098 /* bit segment start */
1099 WRITE_SEG_LOC (BIT_NAME, 0);
1101 /* add the extra linker options */
1102 for (i = 0; linkOptions[i]; i++)
1103 fprintf (lnkfile, "%s\n", linkOptions[i]);
1105 /* other library paths if specified */
1106 for (i = 0; i < nlibPaths; i++)
1107 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1109 /* standard library path */
1110 if (!options.nostdlib)
1113 if (TARGET_IS_DS390)
1120 switch (options.model)
1133 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1138 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1140 /* standard library files */
1141 /* if (strcmp (port->target, "ds390") == 0) */
1142 if (options.model == MODEL_FLAT24)
1144 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1146 fprintf (lnkfile, "-l %s\n", STD_LIB);
1147 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1148 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1149 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1152 /* additional libraries if any */
1153 for (i = 0; i < nlibFiles; i++)
1154 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1156 /* put in the object files */
1157 if (strcmp (srcFileName, "temp"))
1158 fprintf (lnkfile, "%s ", srcFileName);
1160 for (i = 0; i < nrelFiles; i++)
1161 fprintf (lnkfile, "%s\n", relFiles[i]);
1163 fprintf (lnkfile, "\n-e\n");
1166 if (options.verbose)
1167 printf ("sdcc: Calling linker...\n");
1169 if (port->linker.cmd)
1171 char buffer2[PATH_MAX];
1172 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1173 buildCmdLine2 (buffer, buffer2);
1177 buildCmdLine2 (buffer, port->linker.mcmd);
1180 if (my_system (buffer))
1185 if (strcmp (srcFileName, "temp") == 0)
1187 /* rename "temp.cdb" to "firstRelFile.cdb" */
1188 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1189 f = strcat (f, ".cdb");
1190 rename ("temp.cdb", f);
1195 /*-----------------------------------------------------------------*/
1196 /* assemble - spawns the assembler with arguments */
1197 /*-----------------------------------------------------------------*/
1199 assemble (char **envp)
1201 if (port->assembler.cmd)
1203 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1204 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1209 buildCmdLine2 (buffer, port->assembler.mcmd);
1212 if (my_system (buffer))
1214 /* either system() or the assembler itself has reported an error
1215 perror ("Cannot exec assembler");
1221 /*-----------------------------------------------------------------*/
1222 /* preProcess - spawns the preprocessor with arguments */
1223 /*-----------------------------------------------------------------*/
1225 preProcess (char **envp)
1229 if (!options.c1mode)
1231 /* if using external stack define the macro */
1232 if (options.useXstack)
1233 addToList (preArgv, "-DSDCC_USE_XSTACK");
1235 /* set the macro for stack autos */
1236 if (options.stackAuto)
1237 addToList (preArgv, "-DSDCC_STACK_AUTO");
1239 /* set the macro for stack autos */
1240 if (options.stack10bit)
1241 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1243 /* set the macro for no overlay */
1244 if (options.noOverlay)
1245 addToList (preArgv, "-DSDCC_NOOVERLAY");
1247 /* set the macro for large model */
1248 switch (options.model)
1251 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1254 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1257 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1260 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1263 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1266 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1270 /* add port (processor information to processor */
1271 addToList (preArgv, "-DSDCC_{port}");
1272 addToList (preArgv, "-D__{port}");
1274 /* standard include path */
1275 if (!options.nostdinc) {
1276 addToList (preArgv, "-I{includedir}");
1279 setMainValue ("cppextraopts", join(preArgv));
1282 preOutName = Safe_strdup (tempfilename ());
1284 /* Have to set cppoutfilename to something, even if just pre-processing. */
1285 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1287 if (options.verbose)
1288 printf ("sdcc: Calling preprocessor...\n");
1290 buildCmdLine2 (buffer, _preCmd);
1292 if (my_system (buffer))
1294 // @FIX: Dario Vecchio 03-05-2001
1297 unlink (preOutName);
1298 Safe_free (preOutName);
1311 preOutName = fullSrcFileName;
1314 yyin = fopen (preOutName, "r");
1317 perror ("Preproc file not found\n");
1325 _setPaths (const char *pprefix)
1328 Given the prefix and how the directories were layed out at
1329 configure time, see if the library and include directories are
1330 where expected. If so, set.
1332 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1333 strcpy (scratchFileName, pprefix);
1334 strcat (scratchFileName, buffer);
1336 if (pathExists (scratchFileName))
1338 setMainValue ("includedir", scratchFileName);
1345 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1346 strcpy (scratchFileName, pprefix);
1347 strcat (scratchFileName, buffer);
1349 if (pathExists (scratchFileName))
1351 setMainValue ("libdir", scratchFileName);
1362 _discoverPaths (const char *argv0)
1365 1. Try the SDCCDIR environment variable.
1366 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1367 and library paths with respect to that. Note that under win32
1368 argv[0] is always the full path to the program.
1369 3. If (1) and (2) fail, fall back to the compile time defaults.
1371 Detecting assumes the same layout as when configured. If the
1372 directories have been further moved about then discovery will
1376 /* Some input cases:
1377 "c:\fish\sdcc\bin\sdcc"
1379 "/home/fish/bin/sdcc"
1381 Note that ./sdcc is explicitly not supported as there isn't
1384 /* bindir is handled differently to the lib and include directories.
1385 It's rather unfortunate, but required due to the different
1386 install and development layouts. Logic is different as well.
1389 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1391 strcpy (scratchFileName, argv0);
1392 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1393 setMainValue ("bindir", scratchFileName);
1394 ExePathList[0] = Safe_strdup (scratchFileName);
1396 else if (getenv (SDCCDIR_NAME) != NULL)
1398 getPathDifference (buffer, PREFIX, BINDIR);
1399 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1400 strcat (scratchFileName, buffer);
1401 setMainValue ("bindir", scratchFileName);
1402 ExePathList[0] = Safe_strdup (scratchFileName);
1406 setMainValue ("bindir", BINDIR);
1407 ExePathList[0] = BINDIR;
1413 if (getenv (SDCCDIR_NAME) != NULL)
1415 if (_setPaths (getenv (SDCCDIR_NAME)))
1417 /* Successfully set. */
1422 /* Include and lib weren't where expected. */
1426 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1428 char *pbase = getPrefixFromBinPath (argv0);
1432 /* A bad path. Skip. */
1436 if (_setPaths (pbase))
1438 /* Successfully set. */
1443 /* Include and lib weren't where expected. */
1448 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1449 setMainValue ("libdir", SDCC_LIB_DIR);
1456 populateMainValues (_baseValues);
1457 setMainValue ("port", port->target);
1458 setMainValue ("objext", port->linker.rel_ext);
1459 setMainValue ("asmext", port->assembler.file_ext);
1461 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1462 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1467 * initialises and calls the parser
1471 main (int argc, char **argv, char **envp)
1473 /* turn all optimizations off by default */
1474 memset (&optimize, 0, sizeof (struct optimize));
1476 /*printVersionInfo (); */
1479 fprintf (stderr, "Build error: no ports are enabled.\n");
1483 _findPort (argc, argv);
1485 if (strcmp(port->target, "mcs51") == 0) {
1486 printf("DS390 jammed in A\n");
1491 /* Initalise the port. */
1495 // Create a default exe search path from the path to the sdcc command
1498 setDefaultOptions ();
1501 options.model = MODEL_SMALL;
1502 options.stack10bit=0;
1505 parseCmdLine (argc, argv);
1507 /* if no input then printUsage & exit */
1508 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1509 (options.c1mode && !srcFileName && !options.out_name))
1516 _discoverPaths (argv[0]);
1524 port->finaliseOptions ();
1531 if (options.verbose)
1532 printf ("sdcc: Generating code...\n");
1538 if (TARGET_IS_PIC) {
1539 /* TSD PIC port hack - if the PIC port option is enabled
1540 and SDCC is used to generate PIC code, then we will
1541 generate .asm files in gpasm's format instead of SDCC's
1544 #if !OPT_DISABLE_PIC
1553 // @FIX: Dario Vecchio 03-05-2001
1556 if (yyin && yyin != stdin)
1558 unlink (preOutName);
1559 Safe_free (preOutName);
1564 if (!options.c1mode && !noAssemble)
1566 if (options.verbose)
1567 printf ("sdcc: Calling assembler...\n");
1573 // @FIX: Dario Vecchio 03-05-2001
1576 if (yyin && yyin != stdin)
1578 unlink (preOutName);
1579 Safe_free (preOutName);
1582 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1595 if (preOutName && !options.c1mode)
1597 unlink (preOutName);
1598 Safe_free (preOutName);
1601 if (!options.cc_only &&
1605 (srcFileName || nrelFiles))
1607 if (port->linker.do_link)
1608 port->linker.do_link ();
1613 if (yyin && yyin != stdin)