From 1def4610511fb455742f38b794e9b0e3d34db5fe Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Fri, 28 Dec 2007 01:03:35 +0000 Subject: [PATCH] Parse gtk-doc comments. 2007-12-27 Johan Dahlin * src/scannerlexer.l: Parse gtk-doc comments. * src/gidlwriter.c: (function_generate): Reorganize, avoid duplication and add support for writing deprecated functions. * src/scannerparser.y: * src/scanner.h: Add new structure CDirective and functions to create/free them. * src/scanner.c: (g_igenerator_process_function_symbol), (g_igenerator_process_unregistered_struct_typedef), (g_igenerator_process_struct_typedef), (g_igenerator_process_union_typedef), (g_igenerator_process_enum_typedef), (g_igenerator_process_function_typedef), (g_igenerator_add_symbol), (g_igenerator_start_preprocessor): Parse @deprecated directive for functions. Remove some more C99isms. Send in -C to cpp to avoid stripping comments. * tests/parser/foo-object.h: * tests/parser/Foo-expected.gidl: Add deprecated directive svn path=/trunk/; revision=92 --- ChangeLog | 28 +++++++++++ src/gidlwriter.c | 51 ++++++++++---------- src/scanner.c | 60 +++++++++++++++++++----- src/scanner.h | 39 +++++++++------ src/scannerlexer.l | 86 ++++++++++++++++++++++++++++------ src/scannerparser.y | 23 +++++++++ tests/parser/Foo-expected.gidl | 2 +- tests/parser/foo-object.h | 3 ++ 8 files changed, 224 insertions(+), 68 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f0836b6..694910b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2007-12-27 Johan Dahlin + + * src/scannerlexer.l: + Parse gtk-doc comments. + + * src/gidlwriter.c: (function_generate): + Reorganize, avoid duplication and add support for + writing deprecated functions. + + * src/scannerparser.y: + * src/scanner.h: + Add new structure CDirective and functions to create/free them. + + * src/scanner.c: (g_igenerator_process_function_symbol), + (g_igenerator_process_unregistered_struct_typedef), + (g_igenerator_process_struct_typedef), + (g_igenerator_process_union_typedef), + (g_igenerator_process_enum_typedef), + (g_igenerator_process_function_typedef), (g_igenerator_add_symbol), + (g_igenerator_start_preprocessor): + Parse @deprecated directive for functions. + Remove some more C99isms. + Send in -C to cpp to avoid stripping comments. + + * tests/parser/foo-object.h: + * tests/parser/Foo-expected.gidl: + Add deprecated directive + 2007-12-27 Johan Dahlin * src/scannerlexer.l (intsuffix): Add emacs mode line and diff --git a/src/gidlwriter.c b/src/gidlwriter.c index ce79c5cf..d46762bc 100644 --- a/src/gidlwriter.c +++ b/src/gidlwriter.c @@ -120,43 +120,42 @@ property_generate (GIdlWriter * writer, GIdlNodeProperty * node) static void function_generate (GIdlWriter * writer, GIdlNodeFunction * node) { - char *markup; const char *tag_name; + GString *markup_s; + gchar *markup; + if (node->node.type == G_IDL_NODE_CALLBACK) - { - tag_name = "callback"; - markup = - g_markup_printf_escaped ("\n", node->node.name); - } + tag_name = "callback"; else if (node->is_constructor) - { - tag_name = "constructor"; - markup = - g_markup_printf_escaped ("\n", - node->node.name, node->symbol); - } + tag_name = "constructor"; else if (node->is_method) - { - tag_name = "method"; - markup = - g_markup_printf_escaped ("\n", - node->node.name, node->symbol); - } + tag_name = "method"; else - { - tag_name = "function"; - markup = - g_markup_printf_escaped ("\n", - node->node.name, node->symbol); - } + tag_name = "function"; + + markup_s = g_string_new ("<"); + g_string_append_printf (markup_s, + "%s name=\"%s\"", + tag_name, node->node.name); + + if (node->node.type != G_IDL_NODE_CALLBACK) + g_string_append_printf (markup_s, + g_markup_printf_escaped (" symbol=\"%s\"", node->symbol)); + + if (node->deprecated) + g_string_append_printf (markup_s, " deprecated=\"1\""); + + g_string_append (markup_s, ">\n"); + + g_writer_write_indent (writer, markup_s->str); + g_string_free (markup_s, TRUE); - g_writer_write_indent (writer, markup); - g_free (markup); markup = g_markup_printf_escaped ("\n", node->result->type->unparsed); g_writer_write (writer, markup); g_free (markup); + if (node->parameters != NULL) { GList *l; diff --git a/src/scanner.c b/src/scanner.c index 22156fbe..32f5925e 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -627,6 +627,7 @@ g_igenerator_process_function_symbol (GIGenerator * igenerator, CSymbol * sym) char *last_underscore = strrchr (sym->ident, '_'); GList *param_l; int i; + GSList *l; while (last_underscore != NULL) { @@ -733,6 +734,17 @@ g_igenerator_process_function_symbol (GIGenerator * igenerator, CSymbol * sym) param->type = get_type_from_ctype (param_sym->base_type); gifunc->parameters = g_list_append (gifunc->parameters, param); } + + for (l = sym->directives; l; l = l->next) + { + CDirective *directive = (CDirective*)l->data; + + if (!strcmp (directive->name, "deprecated")) + gifunc->deprecated = strcmp (directive->value, "1") == 0; + else + g_printerr ("Unknown function directive: %s\n", + directive->name); + } } static void @@ -742,22 +754,25 @@ g_igenerator_process_unregistered_struct_typedef (GIGenerator * igenerator, { GIdlNodeStruct *ginode = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT); + GList *member_l; + char *lower_case_prefix; + ginode->node.name = sym->ident; igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp); - char *lower_case_prefix = g_ascii_strdown (sym->ident, -1); + lower_case_prefix = g_ascii_strdown (sym->ident, -1); g_hash_table_insert (igenerator->type_map, sym->ident, ginode); g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode); - GList *member_l; for (member_l = struct_type->child_list; member_l != NULL; member_l = member_l->next) { CSymbol *member = member_l->data; GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD); + ginode->members = g_list_append (ginode->members, gifield); gifield->node.name = member->ident; gifield->type = get_type_from_ctype (member->base_type); @@ -769,10 +784,13 @@ g_igenerator_process_struct_typedef (GIGenerator * igenerator, CSymbol * sym) { CType *struct_type = sym->base_type; gboolean opaque_type = FALSE; + GIdlNode *gitype; + if (struct_type->child_list == NULL) { + CSymbol *struct_symbol; g_assert (struct_type->name != NULL); - CSymbol *struct_symbol = + struct_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, struct_type->name); if (struct_symbol != NULL) @@ -780,11 +798,13 @@ g_igenerator_process_struct_typedef (GIGenerator * igenerator, CSymbol * sym) struct_type = struct_symbol->base_type; } } + if (struct_type->child_list == NULL) { opaque_type = TRUE; } - GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident); + + gitype = g_hash_table_lookup (igenerator->type_map, sym->ident); if (gitype != NULL) { /* struct of a GTypeInstance */ @@ -963,6 +983,8 @@ g_igenerator_process_union_typedef (GIGenerator * igenerator, CSymbol * sym) { CType *union_type = sym->base_type; gboolean opaque_type = FALSE; + GIdlNode *gitype; + if (union_type->child_list == NULL) { g_assert (union_type->name != NULL); @@ -978,7 +1000,8 @@ g_igenerator_process_union_typedef (GIGenerator * igenerator, CSymbol * sym) { opaque_type = TRUE; } - GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident); + + gitype = g_hash_table_lookup (igenerator->type_map, sym->ident); if (gitype != NULL) { g_assert (gitype->type == G_IDL_NODE_BOXED); @@ -1028,11 +1051,16 @@ g_igenerator_process_union_typedef (GIGenerator * igenerator, CSymbol * sym) static void g_igenerator_process_enum_typedef (GIGenerator * igenerator, CSymbol * sym) { - CType *enum_type = sym->base_type; + CType *enum_type; + GList *member_l; + GIdlNodeEnum *ginode; + CSymbol *enum_symbol; + + enum_type = sym->base_type; if (enum_type->child_list == NULL) { g_assert (enum_type->name != NULL); - CSymbol *enum_symbol = + enum_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, enum_type->name); if (enum_symbol != NULL) @@ -1045,8 +1073,8 @@ g_igenerator_process_enum_typedef (GIGenerator * igenerator, CSymbol * sym) /* opaque type */ return; } - GIdlNodeEnum *ginode = - g_hash_table_lookup (igenerator->type_map, sym->ident); + + ginode = g_hash_table_lookup (igenerator->type_map, sym->ident); if (ginode != NULL) { return; @@ -1058,7 +1086,6 @@ g_igenerator_process_enum_typedef (GIGenerator * igenerator, CSymbol * sym) g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp); - GList *member_l; for (member_l = enum_type->child_list; member_l != NULL; member_l = member_l->next) { @@ -1075,6 +1102,9 @@ static void g_igenerator_process_function_typedef (GIGenerator * igenerator, CSymbol * sym) { + GList *param_l; + int i; + /* handle callback types */ GIdlNodeFunction *gifunc = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_CALLBACK); @@ -1088,8 +1118,7 @@ g_igenerator_process_function_typedef (GIGenerator * igenerator, gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM); gifunc->result->type = get_type_from_ctype (sym->base_type->base_type->base_type); - GList *param_l; - int i; + for (param_l = sym->base_type->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) { @@ -1216,6 +1245,10 @@ g_igenerator_add_symbol (GIGenerator * igenerator, CSymbol * symbol) break; } } + + symbol->directives = g_slist_reverse (igenerator->directives); + igenerator->directives = NULL; + if (found_filename || igenerator->macro_scan) { igenerator->symbol_list = @@ -1522,8 +1555,9 @@ g_igenerator_start_preprocessor (GIGenerator *igenerator, int tmp; char *tmpname; - cpp_argv = g_new0 (char *, g_list_length (cpp_options) + 3); + cpp_argv = g_new0 (char *, g_list_length (cpp_options) + 4); cpp_argv[cpp_argc++] = "cpp"; + cpp_argv[cpp_argc++] = "-C"; /* Disable GCC extensions as we cannot parse them yet */ cpp_argv[cpp_argc++] = "-U__GNUC__"; diff --git a/src/scanner.h b/src/scanner.h index e6ce44c0..b2140759 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -30,6 +30,7 @@ G_BEGIN_DECLS typedef struct _GIGenerator GIGenerator; typedef struct _CSymbol CSymbol; typedef struct _CType CType; +typedef struct _CDirective CDirective; struct _GIGenerator { @@ -47,14 +48,16 @@ struct _GIGenerator GHashTable *typedef_table; GHashTable *struct_or_union_or_enum_table; - gboolean macro_scan; - GIdlModule *module; GList *get_type_symbols; GHashTable *type_map; GHashTable *type_by_lower_case_prefix; GHashTable *symbols; /* typename -> module.name */ + + /* scanner variables */ + gboolean macro_scan; + GSList *directives; /* list of CDirective for the current symbol */ }; typedef enum @@ -78,6 +81,7 @@ struct _CSymbol gboolean const_int_set; int const_int; char *const_string; + GSList *directives; /* list of CDirective */ }; typedef enum @@ -139,18 +143,25 @@ struct _CType GList *child_list; }; -CSymbol *csymbol_new (CSymbolType type); -gboolean csymbol_get_const_boolean (CSymbol *symbol); -void csymbol_free (CSymbol * symbol); - -gboolean g_igenerator_parse_file (GIGenerator *igenerator, - FILE *file); -void g_igenerator_set_verbose (GIGenerator *igenerator, - gboolean verbose); -void g_igenerator_add_symbol (GIGenerator *igenerator, - CSymbol *symbol); -gboolean g_igenerator_is_typedef (GIGenerator *igenerator, - const char *name); +struct _CDirective { + char *name; + char *value; +}; +CSymbol * csymbol_new (CSymbolType type); +gboolean csymbol_get_const_boolean (CSymbol *symbol); +void csymbol_free (CSymbol *symbol); +CDirective * cdirective_new (const gchar *name, + const gchar *value); +void cdirective_free (CDirective *directive); + +gboolean g_igenerator_parse_file (GIGenerator *igenerator, + FILE *file); +void g_igenerator_set_verbose (GIGenerator *igenerator, + gboolean verbose); +void g_igenerator_add_symbol (GIGenerator *igenerator, + CSymbol *symbol); +gboolean g_igenerator_is_typedef (GIGenerator *igenerator, + const char *name); G_END_DECLS #endif diff --git a/src/scannerlexer.l b/src/scannerlexer.l index 953ebf2a..35d74f64 100644 --- a/src/scannerlexer.l +++ b/src/scannerlexer.l @@ -39,7 +39,7 @@ int lineno; extern int yylex (GIGenerator *igenerator); #define YY_DECL int yylex (GIGenerator *igenerator) static int yywrap (void); -static void skip_comment (void); +static void parse_comment (GIGenerator *igenerator); static void process_directive (GIGenerator *igenerator); static int check_identifier (GIGenerator *igenerator, const char *); %} @@ -48,7 +48,7 @@ intsuffix ([uU][lL]?)|([lL][uU]?) fracconst ([0-9]*\.[0-9]+)|([0-9]+\.) exppart [eE][-+]?[0-9]+ floatsuffix [fFlL] -chartext ([^\'])|(\\.) +chartext ([^\'])|(\\.) stringtext ([^\"])|(\\.) %% @@ -56,7 +56,7 @@ stringtext ([^\"])|(\\.) "\n" { ++lineno; } /* " */ [\t\f\v\r ]+ { /* Ignore whitespace. */ } -"/*" { skip_comment(); } +"/*" { parse_comment(igenerator); } "//".* { } "#define "[a-zA-Z_][a-zA-Z_0-9]*"(" { yyless (yyleng - 1); return FUNCTION_MACRO; } @@ -173,22 +173,80 @@ stringtext ([^\"])|(\\.) static int yywrap (void) { - return 1; + return 1; } -static void skip_comment (void) +static void parse_gtkdoc (GIGenerator *igenerator, int c2) { - int c1, c2; - - c1 = input(); - c2 = input(); + int c1; + gboolean isline = FALSE; + gchar line[256]; + int i; + gchar **parts; + CDirective *directive; + char *name, *value; + + i = 0; + do { + c1 = c2; + if (c1 == '\n') + { + isline = TRUE; + break; + } + if (i >= 256) + break; + line[i++] = c1; + c2 = input(); + + } while (c2 != EOF && !(c1 == '*' && c2 == '/')); + + if (!isline) + return; + + line[i] = '\0'; + + parts = g_strsplit (line, ": ", 2); + + if (g_strv_length (parts) == 2) + { + name = parts[0]; + value = parts[1]; + } + else /* parts == 1 */ + { + name = parts[0]; + value = "1"; + } + + directive = cdirective_new (name, value); + igenerator->directives = g_slist_prepend (igenerator->directives, + directive); + + g_strfreev (parts); +} - while (c2 != EOF && !(c1 == '*' && c2 == '/')) { - if (c1 == '\n') - ++lineno; - c1 = c2; - c2 = input(); +static void parse_comment (GIGenerator *igenerator) +{ + int c1, c2; + + c1 = input(); + c2 = input(); + + while (c2 != EOF && !(c1 == '*' && c2 == '/')) + { + if (c1 == '\n') + ++lineno; + c1 = c2; + c2 = input(); + + if (c1 == ' ' && c2 == '@') + { + c1 = c2; + c2 = input(); + parse_gtkdoc (igenerator, c2); } + } } static int check_identifier (GIGenerator *igenerator, const char *s) diff --git a/src/scannerparser.y b/src/scannerparser.y index 476b1125..fae5067d 100644 --- a/src/scannerparser.y +++ b/src/scannerparser.y @@ -67,6 +67,8 @@ csymbol_free (CSymbol * symbol) ctype_free (symbol->base_type); g_free (symbol->const_string); g_free (symbol); + g_slist_foreach (symbol->directives, (GFunc)cdirective_free, NULL); + g_slist_free (symbol->directives); } gboolean @@ -161,6 +163,27 @@ csymbol_merge_type (CSymbol *symbol, CType *type) } *foundation_type = ctype_copy (type); } + +CDirective * +cdirective_new (const gchar *name, + const gchar *value) +{ + CDirective *directive; + + directive = g_slice_new (CDirective); + directive->name = g_strdup (name); + directive->value = g_strdup (value); + return directive; +} + +void +cdirective_free (CDirective *directive) +{ + g_free (directive->name); + g_free (directive->value); + g_slice_free (CDirective, directive); +} + %} %error-verbose diff --git a/tests/parser/Foo-expected.gidl b/tests/parser/Foo-expected.gidl index 1100dcab..a95ce47c 100644 --- a/tests/parser/Foo-expected.gidl +++ b/tests/parser/Foo-expected.gidl @@ -1,7 +1,7 @@ - + diff --git a/tests/parser/foo-object.h b/tests/parser/foo-object.h index 2967a99e..808a5e3b 100644 --- a/tests/parser/foo-object.h +++ b/tests/parser/foo-object.h @@ -26,6 +26,9 @@ struct _FooObjectClass GObjectClass parent_class; }; +/* + * @deprecated + */ gint foo_init (void); GType foo_object_get_type (void) G_GNUC_CONST; -- 2.34.1