#include "warning.h"
#ifndef PREPROCESSOR
-#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -U__SIZE_TYPE__ -D__SIZE_TYPE__=__SIZE_TYPE__ -m32"
+#ifdef __APPLE__
+#define PREPROCESSOR "gcc -E -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -U__SIZE_TYPE__ -D__SIZE_TYPE__=unsigned\\ long -m32 -U__STRICT_ANSI__"
+#else
+#define PREPROCESSOR "cpp -std=c99 -U__WCHAR_TYPE__ -D__WCHAR_TYPE__=int -U__SIZE_TYPE__ -D__SIZE_TYPE__=unsigned\\ long -m32 -U__STRICT_ANSI__"
+#endif
#endif
#ifndef LINKER
#endif
#ifndef ASSEMBLER
+#ifdef __APPLE__
+#define ASSEMBLER "gcc -c -xassembler"
+#else
#define ASSEMBLER "as --32"
#endif
+#endif
/** The current c mode/dialect. */
unsigned int c_mode = _C89|_C99|_GNUC;
/** use builtins for some libc functions */
bool use_builtins = false;
+/** we have extern function with const attribute. */
+bool have_const_functions = false;
+
/* to switch on printing of implicit casts */
extern bool print_implicit_casts;
/* to switch on printing of parenthesis to indicate operator precedence */
extern bool print_parenthesis;
-static int verbose;
-static struct obstack cppflags_obst, ldflags_obst;
+static int verbose;
+static struct obstack cppflags_obst, ldflags_obst;
+static char dep_target[1024];
+static const char *outname;
typedef struct file_list_entry_t file_list_entry_t;
static FILE *preprocess(const char *fname)
{
- char buf[4096];
obstack_1grow(&cppflags_obst, '\0');
const char *flags = obstack_finish(&cppflags_obst);
- snprintf(buf, sizeof(buf), PREPROCESSOR " %s %s", flags, fname);
+ obstack_printf(&cppflags_obst, "%s", PREPROCESSOR);
+ if (dep_target[0] != '\0') {
+ add_flag(&cppflags_obst, "-MF");
+ add_flag(&cppflags_obst, "%s", dep_target);
+ if (outname != NULL) {
+ add_flag(&cppflags_obst, "-MQ");
+ add_flag(&cppflags_obst, "%s", outname);
+ }
+ }
+ if (flags[0] != '\0') {
+ obstack_printf(&cppflags_obst, " %s", flags);
+ }
+ add_flag(&cppflags_obst, "%s", fname);
+
+ obstack_1grow(&cppflags_obst, '\0');
+ const char *buf = obstack_finish(&cppflags_obst);
if(verbose) {
puts(buf);
}
fprintf(stderr, "invoking preprocessor failed\n");
exit(1);
}
+
return f;
}
}
}
+static inline bool streq(char const* a, char const* b)
+{
+ return strcmp(a, b) == 0;
+}
+
+static inline bool strstart(char const* str, char const* start)
+{
+ do {
+ if (*start == '\0')
+ return true;
+ } while (*str++ == *start++);
+ return false;
+}
+
static FILE *open_file(const char *filename)
{
- if (strcmp(filename, "-") == 0) {
+ if (streq(filename, "-")) {
return stdin;
}
static filetype_t get_filetype_from_string(const char *string)
{
- if (strcmp(string, "c") == 0 || strcmp(string, "c-header") == 0)
+ if (streq(string, "c") || streq(string, "c-header"))
return FILETYPE_C;
- if (strcmp(string, "assembler") == 0)
+ if (streq(string, "assembler"))
return FILETYPE_PREPROCESSED_ASSEMBLER;
- if (strcmp(string, "assembler-with-cpp") == 0)
+ if (streq(string, "assembler-with-cpp"))
return FILETYPE_ASSEMBLER;
- if (strcmp(string, "none") == 0)
+ if (streq(string, "none"))
return FILETYPE_AUTODETECT;
return FILETYPE_UNKNOWN;
{
initialize_firm();
- const char *outname = NULL;
- const char *dumpfunction = NULL;
- compile_mode_t mode = CompileAssembleLink;
- int opt_level = 1;
- int result = EXIT_SUCCESS;
- char cpu_arch[16] = "ia32";
- file_list_entry_t *files = NULL;
- file_list_entry_t *last_file = NULL;
+ const char *dumpfunction = NULL;
+ compile_mode_t mode = CompileAssembleLink;
+ int opt_level = 1;
+ int result = EXIT_SUCCESS;
+ char cpu_arch[16] = "ia32";
+ file_list_entry_t *files = NULL;
+ file_list_entry_t *last_file = NULL;
+ bool construct_dep_target = false;
struct obstack file_obst;
obstack_init(&cppflags_obst);
default:
case 4:
set_option("strict-aliasing");
+ /* use_builtins = true; */
/* fallthrough */
case 3:
set_option("cond-eval");
set_option("if-conv");
- use_builtins = true;
/* fallthrough */
case 2:
set_option("inline");
break;
}
+#ifdef __APPLE__
+ /* Darwin expects the stack to be aligned to 16byte boundary */
+ firm_be_option("ia32-stackalign=4");
+#endif
+
/* parse rest of options */
filetype_t forced_filetype = FILETYPE_AUTODETECT;
bool help_displayed = false;
fprintf(stderr, "Unknown language '%s'\n", opt);
argument_errors = true;
}
- } else if(strcmp(option, "M") == 0) {
+ } else if (streq(option, "M")) {
mode = PreprocessOnly;
add_flag(&cppflags_obst, "-M");
- } else if(strcmp(option, "MMD") == 0
- || strcmp(option, "MD") == 0
- || strcmp(option, "MM") == 0) {
+ } else if (streq(option, "MMD") ||
+ streq(option, "MD")) {
+ construct_dep_target = true;
+ add_flag(&cppflags_obst, "-%s", option);
+ } else if(streq(option, "MM") ||
+ streq(option, "MP")) {
add_flag(&cppflags_obst, "-%s", option);
- } else if(strcmp(option, "MT") == 0
- || strcmp(option, "MQ") == 0
- || strcmp(option, "MF") == 0) {
+ } else if (streq(option, "MT") ||
+ streq(option, "MQ") ||
+ streq(option, "MF")) {
const char *opt;
GET_ARG_AFTER(opt, "-MT");
add_flag(&cppflags_obst, "-%s", option);
add_flag(&cppflags_obst, "%s", opt);
- } else if(strcmp(option, "pipe") == 0) {
+ } else if (streq(option, "pipe")) {
/* here for gcc compatibility */
- } else if(option[0] == 'f') {
- const char *opt;
- GET_ARG_AFTER(opt, "-f");
-
- if(strcmp(opt, "syntax-only") == 0) {
- mode = ParseOnly;
- } else if(strcmp(opt, "omit-frame-pointer") == 0) {
- set_be_option("omitfp");
- } else if(strcmp(opt, "no-omit-frame-pointer") == 0) {
- set_be_option("omitfp=no");
- } else if(strcmp(opt, "strength-reduce") == 0) {
- firm_option("strength-red");
- } else if(strcmp(opt, "fast-math") == 0
- || strcmp(opt, "unroll-loops") == 0
- || strcmp(opt, "expensive-optimizations") == 0
- || strcmp(opt, "no-common") == 0
- || strncmp(opt, "align-loops=", sizeof("align-loops=")-1) == 0
- || strncmp(opt, "align-jumps=", sizeof("align-jumps=")-1) == 0
- || strncmp(opt, "align-functions=", sizeof("align-functions=")-1) == 0) {
- fprintf(stderr, "ignoring gcc option '-f %s'\n", opt);
+ } else if (option[0] == 'f') {
+ char const *orig_opt;
+ GET_ARG_AFTER(orig_opt, "-f");
+
+ if (strstart(orig_opt, "align-loops=") ||
+ strstart(orig_opt, "align-jumps=") ||
+ strstart(orig_opt, "align-functions=")) {
+ fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
} else {
- int res = firm_option(opt);
- if (res == 0) {
- fprintf(stderr, "error: unknown Firm option '-f %s'\n",
- opt);
- argument_errors = true;
- continue;
- } else if (res == -1) {
- help_displayed = true;
+ char const *opt = orig_opt;
+ bool truth_value = true;
+ if (opt[0] == 'n' && opt[1] == 'o' && opt[2] == '-') {
+ truth_value = false;
+ opt += 3;
+ }
+
+ if (streq(opt, "dollars-in-identifiers")) {
+ allow_dollar_in_symbol = truth_value;
+ } if (streq(opt, "builtins")) {
+ use_builtins = truth_value;
+ } else if (streq(opt, "short-wchar")) {
+ opt_short_wchar_t = truth_value;
+ } else if (streq(opt, "syntax-only")) {
+ mode = truth_value ? ParseOnly : CompileAssembleLink;
+ } else if (streq(opt, "omit-frame-pointer")) {
+ set_be_option(truth_value ? "omitfp" : "omitfp=no");
+ } else if (streq(opt, "strength-reduce")) {
+ firm_option(truth_value ? "strength-red" : "no-strength-red");
+ } else if (streq(opt, "fast-math") ||
+ streq(opt, "jump-tables") ||
+ streq(opt, "unroll-loops") ||
+ streq(opt, "expensive-optimizations") ||
+ streq(opt, "common") ||
+ streq(opt, "PIC") ||
+ streq(opt, "align-loops") ||
+ streq(opt, "align-jumps") ||
+ streq(opt, "align-functions")) {
+ fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
+ } else {
+ int res = firm_option(orig_opt);
+ if (res == 0) {
+ fprintf(stderr, "error: unknown Firm option '-f%s'\n",
+ orig_opt);
+ argument_errors = true;
+ continue;
+ } else if (res == -1) {
+ help_displayed = true;
+ }
}
}
- } else if(option[0] == 'b') {
+ } else if (option[0] == 'b') {
const char *opt;
GET_ARG_AFTER(opt, "-b");
int res = firm_be_option(opt);
argument_errors = true;
} else if (res == -1) {
help_displayed = true;
- } else {
- if (strncmp(opt, "isa=", 4) == 0)
- strncpy(cpu_arch, opt, sizeof(cpu_arch));
+ } else if (strstart(opt, "isa=")) {
+ strncpy(cpu_arch, opt, sizeof(cpu_arch));
+ }
+ } else if (option[0] == 'W') {
+ if (strstart(option + 1, "l,")) // a gcc-style linker option
+ {
+ const char *opt;
+ GET_ARG_AFTER(opt, "-Wl,");
+ add_flag(&ldflags_obst, "-Wl,%s", opt);
}
- } else if(option[0] == 'W') {
- set_warning_opt(&option[1]);
+ else set_warning_opt(&option[1]);
} else if(option[0] == 'm') {
/* -m options */
const char *opt;
char arch_opt[64];
GET_ARG_AFTER(opt, "-m");
- if(strncmp(opt, "arch=", 5) == 0) {
+ if (strstart(opt, "arch=")) {
GET_ARG_AFTER(opt, "-march=");
snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
if (res == 0)
argument_errors = true;
}
- } else if(strncmp(opt, "tune=", 5) == 0) {
+ } else if (strstart(opt, "tune=")) {
GET_ARG_AFTER(opt, "-mtune=");
snprintf(arch_opt, sizeof(arch_opt), "%s-opt=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
if (res == 0)
argument_errors = true;
- } else if(strncmp(opt, "cpu=", 4) == 0) {
+ } else if (strstart(opt, "cpu=")) {
GET_ARG_AFTER(opt, "-mcpu=");
snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
if (res == 0)
argument_errors = true;
- } else if(strncmp(opt, "fpmath=", 7) == 0) {
+ } else if (strstart(opt, "fpmath=")) {
GET_ARG_AFTER(opt, "-mfpmath=");
- if(strcmp(opt, "387") == 0)
+ if (streq(opt, "387"))
opt = "x87";
- else if(strcmp(opt, "sse") == 0)
+ else if (streq(opt, "sse"))
opt = "sse2";
else {
fprintf(stderr, "error: option -mfpumath supports only 387 or sse\n");
if (res == 0)
argument_errors = true;
}
- } else if(strncmp(opt, "preferred-stack-boundary=", 25) == 0) {
+ } else if (strstart(opt, "preferred-stack-boundary=")) {
GET_ARG_AFTER(opt, "-mpreferred-stack-boundary=");
snprintf(arch_opt, sizeof(arch_opt), "%s-stackalign=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
if (res == 0)
argument_errors = true;
- } else if(strcmp(opt, "omit-leaf-frame-pointer") == 0) {
+ } else if (streq(opt, "omit-leaf-frame-pointer")) {
set_be_option("omitleaffp=1");
- } else if(strcmp(opt, "no-omit-leaf-frame-pointer") == 0) {
+ } else if (streq(opt, "no-omit-leaf-frame-pointer")) {
set_be_option("omitleaffp=0");
} else {
char *endptr;
machine_size = (unsigned int)value;
}
}
- } else if(strcmp(option, "pg") == 0) {
+ } else if (streq(option, "pg")) {
set_be_option("gprof");
add_flag(&ldflags_obst, "-pg");
- } else if(strcmp(option, "pedantic") == 0) {
+ } else if (streq(option, "pedantic") ||
+ streq(option, "ansi")) {
fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
- } else if(strcmp(option, "shared") == 0) {
+ } else if (streq(option, "shared")) {
add_flag(&ldflags_obst, "-shared");
- } else if(strncmp(option, "std=", 4) == 0) {
- if(strcmp(&option[4], "c99") == 0) {
+ } else if (strstart(option, "std=")) {
+ if (streq(&option[4], "c99")) {
c_mode = _C89|_C99;
- } else if(strcmp(&option[4], "c89") == 0) {
+ } else if (streq(&option[4], "c89")) {
c_mode = _C89;
- } else if(strcmp(&option[4], "gnu99") == 0) {
+ } else if (streq(&option[4], "gnu99")) {
c_mode = _C89|_C99|_GNUC;
- } else if(strcmp(&option[4], "microsoft") == 0) {
+ } else if (streq(&option[4], "microsoft")) {
c_mode = _C89|_C99|_MS;
} else
fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
- } else if(strcmp(option, "version") == 0) {
+ } else if (streq(option, "version")) {
print_cparser_version();
} else if (option[0] == '-') {
/* double dash option */
++option;
- if(strcmp(option, "gcc") == 0) {
+ if (streq(option, "gcc")) {
c_mode |= _GNUC;
- } else if(strcmp(option, "no-gcc") == 0) {
+ } else if (streq(option, "no-gcc")) {
c_mode &= ~_GNUC;
- } else if(strcmp(option, "ms") == 0) {
+ } else if (streq(option, "ms")) {
c_mode |= _MS;
- } else if(strcmp(option, "no-ms") == 0) {
+ } else if (streq(option, "no-ms")) {
c_mode &= ~_MS;
- } else if(strcmp(option, "signed-chars") == 0) {
+ } else if (streq(option, "signed-chars")) {
char_is_signed = true;
- } else if(strcmp(option, "unsigned-chars") == 0) {
+ } else if (streq(option, "unsigned-chars")) {
char_is_signed = false;
- } else if(strcmp(option, "strict") == 0) {
+ } else if (streq(option, "strict")) {
strict_mode = true;
- } else if(strcmp(option, "lextest") == 0) {
+ } else if (streq(option, "lextest")) {
mode = LexTest;
- } else if(strcmp(option, "benchmark") == 0) {
+ } else if (streq(option, "benchmark")) {
mode = BenchmarkParser;
- } else if(strcmp(option, "print-ast") == 0) {
+ } else if (streq(option, "print-ast")) {
mode = PrintAst;
- } else if(strcmp(option, "print-implicit-cast") == 0) {
+ } else if (streq(option, "print-implicit-cast")) {
print_implicit_casts = true;
- } else if(strcmp(option, "print-parenthesis") == 0) {
+ } else if (streq(option, "print-parenthesis")) {
print_parenthesis = true;
- } else if(strcmp(option, "print-fluffy") == 0) {
+ } else if (streq(option, "print-fluffy")) {
mode = PrintFluffy;
- } else if(strcmp(option, "print-caml") == 0) {
+ } else if (streq(option, "print-caml")) {
mode = PrintCaml;
- } else if(strcmp(option, "version") == 0) {
+ } else if (streq(option, "version")) {
print_cparser_version();
exit(EXIT_SUCCESS);
- } else if(strcmp(option, "dump-function") == 0) {
+ } else if (streq(option, "dump-function")) {
++i;
if(i >= argc) {
fprintf(stderr, "error: "
filetype_t type = forced_filetype;
const char *filename = arg;
if (type == FILETYPE_AUTODETECT) {
- size_t len = strlen(arg);
+ size_t const len = strlen(arg);
if (len < 2 && arg[0] == '-') {
- /* - implicitely means C source file */
+ /* - implicitly means C source file */
type = FILETYPE_C;
filename = NULL;
- } else if (len > 2 && arg[len-2] == '.') {
- switch(arg[len-1]) {
- case 'c': type = FILETYPE_C; break;
- case 'h': type = FILETYPE_C; break;
+ } else if (len > 2 && arg[len - 2] == '.') {
+ switch (arg[len - 1]) {
+ case 'c': type = FILETYPE_C; break;
+ case 'h': type = FILETYPE_C; break;
case 's': type = FILETYPE_PREPROCESSED_ASSEMBLER; break;
- case 'S': type = FILETYPE_ASSEMBLER; break;
- case 'o': type = FILETYPE_OBJECT; break;
+ case 'S': type = FILETYPE_ASSEMBLER; break;
+
+ case 'a':
+ case 'o': type = FILETYPE_OBJECT; break;
+ }
+ } else if (len > 3 && arg[len - 3] == '.') {
+ if (streq(arg + len - 2, "so")) {
+ type = FILETYPE_OBJECT;
}
}
init_parser();
init_ast2firm();
+ if (construct_dep_target) {
+ if (outname != 0 && strlen(outname) >= 2) {
+ get_output_name(dep_target, sizeof(dep_target), outname, ".d");
+ } else {
+ get_output_name(dep_target, sizeof(dep_target), files->name, ".d");
+ }
+ } else {
+ dep_target[0] = '\0';
+ }
+
char outnamebuf[4096];
if (outname == NULL) {
const char *filename = files->name;
assert(outname != NULL);
FILE *out;
- if(strcmp(outname, "-") == 0) {
+ if (streq(outname, "-")) {
out = stdout;
} else {
out = fopen(outname, "w");
/* preprocess and compile */
if (filetype == FILETYPE_PREPROCESSED_C) {
translation_unit_t *const unit = do_parsing(in, filename);
- if (in == preprocessed_in) {
- int pp_result = pclose(preprocessed_in);
- if (pp_result != EXIT_SUCCESS) {
- return pp_result;
- }
- }
/* prints the AST even if errors occurred */
if (mode == PrintAst) {
fprintf(stderr, "%u warning(s)\n", warning_count);
}
+ if (in == preprocessed_in) {
+ int pp_result = pclose(preprocessed_in);
+ if (pp_result != EXIT_SUCCESS) {
+ exit(EXIT_FAILURE);
+ }
+ }
+
if(mode == BenchmarkParser) {
return result;
} else if(mode == PrintFluffy) {
}
gen_firm_finish(asm_out, filename, /*c_mode=*/1,
- /*firm_const_exists=*/0);
+ have_const_functions);
if (asm_out != out) {
fclose(asm_out);
}
return pp_result;
}
}
+ if(asm_out != out) {
+ fclose(asm_out);
+ }
}
if (mode == Compile)