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 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, NULL },
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." }
211 /** Table of all unsupported options and help text to display when one
215 /** shortOpt as in OPTIONS. */
217 /** longOpt as in OPTIONS. */
219 /** Message to display inside W_UNSUPPORTED_OPT when this option
224 static const UNSUPPORTEDOPT
225 unsupportedOptTable[] = {
226 { 'a', NULL, "use --stack-auto instead." },
227 { 'g', NULL, "use --generic instead" },
228 { 'X', NULL, "use --xstack-loc instead" },
229 { 'x', NULL, "use --xstack instead" },
230 { 'p', NULL, "use --stack-loc instead" },
231 { 'P', NULL, "use --stack-loc instead" },
232 { 'i', NULL, "use --idata-loc instead" },
233 { 'r', NULL, "use --xdata-loc instead" },
234 { 's', NULL, "use --code-loc instead" },
235 { 'Y', NULL, "use -I instead" }
238 /** List of all default constant macros.
240 static const char *_baseValues[] = {
241 "cpp", "{bindir}{sep}sdcpp",
243 /* Path seperator character */
244 "sep", DIR_SEPARATOR_STRING,
248 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
252 static PORT *_ports[] =
254 #if !OPT_DISABLE_MCS51
257 #if !OPT_DISABLE_GBZ80
266 #if !OPT_DISABLE_DS390
272 #if !OPT_DISABLE_I186
275 #if !OPT_DISABLE_TLCS900H
280 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
283 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
285 extern void picglue ();
287 /** Sets the port to the one given by the command line option.
288 @param The name minus the option (eg 'mcs51')
289 @return 0 on success.
292 _setPort (const char *name)
295 for (i = 0; i < NUM_PORTS; i++)
297 if (!strcmp (_ports[i]->target, name))
303 /* Error - didnt find */
304 werror (E_UNKNOWN_TARGET, name);
309 _validatePorts (void)
312 for (i = 0; i < NUM_PORTS; i++)
314 if (_ports[i]->magic != PORT_MAGIC)
316 wassertl (0, "Port definition structure is incomplete");
322 _findPort (int argc, char **argv)
328 if (!strncmp (*argv, "-m", 2))
330 _setPort (*argv + 2);
335 /* Use the first in the list */
339 /*-----------------------------------------------------------------*/
340 /* printVersionInfo - prints the version info */
341 /*-----------------------------------------------------------------*/
349 for (i = 0; i < NUM_PORTS; i++)
350 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
352 fprintf (stderr, " %s"
353 #ifdef SDCC_SUB_VERSION_STR
354 "/" SDCC_SUB_VERSION_STR
363 #if defined(_MSC_VER)
375 /*-----------------------------------------------------------------*/
376 /* printUsage - prints command line syntax */
377 /*-----------------------------------------------------------------*/
384 "Usage : sdcc [options] filename\n"
388 for (i = 0; i < LENGTH(optionsTable); i++) {
389 fprintf(stdout, " %c%c %-20s %s\n",
390 optionsTable[i].shortOpt !=0 ? '-' : ' ',
391 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
392 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
393 optionsTable[i].help != NULL ? optionsTable[i].help : ""
399 /*-----------------------------------------------------------------*/
400 /* parseWithComma - separates string with comma */
401 /*-----------------------------------------------------------------*/
403 parseWithComma (char **dest, char *src)
407 strtok (src, "\r\n \t");
408 /* skip the initial white spaces */
409 while (isspace (*src))
426 /*-----------------------------------------------------------------*/
427 /* setDefaultOptions - sets the default options */
428 /*-----------------------------------------------------------------*/
434 for (i = 0; i < 128; i++)
435 preArgv[i] = asmOptions[i] =
436 linkOptions[i] = relFiles[i] = libFiles[i] =
439 /* first the options part */
440 options.stack_loc = 0; /* stack pointer initialised to 0 */
441 options.xstack_loc = 0; /* xternal stack starts at 0 */
442 options.code_loc = 0; /* code starts at 0 */
443 options.data_loc = 0x0030; /* data starts at 0x0030 */
444 options.xdata_loc = 0;
445 options.idata_loc = 0x80;
446 options.genericPtr = 1; /* default on */
448 options.model = port->general.default_model;
449 options.nostdlib = 0;
450 options.nostdinc = 0;
452 options.shortis8bits = 0;
454 options.stack10bit=0;
456 /* now for the optimizations */
457 /* turn on the everything */
458 optimize.global_cse = 1;
463 optimize.loopInvariant = 1;
464 optimize.loopInduction = 1;
466 /* now for the ports */
467 port->setDefaultOptions ();
470 /*-----------------------------------------------------------------*/
471 /* processFile - determines the type of file from the extension */
472 /*-----------------------------------------------------------------*/
474 processFile (char *s)
478 /* get the file extension */
479 fext = s + strlen (s);
480 while ((fext != s) && *fext != '.')
483 /* now if no '.' then we don't know what the file type is
484 so give a warning and return */
487 werror (W_UNKNOWN_FEXT, s);
491 /* otherwise depending on the file type */
492 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
494 /* source file name : not if we already have a
498 werror (W_TOO_MANY_SRC, s);
502 /* the only source file */
503 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
505 werror (E_FILE_OPEN_ERR, s);
509 /* copy the file name into the buffer */
512 /* get rid of the "." */
513 strtok (buffer, ".");
514 srcFileName = Safe_alloc ( strlen (buffer) + 1);
515 strcpy (srcFileName, buffer);
517 /* get rid of any path information
518 for the module name; do this by going
519 backwards till we get to either '/' or '\' or ':'
520 or start of buffer */
521 fext = buffer + strlen (buffer);
522 while (fext != buffer &&
523 *(fext - 1) != '\\' &&
524 *(fext - 1) != '/' &&
527 moduleName = Safe_alloc ( strlen (fext) + 1);
528 strcpy (moduleName, fext);
533 /* if the extention is type .rel or .r or .REL or .R
534 addtional object file will be passed to the linker */
535 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
536 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
537 strcmp (fext, port->linker.rel_ext) == 0)
539 relFiles[nrelFiles++] = s;
543 /* if .lib or .LIB */
544 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
546 libFiles[nlibFiles++] = s;
550 werror (W_UNKNOWN_FEXT, s);
555 _processC1Arg (char *s)
559 if (options.out_name)
561 werror (W_TOO_MANY_SRC, s);
564 options.out_name = Safe_strdup (s);
573 _setModel (int model, const char *sz)
575 if (port->general.supported_models & model)
576 options.model = model;
578 werror (W_UNSUPPORTED_MODEL, sz, port->target);
581 /** Gets the string argument to this option. If the option is '--opt'
582 then for input of '--optxyz' or '--opt xyz' returns xyz.
585 getStringArg(const char *szStart, char **argv, int *pi, int argc)
587 if (argv[*pi][strlen(szStart)])
589 return &argv[*pi][strlen(szStart)];
596 werror (E_ARGUMENT_MISSING, szStart);
597 /* Die here rather than checking for errors later. */
607 /** Gets the integer argument to this option using the same rules as
611 getIntArg(const char *szStart, char **argv, int *pi, int argc)
613 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
617 verifyShortOption(const char *opt)
619 if (strlen(opt) != 2)
621 werror (W_EXCESS_SHORT_OPTIONS, opt);
626 tryHandleUnsupportedOpt(char **argv, int *pi)
628 if (argv[*pi][0] == '-')
630 const char *longOpt = "";
634 if (argv[*pi][1] == '-')
641 shortOpt = argv[*pi][1];
643 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
645 if (unsupportedOptTable[i].shortOpt == shortOpt ||
646 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
647 // Found an unsupported opt.
649 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
650 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
654 // Didn't find in the table
659 // Not an option, so can't be unsupported :)
665 tryHandleSimpleOpt(char **argv, int *pi)
667 if (argv[*pi][0] == '-')
669 const char *longOpt = "";
673 if (argv[*pi][1] == '-')
680 shortOpt = argv[*pi][1];
683 for (i = 0; i < LENGTH(optionsTable); i++)
685 if (optionsTable[i].shortOpt == shortOpt ||
686 (longOpt && optionsTable[i].longOpt &&
687 strcmp(optionsTable[i].longOpt, longOpt) == 0))
690 // If it is a flag then we can handle it here
691 if (optionsTable[i].pparameter != NULL)
693 if (optionsTable[i].shortOpt == shortOpt)
695 verifyShortOption(argv[*pi]);
698 (*optionsTable[i].pparameter)++;
702 // Not a flag. Handled manually later.
707 // Didn't find in the table
712 // Not an option, so can't be handled.
717 /*-----------------------------------------------------------------*/
718 /* parseCmdLine - parses the command line and sets the options */
719 /*-----------------------------------------------------------------*/
721 parseCmdLine (int argc, char **argv)
725 /* go thru all whole command line */
726 for (i = 1; i < argc; i++)
731 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
736 if (tryHandleSimpleOpt(argv, &i) == TRUE)
742 if (argv[i][0] == '-' && argv[i][1] == '-')
744 if (strcmp (argv[i], OPTION_HELP) == 0)
750 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
752 options.stack10bit = 0;
756 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
762 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
764 _setModel (MODEL_LARGE, argv[i]);
768 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
770 _setModel (MODEL_MEDIUM, argv[i]);
774 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
776 _setModel (MODEL_SMALL, argv[i]);
780 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
782 _setModel (MODEL_FLAT24, argv[i]);
786 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
788 options.dump_rassgn =
794 options.dump_raw = 1;
798 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
800 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
804 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
806 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
810 if (strcmp (argv[i], OPTION_VERSION) == 0)
817 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
819 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
823 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
825 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
829 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
831 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
835 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
837 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
841 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
843 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
847 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
849 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
853 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
855 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
859 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
861 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
865 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
867 optimize.global_cse = 0;
871 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
873 optimize.loopInvariant = 0;
877 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
879 optimize.loopInduction = 0;
883 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
885 options.lessPedantic = 1;
886 setErrorLogLevel(ERROR_LEVEL_WARNING);
890 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
892 options.shortis8bits=1;
896 if (!port->parseOption (&argc, argv, &i))
898 werror (W_UNKNOWN_OPTION, argv[i]);
906 /* if preceded by '-' then option */
912 verifyShortOption(argv[i]);
919 /* Used to select the port */
920 _setPort (argv[i] + 2);
924 verifyShortOption(argv[i]);
930 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
934 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
939 if (argv[i][2] == 'l')
941 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
945 /* assembler options */
946 if (argv[i][2] == 'a')
948 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
952 werror (W_UNKNOWN_OPTION, argv[i]);
958 verifyShortOption(argv[i]);
964 /* preprocessor options */
968 addToList (preArgv, "-M");
973 addToList (preArgv, "-C");
982 char sOpt = argv[i][1];
985 if (argv[i][2] == ' ' || argv[i][2] == '\0')
991 werror(E_ARGUMENT_MISSING, argv[i-1]);
1005 sprintf (buffer, "-%c%s", sOpt, rest);
1006 addToList (preArgv, buffer);
1011 if (!port->parseOption (&argc, argv, &i))
1012 werror (W_UNKNOWN_OPTION, argv[i]);
1017 if (!port->parseOption (&argc, argv, &i))
1019 /* no option must be a filename */
1021 _processC1Arg (argv[i]);
1023 processFile (argv[i]);
1027 /* set up external stack location if not explicitly specified */
1028 if (!options.xstack_loc)
1029 options.xstack_loc = options.xdata_loc;
1031 /* if debug option is set the open the cdbFile */
1032 if (options.debug && srcFileName)
1034 sprintf (scratchFileName, "%s.cdb", srcFileName);
1035 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1036 werror (E_FILE_OPEN_ERR, scratchFileName);
1039 /* add a module record */
1040 fprintf (cdbFile, "M:%s\n", moduleName);
1046 /*-----------------------------------------------------------------*/
1047 /* linkEdit : - calls the linkage editor with options */
1048 /*-----------------------------------------------------------------*/
1050 linkEdit (char **envp)
1057 srcFileName = "temp";
1059 /* first we need to create the <filename>.lnk file */
1060 sprintf (scratchFileName, "%s.lnk", srcFileName);
1061 if (!(lnkfile = fopen (scratchFileName, "w")))
1063 werror (E_FILE_OPEN_ERR, scratchFileName);
1067 /* now write the options */
1068 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1070 /* if iram size specified */
1071 if (options.iram_size)
1072 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1075 fprintf (lnkfile, "-z\n");
1077 #define WRITE_SEG_LOC(N, L) \
1078 segName = Safe_strdup(N); \
1079 c = strtok(segName, " \t"); \
1080 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1081 if (segName) { Safe_free(segName); }
1083 /* code segment start */
1084 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1086 /* data segment start */
1087 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1090 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1093 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1095 /* bit segment start */
1096 WRITE_SEG_LOC (BIT_NAME, 0);
1098 /* add the extra linker options */
1099 for (i = 0; linkOptions[i]; i++)
1100 fprintf (lnkfile, "%s\n", linkOptions[i]);
1102 /* other library paths if specified */
1103 for (i = 0; i < nlibPaths; i++)
1104 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1106 /* standard library path */
1107 if (!options.nostdlib)
1110 if (TARGET_IS_DS390)
1117 switch (options.model)
1130 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1135 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1137 /* standard library files */
1138 /* if (strcmp (port->target, "ds390") == 0) */
1139 if (options.model == MODEL_FLAT24)
1141 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1143 fprintf (lnkfile, "-l %s\n", STD_LIB);
1144 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1145 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1146 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1149 /* additional libraries if any */
1150 for (i = 0; i < nlibFiles; i++)
1151 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1153 /* put in the object files */
1154 if (strcmp (srcFileName, "temp"))
1155 fprintf (lnkfile, "%s ", srcFileName);
1157 for (i = 0; i < nrelFiles; i++)
1158 fprintf (lnkfile, "%s\n", relFiles[i]);
1160 fprintf (lnkfile, "\n-e\n");
1163 if (options.verbose)
1164 printf ("sdcc: Calling linker...\n");
1166 if (port->linker.cmd)
1168 char buffer2[PATH_MAX];
1169 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1170 buildCmdLine2 (buffer, buffer2);
1174 buildCmdLine2 (buffer, port->linker.mcmd);
1177 if (my_system (buffer))
1182 if (strcmp (srcFileName, "temp") == 0)
1184 /* rename "temp.cdb" to "firstRelFile.cdb" */
1185 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1186 f = strcat (f, ".cdb");
1187 rename ("temp.cdb", f);
1192 /*-----------------------------------------------------------------*/
1193 /* assemble - spawns the assembler with arguments */
1194 /*-----------------------------------------------------------------*/
1196 assemble (char **envp)
1198 if (port->assembler.cmd)
1200 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1201 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1206 buildCmdLine2 (buffer, port->assembler.mcmd);
1209 if (my_system (buffer))
1211 /* either system() or the assembler itself has reported an error
1212 perror ("Cannot exec assembler");
1218 /*-----------------------------------------------------------------*/
1219 /* preProcess - spawns the preprocessor with arguments */
1220 /*-----------------------------------------------------------------*/
1222 preProcess (char **envp)
1226 if (!options.c1mode)
1228 /* if using external stack define the macro */
1229 if (options.useXstack)
1230 addToList (preArgv, "-DSDCC_USE_XSTACK");
1232 /* set the macro for stack autos */
1233 if (options.stackAuto)
1234 addToList (preArgv, "-DSDCC_STACK_AUTO");
1236 /* set the macro for stack autos */
1237 if (options.stack10bit)
1238 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1240 /* set the macro for no overlay */
1241 if (options.noOverlay)
1242 addToList (preArgv, "-DSDCC_NOOVERLAY");
1244 /* set the macro for large model */
1245 switch (options.model)
1248 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1251 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1254 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1257 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1260 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1263 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1267 /* add port (processor information to processor */
1268 addToList (preArgv, "-DSDCC_{port}");
1269 addToList (preArgv, "-D__{port}");
1271 /* standard include path */
1272 if (!options.nostdinc) {
1273 addToList (preArgv, "-I{includedir}");
1276 setMainValue ("cppextraopts", join(preArgv));
1279 preOutName = Safe_strdup (tempfilename ());
1281 /* Have to set cppoutfilename to something, even if just pre-processing. */
1282 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1284 if (options.verbose)
1285 printf ("sdcc: Calling preprocessor...\n");
1287 buildCmdLine2 (buffer, _preCmd);
1289 if (my_system (buffer))
1291 // @FIX: Dario Vecchio 03-05-2001
1294 unlink (preOutName);
1295 Safe_free (preOutName);
1308 preOutName = fullSrcFileName;
1311 yyin = fopen (preOutName, "r");
1314 perror ("Preproc file not found\n");
1322 _setPaths (const char *pprefix)
1325 Given the prefix and how the directories were layed out at
1326 configure time, see if the library and include directories are
1327 where expected. If so, set.
1329 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1330 strcpy (scratchFileName, pprefix);
1331 strcat (scratchFileName, buffer);
1333 if (pathExists (scratchFileName))
1335 setMainValue ("includedir", scratchFileName);
1342 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1343 strcpy (scratchFileName, pprefix);
1344 strcat (scratchFileName, buffer);
1346 if (pathExists (scratchFileName))
1348 setMainValue ("libdir", scratchFileName);
1359 _discoverPaths (const char *argv0)
1362 1. Try the SDCCDIR environment variable.
1363 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1364 and library paths with respect to that. Note that under win32
1365 argv[0] is always the full path to the program.
1366 3. If (1) and (2) fail, fall back to the compile time defaults.
1368 Detecting assumes the same layout as when configured. If the
1369 directories have been further moved about then discovery will
1373 /* Some input cases:
1374 "c:\fish\sdcc\bin\sdcc"
1376 "/home/fish/bin/sdcc"
1378 Note that ./sdcc is explicitly not supported as there isn't
1381 /* bindir is handled differently to the lib and include directories.
1382 It's rather unfortunate, but required due to the different
1383 install and development layouts. Logic is different as well.
1386 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1388 strcpy (scratchFileName, argv0);
1389 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1390 setMainValue ("bindir", scratchFileName);
1391 ExePathList[0] = Safe_strdup (scratchFileName);
1393 else if (getenv (SDCCDIR_NAME) != NULL)
1395 getPathDifference (buffer, PREFIX, BINDIR);
1396 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1397 strcat (scratchFileName, buffer);
1398 setMainValue ("bindir", scratchFileName);
1399 ExePathList[0] = Safe_strdup (scratchFileName);
1403 setMainValue ("bindir", BINDIR);
1404 ExePathList[0] = BINDIR;
1410 if (getenv (SDCCDIR_NAME) != NULL)
1412 if (_setPaths (getenv (SDCCDIR_NAME)))
1414 /* Successfully set. */
1419 /* Include and lib weren't where expected. */
1423 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1425 char *pbase = getPrefixFromBinPath (argv0);
1429 /* A bad path. Skip. */
1433 if (_setPaths (pbase))
1435 /* Successfully set. */
1440 /* Include and lib weren't where expected. */
1445 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1446 setMainValue ("libdir", SDCC_LIB_DIR);
1453 populateMainValues (_baseValues);
1454 setMainValue ("port", port->target);
1455 setMainValue ("objext", port->linker.rel_ext);
1456 setMainValue ("asmext", port->assembler.file_ext);
1458 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1459 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1464 * initialises and calls the parser
1468 main (int argc, char **argv, char **envp)
1470 /* turn all optimizations off by default */
1471 memset (&optimize, 0, sizeof (struct optimize));
1473 /*printVersionInfo (); */
1476 fprintf (stderr, "Build error: no ports are enabled.\n");
1480 _findPort (argc, argv);
1482 if (strcmp(port->target, "mcs51") == 0) {
1483 printf("DS390 jammed in A\n");
1488 /* Initalise the port. */
1492 // Create a default exe search path from the path to the sdcc command
1495 setDefaultOptions ();
1498 options.model = MODEL_SMALL;
1499 options.stack10bit=0;
1502 parseCmdLine (argc, argv);
1504 /* if no input then printUsage & exit */
1505 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1506 (options.c1mode && !srcFileName && !options.out_name))
1513 _discoverPaths (argv[0]);
1521 port->finaliseOptions ();
1528 if (options.verbose)
1529 printf ("sdcc: Generating code...\n");
1535 if (TARGET_IS_PIC) {
1536 /* TSD PIC port hack - if the PIC port option is enabled
1537 and SDCC is used to generate PIC code, then we will
1538 generate .asm files in gpasm's format instead of SDCC's
1541 #if !OPT_DISABLE_PIC
1550 // @FIX: Dario Vecchio 03-05-2001
1553 if (yyin && yyin != stdin)
1555 unlink (preOutName);
1556 Safe_free (preOutName);
1561 if (!options.c1mode && !noAssemble)
1563 if (options.verbose)
1564 printf ("sdcc: Calling assembler...\n");
1570 // @FIX: Dario Vecchio 03-05-2001
1573 if (yyin && yyin != stdin)
1575 unlink (preOutName);
1576 Safe_free (preOutName);
1579 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1592 if (preOutName && !options.c1mode)
1594 unlink (preOutName);
1595 Safe_free (preOutName);
1598 if (!options.cc_only &&
1602 (srcFileName || nrelFiles))
1604 if (port->linker.do_link)
1605 port->linker.do_link ();
1610 if (yyin && yyin != stdin)