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, 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" },
207 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." }
210 /** Table of all unsupported options and help text to display when one
214 /** shortOpt as in OPTIONS. */
216 /** longOpt as in OPTIONS. */
218 /** Message to display inside W_UNSUPPORTED_OPT when this option
223 static const UNSUPPORTEDOPT
224 unsupportedOptTable[] = {
225 { 'a', NULL, "use --stack-auto instead." },
226 { 'g', NULL, "use --generic instead" },
227 { 'X', NULL, "use --xstack-loc instead" },
228 { 'x', NULL, "use --xstack instead" },
229 { 'p', NULL, "use --stack-loc instead" },
230 { 'P', NULL, "use --stack-loc instead" },
231 { 'i', NULL, "use --idata-loc instead" },
232 { 'r', NULL, "use --xdata-loc instead" },
233 { 's', NULL, "use --code-loc instead" },
234 { 'Y', NULL, "use -I instead" }
237 /** List of all default constant macros.
239 static const char *_baseValues[] = {
240 "cpp", "{bindir}{sep}sdcpp",
242 /* Path seperator character */
243 "sep", DIR_SEPARATOR_STRING,
247 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
251 static PORT *_ports[] =
253 #if !OPT_DISABLE_MCS51
256 #if !OPT_DISABLE_GBZ80
265 #if !OPT_DISABLE_DS390
271 #if !OPT_DISABLE_I186
274 #if !OPT_DISABLE_TLCS900H
279 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
282 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
284 extern void picglue ();
286 /** Sets the port to the one given by the command line option.
287 @param The name minus the option (eg 'mcs51')
288 @return 0 on success.
291 _setPort (const char *name)
294 for (i = 0; i < NUM_PORTS; i++)
296 if (!strcmp (_ports[i]->target, name))
302 /* Error - didnt find */
303 werror (E_UNKNOWN_TARGET, name);
308 _validatePorts (void)
311 for (i = 0; i < NUM_PORTS; i++)
313 if (_ports[i]->magic != PORT_MAGIC)
315 wassertl (0, "Port definition structure is incomplete");
321 _findPort (int argc, char **argv)
327 if (!strncmp (*argv, "-m", 2))
329 _setPort (*argv + 2);
334 /* Use the first in the list */
338 /*-----------------------------------------------------------------*/
339 /* printVersionInfo - prints the version info */
340 /*-----------------------------------------------------------------*/
348 for (i = 0; i < NUM_PORTS; i++)
349 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
351 fprintf (stderr, " %s"
352 #ifdef SDCC_SUB_VERSION_STR
353 "/" SDCC_SUB_VERSION_STR
362 #if defined(_MSC_VER)
374 /*-----------------------------------------------------------------*/
375 /* printUsage - prints command line syntax */
376 /*-----------------------------------------------------------------*/
383 "Usage : sdcc [options] filename\n"
387 for (i = 0; i < LENGTH(optionsTable); i++) {
388 fprintf(stdout, " %c%c %-20s %s\n",
389 optionsTable[i].shortOpt !=0 ? '-' : ' ',
390 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
391 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
392 optionsTable[i].help != NULL ? optionsTable[i].help : ""
398 /*-----------------------------------------------------------------*/
399 /* parseWithComma - separates string with comma */
400 /*-----------------------------------------------------------------*/
402 parseWithComma (char **dest, char *src)
406 strtok (src, "\r\n \t");
407 /* skip the initial white spaces */
408 while (isspace (*src))
425 /*-----------------------------------------------------------------*/
426 /* setDefaultOptions - sets the default options */
427 /*-----------------------------------------------------------------*/
433 for (i = 0; i < 128; i++)
434 preArgv[i] = asmOptions[i] =
435 linkOptions[i] = relFiles[i] = libFiles[i] =
438 /* first the options part */
439 options.stack_loc = 0; /* stack pointer initialised to 0 */
440 options.xstack_loc = 0; /* xternal stack starts at 0 */
441 options.code_loc = 0; /* code starts at 0 */
442 options.data_loc = 0x0030; /* data starts at 0x0030 */
443 options.xdata_loc = 0;
444 options.idata_loc = 0x80;
445 options.genericPtr = 1; /* default on */
447 options.model = port->general.default_model;
448 options.nostdlib = 0;
449 options.nostdinc = 0;
451 options.shortis8bits = 0;
453 options.stack10bit=0;
455 /* now for the optimizations */
456 /* turn on the everything */
457 optimize.global_cse = 1;
462 optimize.loopInvariant = 1;
463 optimize.loopInduction = 1;
465 /* now for the ports */
466 port->setDefaultOptions ();
469 /*-----------------------------------------------------------------*/
470 /* processFile - determines the type of file from the extension */
471 /*-----------------------------------------------------------------*/
473 processFile (char *s)
477 /* get the file extension */
478 fext = s + strlen (s);
479 while ((fext != s) && *fext != '.')
482 /* now if no '.' then we don't know what the file type is
483 so give a warning and return */
486 werror (W_UNKNOWN_FEXT, s);
490 /* otherwise depending on the file type */
491 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
493 /* source file name : not if we already have a
497 werror (W_TOO_MANY_SRC, s);
501 /* the only source file */
502 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
504 werror (E_FILE_OPEN_ERR, s);
508 /* copy the file name into the buffer */
511 /* get rid of the "." */
512 strtok (buffer, ".");
513 srcFileName = Safe_alloc ( strlen (buffer) + 1);
514 strcpy (srcFileName, buffer);
516 /* get rid of any path information
517 for the module name; do this by going
518 backwards till we get to either '/' or '\' or ':'
519 or start of buffer */
520 fext = buffer + strlen (buffer);
521 while (fext != buffer &&
522 *(fext - 1) != '\\' &&
523 *(fext - 1) != '/' &&
526 moduleName = Safe_alloc ( strlen (fext) + 1);
527 strcpy (moduleName, fext);
532 /* if the extention is type .rel or .r or .REL or .R
533 addtional object file will be passed to the linker */
534 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
535 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
536 strcmp (fext, port->linker.rel_ext) == 0)
538 relFiles[nrelFiles++] = s;
542 /* if .lib or .LIB */
543 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
545 libFiles[nlibFiles++] = s;
549 werror (W_UNKNOWN_FEXT, s);
554 _processC1Arg (char *s)
558 if (options.out_name)
560 werror (W_TOO_MANY_SRC, s);
563 options.out_name = Safe_strdup (s);
572 _setModel (int model, const char *sz)
574 if (port->general.supported_models & model)
575 options.model = model;
577 werror (W_UNSUPPORTED_MODEL, sz, port->target);
580 /** Gets the string argument to this option. If the option is '--opt'
581 then for input of '--optxyz' or '--opt xyz' returns xyz.
584 getStringArg(const char *szStart, char **argv, int *pi, int argc)
586 if (argv[*pi][strlen(szStart)])
588 return &argv[*pi][strlen(szStart)];
595 werror (E_ARGUMENT_MISSING, szStart);
596 /* Die here rather than checking for errors later. */
606 /** Gets the integer argument to this option using the same rules as
610 getIntArg(const char *szStart, char **argv, int *pi, int argc)
612 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
616 verifyShortOption(const char *opt)
618 if (strlen(opt) != 2)
620 werror (W_EXCESS_SHORT_OPTIONS, opt);
625 tryHandleUnsupportedOpt(char **argv, int *pi)
627 if (argv[*pi][0] == '-')
629 const char *longOpt = "";
633 if (argv[*pi][1] == '-')
640 shortOpt = argv[*pi][1];
642 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
644 if (unsupportedOptTable[i].shortOpt == shortOpt ||
645 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
646 // Found an unsupported opt.
648 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
649 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
653 // Didn't find in the table
658 // Not an option, so can't be unsupported :)
664 tryHandleSimpleOpt(char **argv, int *pi)
666 if (argv[*pi][0] == '-')
668 const char *longOpt = "";
672 if (argv[*pi][1] == '-')
679 shortOpt = argv[*pi][1];
682 for (i = 0; i < LENGTH(optionsTable); i++)
684 if (optionsTable[i].shortOpt == shortOpt ||
685 (longOpt && optionsTable[i].longOpt &&
686 strcmp(optionsTable[i].longOpt, longOpt) == 0))
689 // If it is a flag then we can handle it here
690 if (optionsTable[i].pparameter != NULL)
692 if (optionsTable[i].shortOpt == shortOpt)
694 verifyShortOption(argv[*pi]);
697 (*optionsTable[i].pparameter)++;
701 // Not a flag. Handled manually later.
706 // Didn't find in the table
711 // Not an option, so can't be handled.
716 /*-----------------------------------------------------------------*/
717 /* parseCmdLine - parses the command line and sets the options */
718 /*-----------------------------------------------------------------*/
720 parseCmdLine (int argc, char **argv)
724 /* go thru all whole command line */
725 for (i = 1; i < argc; i++)
730 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
735 if (tryHandleSimpleOpt(argv, &i) == TRUE)
741 if (argv[i][0] == '-' && argv[i][1] == '-')
743 if (strcmp (argv[i], OPTION_HELP) == 0)
749 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
751 options.stack10bit = 0;
755 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
761 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
763 _setModel (MODEL_LARGE, argv[i]);
767 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
769 _setModel (MODEL_MEDIUM, argv[i]);
773 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
775 _setModel (MODEL_SMALL, argv[i]);
779 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
781 _setModel (MODEL_FLAT24, argv[i]);
785 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
787 options.dump_rassgn =
793 options.dump_raw = 1;
797 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
799 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
803 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
805 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
809 if (strcmp (argv[i], OPTION_VERSION) == 0)
816 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
818 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
822 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
824 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
828 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
830 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
834 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
836 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
840 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
842 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
846 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
848 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
852 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
854 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
858 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
860 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
864 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
866 optimize.global_cse = 0;
870 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
872 optimize.loopInvariant = 0;
876 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
878 optimize.loopInduction = 0;
882 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
884 options.lessPedantic = 1;
885 setErrorLogLevel(ERROR_LEVEL_WARNING);
889 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
891 options.shortis8bits=1;
895 if (!port->parseOption (&argc, argv, &i))
897 werror (W_UNKNOWN_OPTION, argv[i]);
905 /* if preceded by '-' then option */
911 verifyShortOption(argv[i]);
918 /* Used to select the port */
919 _setPort (argv[i] + 2);
923 verifyShortOption(argv[i]);
929 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
933 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
938 if (argv[i][2] == 'l')
940 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
944 /* assembler options */
945 if (argv[i][2] == 'a')
947 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
951 werror (W_UNKNOWN_OPTION, argv[i]);
957 verifyShortOption(argv[i]);
963 /* preprocessor options */
967 addToList (preArgv, "-M");
972 addToList (preArgv, "-C");
981 char sOpt = argv[i][1];
984 if (argv[i][2] == ' ' || argv[i][2] == '\0')
990 werror(E_ARGUMENT_MISSING, argv[i-1]);
1004 sprintf (buffer, "-%c%s", sOpt, rest);
1005 addToList (preArgv, buffer);
1010 if (!port->parseOption (&argc, argv, &i))
1011 werror (W_UNKNOWN_OPTION, argv[i]);
1016 if (!port->parseOption (&argc, argv, &i))
1018 /* no option must be a filename */
1020 _processC1Arg (argv[i]);
1022 processFile (argv[i]);
1026 /* set up external stack location if not explicitly specified */
1027 if (!options.xstack_loc)
1028 options.xstack_loc = options.xdata_loc;
1030 /* if debug option is set the open the cdbFile */
1031 if (options.debug && srcFileName)
1033 sprintf (scratchFileName, "%s.cdb", srcFileName);
1034 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1035 werror (E_FILE_OPEN_ERR, scratchFileName);
1038 /* add a module record */
1039 fprintf (cdbFile, "M:%s\n", moduleName);
1045 /*-----------------------------------------------------------------*/
1046 /* linkEdit : - calls the linkage editor with options */
1047 /*-----------------------------------------------------------------*/
1049 linkEdit (char **envp)
1056 srcFileName = "temp";
1058 /* first we need to create the <filename>.lnk file */
1059 sprintf (scratchFileName, "%s.lnk", srcFileName);
1060 if (!(lnkfile = fopen (scratchFileName, "w")))
1062 werror (E_FILE_OPEN_ERR, scratchFileName);
1066 /* now write the options */
1067 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1069 /* if iram size specified */
1070 if (options.iram_size)
1071 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1074 fprintf (lnkfile, "-z\n");
1076 #define WRITE_SEG_LOC(N, L) \
1077 segName = Safe_strdup(N); \
1078 c = strtok(segName, " \t"); \
1079 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1080 if (segName) { Safe_free(segName); }
1082 /* code segment start */
1083 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1085 /* data segment start */
1086 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1089 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1092 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1094 /* bit segment start */
1095 WRITE_SEG_LOC (BIT_NAME, 0);
1097 /* add the extra linker options */
1098 for (i = 0; linkOptions[i]; i++)
1099 fprintf (lnkfile, "%s\n", linkOptions[i]);
1101 /* other library paths if specified */
1102 for (i = 0; i < nlibPaths; i++)
1103 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1105 /* standard library path */
1106 if (!options.nostdlib)
1109 if (TARGET_IS_DS390)
1116 switch (options.model)
1129 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1134 fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1136 /* standard library files */
1137 /* if (strcmp (port->target, "ds390") == 0) */
1138 if (options.model == MODEL_FLAT24)
1140 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1142 fprintf (lnkfile, "-l %s\n", STD_LIB);
1143 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1144 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1145 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1148 /* additional libraries if any */
1149 for (i = 0; i < nlibFiles; i++)
1150 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1152 /* put in the object files */
1153 if (strcmp (srcFileName, "temp"))
1154 fprintf (lnkfile, "%s ", srcFileName);
1156 for (i = 0; i < nrelFiles; i++)
1157 fprintf (lnkfile, "%s\n", relFiles[i]);
1159 fprintf (lnkfile, "\n-e\n");
1162 if (options.verbose)
1163 printf ("sdcc: Calling linker...\n");
1165 if (port->linker.cmd)
1167 char buffer2[PATH_MAX];
1168 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1169 buildCmdLine2 (buffer, buffer2);
1173 buildCmdLine2 (buffer, port->linker.mcmd);
1176 if (my_system (buffer))
1181 if (strcmp (srcFileName, "temp") == 0)
1183 /* rename "temp.cdb" to "firstRelFile.cdb" */
1184 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1185 f = strcat (f, ".cdb");
1186 rename ("temp.cdb", f);
1191 /*-----------------------------------------------------------------*/
1192 /* assemble - spawns the assembler with arguments */
1193 /*-----------------------------------------------------------------*/
1195 assemble (char **envp)
1197 if (port->assembler.cmd)
1199 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1200 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1205 buildCmdLine2 (buffer, port->assembler.mcmd);
1208 if (my_system (buffer))
1210 /* either system() or the assembler itself has reported an error
1211 perror ("Cannot exec assembler");
1217 /*-----------------------------------------------------------------*/
1218 /* preProcess - spawns the preprocessor with arguments */
1219 /*-----------------------------------------------------------------*/
1221 preProcess (char **envp)
1225 if (!options.c1mode)
1227 /* if using external stack define the macro */
1228 if (options.useXstack)
1229 addToList (preArgv, "-DSDCC_USE_XSTACK");
1231 /* set the macro for stack autos */
1232 if (options.stackAuto)
1233 addToList (preArgv, "-DSDCC_STACK_AUTO");
1235 /* set the macro for stack autos */
1236 if (options.stack10bit)
1237 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1239 /* set the macro for no overlay */
1240 if (options.noOverlay)
1241 addToList (preArgv, "-DSDCC_NOOVERLAY");
1243 /* set the macro for large model */
1244 switch (options.model)
1247 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1250 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1253 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1256 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1259 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1262 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1266 /* add port (processor information to processor */
1267 addToList (preArgv, "-DSDCC_{port}");
1268 addToList (preArgv, "-D__{port}");
1270 /* standard include path */
1271 if (!options.nostdinc) {
1272 addToList (preArgv, "-I{includedir}");
1275 setMainValue ("cppextraopts", join(preArgv));
1278 preOutName = Safe_strdup (tempfilename ());
1280 /* Have to set cppoutfilename to something, even if just pre-processing. */
1281 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1283 if (options.verbose)
1284 printf ("sdcc: Calling preprocessor...\n");
1286 buildCmdLine2 (buffer, _preCmd);
1288 if (my_system (buffer))
1290 // @FIX: Dario Vecchio 03-05-2001
1293 unlink (preOutName);
1294 Safe_free (preOutName);
1307 preOutName = fullSrcFileName;
1310 yyin = fopen (preOutName, "r");
1313 perror ("Preproc file not found\n");
1321 _setPaths (const char *pprefix)
1324 Given the prefix and how the directories were layed out at
1325 configure time, see if the library and include directories are
1326 where expected. If so, set.
1328 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1329 strcpy (scratchFileName, pprefix);
1330 strcat (scratchFileName, buffer);
1332 if (pathExists (scratchFileName))
1334 setMainValue ("includedir", scratchFileName);
1341 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1342 strcpy (scratchFileName, pprefix);
1343 strcat (scratchFileName, buffer);
1345 if (pathExists (scratchFileName))
1347 setMainValue ("libdir", scratchFileName);
1358 _discoverPaths (const char *argv0)
1361 1. Try the SDCCDIR environment variable.
1362 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1363 and library paths with respect to that. Note that under win32
1364 argv[0] is always the full path to the program.
1365 3. If (1) and (2) fail, fall back to the compile time defaults.
1367 Detecting assumes the same layout as when configured. If the
1368 directories have been further moved about then discovery will
1372 /* Some input cases:
1373 "c:\fish\sdcc\bin\sdcc"
1375 "/home/fish/bin/sdcc"
1377 Note that ./sdcc is explicitly not supported as there isn't
1380 /* bindir is handled differently to the lib and include directories.
1381 It's rather unfortunate, but required due to the different
1382 install and development layouts. Logic is different as well.
1385 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1387 strcpy (scratchFileName, argv0);
1388 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1389 setMainValue ("bindir", scratchFileName);
1390 ExePathList[0] = Safe_strdup (scratchFileName);
1392 else if (getenv (SDCCDIR_NAME) != NULL)
1394 getPathDifference (buffer, PREFIX, BINDIR);
1395 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1396 strcat (scratchFileName, buffer);
1397 setMainValue ("bindir", scratchFileName);
1398 ExePathList[0] = Safe_strdup (scratchFileName);
1402 setMainValue ("bindir", BINDIR);
1403 ExePathList[0] = BINDIR;
1409 if (getenv (SDCCDIR_NAME) != NULL)
1411 if (_setPaths (getenv (SDCCDIR_NAME)))
1413 /* Successfully set. */
1418 /* Include and lib weren't where expected. */
1422 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1424 char *pbase = getPrefixFromBinPath (argv0);
1428 /* A bad path. Skip. */
1432 if (_setPaths (pbase))
1434 /* Successfully set. */
1439 /* Include and lib weren't where expected. */
1444 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1445 setMainValue ("libdir", SDCC_LIB_DIR);
1452 populateMainValues (_baseValues);
1453 setMainValue ("port", port->target);
1454 setMainValue ("objext", port->linker.rel_ext);
1455 setMainValue ("asmext", port->assembler.file_ext);
1457 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1458 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1463 * initialises and calls the parser
1467 main (int argc, char **argv, char **envp)
1469 /* turn all optimizations off by default */
1470 memset (&optimize, 0, sizeof (struct optimize));
1472 /*printVersionInfo (); */
1475 fprintf (stderr, "Build error: no ports are enabled.\n");
1479 _findPort (argc, argv);
1481 if (strcmp(port->target, "mcs51") == 0) {
1482 printf("DS390 jammed in A\n");
1487 /* Initalise the port. */
1491 // Create a default exe search path from the path to the sdcc command
1494 setDefaultOptions ();
1497 options.model = MODEL_SMALL;
1498 options.stack10bit=0;
1501 parseCmdLine (argc, argv);
1503 /* if no input then printUsage & exit */
1504 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1505 (options.c1mode && !srcFileName && !options.out_name))
1512 _discoverPaths (argv[0]);
1520 port->finaliseOptions ();
1527 if (options.verbose)
1528 printf ("sdcc: Generating code...\n");
1534 if (TARGET_IS_PIC) {
1535 /* TSD PIC port hack - if the PIC port option is enabled
1536 and SDCC is used to generate PIC code, then we will
1537 generate .asm files in gpasm's format instead of SDCC's
1540 #if !OPT_DISABLE_PIC
1549 // @FIX: Dario Vecchio 03-05-2001
1552 if (yyin && yyin != stdin)
1554 unlink (preOutName);
1555 Safe_free (preOutName);
1560 if (!options.c1mode && !noAssemble)
1562 if (options.verbose)
1563 printf ("sdcc: Calling assembler...\n");
1569 // @FIX: Dario Vecchio 03-05-2001
1572 if (yyin && yyin != stdin)
1574 unlink (preOutName);
1575 Safe_free (preOutName);
1578 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1591 if (preOutName && !options.c1mode)
1593 unlink (preOutName);
1594 Safe_free (preOutName);
1597 if (!options.cc_only &&
1601 (srcFileName || nrelFiles))
1603 if (port->linker.do_link)
1604 port->linker.do_link ();
1609 if (yyin && yyin != stdin)