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 /*"Version 2.1.8a" */ ;
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"
117 /** Table of all options supported by all ports.
119 * A reference for all options.
120 * An easy way to maintain help for the options.
121 * Automatic support for setting flags on simple options.
124 /** The short option character e.g. 'h' for -h. 0 for none. */
126 /** Long option e.g. "--help". Includes the -- prefix. NULL for
129 /** Pointer to an int that will be incremented every time the
130 option is encountered. May be NULL.
133 /** Help text to go with this option. May be NULL. */
139 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
140 { 'd', NULL, NULL, NULL },
141 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
142 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
143 { 'A', NULL, NULL, NULL },
144 { 'U', NULL, NULL, NULL },
145 { 'C', NULL, NULL, "Preprocessor option" },
146 { 'M', NULL, NULL, "Preprocessor option" },
147 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
148 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
149 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
150 { 'L', NULL, NULL, "Add the next field to the library search path" },
151 { 'l', NULL, NULL, "Include the given library in the link" },
152 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
153 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
154 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
155 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
156 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
157 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
158 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
159 { 0, "--xstack", &options.useXstack, "Use external stack" },
160 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
161 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
162 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
163 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
164 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
165 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
166 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
167 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
168 { 0, "--dumpgcse", &options.dump_gcse, NULL },
169 { 0, "--dumploop", &options.dump_loop, NULL },
170 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
171 { 0, "--dumpliverange", &options.dump_range, NULL },
172 { 0, "--dumpregpack", &options.dump_pack, NULL },
173 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
174 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
175 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
176 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
177 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
178 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
179 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
180 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
181 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
182 { 0, OPTION_IDATA_LOC, NULL, NULL },
183 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
184 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
185 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
186 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
187 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
188 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
189 { 0, "--cyclomatic", &options.cyclomatic, NULL },
190 { 0, "--nooverlay", &options.noOverlay, NULL },
191 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
192 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
193 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
194 { 0, "--peep-asm", &options.asmpeep, NULL },
195 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
196 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
197 { 0, "--stack-after-data", &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
198 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
199 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The input is preprocessed code, the output is assembly code." },
200 { 0, "--help", NULL, "Display this help" },
201 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
202 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
203 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
204 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
205 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
206 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
207 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
208 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
209 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
210 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"}
213 /** Table of all unsupported options and help text to display when one
217 /** shortOpt as in OPTIONS. */
219 /** longOpt as in OPTIONS. */
221 /** Message to display inside W_UNSUPPORTED_OPT when this option
226 static const UNSUPPORTEDOPT
227 unsupportedOptTable[] = {
228 { 'a', NULL, "use --stack-auto instead." },
229 { 'g', NULL, "use --generic instead" },
230 { 'X', NULL, "use --xstack-loc instead" },
231 { 'x', NULL, "use --xstack instead" },
232 { 'p', NULL, "use --stack-loc instead" },
233 { 'P', NULL, "use --stack-loc instead" },
234 { 'i', NULL, "use --idata-loc instead" },
235 { 'r', NULL, "use --xdata-loc instead" },
236 { 's', NULL, "use --code-loc instead" },
237 { 'Y', NULL, "use -I instead" }
240 /** List of all default constant macros.
242 static const char *_baseValues[] = {
243 "cpp", "{bindir}{sep}sdcpp",
245 /* Path seperator character */
246 "sep", DIR_SEPARATOR_STRING,
250 static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
254 static PORT *_ports[] =
256 #if !OPT_DISABLE_MCS51
259 #if !OPT_DISABLE_GBZ80
268 #if !OPT_DISABLE_DS390
274 #if !OPT_DISABLE_I186
277 #if !OPT_DISABLE_TLCS900H
282 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
285 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
287 extern void picglue ();
289 /** Sets the port to the one given by the command line option.
290 @param The name minus the option (eg 'mcs51')
291 @return 0 on success.
294 _setPort (const char *name)
297 for (i = 0; i < NUM_PORTS; i++)
299 if (!strcmp (_ports[i]->target, name))
305 /* Error - didnt find */
306 werror (E_UNKNOWN_TARGET, name);
311 _validatePorts (void)
314 for (i = 0; i < NUM_PORTS; i++)
316 if (_ports[i]->magic != PORT_MAGIC)
318 wassertl (0, "Port definition structure is incomplete");
324 _findPort (int argc, char **argv)
330 if (!strncmp (*argv, "-m", 2))
332 _setPort (*argv + 2);
337 /* Use the first in the list */
341 /*-----------------------------------------------------------------*/
342 /* printVersionInfo - prints the version info */
343 /*-----------------------------------------------------------------*/
351 for (i = 0; i < NUM_PORTS; i++)
352 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
354 fprintf (stderr, " %s"
355 #ifdef SDCC_SUB_VERSION_STR
356 "/" SDCC_SUB_VERSION_STR
365 #if defined(_MSC_VER)
377 /*-----------------------------------------------------------------*/
378 /* printUsage - prints command line syntax */
379 /*-----------------------------------------------------------------*/
386 "Usage : sdcc [options] filename\n"
390 for (i = 0; i < LENGTH(optionsTable); i++) {
391 fprintf(stdout, " %c%c %-20s %s\n",
392 optionsTable[i].shortOpt !=0 ? '-' : ' ',
393 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
394 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
395 optionsTable[i].help != NULL ? optionsTable[i].help : ""
401 /*-----------------------------------------------------------------*/
402 /* parseWithComma - separates string with comma */
403 /*-----------------------------------------------------------------*/
405 parseWithComma (char **dest, char *src)
409 strtok (src, "\r\n \t");
410 /* skip the initial white spaces */
411 while (isspace (*src))
428 /*-----------------------------------------------------------------*/
429 /* setDefaultOptions - sets the default options */
430 /*-----------------------------------------------------------------*/
436 for (i = 0; i < 128; i++)
437 preArgv[i] = asmOptions[i] =
438 linkOptions[i] = relFiles[i] = libFiles[i] =
441 /* first the options part */
442 options.stack_loc = 0; /* stack pointer initialised to 0 */
443 options.xstack_loc = 0; /* xternal stack starts at 0 */
444 options.code_loc = 0; /* code starts at 0 */
445 options.data_loc = 0x0030; /* data starts at 0x0030 */
446 options.xdata_loc = 0;
447 options.idata_loc = 0x80;
448 options.genericPtr = 1; /* default on */
450 options.model = port->general.default_model;
451 options.nostdlib = 0;
452 options.nostdinc = 0;
454 options.shortis8bits = 0;
456 options.stack10bit=0;
458 /* now for the optimizations */
459 /* turn on the everything */
460 optimize.global_cse = 1;
465 optimize.loopInvariant = 1;
466 optimize.loopInduction = 1;
468 /* now for the ports */
469 port->setDefaultOptions ();
472 /*-----------------------------------------------------------------*/
473 /* processFile - determines the type of file from the extension */
474 /*-----------------------------------------------------------------*/
476 processFile (char *s)
480 /* get the file extension */
481 fext = s + strlen (s);
482 while ((fext != s) && *fext != '.')
485 /* now if no '.' then we don't know what the file type is
486 so give a warning and return */
489 werror (W_UNKNOWN_FEXT, s);
493 /* otherwise depending on the file type */
494 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
496 /* source file name : not if we already have a
500 werror (W_TOO_MANY_SRC, s);
504 /* the only source file */
505 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
507 werror (E_FILE_OPEN_ERR, s);
511 /* copy the file name into the buffer */
514 /* get rid of the "." */
515 strtok (buffer, ".");
516 srcFileName = Safe_alloc ( strlen (buffer) + 1);
517 strcpy (srcFileName, buffer);
519 /* get rid of any path information
520 for the module name; do this by going
521 backwards till we get to either '/' or '\' or ':'
522 or start of buffer */
523 fext = buffer + strlen (buffer);
524 while (fext != buffer &&
525 *(fext - 1) != '\\' &&
526 *(fext - 1) != '/' &&
529 moduleName = Safe_alloc ( strlen (fext) + 1);
530 strcpy (moduleName, fext);
535 /* if the extention is type .rel or .r or .REL or .R
536 addtional object file will be passed to the linker */
537 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
538 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
539 strcmp (fext, port->linker.rel_ext) == 0)
541 relFiles[nrelFiles++] = s;
545 /* if .lib or .LIB */
546 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
548 libFiles[nlibFiles++] = s;
552 werror (W_UNKNOWN_FEXT, s);
557 _processC1Arg (char *s)
561 if (options.out_name)
563 werror (W_TOO_MANY_SRC, s);
566 options.out_name = Safe_strdup (s);
575 _setModel (int model, const char *sz)
577 if (port->general.supported_models & model)
578 options.model = model;
580 werror (W_UNSUPPORTED_MODEL, sz, port->target);
583 /** Gets the string argument to this option. If the option is '--opt'
584 then for input of '--optxyz' or '--opt xyz' returns xyz.
587 getStringArg(const char *szStart, char **argv, int *pi, int argc)
589 if (argv[*pi][strlen(szStart)])
591 return &argv[*pi][strlen(szStart)];
598 werror (E_ARGUMENT_MISSING, szStart);
599 /* Die here rather than checking for errors later. */
609 /** Gets the integer argument to this option using the same rules as
613 getIntArg(const char *szStart, char **argv, int *pi, int argc)
615 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
619 verifyShortOption(const char *opt)
621 if (strlen(opt) != 2)
623 werror (W_EXCESS_SHORT_OPTIONS, opt);
628 tryHandleUnsupportedOpt(char **argv, int *pi)
630 if (argv[*pi][0] == '-')
632 const char *longOpt = "";
636 if (argv[*pi][1] == '-')
643 shortOpt = argv[*pi][1];
645 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
647 if (unsupportedOptTable[i].shortOpt == shortOpt ||
648 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
649 // Found an unsupported opt.
651 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
652 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
656 // Didn't find in the table
661 // Not an option, so can't be unsupported :)
667 tryHandleSimpleOpt(char **argv, int *pi)
669 if (argv[*pi][0] == '-')
671 const char *longOpt = "";
675 if (argv[*pi][1] == '-')
682 shortOpt = argv[*pi][1];
685 for (i = 0; i < LENGTH(optionsTable); i++)
687 if (optionsTable[i].shortOpt == shortOpt ||
688 (longOpt && optionsTable[i].longOpt &&
689 strcmp(optionsTable[i].longOpt, longOpt) == 0))
692 // If it is a flag then we can handle it here
693 if (optionsTable[i].pparameter != NULL)
695 if (optionsTable[i].shortOpt == shortOpt)
697 verifyShortOption(argv[*pi]);
700 (*optionsTable[i].pparameter)++;
704 // Not a flag. Handled manually later.
709 // Didn't find in the table
714 // Not an option, so can't be handled.
719 /*-----------------------------------------------------------------*/
720 /* parseCmdLine - parses the command line and sets the options */
721 /*-----------------------------------------------------------------*/
723 parseCmdLine (int argc, char **argv)
727 /* go thru all whole command line */
728 for (i = 1; i < argc; i++)
733 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
738 if (tryHandleSimpleOpt(argv, &i) == TRUE)
744 if (argv[i][0] == '-' && argv[i][1] == '-')
746 if (strcmp (argv[i], OPTION_HELP) == 0)
752 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
754 options.stack10bit = 0;
758 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
764 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
766 _setModel (MODEL_LARGE, argv[i]);
770 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
772 _setModel (MODEL_MEDIUM, argv[i]);
776 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
778 _setModel (MODEL_SMALL, argv[i]);
782 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
784 _setModel (MODEL_FLAT24, argv[i]);
788 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
790 options.dump_rassgn =
796 options.dump_raw = 1;
800 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
802 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
806 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
808 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
812 if (strcmp (argv[i], OPTION_VERSION) == 0)
819 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
821 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
825 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
827 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
831 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
833 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
837 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
839 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
843 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
845 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
849 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
851 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
855 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
857 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
861 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
863 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
867 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
869 optimize.global_cse = 0;
873 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
875 optimize.loopInvariant = 0;
879 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
881 optimize.loopInduction = 0;
885 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
887 options.lessPedantic = 1;
888 setErrorLogLevel(ERROR_LEVEL_WARNING);
892 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
894 options.shortis8bits=1;
898 if (!port->parseOption (&argc, argv, &i))
900 werror (W_UNKNOWN_OPTION, argv[i]);
908 /* if preceded by '-' then option */
914 verifyShortOption(argv[i]);
921 /* Used to select the port */
922 _setPort (argv[i] + 2);
926 verifyShortOption(argv[i]);
932 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
936 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
940 /* pre-processer options */
941 if (argv[i][2] == 'p')
943 parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
946 else if (argv[i][2] == 'l')
948 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
950 /* assembler options */
951 else if (argv[i][2] == 'a')
953 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
957 werror (W_UNKNOWN_OPTION, argv[i]);
962 verifyShortOption(argv[i]);
968 /* preprocessor options */
972 addToList (preArgv, "-M");
977 addToList (preArgv, "-C");
986 char sOpt = argv[i][1];
989 if (argv[i][2] == ' ' || argv[i][2] == '\0')
995 werror(E_ARGUMENT_MISSING, argv[i-1]);
1009 sprintf (buffer, "-%c%s", sOpt, rest);
1010 addToList (preArgv, buffer);
1015 if (!port->parseOption (&argc, argv, &i))
1016 werror (W_UNKNOWN_OPTION, argv[i]);
1021 if (!port->parseOption (&argc, argv, &i))
1023 /* no option must be a filename */
1025 _processC1Arg (argv[i]);
1027 processFile (argv[i]);
1031 /* set up external stack location if not explicitly specified */
1032 if (!options.xstack_loc)
1033 options.xstack_loc = options.xdata_loc;
1035 /* if debug option is set the open the cdbFile */
1036 if (options.debug && srcFileName)
1038 sprintf (scratchFileName, "%s.cdb", srcFileName);
1039 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1040 werror (E_FILE_OPEN_ERR, scratchFileName);
1043 /* add a module record */
1044 fprintf (cdbFile, "M:%s\n", moduleName);
1050 /*-----------------------------------------------------------------*/
1051 /* linkEdit : - calls the linkage editor with options */
1052 /*-----------------------------------------------------------------*/
1054 linkEdit (char **envp)
1061 srcFileName = "temp";
1063 /* first we need to create the <filename>.lnk file */
1064 sprintf (scratchFileName, "%s.lnk", srcFileName);
1065 if (!(lnkfile = fopen (scratchFileName, "w")))
1067 werror (E_FILE_OPEN_ERR, scratchFileName);
1071 /* now write the options */
1072 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1074 /* if iram size specified */
1075 if (options.iram_size)
1076 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1079 fprintf (lnkfile, "-z\n");
1081 #define WRITE_SEG_LOC(N, L) \
1082 segName = Safe_strdup(N); \
1083 c = strtok(segName, " \t"); \
1084 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1085 if (segName) { Safe_free(segName); }
1087 /* code segment start */
1088 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1090 /* data segment start */
1091 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1094 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1097 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1099 /* bit segment start */
1100 WRITE_SEG_LOC (BIT_NAME, 0);
1102 /* add the extra linker options */
1103 for (i = 0; linkOptions[i]; i++)
1104 fprintf (lnkfile, "%s\n", linkOptions[i]);
1106 /* other library paths if specified */
1107 for (i = 0; i < nlibPaths; i++)
1108 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1110 /* standard library path */
1111 if (!options.nostdlib)
1114 if (TARGET_IS_DS390)
1121 switch (options.model)
1134 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1139 mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
1141 /* standard library files */
1142 /* if (strcmp (port->target, "ds390") == 0) */
1143 if (options.model == MODEL_FLAT24)
1145 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1147 fprintf (lnkfile, "-l %s\n", STD_LIB);
1148 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1149 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1150 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1153 /* additional libraries if any */
1154 for (i = 0; i < nlibFiles; i++)
1155 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1157 /* put in the object files */
1158 if (strcmp (srcFileName, "temp"))
1159 fprintf (lnkfile, "%s ", srcFileName);
1161 for (i = 0; i < nrelFiles; i++)
1162 fprintf (lnkfile, "%s\n", relFiles[i]);
1164 fprintf (lnkfile, "\n-e\n");
1167 if (options.verbose)
1168 printf ("sdcc: Calling linker...\n");
1170 if (port->linker.cmd)
1172 char buffer2[PATH_MAX];
1173 buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1174 buildCmdLine2 (buffer, buffer2);
1178 buildCmdLine2 (buffer, port->linker.mcmd);
1181 if (my_system (buffer))
1186 if (strcmp (srcFileName, "temp") == 0)
1188 /* rename "temp.cdb" to "firstRelFile.cdb" */
1189 char *f = strtok (Safe_strdup (relFiles[0]), ".");
1190 f = strcat (f, ".cdb");
1191 rename ("temp.cdb", f);
1196 /*-----------------------------------------------------------------*/
1197 /* assemble - spawns the assembler with arguments */
1198 /*-----------------------------------------------------------------*/
1200 assemble (char **envp)
1202 if (port->assembler.cmd)
1204 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
1205 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1210 buildCmdLine2 (buffer, port->assembler.mcmd);
1213 if (my_system (buffer))
1215 /* either system() or the assembler itself has reported an error
1216 perror ("Cannot exec assembler");
1222 /*-----------------------------------------------------------------*/
1223 /* preProcess - spawns the preprocessor with arguments */
1224 /*-----------------------------------------------------------------*/
1226 preProcess (char **envp)
1230 if (!options.c1mode)
1232 /* if using external stack define the macro */
1233 if (options.useXstack)
1234 addToList (preArgv, "-DSDCC_USE_XSTACK");
1236 /* set the macro for stack autos */
1237 if (options.stackAuto)
1238 addToList (preArgv, "-DSDCC_STACK_AUTO");
1240 /* set the macro for stack autos */
1241 if (options.stack10bit)
1242 addToList (preArgv, "-DSDCC_STACK_TENBIT");
1244 /* set the macro for no overlay */
1245 if (options.noOverlay)
1246 addToList (preArgv, "-DSDCC_NOOVERLAY");
1248 /* set the macro for large model */
1249 switch (options.model)
1252 addToList (preArgv, "-DSDCC_MODEL_LARGE");
1255 addToList (preArgv, "-DSDCC_MODEL_SMALL");
1258 addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1261 addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1264 addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1267 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1271 /* add port (processor information to processor */
1272 addToList (preArgv, "-DSDCC_{port}");
1273 addToList (preArgv, "-D__{port}");
1275 /* standard include path */
1276 if (!options.nostdinc) {
1277 addToList (preArgv, "-I{includedir}");
1280 setMainValue ("cppextraopts", join(preArgv));
1283 preOutName = Safe_strdup (tempfilename ());
1285 /* Have to set cppoutfilename to something, even if just pre-processing. */
1286 setMainValue ("cppoutfilename", preOutName ? preOutName : "");
1288 if (options.verbose)
1289 printf ("sdcc: Calling preprocessor...\n");
1291 buildCmdLine2 (buffer, _preCmd);
1293 if (my_system (buffer))
1295 // @FIX: Dario Vecchio 03-05-2001
1298 unlink (preOutName);
1299 Safe_free (preOutName);
1312 preOutName = fullSrcFileName;
1315 yyin = fopen (preOutName, "r");
1318 perror ("Preproc file not found\n");
1326 _setPaths (const char *pprefix)
1329 Given the prefix and how the directories were layed out at
1330 configure time, see if the library and include directories are
1331 where expected. If so, set.
1333 getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
1334 strcpy (scratchFileName, pprefix);
1335 strcat (scratchFileName, buffer);
1337 if (pathExists (scratchFileName))
1339 setMainValue ("includedir", scratchFileName);
1346 getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
1347 strcpy (scratchFileName, pprefix);
1348 strcat (scratchFileName, buffer);
1350 if (pathExists (scratchFileName))
1352 setMainValue ("libdir", scratchFileName);
1363 _discoverPaths (const char *argv0)
1366 1. Try the SDCCDIR environment variable.
1367 2. If (1) fails, and if the argv[0] includes a path, attempt to find the include
1368 and library paths with respect to that. Note that under win32
1369 argv[0] is always the full path to the program.
1370 3. If (1) and (2) fail, fall back to the compile time defaults.
1372 Detecting assumes the same layout as when configured. If the
1373 directories have been further moved about then discovery will
1377 /* Some input cases:
1378 "c:\fish\sdcc\bin\sdcc"
1380 "/home/fish/bin/sdcc"
1382 Note that ./sdcc is explicitly not supported as there isn't
1385 /* bindir is handled differently to the lib and include directories.
1386 It's rather unfortunate, but required due to the different
1387 install and development layouts. Logic is different as well.
1390 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1392 strcpy (scratchFileName, argv0);
1393 *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
1394 setMainValue ("bindir", scratchFileName);
1395 ExePathList[0] = Safe_strdup (scratchFileName);
1397 else if (getenv (SDCCDIR_NAME) != NULL)
1399 getPathDifference (buffer, PREFIX, BINDIR);
1400 strcpy (scratchFileName, getenv (SDCCDIR_NAME));
1401 strcat (scratchFileName, buffer);
1402 setMainValue ("bindir", scratchFileName);
1403 ExePathList[0] = Safe_strdup (scratchFileName);
1407 setMainValue ("bindir", BINDIR);
1408 ExePathList[0] = BINDIR;
1414 if (getenv (SDCCDIR_NAME) != NULL)
1416 if (_setPaths (getenv (SDCCDIR_NAME)))
1418 /* Successfully set. */
1423 /* Include and lib weren't where expected. */
1427 if (strchr (argv0, DIR_SEPARATOR_CHAR))
1429 char *pbase = getPrefixFromBinPath (argv0);
1433 /* A bad path. Skip. */
1437 if (_setPaths (pbase))
1439 /* Successfully set. */
1444 /* Include and lib weren't where expected. */
1449 setMainValue ("includedir", SDCC_INCLUDE_DIR);
1450 setMainValue ("libdir", SDCC_LIB_DIR);
1457 populateMainValues (_baseValues);
1458 setMainValue ("port", port->target);
1459 setMainValue ("objext", port->linker.rel_ext);
1460 setMainValue ("asmext", port->assembler.file_ext);
1462 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
1463 setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
1468 * initialises and calls the parser
1472 main (int argc, char **argv, char **envp)
1474 /* turn all optimizations off by default */
1475 memset (&optimize, 0, sizeof (struct optimize));
1477 /*printVersionInfo (); */
1480 fprintf (stderr, "Build error: no ports are enabled.\n");
1484 _findPort (argc, argv);
1486 if (strcmp(port->target, "mcs51") == 0) {
1487 printf("DS390 jammed in A\n");
1492 /* Initalise the port. */
1496 // Create a default exe search path from the path to the sdcc command
1499 setDefaultOptions ();
1502 options.model = MODEL_SMALL;
1503 options.stack10bit=0;
1506 parseCmdLine (argc, argv);
1508 /* if no input then printUsage & exit */
1509 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1510 (options.c1mode && !srcFileName && !options.out_name))
1517 _discoverPaths (argv[0]);
1525 port->finaliseOptions ();
1532 if (options.verbose)
1533 printf ("sdcc: Generating code...\n");
1539 if (TARGET_IS_PIC) {
1540 /* TSD PIC port hack - if the PIC port option is enabled
1541 and SDCC is used to generate PIC code, then we will
1542 generate .asm files in gpasm's format instead of SDCC's
1545 #if !OPT_DISABLE_PIC
1554 // @FIX: Dario Vecchio 03-05-2001
1557 if (yyin && yyin != stdin)
1559 unlink (preOutName);
1560 Safe_free (preOutName);
1565 if (!options.c1mode && !noAssemble)
1567 if (options.verbose)
1568 printf ("sdcc: Calling assembler...\n");
1574 // @FIX: Dario Vecchio 03-05-2001
1577 if (yyin && yyin != stdin)
1579 unlink (preOutName);
1580 Safe_free (preOutName);
1583 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1596 if (preOutName && !options.c1mode)
1598 unlink (preOutName);
1599 Safe_free (preOutName);
1602 if (!options.cc_only &&
1606 (srcFileName || nrelFiles))
1608 if (port->linker.do_link)
1609 port->linker.do_link ();
1614 if (yyin && yyin != stdin)