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 pre-processor (p), 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, "dump front-end AST before generating iCode" },
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." },
209 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
210 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
211 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"}
214 /** Table of all unsupported options and help text to display when one
218 /** shortOpt as in OPTIONS. */
220 /** longOpt as in OPTIONS. */
222 /** Message to display inside W_UNSUPPORTED_OPT when this option
227 static const UNSUPPORTEDOPT
228 unsupportedOptTable[] = {
229 { 'a', NULL, "use --stack-auto instead." },
230 { 'g', NULL, "use --generic instead" },
231 { 'X', NULL, "use --xstack-loc instead" },
232 { 'x', NULL, "use --xstack instead" },
233 { 'p', NULL, "use --stack-loc instead" },
234 { 'P', NULL, "use --stack-loc instead" },
235 { 'i', NULL, "use --idata-loc instead" },
236 { 'r', NULL, "use --xdata-loc instead" },
237 { 's', NULL, "use --code-loc instead" },
238 { 'Y', NULL, "use -I instead" }
241 /** List of all default constant macros.
243 static const char *_baseValues[] = {
244 "cpp", "{bindir}{sep}sdcpp",
246 /* Path seperator character */
247 "sep", DIR_SEPARATOR_STRING,
251 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
255 static PORT *_ports[] =
257 #if !OPT_DISABLE_MCS51
260 #if !OPT_DISABLE_GBZ80
269 #if !OPT_DISABLE_DS390
275 #if !OPT_DISABLE_I186
278 #if !OPT_DISABLE_TLCS900H
281 #if !OPT_DISABLE_TININative
286 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
289 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
291 extern void picglue ();
293 /** Sets the port to the one given by the command line option.
294 @param The name minus the option (eg 'mcs51')
295 @return 0 on success.
298 _setPort (const char *name)
301 for (i = 0; i < NUM_PORTS; i++)
303 if (!strcmp (_ports[i]->target, name))
309 /* Error - didnt find */
310 werror (E_UNKNOWN_TARGET, name);
315 _validatePorts (void)
318 for (i = 0; i < NUM_PORTS; i++)
320 if (_ports[i]->magic != PORT_MAGIC)
322 wassertl (0, "Port definition structure is incomplete");
328 _findPort (int argc, char **argv)
334 if (!strncmp (*argv, "-m", 2))
336 _setPort (*argv + 2);
341 /* Use the first in the list */
345 /*-----------------------------------------------------------------*/
346 /* printVersionInfo - prints the version info */
347 /*-----------------------------------------------------------------*/
355 for (i = 0; i < NUM_PORTS; i++)
356 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
358 fprintf (stderr, " %s"
359 #ifdef SDCC_SUB_VERSION_STR
360 "/" SDCC_SUB_VERSION_STR
369 #if defined(_MSC_VER)
381 /*-----------------------------------------------------------------*/
382 /* printUsage - prints command line syntax */
383 /*-----------------------------------------------------------------*/
390 "Usage : sdcc [options] filename\n"
394 for (i = 0; i < LENGTH(optionsTable); i++) {
395 fprintf(stdout, " %c%c %-20s %s\n",
396 optionsTable[i].shortOpt !=0 ? '-' : ' ',
397 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
398 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
399 optionsTable[i].help != NULL ? optionsTable[i].help : ""
405 /*-----------------------------------------------------------------*/
406 /* parseWithComma - separates string with comma */
407 /*-----------------------------------------------------------------*/
409 parseWithComma (char **dest, char *src)
413 strtok (src, "\r\n \t");
414 /* skip the initial white spaces */
415 while (isspace (*src))
432 /*-----------------------------------------------------------------*/
433 /* setDefaultOptions - sets the default options */
434 /*-----------------------------------------------------------------*/
440 for (i = 0; i < 128; i++)
441 preArgv[i] = asmOptions[i] =
442 linkOptions[i] = relFiles[i] = libFiles[i] =
445 /* first the options part */
446 options.stack_loc = 0; /* stack pointer initialised to 0 */
447 options.xstack_loc = 0; /* xternal stack starts at 0 */
448 options.code_loc = 0; /* code starts at 0 */
449 options.data_loc = 0x0030; /* data starts at 0x0030 */
450 options.xdata_loc = 0;
451 options.idata_loc = 0x80;
452 options.genericPtr = 1; /* default on */
454 options.model = port->general.default_model;
455 options.nostdlib = 0;
456 options.nostdinc = 0;
458 options.shortis8bits = 0;
460 options.stack10bit=0;
462 /* now for the optimizations */
463 /* turn on the everything */
464 optimize.global_cse = 1;
469 optimize.loopInvariant = 1;
470 optimize.loopInduction = 1;
472 /* now for the ports */
473 port->setDefaultOptions ();
476 /*-----------------------------------------------------------------*/
477 /* processFile - determines the type of file from the extension */
478 /*-----------------------------------------------------------------*/
480 processFile (char *s)
484 /* get the file extension */
485 fext = s + strlen (s);
486 while ((fext != s) && *fext != '.')
489 /* now if no '.' then we don't know what the file type is
490 so give a warning and return */
493 werror (W_UNKNOWN_FEXT, s);
497 /* otherwise depending on the file type */
498 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
500 /* source file name : not if we already have a
504 werror (W_TOO_MANY_SRC, s);
508 /* the only source file */
509 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
511 werror (E_FILE_OPEN_ERR, s);
515 /* copy the file name into the buffer */
518 /* get rid of the "." */
519 strtok (buffer, ".");
520 srcFileName = Safe_alloc ( strlen (buffer) + 1);
521 strcpy (srcFileName, buffer);
523 /* get rid of any path information
524 for the module name; do this by going
525 backwards till we get to either '/' or '\' or ':'
526 or start of buffer */
527 fext = buffer + strlen (buffer);
528 while (fext != buffer &&
529 *(fext - 1) != '\\' &&
530 *(fext - 1) != '/' &&
533 moduleName = Safe_alloc ( strlen (fext) + 1);
534 strcpy (moduleName, fext);
539 /* if the extention is type .rel or .r or .REL or .R
540 addtional object file will be passed to the linker */
541 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
542 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
543 strcmp (fext, port->linker.rel_ext) == 0)
545 relFiles[nrelFiles++] = s;
549 /* if .lib or .LIB */
550 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
552 libFiles[nlibFiles++] = s;
556 werror (W_UNKNOWN_FEXT, s);
561 _processC1Arg (char *s)
565 if (options.out_name)
567 werror (W_TOO_MANY_SRC, s);
570 options.out_name = Safe_strdup (s);
579 _setModel (int model, const char *sz)
581 if (port->general.supported_models & model)
582 options.model = model;
584 werror (W_UNSUPPORTED_MODEL, sz, port->target);
587 /** Gets the string argument to this option. If the option is '--opt'
588 then for input of '--optxyz' or '--opt xyz' returns xyz.
591 getStringArg(const char *szStart, char **argv, int *pi, int argc)
593 if (argv[*pi][strlen(szStart)])
595 return &argv[*pi][strlen(szStart)];
602 werror (E_ARGUMENT_MISSING, szStart);
603 /* Die here rather than checking for errors later. */
613 /** Gets the integer argument to this option using the same rules as
617 getIntArg(const char *szStart, char **argv, int *pi, int argc)
619 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
623 verifyShortOption(const char *opt)
625 if (strlen(opt) != 2)
627 werror (W_EXCESS_SHORT_OPTIONS, opt);
632 tryHandleUnsupportedOpt(char **argv, int *pi)
634 if (argv[*pi][0] == '-')
636 const char *longOpt = "";
640 if (argv[*pi][1] == '-')
647 shortOpt = argv[*pi][1];
649 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
651 if (unsupportedOptTable[i].shortOpt == shortOpt ||
652 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
653 // Found an unsupported opt.
655 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
656 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
660 // Didn't find in the table
665 // Not an option, so can't be unsupported :)
671 tryHandleSimpleOpt(char **argv, int *pi)
673 if (argv[*pi][0] == '-')
675 const char *longOpt = "";
679 if (argv[*pi][1] == '-')
686 shortOpt = argv[*pi][1];
689 for (i = 0; i < LENGTH(optionsTable); i++)
691 if (optionsTable[i].shortOpt == shortOpt ||
692 (longOpt && optionsTable[i].longOpt &&
693 strcmp(optionsTable[i].longOpt, longOpt) == 0))
696 // If it is a flag then we can handle it here
697 if (optionsTable[i].pparameter != NULL)
699 if (optionsTable[i].shortOpt == shortOpt)
701 verifyShortOption(argv[*pi]);
704 (*optionsTable[i].pparameter)++;
708 // Not a flag. Handled manually later.
713 // Didn't find in the table
718 // Not an option, so can't be handled.
723 /*-----------------------------------------------------------------*/
724 /* parseCmdLine - parses the command line and sets the options */
725 /*-----------------------------------------------------------------*/
727 parseCmdLine (int argc, char **argv)
731 /* go thru all whole command line */
732 for (i = 1; i < argc; i++)
737 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
742 if (tryHandleSimpleOpt(argv, &i) == TRUE)
748 if (argv[i][0] == '-' && argv[i][1] == '-')
750 if (strcmp (argv[i], OPTION_HELP) == 0)
756 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
758 options.stack10bit = 0;
762 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
768 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
770 _setModel (MODEL_LARGE, argv[i]);
774 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
776 _setModel (MODEL_MEDIUM, argv[i]);
780 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
782 _setModel (MODEL_SMALL, argv[i]);
786 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
788 _setModel (MODEL_FLAT24, argv[i]);
792 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
794 options.dump_rassgn =
800 options.dump_raw = 1;
804 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
806 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
810 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
812 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
816 if (strcmp (argv[i], OPTION_VERSION) == 0)
823 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
825 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
829 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
831 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
835 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
837 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
841 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
843 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
847 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
849 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
853 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
855 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
859 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
861 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
865 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
867 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
871 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
873 optimize.global_cse = 0;
877 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
879 optimize.loopInvariant = 0;
883 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
885 optimize.loopInduction = 0;
889 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
891 options.lessPedantic = 1;
892 setErrorLogLevel(ERROR_LEVEL_WARNING);
896 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
898 options.shortis8bits=1;
902 if (!port->parseOption (&argc, argv, &i))
904 werror (W_UNKNOWN_OPTION, argv[i]);
912 /* if preceded by '-' then option */
918 verifyShortOption(argv[i]);
925 /* Used to select the port */
926 _setPort (argv[i] + 2);
930 verifyShortOption(argv[i]);
936 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
940 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
944 /* pre-processer options */
945 if (argv[i][2] == 'p')
947 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
950 else if (argv[i][2] == 'l')
952 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
954 /* assembler options */
955 else if (argv[i][2] == 'a')
957 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
961 werror (W_UNKNOWN_OPTION, argv[i]);
966 verifyShortOption(argv[i]);
972 /* preprocessor options */
976 addToList (preArgv, "-M");
981 addToList (preArgv, "-C");
990 char sOpt = argv[i][1];
993 if (argv[i][2] == ' ' || argv[i][2] == '\0')
999 werror(E_ARGUMENT_MISSING, argv[i-1]);
1013 sprintf (buffer, "-%c%s", sOpt, rest);
1014 addToList (preArgv, buffer);
1019 if (!port->parseOption (&argc, argv, &i))
1020 werror (W_UNKNOWN_OPTION, argv[i]);
1025 if (!port->parseOption (&argc, argv, &i))
1027 /* no option must be a filename */
1029 _processC1Arg (argv[i]);
1031 processFile (argv[i]);
1035 /* set up external stack location if not explicitly specified */
1036 if (!options.xstack_loc)
1037 options.xstack_loc = options.xdata_loc;
1039 /* if debug option is set the open the cdbFile */
1040 if (options.debug && srcFileName)
1042 sprintf (scratchFileName, "%s.cdb", srcFileName);
1043 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1044 werror (E_FILE_OPEN_ERR, scratchFileName);
1047 /* add a module record */
1048 fprintf (cdbFile, "M:%s\n", moduleName);
1054 /*-----------------------------------------------------------------*/
1055 /* linkEdit : - calls the linkage editor with options */
1056 /*-----------------------------------------------------------------*/
1058 linkEdit (char **envp)
1065 srcFileName = "temp";
1067 /* first we need to create the <filename>.lnk file */
1068 sprintf (scratchFileName, "%s.lnk", srcFileName);
1069 if (!(lnkfile = fopen (scratchFileName, "w")))
1071 werror (E_FILE_OPEN_ERR, scratchFileName);
1075 /* now write the options */
1076 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1078 /* if iram size specified */
1079 if (options.iram_size)
1080 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1083 fprintf (lnkfile, "-z\n");
1085 #define WRITE_SEG_LOC(N, L) \
1086 segName = Safe_strdup(N); \
1087 c = strtok(segName, " \t"); \
1088 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1089 if (segName) { Safe_free(segName); }
1091 /* code segment start */
1092 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1094 /* data segment start */
1095 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1098 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1101 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1103 /* bit segment start */
1104 WRITE_SEG_LOC (BIT_NAME, 0);
1106 /* add the extra linker options */
1107 for (i = 0; linkOptions[i]; i++)
1108 fprintf (lnkfile, "%s\n", linkOptions[i]);
1110 /* other library paths if specified */
1111 for (i = 0; i < nlibPaths; i++)
1112 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1114 /* standard library path */
1115 if (!options.nostdlib)
1118 if (TARGET_IS_DS390)
1125 switch (options.model)
1138 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1143 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1145 /* standard library files */
1146 /* if (strcmp (port->target, "ds390") == 0) */
1147 if (options.model == MODEL_FLAT24)
1149 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1151 fprintf (lnkfile, "-l %s\n", STD_LIB);
1152 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1153 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1154 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1157 /* additional libraries if any */
1158 for (i = 0; i < nlibFiles; i++)
1159 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1161 /* put in the object files */
1162 if (strcmp (srcFileName, "temp"))
1163 fprintf (lnkfile, "%s ", srcFileName);
1165 for (i = 0; i < nrelFiles; i++)
1166 fprintf (lnkfile, "%s\n", relFiles[i]);
1168 fprintf (lnkfile, "\n-e\n");
1171 if (options.verbose)
1172 printf ("sdcc: Calling linker...\n");
1174 if (port->linker.cmd)
1176 char buffer2[PATH_MAX];
1177 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1178 buildCmdLine2 (buffer, buffer2);
1182 buildCmdLine2 (buffer, port->linker.mcmd);
1185 if (my_system (buffer))
1190 if (strcmp (srcFileName, "temp") == 0)
1192 /* rename "temp.cdb" to "firstRelFile.cdb" */
1193 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1194 f = strcat (f, ".cdb");
1195 rename ("temp.cdb", f);
1200 /*-----------------------------------------------------------------*/
1201 /* assemble - spawns the assembler with arguments */
1202 /*-----------------------------------------------------------------*/
1204 assemble (char **envp)
1206 if (port->assembler.cmd)
1208 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1209 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1214 buildCmdLine2 (buffer, port->assembler.mcmd);
1217 if (my_system (buffer))
1219 /* either system() or the assembler itself has reported an error
1220 perror ("Cannot exec assembler");
1226 /*-----------------------------------------------------------------*/
1227 /* preProcess - spawns the preprocessor with arguments */
1228 /*-----------------------------------------------------------------*/
1230 preProcess (char **envp)
1234 if (!options.c1mode)
1236 /* if using external stack define the macro */
1237 if (options.useXstack)
1238 addToList (preArgv, "-DSDCC_USE_XSTACK");
1240 /* set the macro for stack autos */
1241 if (options.stackAuto)
1242 addToList (preArgv, "-DSDCC_STACK_AUTO");
1244 /* set the macro for stack autos */
1245 if (options.stack10bit)
1246 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1248 /* set the macro for no overlay */
1249 if (options.noOverlay)
1250 addToList (preArgv, "-DSDCC_NOOVERLAY");
1252 /* set the macro for large model */
1253 switch (options.model)
1256 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1259 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1262 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1265 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1268 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1271 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1275 /* add port (processor information to processor */
1276 addToList (preArgv, "-DSDCC_{port}");
1277 addToList (preArgv, "-D__{port}");
1279 /* standard include path */
1280 if (!options.nostdinc) {
1281 addToList (preArgv, "-I{includedir}");
1284 setMainValue ("cppextraopts", join(preArgv));
1287 preOutName = Safe_strdup (tempfilename ());
1289 /* Have to set cppoutfilename to something, even if just pre-processing. */
1290 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1292 if (options.verbose)
1293 printf ("sdcc: Calling preprocessor...\n");
1295 buildCmdLine2 (buffer, _preCmd);
1297 if (my_system (buffer))
1299 // @FIX: Dario Vecchio 03-05-2001
1302 unlink (preOutName);
1303 Safe_free (preOutName);
1316 preOutName = fullSrcFileName;
1319 yyin = fopen (preOutName, "r");
1322 perror ("Preproc file not found\n");
1330 _setPaths (const char *pprefix)
1333 Given the prefix and how the directories were layed out at
1334 configure time, see if the library and include directories are
1335 where expected. If so, set.
1337 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1338 strcpy (scratchFileName, pprefix);
1339 strcat (scratchFileName, buffer);
1341 if (pathExists (scratchFileName))
1343 setMainValue ("includedir", scratchFileName);
1350 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1351 strcpy (scratchFileName, pprefix);
1352 strcat (scratchFileName, buffer);
1354 if (pathExists (scratchFileName))
1356 setMainValue ("libdir", scratchFileName);
1367 _discoverPaths (const char *argv0)
1370 1. Try the SDCCDIR environment variable.
1371 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1372 and library paths with respect to that. Note that under win32
1373 argv[0] is always the full path to the program.
1374 3. If (1) and (2) fail, fall back to the compile time defaults.
1376 Detecting assumes the same layout as when configured. If the
1377 directories have been further moved about then discovery will
1381 /* Some input cases:
1382 "c:\fish\sdcc\bin\sdcc"
1384 "/home/fish/bin/sdcc"
1386 Note that ./sdcc is explicitly not supported as there isn't
1389 /* bindir is handled differently to the lib and include directories.
1390 It's rather unfortunate, but required due to the different
1391 install and development layouts. Logic is different as well.
1394 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1396 strcpy (scratchFileName, argv0);
1397 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1398 setMainValue ("bindir", scratchFileName);
1399 ExePathList[0] = Safe_strdup (scratchFileName);
1401 else if (getenv (SDCCDIR_NAME) != NULL)
1403 getPathDifference (buffer, PREFIX, BINDIR);
1404 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1405 strcat (scratchFileName, buffer);
1406 setMainValue ("bindir", scratchFileName);
1407 ExePathList[0] = Safe_strdup (scratchFileName);
1411 setMainValue ("bindir", BINDIR);
1412 ExePathList[0] = BINDIR;
1418 if (getenv (SDCCDIR_NAME) != NULL)
1420 if (_setPaths (getenv (SDCCDIR_NAME)))
1422 /* Successfully set. */
1427 /* Include and lib weren't where expected. */
1431 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1433 char *pbase = getPrefixFromBinPath (argv0);
1437 /* A bad path. Skip. */
1441 if (_setPaths (pbase))
1443 /* Successfully set. */
1448 /* Include and lib weren't where expected. */
1453 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1454 setMainValue ("libdir", SDCC_LIB_DIR);
1461 populateMainValues (_baseValues);
1462 setMainValue ("port", port->target);
1463 setMainValue ("objext", port->linker.rel_ext);
1464 setMainValue ("asmext", port->assembler.file_ext);
1466 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1467 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1472 * initialises and calls the parser
1476 main (int argc, char **argv, char **envp)
1478 /* turn all optimizations off by default */
1479 memset (&optimize, 0, sizeof (struct optimize));
1481 /*printVersionInfo (); */
1484 fprintf (stderr, "Build error: no ports are enabled.\n");
1488 _findPort (argc, argv);
1490 if (strcmp(port->target, "mcs51") == 0) {
1491 printf("DS390 jammed in A\n");
1496 /* Initalise the port. */
1500 // Create a default exe search path from the path to the sdcc command
1503 setDefaultOptions ();
1506 options.model = MODEL_SMALL;
1507 options.stack10bit=0;
1510 parseCmdLine (argc, argv);
1512 /* if no input then printUsage & exit */
1513 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1514 (options.c1mode && !srcFileName && !options.out_name))
1521 _discoverPaths (argv[0]);
1529 port->finaliseOptions ();
1537 if (options.verbose)
1538 printf ("sdcc: Generating code...\n");
1544 if (TARGET_IS_PIC) {
1545 /* TSD PIC port hack - if the PIC port option is enabled
1546 and SDCC is used to generate PIC code, then we will
1547 generate .asm files in gpasm's format instead of SDCC's
1550 #if !OPT_DISABLE_PIC
1559 // @FIX: Dario Vecchio 03-05-2001
1562 if (yyin && yyin != stdin)
1564 unlink (preOutName);
1565 Safe_free (preOutName);
1570 if (!options.c1mode && !noAssemble)
1572 if (options.verbose)
1573 printf ("sdcc: Calling assembler...\n");
1579 // @FIX: Dario Vecchio 03-05-2001
1582 if (yyin && yyin != stdin)
1584 unlink (preOutName);
1585 Safe_free (preOutName);
1588 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1601 if (preOutName && !options.c1mode)
1603 unlink (preOutName);
1604 Safe_free (preOutName);
1607 if (!options.cc_only &&
1611 (srcFileName || nrelFiles))
1613 if (port->linker.do_link)
1614 port->linker.do_link ();
1619 if (yyin && yyin != stdin)