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[FILENAME_MAX];
83 char buffer[FILENAME_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, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
175 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
176 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
177 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
178 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
179 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
180 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
181 { 0, OPTION_IDATA_LOC, NULL, NULL },
182 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
183 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
184 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
185 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
186 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
187 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
188 { 0, "--cyclomatic", &options.cyclomatic, NULL },
189 { 0, "--nooverlay", &options.noOverlay, NULL },
190 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
191 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
192 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
193 { 0, "--peep-asm", &options.asmpeep, NULL },
194 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
195 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
196 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
197 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
198 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
199 { 0, "--help", NULL, "Display this help" },
200 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
201 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
202 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
203 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
204 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
205 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
206 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" }
209 /** Table of all unsupported options and help text to display when one
213 /** shortOpt as in OPTIONS. */
215 /** longOpt as in OPTIONS. */
217 /** Message to display inside W_UNSUPPORTED_OPT when this option
222 static const UNSUPPORTEDOPT
223 unsupportedOptTable[] = {
224 { 'a', NULL, "use --stack-auto instead." },
225 { 'g', NULL, "use --generic instead" },
226 { 'X', NULL, "use --xstack-loc instead" },
227 { 'x', NULL, "use --xstack instead" },
228 { 'p', NULL, "use --stack-loc instead" },
229 { 'P', NULL, "use --stack-loc instead" },
230 { 'i', NULL, "use --idata-loc instead" },
231 { 'r', NULL, "use --xdata-loc instead" },
232 { 's', NULL, "use --code-loc instead" },
233 { 'Y', NULL, "use -I instead" }
236 /** List of all default constant macros.
238 static const char *_baseValues[] = {
239 "cpp", "{bindir}{sep}sdcpp",
241 /* Path seperator character */
242 "sep", DIR_SEPARATOR_STRING,
246 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
250 static PORT *_ports[] =
252 #if !OPT_DISABLE_MCS51
255 #if !OPT_DISABLE_GBZ80
264 #if !OPT_DISABLE_DS390
270 #if !OPT_DISABLE_I186
273 #if !OPT_DISABLE_TLCS900H
278 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
281 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
283 extern void picglue ();
285 /** Sets the port to the one given by the command line option.
286 @param The name minus the option (eg 'mcs51')
287 @return 0 on success.
290 _setPort (const char *name)
293 for (i = 0; i < NUM_PORTS; i++)
295 if (!strcmp (_ports[i]->target, name))
301 /* Error - didnt find */
302 werror (E_UNKNOWN_TARGET, name);
307 _validatePorts (void)
310 for (i = 0; i < NUM_PORTS; i++)
312 if (_ports[i]->magic != PORT_MAGIC)
314 wassertl (0, "Port definition structure is incomplete");
320 _findPort (int argc, char **argv)
326 if (!strncmp (*argv, "-m", 2))
328 _setPort (*argv + 2);
333 /* Use the first in the list */
337 /*-----------------------------------------------------------------*/
338 /* printVersionInfo - prints the version info */
339 /*-----------------------------------------------------------------*/
347 for (i = 0; i < NUM_PORTS; i++)
348 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
350 fprintf (stderr, " %s"
351 #ifdef SDCC_SUB_VERSION_STR
352 "/" SDCC_SUB_VERSION_STR
361 #if defined(_MSC_VER)
373 /*-----------------------------------------------------------------*/
374 /* printUsage - prints command line syntax */
375 /*-----------------------------------------------------------------*/
382 "Usage : sdcc [options] filename\n"
386 for (i = 0; i < LENGTH(optionsTable); i++) {
387 fprintf(stdout, " %c%c %-20s %s\n",
388 optionsTable[i].shortOpt !=0 ? '-' : ' ',
389 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
390 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
391 optionsTable[i].help != NULL ? optionsTable[i].help : ""
397 /*-----------------------------------------------------------------*/
398 /* parseWithComma - separates string with comma */
399 /*-----------------------------------------------------------------*/
401 parseWithComma (char **dest, char *src)
405 strtok (src, "\r\n \t");
406 /* skip the initial white spaces */
407 while (isspace (*src))
424 /*-----------------------------------------------------------------*/
425 /* setDefaultOptions - sets the default options */
426 /*-----------------------------------------------------------------*/
432 for (i = 0; i < 128; i++)
433 preArgv[i] = asmOptions[i] =
434 linkOptions[i] = relFiles[i] = libFiles[i] =
437 /* first the options part */
438 options.stack_loc = 0; /* stack pointer initialised to 0 */
439 options.xstack_loc = 0; /* xternal stack starts at 0 */
440 options.code_loc = 0; /* code starts at 0 */
441 options.data_loc = 0x0030; /* data starts at 0x0030 */
442 options.xdata_loc = 0;
443 options.idata_loc = 0x80;
444 options.genericPtr = 1; /* default on */
446 options.model = port->general.default_model;
447 options.nostdlib = 0;
448 options.nostdinc = 0;
450 options.shortis8bits = 0;
452 options.stack10bit=0;
454 /* now for the optimizations */
455 /* turn on the everything */
456 optimize.global_cse = 1;
461 optimize.loopInvariant = 1;
462 optimize.loopInduction = 1;
464 /* now for the ports */
465 port->setDefaultOptions ();
468 /*-----------------------------------------------------------------*/
469 /* processFile - determines the type of file from the extension */
470 /*-----------------------------------------------------------------*/
472 processFile (char *s)
476 /* get the file extension */
477 fext = s + strlen (s);
478 while ((fext != s) && *fext != '.')
481 /* now if no '.' then we don't know what the file type is
482 so give a warning and return */
485 werror (W_UNKNOWN_FEXT, s);
489 /* otherwise depending on the file type */
490 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
492 /* source file name : not if we already have a
496 werror (W_TOO_MANY_SRC, s);
500 /* the only source file */
501 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
503 werror (E_FILE_OPEN_ERR, s);
507 /* copy the file name into the buffer */
510 /* get rid of the "." */
511 strtok (buffer, ".");
512 srcFileName = Safe_alloc ( strlen (buffer) + 1);
513 strcpy (srcFileName, buffer);
515 /* get rid of any path information
516 for the module name; do this by going
517 backwards till we get to either '/' or '\' or ':'
518 or start of buffer */
519 fext = buffer + strlen (buffer);
520 while (fext != buffer &&
521 *(fext - 1) != '\\' &&
522 *(fext - 1) != '/' &&
525 moduleName = Safe_alloc ( strlen (fext) + 1);
526 strcpy (moduleName, fext);
531 /* if the extention is type .rel or .r or .REL or .R
532 addtional object file will be passed to the linker */
533 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
534 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
535 strcmp (fext, port->linker.rel_ext) == 0)
537 relFiles[nrelFiles++] = s;
541 /* if .lib or .LIB */
542 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
544 libFiles[nlibFiles++] = s;
548 werror (W_UNKNOWN_FEXT, s);
553 _processC1Arg (char *s)
557 if (options.out_name)
559 werror (W_TOO_MANY_SRC, s);
562 options.out_name = strdup (s);
571 _setModel (int model, const char *sz)
573 if (port->general.supported_models & model)
574 options.model = model;
576 werror (W_UNSUPPORTED_MODEL, sz, port->target);
579 /** Gets the string argument to this option. If the option is '--opt'
580 then for input of '--optxyz' or '--opt xyz' returns xyz.
583 getStringArg(const char *szStart, char **argv, int *pi, int argc)
585 if (argv[*pi][strlen(szStart)])
587 return &argv[*pi][strlen(szStart)];
594 werror (E_ARGUMENT_MISSING, szStart);
595 /* Die here rather than checking for errors later. */
605 /** Gets the integer argument to this option using the same rules as
609 getIntArg(const char *szStart, char **argv, int *pi, int argc)
611 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
615 verifyShortOption(const char *opt)
617 if (strlen(opt) != 2)
619 werror (W_EXCESS_SHORT_OPTIONS, opt);
624 tryHandleUnsupportedOpt(char **argv, int *pi)
626 if (argv[*pi][0] == '-')
628 const char *longOpt = "";
632 if (argv[*pi][1] == '-')
639 shortOpt = argv[*pi][1];
641 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
643 if (unsupportedOptTable[i].shortOpt == shortOpt ||
644 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
645 // Found an unsupported opt.
647 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
648 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
652 // Didn't find in the table
657 // Not an option, so can't be unsupported :)
663 tryHandleSimpleOpt(char **argv, int *pi)
665 if (argv[*pi][0] == '-')
667 const char *longOpt = "";
671 if (argv[*pi][1] == '-')
678 shortOpt = argv[*pi][1];
681 for (i = 0; i < LENGTH(optionsTable); i++)
683 if (optionsTable[i].shortOpt == shortOpt ||
684 (longOpt && optionsTable[i].longOpt &&
685 strcmp(optionsTable[i].longOpt, longOpt) == 0))
688 // If it is a flag then we can handle it here
689 if (optionsTable[i].pparameter != NULL)
691 if (optionsTable[i].shortOpt == shortOpt)
693 verifyShortOption(argv[*pi]);
696 (*optionsTable[i].pparameter)++;
700 // Not a flag. Handled manually later.
705 // Didn't find in the table
710 // Not an option, so can't be handled.
715 /*-----------------------------------------------------------------*/
716 /* parseCmdLine - parses the command line and sets the options */
717 /*-----------------------------------------------------------------*/
719 parseCmdLine (int argc, char **argv)
723 /* go thru all whole command line */
724 for (i = 1; i < argc; i++)
729 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
734 if (tryHandleSimpleOpt(argv, &i) == TRUE)
740 if (argv[i][0] == '-' && argv[i][1] == '-')
742 if (strcmp (argv[i], OPTION_HELP) == 0)
748 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
750 options.stack10bit = 0;
754 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
760 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
762 _setModel (MODEL_LARGE, argv[i]);
766 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
768 _setModel (MODEL_MEDIUM, argv[i]);
772 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
774 _setModel (MODEL_SMALL, argv[i]);
778 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
780 _setModel (MODEL_FLAT24, argv[i]);
784 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
786 options.dump_rassgn =
792 options.dump_raw = 1;
796 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
798 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
802 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
804 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
808 if (strcmp (argv[i], OPTION_VERSION) == 0)
815 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
817 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
821 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
823 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
827 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
829 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
833 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
835 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
839 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
841 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
845 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
847 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
851 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
853 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
857 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
859 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
863 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
865 optimize.global_cse = 0;
869 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
871 optimize.loopInvariant = 0;
875 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
877 optimize.loopInduction = 0;
881 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
883 options.lessPedantic = 1;
884 setErrorLogLevel(ERROR_LEVEL_WARNING);
888 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
890 options.shortis8bits=1;
894 if (!port->parseOption (&argc, argv, &i))
896 werror (W_UNKNOWN_OPTION, argv[i]);
904 /* if preceded by '-' then option */
910 verifyShortOption(argv[i]);
917 /* Used to select the port */
918 _setPort (argv[i] + 2);
922 verifyShortOption(argv[i]);
928 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
932 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
937 if (argv[i][2] == 'l')
939 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
943 /* assembler options */
944 if (argv[i][2] == 'a')
946 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
950 werror (W_UNKNOWN_OPTION, argv[i]);
956 verifyShortOption(argv[i]);
962 /* preprocessor options */
966 addToList (preArgv, "-M");
971 addToList (preArgv, "-C");
980 char sOpt = argv[i][1];
983 if (argv[i][2] == ' ' || argv[i][2] == '\0')
989 werror(E_ARGUMENT_MISSING, argv[i-1]);
1003 sprintf (buffer, "-%c%s", sOpt, rest);
1004 addToList (preArgv, buffer);
1009 if (!port->parseOption (&argc, argv, &i))
1010 werror (W_UNKNOWN_OPTION, argv[i]);
1015 if (!port->parseOption (&argc, argv, &i))
1017 /* no option must be a filename */
1019 _processC1Arg (argv[i]);
1021 processFile (argv[i]);
1025 /* set up external stack location if not explicitly specified */
1026 if (!options.xstack_loc)
1027 options.xstack_loc = options.xdata_loc;
1029 /* if debug option is set the open the cdbFile */
1030 if (options.debug && srcFileName)
1032 sprintf (scratchFileName, "%s.cdb", srcFileName);
1033 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1034 werror (E_FILE_OPEN_ERR, scratchFileName);
1037 /* add a module record */
1038 fprintf (cdbFile, "M:%s\n", moduleName);
1044 /*-----------------------------------------------------------------*/
1045 /* linkEdit : - calls the linkage editor with options */
1046 /*-----------------------------------------------------------------*/
1048 linkEdit (char **envp)
1055 srcFileName = "temp";
1057 /* first we need to create the <filename>.lnk file */
1058 sprintf (scratchFileName, "%s.lnk", srcFileName);
1059 if (!(lnkfile = fopen (scratchFileName, "w")))
1061 werror (E_FILE_OPEN_ERR, scratchFileName);
1065 /* now write the options */
1066 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1068 /* if iram size specified */
1069 if (options.iram_size)
1070 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1073 fprintf (lnkfile, "-z\n");
1075 #define WRITE_SEG_LOC(N, L) \
1076 segName = strdup(N); \
1077 c = strtok(segName, " \t"); \
1078 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1079 if (segName) { Safe_free(segName); }
1081 /* code segment start */
1082 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1084 /* data segment start */
1085 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1088 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1091 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1093 /* bit segment start */
1094 WRITE_SEG_LOC (BIT_NAME, 0);
1096 /* add the extra linker options */
1097 for (i = 0; linkOptions[i]; i++)
1098 fprintf (lnkfile, "%s\n", linkOptions[i]);
1100 /* other library paths if specified */
1101 for (i = 0; i < nlibPaths; i++)
1102 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1104 /* standard library path */
1105 if (!options.nostdlib)
1108 if (TARGET_IS_DS390)
1115 switch (options.model)
1128 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1133 fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1135 /* standard library files */
1136 /* if (strcmp (port->target, "ds390") == 0) */
1137 if (options.model == MODEL_FLAT24)
1139 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1141 fprintf (lnkfile, "-l %s\n", STD_LIB);
1142 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1143 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1144 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1147 /* additional libraries if any */
1148 for (i = 0; i < nlibFiles; i++)
1149 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1151 /* put in the object files */
1152 if (strcmp (srcFileName, "temp"))
1153 fprintf (lnkfile, "%s ", srcFileName);
1155 for (i = 0; i < nrelFiles; i++)
1156 fprintf (lnkfile, "%s\n", relFiles[i]);
1158 fprintf (lnkfile, "\n-e\n");
1161 if (options.verbose)
1162 printf ("sdcc: Calling linker...\n");
1164 if (port->linker.cmd)
1166 buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1170 buildCmdLine2 (buffer, port->linker.mcmd);
1173 if (my_system (buffer))
1178 if (strcmp (srcFileName, "temp") == 0)
1180 /* rename "temp.cdb" to "firstRelFile.cdb" */
1181 char *f = strtok (strdup (relFiles[0]), ".");
1182 f = strcat (f, ".cdb");
1183 rename ("temp.cdb", f);
1188 /*-----------------------------------------------------------------*/
1189 /* assemble - spawns the assembler with arguments */
1190 /*-----------------------------------------------------------------*/
1192 assemble (char **envp)
1194 if (port->assembler.cmd)
1196 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1197 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1202 buildCmdLine2 (buffer, port->assembler.mcmd);
1205 if (my_system (buffer))
1207 /* either system() or the assembler itself has reported an error
1208 perror ("Cannot exec assembler");
1214 /*-----------------------------------------------------------------*/
1215 /* preProcess - spawns the preprocessor with arguments */
1216 /*-----------------------------------------------------------------*/
1218 preProcess (char **envp)
1222 if (!options.c1mode)
1224 /* if using external stack define the macro */
1225 if (options.useXstack)
1226 addToList (preArgv, "-DSDCC_USE_XSTACK");
1228 /* set the macro for stack autos */
1229 if (options.stackAuto)
1230 addToList (preArgv, "-DSDCC_STACK_AUTO");
1232 /* set the macro for stack autos */
1233 if (options.stack10bit)
1234 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1236 /* set the macro for large model */
1237 switch (options.model)
1240 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1243 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1246 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1249 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1252 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1255 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1259 /* add port (processor information to processor */
1260 addToList (preArgv, "-DSDCC_{port}");
1261 addToList (preArgv, "-D__{port}");
1263 /* standard include path */
1264 if (!options.nostdinc) {
1265 addToList (preArgv, "-I{includedir}");
1268 setMainValue ("cppextraopts", join(preArgv));
1271 preOutName = Safe_strdup (tempfilename ());
1273 /* Have to set cppoutfilename to something, even if just pre-processing. */
1274 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1276 if (options.verbose)
1277 printf ("sdcc: Calling preprocessor...\n");
1279 buildCmdLine2 (buffer, _preCmd);
1281 if (my_system (buffer))
1283 // @FIX: Dario Vecchio 03-05-2001
1286 unlink (preOutName);
1287 Safe_free (preOutName);
1300 preOutName = fullSrcFileName;
1303 yyin = fopen (preOutName, "r");
1306 perror ("Preproc file not found\n");
1314 _setPaths (const char *pprefix)
1317 Given the prefix and how the directories were layed out at
1318 configure time, see if the library and include directories are
1319 where expected. If so, set.
1321 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1322 strcpy (scratchFileName, pprefix);
1323 strcat (scratchFileName, buffer);
1325 if (pathExists (scratchFileName))
1327 setMainValue ("includedir", scratchFileName);
1334 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1335 strcpy (scratchFileName, pprefix);
1336 strcat (scratchFileName, buffer);
1338 if (pathExists (scratchFileName))
1340 setMainValue ("libdir", scratchFileName);
1351 _discoverPaths (const char *argv0)
1354 1. Try the SDCCDIR environment variable.
1355 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1356 and library paths with respect to that. Note that under win32
1357 argv[0] is always the full path to the program.
1358 3. If (1) and (2) fail, fall back to the compile time defaults.
1360 Detecting assumes the same layout as when configured. If the
1361 directories have been further moved about then discovery will
1365 /* Some input cases:
1366 "c:\fish\sdcc\bin\sdcc"
1368 "/home/fish/bin/sdcc"
1370 Note that ./sdcc is explicitly not supported as there isn't
1373 /* bindir is handled differently to the lib and include directories.
1374 It's rather unfortunate, but required due to the different
1375 install and development layouts. Logic is different as well.
1378 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1380 strcpy (scratchFileName, argv0);
1381 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1382 setMainValue ("bindir", scratchFileName);
1383 ExePathList[0] = gc_strdup (scratchFileName);
1385 else if (getenv (SDCCDIR_NAME) != NULL)
1387 getPathDifference (buffer, PREFIX, BINDIR);
1388 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1389 strcat (scratchFileName, buffer);
1390 setMainValue ("bindir", scratchFileName);
1391 ExePathList[0] = gc_strdup (scratchFileName);
1395 setMainValue ("bindir", BINDIR);
1396 ExePathList[0] = BINDIR;
1402 if (getenv (SDCCDIR_NAME) != NULL)
1404 if (_setPaths (getenv (SDCCDIR_NAME)))
1406 /* Successfully set. */
1411 /* Include and lib weren't where expected. */
1415 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1417 char *pbase = getPrefixFromBinPath (argv0);
1421 /* A bad path. Skip. */
1425 if (_setPaths (pbase))
1427 /* Successfully set. */
1432 /* Include and lib weren't where expected. */
1437 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1438 setMainValue ("libdir", SDCC_LIB_DIR);
1445 populateMainValues (_baseValues);
1446 setMainValue ("port", port->target);
1447 setMainValue ("fullsrcfilename", fullSrcFileName);
1448 setMainValue ("srcfilename", srcFileName);
1449 setMainValue ("objext", port->linker.rel_ext);
1450 setMainValue ("asmext", port->assembler.file_ext);
1455 * initialises and calls the parser
1459 main (int argc, char **argv, char **envp)
1461 /* turn all optimizations off by default */
1462 memset (&optimize, 0, sizeof (struct optimize));
1464 /*printVersionInfo (); */
1467 fprintf (stderr, "Build error: no ports are enabled.\n");
1471 _findPort (argc, argv);
1473 if (strcmp(port->target, "mcs51") == 0) {
1474 printf("DS390 jammed in A\n");
1479 /* Initalise the port. */
1483 // Create a default exe search path from the path to the sdcc command
1486 setDefaultOptions ();
1489 options.model = MODEL_SMALL;
1490 options.stack10bit=0;
1493 parseCmdLine (argc, argv);
1495 /* if no input then printUsage & exit */
1496 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1497 (options.c1mode && !srcFileName && !options.out_name))
1506 _discoverPaths (argv[0]);
1512 port->finaliseOptions ();
1519 if (options.verbose)
1520 printf ("sdcc: Generating code...\n");
1526 if (TARGET_IS_PIC) {
1527 /* TSD PIC port hack - if the PIC port option is enabled
1528 and SDCC is used to generate PIC code, then we will
1529 generate .asm files in gpasm's format instead of SDCC's
1532 #if !OPT_DISABLE_PIC
1541 // @FIX: Dario Vecchio 03-05-2001
1544 if (yyin && yyin != stdin)
1546 unlink (preOutName);
1547 Safe_free (preOutName);
1552 if (!options.c1mode && !noAssemble)
1554 if (options.verbose)
1555 printf ("sdcc: Calling assembler...\n");
1561 // @FIX: Dario Vecchio 03-05-2001
1564 if (yyin && yyin != stdin)
1566 unlink (preOutName);
1567 Safe_free (preOutName);
1570 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1583 if (preOutName && !options.c1mode)
1585 unlink (preOutName);
1586 Safe_free (preOutName);
1589 if (!options.cc_only &&
1593 (srcFileName || nrelFiles))
1595 if (port->linker.do_link)
1596 port->linker.do_link ();
1601 if (yyin && yyin != stdin)