1 /*-------------------------------------------------------------------------
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
31 #include "SDCCmacro.h"
40 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 /** Name of the environment variable checked for other instalations. */
46 #define SDCCDIR_NAME "SDCCDIR"
49 extern int yyparse ();
51 FILE *srcFile; /* source file */
52 FILE *cdbFile = NULL; /* debugger information output file */
53 char *fullSrcFileName; /* full name for the source file */
54 char *srcFileName; /* source file name with the .c stripped */
55 char *moduleName; /* module name is srcFilename stripped of any path */
56 const char *preArgv[128]; /* pre-processor arguments */
58 struct optimize optimize;
59 struct options options;
60 char *VersionString = SDCC_VERSION_STR;
63 char *linkOptions[128];
64 const char *asmOptions[128];
71 bool verboseExec = FALSE;
74 /* uncomment JAMIN_DS390 to always override and use ds390 port
75 for mcs51 work. This is temporary, for compatibility testing. */
76 /* #define JAMIN_DS390 */
81 // Globally accessible scratch buffer for file names.
82 char scratchFileName[PATH_MAX];
83 char buffer[PATH_MAX];
85 // In MSC VC6 default search path for exe's to path for this
87 char DefaultExePath[128];
89 #define OPTION_HELP "-help"
91 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
93 #define OPTION_STACK_8BIT "--stack-8bit"
94 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
95 #define OPTION_LARGE_MODEL "--model-large"
96 #define OPTION_MEDIUM_MODEL "--model-medium"
97 #define OPTION_SMALL_MODEL "--model-small"
98 #define OPTION_FLAT24_MODEL "--model-flat24"
99 #define OPTION_DUMP_ALL "--dumpall"
100 #define OPTION_PEEP_FILE "--peep-file"
101 #define OPTION_LIB_PATH "--lib-path"
102 #define OPTION_XSTACK_LOC "--xstack-loc"
103 #define OPTION_CALLEE_SAVES "--callee-saves"
104 #define OPTION_STACK_LOC "--stack-loc"
105 #define OPTION_XRAM_LOC "--xram-loc"
106 #define OPTION_IRAM_SIZE "--iram-size"
107 #define OPTION_VERSION "--version"
108 #define OPTION_DATA_LOC "--data-loc"
109 #define OPTION_CODE_LOC "--code-loc"
110 #define OPTION_IDATA_LOC "--idata-loc"
111 #define OPTION_NO_LOOP_INV "--noinvariant"
112 #define OPTION_NO_LOOP_IND "--noinduction"
113 #define OPTION_LESS_PEDANTIC "--lesspedantic"
114 #define OPTION_NO_GCSE "--nogcse"
115 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
116 #define OPTION_TINI_LIBID "--tini-libid"
118 /** Table of all options supported by all ports.
120 * A reference for all options.
121 * An easy way to maintain help for the options.
122 * Automatic support for setting flags on simple options.
125 /** The short option character e.g. 'h' for -h. 0 for none. */
127 /** Long option e.g. "--help". Includes the -- prefix. NULL for
130 /** Pointer to an int that will be incremented every time the
131 option is encountered. May be NULL.
134 /** Help text to go with this option. May be NULL. */
140 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
141 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
142 { 'd', NULL, NULL, NULL },
143 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
144 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
145 { 'A', NULL, NULL, NULL },
146 { 'U', NULL, NULL, NULL },
147 { 'C', NULL, NULL, "Preprocessor option" },
148 { 'M', NULL, NULL, "Preprocessor option" },
149 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
150 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
151 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
152 { 'L', NULL, NULL, "Add the next field to the library search path" },
153 { 'l', NULL, NULL, "Include the given library in the link" },
154 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
155 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
156 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
157 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
158 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
159 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
160 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
161 { 0, "--xstack", &options.useXstack, "Use external stack" },
162 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
163 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
164 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
165 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
166 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
167 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
168 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
169 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
170 { 0, "--dumpgcse", &options.dump_gcse, NULL },
171 { 0, "--dumploop", &options.dump_loop, NULL },
172 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
173 { 0, "--dumpliverange", &options.dump_range, NULL },
174 { 0, "--dumpregpack", &options.dump_pack, NULL },
175 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
176 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
177 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
178 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
179 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
180 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
181 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
182 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
183 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
184 { 0, OPTION_IDATA_LOC, NULL, NULL },
185 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
186 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
187 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
188 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
189 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
190 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
191 { 0, "--cyclomatic", &options.cyclomatic, NULL },
192 { 0, "--nooverlay", &options.noOverlay, NULL },
193 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
194 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
195 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
196 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
197 { 0, "--peep-asm", &options.asmpeep, NULL },
198 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
199 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
200 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
201 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
202 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
203 { 0, "--help", NULL, "Display this help" },
204 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
205 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
206 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
207 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
208 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
209 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
210 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
211 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
212 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
213 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
214 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
215 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
216 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
217 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"}
220 /** Table of all unsupported options and help text to display when one
224 /** shortOpt as in OPTIONS. */
226 /** longOpt as in OPTIONS. */
228 /** Message to display inside W_UNSUPPORTED_OPT when this option
233 static const UNSUPPORTEDOPT
234 unsupportedOptTable[] = {
235 { 'a', NULL, "use --stack-auto instead." },
236 { 'g', NULL, "use --generic instead" },
237 { 'X', NULL, "use --xstack-loc instead" },
238 { 'x', NULL, "use --xstack instead" },
239 { 'i', NULL, "use --idata-loc instead" },
240 { 'r', NULL, "use --xdata-loc instead" },
241 { 's', NULL, "use --code-loc instead" },
242 { 'Y', NULL, "use -I instead" }
245 /** List of all default constant macros.
247 static const char *_baseValues[] = {
248 "cpp", "{bindir}{sep}sdcpp",
250 /* Path seperator character */
251 "sep", DIR_SEPARATOR_STRING,
255 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
259 static PORT *_ports[] =
261 #if !OPT_DISABLE_MCS51
264 #if !OPT_DISABLE_GBZ80
273 #if !OPT_DISABLE_DS390
279 #if !OPT_DISABLE_I186
282 #if !OPT_DISABLE_TLCS900H
285 #if !OPT_DISABLE_TININative
288 #if !OPT_DISABLE_XA51
293 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
296 extern void picglue ();
299 /** Sets the port to the one given by the command line option.
300 @param The name minus the option (eg 'mcs51')
301 @return 0 on success.
304 _setPort (const char *name)
307 for (i = 0; i < NUM_PORTS; i++)
309 if (!strcmp (_ports[i]->target, name))
315 /* Error - didnt find */
316 werror (E_UNKNOWN_TARGET, name);
321 _validatePorts (void)
324 for (i = 0; i < NUM_PORTS; i++)
326 if (_ports[i]->magic != PORT_MAGIC)
328 /* Uncomment this line to debug which port is causing the problem
329 * (the target name is close to the beginning of the port struct
330 * and probably can be accessed just fine). */
331 fprintf(stderr,"%s :",_ports[i]->target);
332 wassertl (0, "Port definition structure is incomplete");
337 /* search through the command line options for the port */
339 _findPort (int argc, char **argv)
345 if (!strncmp (*argv, "-m", 2))
347 _setPort (*argv + 2);
352 /* Use the first in the list */
356 /*-----------------------------------------------------------------*/
357 /* printVersionInfo - prints the version info */
358 /*-----------------------------------------------------------------*/
366 for (i = 0; i < NUM_PORTS; i++)
367 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
369 fprintf (stderr, " %s"
370 #ifdef SDCC_SUB_VERSION_STR
371 "/" SDCC_SUB_VERSION_STR
380 #if defined(_MSC_VER)
392 /*-----------------------------------------------------------------*/
393 /* printUsage - prints command line syntax */
394 /*-----------------------------------------------------------------*/
401 "Usage : sdcc [options] filename\n"
405 for (i = 0; i < LENGTH(optionsTable); i++) {
406 fprintf(stdout, " %c%c %-20s %s\n",
407 optionsTable[i].shortOpt !=0 ? '-' : ' ',
408 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
409 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
410 optionsTable[i].help != NULL ? optionsTable[i].help : ""
416 /*-----------------------------------------------------------------*/
417 /* parseWithComma - separates string with comma */
418 /*-----------------------------------------------------------------*/
420 parseWithComma (char **dest, char *src)
424 strtok (src, "\r\n \t");
425 /* skip the initial white spaces */
426 while (isspace (*src))
443 /*-----------------------------------------------------------------*/
444 /* setDefaultOptions - sets the default options */
445 /*-----------------------------------------------------------------*/
451 for (i = 0; i < 128; i++)
452 preArgv[i] = asmOptions[i] =
453 linkOptions[i] = relFiles[i] = libFiles[i] =
456 /* first the options part */
457 options.stack_loc = 0; /* stack pointer initialised to 0 */
458 options.xstack_loc = 0; /* xternal stack starts at 0 */
459 options.code_loc = 0; /* code starts at 0 */
460 options.data_loc = 0x0030; /* data starts at 0x0030 */
461 options.xdata_loc = 0;
462 options.idata_loc = 0x80;
463 options.genericPtr = 1; /* default on */
465 options.model = port->general.default_model;
466 options.nostdlib = 0;
467 options.nostdinc = 0;
469 options.shortis8bits = 0;
471 options.stack10bit=0;
473 /* now for the optimizations */
474 /* turn on the everything */
475 optimize.global_cse = 1;
480 optimize.loopInvariant = 1;
481 optimize.loopInduction = 1;
483 /* now for the ports */
484 port->setDefaultOptions ();
487 /*-----------------------------------------------------------------*/
488 /* processFile - determines the type of file from the extension */
489 /*-----------------------------------------------------------------*/
491 processFile (char *s)
495 /* get the file extension */
496 fext = s + strlen (s);
497 while ((fext != s) && *fext != '.')
500 /* now if no '.' then we don't know what the file type is
501 so give a warning and return */
504 werror (W_UNKNOWN_FEXT, s);
508 /* otherwise depending on the file type */
509 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
511 /* source file name : not if we already have a
515 werror (W_TOO_MANY_SRC, s);
519 /* the only source file */
520 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
522 werror (E_FILE_OPEN_ERR, s);
526 /* copy the file name into the buffer */
529 /* get rid of the "."-extension */
531 /* is there a dot at all? */
532 if (strchr (buffer, '.') &&
533 /* is the dot in the filename, not in the path? */
534 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
535 strrchr (buffer, '\\') < strrchr (buffer, '.')))
536 *strrchr (buffer, '.') = '\0';
538 srcFileName = Safe_alloc ( strlen (buffer) + 1);
539 strcpy (srcFileName, buffer);
541 /* get rid of any path information
542 for the module name; do this by going
543 backwards till we get to either '/' or '\' or ':'
544 or start of buffer */
545 fext = buffer + strlen (buffer);
546 while (fext != buffer &&
547 *(fext - 1) != '\\' &&
548 *(fext - 1) != '/' &&
551 moduleName = Safe_alloc ( strlen (fext) + 1);
552 strcpy (moduleName, fext);
557 /* if the extention is type .rel or .r or .REL or .R
558 addtional object file will be passed to the linker */
559 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
560 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
561 strcmp (fext, port->linker.rel_ext) == 0)
563 relFiles[nrelFiles++] = s;
567 /* if .lib or .LIB */
568 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
570 libFiles[nlibFiles++] = s;
574 werror (W_UNKNOWN_FEXT, s);
579 _processC1Arg (char *s)
583 if (options.out_name)
585 werror (W_TOO_MANY_SRC, s);
588 options.out_name = Safe_strdup (s);
597 _setModel (int model, const char *sz)
599 if (port->general.supported_models & model)
600 options.model = model;
602 werror (W_UNSUPPORTED_MODEL, sz, port->target);
606 _setProcessor (char *_processor)
608 port->processor = _processor;
609 fprintf(stderr,"Processor: %s\n",_processor);
612 /** Gets the string argument to this option. If the option is '--opt'
613 then for input of '--optxyz' or '--opt xyz' returns xyz.
616 getStringArg(const char *szStart, char **argv, int *pi, int argc)
618 if (argv[*pi][strlen(szStart)])
620 return &argv[*pi][strlen(szStart)];
627 werror (E_ARGUMENT_MISSING, szStart);
628 /* Die here rather than checking for errors later. */
638 /** Gets the integer argument to this option using the same rules as
642 getIntArg(const char *szStart, char **argv, int *pi, int argc)
644 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
648 verifyShortOption(const char *opt)
650 if (strlen(opt) != 2)
652 werror (W_EXCESS_SHORT_OPTIONS, opt);
657 tryHandleUnsupportedOpt(char **argv, int *pi)
659 if (argv[*pi][0] == '-')
661 const char *longOpt = "";
665 if (argv[*pi][1] == '-')
672 shortOpt = argv[*pi][1];
674 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
676 if (unsupportedOptTable[i].shortOpt == shortOpt ||
677 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
678 // Found an unsupported opt.
680 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
681 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
685 // Didn't find in the table
690 // Not an option, so can't be unsupported :)
696 tryHandleSimpleOpt(char **argv, int *pi)
698 if (argv[*pi][0] == '-')
700 const char *longOpt = "";
704 if (argv[*pi][1] == '-')
711 shortOpt = argv[*pi][1];
714 for (i = 0; i < LENGTH(optionsTable); 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 // Not an option, so can't be handled.
748 /*-----------------------------------------------------------------*/
749 /* parseCmdLine - parses the command line and sets the options */
750 /*-----------------------------------------------------------------*/
752 parseCmdLine (int argc, char **argv)
756 /* go thru all whole command line */
757 for (i = 1; i < argc; i++)
762 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
767 if (tryHandleSimpleOpt(argv, &i) == TRUE)
773 if (argv[i][0] == '-' && argv[i][1] == '-')
775 if (strcmp (argv[i], OPTION_HELP) == 0)
781 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
783 options.stack10bit = 0;
787 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
793 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
795 _setModel (MODEL_LARGE, argv[i]);
799 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
801 _setModel (MODEL_MEDIUM, argv[i]);
805 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
807 _setModel (MODEL_SMALL, argv[i]);
811 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
813 _setModel (MODEL_FLAT24, argv[i]);
817 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
819 options.dump_rassgn =
825 options.dump_raw = 1;
829 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
831 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
835 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
837 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
841 if (strcmp (argv[i], OPTION_VERSION) == 0)
848 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
850 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
854 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
856 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
860 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
862 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
866 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
868 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
872 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
874 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
878 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
880 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
884 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
886 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
890 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
892 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
896 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
898 optimize.global_cse = 0;
902 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
904 optimize.loopInvariant = 0;
908 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
910 optimize.loopInduction = 0;
914 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
916 options.lessPedantic = 1;
917 setErrorLogLevel(ERROR_LEVEL_WARNING);
921 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
923 options.shortis8bits=1;
927 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
929 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
933 if (!port->parseOption (&argc, argv, &i))
935 werror (W_UNKNOWN_OPTION, argv[i]);
943 /* if preceded by '-' then option */
949 verifyShortOption(argv[i]);
956 /* Used to select the port */
957 _setPort (argv[i] + 2);
961 /* Used to select the processor in port */
962 _setProcessor (getStringArg("-p", argv, &i, argc));
966 verifyShortOption(argv[i]);
972 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
976 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
980 /* pre-processer options */
981 if (argv[i][2] == 'p')
983 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
986 else if (argv[i][2] == 'l')
988 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
990 /* assembler options */
991 else if (argv[i][2] == 'a')
993 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
997 werror (W_UNKNOWN_OPTION, argv[i]);
1002 verifyShortOption(argv[i]);
1004 printVersionInfo ();
1008 /* preprocessor options */
1012 addToList (preArgv, "-M");
1017 addToList (preArgv, "-C");
1026 char sOpt = argv[i][1];
1029 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1035 werror(E_ARGUMENT_MISSING, argv[i-1]);
1049 sprintf (buffer, "-%c%s", sOpt, rest);
1050 addToList (preArgv, buffer);
1055 if (!port->parseOption (&argc, argv, &i))
1056 werror (W_UNKNOWN_OPTION, argv[i]);
1061 if (!port->parseOption (&argc, argv, &i))
1063 /* no option must be a filename */
1065 _processC1Arg (argv[i]);
1067 processFile (argv[i]);
1071 /* set up external stack location if not explicitly specified */
1072 if (!options.xstack_loc)
1073 options.xstack_loc = options.xdata_loc;
1075 /* if debug option is set the open the cdbFile */
1076 if (options.debug && srcFileName)
1078 sprintf (scratchFileName, "%s.cdb", srcFileName);
1079 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1080 werror (E_FILE_OPEN_ERR, scratchFileName);
1083 /* add a module record */
1084 fprintf (cdbFile, "M:%s\n", moduleName);
1090 /*-----------------------------------------------------------------*/
1091 /* linkEdit : - calls the linkage editor with options */
1092 /*-----------------------------------------------------------------*/
1094 linkEdit (char **envp)
1101 srcFileName = "temp";
1103 /* first we need to create the <filename>.lnk file */
1104 sprintf (scratchFileName, "%s.lnk", srcFileName);
1105 if (!(lnkfile = fopen (scratchFileName, "w")))
1107 werror (E_FILE_OPEN_ERR, scratchFileName);
1111 /* now write the options */
1112 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1114 /* if iram size specified */
1115 if (options.iram_size)
1116 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1119 fprintf (lnkfile, "-z\n");
1121 #define WRITE_SEG_LOC(N, L) \
1122 segName = Safe_strdup(N); \
1123 c = strtok(segName, " \t"); \
1124 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1125 if (segName) { Safe_free(segName); }
1127 /* code segment start */
1128 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1130 /* data segment start */
1131 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1134 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1138 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1141 /* bit segment start */
1142 WRITE_SEG_LOC (BIT_NAME, 0);
1144 /* add the extra linker options */
1145 for (i = 0; linkOptions[i]; i++)
1146 fprintf (lnkfile, "%s\n", linkOptions[i]);
1148 /* other library paths if specified */
1149 for (i = 0; i < nlibPaths; i++)
1150 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1152 /* standard library path */
1153 if (!options.nostdlib)
1155 switch (options.model)
1171 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1175 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1177 /* standard library files */
1178 #if !OPT_DISABLE_DS390
1179 if (options.model == MODEL_FLAT24)
1181 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1185 #if !OPT_DISABLE_XA51
1187 if (options.model == MODEL_PAGE0)
1189 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1193 fprintf (lnkfile, "-l %s\n", STD_LIB);
1194 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1195 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1196 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1199 /* additional libraries if any */
1200 for (i = 0; i < nlibFiles; i++)
1201 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1203 /* put in the object files */
1204 if (strcmp (srcFileName, "temp"))
1205 fprintf (lnkfile, "%s ", srcFileName);
1207 for (i = 0; i < nrelFiles; i++)
1208 fprintf (lnkfile, "%s\n", relFiles[i]);
1210 fprintf (lnkfile, "\n-e\n");
1213 if (options.verbose)
1214 printf ("sdcc: Calling linker...\n");
1216 if (port->linker.cmd)
1218 char buffer2[PATH_MAX];
1219 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1220 buildCmdLine2 (buffer, buffer2);
1224 buildCmdLine2 (buffer, port->linker.mcmd);
1227 if (my_system (buffer))
1232 if (strcmp (srcFileName, "temp") == 0)
1234 /* rename "temp.cdb" to "firstRelFile.cdb" */
1235 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1236 f = strcat (f, ".cdb");
1237 rename ("temp.cdb", f);
1242 /*-----------------------------------------------------------------*/
1243 /* assemble - spawns the assembler with arguments */
1244 /*-----------------------------------------------------------------*/
1246 assemble (char **envp)
1248 if (port->assembler.do_assemble) {
1249 port->assembler.do_assemble(asmOptions);
1251 } else if (port->assembler.cmd) {
1252 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1253 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1256 buildCmdLine2 (buffer, port->assembler.mcmd);
1259 if (my_system (buffer)) {
1260 /* either system() or the assembler itself has reported an error
1261 perror ("Cannot exec assembler");
1267 /*-----------------------------------------------------------------*/
1268 /* preProcess - spawns the preprocessor with arguments */
1269 /*-----------------------------------------------------------------*/
1271 preProcess (char **envp)
1275 if (!options.c1mode)
1277 /* if using external stack define the macro */
1278 if (options.useXstack)
1279 addToList (preArgv, "-DSDCC_USE_XSTACK");
1281 /* set the macro for stack autos */
1282 if (options.stackAuto)
1283 addToList (preArgv, "-DSDCC_STACK_AUTO");
1285 /* set the macro for stack autos */
1286 if (options.stack10bit)
1287 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1289 /* set the macro for no overlay */
1290 if (options.noOverlay)
1291 addToList (preArgv, "-DSDCC_NOOVERLAY");
1293 /* set the macro for large model */
1294 switch (options.model)
1297 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1300 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1303 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1306 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1309 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1312 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1315 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1319 /* add port (processor information to processor */
1320 addToList (preArgv, "-DSDCC_{port}");
1321 addToList (preArgv, "-D__{port}");
1323 /* standard include path */
1324 if (!options.nostdinc) {
1325 addToList (preArgv, "-I{includedir}");
1328 setMainValue ("cppextraopts", join(preArgv));
1331 preOutName = Safe_strdup (tempfilename ());
1333 /* Have to set cppoutfilename to something, even if just pre-processing. */
1334 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1336 if (options.verbose)
1337 printf ("sdcc: Calling preprocessor...\n");
1339 buildCmdLine2 (buffer, _preCmd);
1341 if (my_system (buffer))
1343 // @FIX: Dario Vecchio 03-05-2001
1346 unlink (preOutName);
1347 Safe_free (preOutName);
1360 preOutName = fullSrcFileName;
1363 yyin = fopen (preOutName, "r");
1366 perror ("Preproc file not found\n");
1374 _setPaths (const char *pprefix)
1377 Given the prefix and how the directories were layed out at
1378 configure time, see if the library and include directories are
1379 where expected. If so, set.
1381 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1382 strcpy (scratchFileName, pprefix);
1383 strcat (scratchFileName, buffer);
1385 if (pathExists (scratchFileName))
1387 setMainValue ("includedir", scratchFileName);
1394 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1395 strcpy (scratchFileName, pprefix);
1396 strcat (scratchFileName, buffer);
1398 if (pathExists (scratchFileName))
1400 setMainValue ("libdir", scratchFileName);
1411 _discoverPaths (const char *argv0)
1414 1. Try the SDCCDIR environment variable.
1415 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1416 and library paths with respect to that. Note that under win32
1417 argv[0] is always the full path to the program.
1418 3. If (1) and (2) fail, fall back to the compile time defaults.
1420 Detecting assumes the same layout as when configured. If the
1421 directories have been further moved about then discovery will
1425 /* Some input cases:
1426 "c:\fish\sdcc\bin\sdcc"
1428 "/home/fish/bin/sdcc"
1430 Note that ./sdcc is explicitly not supported as there isn't
1433 /* bindir is handled differently to the lib and include directories.
1434 It's rather unfortunate, but required due to the different
1435 install and development layouts. Logic is different as well.
1438 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1440 strcpy (scratchFileName, argv0);
1441 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1442 setMainValue ("bindir", scratchFileName);
1443 ExePathList[0] = Safe_strdup (scratchFileName);
1445 else if (getenv (SDCCDIR_NAME) != NULL)
1447 getPathDifference (buffer, PREFIX, BINDIR);
1448 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1449 strcat (scratchFileName, buffer);
1450 setMainValue ("bindir", scratchFileName);
1451 ExePathList[0] = Safe_strdup (scratchFileName);
1455 setMainValue ("bindir", BINDIR);
1456 ExePathList[0] = BINDIR;
1462 if (getenv (SDCCDIR_NAME) != NULL)
1464 if (_setPaths (getenv (SDCCDIR_NAME)))
1466 /* Successfully set. */
1471 /* Include and lib weren't where expected. */
1475 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1477 char *pbase = getPrefixFromBinPath (argv0);
1481 /* A bad path. Skip. */
1485 if (_setPaths (pbase))
1487 /* Successfully set. */
1492 /* Include and lib weren't where expected. */
1497 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1498 setMainValue ("libdir", SDCC_LIB_DIR);
1505 populateMainValues (_baseValues);
1506 setMainValue ("port", port->target);
1507 setMainValue ("objext", port->linker.rel_ext);
1508 setMainValue ("asmext", port->assembler.file_ext);
1510 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1511 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1516 * initialises and calls the parser
1520 main (int argc, char **argv, char **envp)
1522 /* turn all optimizations off by default */
1523 memset (&optimize, 0, sizeof (struct optimize));
1525 /*printVersionInfo (); */
1528 fprintf (stderr, "Build error: no ports are enabled.\n");
1532 _findPort (argc, argv);
1534 if (strcmp(port->target, "mcs51") == 0) {
1535 printf("DS390 jammed in A\n");
1540 /* Initalise the port. */
1544 // Create a default exe search path from the path to the sdcc command
1547 setDefaultOptions ();
1550 options.model = MODEL_SMALL;
1551 options.stack10bit=0;
1554 parseCmdLine (argc, argv);
1556 /* if no input then printUsage & exit */
1557 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1558 (options.c1mode && !srcFileName && !options.out_name))
1565 _discoverPaths (argv[0]);
1572 port->finaliseOptions ();
1581 if (options.verbose)
1582 printf ("sdcc: Generating code...\n");
1588 if (TARGET_IS_PIC) {
1589 /* TSD PIC port hack - if the PIC port option is enabled
1590 and SDCC is used to generate PIC code, then we will
1591 generate .asm files in gpasm's format instead of SDCC's
1594 #if !OPT_DISABLE_PIC
1603 // @FIX: Dario Vecchio 03-05-2001
1606 if (yyin && yyin != stdin)
1608 unlink (preOutName);
1609 Safe_free (preOutName);
1614 if (!options.c1mode && !noAssemble)
1616 if (options.verbose)
1617 printf ("sdcc: Calling assembler...\n");
1623 // @FIX: Dario Vecchio 03-05-2001
1626 if (yyin && yyin != stdin)
1628 unlink (preOutName);
1629 Safe_free (preOutName);
1632 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1645 if (preOutName && !options.c1mode)
1647 unlink (preOutName);
1648 Safe_free (preOutName);
1651 if (!options.cc_only &&
1655 (srcFileName || nrelFiles))
1657 if (port->linker.do_link)
1658 port->linker.do_link ();
1663 if (yyin && yyin != stdin)