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"
41 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
46 /** Name of the environment variable checked for other instalations. */
47 #define SDCCDIR_NAME "SDCCDIR"
50 extern int yyparse ();
52 FILE *srcFile; /* source file */
53 FILE *cdbFile = NULL; /* debugger information output file */
54 char *fullSrcFileName; /* full name for the source file */
55 char *srcFileName; /* source file name with the .c stripped */
56 char *moduleName; /* module name is srcFilename stripped of any path */
57 const char *preArgv[128]; /* pre-processor arguments */
59 struct optimize optimize;
60 struct options options;
61 char *VersionString = SDCC_VERSION_STR;
64 char *linkOptions[128];
65 const char *asmOptions[128];
72 bool verboseExec = FALSE;
75 /* uncomment JAMIN_DS390 to always override and use ds390 port
76 for mcs51 work. This is temporary, for compatibility testing. */
77 /* #define JAMIN_DS390 */
82 // Globally accessible scratch buffer for file names.
83 char scratchFileName[PATH_MAX];
84 char buffer[PATH_MAX];
86 // In MSC VC6 default search path for exe's to path for this
88 char DefaultExePath[128];
90 #define OPTION_HELP "-help"
92 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
94 #define OPTION_STACK_8BIT "--stack-8bit"
95 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
96 #define OPTION_LARGE_MODEL "--model-large"
97 #define OPTION_MEDIUM_MODEL "--model-medium"
98 #define OPTION_SMALL_MODEL "--model-small"
99 #define OPTION_FLAT24_MODEL "--model-flat24"
100 #define OPTION_DUMP_ALL "--dumpall"
101 #define OPTION_PEEP_FILE "--peep-file"
102 #define OPTION_LIB_PATH "--lib-path"
103 #define OPTION_XSTACK_LOC "--xstack-loc"
104 #define OPTION_CALLEE_SAVES "--callee-saves"
105 #define OPTION_STACK_LOC "--stack-loc"
106 #define OPTION_XRAM_LOC "--xram-loc"
107 #define OPTION_IRAM_SIZE "--iram-size"
108 #define OPTION_VERSION "--version"
109 #define OPTION_DATA_LOC "--data-loc"
110 #define OPTION_CODE_LOC "--code-loc"
111 #define OPTION_IDATA_LOC "--idata-loc"
112 #define OPTION_NO_LOOP_INV "--noinvariant"
113 #define OPTION_NO_LOOP_IND "--noinduction"
114 #define OPTION_LESS_PEDANTIC "--lesspedantic"
115 #define OPTION_NO_GCSE "--nogcse"
116 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
117 #define OPTION_TINI_LIBID "--tini-libid"
121 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
122 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
123 { 'd', NULL, NULL, NULL },
124 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
125 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
126 { 'A', NULL, NULL, NULL },
127 { 'U', NULL, NULL, NULL },
128 { 'C', NULL, NULL, "Preprocessor option" },
129 { 'M', NULL, NULL, "Preprocessor option" },
130 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
131 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
132 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
133 { 'L', NULL, NULL, "Add the next field to the library search path" },
134 { 'l', NULL, NULL, "Include the given library in the link" },
135 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
136 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
137 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
138 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
139 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
140 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
141 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
142 { 0, "--xstack", &options.useXstack, "Use external stack" },
143 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
144 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
145 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
146 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
147 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
148 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
149 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
150 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
151 { 0, "--dumpgcse", &options.dump_gcse, NULL },
152 { 0, "--dumploop", &options.dump_loop, NULL },
153 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
154 { 0, "--dumpliverange", &options.dump_range, NULL },
155 { 0, "--dumpregpack", &options.dump_pack, NULL },
156 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
157 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
158 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
159 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
160 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
161 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
162 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
163 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
164 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
165 { 0, OPTION_IDATA_LOC, NULL, NULL },
166 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
167 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
168 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
169 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
170 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
171 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
172 { 0, "--cyclomatic", &options.cyclomatic, NULL },
173 { 0, "--nooverlay", &options.noOverlay, NULL },
174 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
175 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
176 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
177 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
178 { 0, "--peep-asm", &options.asmpeep, NULL },
179 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
180 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
181 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
182 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
183 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
184 { 0, "--help", NULL, "Display this help" },
185 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
186 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
187 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
188 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
189 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
190 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
191 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
192 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
193 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
194 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
195 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
196 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
197 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
198 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
203 /** Table of all unsupported options and help text to display when one
207 /** shortOpt as in OPTIONS. */
209 /** longOpt as in OPTIONS. */
211 /** Message to display inside W_UNSUPPORTED_OPT when this option
216 static const UNSUPPORTEDOPT
217 unsupportedOptTable[] = {
218 { 'a', NULL, "use --stack-auto instead." },
219 { 'g', NULL, "use --generic instead" },
220 { 'X', NULL, "use --xstack-loc instead" },
221 { 'x', NULL, "use --xstack instead" },
222 { 'i', NULL, "use --idata-loc instead" },
223 { 'r', NULL, "use --xdata-loc instead" },
224 { 's', NULL, "use --code-loc instead" },
225 { 'Y', NULL, "use -I instead" }
228 /** List of all default constant macros.
230 static const char *_baseValues[] = {
231 "cpp", "{bindir}{sep}sdcpp",
233 /* Path seperator character */
234 "sep", DIR_SEPARATOR_STRING,
238 static const char *_preCmd = "{cpp} -nostdinc -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
242 static PORT *_ports[] =
244 #if !OPT_DISABLE_MCS51
247 #if !OPT_DISABLE_GBZ80
256 #if !OPT_DISABLE_DS390
262 #if !OPT_DISABLE_TININative
265 #if !OPT_DISABLE_XA51
270 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
273 extern void picglue ();
276 /** Sets the port to the one given by the command line option.
277 @param The name minus the option (eg 'mcs51')
278 @return 0 on success.
281 _setPort (const char *name)
284 for (i = 0; i < NUM_PORTS; i++)
286 if (!strcmp (_ports[i]->target, name))
292 /* Error - didnt find */
293 werror (E_UNKNOWN_TARGET, name);
297 /* Override the default processor with the one specified
298 * on the command line */
300 _setProcessor (char *_processor)
302 port->processor = _processor;
303 fprintf(stderr,"Processor: %s\n",_processor);
307 _validatePorts (void)
310 for (i = 0; i < NUM_PORTS; i++)
312 if (_ports[i]->magic != PORT_MAGIC)
314 /* Uncomment this line to debug which port is causing the problem
315 * (the target name is close to the beginning of the port struct
316 * and probably can be accessed just fine). */
317 fprintf(stderr,"%s :",_ports[i]->target);
318 wassertl (0, "Port definition structure is incomplete");
323 /* search through the command line options for the port */
325 _findPort (int argc, char **argv)
331 if (!strncmp (*argv, "-m", 2))
333 _setPort (*argv + 2);
338 /* Use the first in the list */
342 /* search through the command line options for the processor */
344 _findProcessor (int argc, char **argv)
348 if (!strncmp (*argv, "-p", 2))
350 _setProcessor (*argv + 2);
356 /* no error if processor was not specified. */
359 /*-----------------------------------------------------------------*/
360 /* printVersionInfo - prints the version info */
361 /*-----------------------------------------------------------------*/
369 for (i = 0; i < NUM_PORTS; i++)
370 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
372 fprintf (stderr, " %s"
373 #ifdef SDCC_SUB_VERSION_STR
374 "/" SDCC_SUB_VERSION_STR
383 #if defined(_MSC_VER)
396 printOptions(const OPTION *optionsTable)
399 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
401 fprintf(stdout, " %c%c %-20s %s\n",
402 optionsTable[i].shortOpt !=0 ? '-' : ' ',
403 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
404 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
405 optionsTable[i].help != NULL ? optionsTable[i].help : ""
410 /*-----------------------------------------------------------------*/
411 /* printUsage - prints command line syntax */
412 /*-----------------------------------------------------------------*/
419 "Usage : sdcc [options] filename\n"
423 printOptions(optionsTable);
425 for (i = 0; i < NUM_PORTS; i++)
427 if (_ports[i]->poptions != NULL)
429 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
430 printOptions (_ports[i]->poptions);
437 /*-----------------------------------------------------------------*/
438 /* parseWithComma - separates string with comma */
439 /*-----------------------------------------------------------------*/
441 parseWithComma (char **dest, char *src)
445 strtok (src, "\r\n \t");
446 /* skip the initial white spaces */
447 while (isspace (*src))
464 /*-----------------------------------------------------------------*/
465 /* setDefaultOptions - sets the default options */
466 /*-----------------------------------------------------------------*/
472 for (i = 0; i < 128; i++)
473 preArgv[i] = asmOptions[i] =
474 linkOptions[i] = relFiles[i] = libFiles[i] =
477 /* first the options part */
478 options.stack_loc = 0; /* stack pointer initialised to 0 */
479 options.xstack_loc = 0; /* xternal stack starts at 0 */
480 options.code_loc = 0; /* code starts at 0 */
481 options.data_loc = 0x0030; /* data starts at 0x0030 */
482 options.xdata_loc = 0;
483 options.idata_loc = 0x80;
484 options.genericPtr = 1; /* default on */
486 options.model = port->general.default_model;
487 options.nostdlib = 0;
488 options.nostdinc = 0;
490 options.shortis8bits = 0;
492 options.stack10bit=0;
494 /* now for the optimizations */
495 /* turn on the everything */
496 optimize.global_cse = 1;
501 optimize.loopInvariant = 1;
502 optimize.loopInduction = 1;
504 /* now for the ports */
505 port->setDefaultOptions ();
508 /*-----------------------------------------------------------------*/
509 /* processFile - determines the type of file from the extension */
510 /*-----------------------------------------------------------------*/
512 processFile (char *s)
516 /* get the file extension */
517 fext = s + strlen (s);
518 while ((fext != s) && *fext != '.')
521 /* now if no '.' then we don't know what the file type is
522 so give a warning and return */
525 werror (W_UNKNOWN_FEXT, s);
529 /* otherwise depending on the file type */
530 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
532 /* source file name : not if we already have a
536 werror (W_TOO_MANY_SRC, s);
540 /* the only source file */
541 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
543 werror (E_FILE_OPEN_ERR, s);
547 /* copy the file name into the buffer */
550 /* get rid of the "."-extension */
552 /* is there a dot at all? */
553 if (strchr (buffer, '.') &&
554 /* is the dot in the filename, not in the path? */
555 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
556 strrchr (buffer, '\\') < strrchr (buffer, '.')))
557 *strrchr (buffer, '.') = '\0';
559 srcFileName = Safe_alloc ( strlen (buffer) + 1);
560 strcpy (srcFileName, buffer);
562 /* get rid of any path information
563 for the module name; do this by going
564 backwards till we get to either '/' or '\' or ':'
565 or start of buffer */
566 fext = buffer + strlen (buffer);
567 while (fext != buffer &&
568 *(fext - 1) != '\\' &&
569 *(fext - 1) != '/' &&
572 moduleName = Safe_alloc ( strlen (fext) + 1);
573 strcpy (moduleName, fext);
578 /* if the extention is type .rel or .r or .REL or .R
579 addtional object file will be passed to the linker */
580 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
581 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
582 strcmp (fext, port->linker.rel_ext) == 0)
584 relFiles[nrelFiles++] = s;
588 /* if .lib or .LIB */
589 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
591 libFiles[nlibFiles++] = s;
595 werror (W_UNKNOWN_FEXT, s);
600 _processC1Arg (char *s)
604 if (options.out_name)
606 werror (W_TOO_MANY_SRC, s);
609 options.out_name = Safe_strdup (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_DATA_LOC) == 0)
912 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
916 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
918 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
922 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
924 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
928 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
930 optimize.global_cse = 0;
934 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
936 optimize.loopInvariant = 0;
940 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
942 optimize.loopInduction = 0;
946 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
948 options.lessPedantic = 1;
949 setErrorLogLevel(ERROR_LEVEL_WARNING);
953 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
955 options.shortis8bits=1;
959 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
961 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
965 if (!port->parseOption (&argc, argv, &i))
967 werror (W_UNKNOWN_OPTION, argv[i]);
975 /* if preceded by '-' then option */
981 verifyShortOption(argv[i]);
988 /* Used to select the port. But this has already been done. */
992 /* Used to select the processor in port. But this has
993 * already been done. */
997 verifyShortOption(argv[i]);
1003 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
1007 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
1011 /* pre-processer options */
1012 if (argv[i][2] == 'p')
1014 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
1016 /* linker options */
1017 else if (argv[i][2] == 'l')
1019 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
1021 /* assembler options */
1022 else if (argv[i][2] == 'a')
1024 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
1028 werror (W_UNKNOWN_OPTION, argv[i]);
1033 verifyShortOption(argv[i]);
1035 printVersionInfo ();
1039 /* preprocessor options */
1043 addToList (preArgv, "-M");
1048 addToList (preArgv, "-C");
1057 char sOpt = argv[i][1];
1060 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1066 werror(E_ARGUMENT_MISSING, argv[i-1]);
1080 sprintf (buffer, "-%c%s", sOpt, rest);
1081 addToList (preArgv, buffer);
1086 if (!port->parseOption (&argc, argv, &i))
1087 werror (W_UNKNOWN_OPTION, argv[i]);
1092 if (!port->parseOption (&argc, argv, &i))
1094 /* no option must be a filename */
1096 _processC1Arg (argv[i]);
1098 processFile (argv[i]);
1102 /* set up external stack location if not explicitly specified */
1103 if (!options.xstack_loc)
1104 options.xstack_loc = options.xdata_loc;
1106 /* if debug option is set the open the cdbFile */
1107 if (options.debug && srcFileName)
1109 sprintf (scratchFileName, "%s.cdb", srcFileName);
1110 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1111 werror (E_FILE_OPEN_ERR, scratchFileName);
1114 /* add a module record */
1115 fprintf (cdbFile, "M:%s\n", moduleName);
1121 /*-----------------------------------------------------------------*/
1122 /* linkEdit : - calls the linkage editor with options */
1123 /*-----------------------------------------------------------------*/
1125 linkEdit (char **envp)
1132 srcFileName = "temp";
1134 /* first we need to create the <filename>.lnk file */
1135 sprintf (scratchFileName, "%s.lnk", srcFileName);
1136 if (!(lnkfile = fopen (scratchFileName, "w")))
1138 werror (E_FILE_OPEN_ERR, scratchFileName);
1142 /* now write the options */
1143 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1145 /* if iram size specified */
1146 if (options.iram_size)
1147 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1150 fprintf (lnkfile, "-z\n");
1152 #define WRITE_SEG_LOC(N, L) \
1153 segName = Safe_strdup(N); \
1154 c = strtok(segName, " \t"); \
1155 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1156 if (segName) { Safe_free(segName); }
1158 /* code segment start */
1159 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1161 /* data segment start */
1162 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1165 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1169 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1172 /* bit segment start */
1173 WRITE_SEG_LOC (BIT_NAME, 0);
1175 /* add the extra linker options */
1176 for (i = 0; linkOptions[i]; i++)
1177 fprintf (lnkfile, "%s\n", linkOptions[i]);
1179 /* other library paths if specified */
1180 for (i = 0; i < nlibPaths; i++)
1181 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1183 /* standard library path */
1184 if (!options.nostdlib)
1186 switch (options.model)
1202 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1206 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1208 /* standard library files */
1209 #if !OPT_DISABLE_DS390
1210 if (options.model == MODEL_FLAT24)
1212 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1216 #if !OPT_DISABLE_XA51
1218 if (options.model == MODEL_PAGE0)
1220 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1224 fprintf (lnkfile, "-l %s\n", STD_LIB);
1225 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1226 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1227 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1230 /* additional libraries if any */
1231 for (i = 0; i < nlibFiles; i++)
1232 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1234 /* put in the object files */
1235 if (strcmp (srcFileName, "temp"))
1236 fprintf (lnkfile, "%s ", srcFileName);
1238 for (i = 0; i < nrelFiles; i++)
1239 fprintf (lnkfile, "%s\n", relFiles[i]);
1241 fprintf (lnkfile, "\n-e\n");
1244 if (options.verbose)
1245 printf ("sdcc: Calling linker...\n");
1247 if (port->linker.cmd)
1249 char buffer2[PATH_MAX];
1250 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1251 buildCmdLine2 (buffer, buffer2);
1255 buildCmdLine2 (buffer, port->linker.mcmd);
1258 if (my_system (buffer))
1263 if (strcmp (srcFileName, "temp") == 0)
1265 /* rename "temp.cdb" to "firstRelFile.cdb" */
1266 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1267 f = strcat (f, ".cdb");
1268 rename ("temp.cdb", f);
1273 /*-----------------------------------------------------------------*/
1274 /* assemble - spawns the assembler with arguments */
1275 /*-----------------------------------------------------------------*/
1277 assemble (char **envp)
1279 if (port->assembler.do_assemble) {
1280 port->assembler.do_assemble(asmOptions);
1282 } else if (port->assembler.cmd) {
1283 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1284 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1287 buildCmdLine2 (buffer, port->assembler.mcmd);
1290 if (my_system (buffer)) {
1291 /* either system() or the assembler itself has reported an error
1292 perror ("Cannot exec assembler");
1298 /*-----------------------------------------------------------------*/
1299 /* preProcess - spawns the preprocessor with arguments */
1300 /*-----------------------------------------------------------------*/
1302 preProcess (char **envp)
1306 if (!options.c1mode)
1308 /* if using external stack define the macro */
1309 if (options.useXstack)
1310 addToList (preArgv, "-DSDCC_USE_XSTACK");
1312 /* set the macro for stack autos */
1313 if (options.stackAuto)
1314 addToList (preArgv, "-DSDCC_STACK_AUTO");
1316 /* set the macro for stack autos */
1317 if (options.stack10bit)
1318 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1320 /* set the macro for no overlay */
1321 if (options.noOverlay)
1322 addToList (preArgv, "-DSDCC_NOOVERLAY");
1324 /* set the macro for large model */
1325 switch (options.model)
1328 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1331 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1334 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1337 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1340 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1343 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1346 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1350 /* add port (processor information to processor */
1351 addToList (preArgv, "-DSDCC_{port}");
1352 addToList (preArgv, "-D__{port}");
1354 /* standard include path */
1355 if (!options.nostdinc) {
1356 addToList (preArgv, "-I{includedir}");
1359 setMainValue ("cppextraopts", join(preArgv));
1362 preOutName = Safe_strdup (tempfilename ());
1364 /* Have to set cppoutfilename to something, even if just pre-processing. */
1365 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1367 if (options.verbose)
1368 printf ("sdcc: Calling preprocessor...\n");
1370 buildCmdLine2 (buffer, _preCmd);
1372 if (my_system (buffer))
1374 // @FIX: Dario Vecchio 03-05-2001
1377 unlink (preOutName);
1378 Safe_free (preOutName);
1391 preOutName = fullSrcFileName;
1394 yyin = fopen (preOutName, "r");
1397 perror ("Preproc file not found\n");
1405 _setPaths (const char *pprefix)
1408 Given the prefix and how the directories were layed out at
1409 configure time, see if the library and include directories are
1410 where expected. If so, set.
1412 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1413 strcpy (scratchFileName, pprefix);
1414 strcat (scratchFileName, buffer);
1416 if (pathExists (scratchFileName))
1418 setMainValue ("includedir", scratchFileName);
1425 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1426 strcpy (scratchFileName, pprefix);
1427 strcat (scratchFileName, buffer);
1429 if (pathExists (scratchFileName))
1431 setMainValue ("libdir", scratchFileName);
1442 _discoverPaths (const char *argv0)
1445 1. Try the SDCCDIR environment variable.
1446 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1447 and library paths with respect to that. Note that under win32
1448 argv[0] is always the full path to the program.
1449 3. If (1) and (2) fail, fall back to the compile time defaults.
1451 Detecting assumes the same layout as when configured. If the
1452 directories have been further moved about then discovery will
1456 /* Some input cases:
1457 "c:\fish\sdcc\bin\sdcc"
1459 "/home/fish/bin/sdcc"
1461 Note that ./sdcc is explicitly not supported as there isn't
1464 /* bindir is handled differently to the lib and include directories.
1465 It's rather unfortunate, but required due to the different
1466 install and development layouts. Logic is different as well.
1469 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1471 strcpy (scratchFileName, argv0);
1472 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1473 setMainValue ("bindir", scratchFileName);
1474 ExePathList[0] = Safe_strdup (scratchFileName);
1476 else if (getenv (SDCCDIR_NAME) != NULL)
1478 getPathDifference (buffer, PREFIX, BINDIR);
1479 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1480 strcat (scratchFileName, buffer);
1481 setMainValue ("bindir", scratchFileName);
1482 ExePathList[0] = Safe_strdup (scratchFileName);
1486 setMainValue ("bindir", BINDIR);
1487 ExePathList[0] = BINDIR;
1493 if (getenv (SDCCDIR_NAME) != NULL)
1495 if (_setPaths (getenv (SDCCDIR_NAME)))
1497 /* Successfully set. */
1502 /* Include and lib weren't where expected. */
1506 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1508 char *pbase = getPrefixFromBinPath (argv0);
1512 /* A bad path. Skip. */
1516 if (_setPaths (pbase))
1518 /* Successfully set. */
1523 /* Include and lib weren't where expected. */
1528 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1529 setMainValue ("libdir", SDCC_LIB_DIR);
1536 populateMainValues (_baseValues);
1537 setMainValue ("port", port->target);
1538 setMainValue ("objext", port->linker.rel_ext);
1539 setMainValue ("asmext", port->assembler.file_ext);
1541 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1542 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1547 * initialises and calls the parser
1551 main (int argc, char **argv, char **envp)
1553 /* turn all optimizations off by default */
1554 memset (&optimize, 0, sizeof (struct optimize));
1556 /*printVersionInfo (); */
1559 fprintf (stderr, "Build error: no ports are enabled.\n");
1563 /* Before parsing the command line options, do a
1564 * search for the port and processor and initialize
1565 * them if they're found. (We can't gurantee that these
1566 * will be the first options specified).
1569 _findPort (argc, argv);
1572 if (strcmp(port->target, "mcs51") == 0) {
1573 printf("DS390 jammed in A\n");
1579 _findProcessor (argc, argv);
1581 /* Initalise the port. */
1585 // Create a default exe search path from the path to the sdcc command
1588 setDefaultOptions ();
1591 options.model = MODEL_SMALL;
1592 options.stack10bit=0;
1595 parseCmdLine (argc, argv);
1597 /* if no input then printUsage & exit */
1598 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1599 (options.c1mode && !srcFileName && !options.out_name))
1606 _discoverPaths (argv[0]);
1613 port->finaliseOptions ();
1622 if (options.verbose)
1623 printf ("sdcc: Generating code...\n");
1629 if (TARGET_IS_PIC) {
1630 /* TSD PIC port hack - if the PIC port option is enabled
1631 and SDCC is used to generate PIC code, then we will
1632 generate .asm files in gpasm's format instead of SDCC's
1635 #if !OPT_DISABLE_PIC
1644 // @FIX: Dario Vecchio 03-05-2001
1647 if (yyin && yyin != stdin)
1649 unlink (preOutName);
1650 Safe_free (preOutName);
1655 if (!options.c1mode && !noAssemble)
1657 if (options.verbose)
1658 printf ("sdcc: Calling assembler...\n");
1664 // @FIX: Dario Vecchio 03-05-2001
1667 if (yyin && yyin != stdin)
1669 unlink (preOutName);
1670 Safe_free (preOutName);
1673 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1686 if (yyin && yyin != stdin)
1689 if (preOutName && !options.c1mode)
1691 unlink (preOutName);
1692 Safe_free (preOutName);
1695 if (!options.cc_only &&
1699 (srcFileName || nrelFiles))
1701 if (port->linker.do_link)
1702 port->linker.do_link ();