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
283 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
286 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
288 extern void picglue ();
290 /** Sets the port to the one given by the command line option.
291 @param The name minus the option (eg 'mcs51')
292 @return 0 on success.
295 _setPort (const char *name)
298 for (i = 0; i < NUM_PORTS; i++)
300 if (!strcmp (_ports[i]->target, name))
306 /* Error - didnt find */
307 werror (E_UNKNOWN_TARGET, name);
312 _validatePorts (void)
315 for (i = 0; i < NUM_PORTS; i++)
317 if (_ports[i]->magic != PORT_MAGIC)
319 wassertl (0, "Port definition structure is incomplete");
325 _findPort (int argc, char **argv)
331 if (!strncmp (*argv, "-m", 2))
333 _setPort (*argv + 2);
338 /* Use the first in the list */
342 /*-----------------------------------------------------------------*/
343 /* printVersionInfo - prints the version info */
344 /*-----------------------------------------------------------------*/
352 for (i = 0; i < NUM_PORTS; i++)
353 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
355 fprintf (stderr, " %s"
356 #ifdef SDCC_SUB_VERSION_STR
357 "/" SDCC_SUB_VERSION_STR
366 #if defined(_MSC_VER)
378 /*-----------------------------------------------------------------*/
379 /* printUsage - prints command line syntax */
380 /*-----------------------------------------------------------------*/
387 "Usage : sdcc [options] filename\n"
391 for (i = 0; i < LENGTH(optionsTable); i++) {
392 fprintf(stdout, " %c%c %-20s %s\n",
393 optionsTable[i].shortOpt !=0 ? '-' : ' ',
394 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
395 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
396 optionsTable[i].help != NULL ? optionsTable[i].help : ""
402 /*-----------------------------------------------------------------*/
403 /* parseWithComma - separates string with comma */
404 /*-----------------------------------------------------------------*/
406 parseWithComma (char **dest, char *src)
410 strtok (src, "\r\n \t");
411 /* skip the initial white spaces */
412 while (isspace (*src))
429 /*-----------------------------------------------------------------*/
430 /* setDefaultOptions - sets the default options */
431 /*-----------------------------------------------------------------*/
437 for (i = 0; i < 128; i++)
438 preArgv[i] = asmOptions[i] =
439 linkOptions[i] = relFiles[i] = libFiles[i] =
442 /* first the options part */
443 options.stack_loc = 0; /* stack pointer initialised to 0 */
444 options.xstack_loc = 0; /* xternal stack starts at 0 */
445 options.code_loc = 0; /* code starts at 0 */
446 options.data_loc = 0x0030; /* data starts at 0x0030 */
447 options.xdata_loc = 0;
448 options.idata_loc = 0x80;
449 options.genericPtr = 1; /* default on */
451 options.model = port->general.default_model;
452 options.nostdlib = 0;
453 options.nostdinc = 0;
455 options.shortis8bits = 0;
457 options.stack10bit=0;
459 /* now for the optimizations */
460 /* turn on the everything */
461 optimize.global_cse = 1;
466 optimize.loopInvariant = 1;
467 optimize.loopInduction = 1;
469 /* now for the ports */
470 port->setDefaultOptions ();
473 /*-----------------------------------------------------------------*/
474 /* processFile - determines the type of file from the extension */
475 /*-----------------------------------------------------------------*/
477 processFile (char *s)
481 /* get the file extension */
482 fext = s + strlen (s);
483 while ((fext != s) && *fext != '.')
486 /* now if no '.' then we don't know what the file type is
487 so give a warning and return */
490 werror (W_UNKNOWN_FEXT, s);
494 /* otherwise depending on the file type */
495 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
497 /* source file name : not if we already have a
501 werror (W_TOO_MANY_SRC, s);
505 /* the only source file */
506 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
508 werror (E_FILE_OPEN_ERR, s);
512 /* copy the file name into the buffer */
515 /* get rid of the "." */
516 strtok (buffer, ".");
517 srcFileName = Safe_alloc ( strlen (buffer) + 1);
518 strcpy (srcFileName, buffer);
520 /* get rid of any path information
521 for the module name; do this by going
522 backwards till we get to either '/' or '\' or ':'
523 or start of buffer */
524 fext = buffer + strlen (buffer);
525 while (fext != buffer &&
526 *(fext - 1) != '\\' &&
527 *(fext - 1) != '/' &&
530 moduleName = Safe_alloc ( strlen (fext) + 1);
531 strcpy (moduleName, fext);
536 /* if the extention is type .rel or .r or .REL or .R
537 addtional object file will be passed to the linker */
538 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
539 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
540 strcmp (fext, port->linker.rel_ext) == 0)
542 relFiles[nrelFiles++] = s;
546 /* if .lib or .LIB */
547 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
549 libFiles[nlibFiles++] = s;
553 werror (W_UNKNOWN_FEXT, s);
558 _processC1Arg (char *s)
562 if (options.out_name)
564 werror (W_TOO_MANY_SRC, s);
567 options.out_name = Safe_strdup (s);
576 _setModel (int model, const char *sz)
578 if (port->general.supported_models & model)
579 options.model = model;
581 werror (W_UNSUPPORTED_MODEL, sz, port->target);
584 /** Gets the string argument to this option. If the option is '--opt'
585 then for input of '--optxyz' or '--opt xyz' returns xyz.
588 getStringArg(const char *szStart, char **argv, int *pi, int argc)
590 if (argv[*pi][strlen(szStart)])
592 return &argv[*pi][strlen(szStart)];
599 werror (E_ARGUMENT_MISSING, szStart);
600 /* Die here rather than checking for errors later. */
610 /** Gets the integer argument to this option using the same rules as
614 getIntArg(const char *szStart, char **argv, int *pi, int argc)
616 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
620 verifyShortOption(const char *opt)
622 if (strlen(opt) != 2)
624 werror (W_EXCESS_SHORT_OPTIONS, opt);
629 tryHandleUnsupportedOpt(char **argv, int *pi)
631 if (argv[*pi][0] == '-')
633 const char *longOpt = "";
637 if (argv[*pi][1] == '-')
644 shortOpt = argv[*pi][1];
646 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
648 if (unsupportedOptTable[i].shortOpt == shortOpt ||
649 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
650 // Found an unsupported opt.
652 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
653 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
657 // Didn't find in the table
662 // Not an option, so can't be unsupported :)
668 tryHandleSimpleOpt(char **argv, int *pi)
670 if (argv[*pi][0] == '-')
672 const char *longOpt = "";
676 if (argv[*pi][1] == '-')
683 shortOpt = argv[*pi][1];
686 for (i = 0; i < LENGTH(optionsTable); i++)
688 if (optionsTable[i].shortOpt == shortOpt ||
689 (longOpt && optionsTable[i].longOpt &&
690 strcmp(optionsTable[i].longOpt, longOpt) == 0))
693 // If it is a flag then we can handle it here
694 if (optionsTable[i].pparameter != NULL)
696 if (optionsTable[i].shortOpt == shortOpt)
698 verifyShortOption(argv[*pi]);
701 (*optionsTable[i].pparameter)++;
705 // Not a flag. Handled manually later.
710 // Didn't find in the table
715 // Not an option, so can't be handled.
720 /*-----------------------------------------------------------------*/
721 /* parseCmdLine - parses the command line and sets the options */
722 /*-----------------------------------------------------------------*/
724 parseCmdLine (int argc, char **argv)
728 /* go thru all whole command line */
729 for (i = 1; i < argc; i++)
734 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
739 if (tryHandleSimpleOpt(argv, &i) == TRUE)
745 if (argv[i][0] == '-' && argv[i][1] == '-')
747 if (strcmp (argv[i], OPTION_HELP) == 0)
753 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
755 options.stack10bit = 0;
759 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
765 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
767 _setModel (MODEL_LARGE, argv[i]);
771 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
773 _setModel (MODEL_MEDIUM, argv[i]);
777 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
779 _setModel (MODEL_SMALL, argv[i]);
783 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
785 _setModel (MODEL_FLAT24, argv[i]);
789 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
791 options.dump_rassgn =
797 options.dump_raw = 1;
801 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
803 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
807 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
809 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
813 if (strcmp (argv[i], OPTION_VERSION) == 0)
820 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
822 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
826 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
828 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
832 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
834 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
838 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
840 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
844 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
846 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
850 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
852 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
856 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
858 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
862 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
864 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
868 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
870 optimize.global_cse = 0;
874 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
876 optimize.loopInvariant = 0;
880 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
882 optimize.loopInduction = 0;
886 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
888 options.lessPedantic = 1;
889 setErrorLogLevel(ERROR_LEVEL_WARNING);
893 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
895 options.shortis8bits=1;
899 if (!port->parseOption (&argc, argv, &i))
901 werror (W_UNKNOWN_OPTION, argv[i]);
909 /* if preceded by '-' then option */
915 verifyShortOption(argv[i]);
922 /* Used to select the port */
923 _setPort (argv[i] + 2);
927 verifyShortOption(argv[i]);
933 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
937 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
941 /* pre-processer options */
942 if (argv[i][2] == 'p')
944 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
947 else if (argv[i][2] == 'l')
949 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
951 /* assembler options */
952 else if (argv[i][2] == 'a')
954 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
958 werror (W_UNKNOWN_OPTION, argv[i]);
963 verifyShortOption(argv[i]);
969 /* preprocessor options */
973 addToList (preArgv, "-M");
978 addToList (preArgv, "-C");
987 char sOpt = argv[i][1];
990 if (argv[i][2] == ' ' || argv[i][2] == '\0')
996 werror(E_ARGUMENT_MISSING, argv[i-1]);
1010 sprintf (buffer, "-%c%s", sOpt, rest);
1011 addToList (preArgv, buffer);
1016 if (!port->parseOption (&argc, argv, &i))
1017 werror (W_UNKNOWN_OPTION, argv[i]);
1022 if (!port->parseOption (&argc, argv, &i))
1024 /* no option must be a filename */
1026 _processC1Arg (argv[i]);
1028 processFile (argv[i]);
1032 /* set up external stack location if not explicitly specified */
1033 if (!options.xstack_loc)
1034 options.xstack_loc = options.xdata_loc;
1036 /* if debug option is set the open the cdbFile */
1037 if (options.debug && srcFileName)
1039 sprintf (scratchFileName, "%s.cdb", srcFileName);
1040 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1041 werror (E_FILE_OPEN_ERR, scratchFileName);
1044 /* add a module record */
1045 fprintf (cdbFile, "M:%s\n", moduleName);
1051 /*-----------------------------------------------------------------*/
1052 /* linkEdit : - calls the linkage editor with options */
1053 /*-----------------------------------------------------------------*/
1055 linkEdit (char **envp)
1062 srcFileName = "temp";
1064 /* first we need to create the <filename>.lnk file */
1065 sprintf (scratchFileName, "%s.lnk", srcFileName);
1066 if (!(lnkfile = fopen (scratchFileName, "w")))
1068 werror (E_FILE_OPEN_ERR, scratchFileName);
1072 /* now write the options */
1073 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1075 /* if iram size specified */
1076 if (options.iram_size)
1077 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1080 fprintf (lnkfile, "-z\n");
1082 #define WRITE_SEG_LOC(N, L) \
1083 segName = Safe_strdup(N); \
1084 c = strtok(segName, " \t"); \
1085 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1086 if (segName) { Safe_free(segName); }
1088 /* code segment start */
1089 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1091 /* data segment start */
1092 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1095 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1098 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1100 /* bit segment start */
1101 WRITE_SEG_LOC (BIT_NAME, 0);
1103 /* add the extra linker options */
1104 for (i = 0; linkOptions[i]; i++)
1105 fprintf (lnkfile, "%s\n", linkOptions[i]);
1107 /* other library paths if specified */
1108 for (i = 0; i < nlibPaths; i++)
1109 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1111 /* standard library path */
1112 if (!options.nostdlib)
1115 if (TARGET_IS_DS390)
1122 switch (options.model)
1135 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1140 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1142 /* standard library files */
1143 /* if (strcmp (port->target, "ds390") == 0) */
1144 if (options.model == MODEL_FLAT24)
1146 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1148 fprintf (lnkfile, "-l %s\n", STD_LIB);
1149 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1150 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1151 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1154 /* additional libraries if any */
1155 for (i = 0; i < nlibFiles; i++)
1156 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1158 /* put in the object files */
1159 if (strcmp (srcFileName, "temp"))
1160 fprintf (lnkfile, "%s ", srcFileName);
1162 for (i = 0; i < nrelFiles; i++)
1163 fprintf (lnkfile, "%s\n", relFiles[i]);
1165 fprintf (lnkfile, "\n-e\n");
1168 if (options.verbose)
1169 printf ("sdcc: Calling linker...\n");
1171 if (port->linker.cmd)
1173 char buffer2[PATH_MAX];
1174 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1175 buildCmdLine2 (buffer, buffer2);
1179 buildCmdLine2 (buffer, port->linker.mcmd);
1182 if (my_system (buffer))
1187 if (strcmp (srcFileName, "temp") == 0)
1189 /* rename "temp.cdb" to "firstRelFile.cdb" */
1190 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1191 f = strcat (f, ".cdb");
1192 rename ("temp.cdb", f);
1197 /*-----------------------------------------------------------------*/
1198 /* assemble - spawns the assembler with arguments */
1199 /*-----------------------------------------------------------------*/
1201 assemble (char **envp)
1203 if (port->assembler.cmd)
1205 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1206 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1211 buildCmdLine2 (buffer, port->assembler.mcmd);
1214 if (my_system (buffer))
1216 /* either system() or the assembler itself has reported an error
1217 perror ("Cannot exec assembler");
1223 /*-----------------------------------------------------------------*/
1224 /* preProcess - spawns the preprocessor with arguments */
1225 /*-----------------------------------------------------------------*/
1227 preProcess (char **envp)
1231 if (!options.c1mode)
1233 /* if using external stack define the macro */
1234 if (options.useXstack)
1235 addToList (preArgv, "-DSDCC_USE_XSTACK");
1237 /* set the macro for stack autos */
1238 if (options.stackAuto)
1239 addToList (preArgv, "-DSDCC_STACK_AUTO");
1241 /* set the macro for stack autos */
1242 if (options.stack10bit)
1243 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1245 /* set the macro for no overlay */
1246 if (options.noOverlay)
1247 addToList (preArgv, "-DSDCC_NOOVERLAY");
1249 /* set the macro for large model */
1250 switch (options.model)
1253 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1256 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1259 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1262 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1265 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1268 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1272 /* add port (processor information to processor */
1273 addToList (preArgv, "-DSDCC_{port}");
1274 addToList (preArgv, "-D__{port}");
1276 /* standard include path */
1277 if (!options.nostdinc) {
1278 addToList (preArgv, "-I{includedir}");
1281 setMainValue ("cppextraopts", join(preArgv));
1284 preOutName = Safe_strdup (tempfilename ());
1286 /* Have to set cppoutfilename to something, even if just pre-processing. */
1287 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1289 if (options.verbose)
1290 printf ("sdcc: Calling preprocessor...\n");
1292 buildCmdLine2 (buffer, _preCmd);
1294 if (my_system (buffer))
1296 // @FIX: Dario Vecchio 03-05-2001
1299 unlink (preOutName);
1300 Safe_free (preOutName);
1313 preOutName = fullSrcFileName;
1316 yyin = fopen (preOutName, "r");
1319 perror ("Preproc file not found\n");
1327 _setPaths (const char *pprefix)
1330 Given the prefix and how the directories were layed out at
1331 configure time, see if the library and include directories are
1332 where expected. If so, set.
1334 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1335 strcpy (scratchFileName, pprefix);
1336 strcat (scratchFileName, buffer);
1338 if (pathExists (scratchFileName))
1340 setMainValue ("includedir", scratchFileName);
1347 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1348 strcpy (scratchFileName, pprefix);
1349 strcat (scratchFileName, buffer);
1351 if (pathExists (scratchFileName))
1353 setMainValue ("libdir", scratchFileName);
1364 _discoverPaths (const char *argv0)
1367 1. Try the SDCCDIR environment variable.
1368 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1369 and library paths with respect to that. Note that under win32
1370 argv[0] is always the full path to the program.
1371 3. If (1) and (2) fail, fall back to the compile time defaults.
1373 Detecting assumes the same layout as when configured. If the
1374 directories have been further moved about then discovery will
1378 /* Some input cases:
1379 "c:\fish\sdcc\bin\sdcc"
1381 "/home/fish/bin/sdcc"
1383 Note that ./sdcc is explicitly not supported as there isn't
1386 /* bindir is handled differently to the lib and include directories.
1387 It's rather unfortunate, but required due to the different
1388 install and development layouts. Logic is different as well.
1391 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1393 strcpy (scratchFileName, argv0);
1394 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1395 setMainValue ("bindir", scratchFileName);
1396 ExePathList[0] = Safe_strdup (scratchFileName);
1398 else if (getenv (SDCCDIR_NAME) != NULL)
1400 getPathDifference (buffer, PREFIX, BINDIR);
1401 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1402 strcat (scratchFileName, buffer);
1403 setMainValue ("bindir", scratchFileName);
1404 ExePathList[0] = Safe_strdup (scratchFileName);
1408 setMainValue ("bindir", BINDIR);
1409 ExePathList[0] = BINDIR;
1415 if (getenv (SDCCDIR_NAME) != NULL)
1417 if (_setPaths (getenv (SDCCDIR_NAME)))
1419 /* Successfully set. */
1424 /* Include and lib weren't where expected. */
1428 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1430 char *pbase = getPrefixFromBinPath (argv0);
1434 /* A bad path. Skip. */
1438 if (_setPaths (pbase))
1440 /* Successfully set. */
1445 /* Include and lib weren't where expected. */
1450 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1451 setMainValue ("libdir", SDCC_LIB_DIR);
1458 populateMainValues (_baseValues);
1459 setMainValue ("port", port->target);
1460 setMainValue ("objext", port->linker.rel_ext);
1461 setMainValue ("asmext", port->assembler.file_ext);
1463 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1464 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1469 * initialises and calls the parser
1473 main (int argc, char **argv, char **envp)
1475 /* turn all optimizations off by default */
1476 memset (&optimize, 0, sizeof (struct optimize));
1478 /*printVersionInfo (); */
1481 fprintf (stderr, "Build error: no ports are enabled.\n");
1485 _findPort (argc, argv);
1487 if (strcmp(port->target, "mcs51") == 0) {
1488 printf("DS390 jammed in A\n");
1493 /* Initalise the port. */
1497 // Create a default exe search path from the path to the sdcc command
1500 setDefaultOptions ();
1503 options.model = MODEL_SMALL;
1504 options.stack10bit=0;
1507 parseCmdLine (argc, argv);
1509 /* if no input then printUsage & exit */
1510 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1511 (options.c1mode && !srcFileName && !options.out_name))
1518 _discoverPaths (argv[0]);
1526 port->finaliseOptions ();
1534 if (options.verbose)
1535 printf ("sdcc: Generating code...\n");
1541 if (TARGET_IS_PIC) {
1542 /* TSD PIC port hack - if the PIC port option is enabled
1543 and SDCC is used to generate PIC code, then we will
1544 generate .asm files in gpasm's format instead of SDCC's
1547 #if !OPT_DISABLE_PIC
1556 // @FIX: Dario Vecchio 03-05-2001
1559 if (yyin && yyin != stdin)
1561 unlink (preOutName);
1562 Safe_free (preOutName);
1567 if (!options.c1mode && !noAssemble)
1569 if (options.verbose)
1570 printf ("sdcc: Calling assembler...\n");
1576 // @FIX: Dario Vecchio 03-05-2001
1579 if (yyin && yyin != stdin)
1581 unlink (preOutName);
1582 Safe_free (preOutName);
1585 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1598 if (preOutName && !options.c1mode)
1600 unlink (preOutName);
1601 Safe_free (preOutName);
1604 if (!options.cc_only &&
1608 (srcFileName || nrelFiles))
1610 if (port->linker.do_link)
1611 port->linker.do_link ();
1616 if (yyin && yyin != stdin)