}
+ if (declarator_alias_target[0]) {
+
+ if (!name) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute requires a named declaration");
+ } else if (!declarator_has_function || declarator_function_is_pointer) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute is only supported for functions");
+ } else if (tok.kind == TOK_LBRACE || is_type_start (tok.kind)) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "function '%s' cannot be both defined and declared with 'alias'", name);
+ } else {
+ record_dllalias (name, declarator_alias_target, declaration_dllexport || parsed_dllexport || declarator_dllexport);
+ }
+
+ declarator_alias_target[0] = '\0';
+
+ }
+
if (name && declarator_has_function && (tok.kind == TOK_LBRACE || is_type_start (tok.kind))) {
if (declaration_dllexport || parsed_dllexport || declarator_dllexport) {
}
+static int dll_export_name_is_present (const char *wanted) {
+
+ long i;
+
+ if (!wanted) {
+ return 0;
+ }
+
+ for (i = 0; i < vec_dllexports.length; i++) {
+
+ if (vec_dllexports.data[i] && strcmp (vec_dllexports.data[i], wanted) == 0) {
+ return 1;
+ }
+
+ }
+
+ return 0;
+
+}
+
void compile_translation_unit64 (void) {
if (state->ofp) {
emit_pending_extern_symbols ();
- if (vec_dllexports.length) {
+ if (vec_dllexports.length || vec_dllaliases.length) {
char *p, *tmp;
}
+ for (i = 0; i < vec_dllaliases.length; i++) {
+
+ struct dll_alias_entry *entry = vec_dllaliases.data[i];
+
+ const char *alias_name;
+ const char *target_name;
+
+ if (!entry || !entry->dllexport || !dll_export_name_is_present (entry->target)) {
+ continue;
+ }
+
+ alias_name = asm_global_symbol_name (entry->name);
+ target_name = asm_global_symbol_name (entry->target);
+
+ if (alias_name && target_name) {
+ fprintf (fp, " %s=%s\n", alias_name, target_name);
+ }
+
+ }
+
fclose (fp);
}
int declaration_noreturn = 0;
int declaration_dllimport = 0;
+ int declaration_dllexport = 0;
int decl_is_pointer;
int decl_pointer_depth;
declaration_is_inline = parsed_type_is_inline;
declaration_storage = parsed_storage_class;
declaration_dllimport = parsed_dllimport;
+ declaration_dllexport = parsed_dllexport;
declaration_noreturn = parsed_noreturn;
parse_declarator (&name);
declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
+ declaration_dllexport = declaration_dllexport || parsed_dllexport || declarator_dllexport;
declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn;
apply_typedef_array_to_declarator ();
}
+ if (declarator_alias_target[0]) {
+
+ if (!name) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute requires a named declaration");
+ } else if (!declarator_has_function || declarator_function_is_pointer) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "'alias' attribute is only supported for functions");
+ } else if (tok.kind == TOK_LBRACE || is_type_start (tok.kind)) {
+ report_line_at (get_filename (), name_line, REPORT_ERROR, name_start, name_caret, "function '%s' cannot be both defined and declared with 'alias'", name);
+ } else {
+ record_dllalias (name, declarator_alias_target, declaration_dllexport || parsed_dllexport || declarator_dllexport);
+ }
+
+ declarator_alias_target[0] = '\0';
+
+ }
+
if (name && declarator_has_function && (tok.kind == TOK_LBRACE || is_type_start (tok.kind))) {
- if (parsed_dllexport || declarator_dllexport) {
+ if (declaration_dllexport || parsed_dllexport || declarator_dllexport) {
vec_push (&vec_dllexports, xstrdup (name));
declarator_dllexport = 0;
+ declaration_dllexport = 0;
+
parsed_dllexport = 0;
}
}
+static int dll_export_name_is_present (const char *wanted) {
+
+ long i;
+
+ if (!wanted) {
+ return 0;
+ }
+
+ for (i = 0; i < vec_dllexports.length; i++) {
+
+ if (vec_dllexports.data[i] && strcmp (vec_dllexports.data[i], wanted) == 0) {
+ return 1;
+ }
+
+ }
+
+ return 0;
+
+}
+
void compile_translation_unit32 (void) {
if (state->ofp) {
emit_pending_extern_symbols ();
- if (vec_dllexports.length) {
+ if (vec_dllexports.length || vec_dllaliases.length) {
char *p, *tmp;
}
+ for (i = 0; i < vec_dllaliases.length; i++) {
+
+ struct dll_alias_entry *entry = vec_dllaliases.data[i];
+
+ const char *alias_name;
+ const char *target_name;
+
+ if (!entry || !entry->dllexport || !dll_export_name_is_present (entry->target)) {
+ continue;
+ }
+
+ alias_name = asm_global_symbol_name (entry->name);
+ target_name = asm_global_symbol_name (entry->target);
+
+ if (alias_name && target_name) {
+ fprintf (fp, " %s=%s\n", alias_name, target_name);
+ }
+
+ }
+
fclose (fp);
}
enum token_kind parsed_calling_convention = TOK_EOF;
struct vector vec_dllexports = { 0 };
+struct vector vec_dllaliases = { 0 };
int parsed_dllexport = 0;
int parsed_dllimport = 0;
int declarator_dllexport = 0;
int declarator_dllimport = 0;
+char declarator_alias_target[512] = { 0 };
+
enum token_kind declarator_calling_convention = TOK_EOF;
int global_initializer_accept_symbol_addresses = 0;
return tok.kind == TOK_PPSTR || tok.kind == TOK_LSTR;
}
+void record_dllalias (const char *name, const char *target, int dllexport) {
+
+ struct dll_alias_entry *entry;
+
+ if (!name || !*name || !target || !*target) {
+ return;
+ }
+
+ entry = xmalloc (sizeof (*entry));
+
+ entry->name = xstrdup (name);
+ entry->target = xstrdup (target);
+
+ entry->dllexport = dllexport;
+ vec_push (&vec_dllaliases, entry);
+
+}
+
int expect (enum token_kind k, const char *what) {
if (tok.kind == k) {
}
+static int parse_alias_attribute_argument (void) {
+
+ const char *s;
+ size_t len;
+
+ if (!_accept (TOK_LPAREN)) {
+
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected '(' after 'alias'");
+ return 0;
+
+ }
+
+ if (!is_string_token () || !tok.ident || tok.kind == TOK_LSTR) {
+
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected string literal in 'alias' attribute");
+
+ skip_attribute_arguments ();
+ return 0;
+
+ }
+
+ s = tok.ident;
+ len = strlen (s);
+
+ if (len < 2 || s[0] != '"' || s[len - 1] != '"') {
+
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "invalid string literal in 'alias' attribute");
+
+ get_token ();
+ expect (TOK_RPAREN, ")");
+
+ return 0;
+
+ }
+
+ if (len - 2 >= sizeof (declarator_alias_target)) {
+
+ report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "alias target name is too long");
+
+ get_token ();
+ expect (TOK_RPAREN, ")");
+
+ return 0;
+
+ }
+
+ memcpy (declarator_alias_target, s + 1, len - 2);
+ declarator_alias_target[len - 2] = '\0';
+
+ get_token ();
+
+ expect (TOK_RPAREN, ")");
+ return 1;
+
+}
+
static void apply_decl_attribute (const char *spelling, int is_gnu) {
if (attribute_name_is (spelling, "dllexport")) {
} else {
name = xstrdup (tok.ident);
-
- apply_decl_attribute (name, 1);
get_token ();
- if (tok.kind == TOK_LPAREN) {
- skip_attribute_arguments ();
+ if (attribute_name_is (name, "alias")) {
+ parse_alias_attribute_argument ();
+ } else {
+
+ apply_decl_attribute (name, 1);
+
+ if (tok.kind == TOK_LPAREN) {
+ skip_attribute_arguments ();
+ }
+
}
free (name);
const char *saved_captured_declarator_name_caret = captured_declarator_name_caret;
enum token_kind saved_declarator_calling_convention = declarator_calling_convention;
+ char saved_declarator_alias_target[sizeof declarator_alias_target];
int saved_declarator_dllexport = declarator_dllexport;
int saved_declarator_dllimport = declarator_dllimport;
int saved_declarator_noreturn = declarator_noreturn;
unsigned long saved_captured_declarator_name_line = captured_declarator_name_line;
+ memcpy (saved_declarator_alias_target, declarator_alias_target, sizeof (declarator_alias_target));
if (top_level) {
declarator_calling_convention = TOK_EOF;
capture_declarator_name_location = 1;
+ memcpy (declarator_alias_target, saved_declarator_alias_target, sizeof (declarator_alias_target));
+
declarator_dllexport = 0;
declarator_dllimport = 0;
declarator_noreturn = 0;
extern enum token_kind postfix_member_calling_convention;
extern enum token_kind parsed_calling_convention;
+struct dll_alias_entry {
+
+ char *target, *name;
+ int dllexport;
+
+};
+
+extern struct vector vec_dllaliases;
extern struct vector vec_dllexports;
extern int parsed_dllexport;
extern int declarator_pointer_depth;
extern int declarator_has_array;
+extern char declarator_alias_target[512];
extern int declarator_dllexport;
extern int declarator_dllimport;
extern int declarator_noreturn;
int parse_cast_type_name (int *out_size, int *out_is_unsigned, int *out_is_pointer);
int resolve_enum_constant (const char *name, int64_s *out);
+void record_dllalias (const char *name, const char *target, int dllexport);
#define DATA_CHAR (1 | (1 << 5))
#define DATA_SHORT (2 | (1 << 6))