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 buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1171 buildCmdLine2 (buffer, port->linker.mcmd);
1174 if (my_system (buffer))
1179 if (strcmp (srcFileName, "temp") == 0)
1181 /* rename "temp.cdb" to "firstRelFile.cdb" */
1182 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1183 f = strcat (f, ".cdb");
1184 rename ("temp.cdb", f);
1189 /*-----------------------------------------------------------------*/
1190 /* assemble - spawns the assembler with arguments */
1191 /*-----------------------------------------------------------------*/
1193 assemble (char **envp)
1195 if (port->assembler.cmd)
1197 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1198 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1203 buildCmdLine2 (buffer, port->assembler.mcmd);
1206 if (my_system (buffer))
1208 /* either system() or the assembler itself has reported an error
1209 perror ("Cannot exec assembler");
1215 /*-----------------------------------------------------------------*/
1216 /* preProcess - spawns the preprocessor with arguments */
1217 /*-----------------------------------------------------------------*/
1219 preProcess (char **envp)
1223 if (!options.c1mode)
1225 /* if using external stack define the macro */
1226 if (options.useXstack)
1227 addToList (preArgv, "-DSDCC_USE_XSTACK");
1229 /* set the macro for stack autos */
1230 if (options.stackAuto)
1231 addToList (preArgv, "-DSDCC_STACK_AUTO");
1233 /* set the macro for stack autos */
1234 if (options.stack10bit)
1235 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1237 /* set the macro for no overlay */
1238 if (options.noOverlay)
1239 addToList (preArgv, "-DSDCC_NOOVERLAY");
1241 /* set the macro for large model */
1242 switch (options.model)
1245 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1248 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1251 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1254 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1257 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1260 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1264 /* add port (processor information to processor */
1265 addToList (preArgv, "-DSDCC_{port}");
1266 addToList (preArgv, "-D__{port}");
1268 /* standard include path */
1269 if (!options.nostdinc) {
1270 addToList (preArgv, "-I{includedir}");
1273 setMainValue ("cppextraopts", join(preArgv));
1276 preOutName = Safe_strdup (tempfilename ());
1278 /* Have to set cppoutfilename to something, even if just pre-processing. */
1279 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1281 if (options.verbose)
1282 printf ("sdcc: Calling preprocessor...\n");
1284 buildCmdLine2 (buffer, _preCmd);
1286 if (my_system (buffer))
1288 // @FIX: Dario Vecchio 03-05-2001
1291 unlink (preOutName);
1292 Safe_free (preOutName);
1305 preOutName = fullSrcFileName;
1308 yyin = fopen (preOutName, "r");
1311 perror ("Preproc file not found\n");
1319 _setPaths (const char *pprefix)
1322 Given the prefix and how the directories were layed out at
1323 configure time, see if the library and include directories are
1324 where expected. If so, set.
1326 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1327 strcpy (scratchFileName, pprefix);
1328 strcat (scratchFileName, buffer);
1330 if (pathExists (scratchFileName))
1332 setMainValue ("includedir", scratchFileName);
1339 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1340 strcpy (scratchFileName, pprefix);
1341 strcat (scratchFileName, buffer);
1343 if (pathExists (scratchFileName))
1345 setMainValue ("libdir", scratchFileName);
1356 _discoverPaths (const char *argv0)
1359 1. Try the SDCCDIR environment variable.
1360 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1361 and library paths with respect to that. Note that under win32
1362 argv[0] is always the full path to the program.
1363 3. If (1) and (2) fail, fall back to the compile time defaults.
1365 Detecting assumes the same layout as when configured. If the
1366 directories have been further moved about then discovery will
1370 /* Some input cases:
1371 "c:\fish\sdcc\bin\sdcc"
1373 "/home/fish/bin/sdcc"
1375 Note that ./sdcc is explicitly not supported as there isn't
1378 /* bindir is handled differently to the lib and include directories.
1379 It's rather unfortunate, but required due to the different
1380 install and development layouts. Logic is different as well.
1383 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1385 strcpy (scratchFileName, argv0);
1386 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1387 setMainValue ("bindir", scratchFileName);
1388 ExePathList[0] = Safe_strdup (scratchFileName);
1390 else if (getenv (SDCCDIR_NAME) != NULL)
1392 getPathDifference (buffer, PREFIX, BINDIR);
1393 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1394 strcat (scratchFileName, buffer);
1395 setMainValue ("bindir", scratchFileName);
1396 ExePathList[0] = Safe_strdup (scratchFileName);
1400 setMainValue ("bindir", BINDIR);
1401 ExePathList[0] = BINDIR;
1407 if (getenv (SDCCDIR_NAME) != NULL)
1409 if (_setPaths (getenv (SDCCDIR_NAME)))
1411 /* Successfully set. */
1416 /* Include and lib weren't where expected. */
1420 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1422 char *pbase = getPrefixFromBinPath (argv0);
1426 /* A bad path. Skip. */
1430 if (_setPaths (pbase))
1432 /* Successfully set. */
1437 /* Include and lib weren't where expected. */
1442 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1443 setMainValue ("libdir", SDCC_LIB_DIR);
1450 populateMainValues (_baseValues);
1451 setMainValue ("port", port->target);
1452 setMainValue ("fullsrcfilename", fullSrcFileName);
1453 setMainValue ("srcfilename", srcFileName);
1454 setMainValue ("objext", port->linker.rel_ext);
1455 setMainValue ("asmext", port->assembler.file_ext);
1460 * initialises and calls the parser
1464 main (int argc, char **argv, char **envp)
1466 /* turn all optimizations off by default */
1467 memset (&optimize, 0, sizeof (struct optimize));
1469 /*printVersionInfo (); */
1472 fprintf (stderr, "Build error: no ports are enabled.\n");
1476 _findPort (argc, argv);
1478 if (strcmp(port->target, "mcs51") == 0) {
1479 printf("DS390 jammed in A\n");
1484 /* Initalise the port. */
1488 // Create a default exe search path from the path to the sdcc command
1491 setDefaultOptions ();
1494 options.model = MODEL_SMALL;
1495 options.stack10bit=0;
1498 parseCmdLine (argc, argv);
1500 /* if no input then printUsage & exit */
1501 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1502 (options.c1mode && !srcFileName && !options.out_name))
1511 _discoverPaths (argv[0]);
1517 port->finaliseOptions ();
1524 if (options.verbose)
1525 printf ("sdcc: Generating code...\n");
1531 if (TARGET_IS_PIC) {
1532 /* TSD PIC port hack - if the PIC port option is enabled
1533 and SDCC is used to generate PIC code, then we will
1534 generate .asm files in gpasm's format instead of SDCC's
1537 #if !OPT_DISABLE_PIC
1546 // @FIX: Dario Vecchio 03-05-2001
1549 if (yyin && yyin != stdin)
1551 unlink (preOutName);
1552 Safe_free (preOutName);
1557 if (!options.c1mode && !noAssemble)
1559 if (options.verbose)
1560 printf ("sdcc: Calling assembler...\n");
1566 // @FIX: Dario Vecchio 03-05-2001
1569 if (yyin && yyin != stdin)
1571 unlink (preOutName);
1572 Safe_free (preOutName);
1575 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1588 if (preOutName && !options.c1mode)
1590 unlink (preOutName);
1591 Safe_free (preOutName);
1594 if (!options.cc_only &&
1598 (srcFileName || nrelFiles))
1600 if (port->linker.do_link)
1601 port->linker.do_link ();
1606 if (yyin && yyin != stdin)