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 "." */
524 strtok (buffer, ".");
525 srcFileName = Safe_alloc ( strlen (buffer) + 1);
526 strcpy (srcFileName, buffer);
528 /* get rid of any path information
529 for the module name; do this by going
530 backwards till we get to either '/' or '\' or ':'
531 or start of buffer */
532 fext = buffer + strlen (buffer);
533 while (fext != buffer &&
534 *(fext - 1) != '\\' &&
535 *(fext - 1) != '/' &&
538 moduleName = Safe_alloc ( strlen (fext) + 1);
539 strcpy (moduleName, fext);
544 /* if the extention is type .rel or .r or .REL or .R
545 addtional object file will be passed to the linker */
546 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
547 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
548 strcmp (fext, port->linker.rel_ext) == 0)
550 relFiles[nrelFiles++] = s;
554 /* if .lib or .LIB */
555 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
557 libFiles[nlibFiles++] = s;
561 werror (W_UNKNOWN_FEXT, s);
566 _processC1Arg (char *s)
570 if (options.out_name)
572 werror (W_TOO_MANY_SRC, s);
575 options.out_name = Safe_strdup (s);
584 _setModel (int model, const char *sz)
586 if (port->general.supported_models & model)
587 options.model = model;
589 werror (W_UNSUPPORTED_MODEL, sz, port->target);
592 /** Gets the string argument to this option. If the option is '--opt'
593 then for input of '--optxyz' or '--opt xyz' returns xyz.
596 getStringArg(const char *szStart, char **argv, int *pi, int argc)
598 if (argv[*pi][strlen(szStart)])
600 return &argv[*pi][strlen(szStart)];
607 werror (E_ARGUMENT_MISSING, szStart);
608 /* Die here rather than checking for errors later. */
618 /** Gets the integer argument to this option using the same rules as
622 getIntArg(const char *szStart, char **argv, int *pi, int argc)
624 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
628 verifyShortOption(const char *opt)
630 if (strlen(opt) != 2)
632 werror (W_EXCESS_SHORT_OPTIONS, opt);
637 tryHandleUnsupportedOpt(char **argv, int *pi)
639 if (argv[*pi][0] == '-')
641 const char *longOpt = "";
645 if (argv[*pi][1] == '-')
652 shortOpt = argv[*pi][1];
654 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
656 if (unsupportedOptTable[i].shortOpt == shortOpt ||
657 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
658 // Found an unsupported opt.
660 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
661 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
665 // Didn't find in the table
670 // Not an option, so can't be unsupported :)
676 tryHandleSimpleOpt(char **argv, int *pi)
678 if (argv[*pi][0] == '-')
680 const char *longOpt = "";
684 if (argv[*pi][1] == '-')
691 shortOpt = argv[*pi][1];
694 for (i = 0; i < LENGTH(optionsTable); i++)
696 if (optionsTable[i].shortOpt == shortOpt ||
697 (longOpt && optionsTable[i].longOpt &&
698 strcmp(optionsTable[i].longOpt, longOpt) == 0))
701 // If it is a flag then we can handle it here
702 if (optionsTable[i].pparameter != NULL)
704 if (optionsTable[i].shortOpt == shortOpt)
706 verifyShortOption(argv[*pi]);
709 (*optionsTable[i].pparameter)++;
713 // Not a flag. Handled manually later.
718 // Didn't find in the table
723 // Not an option, so can't be handled.
728 /*-----------------------------------------------------------------*/
729 /* parseCmdLine - parses the command line and sets the options */
730 /*-----------------------------------------------------------------*/
732 parseCmdLine (int argc, char **argv)
736 /* go thru all whole command line */
737 for (i = 1; i < argc; i++)
742 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
747 if (tryHandleSimpleOpt(argv, &i) == TRUE)
753 if (argv[i][0] == '-' && argv[i][1] == '-')
755 if (strcmp (argv[i], OPTION_HELP) == 0)
761 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
763 options.stack10bit = 0;
767 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
773 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
775 _setModel (MODEL_LARGE, argv[i]);
779 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
781 _setModel (MODEL_MEDIUM, argv[i]);
785 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
787 _setModel (MODEL_SMALL, argv[i]);
791 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
793 _setModel (MODEL_FLAT24, argv[i]);
797 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
799 options.dump_rassgn =
805 options.dump_raw = 1;
809 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
811 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
815 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
817 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
821 if (strcmp (argv[i], OPTION_VERSION) == 0)
828 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
830 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
834 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
836 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
840 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
842 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
846 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
848 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
852 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
854 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
858 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
860 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
864 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
866 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
870 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
872 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
876 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
878 optimize.global_cse = 0;
882 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
884 optimize.loopInvariant = 0;
888 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
890 optimize.loopInduction = 0;
894 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
896 options.lessPedantic = 1;
897 setErrorLogLevel(ERROR_LEVEL_WARNING);
901 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
903 options.shortis8bits=1;
907 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
909 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
913 if (!port->parseOption (&argc, argv, &i))
915 werror (W_UNKNOWN_OPTION, argv[i]);
923 /* if preceded by '-' then option */
929 verifyShortOption(argv[i]);
936 /* Used to select the port */
937 _setPort (argv[i] + 2);
941 verifyShortOption(argv[i]);
947 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
951 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
955 /* pre-processer options */
956 if (argv[i][2] == 'p')
958 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
961 else if (argv[i][2] == 'l')
963 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
965 /* assembler options */
966 else if (argv[i][2] == 'a')
968 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
972 werror (W_UNKNOWN_OPTION, argv[i]);
977 verifyShortOption(argv[i]);
983 /* preprocessor options */
987 addToList (preArgv, "-M");
992 addToList (preArgv, "-C");
1001 char sOpt = argv[i][1];
1004 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1010 werror(E_ARGUMENT_MISSING, argv[i-1]);
1024 sprintf (buffer, "-%c%s", sOpt, rest);
1025 addToList (preArgv, buffer);
1030 if (!port->parseOption (&argc, argv, &i))
1031 werror (W_UNKNOWN_OPTION, argv[i]);
1036 if (!port->parseOption (&argc, argv, &i))
1038 /* no option must be a filename */
1040 _processC1Arg (argv[i]);
1042 processFile (argv[i]);
1046 /* set up external stack location if not explicitly specified */
1047 if (!options.xstack_loc)
1048 options.xstack_loc = options.xdata_loc;
1050 /* if debug option is set the open the cdbFile */
1051 if (options.debug && srcFileName)
1053 sprintf (scratchFileName, "%s.cdb", srcFileName);
1054 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1055 werror (E_FILE_OPEN_ERR, scratchFileName);
1058 /* add a module record */
1059 fprintf (cdbFile, "M:%s\n", moduleName);
1065 /*-----------------------------------------------------------------*/
1066 /* linkEdit : - calls the linkage editor with options */
1067 /*-----------------------------------------------------------------*/
1069 linkEdit (char **envp)
1076 srcFileName = "temp";
1078 /* first we need to create the <filename>.lnk file */
1079 sprintf (scratchFileName, "%s.lnk", srcFileName);
1080 if (!(lnkfile = fopen (scratchFileName, "w")))
1082 werror (E_FILE_OPEN_ERR, scratchFileName);
1086 /* now write the options */
1087 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1089 /* if iram size specified */
1090 if (options.iram_size)
1091 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1094 fprintf (lnkfile, "-z\n");
1096 #define WRITE_SEG_LOC(N, L) \
1097 segName = Safe_strdup(N); \
1098 c = strtok(segName, " \t"); \
1099 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1100 if (segName) { Safe_free(segName); }
1102 /* code segment start */
1103 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1105 /* data segment start */
1106 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1109 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1112 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1114 /* bit segment start */
1115 WRITE_SEG_LOC (BIT_NAME, 0);
1117 /* add the extra linker options */
1118 for (i = 0; linkOptions[i]; i++)
1119 fprintf (lnkfile, "%s\n", linkOptions[i]);
1121 /* other library paths if specified */
1122 for (i = 0; i < nlibPaths; i++)
1123 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1125 /* standard library path */
1126 if (!options.nostdlib)
1129 if (TARGET_IS_DS390)
1136 switch (options.model)
1149 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1154 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1156 /* standard library files */
1157 /* if (strcmp (port->target, "ds390") == 0) */
1158 if (options.model == MODEL_FLAT24)
1160 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1162 fprintf (lnkfile, "-l %s\n", STD_LIB);
1163 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1164 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1165 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1168 /* additional libraries if any */
1169 for (i = 0; i < nlibFiles; i++)
1170 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1172 /* put in the object files */
1173 if (strcmp (srcFileName, "temp"))
1174 fprintf (lnkfile, "%s ", srcFileName);
1176 for (i = 0; i < nrelFiles; i++)
1177 fprintf (lnkfile, "%s\n", relFiles[i]);
1179 fprintf (lnkfile, "\n-e\n");
1182 if (options.verbose)
1183 printf ("sdcc: Calling linker...\n");
1185 if (port->linker.cmd)
1187 char buffer2[PATH_MAX];
1188 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1189 buildCmdLine2 (buffer, buffer2);
1193 buildCmdLine2 (buffer, port->linker.mcmd);
1196 if (my_system (buffer))
1201 if (strcmp (srcFileName, "temp") == 0)
1203 /* rename "temp.cdb" to "firstRelFile.cdb" */
1204 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1205 f = strcat (f, ".cdb");
1206 rename ("temp.cdb", f);
1211 /*-----------------------------------------------------------------*/
1212 /* assemble - spawns the assembler with arguments */
1213 /*-----------------------------------------------------------------*/
1215 assemble (char **envp)
1217 if (port->assembler.do_assemble) {
1218 port->assembler.do_assemble(asmOptions);
1220 } else if (port->assembler.cmd) {
1221 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1222 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1225 buildCmdLine2 (buffer, port->assembler.mcmd);
1228 if (my_system (buffer)) {
1229 /* either system() or the assembler itself has reported an error
1230 perror ("Cannot exec assembler");
1236 /*-----------------------------------------------------------------*/
1237 /* preProcess - spawns the preprocessor with arguments */
1238 /*-----------------------------------------------------------------*/
1240 preProcess (char **envp)
1244 if (!options.c1mode)
1246 /* if using external stack define the macro */
1247 if (options.useXstack)
1248 addToList (preArgv, "-DSDCC_USE_XSTACK");
1250 /* set the macro for stack autos */
1251 if (options.stackAuto)
1252 addToList (preArgv, "-DSDCC_STACK_AUTO");
1254 /* set the macro for stack autos */
1255 if (options.stack10bit)
1256 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1258 /* set the macro for no overlay */
1259 if (options.noOverlay)
1260 addToList (preArgv, "-DSDCC_NOOVERLAY");
1262 /* set the macro for large model */
1263 switch (options.model)
1266 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1269 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1272 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1275 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1278 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1281 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1285 /* add port (processor information to processor */
1286 addToList (preArgv, "-DSDCC_{port}");
1287 addToList (preArgv, "-D__{port}");
1289 /* standard include path */
1290 if (!options.nostdinc) {
1291 addToList (preArgv, "-I{includedir}");
1294 setMainValue ("cppextraopts", join(preArgv));
1297 preOutName = Safe_strdup (tempfilename ());
1299 /* Have to set cppoutfilename to something, even if just pre-processing. */
1300 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1302 if (options.verbose)
1303 printf ("sdcc: Calling preprocessor...\n");
1305 buildCmdLine2 (buffer, _preCmd);
1307 if (my_system (buffer))
1309 // @FIX: Dario Vecchio 03-05-2001
1312 unlink (preOutName);
1313 Safe_free (preOutName);
1326 preOutName = fullSrcFileName;
1329 yyin = fopen (preOutName, "r");
1332 perror ("Preproc file not found\n");
1340 _setPaths (const char *pprefix)
1343 Given the prefix and how the directories were layed out at
1344 configure time, see if the library and include directories are
1345 where expected. If so, set.
1347 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1348 strcpy (scratchFileName, pprefix);
1349 strcat (scratchFileName, buffer);
1351 if (pathExists (scratchFileName))
1353 setMainValue ("includedir", scratchFileName);
1360 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1361 strcpy (scratchFileName, pprefix);
1362 strcat (scratchFileName, buffer);
1364 if (pathExists (scratchFileName))
1366 setMainValue ("libdir", scratchFileName);
1377 _discoverPaths (const char *argv0)
1380 1. Try the SDCCDIR environment variable.
1381 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1382 and library paths with respect to that. Note that under win32
1383 argv[0] is always the full path to the program.
1384 3. If (1) and (2) fail, fall back to the compile time defaults.
1386 Detecting assumes the same layout as when configured. If the
1387 directories have been further moved about then discovery will
1391 /* Some input cases:
1392 "c:\fish\sdcc\bin\sdcc"
1394 "/home/fish/bin/sdcc"
1396 Note that ./sdcc is explicitly not supported as there isn't
1399 /* bindir is handled differently to the lib and include directories.
1400 It's rather unfortunate, but required due to the different
1401 install and development layouts. Logic is different as well.
1404 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1406 strcpy (scratchFileName, argv0);
1407 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1408 setMainValue ("bindir", scratchFileName);
1409 ExePathList[0] = Safe_strdup (scratchFileName);
1411 else if (getenv (SDCCDIR_NAME) != NULL)
1413 getPathDifference (buffer, PREFIX, BINDIR);
1414 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1415 strcat (scratchFileName, buffer);
1416 setMainValue ("bindir", scratchFileName);
1417 ExePathList[0] = Safe_strdup (scratchFileName);
1421 setMainValue ("bindir", BINDIR);
1422 ExePathList[0] = BINDIR;
1428 if (getenv (SDCCDIR_NAME) != NULL)
1430 if (_setPaths (getenv (SDCCDIR_NAME)))
1432 /* Successfully set. */
1437 /* Include and lib weren't where expected. */
1441 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1443 char *pbase = getPrefixFromBinPath (argv0);
1447 /* A bad path. Skip. */
1451 if (_setPaths (pbase))
1453 /* Successfully set. */
1458 /* Include and lib weren't where expected. */
1463 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1464 setMainValue ("libdir", SDCC_LIB_DIR);
1471 populateMainValues (_baseValues);
1472 setMainValue ("port", port->target);
1473 setMainValue ("objext", port->linker.rel_ext);
1474 setMainValue ("asmext", port->assembler.file_ext);
1476 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1477 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1482 * initialises and calls the parser
1486 main (int argc, char **argv, char **envp)
1488 /* turn all optimizations off by default */
1489 memset (&optimize, 0, sizeof (struct optimize));
1491 /*printVersionInfo (); */
1494 fprintf (stderr, "Build error: no ports are enabled.\n");
1498 _findPort (argc, argv);
1500 if (strcmp(port->target, "mcs51") == 0) {
1501 printf("DS390 jammed in A\n");
1506 /* Initalise the port. */
1510 // Create a default exe search path from the path to the sdcc command
1513 setDefaultOptions ();
1516 options.model = MODEL_SMALL;
1517 options.stack10bit=0;
1520 parseCmdLine (argc, argv);
1522 /* if no input then printUsage & exit */
1523 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1524 (options.c1mode && !srcFileName && !options.out_name))
1531 _discoverPaths (argv[0]);
1539 port->finaliseOptions ();
1547 if (options.verbose)
1548 printf ("sdcc: Generating code...\n");
1554 if (TARGET_IS_PIC) {
1555 /* TSD PIC port hack - if the PIC port option is enabled
1556 and SDCC is used to generate PIC code, then we will
1557 generate .asm files in gpasm's format instead of SDCC's
1560 #if !OPT_DISABLE_PIC
1569 // @FIX: Dario Vecchio 03-05-2001
1572 if (yyin && yyin != stdin)
1574 unlink (preOutName);
1575 Safe_free (preOutName);
1580 if (!options.c1mode && !noAssemble)
1582 if (options.verbose)
1583 printf ("sdcc: Calling assembler...\n");
1589 // @FIX: Dario Vecchio 03-05-2001
1592 if (yyin && yyin != stdin)
1594 unlink (preOutName);
1595 Safe_free (preOutName);
1598 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1611 if (preOutName && !options.c1mode)
1613 unlink (preOutName);
1614 Safe_free (preOutName);
1617 if (!options.cc_only &&
1621 (srcFileName || nrelFiles))
1623 if (port->linker.do_link)
1624 port->linker.do_link ();
1629 if (yyin && yyin != stdin)