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
288 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
291 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
293 extern void picglue ();
295 /** Sets the port to the one given by the command line option.
296 @param The name minus the option (eg 'mcs51')
297 @return 0 on success.
300 _setPort (const char *name)
303 for (i = 0; i < NUM_PORTS; i++)
305 if (!strcmp (_ports[i]->target, name))
311 /* Error - didnt find */
312 werror (E_UNKNOWN_TARGET, name);
317 _validatePorts (void)
320 for (i = 0; i < NUM_PORTS; i++)
322 if (_ports[i]->magic != PORT_MAGIC)
324 wassertl (0, "Port definition structure is incomplete");
330 _findPort (int argc, char **argv)
336 if (!strncmp (*argv, "-m", 2))
338 _setPort (*argv + 2);
343 /* Use the first in the list */
347 /*-----------------------------------------------------------------*/
348 /* printVersionInfo - prints the version info */
349 /*-----------------------------------------------------------------*/
357 for (i = 0; i < NUM_PORTS; i++)
358 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
360 fprintf (stderr, " %s"
361 #ifdef SDCC_SUB_VERSION_STR
362 "/" SDCC_SUB_VERSION_STR
371 #if defined(_MSC_VER)
383 /*-----------------------------------------------------------------*/
384 /* printUsage - prints command line syntax */
385 /*-----------------------------------------------------------------*/
392 "Usage : sdcc [options] filename\n"
396 for (i = 0; i < LENGTH(optionsTable); i++) {
397 fprintf(stdout, " %c%c %-20s %s\n",
398 optionsTable[i].shortOpt !=0 ? '-' : ' ',
399 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
400 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
401 optionsTable[i].help != NULL ? optionsTable[i].help : ""
407 /*-----------------------------------------------------------------*/
408 /* parseWithComma - separates string with comma */
409 /*-----------------------------------------------------------------*/
411 parseWithComma (char **dest, char *src)
415 strtok (src, "\r\n \t");
416 /* skip the initial white spaces */
417 while (isspace (*src))
434 /*-----------------------------------------------------------------*/
435 /* setDefaultOptions - sets the default options */
436 /*-----------------------------------------------------------------*/
442 for (i = 0; i < 128; i++)
443 preArgv[i] = asmOptions[i] =
444 linkOptions[i] = relFiles[i] = libFiles[i] =
447 /* first the options part */
448 options.stack_loc = 0; /* stack pointer initialised to 0 */
449 options.xstack_loc = 0; /* xternal stack starts at 0 */
450 options.code_loc = 0; /* code starts at 0 */
451 options.data_loc = 0x0030; /* data starts at 0x0030 */
452 options.xdata_loc = 0;
453 options.idata_loc = 0x80;
454 options.genericPtr = 1; /* default on */
456 options.model = port->general.default_model;
457 options.nostdlib = 0;
458 options.nostdinc = 0;
460 options.shortis8bits = 0;
462 options.stack10bit=0;
464 /* now for the optimizations */
465 /* turn on the everything */
466 optimize.global_cse = 1;
471 optimize.loopInvariant = 1;
472 optimize.loopInduction = 1;
474 /* now for the ports */
475 port->setDefaultOptions ();
478 /*-----------------------------------------------------------------*/
479 /* processFile - determines the type of file from the extension */
480 /*-----------------------------------------------------------------*/
482 processFile (char *s)
486 /* get the file extension */
487 fext = s + strlen (s);
488 while ((fext != s) && *fext != '.')
491 /* now if no '.' then we don't know what the file type is
492 so give a warning and return */
495 werror (W_UNKNOWN_FEXT, s);
499 /* otherwise depending on the file type */
500 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
502 /* source file name : not if we already have a
506 werror (W_TOO_MANY_SRC, s);
510 /* the only source file */
511 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
513 werror (E_FILE_OPEN_ERR, s);
517 /* copy the file name into the buffer */
520 /* get rid of the "." */
521 strtok (buffer, ".");
522 srcFileName = Safe_alloc ( strlen (buffer) + 1);
523 strcpy (srcFileName, buffer);
525 /* get rid of any path information
526 for the module name; do this by going
527 backwards till we get to either '/' or '\' or ':'
528 or start of buffer */
529 fext = buffer + strlen (buffer);
530 while (fext != buffer &&
531 *(fext - 1) != '\\' &&
532 *(fext - 1) != '/' &&
535 moduleName = Safe_alloc ( strlen (fext) + 1);
536 strcpy (moduleName, fext);
541 /* if the extention is type .rel or .r or .REL or .R
542 addtional object file will be passed to the linker */
543 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
544 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
545 strcmp (fext, port->linker.rel_ext) == 0)
547 relFiles[nrelFiles++] = s;
551 /* if .lib or .LIB */
552 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
554 libFiles[nlibFiles++] = s;
558 werror (W_UNKNOWN_FEXT, s);
563 _processC1Arg (char *s)
567 if (options.out_name)
569 werror (W_TOO_MANY_SRC, s);
572 options.out_name = Safe_strdup (s);
581 _setModel (int model, const char *sz)
583 if (port->general.supported_models & model)
584 options.model = model;
586 werror (W_UNSUPPORTED_MODEL, sz, port->target);
589 /** Gets the string argument to this option. If the option is '--opt'
590 then for input of '--optxyz' or '--opt xyz' returns xyz.
593 getStringArg(const char *szStart, char **argv, int *pi, int argc)
595 if (argv[*pi][strlen(szStart)])
597 return &argv[*pi][strlen(szStart)];
604 werror (E_ARGUMENT_MISSING, szStart);
605 /* Die here rather than checking for errors later. */
615 /** Gets the integer argument to this option using the same rules as
619 getIntArg(const char *szStart, char **argv, int *pi, int argc)
621 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
625 verifyShortOption(const char *opt)
627 if (strlen(opt) != 2)
629 werror (W_EXCESS_SHORT_OPTIONS, opt);
634 tryHandleUnsupportedOpt(char **argv, int *pi)
636 if (argv[*pi][0] == '-')
638 const char *longOpt = "";
642 if (argv[*pi][1] == '-')
649 shortOpt = argv[*pi][1];
651 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
653 if (unsupportedOptTable[i].shortOpt == shortOpt ||
654 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
655 // Found an unsupported opt.
657 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
658 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
662 // Didn't find in the table
667 // Not an option, so can't be unsupported :)
673 tryHandleSimpleOpt(char **argv, int *pi)
675 if (argv[*pi][0] == '-')
677 const char *longOpt = "";
681 if (argv[*pi][1] == '-')
688 shortOpt = argv[*pi][1];
691 for (i = 0; i < LENGTH(optionsTable); i++)
693 if (optionsTable[i].shortOpt == shortOpt ||
694 (longOpt && optionsTable[i].longOpt &&
695 strcmp(optionsTable[i].longOpt, longOpt) == 0))
698 // If it is a flag then we can handle it here
699 if (optionsTable[i].pparameter != NULL)
701 if (optionsTable[i].shortOpt == shortOpt)
703 verifyShortOption(argv[*pi]);
706 (*optionsTable[i].pparameter)++;
710 // Not a flag. Handled manually later.
715 // Didn't find in the table
720 // Not an option, so can't be handled.
725 /*-----------------------------------------------------------------*/
726 /* parseCmdLine - parses the command line and sets the options */
727 /*-----------------------------------------------------------------*/
729 parseCmdLine (int argc, char **argv)
733 /* go thru all whole command line */
734 for (i = 1; i < argc; i++)
739 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
744 if (tryHandleSimpleOpt(argv, &i) == TRUE)
750 if (argv[i][0] == '-' && argv[i][1] == '-')
752 if (strcmp (argv[i], OPTION_HELP) == 0)
758 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
760 options.stack10bit = 0;
764 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
770 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
772 _setModel (MODEL_LARGE, argv[i]);
776 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
778 _setModel (MODEL_MEDIUM, argv[i]);
782 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
784 _setModel (MODEL_SMALL, argv[i]);
788 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
790 _setModel (MODEL_FLAT24, argv[i]);
794 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
796 options.dump_rassgn =
802 options.dump_raw = 1;
806 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
808 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
812 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
814 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
818 if (strcmp (argv[i], OPTION_VERSION) == 0)
825 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
827 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
831 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
833 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
837 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
839 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
843 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
845 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
849 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
851 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
855 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
857 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
861 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
863 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
867 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
869 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
873 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
875 optimize.global_cse = 0;
879 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
881 optimize.loopInvariant = 0;
885 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
887 optimize.loopInduction = 0;
891 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
893 options.lessPedantic = 1;
894 setErrorLogLevel(ERROR_LEVEL_WARNING);
898 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
900 options.shortis8bits=1;
904 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
906 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
910 if (!port->parseOption (&argc, argv, &i))
912 werror (W_UNKNOWN_OPTION, argv[i]);
920 /* if preceded by '-' then option */
926 verifyShortOption(argv[i]);
933 /* Used to select the port */
934 _setPort (argv[i] + 2);
938 verifyShortOption(argv[i]);
944 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
948 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
952 /* pre-processer options */
953 if (argv[i][2] == 'p')
955 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
958 else if (argv[i][2] == 'l')
960 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
962 /* assembler options */
963 else if (argv[i][2] == 'a')
965 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
969 werror (W_UNKNOWN_OPTION, argv[i]);
974 verifyShortOption(argv[i]);
980 /* preprocessor options */
984 addToList (preArgv, "-M");
989 addToList (preArgv, "-C");
998 char sOpt = argv[i][1];
1001 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1007 werror(E_ARGUMENT_MISSING, argv[i-1]);
1021 sprintf (buffer, "-%c%s", sOpt, rest);
1022 addToList (preArgv, buffer);
1027 if (!port->parseOption (&argc, argv, &i))
1028 werror (W_UNKNOWN_OPTION, argv[i]);
1033 if (!port->parseOption (&argc, argv, &i))
1035 /* no option must be a filename */
1037 _processC1Arg (argv[i]);
1039 processFile (argv[i]);
1043 /* set up external stack location if not explicitly specified */
1044 if (!options.xstack_loc)
1045 options.xstack_loc = options.xdata_loc;
1047 /* if debug option is set the open the cdbFile */
1048 if (options.debug && srcFileName)
1050 sprintf (scratchFileName, "%s.cdb", srcFileName);
1051 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1052 werror (E_FILE_OPEN_ERR, scratchFileName);
1055 /* add a module record */
1056 fprintf (cdbFile, "M:%s\n", moduleName);
1062 /*-----------------------------------------------------------------*/
1063 /* linkEdit : - calls the linkage editor with options */
1064 /*-----------------------------------------------------------------*/
1066 linkEdit (char **envp)
1073 srcFileName = "temp";
1075 /* first we need to create the <filename>.lnk file */
1076 sprintf (scratchFileName, "%s.lnk", srcFileName);
1077 if (!(lnkfile = fopen (scratchFileName, "w")))
1079 werror (E_FILE_OPEN_ERR, scratchFileName);
1083 /* now write the options */
1084 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1086 /* if iram size specified */
1087 if (options.iram_size)
1088 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1091 fprintf (lnkfile, "-z\n");
1093 #define WRITE_SEG_LOC(N, L) \
1094 segName = Safe_strdup(N); \
1095 c = strtok(segName, " \t"); \
1096 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1097 if (segName) { Safe_free(segName); }
1099 /* code segment start */
1100 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1102 /* data segment start */
1103 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1106 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1109 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1111 /* bit segment start */
1112 WRITE_SEG_LOC (BIT_NAME, 0);
1114 /* add the extra linker options */
1115 for (i = 0; linkOptions[i]; i++)
1116 fprintf (lnkfile, "%s\n", linkOptions[i]);
1118 /* other library paths if specified */
1119 for (i = 0; i < nlibPaths; i++)
1120 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1122 /* standard library path */
1123 if (!options.nostdlib)
1126 if (TARGET_IS_DS390)
1133 switch (options.model)
1146 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1151 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1153 /* standard library files */
1154 /* if (strcmp (port->target, "ds390") == 0) */
1155 if (options.model == MODEL_FLAT24)
1157 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1159 fprintf (lnkfile, "-l %s\n", STD_LIB);
1160 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1161 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1162 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1165 /* additional libraries if any */
1166 for (i = 0; i < nlibFiles; i++)
1167 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1169 /* put in the object files */
1170 if (strcmp (srcFileName, "temp"))
1171 fprintf (lnkfile, "%s ", srcFileName);
1173 for (i = 0; i < nrelFiles; i++)
1174 fprintf (lnkfile, "%s\n", relFiles[i]);
1176 fprintf (lnkfile, "\n-e\n");
1179 if (options.verbose)
1180 printf ("sdcc: Calling linker...\n");
1182 if (port->linker.cmd)
1184 char buffer2[PATH_MAX];
1185 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1186 buildCmdLine2 (buffer, buffer2);
1190 buildCmdLine2 (buffer, port->linker.mcmd);
1193 if (my_system (buffer))
1198 if (strcmp (srcFileName, "temp") == 0)
1200 /* rename "temp.cdb" to "firstRelFile.cdb" */
1201 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1202 f = strcat (f, ".cdb");
1203 rename ("temp.cdb", f);
1208 /*-----------------------------------------------------------------*/
1209 /* assemble - spawns the assembler with arguments */
1210 /*-----------------------------------------------------------------*/
1212 assemble (char **envp)
1214 if (port->assembler.do_assemble) {
1215 port->assembler.do_assemble(asmOptions);
1217 } else if (port->assembler.cmd) {
1218 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1219 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1222 buildCmdLine2 (buffer, port->assembler.mcmd);
1225 if (my_system (buffer)) {
1226 /* either system() or the assembler itself has reported an error
1227 perror ("Cannot exec assembler");
1233 /*-----------------------------------------------------------------*/
1234 /* preProcess - spawns the preprocessor with arguments */
1235 /*-----------------------------------------------------------------*/
1237 preProcess (char **envp)
1241 if (!options.c1mode)
1243 /* if using external stack define the macro */
1244 if (options.useXstack)
1245 addToList (preArgv, "-DSDCC_USE_XSTACK");
1247 /* set the macro for stack autos */
1248 if (options.stackAuto)
1249 addToList (preArgv, "-DSDCC_STACK_AUTO");
1251 /* set the macro for stack autos */
1252 if (options.stack10bit)
1253 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1255 /* set the macro for no overlay */
1256 if (options.noOverlay)
1257 addToList (preArgv, "-DSDCC_NOOVERLAY");
1259 /* set the macro for large model */
1260 switch (options.model)
1263 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1266 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1269 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1272 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1275 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1278 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1282 /* add port (processor information to processor */
1283 addToList (preArgv, "-DSDCC_{port}");
1284 addToList (preArgv, "-D__{port}");
1286 /* standard include path */
1287 if (!options.nostdinc) {
1288 addToList (preArgv, "-I{includedir}");
1291 setMainValue ("cppextraopts", join(preArgv));
1294 preOutName = Safe_strdup (tempfilename ());
1296 /* Have to set cppoutfilename to something, even if just pre-processing. */
1297 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1299 if (options.verbose)
1300 printf ("sdcc: Calling preprocessor...\n");
1302 buildCmdLine2 (buffer, _preCmd);
1304 if (my_system (buffer))
1306 // @FIX: Dario Vecchio 03-05-2001
1309 unlink (preOutName);
1310 Safe_free (preOutName);
1323 preOutName = fullSrcFileName;
1326 yyin = fopen (preOutName, "r");
1329 perror ("Preproc file not found\n");
1337 _setPaths (const char *pprefix)
1340 Given the prefix and how the directories were layed out at
1341 configure time, see if the library and include directories are
1342 where expected. If so, set.
1344 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1345 strcpy (scratchFileName, pprefix);
1346 strcat (scratchFileName, buffer);
1348 if (pathExists (scratchFileName))
1350 setMainValue ("includedir", scratchFileName);
1357 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1358 strcpy (scratchFileName, pprefix);
1359 strcat (scratchFileName, buffer);
1361 if (pathExists (scratchFileName))
1363 setMainValue ("libdir", scratchFileName);
1374 _discoverPaths (const char *argv0)
1377 1. Try the SDCCDIR environment variable.
1378 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1379 and library paths with respect to that. Note that under win32
1380 argv[0] is always the full path to the program.
1381 3. If (1) and (2) fail, fall back to the compile time defaults.
1383 Detecting assumes the same layout as when configured. If the
1384 directories have been further moved about then discovery will
1388 /* Some input cases:
1389 "c:\fish\sdcc\bin\sdcc"
1391 "/home/fish/bin/sdcc"
1393 Note that ./sdcc is explicitly not supported as there isn't
1396 /* bindir is handled differently to the lib and include directories.
1397 It's rather unfortunate, but required due to the different
1398 install and development layouts. Logic is different as well.
1401 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1403 strcpy (scratchFileName, argv0);
1404 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1405 setMainValue ("bindir", scratchFileName);
1406 ExePathList[0] = Safe_strdup (scratchFileName);
1408 else if (getenv (SDCCDIR_NAME) != NULL)
1410 getPathDifference (buffer, PREFIX, BINDIR);
1411 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1412 strcat (scratchFileName, buffer);
1413 setMainValue ("bindir", scratchFileName);
1414 ExePathList[0] = Safe_strdup (scratchFileName);
1418 setMainValue ("bindir", BINDIR);
1419 ExePathList[0] = BINDIR;
1425 if (getenv (SDCCDIR_NAME) != NULL)
1427 if (_setPaths (getenv (SDCCDIR_NAME)))
1429 /* Successfully set. */
1434 /* Include and lib weren't where expected. */
1438 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1440 char *pbase = getPrefixFromBinPath (argv0);
1444 /* A bad path. Skip. */
1448 if (_setPaths (pbase))
1450 /* Successfully set. */
1455 /* Include and lib weren't where expected. */
1460 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1461 setMainValue ("libdir", SDCC_LIB_DIR);
1468 populateMainValues (_baseValues);
1469 setMainValue ("port", port->target);
1470 setMainValue ("objext", port->linker.rel_ext);
1471 setMainValue ("asmext", port->assembler.file_ext);
1473 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1474 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1479 * initialises and calls the parser
1483 main (int argc, char **argv, char **envp)
1485 /* turn all optimizations off by default */
1486 memset (&optimize, 0, sizeof (struct optimize));
1488 /*printVersionInfo (); */
1491 fprintf (stderr, "Build error: no ports are enabled.\n");
1495 _findPort (argc, argv);
1497 if (strcmp(port->target, "mcs51") == 0) {
1498 printf("DS390 jammed in A\n");
1503 /* Initalise the port. */
1507 // Create a default exe search path from the path to the sdcc command
1510 setDefaultOptions ();
1513 options.model = MODEL_SMALL;
1514 options.stack10bit=0;
1517 parseCmdLine (argc, argv);
1519 /* if no input then printUsage & exit */
1520 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1521 (options.c1mode && !srcFileName && !options.out_name))
1528 _discoverPaths (argv[0]);
1536 port->finaliseOptions ();
1544 if (options.verbose)
1545 printf ("sdcc: Generating code...\n");
1551 if (TARGET_IS_PIC) {
1552 /* TSD PIC port hack - if the PIC port option is enabled
1553 and SDCC is used to generate PIC code, then we will
1554 generate .asm files in gpasm's format instead of SDCC's
1557 #if !OPT_DISABLE_PIC
1566 // @FIX: Dario Vecchio 03-05-2001
1569 if (yyin && yyin != stdin)
1571 unlink (preOutName);
1572 Safe_free (preOutName);
1577 if (!options.c1mode && !noAssemble)
1579 if (options.verbose)
1580 printf ("sdcc: Calling assembler...\n");
1586 // @FIX: Dario Vecchio 03-05-2001
1589 if (yyin && yyin != stdin)
1591 unlink (preOutName);
1592 Safe_free (preOutName);
1595 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1608 if (preOutName && !options.c1mode)
1610 unlink (preOutName);
1611 Safe_free (preOutName);
1614 if (!options.cc_only &&
1618 (srcFileName || nrelFiles))
1620 if (port->linker.do_link)
1621 port->linker.do_link ();
1626 if (yyin && yyin != stdin)