diff options
author | Stef Walter <stefw@gnome.org> | 2013-04-19 16:18:40 +0200 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2013-10-21 20:42:10 +0200 |
commit | 917da2d1aeffdc884a5fd5cf5b38a60ef088d0fb (patch) | |
tree | 115a99b4da986468aca556aec5af292626807948 /giscanner | |
parent | ebb80508d6959a0c94351e841c2cab6220602e62 (diff) | |
download | gobject-introspection-917da2d1aeffdc884a5fd5cf5b38a60ef088d0fb.tar.gz |
giscanner: Respect __GI_SCANNER__ when scanning for macros
When scanning for macros respect ifdefs of __GI_SCANNER__
in the various header files. Only #ifdef and #ifndef are supported.
If __GI_SCANNER__ appears in plain #if statements, a warning is
printed.
https://bugzilla.gnome.org/show_bug.cgi?id=698367
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/scannerlexer.l | 10 | ||||
-rw-r--r-- | giscanner/scannerparser.y | 157 | ||||
-rw-r--r-- | giscanner/sourcescanner.c | 23 | ||||
-rw-r--r-- | giscanner/sourcescanner.h | 4 |
4 files changed, 191 insertions, 3 deletions
diff --git a/giscanner/scannerlexer.l b/giscanner/scannerlexer.l index f30191db..7734938a 100644 --- a/giscanner/scannerlexer.l +++ b/giscanner/scannerlexer.l @@ -80,6 +80,14 @@ stringtext ([^\\\"])|(\\.) "#define "[a-zA-Z_][a-zA-Z_0-9]*"(" { yyless (yyleng - 1); return FUNCTION_MACRO; } "#define "[a-zA-Z_][a-zA-Z_0-9]* { return OBJECT_MACRO; } +"#ifdef"[\t ]+"__GI_SCANNER__"[\t ]?.*"\n" { return IFDEF_GI_SCANNER; } +"#ifndef"[\t ]+"__GI_SCANNER__"[\t ]?.*"\n" { return IFNDEF_GI_SCANNER; } +"#ifndef ".*"\n" { return IFNDEF_COND; } +"#ifdef ".*"\n" { return IFDEF_COND; } +"#if ".*"\n" { return IF_COND; } +"#elif ".*"\n" { return ELIF_COND; } +"#else".*"\n" { return ELSE_COND; } +"#endif".*"\n" { return ENDIF_COND; } "#pragma ".*"\n" { /* Ignore pragma. */ } "# "[0-9]+" ".*"\n" { process_linemarks(scanner); } @@ -269,7 +277,7 @@ parse_comment (GISourceScanner *scanner) comment->line = comment_lineno; comment->filename = g_file_get_parse_name (scanner->current_file); - scanner->comments = g_slist_prepend (scanner->comments, comment); + gi_source_scanner_take_comment (scanner, comment); } else { /* * Ignore all other comment blocks diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y index d440fd38..faf73410 100644 --- a/giscanner/scannerparser.y +++ b/giscanner/scannerparser.y @@ -128,6 +128,84 @@ out: return dest; } +enum { + IRRELEVANT = 1, + NOT_GI_SCANNER = 2, + FOR_GI_SCANNER = 3, +}; + +static void +update_skipping (GISourceScanner *scanner) +{ + GList *l; + for (l = scanner->conditionals.head; l != NULL; l = g_list_next (l)) + { + if (GPOINTER_TO_INT (l->data) == NOT_GI_SCANNER) + { + scanner->skipping = TRUE; + return; + } + } + + scanner->skipping = FALSE; +} + +static void +push_conditional (GISourceScanner *scanner, + gint type) +{ + g_assert (type != 0); + g_queue_push_head (&scanner->conditionals, GINT_TO_POINTER (type)); +} + +static gint +pop_conditional (GISourceScanner *scanner) +{ + gint type = GPOINTER_TO_INT (g_queue_pop_head (&scanner->conditionals)); + + if (type == 0) + { + gchar *filename = g_file_get_path (scanner->current_file); + fprintf (stderr, "%s:%d: mismatched %s", filename, lineno, yytext); + g_free (filename); + } + + return type; +} + +static void +warn_if_cond_has_gi_scanner (GISourceScanner *scanner, + const gchar *text) +{ + /* Some other conditional that is not __GI_SCANNER__ */ + if (strstr (text, "__GI_SCANNER__")) + { + gchar *filename = g_file_get_path (scanner->current_file); + fprintf (stderr, "%s:%d: the __GI_SCANNER__ constant should only be used with simple #ifdef or #endif: %s", + filename, lineno, text); + g_free (filename); + } +} + +static void +toggle_conditional (GISourceScanner *scanner) +{ + switch (pop_conditional (scanner)) + { + case FOR_GI_SCANNER: + push_conditional (scanner, NOT_GI_SCANNER); + break; + case NOT_GI_SCANNER: + push_conditional (scanner, FOR_GI_SCANNER); + break; + case 0: + break; + default: + push_conditional (scanner, IRRELEVANT); + break; + } +} + %} %error-verbose @@ -160,6 +238,8 @@ out: %token VOID VOLATILE WHILE %token FUNCTION_MACRO OBJECT_MACRO +%token IFDEF_GI_SCANNER IFNDEF_GI_SCANNER +%token IFDEF_COND IFNDEF_COND IF_COND ELIF_COND ELSE_COND ENDIF_COND %start translation_unit @@ -1403,9 +1483,55 @@ object_macro_define } ; +preproc_conditional + : IFDEF_GI_SCANNER + { + push_conditional (scanner, FOR_GI_SCANNER); + update_skipping (scanner); + } + | IFNDEF_GI_SCANNER + { + push_conditional (scanner, NOT_GI_SCANNER); + update_skipping (scanner); + } + | IFDEF_COND + { + warn_if_cond_has_gi_scanner (scanner, yytext); + push_conditional (scanner, IRRELEVANT); + } + | IFNDEF_COND + { + warn_if_cond_has_gi_scanner (scanner, yytext); + push_conditional (scanner, IRRELEVANT); + } + | IF_COND + { + warn_if_cond_has_gi_scanner (scanner, yytext); + push_conditional (scanner, IRRELEVANT); + } + | ELIF_COND + { + warn_if_cond_has_gi_scanner (scanner, yytext); + pop_conditional (scanner); + push_conditional (scanner, IRRELEVANT); + update_skipping (scanner); + } + | ELSE_COND + { + toggle_conditional (scanner); + update_skipping (scanner); + } + | ENDIF_COND + { + pop_conditional (scanner); + update_skipping (scanner); + } + ; + macro : function_macro_define | object_macro_define + | preproc_conditional | error ; @@ -1435,14 +1561,19 @@ eat_hspace (FILE * f) } static int -eat_line (FILE * f, int c) +pass_line (FILE * f, int c, + FILE *out) { while (c != EOF && c != '\n') { + if (out) + fputc (c, out); c = fgetc (f); } if (c == '\n') { + if (out) + fputc (c, out); c = fgetc (f); if (c == ' ' || c == '\t') { @@ -1453,6 +1584,12 @@ eat_line (FILE * f, int c) } static int +eat_line (FILE * f, int c) +{ + return pass_line (f, c, NULL); +} + +static int read_identifier (FILE * f, int c, char **identifier) { GString *id = g_string_new (""); @@ -1484,6 +1621,7 @@ gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames) GString *define_line; char *str; gboolean error_line = FALSE; + gboolean end_of_word; int c = eat_hspace (f); while (c != EOF) { @@ -1502,7 +1640,22 @@ gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames) c = eat_hspace (f); c = read_identifier (f, c, &str); - if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t')) + end_of_word = (c == ' ' || c == '\t' || c == '\n' || c == EOF); + if (end_of_word && + (g_str_equal (str, "if") || + g_str_equal (str, "endif") || + g_str_equal (str, "ifndef") || + g_str_equal (str, "ifdef") || + g_str_equal (str, "else") || + g_str_equal (str, "elif"))) + { + fprintf (fmacros, "#%s ", str); + g_free (str); + c = pass_line (f, c, fmacros); + line++; + continue; + } + else if (strcmp (str, "define") != 0 || !end_of_word) { g_free (str); /* ignore line */ diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c index 70eca8d0..30c2b036 100644 --- a/giscanner/sourcescanner.c +++ b/giscanner/sourcescanner.c @@ -221,6 +221,7 @@ gi_source_scanner_new (void) scanner->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); + g_queue_init (&scanner->conditionals); return scanner; } @@ -247,6 +248,7 @@ gi_source_scanner_free (GISourceScanner *scanner) g_hash_table_unref (scanner->files); + g_queue_clear (&scanner->conditionals); } gboolean @@ -268,6 +270,12 @@ void gi_source_scanner_add_symbol (GISourceScanner *scanner, GISourceSymbol *symbol) { + if (scanner->skipping) + { + g_debug ("skipping symbol due to __GI_SCANNER__ cond: %s", symbol->ident); + return; + } + g_assert (scanner->current_file); if (scanner->macro_scan || g_hash_table_contains (scanner->files, scanner->current_file)) @@ -295,6 +303,21 @@ gi_source_scanner_add_symbol (GISourceScanner *scanner, } } +void +gi_source_scanner_take_comment (GISourceScanner *scanner, + GISourceComment *comment) +{ + if (scanner->skipping) + { + g_debug ("skipping comment due to __GI_SCANNER__ cond"); + gi_source_comment_free (comment); + return; + } + + scanner->comments = g_slist_prepend (scanner->comments, + comment); +} + GSList * gi_source_scanner_get_symbols (GISourceScanner *scanner) { diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h index 2db9bdf6..254e43bf 100644 --- a/giscanner/sourcescanner.h +++ b/giscanner/sourcescanner.h @@ -115,6 +115,8 @@ struct _GISourceScanner GSList *comments; /* _GIComment */ GHashTable *typedef_table; GHashTable *struct_or_union_or_enum_table; + gboolean skipping; + GQueue conditionals; }; struct _GISourceSymbol @@ -168,6 +170,8 @@ GISourceSymbol * gi_source_symbol_copy (GISourceSymbol *symb /* Private */ void gi_source_scanner_add_symbol (GISourceScanner *scanner, GISourceSymbol *symbol); +void gi_source_scanner_take_comment (GISourceScanner *scanner, + GISourceComment *comment); gboolean gi_source_scanner_is_typedef (GISourceScanner *scanner, const char *name); void gi_source_symbol_merge_type (GISourceSymbol *symbol, |