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 int RegBankUsed[4]={1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
60 struct optimize optimize;
61 struct options options;
62 char *VersionString = SDCC_VERSION_STR;
65 char *linkOptions[128];
66 const char *asmOptions[128];
73 bool verboseExec = FALSE;
76 /* uncomment JAMIN_DS390 to always override and use ds390 port
77 for mcs51 work. This is temporary, for compatibility testing. */
78 /* #define JAMIN_DS390 */
83 // Globally accessible scratch buffer for file names.
84 char scratchFileName[PATH_MAX];
85 char buffer[PATH_MAX];
87 // In MSC VC6 default search path for exe's to path for this
89 char DefaultExePath[128];
91 #define OPTION_HELP "-help"
93 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
95 #define OPTION_STACK_8BIT "--stack-8bit"
96 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
97 #define OPTION_LARGE_MODEL "--model-large"
98 #define OPTION_MEDIUM_MODEL "--model-medium"
99 #define OPTION_SMALL_MODEL "--model-small"
100 #define OPTION_FLAT24_MODEL "--model-flat24"
101 #define OPTION_DUMP_ALL "--dumpall"
102 #define OPTION_PEEP_FILE "--peep-file"
103 #define OPTION_LIB_PATH "--lib-path"
104 #define OPTION_XSTACK_LOC "--xstack-loc"
105 #define OPTION_CALLEE_SAVES "--callee-saves"
106 #define OPTION_STACK_LOC "--stack-loc"
107 #define OPTION_XRAM_LOC "--xram-loc"
108 #define OPTION_IRAM_SIZE "--iram-size"
109 #define OPTION_VERSION "--version"
110 #define OPTION_DATA_LOC "--data-loc"
111 #define OPTION_CODE_LOC "--code-loc"
112 #define OPTION_IDATA_LOC "--idata-loc"
113 #define OPTION_NO_LOOP_INV "--noinvariant"
114 #define OPTION_NO_LOOP_IND "--noinduction"
115 #define OPTION_LESS_PEDANTIC "--lesspedantic"
116 #define OPTION_NO_GCSE "--nogcse"
117 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
118 #define OPTION_TINI_LIBID "--tini-libid"
122 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
123 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
124 { 'd', NULL, NULL, NULL },
125 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
126 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
127 { 'A', NULL, NULL, NULL },
128 { 'U', NULL, NULL, NULL },
129 { 'C', NULL, NULL, "Preprocessor option" },
130 { 'M', NULL, NULL, "Preprocessor option" },
131 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
132 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
133 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
134 { 'L', NULL, NULL, "Add the next field to the library search path" },
135 { 'l', NULL, NULL, "Include the given library in the link" },
136 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
137 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
138 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
139 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
140 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
141 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
142 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
143 { 0, "--xstack", &options.useXstack, "Use external stack" },
144 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
145 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
146 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
147 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
148 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
149 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
150 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
151 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
152 { 0, "--dumpgcse", &options.dump_gcse, NULL },
153 { 0, "--dumploop", &options.dump_loop, NULL },
154 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
155 { 0, "--dumpliverange", &options.dump_range, NULL },
156 { 0, "--dumpregpack", &options.dump_pack, NULL },
157 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
158 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
159 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
160 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
161 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
162 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
163 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
164 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
165 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
166 { 0, OPTION_IDATA_LOC, NULL, NULL },
167 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
168 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
169 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
170 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
171 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
172 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
173 { 0, "--cyclomatic", &options.cyclomatic, NULL },
174 { 0, "--nooverlay", &options.noOverlay, NULL },
175 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
176 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
177 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
178 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
179 { 0, "--peep-asm", &options.asmpeep, NULL },
180 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
181 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
182 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
183 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
184 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
185 { 0, "--help", NULL, "Display this help" },
186 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
187 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
188 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
189 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
190 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
191 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
192 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
193 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
194 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
195 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
196 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
197 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
198 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
199 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
204 /** Table of all unsupported options and help text to display when one
208 /** shortOpt as in OPTIONS. */
210 /** longOpt as in OPTIONS. */
212 /** Message to display inside W_UNSUPPORTED_OPT when this option
217 static const UNSUPPORTEDOPT
218 unsupportedOptTable[] = {
219 { 'a', NULL, "use --stack-auto instead." },
220 { 'g', NULL, "use --generic instead" },
221 { 'X', NULL, "use --xstack-loc instead" },
222 { 'x', NULL, "use --xstack instead" },
223 { 'i', NULL, "use --idata-loc instead" },
224 { 'r', NULL, "use --xdata-loc instead" },
225 { 's', NULL, "use --code-loc instead" },
226 { 'Y', NULL, "use -I instead" }
229 /** List of all default constant macros.
231 static const char *_baseValues[] = {
232 "cpp", "{bindir}{sep}sdcpp",
234 /* Path seperator character */
235 "sep", DIR_SEPARATOR_STRING,
239 static const char *_preCmd = "{cpp} -nostdinc -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
243 static PORT *_ports[] =
245 #if !OPT_DISABLE_MCS51
248 #if !OPT_DISABLE_GBZ80
257 #if !OPT_DISABLE_DS390
263 #if !OPT_DISABLE_TININative
266 #if !OPT_DISABLE_XA51
271 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
274 extern void picglue ();
277 /** Sets the port to the one given by the command line option.
278 @param The name minus the option (eg 'mcs51')
279 @return 0 on success.
282 _setPort (const char *name)
285 for (i = 0; i < NUM_PORTS; i++)
287 if (!strcmp (_ports[i]->target, name))
293 /* Error - didnt find */
294 werror (E_UNKNOWN_TARGET, name);
298 /* Override the default processor with the one specified
299 * on the command line */
301 _setProcessor (char *_processor)
303 port->processor = _processor;
304 fprintf(stderr,"Processor: %s\n",_processor);
308 _validatePorts (void)
311 for (i = 0; i < NUM_PORTS; i++)
313 if (_ports[i]->magic != PORT_MAGIC)
315 /* Uncomment this line to debug which port is causing the problem
316 * (the target name is close to the beginning of the port struct
317 * and probably can be accessed just fine). */
318 fprintf(stderr,"%s :",_ports[i]->target);
319 wassertl (0, "Port definition structure is incomplete");
324 /* search through the command line options for the port */
326 _findPort (int argc, char **argv)
332 if (!strncmp (*argv, "-m", 2))
334 _setPort (*argv + 2);
339 /* Use the first in the list */
343 /* search through the command line options for the processor */
345 _findProcessor (int argc, char **argv)
349 if (!strncmp (*argv, "-p", 2))
351 _setProcessor (*argv + 2);
357 /* no error if processor was not specified. */
360 /*-----------------------------------------------------------------*/
361 /* printVersionInfo - prints the version info */
362 /*-----------------------------------------------------------------*/
370 for (i = 0; i < NUM_PORTS; i++)
371 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
373 fprintf (stderr, " %s"
374 #ifdef SDCC_SUB_VERSION_STR
375 "/" SDCC_SUB_VERSION_STR
384 #if defined(_MSC_VER)
397 printOptions(const OPTION *optionsTable)
400 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
402 fprintf(stdout, " %c%c %-20s %s\n",
403 optionsTable[i].shortOpt !=0 ? '-' : ' ',
404 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
405 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
406 optionsTable[i].help != NULL ? optionsTable[i].help : ""
411 /*-----------------------------------------------------------------*/
412 /* printUsage - prints command line syntax */
413 /*-----------------------------------------------------------------*/
420 "Usage : sdcc [options] filename\n"
424 printOptions(optionsTable);
426 for (i = 0; i < NUM_PORTS; i++)
428 if (_ports[i]->poptions != NULL)
430 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
431 printOptions (_ports[i]->poptions);
438 /*-----------------------------------------------------------------*/
439 /* parseWithComma - separates string with comma */
440 /*-----------------------------------------------------------------*/
442 parseWithComma (char **dest, char *src)
446 strtok (src, "\r\n \t");
447 /* skip the initial white spaces */
448 while (isspace (*src))
465 /*-----------------------------------------------------------------*/
466 /* setDefaultOptions - sets the default options */
467 /*-----------------------------------------------------------------*/
473 for (i = 0; i < 128; i++)
474 preArgv[i] = asmOptions[i] =
475 linkOptions[i] = relFiles[i] = libFiles[i] =
478 /* first the options part */
479 options.stack_loc = 0; /* stack pointer initialised to 0 */
480 options.xstack_loc = 0; /* xternal stack starts at 0 */
481 options.code_loc = 0; /* code starts at 0 */
482 options.data_loc = 0; /* JCF: By default let the linker locate data */
483 options.xdata_loc = 0;
484 options.idata_loc = 0x80;
485 options.genericPtr = 1; /* default on */
487 options.model = port->general.default_model;
488 options.nostdlib = 0;
489 options.nostdinc = 0;
491 options.shortis8bits = 0;
493 options.stack10bit=0;
495 /* now for the optimizations */
496 /* turn on the everything */
497 optimize.global_cse = 1;
502 optimize.loopInvariant = 1;
503 optimize.loopInduction = 1;
505 /* now for the ports */
506 port->setDefaultOptions ();
509 /*-----------------------------------------------------------------*/
510 /* processFile - determines the type of file from the extension */
511 /*-----------------------------------------------------------------*/
513 processFile (char *s)
517 /* get the file extension */
518 fext = s + strlen (s);
519 while ((fext != s) && *fext != '.')
522 /* now if no '.' then we don't know what the file type is
523 so give a warning and return */
526 werror (W_UNKNOWN_FEXT, s);
530 /* otherwise depending on the file type */
531 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
533 /* source file name : not if we already have a
537 werror (W_TOO_MANY_SRC, s);
541 /* the only source file */
542 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
544 werror (E_FILE_OPEN_ERR, s);
548 /* copy the file name into the buffer */
551 /* get rid of the "."-extension */
553 /* is there a dot at all? */
554 if (strchr (buffer, '.') &&
555 /* is the dot in the filename, not in the path? */
556 (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
557 strrchr (buffer, '\\') < strrchr (buffer, '.')))
558 *strrchr (buffer, '.') = '\0';
560 srcFileName = Safe_alloc ( strlen (buffer) + 1);
561 strcpy (srcFileName, buffer);
563 /* get rid of any path information
564 for the module name; do this by going
565 backwards till we get to either '/' or '\' or ':'
566 or start of buffer */
567 fext = buffer + strlen (buffer);
568 while (fext != buffer &&
569 *(fext - 1) != '\\' &&
570 *(fext - 1) != '/' &&
573 moduleName = Safe_alloc ( strlen (fext) + 1);
574 strcpy (moduleName, fext);
579 /* if the extention is type .rel or .r or .REL or .R
580 addtional object file will be passed to the linker */
581 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
582 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
583 strcmp (fext, port->linker.rel_ext) == 0)
585 relFiles[nrelFiles++] = s;
589 /* if .lib or .LIB */
590 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
592 libFiles[nlibFiles++] = s;
596 werror (W_UNKNOWN_FEXT, s);
601 _processC1Arg (char *s)
605 if (options.out_name)
607 werror (W_TOO_MANY_SRC, s);
610 options.out_name = Safe_strdup (s);
619 _setModel (int model, const char *sz)
621 if (port->general.supported_models & model)
622 options.model = model;
624 werror (W_UNSUPPORTED_MODEL, sz, port->target);
627 /** Gets the string argument to this option. If the option is '--opt'
628 then for input of '--optxyz' or '--opt xyz' returns xyz.
631 getStringArg(const char *szStart, char **argv, int *pi, int argc)
633 if (argv[*pi][strlen(szStart)])
635 return &argv[*pi][strlen(szStart)];
642 werror (E_ARGUMENT_MISSING, szStart);
643 /* Die here rather than checking for errors later. */
653 /** Gets the integer argument to this option using the same rules as
657 getIntArg(const char *szStart, char **argv, int *pi, int argc)
659 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
663 verifyShortOption(const char *opt)
665 if (strlen(opt) != 2)
667 werror (W_EXCESS_SHORT_OPTIONS, opt);
672 tryHandleUnsupportedOpt(char **argv, int *pi)
674 if (argv[*pi][0] == '-')
676 const char *longOpt = "";
680 if (argv[*pi][1] == '-')
687 shortOpt = argv[*pi][1];
689 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
691 if (unsupportedOptTable[i].shortOpt == shortOpt ||
692 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
693 // Found an unsupported opt.
695 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
696 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
700 // Didn't find in the table
705 // Not an option, so can't be unsupported :)
711 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
714 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
716 if (optionsTable[i].shortOpt == shortOpt ||
717 (longOpt && optionsTable[i].longOpt &&
718 strcmp(optionsTable[i].longOpt, longOpt) == 0))
721 // If it is a flag then we can handle it here
722 if (optionsTable[i].pparameter != NULL)
724 if (optionsTable[i].shortOpt == shortOpt)
726 verifyShortOption(argv[*pi]);
729 (*optionsTable[i].pparameter)++;
733 // Not a flag. Handled manually later.
738 // Didn't find in the table
743 tryHandleSimpleOpt(char **argv, int *pi)
745 if (argv[*pi][0] == '-')
747 const char *longOpt = "";
750 if (argv[*pi][1] == '-')
757 shortOpt = argv[*pi][1];
760 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
764 else if (port && port->poptions &&
765 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
776 // Not an option, so can't be handled.
781 /*-----------------------------------------------------------------*/
782 /* parseCmdLine - parses the command line and sets the options */
783 /*-----------------------------------------------------------------*/
785 parseCmdLine (int argc, char **argv)
789 /* go thru all whole command line */
790 for (i = 1; i < argc; i++)
795 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
800 if (tryHandleSimpleOpt(argv, &i) == TRUE)
806 if (argv[i][0] == '-' && argv[i][1] == '-')
808 if (strcmp (argv[i], OPTION_HELP) == 0)
814 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
816 options.stack10bit = 0;
820 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
826 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
828 _setModel (MODEL_LARGE, argv[i]);
832 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
834 _setModel (MODEL_MEDIUM, argv[i]);
838 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
840 _setModel (MODEL_SMALL, argv[i]);
844 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
846 _setModel (MODEL_FLAT24, argv[i]);
850 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
852 options.dump_rassgn =
858 options.dump_raw = 1;
862 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
864 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
868 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
870 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
874 if (strcmp (argv[i], OPTION_VERSION) == 0)
881 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
883 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
887 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
889 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
893 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
895 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
899 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
901 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
905 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
907 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
911 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
913 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
917 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
919 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
923 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
925 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
929 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
931 optimize.global_cse = 0;
935 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
937 optimize.loopInvariant = 0;
941 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
943 optimize.loopInduction = 0;
947 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
949 options.lessPedantic = 1;
950 setErrorLogLevel(ERROR_LEVEL_WARNING);
954 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
956 options.shortis8bits=1;
960 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
962 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
966 if (!port->parseOption (&argc, argv, &i))
968 werror (W_UNKNOWN_OPTION, argv[i]);
976 /* if preceded by '-' then option */
982 verifyShortOption(argv[i]);
989 /* Used to select the port. But this has already been done. */
993 /* Used to select the processor in port. But this has
994 * already been done. */
998 verifyShortOption(argv[i]);
1000 options.cc_only = 1;
1004 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
1008 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
1012 /* pre-processer options */
1013 if (argv[i][2] == 'p')
1015 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
1017 /* linker options */
1018 else if (argv[i][2] == 'l')
1020 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
1022 /* assembler options */
1023 else if (argv[i][2] == 'a')
1025 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
1029 werror (W_UNKNOWN_OPTION, argv[i]);
1034 verifyShortOption(argv[i]);
1036 printVersionInfo ();
1040 /* preprocessor options */
1044 addToList (preArgv, "-M");
1049 addToList (preArgv, "-C");
1058 char sOpt = argv[i][1];
1061 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1067 werror(E_ARGUMENT_MISSING, argv[i-1]);
1081 sprintf (buffer, "-%c%s", sOpt, rest);
1082 addToList (preArgv, buffer);
1087 if (!port->parseOption (&argc, argv, &i))
1088 werror (W_UNKNOWN_OPTION, argv[i]);
1093 if (!port->parseOption (&argc, argv, &i))
1095 /* no option must be a filename */
1097 _processC1Arg (argv[i]);
1099 processFile (argv[i]);
1103 /* set up external stack location if not explicitly specified */
1104 if (!options.xstack_loc)
1105 options.xstack_loc = options.xdata_loc;
1107 /* if debug option is set the open the cdbFile */
1108 if (options.debug && srcFileName)
1110 sprintf (scratchFileName, "%s.cdb", srcFileName);
1111 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1112 werror (E_FILE_OPEN_ERR, scratchFileName);
1115 /* add a module record */
1116 fprintf (cdbFile, "M:%s\n", moduleName);
1122 /*-----------------------------------------------------------------*/
1123 /* linkEdit : - calls the linkage editor with options */
1124 /*-----------------------------------------------------------------*/
1126 linkEdit (char **envp)
1133 srcFileName = "temp";
1135 /* first we need to create the <filename>.lnk file */
1136 sprintf (scratchFileName, "%s.lnk", srcFileName);
1137 if (!(lnkfile = fopen (scratchFileName, "w")))
1139 werror (E_FILE_OPEN_ERR, scratchFileName);
1143 /* now write the options. JCF: added option 'y' */
1144 fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
1146 /* if iram size specified */
1147 if (options.iram_size)
1148 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1151 fprintf (lnkfile, "-z\n");
1153 #define WRITE_SEG_LOC(N, L) \
1154 segName = Safe_strdup(N); \
1155 c = strtok(segName, " \t"); \
1156 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1157 if (segName) { Safe_free(segName); }
1159 /* code segment start */
1160 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1162 /* data segment start */
1163 if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
1164 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1168 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1172 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1175 /* bit segment start */
1176 WRITE_SEG_LOC (BIT_NAME, 0);
1178 /* JCF: stack start */
1179 if(options.stack_loc) {
1180 WRITE_SEG_LOC ("SSEG", options.stack_loc & 0xff);
1183 /* add the extra linker options */
1184 for (i = 0; linkOptions[i]; i++)
1185 fprintf (lnkfile, "%s\n", linkOptions[i]);
1187 /* other library paths if specified */
1188 for (i = 0; i < nlibPaths; i++)
1189 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1191 /* standard library path */
1192 if (!options.nostdlib)
1194 switch (options.model)
1210 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1214 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1216 /* standard library files */
1217 #if !OPT_DISABLE_DS390
1218 if (options.model == MODEL_FLAT24)
1220 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1224 #if !OPT_DISABLE_XA51
1226 if (options.model == MODEL_PAGE0)
1228 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1232 fprintf (lnkfile, "-l %s\n", STD_LIB);
1233 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1234 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1235 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1238 /* additional libraries if any */
1239 for (i = 0; i < nlibFiles; i++)
1240 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1242 /* put in the object files */
1243 if (strcmp (srcFileName, "temp"))
1244 fprintf (lnkfile, "%s ", srcFileName);
1246 for (i = 0; i < nrelFiles; i++)
1247 fprintf (lnkfile, "%s\n", relFiles[i]);
1249 fprintf (lnkfile, "\n-e\n");
1252 if (options.verbose)
1253 printf ("sdcc: Calling linker...\n");
1255 if (port->linker.cmd)
1257 char buffer2[PATH_MAX];
1258 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1259 buildCmdLine2 (buffer, buffer2);
1263 buildCmdLine2 (buffer, port->linker.mcmd);
1266 if (my_system (buffer))
1271 if (strcmp (srcFileName, "temp") == 0)
1273 /* rename "temp.cdb" to "firstRelFile.cdb" */
1274 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1275 f = strcat (f, ".cdb");
1276 rename ("temp.cdb", f);
1281 /*-----------------------------------------------------------------*/
1282 /* assemble - spawns the assembler with arguments */
1283 /*-----------------------------------------------------------------*/
1285 assemble (char **envp)
1287 if (port->assembler.do_assemble) {
1288 port->assembler.do_assemble(asmOptions);
1290 } else if (port->assembler.cmd) {
1291 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1292 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1295 buildCmdLine2 (buffer, port->assembler.mcmd);
1298 if (my_system (buffer)) {
1299 /* either system() or the assembler itself has reported an error
1300 perror ("Cannot exec assembler");
1306 /*-----------------------------------------------------------------*/
1307 /* preProcess - spawns the preprocessor with arguments */
1308 /*-----------------------------------------------------------------*/
1310 preProcess (char **envp)
1314 if (!options.c1mode)
1316 /* if using external stack define the macro */
1317 if (options.useXstack)
1318 addToList (preArgv, "-DSDCC_USE_XSTACK");
1320 /* set the macro for stack autos */
1321 if (options.stackAuto)
1322 addToList (preArgv, "-DSDCC_STACK_AUTO");
1324 /* set the macro for stack autos */
1325 if (options.stack10bit)
1326 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1328 /* set the macro for no overlay */
1329 if (options.noOverlay)
1330 addToList (preArgv, "-DSDCC_NOOVERLAY");
1332 /* set the macro for large model */
1333 switch (options.model)
1336 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1339 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1342 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1345 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1348 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1351 addToList (preArgv, "-DSDCC_MODEL_PAGE0");
1354 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1358 /* add port (processor information to processor */
1359 addToList (preArgv, "-DSDCC_{port}");
1360 addToList (preArgv, "-D__{port}");
1362 /* standard include path */
1363 if (!options.nostdinc) {
1364 addToList (preArgv, "-I{includedir}");
1367 setMainValue ("cppextraopts", join(preArgv));
1370 preOutName = Safe_strdup (tempfilename ());
1372 /* Have to set cppoutfilename to something, even if just pre-processing. */
1373 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1375 if (options.verbose)
1376 printf ("sdcc: Calling preprocessor...\n");
1378 buildCmdLine2 (buffer, _preCmd);
1380 if (my_system (buffer))
1382 // @FIX: Dario Vecchio 03-05-2001
1385 unlink (preOutName);
1386 Safe_free (preOutName);
1399 preOutName = fullSrcFileName;
1402 yyin = fopen (preOutName, "r");
1405 perror ("Preproc file not found\n");
1413 _setPaths (const char *pprefix)
1416 Given the prefix and how the directories were layed out at
1417 configure time, see if the library and include directories are
1418 where expected. If so, set.
1420 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1421 strcpy (scratchFileName, pprefix);
1422 strcat (scratchFileName, buffer);
1424 if (pathExists (scratchFileName))
1426 setMainValue ("includedir", scratchFileName);
1433 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1434 strcpy (scratchFileName, pprefix);
1435 strcat (scratchFileName, buffer);
1437 if (pathExists (scratchFileName))
1439 setMainValue ("libdir", scratchFileName);
1450 _discoverPaths (const char *argv0)
1453 1. Try the SDCCDIR environment variable.
1454 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1455 and library paths with respect to that. Note that under win32
1456 argv[0] is always the full path to the program.
1457 3. If (1) and (2) fail, fall back to the compile time defaults.
1459 Detecting assumes the same layout as when configured. If the
1460 directories have been further moved about then discovery will
1464 /* Some input cases:
1465 "c:\fish\sdcc\bin\sdcc"
1467 "/home/fish/bin/sdcc"
1469 Note that ./sdcc is explicitly not supported as there isn't
1472 /* bindir is handled differently to the lib and include directories.
1473 It's rather unfortunate, but required due to the different
1474 install and development layouts. Logic is different as well.
1477 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1479 strcpy (scratchFileName, argv0);
1480 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1481 setMainValue ("bindir", scratchFileName);
1482 ExePathList[0] = Safe_strdup (scratchFileName);
1484 else if (getenv (SDCCDIR_NAME) != NULL)
1486 getPathDifference (buffer, PREFIX, BINDIR);
1487 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1488 strcat (scratchFileName, buffer);
1489 setMainValue ("bindir", scratchFileName);
1490 ExePathList[0] = Safe_strdup (scratchFileName);
1494 setMainValue ("bindir", BINDIR);
1495 ExePathList[0] = BINDIR;
1501 if (getenv (SDCCDIR_NAME) != NULL)
1503 if (_setPaths (getenv (SDCCDIR_NAME)))
1505 /* Successfully set. */
1510 /* Include and lib weren't where expected. */
1514 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1516 char *pbase = getPrefixFromBinPath (argv0);
1520 /* A bad path. Skip. */
1524 if (_setPaths (pbase))
1526 /* Successfully set. */
1531 /* Include and lib weren't where expected. */
1536 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1537 setMainValue ("libdir", SDCC_LIB_DIR);
1544 populateMainValues (_baseValues);
1545 setMainValue ("port", port->target);
1546 setMainValue ("objext", port->linker.rel_ext);
1547 setMainValue ("asmext", port->assembler.file_ext);
1549 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1550 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1555 * initialises and calls the parser
1559 main (int argc, char **argv, char **envp)
1561 /* turn all optimizations off by default */
1562 memset (&optimize, 0, sizeof (struct optimize));
1564 /*printVersionInfo (); */
1567 fprintf (stderr, "Build error: no ports are enabled.\n");
1571 /* install atexit handler */
1572 atexit(rm_tmpfiles);
1574 /* Before parsing the command line options, do a
1575 * search for the port and processor and initialize
1576 * them if they're found. (We can't gurantee that these
1577 * will be the first options specified).
1580 _findPort (argc, argv);
1583 if (strcmp(port->target, "mcs51") == 0) {
1584 printf("DS390 jammed in A\n");
1590 _findProcessor (argc, argv);
1592 /* Initalise the port. */
1596 // Create a default exe search path from the path to the sdcc command
1599 setDefaultOptions ();
1602 options.model = MODEL_SMALL;
1603 options.stack10bit=0;
1606 parseCmdLine (argc, argv);
1608 /* if no input then printUsage & exit */
1609 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1610 (options.c1mode && !srcFileName && !options.out_name))
1617 _discoverPaths (argv[0]);
1624 port->finaliseOptions ();
1633 if (options.verbose)
1634 printf ("sdcc: Generating code...\n");
1639 // @FIX: Dario Vecchio 03-05-2001
1641 if (yyin && yyin != stdin)
1643 unlink (preOutName);
1644 Safe_free (preOutName);
1650 if (TARGET_IS_PIC) {
1651 /* TSD PIC port hack - if the PIC port option is enabled
1652 and SDCC is used to generate PIC code, then we will
1653 generate .asm files in gpasm's format instead of SDCC's
1656 #if !OPT_DISABLE_PIC
1664 if (!options.c1mode && !noAssemble)
1666 if (options.verbose)
1667 printf ("sdcc: Calling assembler...\n");
1677 if (yyin && yyin != stdin)
1680 if (preOutName && !options.c1mode)
1682 unlink (preOutName);
1683 Safe_free (preOutName);
1686 if (!options.cc_only &&
1690 (srcFileName || nrelFiles))
1692 if (port->linker.do_link)
1693 port->linker.do_link ();