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 -------------------------------------------------------------------------*/
32 #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 /* can be NULL while linking without compiling */
55 char *fullDstFileName; /* full name for the output file; */
56 /* only given by -o, otherwise NULL */
57 char *dstFileName; /* destination file name without extension */
58 char *dstPath = ""; /* path for the output files; */
59 /* "" is equivalent with cwd */
60 char *moduleName; /* module name is source file without path and extension */
61 /* can be NULL while linking without compiling */
62 const char *preArgv[128]; /* pre-processor arguments */
64 int RegBankUsed[4]={1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
65 struct optimize optimize;
66 struct options options;
67 char *VersionString = SDCC_VERSION_STR;
70 char *linkOptions[128];
71 const char *asmOptions[128];
78 bool verboseExec = FALSE;
80 bool noXinitOpt = FALSE;
82 /* uncomment JAMIN_DS390 to always override and use ds390 port
83 for mcs51 work. This is temporary, for compatibility testing. */
84 /* #define JAMIN_DS390 */
89 // Globally accessible scratch buffer for file names.
90 char scratchFileName[PATH_MAX];
91 char buffer[PATH_MAX];
93 // In MSC VC6 default search path for exe's to path for this
95 char DefaultExePath[128];
97 #define OPTION_HELP "-help"
99 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
101 #define OPTION_STACK_8BIT "--stack-8bit"
102 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
103 #define OPTION_LARGE_MODEL "--model-large"
104 #define OPTION_MEDIUM_MODEL "--model-medium"
105 #define OPTION_SMALL_MODEL "--model-small"
106 #define OPTION_FLAT24_MODEL "--model-flat24"
107 #define OPTION_DUMP_ALL "--dumpall"
108 #define OPTION_PEEP_FILE "--peep-file"
109 #define OPTION_LIB_PATH "--lib-path"
110 #define OPTION_XSTACK_LOC "--xstack-loc"
111 #define OPTION_CALLEE_SAVES "--callee-saves"
112 #define OPTION_STACK_LOC "--stack-loc"
113 #define OPTION_XRAM_LOC "--xram-loc"
114 #define OPTION_IRAM_SIZE "--iram-size"
115 #define OPTION_VERSION "--version"
116 #define OPTION_DATA_LOC "--data-loc"
117 #define OPTION_CODE_LOC "--code-loc"
118 #define OPTION_IDATA_LOC "--idata-loc"
119 #define OPTION_NO_LOOP_INV "--noinvariant"
120 #define OPTION_NO_LOOP_IND "--noinduction"
121 #define OPTION_LESS_PEDANTIC "--lesspedantic"
122 #define OPTION_NO_GCSE "--nogcse"
123 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
124 #define OPTION_TINI_LIBID "--tini-libid"
125 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
126 #define OPTION_XRAM_SIZE "--xram-size"
127 #define OPTION_CODE_SIZE "--code-size"
131 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
132 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
133 { 'd', NULL, NULL, NULL },
134 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
135 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
136 { 'A', NULL, NULL, NULL },
137 { 'U', NULL, NULL, NULL },
138 { 'C', NULL, NULL, "Preprocessor option" },
139 { 'M', NULL, NULL, "Preprocessor option" },
140 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
141 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
142 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
143 { 'L', NULL, NULL, "Add the next field to the library search path" },
144 { 'l', NULL, NULL, "Include the given library in the link" },
145 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
146 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
147 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
148 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
149 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
150 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
151 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
152 { 0, "--xstack", &options.useXstack, "Use external stack" },
153 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
154 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
155 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
156 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
157 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
158 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
159 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
160 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
161 { 0, "--dumpgcse", &options.dump_gcse, NULL },
162 { 0, "--dumploop", &options.dump_loop, NULL },
163 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
164 { 0, "--dumpliverange", &options.dump_range, NULL },
165 { 0, "--dumpregpack", &options.dump_pack, NULL },
166 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
167 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
168 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
169 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
170 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
171 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
172 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
173 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
174 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
175 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
176 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
177 { 0, OPTION_IDATA_LOC, NULL, NULL },
178 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
179 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
180 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
181 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
182 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
183 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
184 { 0, "--cyclomatic", &options.cyclomatic, NULL },
185 { 0, "--nooverlay", &options.noOverlay, NULL },
186 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
187 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
188 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
189 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
190 { 0, "--peep-asm", &options.asmpeep, NULL },
191 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
192 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
193 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
194 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
195 { 0, "--help", NULL, "Display this help" },
196 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
197 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
198 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
199 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
200 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
201 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
202 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
203 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
204 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
205 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
206 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
207 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
208 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
209 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
210 { 0, OPTION_NO_XINIT_OPT, &noXinitOpt, "don't memcpy initialized xram from code"},
215 /** Table of all unsupported options and help text to display when one
219 /** shortOpt as in OPTIONS. */
221 /** longOpt as in OPTIONS. */
223 /** Message to display inside W_UNSUPPORTED_OPT when this option
228 static const UNSUPPORTEDOPT
229 unsupportedOptTable[] = {
230 { 'X', NULL, "use --xstack-loc instead" },
231 { 'x', NULL, "use --xstack instead" },
232 { 'i', NULL, "use --idata-loc instead" },
233 { 'r', NULL, "use --xdata-loc instead" },
234 { 's', NULL, "use --code-loc instead" },
235 { 'Y', NULL, "use -I instead" }
238 /** List of all default constant macros.
240 static const char *_baseValues[] = {
241 "cpp", "{bindir}{sep}sdcpp",
243 /* Path seperator character */
244 "sep", DIR_SEPARATOR_STRING,
248 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
252 static PORT *_ports[] =
254 #if !OPT_DISABLE_MCS51
257 #if !OPT_DISABLE_GBZ80
266 #if !OPT_DISABLE_DS390
272 #if !OPT_DISABLE_TININative
275 #if !OPT_DISABLE_XA51
280 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
283 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);
307 /* Override the default processor with the one specified
308 * on the command line */
310 _setProcessor (char *_processor)
312 port->processor = _processor;
313 fprintf(stderr,"Processor: %s\n",_processor);
317 _validatePorts (void)
320 for (i = 0; i < NUM_PORTS; i++)
322 if (_ports[i]->magic != PORT_MAGIC)
324 /* Uncomment this line to debug which port is causing the problem
325 * (the target name is close to the beginning of the port struct
326 * and probably can be accessed just fine). */
327 fprintf(stderr,"%s :",_ports[i]->target);
328 wassertl (0, "Port definition structure is incomplete");
333 /* search through the command line options for the port */
335 _findPort (int argc, char **argv)
341 if (!strncmp (*argv, "-m", 2))
343 _setPort (*argv + 2);
348 /* Use the first in the list */
352 /* search through the command line options for the processor */
354 _findProcessor (int argc, char **argv)
358 if (!strncmp (*argv, "-p", 2))
360 _setProcessor (*argv + 2);
366 /* no error if processor was not specified. */
369 /*-----------------------------------------------------------------*/
370 /* printVersionInfo - prints the version info */
371 /*-----------------------------------------------------------------*/
379 for (i = 0; i < NUM_PORTS; i++)
380 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
382 fprintf (stderr, " %s"
383 #ifdef SDCC_SUB_VERSION_STR
384 "/" SDCC_SUB_VERSION_STR
389 #elif defined __MINGW32__
395 # if defined(_MSC_VER)
408 printOptions(const OPTION *optionsTable)
411 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
413 fprintf(stdout, " %c%c %-20s %s\n",
414 optionsTable[i].shortOpt !=0 ? '-' : ' ',
415 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
416 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
417 optionsTable[i].help != NULL ? optionsTable[i].help : ""
422 /*-----------------------------------------------------------------*/
423 /* printUsage - prints command line syntax */
424 /*-----------------------------------------------------------------*/
431 "Usage : sdcc [options] filename\n"
435 printOptions(optionsTable);
437 for (i = 0; i < NUM_PORTS; i++)
439 if (_ports[i]->poptions != NULL)
441 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
442 printOptions (_ports[i]->poptions);
449 /*-----------------------------------------------------------------*/
450 /* parseWithComma - separates string with comma */
451 /*-----------------------------------------------------------------*/
453 parseWithComma (char **dest, char *src)
457 strtok (src, "\r\n \t");
458 /* skip the initial white spaces */
459 while (isspace (*src))
476 /*-----------------------------------------------------------------*/
477 /* setDefaultOptions - sets the default options */
478 /*-----------------------------------------------------------------*/
484 for (i = 0; i < 128; i++)
485 preArgv[i] = asmOptions[i] =
486 linkOptions[i] = relFiles[i] = libFiles[i] =
489 /* first the options part */
490 options.stack_loc = 0; /* stack pointer initialised to 0 */
491 options.xstack_loc = 0; /* xternal stack starts at 0 */
492 options.code_loc = 0; /* code starts at 0 */
493 options.data_loc = 0; /* JCF: By default let the linker locate data */
494 options.xdata_loc = 0;
495 options.idata_loc = 0x80;
497 options.model = port->general.default_model;
498 options.nostdlib = 0;
499 options.nostdinc = 0;
501 options.shortis8bits = 0;
503 options.stack10bit=0;
505 /* now for the optimizations */
506 /* turn on the everything */
507 optimize.global_cse = 1;
512 optimize.loopInvariant = 1;
513 optimize.loopInduction = 1;
515 /* now for the ports */
516 port->setDefaultOptions ();
519 /*-----------------------------------------------------------------*/
520 /* processFile - determines the type of file from the extension */
521 /*-----------------------------------------------------------------*/
523 processFile (char *s)
527 /* get the file extension */
528 fext = s + strlen (s);
529 while ((fext != s) && *fext != '.')
532 /* now if no '.' then we don't know what the file type is
533 so give a warning and return */
536 werror (W_UNKNOWN_FEXT, s);
540 /* otherwise depending on the file type */
541 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
543 /* source file name : not if we already have a
547 werror (W_TOO_MANY_SRC, s);
551 /* the only source file */
553 if (!(srcFile = fopen (fullSrcFileName, "r")))
555 werror (E_FILE_OPEN_ERR, s);
559 /* copy the file name into the buffer */
562 /* get rid of the "."-extension */
564 /* is there a dot at all? */
565 if (strrchr (buffer, '.') &&
566 /* is the dot in the filename, not in the path? */
567 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
569 *strrchr (buffer, '.') = '\0';
572 /* get rid of any path information
573 for the module name; */
574 fext = buffer + strlen (buffer);
576 /* do this by going backwards till we
577 get '\' or ':' or start of buffer */
578 while (fext != buffer &&
579 *(fext - 1) != DIR_SEPARATOR_CHAR &&
585 /* do this by going backwards till we
586 get '/' or start of buffer */
587 while (fext != buffer &&
588 *(fext - 1) != DIR_SEPARATOR_CHAR)
593 moduleName = Safe_strdup ( fext );
597 /* if the extention is type .rel or .r or .REL or .R
598 addtional object file will be passed to the linker */
599 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
600 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
601 strcmp (fext, port->linker.rel_ext) == 0)
603 relFiles[nrelFiles++] = s;
607 /* if .lib or .LIB */
608 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
610 libFiles[nlibFiles++] = s;
614 werror (W_UNKNOWN_FEXT, s);
619 _setModel (int model, const char *sz)
621 if (port->general.supported_models & model)
622 options.model = model;
624 werror (W_UNSUPPORTED_MODEL, sz, port->target);
627 /** Gets the string argument to this option. If the option is '--opt'
628 then for input of '--optxyz' or '--opt xyz' returns xyz.
631 getStringArg(const char *szStart, char **argv, int *pi, int argc)
633 if (argv[*pi][strlen(szStart)])
635 return &argv[*pi][strlen(szStart)];
642 werror (E_ARGUMENT_MISSING, szStart);
643 /* Die here rather than checking for errors later. */
653 /** Gets the integer argument to this option using the same rules as
657 getIntArg(const char *szStart, char **argv, int *pi, int argc)
659 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
663 verifyShortOption(const char *opt)
665 if (strlen(opt) != 2)
667 werror (W_EXCESS_SHORT_OPTIONS, opt);
672 tryHandleUnsupportedOpt(char **argv, int *pi)
674 if (argv[*pi][0] == '-')
676 const char *longOpt = "";
680 if (argv[*pi][1] == '-')
687 shortOpt = argv[*pi][1];
689 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
691 if (unsupportedOptTable[i].shortOpt == shortOpt ||
692 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
693 // Found an unsupported opt.
695 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
696 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
700 // Didn't find in the table
705 // Not an option, so can't be unsupported :)
711 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
714 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
716 if (optionsTable[i].shortOpt == shortOpt ||
717 (longOpt && optionsTable[i].longOpt &&
718 strcmp(optionsTable[i].longOpt, longOpt) == 0))
721 // If it is a flag then we can handle it here
722 if (optionsTable[i].pparameter != NULL)
724 if (optionsTable[i].shortOpt == shortOpt)
726 verifyShortOption(argv[*pi]);
729 (*optionsTable[i].pparameter)++;
733 // Not a flag. Handled manually later.
738 // Didn't find in the table
743 tryHandleSimpleOpt(char **argv, int *pi)
745 if (argv[*pi][0] == '-')
747 const char *longOpt = "";
750 if (argv[*pi][1] == '-')
757 shortOpt = argv[*pi][1];
760 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
764 else if (port && port->poptions &&
765 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
776 // Not an option, so can't be handled.
781 /*-----------------------------------------------------------------*/
782 /* parseCmdLine - parses the command line and sets the options */
783 /*-----------------------------------------------------------------*/
785 parseCmdLine (int argc, char **argv)
789 /* go thru all whole command line */
790 for (i = 1; i < argc; i++)
795 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
800 if (tryHandleSimpleOpt(argv, &i) == TRUE)
806 if (argv[i][0] == '-' && argv[i][1] == '-')
808 if (strcmp (argv[i], OPTION_HELP) == 0)
814 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
816 options.stack10bit = 0;
820 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
826 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
828 _setModel (MODEL_LARGE, argv[i]);
832 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
834 _setModel (MODEL_MEDIUM, argv[i]);
838 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
840 _setModel (MODEL_SMALL, argv[i]);
844 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
846 _setModel (MODEL_FLAT24, argv[i]);
850 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
852 options.dump_rassgn =
858 options.dump_raw = 1;
862 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
864 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
868 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
870 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
874 if (strcmp (argv[i], OPTION_VERSION) == 0)
881 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
883 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
887 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
889 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
893 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
895 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
899 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
901 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
905 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
907 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
911 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
913 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
914 options.xram_size_set = TRUE;
918 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
920 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
924 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
926 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
930 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
932 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
936 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
938 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
942 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
944 optimize.global_cse = 0;
948 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
950 optimize.loopInvariant = 0;
954 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
956 optimize.loopInduction = 0;
960 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
962 options.lessPedantic = 1;
963 setErrorLogLevel(ERROR_LEVEL_WARNING);
967 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
969 options.shortis8bits=1;
973 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
975 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
979 if (!port->parseOption (&argc, argv, &i))
981 werror (W_UNKNOWN_OPTION, argv[i]);
989 /* if preceded by '-' then option */
995 verifyShortOption(argv[i]);
1002 /* Used to select the port. But this has already been done. */
1006 /* Used to select the processor in port. But this has
1007 * already been done. */
1011 verifyShortOption(argv[i]);
1013 options.cc_only = 1;
1017 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
1021 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
1028 /* copy the file name into the buffer */
1029 strcpy (buffer, getStringArg("-o", argv, &i, argc));
1030 /* point to last character */
1031 p = buffer + strlen (buffer) - 1;
1032 if (*p == DIR_SEPARATOR_CHAR)
1034 /* only output path specified */
1035 dstPath = Safe_strdup (buffer);
1036 fullDstFileName = NULL;
1040 fullDstFileName = Safe_strdup (buffer);
1042 /* get rid of the "."-extension */
1044 /* is there a dot at all? */
1045 if (strrchr (buffer, '.') &&
1046 /* is the dot in the filename, not in the path? */
1047 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1048 *strrchr (buffer, '.') = '\0';
1050 dstFileName = Safe_strdup (buffer);
1052 /* strip module name to get path */
1053 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1056 /* path with trailing / */
1058 dstPath = Safe_strdup (buffer);
1065 /* pre-processer options */
1066 if (argv[i][2] == 'p')
1068 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
1070 /* linker options */
1071 else if (argv[i][2] == 'l')
1073 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
1075 /* assembler options */
1076 else if (argv[i][2] == 'a')
1078 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
1082 werror (W_UNKNOWN_OPTION, argv[i]);
1087 verifyShortOption(argv[i]);
1089 printVersionInfo ();
1093 /* preprocessor options */
1097 addToList (preArgv, "-M");
1102 addToList (preArgv, "-C");
1111 char sOpt = argv[i][1];
1114 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1120 werror(E_ARGUMENT_MISSING, argv[i-1]);
1134 sprintf (buffer, "-%c%s", sOpt, rest);
1135 addToList (preArgv, buffer);
1140 if (!port->parseOption (&argc, argv, &i))
1141 werror (W_UNKNOWN_OPTION, argv[i]);
1146 if (!port->parseOption (&argc, argv, &i))
1148 /* no option must be a filename */
1149 processFile (argv[i]);
1153 /* if no dstFileName given with -o, we've to find one: */
1156 /* use the modulename from the C-source */
1157 if (fullSrcFileName)
1159 dstFileName = Safe_alloc (strlen (dstPath) + strlen (moduleName) + 1);
1160 strcpy (dstFileName, dstPath);
1161 strcat (dstFileName, moduleName);
1163 /* use the modulename from the first object file */
1164 else if (nrelFiles >= 1)
1168 strcpy (buffer, relFiles[0]);
1169 /* remove extension (it must be .rel) */
1170 *strrchr (buffer, '.') = '\0';
1172 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1179 objectName = buffer;
1181 dstFileName = Safe_alloc (strlen (dstPath) + strlen (objectName) + 1);
1182 strcpy (dstFileName, dstPath);
1183 strcat (dstFileName, objectName);
1185 /* else no module given: help text is displayed */
1188 /* set up external stack location if not explicitly specified */
1189 if (!options.xstack_loc)
1190 options.xstack_loc = options.xdata_loc;
1192 /* if debug option is set the open the cdbFile */
1193 if (options.debug && fullSrcFileName)
1195 sprintf (scratchFileName, "%s.adb", dstFileName); //JCF: Nov 30, 2002
1196 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1197 werror (E_FILE_OPEN_ERR, scratchFileName);
1200 /* add a module record */
1201 fprintf (cdbFile, "M:%s\n", moduleName);
1207 /*-----------------------------------------------------------------*/
1208 /* linkEdit : - calls the linkage editor with options */
1209 /*-----------------------------------------------------------------*/
1211 linkEdit (char **envp)
1217 /* first we need to create the <filename>.lnk file */
1218 sprintf (scratchFileName, "%s.lnk", dstFileName);
1219 if (!(lnkfile = fopen (scratchFileName, "w")))
1221 werror (E_FILE_OPEN_ERR, scratchFileName);
1225 /* now write the options. JCF: added option 'y' */
1226 fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1228 /* if iram size specified */
1229 if (options.iram_size)
1230 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1232 /* if xram size specified */
1233 if (options.xram_size_set)
1234 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1236 /* if code size specified */
1237 if (options.code_size)
1238 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1241 fprintf (lnkfile, "-z\n");
1243 #define WRITE_SEG_LOC(N, L) \
1244 segName = Safe_strdup(N); \
1245 c = strtok(segName, " \t"); \
1246 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1247 if (segName) { Safe_free(segName); }
1249 /* code segment start */
1250 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1252 /* data segment start */
1253 if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
1254 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1258 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1262 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1265 /* bit segment start */
1266 WRITE_SEG_LOC (BIT_NAME, 0);
1268 /* JCF: stack start */
1269 if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
1270 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1273 /* add the extra linker options */
1274 for (i = 0; linkOptions[i]; i++)
1275 fprintf (lnkfile, "%s\n", linkOptions[i]);
1277 /* other library paths if specified */
1278 for (i = 0; i < nlibPaths; i++)
1279 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1281 /* standard library path */
1282 if (!options.nostdlib)
1284 switch (options.model)
1300 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1304 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1306 /* standard library files */
1307 #if !OPT_DISABLE_DS390
1308 if (options.model == MODEL_FLAT24)
1310 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1314 #if !OPT_DISABLE_XA51
1316 if (options.model == MODEL_PAGE0)
1318 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1322 fprintf (lnkfile, "-l %s\n", STD_LIB);
1323 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1324 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1325 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1328 /* additional libraries if any */
1329 for (i = 0; i < nlibFiles; i++)
1330 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1332 /* put in the object files */
1333 if (fullSrcFileName)
1334 fprintf (lnkfile, "%s ", dstFileName);
1336 for (i = 0; i < nrelFiles; i++)
1337 fprintf (lnkfile, "%s\n", relFiles[i]);
1339 fprintf (lnkfile, "\n-e\n");
1342 if (options.verbose)
1343 printf ("sdcc: Calling linker...\n");
1345 /* build linker output filename */
1347 /* -o option overrides default name? */
1348 if (fullDstFileName)
1350 strcpy (scratchFileName, fullDstFileName);
1354 /* the linked file gets the name of the first modul */
1355 if (fullSrcFileName)
1357 strcpy (scratchFileName, dstFileName);
1361 strcpy (scratchFileName, relFiles[0]);
1362 /* strip ".rel" extension */
1363 *strrchr (scratchFileName, '.') = '\0';
1365 strcat (scratchFileName, options.out_fmt ? ".S19" : ".ihx");
1368 if (port->linker.cmd)
1370 char buffer2[PATH_MAX];
1371 buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, NULL);
1372 buildCmdLine2 (buffer, buffer2);
1376 buildCmdLine2 (buffer, port->linker.mcmd);
1379 system_ret = my_system (buffer);
1380 /* TODO: most linker don't have a -o parameter */
1381 /* -o option overrides default name? */
1382 if (fullDstFileName)
1385 /* the linked file gets the name of the first modul */
1386 if (fullSrcFileName)
1388 strcpy (scratchFileName, dstFileName);
1389 p = strlen (scratchFileName) + scratchFileName;
1393 strcpy (scratchFileName, relFiles[0]);
1394 /* strip "rel" extension */
1395 p = strrchr (scratchFileName, '.') + 1;
1397 strcpy (p, options.out_fmt ? "S19" : "ihx");
1398 rename (scratchFileName, fullDstFileName);
1400 q = strrchr (fullDstFileName, '.');
1403 /* point after the '.' of the extension */
1408 /* no extension: append new extensions */
1409 q = strlen (fullDstFileName) + fullDstFileName;
1413 rename (scratchFileName, fullDstFileName);
1416 rename (scratchFileName, fullDstFileName);
1424 /*-----------------------------------------------------------------*/
1425 /* assemble - spawns the assembler with arguments */
1426 /*-----------------------------------------------------------------*/
1428 assemble (char **envp)
1430 /* build assembler output filename */
1432 /* -o option overrides default name? */
1433 if (options.cc_only && fullDstFileName) {
1434 strcpy (scratchFileName, fullDstFileName);
1436 /* the assembled file gets the name of the first modul */
1437 strcpy (scratchFileName, dstFileName);
1438 strcat (scratchFileName, port->linker.rel_ext);
1441 if (port->assembler.do_assemble) {
1442 port->assembler.do_assemble(asmOptions);
1444 } else if (port->assembler.cmd) {
1445 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1446 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1449 buildCmdLine2 (buffer, port->assembler.mcmd);
1452 if (my_system (buffer)) {
1453 /* either system() or the assembler itself has reported an error
1454 perror ("Cannot exec assembler");
1458 /* TODO: most assembler don't have a -o parameter */
1459 /* -o option overrides default name? */
1460 if (options.cc_only && fullDstFileName) {
1461 strcpy (scratchFileName, dstFileName);
1462 strcat (scratchFileName, port->linker.rel_ext);
1463 rename (scratchFileName, fullDstFileName);
1467 /*-----------------------------------------------------------------*/
1468 /* preProcess - spawns the preprocessor with arguments */
1469 /*-----------------------------------------------------------------*/
1471 preProcess (char **envp)
1475 if (!options.c1mode)
1477 /* if using external stack define the macro */
1478 if (options.useXstack)
1479 addToList (preArgv, "-DSDCC_USE_XSTACK");
1481 /* set the macro for stack autos */
1482 if (options.stackAuto)
1483 addToList (preArgv, "-DSDCC_STACK_AUTO");
1485 /* set the macro for stack autos */
1486 if (options.stack10bit)
1487 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1489 /* set the macro for no overlay */
1490 if (options.noOverlay)
1491 addToList (preArgv, "-DSDCC_NOOVERLAY");
1493 /* set the macro for large model */
1494 switch (options.model)
1497 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1500 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1503 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1506 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1509 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1512 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1515 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1519 /* add port (processor information to processor */
1520 addToList (preArgv, "-DSDCC_{port}");
1521 addToList (preArgv, "-D__{port}");
1523 /* standard include path */
1524 if (!options.nostdinc) {
1525 addToList (preArgv, "-I{includedir}");
1528 setMainValue ("cppextraopts", join(preArgv));
1532 if (fullDstFileName)
1533 preOutName = Safe_strdup (fullDstFileName);
1536 preOutName = Safe_strdup (tempfilename ());
1538 /* Have to set cppoutfilename to something, even if just pre-processing. */
1539 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1541 if (options.verbose)
1542 printf ("sdcc: Calling preprocessor...\n");
1544 buildCmdLine2 (buffer, _preCmd);
1546 if (my_system (buffer))
1548 // @FIX: Dario Vecchio 03-05-2001
1551 unlink (preOutName);
1552 Safe_free (preOutName);
1565 preOutName = fullSrcFileName;
1568 yyin = fopen (preOutName, "r");
1571 perror ("Preproc file not found\n");
1579 _setPaths (const char *pprefix)
1582 Given the prefix and how the directories were layed out at
1583 configure time, see if the library and include directories are
1584 where expected. If so, set.
1586 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1587 strcpy (scratchFileName, pprefix);
1588 strcat (scratchFileName, buffer);
1590 if (pathExists (scratchFileName))
1592 setMainValue ("includedir", scratchFileName);
1599 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1600 strcpy (scratchFileName, pprefix);
1601 strcat (scratchFileName, buffer);
1603 if (pathExists (scratchFileName))
1605 setMainValue ("libdir", scratchFileName);
1616 _discoverPaths (const char *argv0)
1619 1. Try the SDCCDIR environment variable.
1620 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1621 and library paths with respect to that. Note that under win32
1622 argv[0] is always the full path to the program.
1623 3. If (1) and (2) fail, fall back to the compile time defaults.
1625 Detecting assumes the same layout as when configured. If the
1626 directories have been further moved about then discovery will
1630 /* Some input cases:
1631 "c:\fish\sdcc\bin\sdcc"
1633 "/home/fish/bin/sdcc"
1635 Note that ./sdcc is explicitly not supported as there isn't
1638 /* bindir is handled differently to the lib and include directories.
1639 It's rather unfortunate, but required due to the different
1640 install and development layouts. Logic is different as well.
1643 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1645 strcpy (scratchFileName, argv0);
1646 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1647 setMainValue ("bindir", scratchFileName);
1648 ExePathList[0] = Safe_strdup (scratchFileName);
1650 else if (getenv (SDCCDIR_NAME) != NULL)
1652 getPathDifference (buffer, PREFIX, BINDIR);
1653 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1654 strcat (scratchFileName, buffer);
1655 setMainValue ("bindir", scratchFileName);
1656 ExePathList[0] = Safe_strdup (scratchFileName);
1660 setMainValue ("bindir", BINDIR);
1661 ExePathList[0] = BINDIR;
1667 if (getenv (SDCCDIR_NAME) != NULL)
1669 if (_setPaths (getenv (SDCCDIR_NAME)))
1671 /* Successfully set. */
1676 /* Include and lib weren't where expected. */
1680 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1682 char *pbase = getPrefixFromBinPath (argv0);
1686 /* A bad path. Skip. */
1690 if (_setPaths (pbase))
1692 /* Successfully set. */
1697 /* Include and lib weren't where expected. */
1702 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1703 setMainValue ("libdir", SDCC_LIB_DIR);
1710 populateMainValues (_baseValues);
1711 setMainValue ("port", port->target);
1712 setMainValue ("objext", port->linker.rel_ext);
1713 setMainValue ("asmext", port->assembler.file_ext);
1715 setMainValue ("dstfilename", dstFileName);
1716 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1718 if (options.cc_only && fullDstFileName)
1719 /* compile + assemble and -o given: -o specifies name of object file */
1721 setMainValue ("objdstfilename", fullDstFileName);
1725 setMainValue ("objdstfilename", "{stdobjdstfilename}");
1727 if (fullDstFileName)
1728 /* if we're linking, -o gives the final file name */
1730 setMainValue ("linkdstfilename", fullDstFileName);
1734 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
1740 sig_handler (int signal)
1747 sig_string = "SIGABRT";
1750 sig_string = "SIGTERM";
1753 sig_string = "SIGINT";
1756 sig_string = "SIGSEGV";
1759 sig_string = "Unknown?";
1762 fprintf (stderr, "Catched signal %d: %s\n", signal, sig_string);
1768 * initialises and calls the parser
1772 main (int argc, char **argv, char **envp)
1774 /* turn all optimizations off by default */
1775 memset (&optimize, 0, sizeof (struct optimize));
1777 /*printVersionInfo (); */
1780 fprintf (stderr, "Build error: no ports are enabled.\n");
1784 /* install atexit handler */
1785 atexit(rm_tmpfiles);
1787 /* install signal handler;
1788 it's only purpuse is to call exit() to remove temp files */
1789 signal (SIGABRT, sig_handler);
1790 signal (SIGTERM, sig_handler);
1791 signal (SIGINT , sig_handler);
1792 signal (SIGSEGV, sig_handler);
1794 /* Before parsing the command line options, do a
1795 * search for the port and processor and initialize
1796 * them if they're found. (We can't gurantee that these
1797 * will be the first options specified).
1800 _findPort (argc, argv);
1803 if (strcmp(port->target, "mcs51") == 0) {
1804 printf("DS390 jammed in A\n");
1810 _findProcessor (argc, argv);
1812 /* Initalise the port. */
1816 // Create a default exe search path from the path to the sdcc command
1819 setDefaultOptions ();
1822 options.model = MODEL_SMALL;
1823 options.stack10bit=0;
1826 parseCmdLine (argc, argv);
1828 /* if no input then printUsage & exit */
1829 if ((!options.c1mode && !fullSrcFileName && !nrelFiles) ||
1830 (options.c1mode && !fullSrcFileName))
1837 _discoverPaths (argv[0]);
1839 /* initMem() is expensive, but
1840 initMem() must called before port->finaliseOptions ().
1841 And the z80 port needs port->finaliseOptions(),
1842 even if we're only linking. */
1844 port->finaliseOptions ();
1846 if (fullSrcFileName)
1856 if (options.verbose)
1857 printf ("sdcc: Generating code...\n");
1862 // @FIX: Dario Vecchio 03-05-2001
1864 if (yyin && yyin != stdin)
1866 unlink (preOutName);
1867 Safe_free (preOutName);
1873 if (TARGET_IS_PIC) {
1874 /* TSD PIC port hack - if the PIC port option is enabled
1875 and SDCC is used to generate PIC code, then we will
1876 generate .asm files in gpasm's format instead of SDCC's
1879 #if !OPT_DISABLE_PIC
1887 if (!options.c1mode && !noAssemble)
1889 if (options.verbose)
1890 printf ("sdcc: Calling assembler...\n");
1900 if (yyin && yyin != stdin)
1903 if (preOutName && !options.c1mode)
1905 unlink (preOutName);
1906 Safe_free (preOutName);
1909 if (!options.cc_only &&
1913 (fullSrcFileName || nrelFiles))
1915 if (port->linker.do_link)
1916 port->linker.do_link ();