[SYMBOL_LINES] Support for line numbers on Symbols
[gnome.gobject-introspection] / giscanner / sourcescanner.c
1 /* GObject introspection: public scanner api
2  *
3  * Copyright (C) 2007 Jürg Billeter
4  * Copyright (C) 2008 Johan Dahlin
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22
23 #include "sourcescanner.h"
24 #include <string.h>
25
26 GISourceSymbol *
27 gi_source_symbol_new (GISourceSymbolType type, int line)
28 {
29   GISourceSymbol *s = g_slice_new0 (GISourceSymbol);
30   s->ref_count = 1;
31   s->type = type;
32   s->line = line;
33   return s;
34 }
35
36 void
37 ctype_free (GISourceType * type)
38 {
39   g_free (type->name);
40   g_list_foreach (type->child_list, (GFunc)gi_source_symbol_unref, NULL);
41   g_list_free (type->child_list);
42   g_slice_free (GISourceType, type);
43 }
44
45 GISourceSymbol *
46 gi_source_symbol_ref (GISourceSymbol * symbol)
47 {
48   symbol->ref_count++;
49   return symbol;
50 }
51
52 void
53 gi_source_symbol_unref (GISourceSymbol * symbol)
54 {
55   if (!symbol)
56     return;
57   symbol->ref_count--;
58   if (symbol->ref_count == 0)
59     {
60       g_free (symbol->ident);
61       if (symbol->base_type)
62         ctype_free (symbol->base_type);
63       g_free (symbol->const_string);
64       g_free (symbol->source_filename);
65       g_slice_free (GISourceSymbol, symbol);
66     }
67 }
68  
69 gboolean
70 gi_source_symbol_get_const_boolean (GISourceSymbol * symbol)
71 {
72   return (symbol->const_int_set && symbol->const_int) || symbol->const_string;
73 }
74
75 /* use specified type as base type of symbol */
76 void
77 gi_source_symbol_merge_type (GISourceSymbol *symbol,
78                              GISourceType   *type)
79 {
80   GISourceType **foundation_type = &(symbol->base_type);
81
82   while (*foundation_type != NULL)
83     {
84       foundation_type = &((*foundation_type)->base_type);
85     }
86   *foundation_type = type;
87 }
88
89
90 GISourceType *
91 gi_source_type_new (GISourceTypeType type)
92 {
93   GISourceType *t = g_slice_new0 (GISourceType);
94   t->type = type;
95   return t;
96 }
97
98 GISourceType *
99 gi_source_type_copy (GISourceType * type)
100 {
101   GList *l;
102   GISourceType *result = g_slice_new0 (GISourceType);
103   result->type = type->type;
104   result->storage_class_specifier = type->storage_class_specifier;
105   result->type_qualifier = type->type_qualifier;
106   result->function_specifier = type->function_specifier;
107   if (type->name)
108     result->name = g_strdup (type->name);
109   if (type->base_type)
110     result->base_type = gi_source_type_copy (type->base_type);
111   for (l = type->child_list; l; l = l->next)
112     result->child_list = g_list_append (result->child_list, gi_source_symbol_ref (l->data));
113   result->is_bitfield = type->is_bitfield;
114   return result;
115 }
116
117 GISourceType *
118 gi_source_basic_type_new (const char *name)
119 {
120   GISourceType *basic_type = gi_source_type_new (CTYPE_BASIC_TYPE);
121   basic_type->name = g_strdup (name);
122   return basic_type;
123 }
124
125 GISourceType *
126 gi_source_typedef_new (const char *name)
127 {
128   GISourceType *typedef_ = gi_source_type_new (CTYPE_TYPEDEF);
129   typedef_->name = g_strdup (name);
130   return typedef_;
131 }
132
133 GISourceType *
134 gi_source_struct_new (const char *name)
135 {
136   GISourceType *struct_ = gi_source_type_new (CTYPE_STRUCT);
137   struct_->name = g_strdup (name);
138   return struct_;
139 }
140
141 GISourceType *
142 gi_source_union_new (const char *name)
143 {
144   GISourceType *union_ = gi_source_type_new (CTYPE_UNION);
145   union_->name = g_strdup (name);
146   return union_;
147 }
148
149 GISourceType *
150 gi_source_enum_new (const char *name)
151 {
152   GISourceType *enum_ = gi_source_type_new (CTYPE_ENUM);
153   enum_->name = g_strdup (name);
154   return enum_;
155 }
156
157 GISourceType *
158 gi_source_pointer_new (GISourceType * base_type)
159 {
160   GISourceType *pointer = gi_source_type_new (CTYPE_POINTER);
161   if (base_type != NULL)
162     pointer->base_type = gi_source_type_copy (base_type);
163   return pointer;
164 }
165
166 GISourceType *
167 gi_source_array_new (GISourceSymbol *size)
168 {
169   GISourceType *array = gi_source_type_new (CTYPE_ARRAY);
170   if (size != NULL && size->type == CSYMBOL_TYPE_CONST && size->const_int_set)
171       array->child_list = g_list_append (array->child_list, size);
172   return array;
173 }
174
175 GISourceType *
176 gi_source_function_new (void)
177 {
178   GISourceType *func = gi_source_type_new (CTYPE_FUNCTION);
179   return func;
180 }
181
182 GISourceScanner *
183 gi_source_scanner_new (void)
184 {
185   GISourceScanner * scanner;
186
187   scanner = g_slice_new0 (GISourceScanner);
188   scanner->typedef_table = g_hash_table_new_full (g_str_hash, g_str_equal,
189                                                   g_free, NULL);
190   scanner->struct_or_union_or_enum_table =
191     g_hash_table_new_full (g_str_hash, g_str_equal,
192                            g_free, (GDestroyNotify)gi_source_symbol_unref);
193
194   return scanner;
195 }
196
197 void
198 gi_source_scanner_free (GISourceScanner *scanner)
199 {
200   g_free (scanner->current_filename);
201
202   g_hash_table_destroy (scanner->typedef_table);
203   g_hash_table_destroy (scanner->struct_or_union_or_enum_table);
204
205   g_slist_foreach (scanner->comments, (GFunc)g_free, NULL);
206   g_slist_free (scanner->comments);
207   g_slist_foreach (scanner->symbols, (GFunc)gi_source_symbol_unref, NULL);
208   g_slist_free (scanner->symbols);
209
210   g_list_foreach (scanner->filenames, (GFunc)g_free, NULL);
211   g_list_free (scanner->filenames);
212
213 }
214
215 gboolean
216 gi_source_scanner_is_typedef (GISourceScanner *scanner,
217                               const char      *name)
218 {
219   gboolean b = g_hash_table_lookup (scanner->typedef_table, name) != NULL;
220   return b;
221 }
222
223 void
224 gi_source_scanner_set_macro_scan (GISourceScanner  *scanner,
225                                   gboolean          macro_scan)
226 {
227   scanner->macro_scan = macro_scan;
228 }
229
230 void
231 gi_source_scanner_add_symbol (GISourceScanner  *scanner,
232                               GISourceSymbol   *symbol)
233 {
234   gboolean found_filename = FALSE;
235   GList *l;
236
237   g_assert (scanner->current_filename);
238   for (l = scanner->filenames; l != NULL; l = l->next)
239     {
240       if (strcmp (l->data, scanner->current_filename) == 0)
241         {
242           found_filename = TRUE;
243           break;
244         }
245     }
246
247   if (found_filename || scanner->macro_scan)
248     scanner->symbols = g_slist_prepend (scanner->symbols,
249                                         gi_source_symbol_ref (symbol));
250   /* TODO: Refcounted string here or some other optimization */
251   if (found_filename && symbol->source_filename == NULL)
252     {
253       symbol->source_filename = g_strdup (scanner->current_filename);
254     }
255
256   switch (symbol->type)
257     {
258     case CSYMBOL_TYPE_TYPEDEF:
259       g_hash_table_insert (scanner->typedef_table,
260                            g_strdup (symbol->ident),
261                            GINT_TO_POINTER (TRUE));
262       break;
263     case CSYMBOL_TYPE_STRUCT:
264     case CSYMBOL_TYPE_UNION:
265     case CSYMBOL_TYPE_ENUM:
266       g_hash_table_insert (scanner->struct_or_union_or_enum_table,
267                            g_strdup (symbol->ident),
268                            gi_source_symbol_ref (symbol));
269       break;
270     default:
271       break;
272     }
273 }
274
275 GSList *
276 gi_source_scanner_get_symbols (GISourceScanner  *scanner)
277 {
278   return g_slist_reverse (scanner->symbols);
279 }
280
281 GSList *
282 gi_source_scanner_get_comments(GISourceScanner  *scanner)
283 {
284   return g_slist_reverse (scanner->comments);
285 }