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"
39 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
44 /** Name of the environment variable checked for other instalations. */
45 #define SDCCDIR_NAME "SDCCDIR"
48 extern int yyparse ();
50 FILE *srcFile; /* source file */
51 FILE *cdbFile = NULL; /* debugger information output file */
52 char *fullSrcFileName; /* full name for the source file; */
53 /* can be NULL while linking without compiling */
54 char *fullDstFileName; /* full name for the output file; */
55 /* only given by -o, otherwise NULL */
56 char *dstFileName; /* destination file name without extension */
57 char *dstPath = ""; /* path for the output files; */
58 /* "" is equivalent with cwd */
59 char *moduleName; /* module name is source file without path and extension */
60 /* can be NULL while linking without compiling */
61 const char *preArgv[128]; /* pre-processor arguments */
63 int RegBankUsed[4]={1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
64 struct optimize optimize;
65 struct options options;
66 char *VersionString = SDCC_VERSION_STR;
69 char *linkOptions[128];
70 const char *asmOptions[128];
77 bool verboseExec = FALSE;
79 bool noXinitOpt = FALSE;
81 /* uncomment JAMIN_DS390 to always override and use ds390 port
82 for mcs51 work. This is temporary, for compatibility testing. */
83 /* #define JAMIN_DS390 */
88 // Globally accessible scratch buffer for file names.
89 char scratchFileName[PATH_MAX];
90 char buffer[PATH_MAX];
92 // In MSC VC6 default search path for exe's to path for this
94 char DefaultExePath[128];
96 #define OPTION_HELP "-help"
98 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
100 #define OPTION_STACK_8BIT "--stack-8bit"
101 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
102 #define OPTION_LARGE_MODEL "--model-large"
103 #define OPTION_MEDIUM_MODEL "--model-medium"
104 #define OPTION_SMALL_MODEL "--model-small"
105 #define OPTION_FLAT24_MODEL "--model-flat24"
106 #define OPTION_DUMP_ALL "--dumpall"
107 #define OPTION_PEEP_FILE "--peep-file"
108 #define OPTION_LIB_PATH "--lib-path"
109 #define OPTION_XSTACK_LOC "--xstack-loc"
110 #define OPTION_CALLEE_SAVES "--callee-saves"
111 #define OPTION_STACK_LOC "--stack-loc"
112 #define OPTION_XRAM_LOC "--xram-loc"
113 #define OPTION_IRAM_SIZE "--iram-size"
114 #define OPTION_VERSION "--version"
115 #define OPTION_DATA_LOC "--data-loc"
116 #define OPTION_CODE_LOC "--code-loc"
117 #define OPTION_IDATA_LOC "--idata-loc"
118 #define OPTION_NO_LOOP_INV "--noinvariant"
119 #define OPTION_NO_LOOP_IND "--noinduction"
120 #define OPTION_LESS_PEDANTIC "--lesspedantic"
121 #define OPTION_NO_GCSE "--nogcse"
122 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
123 #define OPTION_TINI_LIBID "--tini-libid"
124 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
125 #define OPTION_XRAM_SIZE "--xram-size"
126 #define OPTION_CODE_SIZE "--code-size"
130 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
131 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
132 { 'd', NULL, NULL, NULL },
133 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
134 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
135 { 'A', NULL, NULL, NULL },
136 { 'U', NULL, NULL, NULL },
137 { 'C', NULL, NULL, "Preprocessor option" },
138 { 'M', NULL, NULL, "Preprocessor option" },
139 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
140 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
141 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
142 { 'L', NULL, NULL, "Add the next field to the library search path" },
143 { 'l', NULL, NULL, "Include the given library in the link" },
144 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
145 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
146 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
147 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
148 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
149 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
150 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
151 { 0, "--xstack", &options.useXstack, "Use external stack" },
152 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
153 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
154 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
155 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
156 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
157 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
158 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
159 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
160 { 0, "--dumpgcse", &options.dump_gcse, NULL },
161 { 0, "--dumploop", &options.dump_loop, NULL },
162 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
163 { 0, "--dumpliverange", &options.dump_range, NULL },
164 { 0, "--dumpregpack", &options.dump_pack, NULL },
165 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
166 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
167 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
168 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
169 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
170 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
171 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
172 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
173 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
174 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
175 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
176 { 0, OPTION_IDATA_LOC, NULL, NULL },
177 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
178 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
179 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
180 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
181 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
182 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
183 { 0, "--cyclomatic", &options.cyclomatic, NULL },
184 { 0, "--nooverlay", &options.noOverlay, NULL },
185 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
186 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
187 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
188 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
189 { 0, "--peep-asm", &options.asmpeep, NULL },
190 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
191 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
192 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
193 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
194 { 0, "--help", NULL, "Display this help" },
195 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
196 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
197 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
198 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
199 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
200 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
201 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
202 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
203 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
204 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
205 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
206 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
207 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
208 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
209 { 0, OPTION_NO_XINIT_OPT, &noXinitOpt, "don't memcpy initialized xram from code"},
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 { 'X', NULL, "use --xstack-loc instead" },
230 { 'x', NULL, "use --xstack 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} -nostdinc -Wall -std=c99 -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_TININative
274 #if !OPT_DISABLE_XA51
279 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
282 extern void picglue ();
285 /** Sets the port to the one given by the command line option.
286 @param The name minus the option (eg 'mcs51')
287 @return 0 on success.
290 _setPort (const char *name)
293 for (i = 0; i < NUM_PORTS; i++)
295 if (!strcmp (_ports[i]->target, name))
301 /* Error - didnt find */
302 werror (E_UNKNOWN_TARGET, name);
306 /* Override the default processor with the one specified
307 * on the command line */
309 _setProcessor (char *_processor)
311 port->processor = _processor;
312 fprintf(stderr,"Processor: %s\n",_processor);
316 _validatePorts (void)
319 for (i = 0; i < NUM_PORTS; i++)
321 if (_ports[i]->magic != PORT_MAGIC)
323 /* Uncomment this line to debug which port is causing the problem
324 * (the target name is close to the beginning of the port struct
325 * and probably can be accessed just fine). */
326 fprintf(stderr,"%s :",_ports[i]->target);
327 wassertl (0, "Port definition structure is incomplete");
332 /* search through the command line options for the port */
334 _findPort (int argc, char **argv)
340 if (!strncmp (*argv, "-m", 2))
342 _setPort (*argv + 2);
347 /* Use the first in the list */
351 /* search through the command line options for the processor */
353 _findProcessor (int argc, char **argv)
357 if (!strncmp (*argv, "-p", 2))
359 _setProcessor (*argv + 2);
365 /* no error if processor was not specified. */
368 /*-----------------------------------------------------------------*/
369 /* printVersionInfo - prints the version info */
370 /*-----------------------------------------------------------------*/
378 for (i = 0; i < NUM_PORTS; i++)
379 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
381 fprintf (stderr, " %s"
382 #ifdef SDCC_SUB_VERSION_STR
383 "/" SDCC_SUB_VERSION_STR
388 #elif defined __MINGW32__
394 # if defined(_MSC_VER)
407 printOptions(const OPTION *optionsTable)
410 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
412 fprintf(stdout, " %c%c %-20s %s\n",
413 optionsTable[i].shortOpt !=0 ? '-' : ' ',
414 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
415 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
416 optionsTable[i].help != NULL ? optionsTable[i].help : ""
421 /*-----------------------------------------------------------------*/
422 /* printUsage - prints command line syntax */
423 /*-----------------------------------------------------------------*/
430 "Usage : sdcc [options] filename\n"
434 printOptions(optionsTable);
436 for (i = 0; i < NUM_PORTS; i++)
438 if (_ports[i]->poptions != NULL)
440 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
441 printOptions (_ports[i]->poptions);
448 /*-----------------------------------------------------------------*/
449 /* parseWithComma - separates string with comma */
450 /*-----------------------------------------------------------------*/
452 parseWithComma (char **dest, char *src)
456 strtok (src, "\r\n \t");
457 /* skip the initial white spaces */
458 while (isspace (*src))
475 /*-----------------------------------------------------------------*/
476 /* setDefaultOptions - sets the default options */
477 /*-----------------------------------------------------------------*/
483 for (i = 0; i < 128; i++)
484 preArgv[i] = asmOptions[i] =
485 linkOptions[i] = relFiles[i] = libFiles[i] =
488 /* first the options part */
489 options.stack_loc = 0; /* stack pointer initialised to 0 */
490 options.xstack_loc = 0; /* xternal stack starts at 0 */
491 options.code_loc = 0; /* code starts at 0 */
492 options.data_loc = 0; /* JCF: By default let the linker locate data */
493 options.xdata_loc = 0;
494 options.idata_loc = 0x80;
496 options.model = port->general.default_model;
497 options.nostdlib = 0;
498 options.nostdinc = 0;
500 options.shortis8bits = 0;
502 options.stack10bit=0;
504 /* now for the optimizations */
505 /* turn on the everything */
506 optimize.global_cse = 1;
511 optimize.loopInvariant = 1;
512 optimize.loopInduction = 1;
514 /* now for the ports */
515 port->setDefaultOptions ();
518 /*-----------------------------------------------------------------*/
519 /* processFile - determines the type of file from the extension */
520 /*-----------------------------------------------------------------*/
522 processFile (char *s)
526 /* get the file extension */
527 fext = s + strlen (s);
528 while ((fext != s) && *fext != '.')
531 /* now if no '.' then we don't know what the file type is
532 so give a warning and return */
535 werror (W_UNKNOWN_FEXT, s);
539 /* otherwise depending on the file type */
540 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
542 /* source file name : not if we already have a
546 werror (W_TOO_MANY_SRC, s);
550 /* the only source file */
552 if (!(srcFile = fopen (fullSrcFileName, "r")))
554 werror (E_FILE_OPEN_ERR, s);
558 /* copy the file name into the buffer */
561 /* get rid of the "."-extension */
563 /* is there a dot at all? */
564 if (strrchr (buffer, '.') &&
565 /* is the dot in the filename, not in the path? */
566 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
568 *strrchr (buffer, '.') = '\0';
571 /* get rid of any path information
572 for the module name; */
573 fext = buffer + strlen (buffer);
575 /* do this by going backwards till we
576 get '\' or ':' or start of buffer */
577 while (fext != buffer &&
578 *(fext - 1) != DIR_SEPARATOR_CHAR &&
584 /* do this by going backwards till we
585 get '/' or start of buffer */
586 while (fext != buffer &&
587 *(fext - 1) != DIR_SEPARATOR_CHAR)
592 moduleName = Safe_strdup ( fext );
596 /* if the extention is type .rel or .r or .REL or .R
597 addtional object file will be passed to the linker */
598 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
599 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
600 strcmp (fext, port->linker.rel_ext) == 0)
602 relFiles[nrelFiles++] = s;
606 /* if .lib or .LIB */
607 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
609 libFiles[nlibFiles++] = s;
613 werror (W_UNKNOWN_FEXT, s);
618 _setModel (int model, const char *sz)
620 if (port->general.supported_models & model)
621 options.model = model;
623 werror (W_UNSUPPORTED_MODEL, sz, port->target);
626 /** Gets the string argument to this option. If the option is '--opt'
627 then for input of '--optxyz' or '--opt xyz' returns xyz.
630 getStringArg(const char *szStart, char **argv, int *pi, int argc)
632 if (argv[*pi][strlen(szStart)])
634 return &argv[*pi][strlen(szStart)];
641 werror (E_ARGUMENT_MISSING, szStart);
642 /* Die here rather than checking for errors later. */
652 /** Gets the integer argument to this option using the same rules as
656 getIntArg(const char *szStart, char **argv, int *pi, int argc)
658 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
662 verifyShortOption(const char *opt)
664 if (strlen(opt) != 2)
666 werror (W_EXCESS_SHORT_OPTIONS, opt);
671 tryHandleUnsupportedOpt(char **argv, int *pi)
673 if (argv[*pi][0] == '-')
675 const char *longOpt = "";
679 if (argv[*pi][1] == '-')
686 shortOpt = argv[*pi][1];
688 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
690 if (unsupportedOptTable[i].shortOpt == shortOpt ||
691 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
692 // Found an unsupported opt.
694 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
695 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
699 // Didn't find in the table
704 // Not an option, so can't be unsupported :)
710 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
713 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
715 if (optionsTable[i].shortOpt == shortOpt ||
716 (longOpt && optionsTable[i].longOpt &&
717 strcmp(optionsTable[i].longOpt, longOpt) == 0))
720 // If it is a flag then we can handle it here
721 if (optionsTable[i].pparameter != NULL)
723 if (optionsTable[i].shortOpt == shortOpt)
725 verifyShortOption(argv[*pi]);
728 (*optionsTable[i].pparameter)++;
732 // Not a flag. Handled manually later.
737 // Didn't find in the table
742 tryHandleSimpleOpt(char **argv, int *pi)
744 if (argv[*pi][0] == '-')
746 const char *longOpt = "";
749 if (argv[*pi][1] == '-')
756 shortOpt = argv[*pi][1];
759 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
763 else if (port && port->poptions &&
764 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
775 // Not an option, so can't be handled.
780 /*-----------------------------------------------------------------*/
781 /* parseCmdLine - parses the command line and sets the options */
782 /*-----------------------------------------------------------------*/
784 parseCmdLine (int argc, char **argv)
788 /* go thru all whole command line */
789 for (i = 1; i < argc; i++)
794 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
799 if (tryHandleSimpleOpt(argv, &i) == TRUE)
805 if (argv[i][0] == '-' && argv[i][1] == '-')
807 if (strcmp (argv[i], OPTION_HELP) == 0)
813 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
815 options.stack10bit = 0;
819 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
825 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
827 _setModel (MODEL_LARGE, argv[i]);
831 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
833 _setModel (MODEL_MEDIUM, argv[i]);
837 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
839 _setModel (MODEL_SMALL, argv[i]);
843 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
845 _setModel (MODEL_FLAT24, argv[i]);
849 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
851 options.dump_rassgn =
857 options.dump_raw = 1;
861 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
863 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
867 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
869 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
873 if (strcmp (argv[i], OPTION_VERSION) == 0)
880 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
882 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
886 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
888 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
892 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
894 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
898 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
900 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
904 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
906 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
910 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
912 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
913 options.xram_size_set = TRUE;
917 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
919 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
923 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
925 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
929 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
931 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
935 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
937 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
941 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
943 optimize.global_cse = 0;
947 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
949 optimize.loopInvariant = 0;
953 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
955 optimize.loopInduction = 0;
959 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
961 options.lessPedantic = 1;
962 setErrorLogLevel(ERROR_LEVEL_WARNING);
966 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
968 options.shortis8bits=1;
972 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
974 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
978 if (!port->parseOption (&argc, argv, &i))
980 werror (W_UNKNOWN_OPTION, argv[i]);
988 /* if preceded by '-' then option */
994 verifyShortOption(argv[i]);
1001 /* Used to select the port. But this has already been done. */
1005 /* Used to select the processor in port. But this has
1006 * already been done. */
1010 verifyShortOption(argv[i]);
1012 options.cc_only = 1;
1016 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
1020 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
1027 /* copy the file name into the buffer */
1028 strcpy (buffer, getStringArg("-o", argv, &i, argc));
1029 /* point to last character */
1030 p = buffer + strlen (buffer) - 1;
1031 if (*p == DIR_SEPARATOR_CHAR)
1033 /* only output path specified */
1034 dstPath = Safe_strdup (buffer);
1035 fullDstFileName = NULL;
1039 fullDstFileName = Safe_strdup (buffer);
1041 /* get rid of the "."-extension */
1043 /* is there a dot at all? */
1044 if (strrchr (buffer, '.') &&
1045 /* is the dot in the filename, not in the path? */
1046 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1047 *strrchr (buffer, '.') = '\0';
1049 dstFileName = Safe_strdup (buffer);
1051 /* strip module name to get path */
1052 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1055 /* path with trailing / */
1057 dstPath = Safe_strdup (buffer);
1064 /* pre-processer options */
1065 if (argv[i][2] == 'p')
1067 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
1069 /* linker options */
1070 else if (argv[i][2] == 'l')
1072 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
1074 /* assembler options */
1075 else if (argv[i][2] == 'a')
1077 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
1081 werror (W_UNKNOWN_OPTION, argv[i]);
1086 verifyShortOption(argv[i]);
1088 printVersionInfo ();
1092 /* preprocessor options */
1096 addToList (preArgv, "-M");
1101 addToList (preArgv, "-C");
1110 char sOpt = argv[i][1];
1113 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1119 werror(E_ARGUMENT_MISSING, argv[i-1]);
1133 sprintf (buffer, "-%c%s", sOpt, rest);
1134 addToList (preArgv, buffer);
1139 if (!port->parseOption (&argc, argv, &i))
1140 werror (W_UNKNOWN_OPTION, argv[i]);
1145 if (!port->parseOption (&argc, argv, &i))
1147 /* no option must be a filename */
1148 processFile (argv[i]);
1152 /* if no dstFileName given with -o, we've to find one: */
1155 /* use the modulename from the C-source */
1156 if (fullSrcFileName)
1158 dstFileName = Safe_alloc (strlen (dstPath) + strlen (moduleName) + 1);
1159 strcpy (dstFileName, dstPath);
1160 strcat (dstFileName, moduleName);
1162 /* use the modulename from the first object file */
1163 else if (nrelFiles >= 1)
1167 strcpy (buffer, relFiles[0]);
1168 /* remove extension (it must be .rel) */
1169 *strrchr (buffer, '.') = '\0';
1171 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1178 objectName = buffer;
1180 dstFileName = Safe_alloc (strlen (dstPath) + strlen (objectName) + 1);
1181 strcpy (dstFileName, dstPath);
1182 strcat (dstFileName, objectName);
1184 /* else no module given: help text is displayed */
1187 /* set up external stack location if not explicitly specified */
1188 if (!options.xstack_loc)
1189 options.xstack_loc = options.xdata_loc;
1191 /* if debug option is set the open the cdbFile */
1192 if (options.debug && fullSrcFileName)
1194 sprintf (scratchFileName, "%s.adb", dstFileName); //JCF: Nov 30, 2002
1195 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1196 werror (E_FILE_OPEN_ERR, scratchFileName);
1199 /* add a module record */
1200 fprintf (cdbFile, "M:%s\n", moduleName);
1206 /*-----------------------------------------------------------------*/
1207 /* linkEdit : - calls the linkage editor with options */
1208 /*-----------------------------------------------------------------*/
1210 linkEdit (char **envp)
1216 /* first we need to create the <filename>.lnk file */
1217 sprintf (scratchFileName, "%s.lnk", dstFileName);
1218 if (!(lnkfile = fopen (scratchFileName, "w")))
1220 werror (E_FILE_OPEN_ERR, scratchFileName);
1224 /* now write the options. JCF: added option 'y' */
1225 fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1227 /* if iram size specified */
1228 if (options.iram_size)
1229 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1231 /* if xram size specified */
1232 if (options.xram_size_set)
1233 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1235 /* if code size specified */
1236 if (options.code_size)
1237 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1240 fprintf (lnkfile, "-z\n");
1242 #define WRITE_SEG_LOC(N, L) \
1243 segName = Safe_strdup(N); \
1244 c = strtok(segName, " \t"); \
1245 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1246 if (segName) { Safe_free(segName); }
1248 /* code segment start */
1249 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1251 /* data segment start */
1252 if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
1253 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1257 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1261 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1264 /* bit segment start */
1265 WRITE_SEG_LOC (BIT_NAME, 0);
1267 /* JCF: stack start */
1268 if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
1269 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1272 /* add the extra linker options */
1273 for (i = 0; linkOptions[i]; i++)
1274 fprintf (lnkfile, "%s\n", linkOptions[i]);
1276 /* other library paths if specified */
1277 for (i = 0; i < nlibPaths; i++)
1278 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1280 /* standard library path */
1281 if (!options.nostdlib)
1283 switch (options.model)
1299 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1303 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1305 /* standard library files */
1306 #if !OPT_DISABLE_DS390
1307 if (options.model == MODEL_FLAT24)
1309 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1313 #if !OPT_DISABLE_XA51
1315 if (options.model == MODEL_PAGE0)
1317 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1321 fprintf (lnkfile, "-l %s\n", STD_LIB);
1322 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1323 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1324 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1327 /* additional libraries if any */
1328 for (i = 0; i < nlibFiles; i++)
1329 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1331 /* put in the object files */
1332 if (fullSrcFileName)
1333 fprintf (lnkfile, "%s ", dstFileName);
1335 for (i = 0; i < nrelFiles; i++)
1336 fprintf (lnkfile, "%s\n", relFiles[i]);
1338 fprintf (lnkfile, "\n-e\n");
1341 if (options.verbose)
1342 printf ("sdcc: Calling linker...\n");
1344 /* build linker output filename */
1346 /* -o option overrides default name? */
1347 if (fullDstFileName)
1349 strcpy (scratchFileName, fullDstFileName);
1353 /* the linked file gets the name of the first modul */
1354 if (fullSrcFileName)
1356 strcpy (scratchFileName, dstFileName);
1360 strcpy (scratchFileName, relFiles[0]);
1361 /* strip ".rel" extension */
1362 *strrchr (scratchFileName, '.') = '\0';
1364 strcat (scratchFileName, options.out_fmt ? ".S19" : ".ihx");
1367 if (port->linker.cmd)
1369 char buffer2[PATH_MAX];
1370 buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, NULL);
1371 buildCmdLine2 (buffer, buffer2);
1375 buildCmdLine2 (buffer, port->linker.mcmd);
1378 system_ret = my_system (buffer);
1379 /* TODO: most linker don't have a -o parameter */
1380 /* -o option overrides default name? */
1381 if (fullDstFileName)
1384 /* the linked file gets the name of the first modul */
1385 if (fullSrcFileName)
1387 strcpy (scratchFileName, dstFileName);
1388 p = strlen (scratchFileName) + scratchFileName;
1392 strcpy (scratchFileName, relFiles[0]);
1393 /* strip "rel" extension */
1394 p = strrchr (scratchFileName, '.') + 1;
1396 strcpy (p, options.out_fmt ? "S19" : "ihx");
1397 rename (scratchFileName, fullDstFileName);
1399 q = strrchr (fullDstFileName, '.');
1402 /* point after the '.' of the extension */
1407 /* no extension: append new extensions */
1408 q = strlen (fullDstFileName) + fullDstFileName;
1412 rename (scratchFileName, fullDstFileName);
1415 rename (scratchFileName, fullDstFileName);
1423 /*-----------------------------------------------------------------*/
1424 /* assemble - spawns the assembler with arguments */
1425 /*-----------------------------------------------------------------*/
1427 assemble (char **envp)
1429 /* build assembler output filename */
1431 /* -o option overrides default name? */
1432 if (options.cc_only && fullDstFileName) {
1433 strcpy (scratchFileName, fullDstFileName);
1435 /* the assembled file gets the name of the first modul */
1436 strcpy (scratchFileName, dstFileName);
1437 strcat (scratchFileName, port->linker.rel_ext);
1440 if (port->assembler.do_assemble) {
1441 port->assembler.do_assemble(asmOptions);
1443 } else if (port->assembler.cmd) {
1444 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1445 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1448 buildCmdLine2 (buffer, port->assembler.mcmd);
1451 if (my_system (buffer)) {
1452 /* either system() or the assembler itself has reported an error
1453 perror ("Cannot exec assembler");
1457 /* TODO: most assembler don't have a -o parameter */
1458 /* -o option overrides default name? */
1459 if (options.cc_only && fullDstFileName) {
1460 strcpy (scratchFileName, dstFileName);
1461 strcat (scratchFileName, port->linker.rel_ext);
1462 rename (scratchFileName, fullDstFileName);
1466 /*-----------------------------------------------------------------*/
1467 /* preProcess - spawns the preprocessor with arguments */
1468 /*-----------------------------------------------------------------*/
1470 preProcess (char **envp)
1474 if (!options.c1mode)
1476 /* if using external stack define the macro */
1477 if (options.useXstack)
1478 addToList (preArgv, "-DSDCC_USE_XSTACK");
1480 /* set the macro for stack autos */
1481 if (options.stackAuto)
1482 addToList (preArgv, "-DSDCC_STACK_AUTO");
1484 /* set the macro for stack autos */
1485 if (options.stack10bit)
1486 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1488 /* set the macro for no overlay */
1489 if (options.noOverlay)
1490 addToList (preArgv, "-DSDCC_NOOVERLAY");
1492 /* set the macro for large model */
1493 switch (options.model)
1496 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1499 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1502 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1505 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1508 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1511 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1514 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1518 /* add port (processor information to processor */
1519 addToList (preArgv, "-DSDCC_{port}");
1520 addToList (preArgv, "-D__{port}");
1522 /* standard include path */
1523 if (!options.nostdinc) {
1524 addToList (preArgv, "-I{includedir}");
1527 setMainValue ("cppextraopts", join(preArgv));
1531 if (fullDstFileName)
1532 preOutName = Safe_strdup (fullDstFileName);
1535 preOutName = Safe_strdup (tempfilename ());
1537 /* Have to set cppoutfilename to something, even if just pre-processing. */
1538 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1540 if (options.verbose)
1541 printf ("sdcc: Calling preprocessor...\n");
1543 buildCmdLine2 (buffer, _preCmd);
1545 if (my_system (buffer))
1547 // @FIX: Dario Vecchio 03-05-2001
1550 unlink (preOutName);
1551 Safe_free (preOutName);
1564 preOutName = fullSrcFileName;
1567 yyin = fopen (preOutName, "r");
1570 perror ("Preproc file not found\n");
1578 _setPaths (const char *pprefix)
1581 Given the prefix and how the directories were layed out at
1582 configure time, see if the library and include directories are
1583 where expected. If so, set.
1585 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1586 strcpy (scratchFileName, pprefix);
1587 strcat (scratchFileName, buffer);
1589 if (pathExists (scratchFileName))
1591 setMainValue ("includedir", scratchFileName);
1598 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1599 strcpy (scratchFileName, pprefix);
1600 strcat (scratchFileName, buffer);
1602 if (pathExists (scratchFileName))
1604 setMainValue ("libdir", scratchFileName);
1615 _discoverPaths (const char *argv0)
1618 1. Try the SDCCDIR environment variable.
1619 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1620 and library paths with respect to that. Note that under win32
1621 argv[0] is always the full path to the program.
1622 3. If (1) and (2) fail, fall back to the compile time defaults.
1624 Detecting assumes the same layout as when configured. If the
1625 directories have been further moved about then discovery will
1629 /* Some input cases:
1630 "c:\fish\sdcc\bin\sdcc"
1632 "/home/fish/bin/sdcc"
1634 Note that ./sdcc is explicitly not supported as there isn't
1637 /* bindir is handled differently to the lib and include directories.
1638 It's rather unfortunate, but required due to the different
1639 install and development layouts. Logic is different as well.
1642 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1644 strcpy (scratchFileName, argv0);
1645 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1646 setMainValue ("bindir", scratchFileName);
1647 ExePathList[0] = Safe_strdup (scratchFileName);
1649 else if (getenv (SDCCDIR_NAME) != NULL)
1651 getPathDifference (buffer, PREFIX, BINDIR);
1652 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1653 strcat (scratchFileName, buffer);
1654 setMainValue ("bindir", scratchFileName);
1655 ExePathList[0] = Safe_strdup (scratchFileName);
1659 setMainValue ("bindir", BINDIR);
1660 ExePathList[0] = BINDIR;
1666 if (getenv (SDCCDIR_NAME) != NULL)
1668 if (_setPaths (getenv (SDCCDIR_NAME)))
1670 /* Successfully set. */
1675 /* Include and lib weren't where expected. */
1679 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1681 char *pbase = getPrefixFromBinPath (argv0);
1685 /* A bad path. Skip. */
1689 if (_setPaths (pbase))
1691 /* Successfully set. */
1696 /* Include and lib weren't where expected. */
1701 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1702 setMainValue ("libdir", SDCC_LIB_DIR);
1709 populateMainValues (_baseValues);
1710 setMainValue ("port", port->target);
1711 setMainValue ("objext", port->linker.rel_ext);
1712 setMainValue ("asmext", port->assembler.file_ext);
1714 setMainValue ("dstfilename", dstFileName);
1715 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1717 if (options.cc_only && fullDstFileName)
1718 /* compile + assemble and -o given: -o specifies name of object file */
1720 setMainValue ("objdstfilename", fullDstFileName);
1724 setMainValue ("objdstfilename", "{stdobjdstfilename}");
1726 if (fullDstFileName)
1727 /* if we're linking, -o gives the final file name */
1729 setMainValue ("linkdstfilename", fullDstFileName);
1733 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
1740 * initialises and calls the parser
1744 main (int argc, char **argv, char **envp)
1746 /* turn all optimizations off by default */
1747 memset (&optimize, 0, sizeof (struct optimize));
1749 /*printVersionInfo (); */
1752 fprintf (stderr, "Build error: no ports are enabled.\n");
1756 /* install atexit handler */
1757 atexit(rm_tmpfiles);
1759 /* Before parsing the command line options, do a
1760 * search for the port and processor and initialize
1761 * them if they're found. (We can't gurantee that these
1762 * will be the first options specified).
1765 _findPort (argc, argv);
1768 if (strcmp(port->target, "mcs51") == 0) {
1769 printf("DS390 jammed in A\n");
1775 _findProcessor (argc, argv);
1777 /* Initalise the port. */
1781 // Create a default exe search path from the path to the sdcc command
1784 setDefaultOptions ();
1787 options.model = MODEL_SMALL;
1788 options.stack10bit=0;
1791 parseCmdLine (argc, argv);
1793 /* if no input then printUsage & exit */
1794 if ((!options.c1mode && !fullSrcFileName && !nrelFiles) ||
1795 (options.c1mode && !fullSrcFileName))
1802 _discoverPaths (argv[0]);
1804 /* initMem() is expensive, but
1805 initMem() must called before port->finaliseOptions ().
1806 And the z80 port needs port->finaliseOptions(),
1807 even if we're only linking. */
1809 port->finaliseOptions ();
1811 if (fullSrcFileName)
1821 if (options.verbose)
1822 printf ("sdcc: Generating code...\n");
1827 // @FIX: Dario Vecchio 03-05-2001
1829 if (yyin && yyin != stdin)
1831 unlink (preOutName);
1832 Safe_free (preOutName);
1838 if (TARGET_IS_PIC) {
1839 /* TSD PIC port hack - if the PIC port option is enabled
1840 and SDCC is used to generate PIC code, then we will
1841 generate .asm files in gpasm's format instead of SDCC's
1844 #if !OPT_DISABLE_PIC
1852 if (!options.c1mode && !noAssemble)
1854 if (options.verbose)
1855 printf ("sdcc: Calling assembler...\n");
1865 if (yyin && yyin != stdin)
1868 if (preOutName && !options.c1mode)
1870 unlink (preOutName);
1871 Safe_free (preOutName);
1874 if (!options.cc_only &&
1878 (fullSrcFileName || nrelFiles))
1880 if (port->linker.do_link)
1881 port->linker.do_link ();