1 /*-------------------------------------------------------------------------
2 SDCCmain.c - main file
3
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
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
9 later version.
10
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.
15
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.
19
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 -------------------------------------------------------------------------*/
24
25 #ifdef _WIN32
26 #include <io.h>
27 #else
28 #include <unistd.h>
29 #include <libgen.h>
30 #endif
31
32 #include <signal.h>
33 #include "common.h"
34 #include <ctype.h>
35 #include "dbuf_string.h"
36 #include "SDCCerr.h"
37 #include "SDCCmacro.h"
38 #include "SDCCargs.h"
39
40 #ifdef _WIN32
41 #include <process.h>
42 #else
43 #include <sys/stat.h>
44 #include <unistd.h>
45 #include <sys/resource.h>
46 #endif
47
48 /* REMOVE ME!!! */
49 extern int yyparse (void);
50
51 FILE *srcFile; /* source file */
52 const char *fullSrcFileName; /* full name for the source file; */
53 /* can be NULL while c1mode or linking without compiling */
54 const char *fullDstFileName; /* full name for the output file; */
55 /* only given by -o, otherwise NULL */
56 const char *dstFileName; /* destination file name without extension */
57 const char *moduleName; /* module name is same as module name base, but with all */
58 /* non-alphanumeric characters replaced with underscore */
59 int currRegBank = 0;
60 int RegBankUsed[4] = { 1, 0, 0, 0 }; /*JCF: Reg Bank 0 used by default */
61
62 int BitBankUsed; /* MB: overlayable bit bank */
63 struct optimize optimize;
64 struct options options;
65 int preProcOnly = 0;
66 int noAssemble = 0;
67 set *preArgvSet = NULL; /* pre-processor arguments */
68 set *asmOptionsSet = NULL; /* set of assembler options */
69 set *linkOptionsSet = NULL; /* set of linker options */
70 set *libFilesSet = NULL;
71 set *libPathsSet = NULL;
72 set *relFilesSet = NULL;
73 set *dataDirsSet = NULL; /* list of data search directories */
74 set *includeDirsSet = NULL; /* list of include search directories */
75 set *userIncDirsSet = NULL; /* list of user include directories */
76 set *libDirsSet = NULL; /* list of lib search directories */
77 bool regalloc_dry_run = FALSE;
78
79 static const char *dstPath = ""; /* path for the output files; */
80 /* "" is equivalent with cwd */
81 static const char *moduleNameBase = NULL; /* module name base is source file without path and extension */
82 /* can be NULL while linking without compiling */
83
84 /* uncomment JAMIN_DS390 to always override and use ds390 port
85 for mcs51 work. This is temporary, for compatibility testing. */
86 /* #define JAMIN_DS390 */
87 #ifdef JAMIN_DS390
88 static int ds390_jammed = 0;
89 #endif
90
91 /* Globally accessible scratch buffer for file names.
92 TODO: replace them with local buffers */
93 char buffer[PATH_MAX * 2];
94
95 #define LENGTH(_a) (sizeof (_a) / sizeof (*(_a)))
96
97 #define OPTION_HELP "--help"
98 #define OPTION_OUT_FMT_IHX "--out-fmt-ihx"
99 #define OPTION_OUT_FMT_S19 "--out-fmt-s19"
100 #define OPTION_PEEP_FILE "--peep-file"
101 #define OPTION_LIB_PATH "--lib-path"
102 #define OPTION_CALLEE_SAVES "--callee-saves"
103 #define OPTION_STACK_LOC "--stack-loc"
104 #define OPTION_XSTACK_LOC "--xstack-loc"
105 #define OPTION_DATA_LOC "--data-loc"
106 #define OPTION_IDATA_LOC "--idata-loc"
107 #define OPTION_XRAM_LOC "--xram-loc"
108 #define OPTION_CODE_LOC "--code-loc"
109 #define OPTION_IRAM_SIZE "--iram-size"
110 #define OPTION_XRAM_SIZE "--xram-size"
111 #define OPTION_CODE_SIZE "--code-size"
112 #define OPTION_VERSION "--version"
113 #define OPTION_NO_LABEL_OPT "--nolabelopt"
114 #define OPTION_NO_LOOP_INV "--noinvariant"
115 #define OPTION_NO_LOOP_IND "--noinduction"
116 #define OPTION_LESS_PEDANTIC "--less-pedantic"
117 #define OPTION_DISABLE_WARNING "--disable-warning"
118 #define OPTION_WERROR "--Werror"
119 #define OPTION_DEBUG "--debug"
120 #define OPTION_NO_GCSE "--nogcse"
121 #define OPTION_NO_XINIT_OPT "--no-xinit-opt"
122 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
123 #define OPTION_ICODE_IN_ASM "--i-code-in-asm"
124 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
125 #define OPTION_MSVC_ERROR_STYLE "--vc"
126 #define OPTION_USE_STDOUT "--use-stdout"
127 #define OPTION_NO_PEEP_COMMENTS "--no-peep-comments"
128 #define OPTION_VERBOSE_ASM "--fverbose-asm"
129 #define OPTION_OPT_CODE_SPEED "--opt-code-speed"
130 #define OPTION_OPT_CODE_SIZE "--opt-code-size"
131 #define OPTION_STD_C89 "--std-c89"
132 #define OPTION_STD_C95 "--std-c95"
133 #define OPTION_STD_C99 "--std-c99"
134 #define OPTION_STD_C11 "--std-c11"
135 #define OPTION_STD_C2X "--std-c2x"
136 #define OPTION_STD_SDCC89 "--std-sdcc89"
137 #define OPTION_STD_SDCC99 "--std-sdcc99"
138 #define OPTION_STD_SDCC11 "--std-sdcc11"
139 #define OPTION_STD_SDCC2X "--std-sdcc2x"
140 #define OPTION_CODE_SEG "--codeseg"
141 #define OPTION_CONST_SEG "--constseg"
142 #define OPTION_DATA_SEG "--dataseg"
143 #define OPTION_DOLLARS_IN_IDENT "--fdollars-in-identifiers"
144 #define OPTION_SIGNED_CHAR "--fsigned-char"
145 #define OPTION_USE_NON_FREE "--use-non-free"
146 #define OPTION_PEEP_RETURN "--peep-return"
147 #define OPTION_NO_PEEP_RETURN "--no-peep-return"
148 #define OPTION_NO_OPTSDCC_IN_ASM "--no-optsdcc-in-asm"
149 #define OPTION_MAX_ALLOCS_PER_NODE "--max-allocs-per-node"
150 #define OPTION_NO_LOSPRE "--nolospre"
151 #define OPTION_ALLOW_UNSAFE_READ "--allow-unsafe-read"
152 #define OPTION_DUMP_AST "--dump-ast"
153 #define OPTION_DUMP_I_CODE "--dump-i-code"
154 #define OPTION_DUMP_GRAPHS "--dump-graphs"
155
156 #define OPTION_SMALL_MODEL "--model-small"
157 #define OPTION_MEDIUM_MODEL "--model-medium"
158 #define OPTION_LARGE_MODEL "--model-large"
159 #define OPTION_HUGE_MODEL "--model-huge"
160
161 static const OPTION optionsTable[] = {
162 {0, NULL, NULL, "General options"},
163 {0, OPTION_HELP, NULL, "Display this help"},
164 {'v', OPTION_VERSION, NULL, "Display sdcc's version"},
165 {0, "--verbose", &options.verbose, "Trace calls to the preprocessor, assembler, and linker"},
166 {'V', NULL, &options.verboseExec, "Execute verbosely. Show sub commands as they are run"},
167 {'d', NULL, NULL, "Output list of mcaro definitions in effect. Use with -E"},
168 {'D', NULL, NULL, "Define macro as in -Dmacro"},
169 {'I', NULL, NULL, "Add to the include (*.h) path, as in -Ipath"},
170 {'A', NULL, NULL, NULL},
171 {'U', NULL, NULL, "Undefine macro as in -Umacro"},
172 {'M', NULL, NULL, "Preprocessor option"},
173 {'W', NULL, NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)"},
174 {'S', NULL, &noAssemble, "Compile only; do not assemble or link"},
175 {'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link"},
176 {'E', "--preprocessonly", &preProcOnly, "Preprocess only, do not compile"},
177 {0, "--c1mode", &options.c1mode, "Act in c1 mode. The standard input is preprocessed code, the output is assembly code."},
178 {'o', NULL, NULL, "Place the output into the given path resp. file"},
179 {0, OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
180 {0, OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
181 {0, OPTION_USE_STDOUT, NULL, "send errors to stdout instead of stderr"},
182 {0, "--nostdlib", &options.nostdlib, "Do not include the standard library directory in the search path"},
183 {0, "--nostdinc", &options.nostdinc, "Do not include the standard include directory in the search path"},
184 {0, OPTION_LESS_PEDANTIC, NULL, "Disable some of the more pedantic warnings"},
185 {0, OPTION_DISABLE_WARNING, NULL, "<nnnn> Disable specific warning"},
186 {0, OPTION_WERROR, NULL, "Treat the warnings as errors"},
187 {0, OPTION_DEBUG, NULL, "Enable debugging symbol output"},
188 {0, "--cyclomatic", &options.cyclomatic, "Display complexity of compiled functions"},
189 {0, OPTION_STD_C89, NULL, "Use ISO C90 (aka ANSI C89) standard (slightly incomplete)"},
190 {0, OPTION_STD_SDCC89, NULL, "Use ISO C90 (aka ANSI C89) standard with SDCC extensions"},
191 {0, OPTION_STD_C95, NULL, "Use ISO C95 (aka ISO C94) standard (slightly incomplete)"},
192 {0, OPTION_STD_C99, NULL, "Use ISO C99 standard (incomplete)"},
193 {0, OPTION_STD_SDCC99, NULL, "Use ISO C99 standard with SDCC extensions"},
194 {0, OPTION_STD_C11, NULL, "Use ISO C11 standard (incomplete)"},
195 {0, OPTION_STD_SDCC11, NULL, "Use ISO C11 standard with SDCC extensions (default)"},
196 {0, OPTION_STD_C2X, NULL, "Use ISO C2X standard (incomplete)"},
197 {0, OPTION_STD_SDCC2X, NULL, "Use ISO C2X standard with SDCC extensions"},
198 {0, OPTION_DOLLARS_IN_IDENT, &options.dollars_in_ident, "Permit '$' as an identifier character"},
199 {0, OPTION_SIGNED_CHAR, &options.signed_char, "Make \"char\" signed by default"},
200 {0, OPTION_USE_NON_FREE, &options.use_non_free, "Search / include non-free licensed libraries and header files"},
201
202 {0, NULL, NULL, "Code generation options"},
203 {'m', NULL, NULL, "Set the port to use e.g. -mz80."},
204 {'p', NULL, NULL, "Select port specific processor e.g. -mpic14 -p16f84"},
205 {0, "--stack-auto", &options.stackAuto, "Stack automatic variables"},
206 {0, "--xstack", &options.useXstack, "Use external stack"},
207 {0, "--int-long-reent", &options.intlong_rent, "Use reentrant calls on the int and long support functions"},
208 {0, "--float-reent", &options.float_rent, "Use reentrant calls on the float support functions"},
209 {0, "--xram-movc", &options.xram_movc, "Use movc instead of movx to read xram (xdata)"},
210 {0, OPTION_CALLEE_SAVES, &options.calleeSavesSet, "<func[,func,...]> Cause the called function to save registers instead of the caller", CLAT_SET},
211 {0, "--profile", &options.profile, "On supported ports, generate extra profiling information"},
212 {0, "--fomit-frame-pointer", &options.omitFramePtr, "Leave out the frame pointer."},
213 {0, "--all-callee-saves", &options.all_callee_saves, "callee will always save registers used"},
214 {0, "--stack-probe", &options.stack_probe, "insert call to function __stack_probe at each function prologue"},
215 {0, OPTION_NO_XINIT_OPT, &options.noXinitOpt, "don't memcpy initialized xram from code"},
216 {0, OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
217 {0, OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
218 {0, OPTION_CODE_SEG, NULL, "<name> use this name for the code segment"},
219 {0, OPTION_CONST_SEG, NULL, "<name> use this name for the const segment"},
220 {0, OPTION_DATA_SEG, NULL, "<name> use this name for the data segment"},
221
222 {0, NULL, NULL, "Optimization options"},
223 {0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables"},
224 {0, OPTION_NO_GCSE, NULL, "Disable the GCSE optimisation"},
225 {0, OPTION_NO_LABEL_OPT, NULL, "Disable label optimisation"},
226 {0, OPTION_NO_LOOP_INV, NULL, "Disable optimisation of invariants"},
227 {0, OPTION_NO_LOOP_IND, NULL, "Disable loop variable induction"},
228 {0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation"},
229 {0, "--no-peep", &options.nopeep, "Disable the peephole assembly file optimisation"},
230 {0, "--no-reg-params", &options.noRegParams, "On some ports, disable passing some parameters in registers"},
231 {0, "--peep-asm", &options.asmpeep, "Enable peephole optimization on inline assembly"},
232 {0, OPTION_PEEP_RETURN, NULL, "Enable peephole optimization for return instructions"},
233 {0, OPTION_NO_PEEP_RETURN, NULL, "Disable peephole optimization for return instructions"},
234 {0, OPTION_PEEP_FILE, &options.peep_file, "<file> use this extra peephole file", CLAT_STRING},
235 {0, OPTION_OPT_CODE_SPEED, NULL, "Optimize for code speed rather than size"},
236 {0, OPTION_OPT_CODE_SIZE, NULL, "Optimize for code size rather than speed"},
237 {0, OPTION_MAX_ALLOCS_PER_NODE, &options.max_allocs_per_node, "Maximum number of register assignments considered at each node of the tree decomposition", CLAT_INTEGER},
238 {0, OPTION_NO_LOSPRE, NULL, "Disable lospre"},
239 {0, OPTION_ALLOW_UNSAFE_READ, NULL, "Allow optimizations to read any memory location anytime"},
240 {0, "--nostdlibcall", &optimize.noStdLibCall, "Disable optimization of calls to standard library"},
241
242 {0, NULL, NULL, "Internal debugging options"},
243 {0, OPTION_DUMP_AST, &options.dump_ast, "Dump front-end AST before generating i-code"},
244 {0, OPTION_DUMP_I_CODE, &options.dump_i_code, "Dump the i-code structure at all stages"},
245 {0, OPTION_DUMP_GRAPHS, &options.dump_graphs, "Dump graphs (control-flow, conflict, etc)"},
246 {0, OPTION_ICODE_IN_ASM, &options.iCodeInAsm, "Include i-code as comments in the asm file"},
247 {0, OPTION_VERBOSE_ASM, &options.verboseAsm, "Include code generator comments in the asm output"},
248
249 {0, NULL, NULL, "Linker options"},
250 {'l', NULL, NULL, "Include the given library in the link"},
251 {'L', NULL, NULL, "Add the next field to the library search path"},
252 {0, OPTION_LIB_PATH, &libPathsSet, "<path> use this path to search for libraries", CLAT_ADD_SET},
253 {0, OPTION_OUT_FMT_IHX, NULL, "Output in Intel hex format"},
254 {0, OPTION_OUT_FMT_S19, NULL, "Output in S19 hex format"},
255 {0, OPTION_XRAM_LOC, NULL, "<nnnn> External Ram start location", CLAT_INTEGER},
256 {0, OPTION_XRAM_SIZE, NULL, "<nnnn> External Ram size"},
257 {0, OPTION_IRAM_SIZE, &options.iram_size, "<nnnn> Internal Ram size", CLAT_INTEGER},
258 {0, OPTION_XSTACK_LOC, &options.xstack_loc, "<nnnn> External Stack start location", CLAT_INTEGER},
259 {0, OPTION_CODE_LOC, &options.code_loc, "<nnnn> Code Segment Location", CLAT_INTEGER},
260 {0, OPTION_CODE_SIZE, &options.code_size, "<nnnn> Code Segment size", CLAT_INTEGER},
261 {0, OPTION_STACK_LOC, &options.stack_loc, "<nnnn> Stack pointer initial value", CLAT_INTEGER},
262 {0, OPTION_DATA_LOC, &options.data_loc, "<nnnn> Direct data start location", CLAT_INTEGER},
263 {0, OPTION_IDATA_LOC, &options.idata_loc, NULL, CLAT_INTEGER},
264
265 {0, OPTION_NO_OPTSDCC_IN_ASM, &options.noOptsdccInAsm, "Do not emit .optsdcc in asm"},
266 /* End of options */
267 {0, NULL}
268 };
269
270 /** Table of all unsupported options and help text to display when one
271 is used.
272 */
273 typedef struct
274 {
275 /** shortOpt as in OPTIONS. */
276 char shortOpt;
277 /** longOpt as in OPTIONS. */
278 const char *longOpt;
279 /** Message to display inside W_UNSUPPORTED_OPT when this option
280 is used. */
281 const char *message;
282 } UNSUPPORTEDOPT;
283
284 static const UNSUPPORTEDOPT unsupportedOptTable[] = {
285 {'X', NULL, "use --xstack-loc instead"},
286 {'x', NULL, "use --xstack instead"},
287 {'i', NULL, "use --idata-loc instead"},
288 {'r', NULL, "use --xdata-loc instead"},
289 {'s', NULL, "use --code-loc instead"},
290 {'Y', NULL, "use -I instead"},
291 {0, "--fommit-frame-pointer", "use --fomit-frame-pointer instead"},
292 };
293
294 /** List of all default constant macros.
295 */
296 static const char *_baseValues[] = {
297 "cpp", "sdcpp",
298 "cppextraopts", "",
299 /* Path seperator character */
300 "sep", DIR_SEPARATOR_STRING,
301 NULL
302 };
303
304 static const char *_preCmd = "{cpp} -nostdinc -Wall {cppstd}{cppextraopts} {fullsrcfilename} {cppoutfilename}";
305
306 PORT *port;
307
308 static PORT *_ports[] = {
309 #if !OPT_DISABLE_MCS51
310 &mcs51_port,
311 #endif
312 #if !OPT_DISABLE_Z80
313 &z80_port,
314 #endif
315 #if !OPT_DISABLE_Z180
316 &z180_port,
317 #endif
318 #if !OPT_DISABLE_R2K
319 &r2k_port,
320 #endif
321 #if !OPT_DISABLE_R3KA
322 &r3ka_port,
323 #endif
324 #if !OPT_DISABLE_GBZ80
325 &gbz80_port,
326 #endif
327 #if !OPT_DISABLE_TLCS90
328 &tlcs90_port,
329 #endif
330 #if !OPT_DISABLE_EZ80_Z80
331 &ez80_z80_port,
332 #endif
333 #if !OPT_DISABLE_AVR
334 &avr_port,
335 #endif
336 #if !OPT_DISABLE_DS390
337 &ds390_port,
338 #endif
339 #if !OPT_DISABLE_PIC16
340 &pic16_port,
341 #endif
342 #if !OPT_DISABLE_PIC14
343 &pic_port,
344 #endif
345 #if !OPT_DISABLE_TININative
346 &tininative_port,
347 #endif
348 #if !OPT_DISABLE_DS400
349 &ds400_port,
350 #endif
351 #if !OPT_DISABLE_HC08
352 &hc08_port,
353 #endif
354 #if !OPT_DISABLE_S08
355 &s08_port,
356 #endif
357 #if !OPT_DISABLE_STM8
358 &stm8_port,
359 #endif
360 #if !OPT_DISABLE_PDK13
361 &pdk13_port,
362 #endif
363 #if !OPT_DISABLE_PDK14
364 &pdk14_port,
365 #endif
366 #if !OPT_DISABLE_PDK15
367 &pdk15_port,
368 #endif
369 };
370
371 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
372
373 /** Sets the port to the one given by the command line option.
374 @param The name minus the option (eg 'mcs51')
375 @return 0 on success.
376 */
377 static void
_setPort(const char * name)378 _setPort (const char *name)
379 {
380 int i;
381 for (i = 0; i < NUM_PORTS; i++)
382 {
383 if (!strcmp (_ports[i]->target, name))
384 {
385 port = _ports[i];
386 return;
387 }
388 }
389 /* Error - didnt find */
390 werror (E_UNKNOWN_TARGET, name);
391 exit (EXIT_FAILURE);
392 }
393
394 /* Override the default processor with the one specified
395 * on the command line */
396 static void
_setProcessor(char * _processor)397 _setProcessor (char *_processor)
398 {
399 port->processor = _processor;
400 }
401
402 static void
_validatePorts(void)403 _validatePorts (void)
404 {
405 int i;
406 for (i = 0; i < NUM_PORTS; i++)
407 {
408 if (_ports[i]->magic != PORT_MAGIC)
409 {
410 /* Uncomment this line to debug which port is causing the problem
411 * (the target name is close to the beginning of the port struct
412 * and probably can be accessed just fine). */
413 fprintf (stderr, "%s :", _ports[i]->target);
414 wassertl (0, "Port definition structure is incomplete");
415 }
416 }
417 }
418
419
420 static char *
program_name(const char * path)421 program_name (const char *path)
422 {
423 #ifdef _WIN32
424 char fname[_MAX_FNAME];
425
426 _splitpath (path, NULL, NULL, fname, NULL);
427 return Safe_strdup (fname);
428 #else
429 char *tmpPath = Safe_strdup (path);
430 char *res = Safe_strdup (basename (tmpPath));
431
432 Safe_free (tmpPath);
433 return res;
434 #endif
435 }
436
437 /* search through the command line for the port */
438 static void
_findPort(int argc,char ** argv)439 _findPort (int argc, char **argv)
440 {
441 char *programName = program_name (*argv);
442 int found = 0;
443 int i;
444
445 _validatePorts ();
446
447 /* try to assign port by command line option */
448 while (argc-- && !found)
449 {
450 if (!strncmp (*argv, "-m", 2))
451 {
452 _setPort (*argv + 2);
453 found = 1;
454 }
455 argv++;
456 }
457
458 /* try to assign port by the name of the executable */
459 for (i = 0; i < NUM_PORTS && !found; i++)
460 {
461 if (strstr (programName, _ports[i]->target))
462 {
463 _setPort (_ports[i]->target);
464 found = 1;
465 }
466 }
467
468 if (!found)
469 {
470 /* Use the first in the list as default */
471 port = _ports[0];
472 }
473
474 Safe_free (programName);
475 }
476
477 /* search through the command line options for the processor */
478 static void
_findProcessor(int argc,char ** argv)479 _findProcessor (int argc, char **argv)
480 {
481 while (argc--)
482 {
483 if (!strncmp (*argv, "-p", 2))
484 {
485 _setProcessor (*argv + 2);
486 return;
487 }
488 argv++;
489 }
490
491 /* no error if processor was not specified. */
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* printVersionInfo - prints the version info */
496 /*-----------------------------------------------------------------*/
497 void
printVersionInfo(FILE * stream)498 printVersionInfo (FILE * stream)
499 {
500 int i;
501
502 fprintf (stream, "SDCC : ");
503 for (i = 0; i < NUM_PORTS; i++)
504 fprintf (stream, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
505
506 fprintf (stream, " " SDCC_VERSION_STR
507 #ifdef SDCC_SUB_VERSION_STR
508 "/" SDCC_SUB_VERSION_STR
509 #endif
510 " #%s (%s)\n", getBuildNumber (), getBuildEnvironment ());
511 fprintf (stream, "published under GNU General Public License (GPL)\n");
512 }
513
514 static void
printOptions(const OPTION * optionsTable,FILE * stream)515 printOptions (const OPTION * optionsTable, FILE * stream)
516 {
517 int i;
518 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL || optionsTable[i].help != NULL; i++)
519 {
520 if (!optionsTable[i].shortOpt && !optionsTable[i].longOpt && optionsTable[i].help)
521 {
522 fprintf (stream, "\n%s:\n", optionsTable[i].help);
523 }
524 else
525 {
526 fprintf (stream, " %c%c %-20s %s\n",
527 optionsTable[i].shortOpt != 0 ? '-' : ' ',
528 optionsTable[i].shortOpt != 0 ? optionsTable[i].shortOpt : ' ',
529 optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
530 optionsTable[i].help != NULL ? optionsTable[i].help : "");
531 }
532 }
533 }
534
535 /*-----------------------------------------------------------------*/
536 /* printUsage - prints command line syntax */
537 /*-----------------------------------------------------------------*/
538 static void
printUsage(bool err)539 printUsage (bool err)
540 {
541 int i;
542 FILE *stream = err ? stderr : stdout;
543
544 printVersionInfo (stream);
545 fprintf (stream,
546 "Usage : sdcc [options] filename\n"
547 "Options :-\n");
548
549 printOptions (optionsTable, stream);
550
551 for (i = 0; i < NUM_PORTS; i++)
552 {
553 if (_ports[i]->poptions != NULL)
554 {
555 fprintf (stream, "\nSpecial options for the %s port:\n", _ports[i]->target);
556 printOptions (_ports[i]->poptions, stream);
557 }
558 }
559 }
560
561 /*-----------------------------------------------------------------*/
562 /* setParseWithComma - separates string with comma to a set */
563 /*-----------------------------------------------------------------*/
564 void
setParseWithComma(set ** dest,const char * src)565 setParseWithComma (set ** dest, const char *src)
566 {
567 const char *p, *end;
568 struct dbuf_s dbuf;
569
570 /* skip the initial white spaces */
571 while (isspace ((unsigned char) *src))
572 ++src;
573
574 /* skip the trailing white spaces */
575 end = &src[strlen (src) - 1];
576 while (end >= src && isspace ((unsigned char) *end))
577 --end;
578 ++end;
579
580 p = src;
581 while (src < end)
582 {
583 dbuf_init (&dbuf, 16);
584
585 while (p < end && ',' != *p)
586 ++p;
587 dbuf_append (&dbuf, src, p - src);
588 addSet (dest, dbuf_detach_c_str (&dbuf));
589
590 src = ++p;
591 }
592 }
593
594 /*-------------------------------------------------------------*/
595 /* setStackSize - set the stack size of a running sdcc process */
596 /*-------------------------------------------------------------*/
597 static void
setStackSize(void)598 setStackSize (void)
599 {
600 #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK)
601 struct rlimit rl = {4 * 1024 * 1024, 4 * 1024 * 1024};
602 setrlimit (RLIMIT_STACK, &rl);
603 #endif
604 }
605
606 /*-----------------------------------------------------------------*/
607 /* setDefaultOptions - sets the default options */
608 /*-----------------------------------------------------------------*/
609 static void
setDefaultOptions(void)610 setDefaultOptions (void)
611 {
612 /* first the options part */
613 options.stack_loc = 0; /* stack pointer initialised to 0 */
614 options.xstack_loc = 1; /* xternal stack starts at 1 */
615 options.code_loc = 0; /* code starts at 0 */
616 options.data_loc = 0; /* JCF: By default let the linker locate data */
617 options.xdata_loc = 1; /* MB: Do not use address 0 by default as it equals NULL */
618 options.idata_loc = 0; /* MB: No need to limit idata to 0x80-0xFF */
619 options.nopeep = 0;
620 options.model = port->general.default_model;
621 options.nostdlib = 0;
622 options.nostdinc = 0;
623 options.verbose = 0;
624 options.std_sdcc = 1; /* enable SDCC language extensions */
625 options.std_c95 = 1;
626 options.std_c99 = 1;
627 options.std_c11 = 1; /* default to C11 (we want inline by default, so we need at least C99, and support for C11 is more complete than C99) */
628 options.std_c2x = 0;
629 options.code_seg = CODE_NAME ? Safe_strdup (CODE_NAME) : NULL; /* default to CSEG for generated code */
630 options.const_seg = CONST_NAME ? Safe_strdup (CONST_NAME) : NULL; /* default to CONST for generated code */
631 options.data_seg = DATA_NAME ? Safe_strdup (DATA_NAME) : NULL; /* default to DATA for non-initialized data */
632 options.stack10bit = 0;
633 options.out_fmt = 0;
634 options.dump_graphs = 0;
635 options.dependencyFileOpt = 0;
636
637 /* now for the optimizations */
638 /* turn on the everything */
639 optimize.global_cse = 1;
640 optimize.label1 = 1;
641 optimize.label2 = 1;
642 optimize.label3 = 1;
643 optimize.label4 = 1;
644 optimize.loopInvariant = 1;
645 optimize.loopInduction = 1;
646 options.max_allocs_per_node = 3000;
647 optimize.lospre = 1;
648 optimize.allow_unsafe_read = 0;
649
650 /* now for the ports */
651 port->setDefaultOptions ();
652 }
653
654 /*-----------------------------------------------------------------*/
655 /* processFile - determines the type of file from the extension */
656 /*-----------------------------------------------------------------*/
657 static void
processFile(char * s)658 processFile (char *s)
659 {
660 const char *extp;
661 struct dbuf_s ext;
662 struct dbuf_s path;
663
664 dbuf_init (&ext, 128);
665 dbuf_init (&path, PATH_MAX);
666
667 /* get the file extension.
668 If no '.' then we don't know what the file type is
669 so give an error and return */
670 if (!dbuf_splitFile (s, &path, &ext))
671 {
672 werror (E_UNKNOWN_FEXT, s);
673
674 dbuf_destroy (&ext);
675 dbuf_destroy (&path);
676
677 return;
678 }
679
680 /* otherwise depending on the file type */
681 extp = dbuf_c_str (&ext);
682 if (STRCASECMP (extp, ".c") == 0 || STRCASECMP (extp, ".h") == 0)
683 {
684 char *p, *m;
685
686 dbuf_destroy (&ext);
687
688 /* source file name : not if we already have a
689 source file */
690 if (fullSrcFileName)
691 {
692 werror (W_TOO_MANY_SRC, s);
693
694 dbuf_destroy (&path);
695
696 return;
697 }
698
699 /* the only source file */
700 fullSrcFileName = s;
701 if (!(srcFile = fopen (fullSrcFileName, "r")))
702 {
703 werror (E_FILE_OPEN_ERR, s);
704
705 dbuf_destroy (&path);
706
707 exit (EXIT_FAILURE);
708 }
709
710 /* get rid of any path information
711 for the module name; */
712 dbuf_init (&ext, 128);
713
714 dbuf_splitPath (dbuf_c_str (&path), NULL, &ext);
715 dbuf_destroy (&path);
716
717 moduleNameBase = Safe_strdup (dbuf_c_str (&ext));
718 m = dbuf_detach (&ext);
719
720 for (p = m; *p; ++p)
721 if (!isalnum ((unsigned char) *p))
722 *p = '_';
723 moduleName = m;
724 return;
725 }
726
727 /* if the extension is type rel_ext
728 additional object file will be passed to the linker */
729 if (STRCASECMP (extp, port->linker.rel_ext) == 0)
730 {
731 dbuf_destroy (&ext);
732 dbuf_destroy (&path);
733
734 addSet (&relFilesSet, Safe_strdup (s));
735 return;
736 }
737
738 /* if .lib or .LIB */
739 if (STRCASECMP (extp, ".lib") == 0)
740 {
741 dbuf_destroy (&ext);
742 dbuf_destroy (&path);
743
744 addSet (&libFilesSet, Safe_strdup (s));
745 return;
746 }
747
748 dbuf_destroy (&ext);
749 dbuf_destroy (&path);
750
751 werror (E_UNKNOWN_FEXT, s);
752 }
753
754 static void
_setModel(int model,const char * sz)755 _setModel (int model, const char *sz)
756 {
757 if (port->general.supported_models & model)
758 options.model = model;
759 else
760 werror (W_UNSUPPORTED_MODEL, sz, port->target);
761 }
762
763 /** Gets the string argument to this option. If the option is '--opt'
764 then for input of '--optxyz' or '--opt xyz' returns xyz.
765 */
766 char *
getStringArg(const char * szStart,char ** argv,int * pi,int argc)767 getStringArg (const char *szStart, char **argv, int *pi, int argc)
768 {
769 if (argv[*pi][strlen (szStart)])
770 {
771 return &argv[*pi][strlen (szStart)];
772 }
773 else
774 {
775 ++(*pi);
776 if (*pi >= argc)
777 {
778 werror (E_ARGUMENT_MISSING, szStart);
779 /* Die here rather than checking for errors later. */
780 exit (EXIT_FAILURE);
781 }
782 else
783 {
784 return argv[*pi];
785 }
786 }
787 }
788
789 /** Gets the integer argument to this option using the same rules as
790 getStringArg.
791 */
792 long
getIntArg(const char * szStart,char ** argv,int * pi,int argc)793 getIntArg (const char *szStart, char **argv, int *pi, int argc)
794 {
795 char *p;
796 int val;
797 char *str = getStringArg (szStart, argv, pi, argc);
798
799 val = strtol (str, &p, 0);
800 if (p == str || *p != '\0')
801 {
802 werror (E_BAD_INT_ARGUMENT, szStart);
803 /* Die here rather than checking for errors later. */
804 exit (EXIT_FAILURE);
805 }
806 return val;
807 }
808
809 static void
verifyShortOption(const char * opt)810 verifyShortOption (const char *opt)
811 {
812 if (strlen (opt) != 2)
813 {
814 werror (W_EXCESS_SHORT_OPTIONS, opt);
815 }
816 }
817
818 static bool
tryHandleUnsupportedOpt(char ** argv,int * pi)819 tryHandleUnsupportedOpt (char **argv, int *pi)
820 {
821 if (argv[*pi][0] == '-')
822 {
823 const char *longOpt = "";
824 char shortOpt = -1;
825 int i;
826
827 if (argv[*pi][1] == '-')
828 {
829 /* Long option. */
830 longOpt = argv[*pi];
831 }
832 else
833 {
834 shortOpt = argv[*pi][1];
835 }
836 for (i = 0; i < LENGTH (unsupportedOptTable); i++)
837 {
838 if (unsupportedOptTable[i].shortOpt == shortOpt ||
839 (longOpt && unsupportedOptTable[i].longOpt && !strcmp (unsupportedOptTable[i].longOpt, longOpt)))
840 {
841 /* Found an unsupported opt. */
842 struct dbuf_s dbuf;
843
844 dbuf_init (&dbuf, 100);
845 dbuf_printf (&dbuf, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
846 werror (W_UNSUPP_OPTION, dbuf_detach_c_str (&dbuf), unsupportedOptTable[i].message);
847 return 1;
848 }
849 }
850 /* Didn't find in the table */
851 return 0;
852 }
853 else
854 {
855 /* Not an option, so can't be unsupported :) */
856 return 0;
857 }
858 }
859
860 static bool
scanOptionsTable(const OPTION * optionsTable,char shortOpt,const char * longOpt,char ** argv,int * pi,int argc)861 scanOptionsTable (const OPTION * optionsTable, char shortOpt, const char *longOpt, char **argv, int *pi, int argc)
862 {
863 int i;
864
865 for (i = 0; optionsTable[i].shortOpt != 0 || optionsTable[i].longOpt != NULL || optionsTable[i].help != NULL; i++)
866 {
867 if (optionsTable[i].shortOpt == shortOpt)
868 {
869 if (optionsTable[i].pparameter != NULL)
870 {
871 verifyShortOption (argv[*pi]);
872
873 (*(int *) optionsTable[i].pparameter)++;
874
875 return TRUE;
876 }
877 }
878 else
879 {
880 size_t len = optionsTable[i].longOpt ? strlen (optionsTable[i].longOpt) : 0;
881
882 if (longOpt &&
883 (optionsTable[i].arg_type != CLAT_BOOLEAN ||
884 (optionsTable[i].arg_type == CLAT_BOOLEAN && len == strlen (longOpt) && optionsTable[i].longOpt)) &&
885 strncmp (optionsTable[i].longOpt, longOpt, len) == 0)
886 {
887 /* If it is a flag then we can handle it here */
888 if (optionsTable[i].pparameter != NULL)
889 {
890 switch (optionsTable[i].arg_type)
891 {
892 case CLAT_BOOLEAN:
893 (*(int *) optionsTable[i].pparameter)++;
894 break;
895
896 case CLAT_INTEGER:
897 *(int *) optionsTable[i].pparameter = getIntArg (optionsTable[i].longOpt, argv, pi, argc);
898 break;
899
900 case CLAT_STRING:
901 if (*(char **) optionsTable[i].pparameter)
902 Safe_free (*(char **) optionsTable[i].pparameter);
903 *(char **) optionsTable[i].pparameter =
904 Safe_strdup (getStringArg (optionsTable[i].longOpt, argv, pi, argc));
905 break;
906
907 case CLAT_SET:
908 if (*(set **) optionsTable[i].pparameter)
909 {
910 deleteSet ((set **) optionsTable[i].pparameter);
911 }
912 setParseWithComma ((set **) optionsTable[i].pparameter,
913 getStringArg (optionsTable[i].longOpt, argv, pi, argc));
914 break;
915
916 case CLAT_ADD_SET:
917 addSet ((set **) optionsTable[i].pparameter,
918 Safe_strdup (getStringArg (optionsTable[i].longOpt, argv, pi, argc)));
919 break;
920 }
921 return TRUE;
922 }
923 else
924 {
925 /* Not a flag. Handled manually later. */
926 return FALSE;
927 }
928 }
929 }
930 }
931 /* Didn't find in the table */
932 return FALSE;
933 }
934
935 static bool
tryHandleSimpleOpt(char ** argv,int * pi,int argc)936 tryHandleSimpleOpt (char **argv, int *pi, int argc)
937 {
938 if (argv[*pi][0] == '-')
939 {
940 const char *longOpt = "";
941 char shortOpt = -1;
942
943 if (argv[*pi][1] == '-')
944 {
945 /* Long option. */
946 longOpt = argv[*pi];
947 }
948 else
949 {
950 shortOpt = argv[*pi][1];
951 }
952
953 if (scanOptionsTable (optionsTable, shortOpt, longOpt, argv, pi, argc))
954 {
955 return TRUE;
956 }
957 else if (port && port->poptions && scanOptionsTable (port->poptions, shortOpt, longOpt, argv, pi, argc))
958 {
959 return TRUE;
960 }
961 else
962 {
963 return FALSE;
964 }
965 }
966 else
967 {
968 /* Not an option, so can't be handled. */
969 return FALSE;
970 }
971 }
972
973 /*-----------------------------------------------------------------*/
974 /* parseCmdLine - parses the command line and sets the options */
975 /*-----------------------------------------------------------------*/
976 static int
parseCmdLine(int argc,char ** argv)977 parseCmdLine (int argc, char **argv)
978 {
979 int i;
980
981 /* go thru all whole command line */
982 for (i = 1; i < argc; i++)
983 {
984 if (i >= argc)
985 break;
986
987 /* check port specific options before general ones */
988 if (port->parseOption (&argc, argv, &i) == TRUE)
989 {
990 continue;
991 }
992
993 if (tryHandleUnsupportedOpt (argv, &i) == TRUE)
994 {
995 continue;
996 }
997
998 if (tryHandleSimpleOpt (argv, &i, argc) == TRUE)
999 {
1000 continue;
1001 }
1002
1003 /* options */
1004 if (argv[i][0] == '-' && argv[i][1] == '-')
1005 {
1006 if (strcmp (argv[i], OPTION_USE_STDOUT) == 0)
1007 {
1008 if (options.use_stdout == 0)
1009 {
1010 options.use_stdout = 1;
1011 dup2 (STDOUT_FILENO, STDERR_FILENO);
1012 }
1013 continue;
1014 }
1015 if (strcmp (argv[i], OPTION_HELP) == 0)
1016 {
1017 printUsage (FALSE);
1018 exit (EXIT_SUCCESS);
1019 }
1020
1021 if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
1022 {
1023 options.out_fmt = 'i';
1024 continue;
1025 }
1026
1027 if (strcmp (argv[i], OPTION_OUT_FMT_S19) == 0)
1028 {
1029 options.out_fmt = 's';
1030 continue;
1031 }
1032
1033 if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
1034 {
1035 _setModel (MODEL_SMALL, argv[i]);
1036 continue;
1037 }
1038
1039 if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
1040 {
1041 _setModel (MODEL_MEDIUM, argv[i]);
1042 continue;
1043 }
1044
1045 if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
1046 {
1047 _setModel (MODEL_LARGE, argv[i]);
1048 continue;
1049 }
1050
1051 if (strcmp (argv[i], OPTION_HUGE_MODEL) == 0)
1052 {
1053 _setModel (MODEL_HUGE, argv[i]);
1054 continue;
1055 }
1056
1057 if (strcmp (argv[i], OPTION_VERSION) == 0)
1058 {
1059 printVersionInfo (stdout);
1060 exit (EXIT_SUCCESS);
1061 continue;
1062 }
1063
1064 if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
1065 {
1066 int val = getIntArg (OPTION_XRAM_LOC, argv, &i, argc);
1067 if (options.xdata_loc == options.xstack_loc)
1068 options.xstack_loc = val;
1069 options.xdata_loc = val;
1070 continue;
1071 }
1072
1073 if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
1074 {
1075 options.xram_size = getIntArg (OPTION_XRAM_SIZE, argv, &i, argc);
1076 options.xram_size_set = TRUE;
1077 continue;
1078 }
1079
1080 if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
1081 {
1082 optimize.global_cse = 0;
1083 continue;
1084 }
1085
1086 if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
1087 {
1088 optimize.loopInvariant = 0;
1089 continue;
1090 }
1091
1092 if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
1093 {
1094 optimize.label2 = 0;
1095 optimize.label4 = 0;
1096 continue;
1097 }
1098
1099 if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
1100 {
1101 optimize.loopInduction = 0;
1102 continue;
1103 }
1104
1105 if (strcmp (argv[i], OPTION_OPT_CODE_SPEED) == 0)
1106 {
1107 optimize.codeSpeed = 1;
1108 optimize.codeSize = 0;
1109 continue;
1110 }
1111
1112 if (strcmp (argv[i], OPTION_OPT_CODE_SIZE) == 0)
1113 {
1114 optimize.codeSpeed = 0;
1115 optimize.codeSize = 1;
1116 continue;
1117 }
1118
1119 if (strcmp (argv[i], OPTION_NO_LOSPRE) == 0)
1120 {
1121 optimize.lospre = 0;
1122 continue;
1123 }
1124
1125 if (strcmp (argv[i], OPTION_ALLOW_UNSAFE_READ) == 0)
1126 {
1127 optimize.allow_unsafe_read = 1;
1128 continue;
1129 }
1130
1131 if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0)
1132 {
1133 options.lessPedantic = 1;
1134 setErrorLogLevel (ERROR_LEVEL_WARNING);
1135 continue;
1136 }
1137
1138 if (strcmp (argv[i], OPTION_DISABLE_WARNING) == 0)
1139 {
1140 int w = getIntArg (OPTION_DISABLE_WARNING, argv, &i, argc);
1141 setWarningDisabled (w);
1142 continue;
1143 }
1144
1145 if (strcmp (argv[i], OPTION_WERROR) == 0)
1146 {
1147 setWError (1);
1148 addSet (&preArgvSet, Safe_strdup ("-Werror"));
1149 continue;
1150 }
1151
1152 if (strcmp (argv[i], OPTION_STD_C89) == 0)
1153 {
1154 options.std_c95 = 0;
1155 options.std_c99 = 0;
1156 options.std_c11 = 0;
1157 options.std_c2x = 0;
1158 options.std_sdcc = 0;
1159 continue;
1160 }
1161
1162 if (strcmp (argv[i], OPTION_STD_C95) == 0)
1163 {
1164 options.std_c95 = 1;
1165 options.std_c99 = 0;
1166 options.std_c11 = 0;
1167 options.std_c2x = 0;
1168 options.std_sdcc = 0;
1169 continue;
1170 }
1171
1172 if (strcmp (argv[i], OPTION_STD_C99) == 0)
1173 {
1174 options.std_c95 = 1;
1175 options.std_c99 = 1;
1176 options.std_c11 = 0;
1177 options.std_c2x = 0;
1178 options.std_sdcc = 0;
1179 continue;
1180 }
1181
1182 if (strcmp (argv[i], OPTION_STD_C11) == 0)
1183 {
1184 options.std_c95 = 1;
1185 options.std_c99 = 1;
1186 options.std_c11 = 1;
1187 options.std_c2x = 0;
1188 options.std_sdcc = 0;
1189 continue;
1190 }
1191
1192 if (strcmp (argv[i], OPTION_STD_C2X) == 0)
1193 {
1194 options.std_c95 = 1;
1195 options.std_c99 = 1;
1196 options.std_c11 = 1;
1197 options.std_c2x = 1;
1198 options.std_sdcc = 0;
1199 continue;
1200 }
1201
1202 if (strcmp (argv[i], OPTION_STD_SDCC89) == 0)
1203 {
1204 options.std_c95 = 0;
1205 options.std_c99 = 0;
1206 options.std_c11 = 0;
1207 options.std_c2x = 0;
1208 options.std_sdcc = 1;
1209 continue;
1210 }
1211
1212 if (strcmp (argv[i], OPTION_STD_SDCC99) == 0)
1213 {
1214 options.std_c95 = 1;
1215 options.std_c99 = 1;
1216 options.std_c11 = 0;
1217 options.std_c2x = 0;
1218 options.std_sdcc = 1;
1219 continue;
1220 }
1221
1222 if (strcmp (argv[i], OPTION_STD_SDCC11) == 0)
1223 {
1224 options.std_c95 = 1;
1225 options.std_c99 = 1;
1226 options.std_c11 = 1;
1227 options.std_c2x = 0;
1228 options.std_sdcc = 1;
1229 continue;
1230 }
1231
1232 if (strcmp (argv[i], OPTION_STD_SDCC2X) == 0)
1233 {
1234 options.std_c95 = 1;
1235 options.std_c99 = 1;
1236 options.std_c11 = 1;
1237 options.std_c2x = 1;
1238 options.std_sdcc = 1;
1239 continue;
1240 }
1241
1242 if (strcmp (argv[i], OPTION_CODE_SEG) == 0)
1243 {
1244 struct dbuf_s segname;
1245
1246 dbuf_init (&segname, 16);
1247 dbuf_printf (&segname, "%-8s(CODE)", getStringArg (OPTION_CODE_SEG, argv, &i, argc));
1248 if (options.code_seg)
1249 Safe_free (options.code_seg);
1250 options.code_seg = dbuf_detach (&segname);
1251 continue;
1252 }
1253
1254 if (strcmp (argv[i], OPTION_CONST_SEG) == 0)
1255 {
1256 struct dbuf_s segname;
1257
1258 dbuf_init (&segname, 16);
1259 dbuf_printf (&segname, "%-8s(CODE)", getStringArg (OPTION_CONST_SEG, argv, &i, argc));
1260 if (options.const_seg)
1261 Safe_free (options.const_seg);
1262 options.const_seg = dbuf_detach (&segname);
1263 continue;
1264 }
1265
1266 if (strcmp (argv[i], OPTION_DATA_SEG) == 0)
1267 {
1268 struct dbuf_s segname;
1269
1270 dbuf_init (&segname, 16);
1271 dbuf_printf (&segname, "%-8s(DATA)", getStringArg (OPTION_DATA_SEG, argv, &i, argc));
1272 if (options.data_seg)
1273 Safe_free (options.data_seg);
1274 options.data_seg = dbuf_detach (&segname);
1275 continue;
1276 }
1277
1278 if (strcmp (argv[i], OPTION_PEEP_RETURN) == 0)
1279 {
1280 options.peepReturn = 1;
1281 continue;
1282 }
1283
1284 if (strcmp (argv[i], OPTION_NO_PEEP_RETURN) == 0)
1285 {
1286 options.peepReturn = -1;
1287 continue;
1288 }
1289
1290 if (strcmp (argv[i], OPTION_DEBUG) == 0)
1291 {
1292 if (options.peepReturn == 0)
1293 options.peepReturn = -1;
1294 options.debug = 1;
1295 continue;
1296 }
1297
1298 werror (W_UNKNOWN_OPTION, argv[i]);
1299 continue;
1300 }
1301
1302 /* if preceded by '-' then option */
1303 if (*argv[i] == '-')
1304 {
1305 switch (argv[i][1])
1306 {
1307 case 'h':
1308 verifyShortOption (argv[i]);
1309
1310 printUsage (FALSE);
1311 exit (EXIT_SUCCESS);
1312 break;
1313
1314 case 'm':
1315 /* Used to select the port. But this has already been done. */
1316 break;
1317
1318 case 'p':
1319 /* Used to select the processor in port. But this has
1320 * already been done. */
1321 break;
1322
1323 case 'c':
1324 verifyShortOption (argv[i]);
1325
1326 options.cc_only = 1;
1327 break;
1328
1329 case 'L':
1330 addSet (&libPathsSet, Safe_strdup (getStringArg ("-L", argv, &i, argc)));
1331 break;
1332
1333 case 'l':
1334 addSet (&libFilesSet, Safe_strdup (getStringArg ("-l", argv, &i, argc)));
1335 break;
1336
1337 case 'o':
1338 {
1339 char *outName = getStringArg ("-o", argv, &i, argc);
1340 size_t len = strlen (outName);
1341
1342 /* point to last character */
1343 if (IS_DIR_SEPARATOR (outName[len - 1]))
1344 {
1345 /* only output path specified */
1346 dstPath = Safe_strndup (outName, len - 1);
1347 fullDstFileName = NULL;
1348 }
1349 else
1350 {
1351 struct dbuf_s path;
1352
1353 dbuf_init (&path, PATH_MAX);
1354 fullDstFileName = Safe_strdup (outName);
1355
1356 /* get rid of the "."-extension */
1357 dbuf_splitFile (outName, &path, NULL);
1358
1359 dstFileName = dbuf_detach_c_str (&path);
1360
1361 dbuf_init (&path, PATH_MAX);
1362 /* strip module name to get path */
1363 if (dbuf_splitPath (dstFileName, &path, NULL))
1364 dstPath = dbuf_detach_c_str (&path);
1365 else
1366 dbuf_destroy (&path);
1367 }
1368 break;
1369 }
1370
1371 case 'W':
1372 /* pre-processer options */
1373 if (argv[i][2] == 'p')
1374 {
1375 setParseWithComma (&preArgvSet, getStringArg ("-Wp", argv, &i, argc));
1376 }
1377 /* linker options */
1378 else if (argv[i][2] == 'l')
1379 {
1380 setParseWithComma (&linkOptionsSet, getStringArg ("-Wl", argv, &i, argc));
1381 }
1382 /* assembler options */
1383 else if (argv[i][2] == 'a')
1384 {
1385 setParseWithComma (&asmOptionsSet, getStringArg ("-Wa", argv, &i, argc));
1386 }
1387 else
1388 {
1389 werror (W_UNKNOWN_OPTION, argv[i]);
1390 }
1391 break;
1392
1393 case 'v':
1394 verifyShortOption (argv[i]);
1395
1396 printVersionInfo (stdout);
1397 exit (EXIT_SUCCESS);
1398 break;
1399
1400 /* preprocessor options */
1401 case 'M':
1402 {
1403 if (argv[i][2] == 'M')
1404 {
1405 if (argv[i][3] == 'D')
1406 {
1407 options.dependencyFileOpt = USER_DEPENDENCY_FILE_OPT;
1408 }
1409 else
1410 {
1411 addSet (&preArgvSet, Safe_strdup ("-MM"));
1412 preProcOnly = 1;
1413 }
1414 }
1415 else
1416 {
1417 if (argv[i][2] == 'D')
1418 {
1419 options.dependencyFileOpt = SYSTEM_DEPENDENCY_FILE_OPT;
1420 }
1421 else
1422 {
1423 addSet (&preArgvSet, Safe_strdup ("-M"));
1424 preProcOnly = 1;
1425 }
1426 }
1427 break;
1428 }
1429
1430 case 'd':
1431 case 'D':
1432 case 'I':
1433 case 'A':
1434 case 'U':
1435 {
1436 char sOpt = argv[i][1];
1437 char *rest, *s;
1438 struct dbuf_s dbuf;
1439
1440 if (argv[i][2] == ' ' || argv[i][2] == '\0')
1441 {
1442 i++;
1443 if (i >= argc)
1444 {
1445 /* No argument. */
1446 werror (E_ARGUMENT_MISSING, argv[i - 1]);
1447 break;
1448 }
1449 else
1450 {
1451 rest = argv[i];
1452 }
1453 }
1454 else
1455 rest = &argv[i][2];
1456
1457 if (sOpt == 'Y')
1458 sOpt = 'I';
1459
1460 s = shell_escape (rest);
1461 dbuf_init (&dbuf, 256);
1462 dbuf_printf (&dbuf, "-%c%s", sOpt, s);
1463 Safe_free (s);
1464 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
1465 if (sOpt == 'I')
1466 {
1467 addSet (&includeDirsSet, Safe_strdup (rest));
1468 addSet (&userIncDirsSet, Safe_strdup (rest));
1469 }
1470 }
1471 break;
1472
1473 default:
1474 werror (W_UNKNOWN_OPTION, argv[i]);
1475 }
1476 continue;
1477 }
1478
1479 /* no option must be a filename */
1480 if (options.c1mode)
1481 {
1482 werror (W_NO_FILE_ARG_IN_C1, argv[i]);
1483 }
1484 else
1485 {
1486 processFile (argv[i]);
1487 }
1488 }
1489
1490 /* some sanity checks in c1 mode */
1491 if (options.c1mode)
1492 {
1493 const char *s;
1494
1495 if (fullSrcFileName)
1496 {
1497 fclose (srcFile);
1498 werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
1499 }
1500 fullSrcFileName = NULL;
1501 for (s = setFirstItem (relFilesSet); s != NULL; s = setNextItem (relFilesSet))
1502 {
1503 werror (W_NO_FILE_ARG_IN_C1, s);
1504 }
1505 for (s = setFirstItem (libFilesSet); s != NULL; s = setNextItem (libFilesSet))
1506 {
1507 werror (W_NO_FILE_ARG_IN_C1, s);
1508 }
1509 deleteSet (&relFilesSet);
1510 deleteSet (&libFilesSet);
1511
1512 if (options.cc_only || noAssemble || preProcOnly)
1513 {
1514 werror (W_ILLEGAL_OPT_COMBINATION);
1515 }
1516 options.cc_only = noAssemble = preProcOnly = 0;
1517 if (!dstFileName)
1518 {
1519 werror (E_NEED_OPT_O_IN_C1);
1520 exit (EXIT_FAILURE);
1521 }
1522 else
1523 {
1524 char *p, *m;
1525
1526 m = Safe_strdup (dstFileName);
1527 for (p = m; *p; ++p)
1528 if (!isalnum ((unsigned char) *p))
1529 *p = '_';
1530 moduleName = m;
1531 }
1532 }
1533 /* if no dstFileName given with -o, we've to find one: */
1534 if (!dstFileName)
1535 {
1536 const char *s;
1537
1538 /* use the modulename from the C-source */
1539 if (fullSrcFileName)
1540 {
1541 struct dbuf_s path;
1542
1543 if (*dstPath != '\0')
1544 {
1545 dbuf_init (&path, 128);
1546 dbuf_makePath (&path, dstPath, moduleNameBase);
1547 dstFileName = dbuf_detach_c_str (&path);
1548 }
1549 else
1550 dstFileName = Safe_strdup (moduleNameBase);
1551 }
1552 /* use the modulename from the first object file */
1553 else if ((s = peekSet (relFilesSet)) != NULL)
1554 {
1555 struct dbuf_s file;
1556
1557 dbuf_init (&file, 128);
1558
1559 /* get rid of the "."-extension */
1560 dbuf_splitFile (s, &file, NULL);
1561
1562 s = dbuf_detach_c_str (&file);
1563
1564 dbuf_init (&file, PATH_MAX);
1565
1566 dbuf_splitPath (s, NULL, &file);
1567
1568 if (*dstPath != '\0')
1569 {
1570 struct dbuf_s path;
1571
1572 dbuf_init (&path, PATH_MAX);
1573 dbuf_makePath (&path, dstPath, dbuf_detach_c_str (&file));
1574 dstFileName = dbuf_detach_c_str (&path);
1575 }
1576 else
1577 {
1578 dstFileName = dbuf_detach_c_str (&file);
1579 }
1580 }
1581 /* else no module given: help text is displayed */
1582 }
1583
1584 /* set int, long and float reentrancy based on stack-auto */
1585 if (options.stackAuto)
1586 {
1587 options.intlong_rent++;
1588 options.float_rent++;
1589 }
1590
1591 /* if debug option is set then open the cdbFile */
1592 if (options.debug && fullSrcFileName)
1593 {
1594 struct dbuf_s adbFile;
1595
1596 dbuf_init (&adbFile, PATH_MAX);
1597 dbuf_append_str (&adbFile, dstFileName);
1598 dbuf_append_str (&adbFile, ".adb");
1599
1600 if (debugFile->openFile (dbuf_c_str (&adbFile)))
1601 debugFile->writeModule (moduleName);
1602 else
1603 werror (E_FILE_OPEN_ERR, dbuf_c_str (&adbFile));
1604
1605 dbuf_destroy (&adbFile);
1606 }
1607 MSVC_style (options.vc_err_style);
1608
1609 return 0;
1610 }
1611
1612 /*-----------------------------------------------------------------*/
1613 /* finalizeOptions - finalize (post-process) options */
1614 /*-----------------------------------------------------------------*/
1615 static void
finalizeOptions(void)1616 finalizeOptions (void)
1617 {
1618 /* no peephole comments if not verbose asm */
1619 if (!options.verboseAsm)
1620 options.noPeepComments = 1;
1621 }
1622
1623 static const char *
getOutFmtExt(void)1624 getOutFmtExt (void)
1625 {
1626 switch (options.out_fmt)
1627 {
1628 default:
1629 case 'i':
1630 return ".ihx";
1631
1632 case 's':
1633 return ".s19";
1634
1635 case 'E':
1636 return ".elf";
1637 }
1638 }
1639
1640 /*-----------------------------------------------------------------*/
1641 /* linkEdit : - calls the linkage editor with options */
1642 /*-----------------------------------------------------------------*/
1643 static void
linkEdit(char ** envp)1644 linkEdit (char **envp)
1645 {
1646 FILE *lnkfile;
1647 int system_ret;
1648 const char *s;
1649 struct dbuf_s linkerScriptFileName;
1650 struct dbuf_s binFileName;
1651 char *buf, *tb;
1652
1653 dbuf_init (&linkerScriptFileName, PATH_MAX);
1654 dbuf_init (&binFileName, PATH_MAX);
1655
1656 if (port->linker.needLinkerScript)
1657 {
1658 char out_fmt = (options.out_fmt == 0) ? 'i' : options.out_fmt;
1659
1660 if (NULL != fullDstFileName)
1661 {
1662 dbuf_append_str (&binFileName, fullDstFileName);
1663 }
1664 else
1665 {
1666 dbuf_append_str (&binFileName, dstFileName);
1667 dbuf_append_str (&binFileName, getOutFmtExt ());
1668 }
1669
1670 /* first we need to create the <filename>.lk file */
1671 dbuf_printf (&linkerScriptFileName, "%s.lk", dstFileName);
1672 if (!(lnkfile = fopen (dbuf_c_str (&linkerScriptFileName), "w")))
1673 {
1674 werror (E_FILE_OPEN_ERR, dbuf_c_str (&linkerScriptFileName));
1675 exit (EXIT_FAILURE);
1676 }
1677
1678 if (TARGET_Z80_LIKE)
1679 {
1680 fprintf (lnkfile, "-mjwx\n-%c %s\n", out_fmt, dbuf_c_str (&binFileName));
1681 }
1682 else /* For all the other ports which need linker script */
1683 {
1684 fprintf (lnkfile, "-muwx\n-%c %s\n", out_fmt, dbuf_c_str (&binFileName));
1685 if (TARGET_MCS51_LIKE)
1686 fprintf (lnkfile, "-M\n");
1687 if (!options.no_pack_iram)
1688 fprintf (lnkfile, "-Y\n");
1689 else
1690 werror (W_DEPRECATED_OPTION, "--no-pack-iram");
1691 }
1692
1693 if (!TARGET_Z80_LIKE) /* Not for the z80, gbz80 */
1694 {
1695 /* if iram size specified */
1696 if (options.iram_size)
1697 fprintf (lnkfile, "-I 0x%04x\n", options.iram_size);
1698
1699 /* if stack size specified */
1700 if (options.stack_size)
1701 fprintf (lnkfile, "-S 0x%02x\n", options.stack_size);
1702
1703 /* if xram size specified */
1704 if (options.xram_size_set)
1705 fprintf (lnkfile, "-X 0x%04x\n", options.xram_size);
1706
1707 /* if code size specified */
1708 if (options.code_size)
1709 fprintf (lnkfile, "-C 0x%04x\n", options.code_size);
1710 }
1711
1712 if (options.debug)
1713 fprintf (lnkfile, "-y\n");
1714
1715 #define WRITE_SEG_LOC(N, L) \
1716 if (N) \
1717 { \
1718 char *c, *segName; \
1719 segName = Safe_strdup (N); \
1720 c = strtok (segName, " \t"); \
1721 fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1722 if (segName) { Safe_free (segName); } \
1723 }
1724
1725 if (!TARGET_Z80_LIKE) /* Not for the z80, z180, gbz80 */
1726 {
1727
1728 /* code segment start */
1729 WRITE_SEG_LOC (HOME_NAME, options.code_loc);
1730
1731 /* data segment start. If zero, the linker chooses
1732 the best place for data */
1733 if (options.data_loc)
1734 {
1735 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
1736 }
1737
1738 /* xdata segment start. If zero, the linker chooses
1739 the best place for xdata */
1740 if (options.xdata_loc)
1741 {
1742 WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
1743 }
1744
1745 /* pdata/xstack segment start. If zero, the linker
1746 chooses the best place for them */
1747 if (options.xstack_loc)
1748 {
1749 WRITE_SEG_LOC (PDATA_NAME, options.xstack_loc);
1750 }
1751
1752 /* indirect data */
1753 if (IDATA_NAME)
1754 {
1755 WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
1756 }
1757
1758 /* bit segment start */
1759 WRITE_SEG_LOC (BIT_NAME, 0);
1760
1761 /* stack start */
1762 if ((options.stack_loc) && (options.stack_loc < 0x100) && !TARGET_HC08_LIKE)
1763 {
1764 WRITE_SEG_LOC ("SSEG", options.stack_loc);
1765 }
1766 }
1767 else /* For the z80, z180, gbz80 */
1768 {
1769 WRITE_SEG_LOC ("_CODE", options.code_loc);
1770 WRITE_SEG_LOC ("_DATA", options.data_loc);
1771 }
1772
1773 /* If the port has any special linker area declarations, get 'em */
1774 if (port->extraAreas.genExtraAreaLinkOptions)
1775 {
1776 port->extraAreas.genExtraAreaLinkOptions (lnkfile);
1777 }
1778
1779 /* add the extra linker options */
1780 fputStrSet (lnkfile, linkOptionsSet);
1781
1782 /* command line defined library paths if specified */
1783 for (s = setFirstItem (libPathsSet); s != NULL; s = setNextItem (libPathsSet))
1784 fprintf (lnkfile, "-k %s\n", s);
1785
1786 /* standard library path */
1787 if (!options.nostdlib)
1788 {
1789 for (s = setFirstItem (libDirsSet); s != NULL; s = setNextItem (libDirsSet))
1790 fprintf (lnkfile, "-k %s\n", s);
1791 }
1792
1793 /* command line defined library files if specified */
1794 for (s = setFirstItem (libFilesSet); s != NULL; s = setNextItem (libFilesSet))
1795 fprintf (lnkfile, "-l %s\n", s);
1796
1797 /* standard library files */
1798 if (!options.nostdlib)
1799 {
1800 if (NULL != port->linker.libs)
1801 {
1802 const char *const *p;
1803
1804 for (p = port->linker.libs; NULL != *p; ++p)
1805 {
1806 fprintf (lnkfile, "-l %s\n", *p);
1807 }
1808 }
1809 }
1810
1811 /* put in the object file, generated from the C cource */
1812 if (fullSrcFileName)
1813 {
1814 struct dbuf_s path;
1815
1816 dbuf_init (&path, PATH_MAX);
1817 dbuf_printf (&path, "%s%s", dstFileName, port->linker.rel_ext);
1818 addSetHead (&relFilesSet, dbuf_detach (&path));
1819 }
1820
1821 if (!options.no_std_crt0)
1822 {
1823 const char *const *p;
1824 set *crtSet = NULL;
1825
1826 if (NULL != port->linker.crt)
1827 {
1828 struct dbuf_s crtpath;
1829
1830 dbuf_init (&crtpath, PATH_MAX);
1831
1832 for (p = port->linker.crt; NULL != *p; ++p)
1833 {
1834 /* Try to find where C runtime files are ...
1835 It is very important for this file to be first on the linking proccess
1836 so the areas are set in the correct order, expecially _GSINIT */
1837 for (s = setFirstItem (libDirsSet); s != NULL; s = setNextItem (libDirsSet))
1838 {
1839 dbuf_set_length (&crtpath, 0);
1840 dbuf_printf (&crtpath, "%s%c%s", s, DIR_SEPARATOR_CHAR, *p);
1841
1842 if (!access (dbuf_c_str (&crtpath), 0)) /* Found it! */
1843 {
1844 /* append C runtime file to the crt list */
1845 addSet (&crtSet, Safe_strdup (dbuf_c_str (&crtpath)));
1846 break;
1847 }
1848 }
1849 if (NULL == s)
1850 {
1851 /* not found in standard library directories, search in user defined library paths */
1852 /* TODO: should crt be searched here at all? */
1853 for (s = setFirstItem (libPathsSet); s != NULL; s = setNextItem (libPathsSet))
1854 {
1855 dbuf_set_length (&crtpath, 0);
1856 dbuf_printf (&crtpath, "%s%c%s", s, DIR_SEPARATOR_CHAR, *p);
1857
1858 if (!access (dbuf_c_str (&crtpath), 0)) /* Found it! */
1859 {
1860 /* append C runtime file to the crt list */
1861 addSet (&crtSet, Safe_strdup (dbuf_c_str (&crtpath)));
1862 break;
1863 }
1864 }
1865 }
1866 if (NULL == s)
1867 fprintf (stderr, "Warning: couldn't find %s\n", *p);
1868 }
1869 dbuf_destroy (&crtpath);
1870 }
1871
1872 /* Merge crtSet and relFilesSet */
1873 mergeSets (&crtSet, relFilesSet);
1874 relFilesSet = crtSet;
1875 }
1876
1877 /* put in all object files */
1878 fputStrSet (lnkfile, relFilesSet);
1879
1880 fprintf (lnkfile, "\n-e\n");
1881 fclose (lnkfile);
1882 } /* if(port->linker.needLinkerScript) */
1883
1884 if (port->linker.cmd)
1885 {
1886 /* shell_escape file names */
1887 char *b3 = shell_escape (dbuf_c_str (&linkerScriptFileName));
1888 char *bfn = shell_escape (dbuf_c_str (&binFileName));
1889
1890 buf = buildCmdLine (port->linker.cmd, b3, bfn, NULL, linkOptionsSet);
1891 Safe_free (b3);
1892 Safe_free (bfn);
1893 }
1894 else
1895 {
1896 buf = buildMacros (port->linker.mcmd);
1897 }
1898
1899 dbuf_destroy (&linkerScriptFileName);
1900
1901 tb = setPrefixSuffix (buf);
1902 if (options.verbose)
1903 printf ("sdcc: %s\n", tb);
1904 system_ret = sdcc_system (tb);
1905
1906 /* if the binary file name is defined,
1907 rename the linker output file name to binary file name */
1908 if (fullDstFileName)
1909 {
1910 struct dbuf_s lkrFileName;
1911
1912 dbuf_init (&lkrFileName, PATH_MAX);
1913 dbuf_append_str (&lkrFileName, dstFileName);
1914 dbuf_append_str (&lkrFileName, getOutFmtExt ());
1915
1916 if (FILENAME_CMP (dbuf_c_str (&binFileName), dbuf_c_str (&lkrFileName)))
1917 remove (dbuf_c_str (&binFileName));
1918 rename (dbuf_c_str (&lkrFileName), dbuf_c_str (&binFileName));
1919
1920 dbuf_destroy (&lkrFileName);
1921 }
1922
1923 dbuf_destroy (&binFileName);
1924
1925 if (system_ret)
1926 exit (EXIT_FAILURE);
1927 }
1928
1929 /*-----------------------------------------------------------------*/
1930 /* assemble - spawns the assembler with arguments */
1931 /*-----------------------------------------------------------------*/
1932 static void
assemble(char ** envp)1933 assemble (char **envp)
1934 {
1935 struct dbuf_s asmName;
1936
1937 if (port->assembler.do_assemble)
1938 {
1939 port->assembler.do_assemble (asmOptionsSet);
1940 }
1941 else
1942 {
1943 char *buf, *tb;
1944
1945 /* build assembler output filename */
1946 dbuf_init (&asmName, PATH_MAX);
1947
1948 /* -o option overrides default name? */
1949 if (options.cc_only && fullDstFileName)
1950 {
1951 dbuf_append_str (&asmName, fullDstFileName);
1952 }
1953 else
1954 {
1955 /* the assembled file gets the name of the first module */
1956 dbuf_printf (&asmName, "%s%s", dstFileName, port->linker.rel_ext);
1957 }
1958
1959 if (port->assembler.cmd)
1960 {
1961 /* shell_escape file names */
1962 char *dfn = shell_escape (dstFileName);
1963 char *asmn = shell_escape (dbuf_c_str (&asmName));
1964
1965 buf = buildCmdLine (port->assembler.cmd, dfn, asmn,
1966 options.debug ? port->assembler.debug_opts : port->assembler.plain_opts, asmOptionsSet);
1967 Safe_free (dfn);
1968 Safe_free (asmn);
1969 }
1970 else
1971 {
1972 buf = buildMacros (port->assembler.mcmd);
1973 }
1974
1975 dbuf_destroy (&asmName);
1976 tb = setPrefixSuffix (buf);
1977
1978 if (options.verbose)
1979 printf ("sdcc: %s\n", tb);
1980 if (sdcc_system (tb))
1981 {
1982 Safe_free (buf);
1983 /* either system() or the assembler itself has reported an error */
1984 exit (EXIT_FAILURE);
1985 }
1986 Safe_free (buf);
1987
1988 if (options.cc_only && fullDstFileName && TARGET_PIC_LIKE)
1989 {
1990 /* gpasm assembler doesn't properly handle the -o option:
1991 the file extension is replaced with .o,
1992 so sdcc have to rename the object file manually.
1993 This has been fixed in gpasm svn:
1994 http://sourceforge.net/tracker/?func=detail&aid=3018645&group_id=41924&atid=431665
1995 TODO: This code should be removed when the next gputils version
1996 after gpasm-0.13.7 beta will be released */
1997 struct dbuf_s outName;
1998 dbuf_init (&outName, PATH_MAX);
1999 dbuf_printf (&outName, "%s%s", dstFileName, port->linker.rel_ext);
2000
2001 if (strcmp (dbuf_c_str (&outName), fullDstFileName))
2002 {
2003 /* file names are different: rename the genatated object file */
2004 remove (fullDstFileName);
2005 rename (dbuf_c_str (&outName), fullDstFileName);
2006 }
2007 dbuf_destroy (&outName);
2008 }
2009 }
2010 }
2011
2012 /*-----------------------------------------------------------------*/
2013 /* preProcess - spawns the preprocessor with arguments */
2014 /*-----------------------------------------------------------------*/
2015 static int
preProcess(char ** envp)2016 preProcess (char **envp)
2017 {
2018 if (options.c1mode)
2019 {
2020 yyin = stdin;
2021 }
2022 else
2023 {
2024 const char *s;
2025 set *inclList = NULL;
2026 char *buf;
2027
2028 if (NULL != port->linker.rel_ext)
2029 {
2030 struct dbuf_s dbuf;
2031
2032 dbuf_init (&dbuf, 256);
2033 dbuf_printf (&dbuf, "-obj-ext=%s", port->linker.rel_ext);
2034 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2035 }
2036
2037 if (options.dependencyFileOpt)
2038 {
2039 struct dbuf_s dbuf;
2040
2041 dbuf_init (&dbuf, PATH_MAX);
2042 if (options.dependencyFileOpt == SYSTEM_DEPENDENCY_FILE_OPT)
2043 dbuf_append_str (&dbuf, "-MD ");
2044 else
2045 dbuf_append_str (&dbuf, "-MMD ");
2046 if (fullDstFileName)
2047 dbuf_splitFile (fullDstFileName, &dbuf, NULL);
2048 else
2049 dbuf_append_str (&dbuf, dstFileName);
2050 dbuf_append_str (&dbuf, ".d");
2051 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2052
2053 dbuf_init (&dbuf, PATH_MAX);
2054 if (fullDstFileName)
2055 dbuf_printf (&dbuf, "-MT %s", fullDstFileName);
2056 else
2057 dbuf_printf (&dbuf, "-MT %s%s", dstFileName, port->linker.rel_ext);
2058 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2059 }
2060
2061 /* if using dollar signs in identifiers */
2062 if (options.dollars_in_ident)
2063 addSet (&preArgvSet, Safe_strdup ("-fdollars-in-identifiers"));
2064
2065 /* if using external stack define the macro */
2066 if (options.useXstack)
2067 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_USE_XSTACK"));
2068
2069 /* set the macro for stack autos */
2070 if (options.stackAuto)
2071 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_STACK_AUTO"));
2072
2073 /* set the macro for stack autos */
2074 if (options.stack10bit)
2075 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_STACK_TENBIT"));
2076
2077 /* set the macro for no overlay */
2078 if (options.noOverlay)
2079 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_NOOVERLAY"));
2080
2081 /* set the macro for unsigned char */
2082 if (options.signed_char)
2083 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_CHAR_SIGNED"));
2084 else
2085 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_CHAR_UNSIGNED"));
2086
2087 /* set the macro for non-free */
2088 if (options.use_non_free)
2089 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_USE_NON_FREE"));
2090
2091 /* set the macro for large model */
2092 switch (options.model)
2093 {
2094 case MODEL_LARGE:
2095 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_LARGE"));
2096 break;
2097
2098 case MODEL_SMALL:
2099 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_SMALL"));
2100 break;
2101
2102 case MODEL_COMPACT:
2103 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_COMPACT"));
2104 break;
2105
2106 case MODEL_MEDIUM:
2107 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_MEDIUM"));
2108 break;
2109
2110 case MODEL_HUGE:
2111 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_HUGE"));
2112 break;
2113
2114 case MODEL_FLAT24:
2115 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_MODEL_FLAT24"));
2116 break;
2117
2118 case NO_MODEL:
2119 break;
2120
2121 default:
2122 werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
2123 break;
2124 }
2125
2126 /* set macro corresponding to compiler option */
2127 if (options.intlong_rent)
2128 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_INT_LONG_REENT"));
2129
2130 /* set macro corresponding to compiler option */
2131 if (options.float_rent)
2132 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_FLOAT_REENT"));
2133
2134 if (options.all_callee_saves)
2135 addSet(&preArgvSet, Safe_strdup("-D__SDCC_ALL_CALLEE_SAVES"));
2136
2137 /* add SDCC version number */
2138 {
2139 struct dbuf_s dbuf;
2140
2141 dbuf_init (&dbuf, 32);
2142 dbuf_printf (&dbuf, "-D__SDCC=%d_%d_%d", SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2143 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2144 }
2145 {
2146 struct dbuf_s dbuf;
2147
2148 dbuf_init (&dbuf, 32);
2149 dbuf_printf (&dbuf, "-D__SDCC_VERSION_MAJOR=%d", SDCC_VERSION_HI);
2150 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2151 }
2152 {
2153 struct dbuf_s dbuf;
2154
2155 dbuf_init (&dbuf, 32);
2156 dbuf_printf (&dbuf, "-D__SDCC_VERSION_MINOR=%d", SDCC_VERSION_LO);
2157 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2158 }
2159 {
2160 struct dbuf_s dbuf;
2161
2162 dbuf_init (&dbuf, 32);
2163 dbuf_printf (&dbuf, "-D__SDCC_VERSION_PATCH=%d", SDCC_VERSION_P);
2164 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2165 }
2166
2167 /* A macro that has been deprecated since 3.2.0,
2168 since its name makes it non-compliant.
2169 It got removed a few times, but keeps coming back.
2170 This time it got added back for the 3.7.0 release
2171 to support the old SiLabs IDE */
2172 if (TARGET_IS_MCS51 && options.std_sdcc)
2173 {
2174 struct dbuf_s dbuf;
2175
2176 dbuf_init (&dbuf, 32);
2177 dbuf_printf (&dbuf, "-DSDCC=%d%d%d", SDCC_VERSION_HI, SDCC_VERSION_LO, SDCC_VERSION_P);
2178 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2179 }
2180
2181 /* add SDCC revision number */
2182 {
2183 struct dbuf_s dbuf;
2184
2185 dbuf_init (&dbuf, 20);
2186 dbuf_printf (&dbuf, "-D__SDCC_REVISION=%s", getBuildNumber ());
2187 addSet (&preArgvSet, dbuf_detach_c_str (&dbuf));
2188 }
2189
2190 /* add port (processor information to processor */
2191 addSet (&preArgvSet, Safe_strdup ("-D__SDCC_{port}"));
2192
2193 /* Optional C features not (yet) supported by SDCC */
2194 addSet (&preArgvSet, Safe_strdup ("-D__STDC_NO_COMPLEX__=1"));
2195 addSet (&preArgvSet, Safe_strdup ("-D__STDC_NO_THREADS__=1"));
2196 addSet (&preArgvSet, Safe_strdup ("-D__STDC_NO_ATOMICS__=1"));
2197 addSet (&preArgvSet, Safe_strdup ("-D__STDC_NO_VLA__=1"));
2198
2199 /* Character encoding - these need to be set in device/lib/Makefile.in for $CPP, too */
2200 addSet (&preArgvSet, Safe_strdup ("-D__STDC_ISO_10646__=201409L")); // wchar_t is UTF-32
2201 addSet (&preArgvSet, Safe_strdup ("-D__STDC_UTF_16__=1")); // char16_t is UTF-16
2202 addSet (&preArgvSet, Safe_strdup ("-D__STDC_UTF_32__=1")); // char32_t is UTF-32
2203
2204 /* standard include path */
2205 if (!options.nostdinc)
2206 {
2207 inclList = processStrSet (includeDirsSet, "-isystem ", NULL, shell_escape);
2208 mergeSets (&preArgvSet, inclList);
2209 }
2210
2211 setMainValue ("cppextraopts", (s = joinStrSet (preArgvSet)));
2212 Safe_free ((void *) s);
2213 if (inclList != NULL)
2214 deleteSet (&inclList);
2215
2216 if (preProcOnly && fullDstFileName)
2217 {
2218 /* -E and -o given */
2219 char *s = shell_escape (fullDstFileName);
2220
2221 setMainValue ("cppoutfilename", s);
2222 Safe_free (s);
2223 }
2224 else
2225 {
2226 /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
2227 setMainValue ("cppoutfilename", NULL);
2228 }
2229
2230 if (options.verbose)
2231 printf ("sdcc: Calling preprocessor...\n");
2232 buf = buildMacros (_preCmd);
2233 buf = setPrefixSuffix (buf);
2234 if (options.verbose)
2235 printf ("sdcc: %s\n", buf);
2236
2237 if (preProcOnly)
2238 {
2239 if (sdcc_system (buf))
2240 {
2241 exit (EXIT_FAILURE);
2242 }
2243
2244 exit (EXIT_SUCCESS);
2245 }
2246
2247 yyin = sdcc_popen (buf);
2248 if (yyin == NULL)
2249 {
2250 perror ("Preproc file not found");
2251 exit (EXIT_FAILURE);
2252 }
2253 }
2254
2255 return 0;
2256 }
2257
2258 /* Set bin paths */
2259 static void
setBinPaths(const char * argv0)2260 setBinPaths (const char *argv0)
2261 {
2262 const char *p;
2263
2264 /*
2265 * Search logic:
2266 *
2267 * 1. - $SDCCDIR/PREFIX2BIN_DIR
2268 * 2. - path(argv[0])
2269 * 3. - $PATH
2270 */
2271
2272 /* do it in reverse mode, so that addSetHead() can be used
2273 instead of slower addSet() */
2274
2275 if ((p = getBinPath (argv0)) != NULL)
2276 addSetHead (&binPathSet, (void *) p);
2277
2278 if ((p = getenv (SDCC_DIR_NAME)) != NULL)
2279 {
2280 struct dbuf_s dbuf;
2281
2282 dbuf_init (&dbuf, PATH_MAX);
2283 dbuf_append_str (&dbuf, p);
2284 dbuf_append_str (&dbuf, PREFIX2BIN_DIR);
2285 addSetHead (&binPathSet, dbuf_detach_c_str (&dbuf));
2286 }
2287 }
2288
2289 /* Set system include path */
2290 static void
setIncludePath(void)2291 setIncludePath (void)
2292 {
2293 /*
2294 * Search logic:
2295 *
2296 * 1. - $SDCC_INCLUDE/target
2297 * 2. - $SDCC_INCLUDE
2298 * 3. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2299 * 4. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
2300 * 5. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
2301 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
2302 * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
2303 * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
2304 * 9. - $SDCC_HOME/PREFIX2DATA_DIR/NON_FREE_INCLUDE_DIR_SUFFIX/target
2305 * 10. - path(argv[0])/BIN2DATA_DIR/NON_FREE_INCLUDE_DIR_SUFFIX/target
2306 * 11. - DATADIR/NON_FREE_INCLUDE_DIR_SUFFIX/target (only on *nix)
2307 * 12. - $SDCC_HOME/PREFIX2DATA_DIR/NON_FREE_INCLUDE_DIR_SUFFIX
2308 * 13. - path(argv[0])/BIN2DATA_DIR/NON_FREE_INCLUDE_DIR_SUFFIX
2309 * 14. - DATADIR/NON_FREE_INCLUDE_DIR_SUFFIX (only on *nix)
2310 */
2311
2312 if (!options.nostdinc)
2313 {
2314 char *p;
2315 set *tempSet;
2316
2317 tempSet = processStrSet (dataDirsSet, NULL, INCLUDE_DIR_SUFFIX, NULL);
2318 includeDirsSet = processStrSet (tempSet, NULL, DIR_SEPARATOR_STRING, NULL);
2319 includeDirsSet = processStrSet (includeDirsSet, NULL, port->target, NULL);
2320 mergeSets (&includeDirsSet, tempSet);
2321
2322 if (options.use_non_free)
2323 {
2324 set *tempSet1;
2325
2326 tempSet = processStrSet (dataDirsSet, NULL, NON_FREE_INCLUDE_DIR_SUFFIX, NULL);
2327 tempSet1 = processStrSet (tempSet, NULL, DIR_SEPARATOR_STRING, NULL);
2328 tempSet1 = processStrSet (tempSet1, NULL, port->target, NULL);
2329 mergeSets (&tempSet1, tempSet);
2330 mergeSets (&includeDirsSet, tempSet1);
2331 }
2332
2333 if ((p = getenv (SDCC_INCLUDE_NAME)) != NULL)
2334 {
2335 struct dbuf_s dbuf;
2336
2337 dbuf_init (&dbuf, PATH_MAX);
2338 addSetHead (&includeDirsSet, p);
2339 dbuf_makePath (&dbuf, p, port->target);
2340 addSetHead (&includeDirsSet, dbuf_detach (&dbuf));
2341 }
2342 }
2343 }
2344
2345 /* Set system lib path */
2346 static void
setLibPath(void)2347 setLibPath (void)
2348 {
2349 /*
2350 * Search logic:
2351 *
2352 * 1. - $SDCC_LIB/<model>
2353 * 2. - $SDCC_LIB
2354 * 3. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
2355 * 4. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
2356 * 5. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
2357 * 6. - $SDCC_HOME/PREFIX2DATA_DIR/NON_FREE_LIB_DIR_SUFFIX/<model>
2358 * 7. - path(argv[0])/BIN2DATA_DIR/NON_FREE_LIB_DIR_SUFFIX/<model>
2359 * 8. - DATADIR/NON_FREE_LIB_DIR_SUFFIX/<model> (only on *nix)
2360 */
2361
2362 if (!options.nostdlib)
2363 {
2364 char *p;
2365 const char *targetname;
2366
2367 struct dbuf_s dbuf;
2368
2369 dbuf_init (&dbuf, PATH_MAX);
2370
2371 targetname = port->target;
2372
2373 dbuf_makePath (&dbuf, LIB_DIR_SUFFIX, port->general.get_model ? port->general.get_model () : targetname);
2374 libDirsSet = processStrSet (dataDirsSet, NULL, dbuf_c_str (&dbuf), NULL);
2375
2376 if (options.use_non_free)
2377 {
2378 dbuf_set_length (&dbuf, 0);
2379 dbuf_makePath (&dbuf, NON_FREE_LIB_DIR_SUFFIX, port->general.get_model ? port->general.get_model () : targetname);
2380 mergeSets (&libDirsSet, processStrSet (dataDirsSet, NULL, dbuf_c_str (&dbuf), NULL));
2381 }
2382
2383 if ((p = getenv (SDCC_LIB_NAME)) != NULL)
2384 {
2385 addSetHead (&libDirsSet, Safe_strdup (p));
2386
2387 dbuf_set_length (&dbuf, 0);
2388 dbuf_makePath (&dbuf, p, port->general.get_model ? port->general.get_model () : targetname);
2389 addSetHead (&libDirsSet, dbuf_detach (&dbuf));
2390 }
2391 else
2392 dbuf_destroy (&dbuf);
2393 }
2394 }
2395
2396 /* Set data path */
2397 static void
setDataPaths(const char * argv0)2398 setDataPaths (const char *argv0)
2399 {
2400 const char *p;
2401
2402 /*
2403 * Search logic:
2404 *
2405 * 1. - $SDCC_HOME/PREFIX2DATA_DIR
2406 * 2. - path(argv[0])/BIN2DATA_DIR
2407 * 3. - DATADIR (only on *nix)
2408 */
2409
2410 if ((p = getenv (SDCC_DIR_NAME)) != NULL)
2411 {
2412 struct dbuf_s dbuf;
2413
2414 dbuf_init (&dbuf, PATH_MAX);
2415 dbuf_append_str (&dbuf, p);
2416 dbuf_append_str (&dbuf, PREFIX2DATA_DIR);
2417 addSetHead (&dataDirsSet, dbuf_detach_c_str (&dbuf));
2418 }
2419
2420 if ((p = getBinPath (argv0)) != NULL)
2421 {
2422 struct dbuf_s dbuf;
2423
2424 dbuf_init (&dbuf, PATH_MAX);
2425 dbuf_append_str (&dbuf, p);
2426 dbuf_append_str (&dbuf, BIN2DATA_DIR);
2427 addSetHead (&dataDirsSet, dbuf_detach_c_str (&dbuf));
2428 }
2429
2430 #ifdef _WIN32
2431 if (peekSet (dataDirsSet) == NULL)
2432 {
2433 /* this should never happen... */
2434 wassertl (0, "Can't get binary path");
2435 }
2436 #else
2437 addSet (&dataDirsSet, Safe_strdup (DATADIR));
2438 #endif
2439
2440 setIncludePath ();
2441 setLibPath ();
2442 }
2443
2444 static void
initValues(void)2445 initValues (void)
2446 {
2447 char *s;
2448
2449 populateMainValues (_baseValues);
2450 setMainValue ("port", port->target);
2451 setMainValue ("objext", port->linker.rel_ext);
2452 setMainValue ("asmext", port->assembler.file_ext);
2453
2454 setMainValue ("dstfilename", dstFileName);
2455
2456 s = fullSrcFileName ? shell_escape (fullSrcFileName) : "fullsrcfilename";
2457 setMainValue ("fullsrcfilename", s);
2458 if (fullSrcFileName)
2459 Safe_free (s);
2460
2461 if (options.cc_only && fullDstFileName)
2462 /* compile + assemble and -o given: -o specifies name of object file */
2463 {
2464 setMainValue ("objdstfilename", fullDstFileName);
2465 }
2466 else
2467 {
2468 setMainValue ("objdstfilename", "{stdobjdstfilename}");
2469 }
2470 if (fullDstFileName)
2471 /* if we're linking, -o gives the final file name */
2472 {
2473 setMainValue ("linkdstfilename", fullDstFileName);
2474 }
2475 else
2476 {
2477 setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
2478 }
2479
2480 /*
2481 * Make sure the preprocessor is called with the "-std" option
2482 * corresponding to the --std used to start sdcc
2483 */
2484 setMainValue ("cppstd",
2485 options.std_c11 ? "-std=c11 " :
2486 (options.std_c99 ? "-std=c99 " :
2487 (options.std_c95 ? "-std=iso9899:199409 " :
2488 "-std=c89 ")));
2489 }
2490
2491 static void
doPrintSearchDirs(void)2492 doPrintSearchDirs (void)
2493 {
2494 const char *s;
2495
2496 printf ("programs:\n");
2497 fputStrSet (stdout, binPathSet);
2498
2499 printf ("datadir:\n");
2500 fputStrSet (stdout, dataDirsSet);
2501
2502 printf ("includedir:\n");
2503 fputStrSet (stdout, includeDirsSet);
2504
2505 printf ("libdir:\n");
2506 for (s = setFirstItem (libDirsSet); s != NULL; s = setNextItem (libDirsSet))
2507 fprintf (stdout, "%s\n", s);
2508
2509 printf ("libpath:\n");
2510 fputStrSet (stdout, libPathsSet);
2511 }
2512
2513
2514 static void
sig_handler(int signal)2515 sig_handler (int signal)
2516 {
2517 char *sig_string;
2518
2519 switch (signal)
2520 {
2521 case SIGABRT:
2522 sig_string = "SIGABRT";
2523 break;
2524
2525 case SIGTERM:
2526 sig_string = "SIGTERM";
2527 break;
2528
2529 case SIGINT:
2530 sig_string = "SIGINT";
2531 break;
2532
2533 case SIGSEGV:
2534 sig_string = "SIGSEGV";
2535 break;
2536
2537 default:
2538 sig_string = "Unknown?";
2539 break;
2540 }
2541 fprintf (stderr, "Caught signal %d: %s\n", signal, sig_string);
2542 exit (EXIT_FAILURE);
2543 }
2544
2545 /*
2546 * main routine
2547 * initialises and calls the parser
2548 */
2549
2550 int
main(int argc,char ** argv,char ** envp)2551 main (int argc, char **argv, char **envp)
2552 {
2553 /* get the prefix and the suffix of the sdcc command */
2554 getPrefixSuffix (argv[0]);
2555
2556 /* set a larger stack size of a running sdcc process to 4MB */
2557 setStackSize ();
2558
2559 /* turn all optimizations off by default */
2560 memset (&optimize, 0, sizeof (struct optimize));
2561
2562 if (NUM_PORTS == 0)
2563 {
2564 fprintf (stderr, "Build error: no ports are enabled.\n");
2565 exit (EXIT_FAILURE);
2566 }
2567
2568 /* install signal handler;
2569 it's only purpose is to call exit() to remove temp files */
2570 if (!getenv ("SDCC_LEAVE_SIGNALS"))
2571 {
2572 signal (SIGABRT, sig_handler);
2573 signal (SIGTERM, sig_handler);
2574 signal (SIGINT, sig_handler);
2575 signal (SIGSEGV, sig_handler);
2576 }
2577
2578 /* Before parsing the command line options, do a
2579 * search for the port and processor and initialize
2580 * them if they're found. (We can't gurantee that these
2581 * will be the first options specified).
2582 */
2583
2584 _findPort (argc, argv);
2585
2586 #ifdef JAMIN_DS390
2587 if (strcmp (port->target, "mcs51") == 0)
2588 {
2589 printf ("DS390 jammed in A\n");
2590 _setPort ("ds390");
2591 ds390_jammed = 1;
2592 }
2593 #endif
2594
2595 _findProcessor (argc, argv);
2596
2597 /* Initalise the port. */
2598 if (port->init)
2599 port->init ();
2600
2601 setDefaultOptions ();
2602 #ifdef JAMIN_DS390
2603 if (ds390_jammed)
2604 {
2605 options.model = MODEL_SMALL;
2606 options.stack10bit = 0;
2607 }
2608 #endif
2609
2610 parseCmdLine (argc, argv);
2611
2612 if (options.verbose && NULL != port->processor)
2613 printf ("Processor: %s\n", port->processor);
2614
2615 initValues ();
2616
2617 setBinPaths (argv[0]);
2618 setDataPaths (argv[0]);
2619
2620 if (port->initPaths)
2621 port->initPaths ();
2622
2623 if (options.printSearchDirs)
2624 doPrintSearchDirs ();
2625
2626 /* if no input then printUsage & exit */
2627 if (!options.c1mode && !fullSrcFileName && peekSet (relFilesSet) == NULL)
2628 {
2629 if (options.printSearchDirs)
2630 exit (EXIT_SUCCESS);
2631 printUsage (TRUE);
2632 exit (EXIT_FAILURE);
2633 }
2634
2635 /* initMem() is expensive, but
2636 initMem() must called before port->finaliseOptions ().
2637 And the z80 port needs port->finaliseOptions(),
2638 even if we're only linking. */
2639 initMem ();
2640
2641 /* finalize target specific options */
2642 port->finaliseOptions ();
2643
2644 /* finalize common options */
2645 finalizeOptions ();
2646
2647 if (fullSrcFileName || options.c1mode)
2648 {
2649 preProcess (envp);
2650
2651 initSymt ();
2652 initiCode ();
2653 initCSupport ();
2654 initBuiltIns ();
2655 initPeepHole ();
2656
2657 if (options.verbose)
2658 printf ("sdcc: Generating code...\n");
2659
2660 yyparse ();
2661
2662 if (!options.c1mode)
2663 if (sdcc_pclose (yyin))
2664 fatalError = 1;
2665
2666 if (fatalError)
2667 exit (EXIT_FAILURE);
2668
2669 if (port->general.do_glue != NULL)
2670 (*port->general.do_glue) ();
2671 else
2672 {
2673 /* this shouldn't happen */
2674 assert (FALSE);
2675 /* in case of NDEBUG */
2676 glue ();
2677 }
2678
2679 if (fatalError)
2680 exit (EXIT_FAILURE);
2681
2682 if (!options.c1mode && !noAssemble)
2683 {
2684 if (options.verbose)
2685 printf ("sdcc: Calling assembler...\n");
2686 assemble (envp);
2687 }
2688 }
2689 closeDumpFiles ();
2690
2691 if (options.debug && debugFile)
2692 debugFile->closeFile ();
2693
2694 if (!options.cc_only && !fatalError && !noAssemble && !options.c1mode && (fullSrcFileName || peekSet (relFilesSet) != NULL))
2695 {
2696 if (options.verbose)
2697 printf ("sdcc: Calling linker...\n");
2698
2699 if (port->linker.do_link)
2700 port->linker.do_link ();
2701 else
2702 linkEdit (envp);
2703 }
2704
2705 return 0;
2706 }
2707
2708