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 -------------------------------------------------------------------------*/
38 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
43 extern int yyparse ();
45 FILE *srcFile; /* source file */
46 FILE *cdbFile = NULL; /* debugger information output file */
47 char *fullSrcFileName; /* full name for the source file */
48 char *srcFileName; /* source file name with the .c stripped */
49 char *moduleName; /* module name is srcFilename stripped of any path */
50 const char *preArgv[128]; /* pre-processor arguments */
52 struct optimize optimize;
53 struct options options;
54 char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a" */ ;
57 char *linkOptions[128];
58 const char *asmOptions[128];
65 bool verboseExec = FALSE;
68 // Globally accessible scratch buffer for file names.
69 char scratchFileName[FILENAME_MAX];
71 // In MSC VC6 default search path for exe's to path for this
73 char DefaultExePath[128];
75 #define OPTION_HELP "-help"
77 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
79 #define OPTION_STACK_8BIT "--stack-8bit"
80 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
81 #define OPTION_LARGE_MODEL "--model-large"
82 #define OPTION_MEDIUM_MODEL "--model-medium"
83 #define OPTION_SMALL_MODEL "--model-small"
84 #define OPTION_FLAT24_MODEL "--model-flat24"
85 #define OPTION_DUMP_ALL "--dumpall"
86 #define OPTION_PEEP_FILE "--peep-file"
87 #define OPTION_LIB_PATH "--lib-path"
88 #define OPTION_XSTACK_LOC "--xstack-loc"
89 #define OPTION_CALLEE_SAVES "--callee-saves"
90 #define OPTION_STACK_LOC "--stack-loc"
91 #define OPTION_XRAM_LOC "--xram-loc"
92 #define OPTION_IRAM_SIZE "--iram-size"
93 #define OPTION_VERSION "--version"
94 #define OPTION_DATA_LOC "--data-loc"
95 #define OPTION_CODE_LOC "--code-loc"
96 #define OPTION_IDATA_LOC "--idata-loc"
97 #define OPTION_NO_LOOP_INV "--noinvariant"
98 #define OPTION_NO_LOOP_IND "--noinduction"
99 #define OPTION_LESS_PEDANTIC "--lesspedantic"
100 #define OPTION_NO_GCSE "--nogcse"
101 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
103 /** Table of all options supported by all ports.
105 * A reference for all options.
106 * An easy way to maintain help for the options.
107 * Automatic support for setting flags on simple options.
110 /** The short option character e.g. 'h' for -h. 0 for none. */
112 /** Long option e.g. "--help". Includes the -- prefix. NULL for
115 /** Pointer to an int that will be incremented every time the
116 option is encountered. May be NULL.
119 /** Help text to go with this option. May be NULL. */
125 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
126 { 'd', NULL, NULL, NULL },
127 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
128 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
129 { 'A', NULL, NULL, NULL },
130 { 'U', NULL, NULL, NULL },
131 { 'C', NULL, NULL, "Preprocessor option" },
132 { 'M', NULL, NULL, "Preprocessor option" },
133 { 'V', NULL, &verboseExec, "Execute verbosely. Show sub commands as they are run" },
134 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
135 { 'W', NULL, NULL, "Pass through options to the assembler (a) or linker (l)" },
136 { 'L', NULL, NULL, "Add the next field to the library search path" },
137 { 'l', NULL, NULL, "Include the given library in the link" },
138 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
139 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
140 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
141 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
142 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
143 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
144 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
145 { 0, "--xstack", &options.useXstack, "Use external stack" },
146 { 0, "--generic", &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
147 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
148 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
149 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
150 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
151 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
152 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
153 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
154 { 0, "--dumpgcse", &options.dump_gcse, NULL },
155 { 0, "--dumploop", &options.dump_loop, NULL },
156 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
157 { 0, "--dumpliverange", &options.dump_range, NULL },
158 { 0, "--dumpregpack", &options.dump_pack, NULL },
159 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
160 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
161 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
162 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
163 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
164 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
165 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
166 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
167 { 0, OPTION_IDATA_LOC, NULL, NULL },
168 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
169 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
170 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
171 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the floar support functions" },
172 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
173 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
174 { 0, "--cyclomatic", &options.cyclomatic, NULL },
175 { 0, "--nooverlay", &options.noOverlay, NULL },
176 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
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" }
195 /** Table of all unsupported options and help text to display when one
199 /** shortOpt as in OPTIONS. */
201 /** longOpt as in OPTIONS. */
203 /** Message to display inside W_UNSUPPORTED_OPT when this option
208 static const UNSUPPORTEDOPT
209 unsupportedOptTable[] = {
210 { 'a', NULL, "use --stack-auto instead." },
211 { 'g', NULL, "use --generic instead" },
212 { 'X', NULL, "use --xstack-loc instead" },
213 { 'x', NULL, "use --xstack instead" },
214 { 'p', NULL, "use --stack-loc instead" },
215 { 'P', NULL, "use --stack-loc instead" },
216 { 'i', NULL, "use --idata-loc instead" },
217 { 'r', NULL, "use --xdata-loc instead" },
218 { 's', NULL, "use --code-loc instead" },
219 { 'Y', NULL, "use -I instead" }
222 static const char *_preCmd[] =
224 "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1",
225 "$l", "$1", "$2", NULL
230 static PORT *_ports[] =
232 #if !OPT_DISABLE_MCS51
235 #if !OPT_DISABLE_GBZ80
244 #if !OPT_DISABLE_DS390
250 #if !OPT_DISABLE_I186
253 #if !OPT_DISABLE_TLCS900H
258 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
261 remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
263 extern void picglue ();
265 /** Sets the port to the one given by the command line option.
266 @param The name minus the option (eg 'mcs51')
267 @return 0 on success.
270 _setPort (const char *name)
273 for (i = 0; i < NUM_PORTS; i++)
275 if (!strcmp (_ports[i]->target, name))
281 /* Error - didnt find */
282 werror (E_UNKNOWN_TARGET, name);
287 _validatePorts (void)
290 for (i = 0; i < NUM_PORTS; i++)
292 if (_ports[i]->magic != PORT_MAGIC)
294 wassertl (0, "Port definition structure is incomplete");
298 /*-----------------------------------------------------------------*/
299 /* printVersionInfo - prints the version info */
300 /*-----------------------------------------------------------------*/
308 for (i = 0; i < NUM_PORTS; i++)
309 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
311 fprintf (stderr, " %s"
312 #ifdef SDCC_SUB_VERSION_STR
313 "/" SDCC_SUB_VERSION_STR
321 #if defined(_MSC_VER)
333 /*-----------------------------------------------------------------*/
334 /* printUsage - prints command line syntax */
335 /*-----------------------------------------------------------------*/
342 "Usage : sdcc [options] filename\n"
346 for (i = 0; i < LENGTH(optionsTable); i++) {
347 fprintf(stdout, " %c%c %-20s %s\n",
348 optionsTable[i].shortOpt !=0 ? '-' : ' ',
349 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
350 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
351 optionsTable[i].help != NULL ? optionsTable[i].help : ""
357 /*-----------------------------------------------------------------*/
358 /* parseWithComma - separates string with comma */
359 /*-----------------------------------------------------------------*/
361 parseWithComma (char **dest, char *src)
365 strtok (src, "\r\n \t");
366 /* skip the initial white spaces */
367 while (isspace (*src))
384 /*-----------------------------------------------------------------*/
385 /* setDefaultOptions - sets the default options */
386 /*-----------------------------------------------------------------*/
392 for (i = 0; i < 128; i++)
393 preArgv[i] = asmOptions[i] =
394 linkOptions[i] = relFiles[i] = libFiles[i] =
397 /* first the options part */
398 options.stack_loc = 0; /* stack pointer initialised to 0 */
399 options.xstack_loc = 0; /* xternal stack starts at 0 */
400 options.code_loc = 0; /* code starts at 0 */
401 options.data_loc = 0x0030; /* data starts at 0x0030 */
402 options.xdata_loc = 0;
403 options.idata_loc = 0x80;
404 options.genericPtr = 1; /* default on */
406 options.model = port->general.default_model;
407 options.nostdlib = 0;
408 options.nostdinc = 0;
410 options.shortis8bits = 0;
412 options.stack10bit=0;
414 /* now for the optimizations */
415 /* turn on the everything */
416 optimize.global_cse = 1;
421 optimize.loopInvariant = 1;
422 optimize.loopInduction = 1;
424 /* now for the ports */
425 port->setDefaultOptions ();
428 /*-----------------------------------------------------------------*/
429 /* processFile - determines the type of file from the extension */
430 /*-----------------------------------------------------------------*/
432 processFile (char *s)
436 /* get the file extension */
437 fext = s + strlen (s);
438 while ((fext != s) && *fext != '.')
441 /* now if no '.' then we don't know what the file type is
442 so give a warning and return */
445 werror (W_UNKNOWN_FEXT, s);
449 /* otherwise depending on the file type */
450 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
452 /* source file name : not if we already have a
456 werror (W_TOO_MANY_SRC, s);
460 /* the only source file */
461 if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
463 werror (E_FILE_OPEN_ERR, s);
467 /* copy the file name into the buffer */
470 /* get rid of the "." */
471 strtok (buffer, ".");
472 srcFileName = Safe_calloc (1, strlen (buffer) + 1);
473 strcpy (srcFileName, buffer);
475 /* get rid of any path information
476 for the module name; do this by going
477 backwards till we get to either '/' or '\' or ':'
478 or start of buffer */
479 fext = buffer + strlen (buffer);
480 while (fext != buffer &&
481 *(fext - 1) != '\\' &&
482 *(fext - 1) != '/' &&
485 moduleName = Safe_calloc (1, strlen (fext) + 1);
486 strcpy (moduleName, fext);
491 /* if the extention is type .rel or .r or .REL or .R
492 addtional object file will be passed to the linker */
493 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
494 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
495 strcmp (fext, port->linker.rel_ext) == 0)
497 relFiles[nrelFiles++] = s;
501 /* if .lib or .LIB */
502 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
504 libFiles[nlibFiles++] = s;
508 werror (W_UNKNOWN_FEXT, s);
513 _processC1Arg (char *s)
517 if (options.out_name)
519 werror (W_TOO_MANY_SRC, s);
522 options.out_name = strdup (s);
531 _addToList (const char **list, const char *str)
533 /* This is the bad way to do things :) */
536 *list = strdup (str);
539 werror (E_OUT_OF_MEM, __FILE__, 0);
546 _setModel (int model, const char *sz)
548 if (port->general.supported_models & model)
549 options.model = model;
551 werror (W_UNSUPPORTED_MODEL, sz, port->target);
554 /** Gets the string argument to this option. If the option is '--opt'
555 then for input of '--optxyz' or '--opt xyz' returns xyz.
558 getStringArg(const char *szStart, char **argv, int *pi, int argc)
560 if (argv[*pi][strlen(szStart)])
562 return &argv[*pi][strlen(szStart)];
569 werror (E_ARGUMENT_MISSING, szStart);
570 /* Die here rather than checking for errors later. */
580 /** Gets the integer argument to this option using the same rules as
584 getIntArg(const char *szStart, char **argv, int *pi, int argc)
586 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
590 verifyShortOption(const char *opt)
592 if (strlen(opt) != 2)
594 werror (W_EXCESS_SHORT_OPTIONS, opt);
599 tryHandleUnsupportedOpt(char **argv, int *pi)
601 if (argv[*pi][0] == '-')
603 const char *longOpt = "";
607 if (argv[*pi][1] == '-')
614 shortOpt = argv[*pi][1];
616 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
618 if (unsupportedOptTable[i].shortOpt == shortOpt ||
619 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
620 // Found an unsupported opt.
622 sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
623 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
627 // Didn't find in the table
632 // Not an option, so can't be unsupported :)
638 tryHandleSimpleOpt(char **argv, int *pi)
640 if (argv[*pi][0] == '-')
642 const char *longOpt = "";
646 if (argv[*pi][1] == '-')
653 shortOpt = argv[*pi][1];
656 for (i = 0; i < LENGTH(optionsTable); i++)
658 if (optionsTable[i].shortOpt == shortOpt ||
659 (longOpt && optionsTable[i].longOpt &&
660 strcmp(optionsTable[i].longOpt, longOpt) == 0))
663 // If it is a flag then we can handle it here
664 if (optionsTable[i].pparameter != NULL)
666 if (optionsTable[i].shortOpt == shortOpt)
668 verifyShortOption(argv[*pi]);
671 (*optionsTable[i].pparameter)++;
675 // Not a flag. Handled manually later.
680 // Didn't find in the table
685 // Not an option, so can't be handled.
690 /*-----------------------------------------------------------------*/
691 /* parseCmdLine - parses the command line and sets the options */
692 /*-----------------------------------------------------------------*/
694 parseCmdLine (int argc, char **argv)
698 /* go thru all whole command line */
699 for (i = 1; i < argc; i++)
704 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
709 if (tryHandleSimpleOpt(argv, &i) == TRUE)
715 if (argv[i][0] == '-' && argv[i][1] == '-')
717 if (strcmp (argv[i], OPTION_HELP) == 0)
723 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
725 options.stack10bit = 0;
729 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
735 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
737 _setModel (MODEL_LARGE, argv[i]);
741 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
743 _setModel (MODEL_MEDIUM, argv[i]);
747 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
749 _setModel (MODEL_SMALL, argv[i]);
753 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
755 _setModel (MODEL_FLAT24, argv[i]);
759 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
761 options.dump_rassgn =
767 options.dump_raw = 1;
771 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
773 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
777 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
779 libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
783 if (strcmp (argv[i], OPTION_VERSION) == 0)
790 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
792 parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
796 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
798 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
802 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
804 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
808 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
810 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
814 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
816 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
820 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
822 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
826 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
828 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
832 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
834 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
838 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
840 optimize.global_cse = 0;
844 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
846 optimize.loopInvariant = 0;
850 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
852 optimize.loopInduction = 0;
856 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
858 setErrorLogLevel(ERROR_LEVEL_WARNING);
862 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
864 options.shortis8bits=1;
868 if (!port->parseOption (&argc, argv, &i))
870 werror (W_UNKNOWN_OPTION, argv[i]);
878 /* if preceded by '-' then option */
884 verifyShortOption(argv[i]);
891 /* Used to select the port */
892 _setPort (argv[i] + 2);
896 verifyShortOption(argv[i]);
902 libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
906 libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
911 if (argv[i][2] == 'l')
913 parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
917 /* assembler options */
918 if (argv[i][2] == 'a')
920 parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
924 werror (W_UNKNOWN_OPTION, argv[i]);
930 verifyShortOption(argv[i]);
936 /* preprocessor options */
940 _addToList (preArgv, "-M");
945 _addToList (preArgv, "-C");
954 char sOpt = argv[i][1];
957 if (argv[i][2] == ' ' || argv[i][2] == '\0')
963 werror(E_ARGUMENT_MISSING, argv[i-1]);
977 sprintf (buffer, "-%c%s", sOpt, rest);
978 _addToList (preArgv, buffer);
983 if (!port->parseOption (&argc, argv, &i))
984 werror (W_UNKNOWN_OPTION, argv[i]);
989 if (!port->parseOption (&argc, argv, &i))
991 /* no option must be a filename */
993 _processC1Arg (argv[i]);
995 processFile (argv[i]);
999 /* set up external stack location if not explicitly specified */
1000 if (!options.xstack_loc)
1001 options.xstack_loc = options.xdata_loc;
1003 /* if debug option is set the open the cdbFile */
1004 if (options.debug && srcFileName)
1006 sprintf (scratchFileName, "%s.cdb", srcFileName);
1007 if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
1008 werror (E_FILE_OPEN_ERR, scratchFileName);
1011 /* add a module record */
1012 fprintf (cdbFile, "M:%s\n", moduleName);
1018 /*-----------------------------------------------------------------*/
1019 /* linkEdit : - calls the linkage editor with options */
1020 /*-----------------------------------------------------------------*/
1022 linkEdit (char **envp)
1029 srcFileName = "temp";
1031 /* first we need to create the <filename>.lnk file */
1032 sprintf (scratchFileName, "%s.lnk", srcFileName);
1033 if (!(lnkfile = fopen (scratchFileName, "w")))
1035 werror (E_FILE_OPEN_ERR, scratchFileName);
1039 /* now write the options */
1040 fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
1042 /* if iram size specified */
1043 if (options.iram_size)
1044 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1047 fprintf (lnkfile, "-z\n");
1049 #define WRITE_SEG_LOC(N, L) \
1050 segName = strdup(N); \
1051 c = strtok(segName, " \t"); \
1052 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1053 if (segName) { free(segName); }
1055 /* code segment start */
1056 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1058 /* data segment start */
1059 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1062 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1065 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1067 /* bit segment start */
1068 WRITE_SEG_LOC (BIT_NAME, 0);
1070 /* add the extra linker options */
1071 for (i = 0; linkOptions[i]; i++)
1072 fprintf (lnkfile, "%s\n", linkOptions[i]);
1074 /* other library paths if specified */
1075 for (i = 0; i < nlibPaths; i++)
1076 fprintf (lnkfile, "-k %s\n", libPaths[i]);
1078 /* standard library path */
1079 if (!options.nostdlib)
1081 if (TARGET_IS_DS390)
1087 switch (options.model)
1099 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1104 fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
1106 /* standard library files */
1107 if (strcmp (port->target, "ds390") == 0)
1109 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1111 fprintf (lnkfile, "-l %s\n", STD_LIB);
1112 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1113 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1114 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1117 /* additional libraries if any */
1118 for (i = 0; i < nlibFiles; i++)
1119 fprintf (lnkfile, "-l %s\n", libFiles[i]);
1121 /* put in the object files */
1122 if (strcmp (srcFileName, "temp"))
1123 fprintf (lnkfile, "%s ", srcFileName);
1125 for (i = 0; i < nrelFiles; i++)
1126 fprintf (lnkfile, "%s\n", relFiles[i]);
1128 fprintf (lnkfile, "\n-e\n");
1131 if (options.verbose)
1132 printf ("sdcc: Calling linker...\n");
1134 buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1135 if (my_system (buffer))
1140 if (strcmp (srcFileName, "temp") == 0)
1142 /* rename "temp.cdb" to "firstRelFile.cdb" */
1143 char *f = strtok (strdup (relFiles[0]), ".");
1144 f = strcat (f, ".cdb");
1145 rename ("temp.cdb", f);
1150 /*-----------------------------------------------------------------*/
1151 /* assemble - spawns the assembler with arguments */
1152 /*-----------------------------------------------------------------*/
1154 assemble (char **envp)
1156 buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1157 if (my_system (buffer))
1159 /* either system() or the assembler itself has reported an error
1160 perror ("Cannot exec assembler");
1168 /*-----------------------------------------------------------------*/
1169 /* preProcess - spawns the preprocessor with arguments */
1170 /*-----------------------------------------------------------------*/
1172 preProcess (char **envp)
1178 if (!options.c1mode)
1180 /* if using external stack define the macro */
1181 if (options.useXstack)
1182 _addToList (preArgv, "-DSDCC_USE_XSTACK");
1184 /* set the macro for stack autos */
1185 if (options.stackAuto)
1186 _addToList (preArgv, "-DSDCC_STACK_AUTO");
1188 /* set the macro for stack autos */
1189 if (options.stack10bit)
1190 _addToList (preArgv, "-DSDCC_STACK_TENBIT");
1192 /* set the macro for large model */
1193 switch (options.model)
1196 _addToList (preArgv, "-DSDCC_MODEL_LARGE");
1199 _addToList (preArgv, "-DSDCC_MODEL_SMALL");
1202 _addToList (preArgv, "-DSDCC_MODEL_COMPACT");
1205 _addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
1208 _addToList (preArgv, "-DSDCC_MODEL_FLAT24");
1211 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1215 /* standard include path */
1216 if (!options.nostdinc) {
1217 _addToList (preArgv, "-I" SDCC_INCLUDE_DIR);
1220 /* add port (processor information to processor */
1221 sprintf (procDef, "-DSDCC_%s", port->target);
1222 _addToList (preArgv, procDef);
1223 sprintf (procDef, "-D__%s", port->target);
1224 _addToList (preArgv, procDef);
1227 preOutName = strdup (tmpnam (NULL));
1229 if (options.verbose)
1230 printf ("sdcc: Calling preprocessor...\n");
1232 buildCmdLine (buffer, _preCmd, fullSrcFileName,
1233 preOutName, srcFileName, preArgv);
1234 if (my_system (buffer))
1236 // @FIX: Dario Vecchio 03-05-2001
1239 unlink (preOutName);
1253 preOutName = fullSrcFileName;
1256 yyin = fopen (preOutName, "r");
1259 perror ("Preproc file not found\n");
1267 _findPort (int argc, char **argv)
1273 if (!strncmp (*argv, "-m", 2))
1275 _setPort (*argv + 2);
1280 /* Use the first in the list */
1286 * initialises and calls the parser
1290 main (int argc, char **argv, char **envp)
1292 /* turn all optimizations off by default */
1293 memset (&optimize, 0, sizeof (struct optimize));
1295 /*printVersionInfo (); */
1298 fprintf (stderr, "Build error: no ports are enabled.\n");
1302 _findPort (argc, argv);
1303 /* Initalise the port. */
1307 // Create a default exe search path from the path to the sdcc command
1311 if (strchr (argv[0], DIR_SEPARATOR_CHAR))
1313 strcpy (DefaultExePath, argv[0]);
1314 *(strrchr (DefaultExePath, DIR_SEPARATOR_CHAR)) = 0;
1315 ExePathList[0] = DefaultExePath;
1319 setDefaultOptions ();
1320 parseCmdLine (argc, argv);
1322 /* if no input then printUsage & exit */
1323 if ((!options.c1mode && !srcFileName && !nrelFiles) ||
1324 (options.c1mode && !srcFileName && !options.out_name))
1336 port->finaliseOptions ();
1343 if (options.verbose)
1344 printf ("sdcc: Generating code...\n");
1350 if (TARGET_IS_PIC) {
1351 /* TSD PIC port hack - if the PIC port option is enabled
1352 and SDCC is used to generate PIC code, then we will
1353 generate .asm files in gpasm's format instead of SDCC's
1356 #if !OPT_DISABLE_PIC
1365 // @FIX: Dario Vecchio 03-05-2001
1368 if (yyin && yyin != stdin)
1370 unlink (preOutName);
1376 if (!options.c1mode && !noAssemble)
1378 if (options.verbose)
1379 printf ("sdcc: Calling assembler...\n");
1385 // @FIX: Dario Vecchio 03-05-2001
1388 if (yyin && yyin != stdin)
1390 unlink (preOutName);
1394 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1407 if (preOutName && !options.c1mode)
1409 unlink (preOutName);
1413 if (!options.cc_only &&
1417 (srcFileName || nrelFiles))
1419 if (port->linker.do_link)
1420 port->linker.do_link ();
1425 if (yyin && yyin != stdin)