#include <libfirm/firm.h>
#include <libfirm/be.h>
-#include "lexer.h"
+#include "preprocessor.h"
#include "token_t.h"
#include "types.h"
#include "type_hash.h"
#define ASSEMBLER "gcc -c -xassembler"
#endif
-unsigned int c_mode = _C89 | _ANSI | _C99 | _GNUC;
+unsigned int c_mode = _C89 | _C99 | _GNUC;
bool byte_order_big_endian = false;
bool strict_mode = false;
bool enable_main_collect2_hack = false;
typedef enum lang_standard_t {
STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
- STANDARD_ANSI, /* c89 (for C) or c++98 (for C++) */
+ STANDARD_ANSI, /* ISO C90 (for C) or ISO C++ 1998 (for C++) */
STANDARD_C89, /* ISO C90 (sic) */
- STANDARD_C90, /* ISO C90 as modified in amendment 1 */
+ STANDARD_C89AMD1, /* ISO C90 as modified in amendment 1 */
STANDARD_C99, /* ISO C99 */
STANDARD_GNU89, /* ISO C90 plus GNU extensions (including some C99) */
STANDARD_GNU99, /* ISO C99 plus GNU extensions */
STANDARD_GNUXX98 /* ISO C++ 1998 plus amendments and GNU extensions */
} lang_standard_t;
-static lang_standard_t standard;
-
typedef struct file_list_entry_t file_list_entry_t;
typedef enum filetype_t {
{
start_parsing();
- input_t *input = input_from_stream(in, input_encoding);
- lexer_switch_input(input, input_name);
+ switch_input(in, input_name);
parse();
translation_unit_t *unit = finish_parsing();
- input_free(input);
+ close_input();
return unit;
}
static void lextest(FILE *in, const char *fname)
{
- input_t *input = input_from_stream(in, input_encoding);
- lexer_switch_input(input, fname);
-
+ switch_input(in, fname);
do {
- lexer_next_preprocessing_token();
- print_token(stdout, &lexer_token);
+ next_preprocessing_token();
+ print_token(stdout, &pp_token);
putchar('\n');
- } while (lexer_token.kind != T_EOF);
- input_free(input);
+ } while (pp_token.kind != T_EOF);
+ close_input();
}
static void add_flag(struct obstack *obst, const char *format, ...)
return get_atomic_kind_name(type->atomic.akind);
}
-static FILE *preprocess(const char *fname, filetype_t filetype)
+static char const* str_lang_standard(lang_standard_t const standard)
+{
+ switch (standard) {
+ case STANDARD_C89: return "c89";
+ case STANDARD_C89AMD1: return "iso9899:199409";
+ case STANDARD_C99: return "c99";
+ case STANDARD_GNU89: return "gnu89";
+ case STANDARD_GNU99: return "gnu99";
+ case STANDARD_CXX98: return "c++98";
+ case STANDARD_GNUXX98: return "gnu++98";
+ case STANDARD_ANSI: break;
+ case STANDARD_DEFAULT: break;
+ }
+ panic("invalid standard");
+}
+
+static FILE *preprocess(const char *fname, filetype_t filetype,
+ lang_standard_t standard)
{
static const char *common_flags = NULL;
obstack_printf(&cppflags_obst, PREPROCESSOR);
}
+ char const *lang;
switch (filetype) {
- case FILETYPE_C:
- add_flag(&cppflags_obst, "-std=c99");
- break;
- case FILETYPE_CXX:
- add_flag(&cppflags_obst, "-std=c++98");
- break;
- case FILETYPE_ASSEMBLER:
- add_flag(&cppflags_obst, "-x");
- add_flag(&cppflags_obst, "assembler-with-cpp");
- break;
- default:
- break;
+ case FILETYPE_C: lang = "c"; break;
+ case FILETYPE_CXX: lang = "c++"; break;
+ case FILETYPE_ASSEMBLER: lang = "assembler-with-cpp"; break;
+ default: lang = NULL; break;
}
+ if (lang)
+ add_flag(&cppflags_obst, "-x%s", lang);
+
+ add_flag(&cppflags_obst, "-std=%s", str_lang_standard(standard));
+
obstack_printf(&cppflags_obst, "%s", common_flags);
/* handle dependency generation */
put_help("-std=STANDARD", "Specify language standard:");
put_choice("c99", "ISO C99 standard");
put_choice("c89", "ISO C89 standard");
+ put_choice("c90", "Same as -std=c89");
put_choice("c9x", "Deprecated");
put_choice("c++", "ISO C++ 98");
put_choice("c++98", "ISO C++ 98");
put_choice("iso9899:1999", "ISO C99");
put_choice("iso9899:199x", "Deprecated");
put_help("-pedantic", "Ignored (gcc compatibility)");
- put_help("-ansi", "Ignored (gcc compatibility)");
+ put_help("-ansi", "-std=c90 (for C) or -std=c++98 (for C++)");
put_help("--strict", "Enable strict conformance checking");
}
setup_target_machine();
/* parse rest of options */
- standard = STANDARD_DEFAULT;
+ lang_standard_t standard = STANDARD_DEFAULT;
unsigned features_on = 0;
unsigned features_off = 0;
filetype_t forced_filetype = FILETYPE_AUTODETECT;
if (option[0] == 'o') {
GET_ARG_AFTER(outname, "-o");
} else if (option[0] == 'g') {
- set_be_option("debuginfo=stabs");
- set_be_option("omitfp=no");
+ /* TODO: parse -gX with 0<=x<=3... */
+ set_be_option("debug=frameinfo");
set_be_option("ia32-nooptcc=yes");
} else if (SINGLE_OPTION('c')) {
mode = CompileAssemble;
set_be_option("gprof");
add_flag(&ldflags_obst, "-pg");
} else if (streq(option, "ansi")) {
- add_flag(&cppflags_obst, "-ansi");
+ standard = STANDARD_ANSI;
} else if (streq(option, "pedantic")) {
fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
} else if (strstart(option, "std=")) {
streq(o, "c++") ? STANDARD_CXX98 :
streq(o, "c++98") ? STANDARD_CXX98 :
streq(o, "c89") ? STANDARD_C89 :
+ streq(o, "c90") ? STANDARD_C89 :
streq(o, "c99") ? STANDARD_C99 :
streq(o, "c9x") ? STANDARD_C99 : // deprecated
streq(o, "gnu++98") ? STANDARD_GNUXX98 :
streq(o, "gnu99") ? STANDARD_GNU99 :
streq(o, "gnu9x") ? STANDARD_GNU99 : // deprecated
streq(o, "iso9899:1990") ? STANDARD_C89 :
- streq(o, "iso9899:199409") ? STANDARD_C90 :
+ streq(o, "iso9899:199409") ? STANDARD_C89AMD1 :
streq(o, "iso9899:1999") ? STANDARD_C99 :
streq(o, "iso9899:199x") ? STANDARD_C99 : // deprecated
(fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg), standard);
init_types_and_adjust();
init_typehash();
init_basic_types();
- if (wchar_atomic_kind == ATOMIC_TYPE_INT)
- init_wchar_types(type_int);
- else if (wchar_atomic_kind == ATOMIC_TYPE_USHORT)
- init_wchar_types(type_short);
- else
- panic("unexpected wchar type");
- init_lexer();
+ if (c_mode & _CXX) {
+ init_wchar_types(ATOMIC_TYPE_WCHAR_T);
+ } else {
+ init_wchar_types(wchar_atomic_kind);
+ }
+ init_preprocessor();
init_ast();
init_parser();
init_ast2firm();
file_list_entry_t *file;
bool already_constructed_firm = false;
for (file = files; file != NULL; file = file->next) {
- char asm_tempfile[1024];
- const char *filename = file->name;
- filetype_t filetype = file->type;
+ char asm_tempfile[1024];
+ const char *filename = file->name;
+ filetype_t filetype = file->type;
+ lang_standard_t file_standard = standard;
if (filetype == FILETYPE_OBJECT)
continue;
+ switch (file_standard) {
+ case STANDARD_ANSI:
+ switch (filetype) {
+ case FILETYPE_C:
+ case FILETYPE_PREPROCESSED_C: file_standard = STANDARD_C89; break;
+ case FILETYPE_CXX:
+ case FILETYPE_PREPROCESSED_CXX: file_standard = STANDARD_CXX98; break;
+ default: break;
+ }
+ break;
+
+ case STANDARD_DEFAULT:
+ switch (filetype) {
+ case FILETYPE_C:
+ case FILETYPE_PREPROCESSED_C: file_standard = STANDARD_GNU99; break;
+ case FILETYPE_CXX:
+ case FILETYPE_PREPROCESSED_CXX: file_standard = STANDARD_GNUXX98; break;
+ default: break;
+ }
+ break;
+
+ default: break;
+ }
FILE *in = NULL;
if (mode == LexTest) {
if (in != NULL)
panic("internal compiler error: in for preprocessor != NULL");
- preprocessed_in = preprocess(filename, filetype);
+ preprocessed_in = preprocess(filename, filetype,
+ file_standard);
if (mode == PreprocessOnly) {
copy_file(out, preprocessed_in);
int pp_result = pclose(preprocessed_in);
/* preprocess and compile */
if (filetype == FILETYPE_PREPROCESSED_C) {
- char const* invalid_mode;
- switch (standard) {
- case STANDARD_ANSI:
- case STANDARD_C89: c_mode = _C89; break;
- /* TODO determine difference between these two */
- case STANDARD_C90: c_mode = _C89; break;
- case STANDARD_C99: c_mode = _C89 | _C99; break;
- case STANDARD_GNU89: c_mode = _C89 | _GNUC; break;
-
-default_c_warn:
- fprintf(stderr,
- "warning: command line option \"-std=%s\" is not valid for C\n",
- invalid_mode);
- /* FALLTHROUGH */
- case STANDARD_DEFAULT:
- case STANDARD_GNU99: c_mode = _C89 | _C99 | _GNUC; break;
-
- case STANDARD_CXX98: invalid_mode = "c++98"; goto default_c_warn;
- case STANDARD_GNUXX98: invalid_mode = "gnu98"; goto default_c_warn;
+ switch (file_standard) {
+ case STANDARD_C89: c_mode = _C89; break;
+ /* TODO determine difference between these two */
+ case STANDARD_C89AMD1: c_mode = _C89; break;
+ case STANDARD_C99: c_mode = _C89 | _C99; break;
+ case STANDARD_GNU89: c_mode = _C89 | _GNUC; break;
+
+ case STANDARD_ANSI:
+ case STANDARD_CXX98:
+ case STANDARD_GNUXX98:
+ case STANDARD_DEFAULT:
+ fprintf(stderr, "warning: command line option \"-std=%s\" is not valid for C\n", str_lang_standard(file_standard));
+ /* FALLTHROUGH */
+ case STANDARD_GNU99: c_mode = _C89 | _C99 | _GNUC; break;
}
goto do_parsing;
} else if (filetype == FILETYPE_PREPROCESSED_CXX) {
- char const* invalid_mode;
- switch (standard) {
- case STANDARD_C89: invalid_mode = "c89"; goto default_cxx_warn;
- case STANDARD_C90: invalid_mode = "c90"; goto default_cxx_warn;
- case STANDARD_C99: invalid_mode = "c99"; goto default_cxx_warn;
- case STANDARD_GNU89: invalid_mode = "gnu89"; goto default_cxx_warn;
- case STANDARD_GNU99: invalid_mode = "gnu99"; goto default_cxx_warn;
-
- case STANDARD_ANSI:
- case STANDARD_CXX98: c_mode = _CXX; break;
-
-default_cxx_warn:
- fprintf(stderr,
- "warning: command line option \"-std=%s\" is not valid for C++\n",
- invalid_mode);
- case STANDARD_DEFAULT:
- case STANDARD_GNUXX98: c_mode = _CXX | _GNUC; break;
+ switch (file_standard) {
+ case STANDARD_CXX98: c_mode = _CXX; break;
+
+ case STANDARD_ANSI:
+ case STANDARD_C89:
+ case STANDARD_C89AMD1:
+ case STANDARD_C99:
+ case STANDARD_GNU89:
+ case STANDARD_GNU99:
+ case STANDARD_DEFAULT:
+ fprintf(stderr, "warning: command line option \"-std=%s\" is not valid for C++\n", str_lang_standard(file_standard));
+ /* FALLTHROUGH */
+ case STANDARD_GNUXX98: c_mode = _CXX | _GNUC; break;
}
do_parsing:
if (already_constructed_firm) {
panic("compiling multiple files/translation units not possible");
}
+ init_implicit_optimizations();
translation_unit_to_firm(unit);
already_constructed_firm = true;
timer_pop(t_construct);
exit_ast2firm();
exit_parser();
exit_ast();
- exit_lexer();
+ exit_preprocessor();
exit_typehash();
exit_types();
exit_tokens();