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 #include "SDCCmacro.h"
40 #include "SDCCdebug.h"
51 extern int yyparse (void);
53 FILE *srcFile; /* source file */
54 char *fullSrcFileName; /* full name for the source file; */
55 /* can be NULL while c1mode or linking without compiling */
56 char *fullDstFileName; /* full name for the output file; */
57 /* only given by -o, otherwise NULL */
58 char *dstFileName; /* destination file name without extension */
59 char *dstPath = ""; /* path for the output files; */
60 /* "" is equivalent with cwd */
61 char *moduleNameBase; /* module name base is source file without path and extension */
62 /* can be NULL while linking without compiling */
63 char *moduleName; /* module name is same as module name base, but with all */
64 /* non-alphanumeric characters replaced with underscore */
66 int RegBankUsed[4] = {1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
67 struct optimize optimize;
68 struct options options;
71 set *preArgvSet = NULL; /* pre-processor arguments */
72 set *asmOptionsSet = NULL; /* set of assembler options */
73 set *linkOptionsSet = NULL; /* set of linker options */
74 set *libFilesSet = NULL;
75 set *libPathsSet = NULL;
76 set *relFilesSet = NULL;
77 set *dataDirsSet = NULL; /* list of data search directories */
78 set *includeDirsSet = NULL; /* list of include search directories */
79 set *libDirsSet = NULL; /* list of lib search directories */
81 /* uncomment JAMIN_DS390 to always override and use ds390 port
82 for mcs51 work. This is temporary, for compatibility testing. */
83 /* #define JAMIN_DS390 */
88 /* Globally accessible scratch buffer for file names. */
89 char scratchFileName[PATH_MAX];
90 char buffer[PATH_MAX * 2];
92 #define OPTION_HELP "-help"
94 #define LENGTH(_a) (sizeof(_a)/sizeof(*(_a)))
96 #define OPTION_STACK_8BIT "--stack-8bit"
97 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
98 #define OPTION_LARGE_MODEL "--model-large"
99 #define OPTION_MEDIUM_MODEL "--model-medium"
100 #define OPTION_SMALL_MODEL "--model-small"
101 #define OPTION_FLAT24_MODEL "--model-flat24"
102 #define OPTION_DUMP_ALL "--dumpall"
103 #define OPTION_PEEP_FILE "--peep-file"
104 #define OPTION_LIB_PATH "--lib-path"
105 #define OPTION_XSTACK_LOC "--xstack-loc"
106 #define OPTION_CALLEE_SAVES "--callee-saves"
107 #define OPTION_STACK_LOC "--stack-loc"
108 #define OPTION_XRAM_LOC "--xram-loc"
109 #define OPTION_IRAM_SIZE "--iram-size"
110 #define OPTION_VERSION "--version"
111 #define OPTION_DATA_LOC "--data-loc"
112 #define OPTION_CODE_LOC "--code-loc"
113 #define OPTION_IDATA_LOC "--idata-loc"
114 #define OPTION_NO_LABEL_OPT "--nolabelopt"
115 #define OPTION_NO_LOOP_INV "--noinvariant"
116 #define OPTION_NO_LOOP_IND "--noinduction"
117 #define OPTION_LESS_PEDANTIC "--less-pedantic"
118 #define OPTION_DISABLE_WARNING "--disable-warning"
119 #define OPTION_NO_GCSE "--nogcse"
120 #define OPTION_SHORT_IS_8BITS "--short-is-8bits"
121 #define OPTION_TINI_LIBID "--tini-libid"
122 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
123 #define OPTION_XRAM_SIZE "--xram-size"
124 #define OPTION_CODE_SIZE "--code-size"
125 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
126 #define OPTION_ICODE_IN_ASM "--i-code-in-asm"
127 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
128 #define OPTION_MSVC_ERROR_STYLE "--vc"
129 #define OPTION_USE_STDOUT "--use-stdout"
130 #define OPTION_STACK_SIZE "--stack-size"
131 #define OPTION_PACK_IRAM "--pack-iram"
132 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
136 { 'm', NULL, NULL, "Set the port to use e.g. -mz80." },
137 { 'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
138 { 'd', NULL, NULL, NULL },
139 { 'D', NULL, NULL, "Define macro as in -Dmacro" },
140 { 'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath" },
141 { 'A', NULL, NULL, NULL },
142 { 'U', NULL, NULL, NULL },
143 { 'C', NULL, NULL, "Preprocessor option" },
144 { 'M', NULL, NULL, "Preprocessor option" },
145 { 'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run" },
146 { 'S', NULL, &noAssemble, "Compile only; do not assemble or link" },
147 { 'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
148 { 'L', NULL, NULL, "Add the next field to the library search path" },
149 { 'l', NULL, NULL, "Include the given library in the link" },
150 { 0, OPTION_LARGE_MODEL, NULL, "external data space is used" },
151 { 0, OPTION_MEDIUM_MODEL, NULL, "not supported" },
152 { 0, OPTION_SMALL_MODEL, NULL, "internal data space is used (default)" },
153 #if !OPT_DISABLE_DS390
154 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
156 { 0, "--stack-auto", &options.stackAuto, "Stack automatic variables" },
157 #if !OPT_DISABLE_DS390
158 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
159 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
161 { 0, "--xstack", &options.useXstack, "Use external stack" },
162 { 0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation" },
163 { 0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation" },
164 { 0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants" },
165 { 0, OPTION_NO_LOOP_IND, NULL, NULL },
166 { 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
167 { 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
168 { 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
169 { 'o', NULL, NULL, "Place the output into the given path resp. file" },
170 { 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
171 { 0, "--dumpgcse", &options.dump_gcse, NULL },
172 { 0, "--dumploop", &options.dump_loop, NULL },
173 { 0, "--dumpdeadcode", &options.dump_kill, NULL },
174 { 0, "--dumpliverange", &options.dump_range, NULL },
175 { 0, "--dumpregpack", &options.dump_pack, NULL },
176 { 0, "--dumpregassign", &options.dump_rassgn, NULL },
177 { 0, "--dumptree", &options.dump_tree, "dump front-end AST before generating iCode" },
178 { 0, OPTION_DUMP_ALL, NULL, "Dump the internal structure at all stages" },
179 { 0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location" },
180 { 0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size" },
181 { 0, OPTION_IRAM_SIZE, NULL, "<nnnn> Internal Ram size" },
182 { 0, OPTION_XSTACK_LOC, NULL, "<nnnn> External Ram start location" },
183 { 0, OPTION_CODE_LOC, NULL, "<nnnn> Code Segment Location" },
184 { 0, OPTION_CODE_SIZE, NULL, "<nnnn> Code Segment size" },
185 { 0, OPTION_STACK_LOC, NULL, "<nnnn> Stack pointer initial value" },
186 { 0, OPTION_DATA_LOC, NULL, "<nnnn> Direct data start location" },
187 { 0, OPTION_IDATA_LOC, NULL, NULL },
188 { 0, OPTION_PEEP_FILE, NULL, "<file> use this extra peep-hole file" },
189 { 0, OPTION_LIB_PATH, NULL, "<path> use this path to search for libraries" },
190 { 0, "--int-long-reent", &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
191 { 0, "--float-reent", &options.float_rent, "Use reenterant calls on the float support functions" },
192 { 0, OPTION_OUT_FMT_IHX, NULL, NULL },
193 { 0, "--out-fmt-s19", &options.out_fmt, NULL },
194 { 0, "--cyclomatic", &options.cyclomatic, NULL },
195 { 0, "--nooverlay", &options.noOverlay, NULL },
196 { 0, "--main-return", &options.mainreturn, "Issue a return after main()" },
197 { 0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)" },
198 { 0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation" },
199 { 0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers" },
200 { 0, "--peep-asm", &options.asmpeep, NULL },
201 { 0, "--debug", &options.debug, "Enable debugging symbol output" },
202 { 'v', OPTION_VERSION, NULL, "Display sdcc's version" },
203 { 'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile" },
204 { 0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code." },
205 { 0, "--help", NULL, "Display this help" },
206 { 0, OPTION_CALLEE_SAVES, NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
207 { 0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path" },
208 { 0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path" },
209 { 0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
210 { 0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings" },
211 { 0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning" },
212 { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8bits (for old times sake)" },
213 { 0, "--profile", &options.profile, "On supported ports, generate extra profiling information" },
214 { 0, "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
215 { 0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used" },
216 #if !OPT_DISABLE_DS390
217 { 0, "--use-accelerator", &options.useAccelerator,"generate code for DS390 Arithmetic Accelerator"},
219 { 0, "--stack-probe", &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
220 #if !OPT_DISABLE_TININative
221 { 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
223 #if !OPT_DISABLE_DS390
224 { 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
226 #if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
227 { 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
228 { 0, OPTION_STACK_SIZE, NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
229 { 0, OPTION_PACK_IRAM, &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
231 { 0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
232 { 0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
233 { 0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "include i-code as comments in the asm file"},
234 { 0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
235 { 0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
236 { 0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
237 { 0, OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
238 #if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
239 { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
245 /** Table of all unsupported options and help text to display when one
249 /** shortOpt as in OPTIONS. */
251 /** longOpt as in OPTIONS. */
253 /** Message to display inside W_UNSUPPORTED_OPT when this option
258 static const UNSUPPORTEDOPT
259 unsupportedOptTable[] = {
260 { 'X', NULL, "use --xstack-loc instead" },
261 { 'x', NULL, "use --xstack instead" },
262 { 'i', NULL, "use --idata-loc instead" },
263 { 'r', NULL, "use --xdata-loc instead" },
264 { 's', NULL, "use --code-loc instead" },
265 { 'Y', NULL, "use -I instead" }
268 /** List of all default constant macros.
270 static const char *_baseValues[] = {
273 /* Path seperator character */
274 "sep", DIR_SEPARATOR_STRING,
278 static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} \"{fullsrcfilename}\" \"{cppoutfilename}\"";
282 static PORT *_ports[] =
284 #if !OPT_DISABLE_MCS51
287 #if !OPT_DISABLE_GBZ80
296 #if !OPT_DISABLE_DS390
299 #if !OPT_DISABLE_PIC16
305 #if !OPT_DISABLE_TININative
308 #if !OPT_DISABLE_XA51
311 #if !OPT_DISABLE_DS400
314 #if !OPT_DISABLE_HC08
319 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
321 /** Sets the port to the one given by the command line option.
322 @param The name minus the option (eg 'mcs51')
323 @return 0 on success.
326 _setPort (const char *name)
329 for (i = 0; i < NUM_PORTS; i++)
331 if (!strcmp (_ports[i]->target, name))
337 /* Error - didnt find */
338 werror (E_UNKNOWN_TARGET, name);
342 /* Override the default processor with the one specified
343 * on the command line */
345 _setProcessor (char *_processor)
347 port->processor = _processor;
348 fprintf(stderr,"Processor: %s\n",_processor);
352 _validatePorts (void)
355 for (i = 0; i < NUM_PORTS; i++)
357 if (_ports[i]->magic != PORT_MAGIC)
359 /* Uncomment this line to debug which port is causing the problem
360 * (the target name is close to the beginning of the port struct
361 * and probably can be accessed just fine). */
362 fprintf(stderr,"%s :",_ports[i]->target);
363 wassertl (0, "Port definition structure is incomplete");
368 /* search through the command line options for the port */
370 _findPort (int argc, char **argv)
376 if (!strncmp (*argv, "-m", 2))
378 _setPort (*argv + 2);
384 /* Use the first in the list */
388 /* search through the command line options for the processor */
390 _findProcessor (int argc, char **argv)
394 if (!strncmp (*argv, "-p", 2))
396 _setProcessor (*argv + 2);
402 /* no error if processor was not specified. */
405 /*-----------------------------------------------------------------*/
406 /* printVersionInfo - prints the version info */
407 /*-----------------------------------------------------------------*/
409 printVersionInfo (void)
415 for (i = 0; i < NUM_PORTS; i++)
416 fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
418 fprintf (stderr, " " SDCC_VERSION_STR
419 #ifdef SDCC_SUB_VERSION_STR
420 "/" SDCC_SUB_VERSION_STR
422 " #%s (" __DATE__ ")"
425 #elif defined __MINGW32__
427 #elif defined __DJGPP__
429 #elif defined(_MSC_VER)
431 #elif defined(__BORLANDC__)
436 , getBuildNumber() );
440 printOptions(const OPTION *optionsTable)
443 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
445 fprintf(stdout, " %c%c %-20s %s\n",
446 optionsTable[i].shortOpt !=0 ? '-' : ' ',
447 optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
448 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
449 optionsTable[i].help != NULL ? optionsTable[i].help : ""
454 /*-----------------------------------------------------------------*/
455 /* printUsage - prints command line syntax */
456 /*-----------------------------------------------------------------*/
463 "Usage : sdcc [options] filename\n"
467 printOptions(optionsTable);
469 for (i = 0; i < NUM_PORTS; i++)
471 if (_ports[i]->poptions != NULL)
473 fprintf (stdout, "\nSpecial options for the %s port:\n", _ports[i]->target);
474 printOptions (_ports[i]->poptions);
481 /*-----------------------------------------------------------------*/
482 /* setParseWithComma - separates string with comma to a set */
483 /*-----------------------------------------------------------------*/
485 setParseWithComma (set **dest, char *src)
490 /* skip the initial white spaces */
491 while (isspace(*src))
494 /* skip the trailing white spaces */
495 length = strlen(src);
496 while (length && isspace(src[length-1]))
497 src[--length] = '\0';
499 for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
500 addSet(dest, Safe_strdup(p));
503 /*-----------------------------------------------------------------*/
504 /* setDefaultOptions - sets the default options */
505 /*-----------------------------------------------------------------*/
507 setDefaultOptions (void)
509 /* first the options part */
510 options.stack_loc = 0; /* stack pointer initialised to 0 */
511 options.xstack_loc = 0; /* xternal stack starts at 0 */
512 options.code_loc = 0; /* code starts at 0 */
513 options.data_loc = 0; /* JCF: By default let the linker locate data */
514 options.xdata_loc = 0;
515 options.idata_loc = 0x80;
517 options.model = port->general.default_model;
518 options.nostdlib = 0;
519 options.nostdinc = 0;
521 options.shortis8bits = 0;
523 options.stack10bit=0;
525 /* now for the optimizations */
526 /* turn on the everything */
527 optimize.global_cse = 1;
532 optimize.loopInvariant = 1;
533 optimize.loopInduction = 1;
535 /* now for the ports */
536 port->setDefaultOptions ();
539 /*-----------------------------------------------------------------*/
540 /* processFile - determines the type of file from the extension */
541 /*-----------------------------------------------------------------*/
543 processFile (char *s)
547 /* get the file extension */
548 fext = s + strlen (s);
549 while ((fext != s) && *fext != '.')
552 /* now if no '.' then we don't know what the file type is
553 so give a warning and return */
556 werror (W_UNKNOWN_FEXT, s);
560 /* otherwise depending on the file type */
561 if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
563 /* source file name : not if we already have a
567 werror (W_TOO_MANY_SRC, s);
571 /* the only source file */
573 if (!(srcFile = fopen (fullSrcFileName, "r")))
575 werror (E_FILE_OPEN_ERR, s);
579 /* copy the file name into the buffer */
580 strncpyz (buffer, s, sizeof(buffer));
582 /* get rid of the "."-extension */
584 /* is there a dot at all? */
585 if (strrchr (buffer, '.') &&
586 /* is the dot in the filename, not in the path? */
587 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
589 *strrchr (buffer, '.') = '\0';
592 /* get rid of any path information
593 for the module name; */
594 fext = buffer + strlen (buffer);
596 /* do this by going backwards till we
597 get '\' or ':' or start of buffer */
598 while (fext != buffer &&
599 *(fext - 1) != DIR_SEPARATOR_CHAR &&
605 /* do this by going backwards till we
606 get '/' or start of buffer */
607 while (fext != buffer &&
608 *(fext - 1) != DIR_SEPARATOR_CHAR)
613 moduleNameBase = Safe_strdup ( fext );
614 moduleName = Safe_strdup ( fext );
616 for (fext = moduleName; *fext; fext++)
617 if (!isalnum (*fext))
622 /* if the extention is type .rel or .r or .REL or .R
623 addtional object file will be passed to the linker */
624 if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
625 strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
626 strcmp (fext, port->linker.rel_ext) == 0)
628 addSet(&relFilesSet, Safe_strdup(s));
632 /* if .lib or .LIB */
633 if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
635 addSet(&libFilesSet, Safe_strdup(s));
639 werror (W_UNKNOWN_FEXT, s);
644 _setModel (int model, const char *sz)
646 if (port->general.supported_models & model)
647 options.model = model;
649 werror (W_UNSUPPORTED_MODEL, sz, port->target);
652 /** Gets the string argument to this option. If the option is '--opt'
653 then for input of '--optxyz' or '--opt xyz' returns xyz.
656 getStringArg(const char *szStart, char **argv, int *pi, int argc)
658 if (argv[*pi][strlen(szStart)])
660 return &argv[*pi][strlen(szStart)];
667 werror (E_ARGUMENT_MISSING, szStart);
668 /* Die here rather than checking for errors later. */
678 /** Gets the integer argument to this option using the same rules as
682 getIntArg(const char *szStart, char **argv, int *pi, int argc)
684 return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
688 verifyShortOption(const char *opt)
690 if (strlen(opt) != 2)
692 werror (W_EXCESS_SHORT_OPTIONS, opt);
697 tryHandleUnsupportedOpt(char **argv, int *pi)
699 if (argv[*pi][0] == '-')
701 const char *longOpt = "";
705 if (argv[*pi][1] == '-')
712 shortOpt = argv[*pi][1];
714 for (i = 0; i < LENGTH(unsupportedOptTable); i++)
716 if (unsupportedOptTable[i].shortOpt == shortOpt ||
717 (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
718 /* Found an unsupported opt. */
720 SNPRINTF(buffer, sizeof(buffer),
722 longOpt ? longOpt : "",
723 shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
724 werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
728 /* Didn't find in the table */
733 /* Not an option, so can't be unsupported :) */
739 scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi)
742 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL; i++)
744 if (optionsTable[i].shortOpt == shortOpt ||
745 (longOpt && optionsTable[i].longOpt &&
746 strcmp(optionsTable[i].longOpt, longOpt) == 0))
749 /* If it is a flag then we can handle it here */
750 if (optionsTable[i].pparameter != NULL)
752 if (optionsTable[i].shortOpt == shortOpt)
754 verifyShortOption(argv[*pi]);
757 (*optionsTable[i].pparameter)++;
761 /* Not a flag. Handled manually later. */
766 /* Didn't find in the table */
771 tryHandleSimpleOpt(char **argv, int *pi)
773 if (argv[*pi][0] == '-')
775 const char *longOpt = "";
778 if (argv[*pi][1] == '-')
785 shortOpt = argv[*pi][1];
788 if (scanOptionsTable(optionsTable, shortOpt, longOpt, argv, pi))
792 else if (port && port->poptions &&
793 scanOptionsTable(port->poptions, shortOpt, longOpt, argv, pi))
804 /* Not an option, so can't be handled. */
809 /*-----------------------------------------------------------------*/
810 /* parseCmdLine - parses the command line and sets the options */
811 /*-----------------------------------------------------------------*/
813 parseCmdLine (int argc, char **argv)
817 /* go thru all whole command line */
818 for (i = 1; i < argc; i++)
823 if (tryHandleUnsupportedOpt(argv, &i) == TRUE)
828 if (tryHandleSimpleOpt(argv, &i) == TRUE)
834 if (argv[i][0] == '-' && argv[i][1] == '-')
836 if (strcmp (argv[i], OPTION_HELP) == 0)
842 if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
844 options.stack10bit = 0;
848 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
854 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
856 _setModel (MODEL_LARGE, argv[i]);
860 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
862 _setModel (MODEL_MEDIUM, argv[i]);
866 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
868 _setModel (MODEL_SMALL, argv[i]);
872 if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
874 _setModel (MODEL_FLAT24, argv[i]);
878 if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
880 options.dump_rassgn =
886 options.dump_raw = 1;
890 if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
892 options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
896 if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
898 addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
902 if (strcmp (argv[i], OPTION_VERSION) == 0)
909 if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
911 setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
915 if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
917 options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
921 if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
923 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
927 if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
929 options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
933 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
935 options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
939 if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
941 options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
945 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
947 options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
948 options.xram_size_set = TRUE;
952 if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
954 options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
958 if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
960 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
964 if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
966 options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
970 if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
972 options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
976 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
978 optimize.global_cse = 0;
982 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
984 optimize.loopInvariant = 0;
988 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
994 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
996 optimize.loopInduction = 0;
1000 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1002 options.lessPedantic = 1;
1003 setErrorLogLevel(ERROR_LEVEL_WARNING);
1007 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1009 int w = getIntArg(OPTION_DISABLE_WARNING, argv, &i, argc);
1010 if (w < MAX_ERROR_WARNING)
1012 setWarningDisabled(w);
1017 if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0)
1019 options.shortis8bits=1;
1023 if (strcmp (argv[i], OPTION_TINI_LIBID) == 0)
1025 options.tini_libid = getIntArg(OPTION_TINI_LIBID, argv, &i, argc);
1029 if (!port->parseOption (&argc, argv, &i))
1031 werror (W_UNKNOWN_OPTION, argv[i]);
1040 /* if preceded by '-' then option */
1041 if (*argv[i] == '-')
1046 verifyShortOption(argv[i]);
1053 /* Used to select the port. But this has already been done. */
1057 /* Used to select the processor in port. But this has
1058 * already been done. */
1062 verifyShortOption(argv[i]);
1064 options.cc_only = 1;
1068 addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
1072 addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
1079 /* copy the file name into the buffer */
1080 strncpyz(buffer, getStringArg("-o", argv, &i, argc),
1082 /* point to last character */
1083 p = buffer + strlen (buffer) - 1;
1084 if (*p == DIR_SEPARATOR_CHAR)
1086 /* only output path specified */
1087 dstPath = Safe_strdup (buffer);
1088 fullDstFileName = NULL;
1092 fullDstFileName = Safe_strdup (buffer);
1094 /* get rid of the "."-extension */
1096 /* is there a dot at all? */
1097 if (strrchr (buffer, '.') &&
1098 /* is the dot in the filename, not in the path? */
1099 (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
1100 *strrchr (buffer, '.') = '\0';
1102 dstFileName = Safe_strdup (buffer);
1104 /* strip module name to get path */
1105 p = strrchr (buffer, DIR_SEPARATOR_CHAR);
1108 /* path with trailing / */
1110 dstPath = Safe_strdup (buffer);
1117 /* pre-processer options */
1118 if (argv[i][2] == 'p')
1120 setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
1122 /* linker options */
1123 else if (argv[i][2] == 'l')
1125 setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
1127 /* assembler options */
1128 else if (argv[i][2] == 'a')
1130 setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
1134 werror (W_UNKNOWN_OPTION, argv[i]);
1139 verifyShortOption(argv[i]);
1141 printVersionInfo ();
1145 /* preprocessor options */
1149 if (argv[i][2] == 'M')
1150 addSet(&preArgvSet, Safe_strdup("-MM"));
1152 addSet(&preArgvSet, Safe_strdup("-M"));
1157 addSet(&preArgvSet, Safe_strdup("-C"));
1167 char sOpt = argv[i][1];
1170 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1176 werror(E_ARGUMENT_MISSING, argv[i-1]);
1190 SNPRINTF (buffer, sizeof(buffer),
1191 ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
1192 addSet(&preArgvSet, Safe_strdup(buffer));
1193 if(sOpt == 'I')addSet(&includeDirsSet, Safe_strdup(rest));
1198 if (!port->parseOption (&argc, argv, &i))
1199 werror (W_UNKNOWN_OPTION, argv[i]);
1204 if (!port->parseOption (&argc, argv, &i))
1206 /* no option must be a filename */
1209 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1213 processFile (argv[i]);
1218 /* some sanity checks in c1 mode */
1223 if (fullSrcFileName)
1226 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1228 fullSrcFileName = NULL;
1229 for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
1231 werror (W_NO_FILE_ARG_IN_C1, s);
1233 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1235 werror (W_NO_FILE_ARG_IN_C1, s);
1237 deleteSet(&relFilesSet);
1238 deleteSet(&libFilesSet);
1240 if (options.cc_only || noAssemble || preProcOnly)
1242 werror (W_ILLEGAL_OPT_COMBINATION);
1244 options.cc_only = noAssemble = preProcOnly = 0;
1247 werror (E_NEED_OPT_O_IN_C1);
1251 /* if no dstFileName given with -o, we've to find one: */
1256 /* use the modulename from the C-source */
1257 if (fullSrcFileName)
1259 size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
1261 dstFileName = Safe_alloc (bufSize);
1262 strncpyz (dstFileName, dstPath, bufSize);
1263 strncatz (dstFileName, moduleNameBase, bufSize);
1265 /* use the modulename from the first object file */
1266 else if ((s = peekSet(relFilesSet)) != NULL)
1271 strncpyz (buffer, s, sizeof(buffer));
1272 /* remove extension (it must be .rel) */
1273 *strrchr (buffer, '.') = '\0';
1275 objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
1282 objectName = buffer;
1284 bufSize = strlen (dstPath) + strlen (objectName) + 1;
1285 dstFileName = Safe_alloc (bufSize);
1286 strncpyz (dstFileName, dstPath, bufSize);
1287 strncatz (dstFileName, objectName, bufSize);
1289 /* else no module given: help text is displayed */
1292 /* set up external stack location if not explicitly specified */
1293 if (!options.xstack_loc)
1294 options.xstack_loc = options.xdata_loc;
1296 /* if debug option is set then open the cdbFile */
1297 if (options.debug && fullSrcFileName)
1299 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1300 "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
1301 if(debugFile->openFile(scratchFileName))
1302 debugFile->writeModule(moduleName);
1304 werror (E_FILE_OPEN_ERR, scratchFileName);
1306 MSVC_style(options.vc_err_style);
1307 if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
1312 /*-----------------------------------------------------------------*/
1313 /* linkEdit : - calls the linkage editor with options */
1314 /*-----------------------------------------------------------------*/
1316 linkEdit (char **envp)
1324 if(port->linker.needLinkerScript)
1328 switch (options.out_fmt)
1331 out_fmt = 'i'; /* Intel hex */
1334 out_fmt = 's'; /* Motorola S19 */
1337 out_fmt = 't'; /* Elf */
1343 /* first we need to create the <filename>.lnk file */
1344 SNPRINTF (scratchFileName, sizeof(scratchFileName),
1345 "%s.lnk", dstFileName);
1346 if (!(lnkfile = fopen (scratchFileName, "w")))
1348 werror (E_FILE_OPEN_ERR, scratchFileName);
1352 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
1354 fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
1355 out_fmt, dstFileName);
1357 else /*For all the other ports. Including pics???*/
1359 fprintf (lnkfile, "-myux%c\n", out_fmt);
1360 if(options.pack_iram)
1361 fprintf (lnkfile, "-Y\n");
1364 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1366 /* if iram size specified */
1367 if (options.iram_size)
1368 fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
1370 /* if stack size specified*/
1371 if(options.stack_size)
1372 fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
1374 /* if xram size specified */
1375 if (options.xram_size_set)
1376 fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
1378 /* if code size specified */
1379 if (options.code_size)
1380 fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
1383 fprintf (lnkfile, "-z\n");
1386 #define WRITE_SEG_LOC(N, L) \
1387 segName = Safe_strdup(N); \
1388 c = strtok(segName, " \t"); \
1389 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1390 if (segName) { Safe_free(segName); }
1392 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
1395 /* code segment start */
1396 WRITE_SEG_LOC (CODE_NAME, options.code_loc);
1398 /* data segment start. If zero, the linker chooses
1399 the best place for data */
1400 if(options.data_loc)
1402 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1406 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1411 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1414 /* bit segment start */
1415 WRITE_SEG_LOC (BIT_NAME, 0);
1418 if ( (options.stack_loc) && (options.stack_loc<0x100) )
1420 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1423 else /*For the z80, gbz80*/
1425 WRITE_SEG_LOC ("_CODE", options.code_loc);
1426 WRITE_SEG_LOC ("_DATA", options.data_loc);
1429 /* If the port has any special linker area declarations, get 'em */
1430 if (port->extraAreas.genExtraAreaLinkOptions)
1432 port->extraAreas.genExtraAreaLinkOptions(lnkfile);
1435 /* add the extra linker options */
1436 fputStrSet(lnkfile, linkOptionsSet);
1438 /* command line defined library paths if specified */
1439 for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
1440 fprintf (lnkfile, "-k %s\n", s);
1442 /* standard library path */
1443 if (!options.nostdlib)
1445 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1447 switch (options.model)
1457 if (TARGET_IS_DS390)
1461 else if (TARGET_IS_DS400)
1468 "Add support for your FLAT24 target in %s @ line %d\n",
1469 __FILE__, __LINE__);
1477 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1482 else /*for the z80, gbz80*/
1486 else if (TARGET_IS_Z80)
1491 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1492 mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
1495 /* command line defined library files if specified */
1496 for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
1497 fprintf (lnkfile, "-l %s\n", s);
1499 /* standard library files */
1500 if (!options.nostdlib)
1502 #if !OPT_DISABLE_DS390
1503 if (options.model == MODEL_FLAT24)
1505 if (TARGET_IS_DS390)
1507 fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
1509 else if (TARGET_IS_DS400)
1511 fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
1516 "Add support for your FLAT24 target in %s @ line %d\n",
1517 __FILE__, __LINE__);
1523 #if !OPT_DISABLE_XA51
1525 if (options.model == MODEL_PAGE0)
1527 fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
1531 if (TARGET_IS_MCS51)
1533 fprintf (lnkfile, "-l mcs51\n");
1535 if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
1536 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
1537 { /*Why the z80 port is not using the standard libraries?*/
1538 fprintf (lnkfile, "-l %s\n", STD_LIB);
1539 fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
1540 fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
1541 fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
1543 else if (TARGET_IS_HC08)
1545 fprintf (lnkfile, "-l hc08\n");
1547 else if (TARGET_IS_Z80)
1549 fprintf (lnkfile, "-l z80\n");
1551 else if (TARGET_IS_GBZ80)
1553 fprintf (lnkfile, "-l gbz80\n");
1557 /*For the z80 and gbz80 ports, try to find where crt0.o is...
1558 It is very important for this file to be first on the linking proccess
1559 so the areas are set in the correct order, expecially _GSINIT*/
1560 if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
1561 !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
1563 char crt0path[PATH_MAX];
1565 for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
1567 sprintf (crt0path, "%s%s%s%scrt0.o",
1568 s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
1570 crt0fp=fopen(crt0path, "r");
1571 if(crt0fp!=NULL)/*Found it!*/
1576 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
1577 windows paths, so convert them to the CYGWIN format*/
1578 char posix_path[PATH_MAX];
1579 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1580 cygwin_conv_to_full_posix_path(crt0path, posix_path);
1581 strcpy(crt0path, posix_path);
1584 fprintf (lnkfile, "%s\n", crt0path);
1588 if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
1591 /* put in the object files */
1592 if (fullSrcFileName)
1593 fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
1595 fputStrSet(lnkfile, relFilesSet);
1597 fprintf (lnkfile, "\n-e\n");
1599 } /* if(port->linker.needLinkerScript) */
1601 if (options.verbose)
1602 printf ("sdcc: Calling linker...\n");
1604 /* build linker output filename */
1606 /* -o option overrides default name? */
1607 if (fullDstFileName)
1609 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1613 /* the linked file gets the name of the first modul */
1614 if (fullSrcFileName)
1616 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1620 s = peekSet(relFilesSet);
1624 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1625 /* strip ".rel" extension */
1626 *strrchr (scratchFileName, '.') = '\0';
1628 strncatz (scratchFileName,
1629 options.out_fmt ? ".S19" : ".ihx",
1630 sizeof(scratchFileName));
1633 if (port->linker.cmd)
1635 char buffer2[PATH_MAX];
1636 char buffer3[PATH_MAX];
1637 set *tempSet=NULL, *libSet=NULL;
1639 strcpy(buffer3, dstFileName);
1640 if(TARGET_IS_PIC16) {
1642 /* use $l to set the linker include directories */
1643 tempSet = appendStrSet(libDirsSet, "-I\"", "\"");
1644 mergeSets(&linkOptionsSet, tempSet);
1646 tempSet = appendStrSet(libPathsSet, "-I\"", "\"");
1647 mergeSets(&linkOptionsSet, tempSet);
1649 /* use $3 for libraries from command line --> libSet */
1650 mergeSets(&libSet, libFilesSet);
1652 tempSet = appendStrSet(relFilesSet, "", "");
1653 mergeSets(&libSet, tempSet);
1654 // libSet = reverseSet(libSet);
1656 if(fullSrcFileName) {
1657 // strcpy(buffer3, strrchr(fullSrcFileName, DIR_SEPARATOR_CHAR)+1);
1658 /* if it didn't work, revert to old behaviour */
1659 if(!strlen(buffer3))strcpy(buffer3, dstFileName);
1660 strcat(buffer3, port->linker.rel_ext);
1662 } else strcpy(buffer3, "");
1665 buildCmdLine (buffer2, port->linker.cmd, buffer3, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
1667 buildCmdLine2 (buffer, sizeof(buffer), buffer2);
1671 buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
1674 /* if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
1676 system_ret = my_system (buffer);
1677 /* TODO: most linker don't have a -o parameter */
1678 /* -o option overrides default name? */
1679 if (fullDstFileName)
1682 /* the linked file gets the name of the first modul */
1683 if (fullSrcFileName)
1685 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1686 p = strlen (scratchFileName) + scratchFileName;
1690 s = peekSet(relFilesSet);
1694 strncpyz (scratchFileName, s, sizeof(scratchFileName));
1695 /* strip ".rel" extension */
1696 p = strrchr (scratchFileName, '.');
1702 strncatz (scratchFileName,
1703 options.out_fmt ? ".S19" : ".ihx",
1704 sizeof(scratchFileName));
1705 if (strcmp (fullDstFileName, scratchFileName))
1706 unlink (fullDstFileName);
1707 rename (scratchFileName, fullDstFileName);
1709 strncpyz (buffer, fullDstFileName, sizeof(buffer));
1710 q = strrchr (buffer, '.');
1713 /* no extension: append new extensions */
1714 q = strlen (buffer) + buffer;
1718 strncatz (scratchFileName, ".map", sizeof(scratchFileName));
1720 strncatz(buffer, ".map", sizeof(buffer));
1721 if (strcmp (scratchFileName, buffer))
1723 rename (scratchFileName, buffer);
1725 strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
1727 strncatz(buffer, ".mem", sizeof(buffer));
1728 if (strcmp (scratchFileName, buffer))
1730 rename (scratchFileName, buffer);
1734 strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
1736 strncatz(buffer, ".cdb", sizeof(buffer));
1737 if (strcmp (scratchFileName, buffer))
1739 rename (scratchFileName, buffer);
1740 /* and the OMF file without extension: */
1743 if (strcmp (scratchFileName, buffer))
1745 rename (scratchFileName, buffer);
1754 /*-----------------------------------------------------------------*/
1755 /* assemble - spawns the assembler with arguments */
1756 /*-----------------------------------------------------------------*/
1758 assemble (char **envp)
1760 /* build assembler output filename */
1762 /* -o option overrides default name? */
1763 if (options.cc_only && fullDstFileName) {
1764 strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
1766 /* the assembled file gets the name of the first modul */
1767 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1768 strncatz (scratchFileName, port->linker.rel_ext,
1769 sizeof(scratchFileName));
1772 if (port->assembler.do_assemble) {
1773 port->assembler.do_assemble(asmOptionsSet);
1775 } else if (port->assembler.cmd) {
1776 buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
1777 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
1780 buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
1783 if (my_system (buffer)) {
1784 /* either system() or the assembler itself has reported an error
1785 perror ("Cannot exec assembler");
1789 /* TODO: most assembler don't have a -o parameter */
1790 /* -o option overrides default name? */
1791 if (options.cc_only && fullDstFileName) {
1792 strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
1793 strncatz (scratchFileName,
1794 port->linker.rel_ext,
1795 sizeof(scratchFileName));
1796 if (strcmp (scratchFileName, fullDstFileName))
1797 unlink (fullDstFileName);
1798 rename (scratchFileName, fullDstFileName);
1802 /*-----------------------------------------------------------------*/
1803 /* preProcess - spawns the preprocessor with arguments */
1804 /*-----------------------------------------------------------------*/
1806 preProcess (char **envp)
1815 set *inclList = NULL;
1817 /* if using external stack define the macro */
1818 if (options.useXstack)
1819 addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
1821 /* set the macro for stack autos */
1822 if (options.stackAuto)
1823 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
1825 /* set the macro for stack autos */
1826 if (options.stack10bit)
1827 addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
1829 /* set the macro for no overlay */
1830 if (options.noOverlay)
1831 addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
1833 /* set the macro for large model */
1834 switch (options.model)
1837 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
1840 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
1843 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
1846 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
1849 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
1852 addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
1855 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
1859 /* add port (processor information to processor */
1860 addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
1861 addSet(&preArgvSet, Safe_strdup("-D__{port}"));
1863 /* standard include path */
1864 if (!options.nostdinc) {
1865 inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
1866 mergeSets(&preArgvSet, inclList);
1869 setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
1870 Safe_free((void *)s);
1871 if (inclList != NULL)
1872 deleteSet(&inclList);
1874 if (preProcOnly && fullDstFileName)
1876 /* -E and -o given */
1877 setMainValue ("cppoutfilename", fullDstFileName);
1881 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
1882 setMainValue ("cppoutfilename", NULL);
1885 if (options.verbose)
1886 printf ("sdcc: Calling preprocessor...\n");
1888 buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
1891 if (my_system (buffer)) {
1898 yyin = my_popen (buffer);
1900 perror ("Preproc file not found");
1903 addSetHead (&pipeSet, yyin);
1911 setBinPaths(const char *argv0)
1919 * 1. - $SDCCDIR/PREFIX2BIN_DIR
1920 * 2. - path(argv[0])
1924 /* do it in reverse mode, so that addSetHead() can be used
1925 instead of slower addSet() */
1927 if ((p = getBinPath(argv0)) != NULL)
1928 addSetHead(&binPathSet, Safe_strdup(p));
1930 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
1931 SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
1932 addSetHead(&binPathSet, Safe_strdup(buf));
1936 if (options.printSearchDirs) {
1937 printf("programs:\n");
1938 fputStrSet(stdout, binPathSet);
1943 /* Set system include path */
1945 setIncludePath(void)
1952 * 1. - $SDCC_INCLUDE
1953 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
1954 * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
1955 * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
1958 includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
1960 if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
1961 addSetHead(&includeDirsSet, p);
1964 if (options.printSearchDirs) {
1965 printf("includedir:\n");
1966 fputStrSet(stdout, includeDirsSet);
1971 /* Set system lib path */
1981 * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
1982 * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
1983 * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
1986 libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
1988 if ((p = getenv(SDCC_LIB_NAME)) != NULL)
1989 addSetHead(&libDirsSet, p);
1992 if (options.printSearchDirs) {
1993 printf("libdir:\n");
1994 fputStrSet(stdout, libDirsSet);
2001 setDataPaths(const char *argv0)
2009 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2010 * 2. - path(argv[0])/BIN2DATA_DIR
2011 * 3. - DATADIR (only on *nix)
2014 if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
2015 SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
2016 addSet(&dataDirsSet, Safe_strdup(buf));
2019 if ((p = getBinPath(argv0)) != NULL) {
2020 SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
2021 addSet(&dataDirsSet, Safe_strdup(buf));
2025 if (peekSet(dataDirsSet) == NULL) {
2026 /* this should never happen... */
2027 wassertl(0, "Can't get binary path");
2030 addSet(&dataDirsSet, Safe_strdup(DATADIR));
2034 if (options.printSearchDirs) {
2035 printf("datadir:\n");
2036 fputStrSet(stdout, dataDirsSet);
2047 populateMainValues (_baseValues);
2048 setMainValue ("port", port->target);
2049 setMainValue ("objext", port->linker.rel_ext);
2050 setMainValue ("asmext", port->assembler.file_ext);
2052 setMainValue ("dstfilename", dstFileName);
2053 setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
2055 if (options.cc_only && fullDstFileName)
2056 /* compile + assemble and -o given: -o specifies name of object file */
2058 setMainValue ("objdstfilename", fullDstFileName);
2062 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2064 if (fullDstFileName)
2065 /* if we're linking, -o gives the final file name */
2067 setMainValue ("linkdstfilename", fullDstFileName);
2071 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2076 static void doPrintSearchDirs(void)
2078 printf("programs:\n");
2079 fputStrSet(stdout, binPathSet);
2081 printf("datadir:\n");
2082 fputStrSet(stdout, dataDirsSet);
2084 printf("includedir:\n");
2085 fputStrSet(stdout, includeDirsSet);
2087 printf("libdir:\n");
2088 fputStrSet(stdout, libDirsSet);
2089 fputStrSet(stdout, libPathsSet);
2094 sig_handler (int signal)
2101 sig_string = "SIGABRT";
2104 sig_string = "SIGTERM";
2107 sig_string = "SIGINT";
2110 sig_string = "SIGSEGV";
2113 sig_string = "Unknown?";
2116 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2122 * initialises and calls the parser
2126 main (int argc, char **argv, char **envp)
2128 /* turn all optimizations off by default */
2129 memset (&optimize, 0, sizeof (struct optimize));
2131 /*printVersionInfo (); */
2134 fprintf (stderr, "Build error: no ports are enabled.\n");
2138 /* install atexit handler */
2139 atexit(rm_tmpfiles);
2141 /* install signal handler;
2142 it's only purpuse is to call exit() to remove temp files */
2143 if (!getenv("SDCC_LEAVE_SIGNALS"))
2145 signal (SIGABRT, sig_handler);
2146 signal (SIGTERM, sig_handler);
2147 signal (SIGINT , sig_handler);
2148 signal (SIGSEGV, sig_handler);
2151 /* Before parsing the command line options, do a
2152 * search for the port and processor and initialize
2153 * them if they're found. (We can't gurantee that these
2154 * will be the first options specified).
2157 _findPort (argc, argv);
2160 if (strcmp(port->target, "mcs51") == 0) {
2161 printf("DS390 jammed in A\n");
2167 _findProcessor (argc, argv);
2169 /* Initalise the port. */
2173 setDefaultOptions ();
2176 options.model = MODEL_SMALL;
2177 options.stack10bit=0;
2180 parseCmdLine (argc, argv);
2183 setBinPaths(argv[0]);
2184 setDataPaths(argv[0]);
2189 if(options.printSearchDirs)
2190 doPrintSearchDirs();
2192 /* if no input then printUsage & exit */
2193 if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
2194 if (!options.printSearchDirs)
2200 /* initMem() is expensive, but
2201 initMem() must called before port->finaliseOptions ().
2202 And the z80 port needs port->finaliseOptions(),
2203 even if we're only linking. */
2205 port->finaliseOptions ();
2207 if (fullSrcFileName || options.c1mode)
2217 if (options.verbose)
2218 printf ("sdcc: Generating code...\n");
2224 deleteSetItem(&pipeSet, yyin);
2230 if (port->general.do_glue != NULL)
2231 (*port->general.do_glue)();
2234 /* this shouldn't happen */
2236 /* in case of NDEBUG */
2244 if (!options.c1mode && !noAssemble)
2246 if (options.verbose)
2247 printf ("sdcc: Calling assembler...\n");
2253 if (options.debug && debugFile)
2254 debugFile->closeFile();
2256 if (!options.cc_only &&
2260 (fullSrcFileName || peekSet(relFilesSet) != NULL))
2262 if (port->linker.do_link)
2263 port->linker.do_link ();