e519a942d639a2103dea6db1349dbcbd54b2006c
[platform/upstream/gobject-introspection.git] / 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 static void
198 gi_source_comment_free (GISourceComment *comment)
199 {
200   g_free (comment->comment);
201   g_free (comment->filename);
202   g_slice_free (GISourceComment, comment);
203 }
204
205 void
206 gi_source_scanner_free (GISourceScanner *scanner)
207 {
208   g_free (scanner->current_filename);
209
210   g_hash_table_destroy (scanner->typedef_table);
211   g_hash_table_destroy (scanner->struct_or_union_or_enum_table);
212
213   g_slist_foreach (scanner->comments, (GFunc)gi_source_comment_free, NULL);
214   g_slist_free (scanner->comments);
215   g_slist_foreach (scanner->symbols, (GFunc)gi_source_symbol_unref, NULL);
216   g_slist_free (scanner->symbols);
217
218   g_list_foreach (scanner->filenames, (GFunc)g_free, NULL);
219   g_list_free (scanner->filenames);
220
221 }
222
223 gboolean
224 gi_source_scanner_is_typedef (GISourceScanner *scanner,
225                               const char      *name)
226 {
227   gboolean b = g_hash_table_lookup (scanner->typedef_table, name) != NULL;
228   return b;
229 }
230
231 void
232 gi_source_scanner_set_macro_scan (GISourceScanner  *scanner,
233                                   gboolean          macro_scan)
234 {
235   scanner->macro_scan = macro_scan;
236 }
237
238 void
239 gi_source_scanner_add_symbol (GISourceScanner  *scanner,
240                               GISourceSymbol   *symbol)
241 {
242   gboolean found_filename = FALSE;
243   GList *l;
244
245   g_assert (scanner->current_filename);
246   for (l = scanner->filenames; l != NULL; l = l->next)
247     {
248       if (strcmp (l->data, scanner->current_filename) == 0)
249         {
250           found_filename = TRUE;
251           break;
252         }
253     }
254
255   if (found_filename || scanner->macro_scan)
256     scanner->symbols = g_slist_prepend (scanner->symbols,
257                                         gi_source_symbol_ref (symbol));
258   /* TODO: Refcounted string here or some other optimization */
259   if (found_filename && symbol->source_filename == NULL)
260     {
261       symbol->source_filename = g_strdup (scanner->current_filename);
262     }
263
264   switch (symbol->type)
265     {
266     case CSYMBOL_TYPE_TYPEDEF:
267       g_hash_table_insert (scanner->typedef_table,
268                            g_strdup (symbol->ident),
269                            GINT_TO_POINTER (TRUE));
270       break;
271     case CSYMBOL_TYPE_STRUCT:
272     case CSYMBOL_TYPE_UNION:
273     case CSYMBOL_TYPE_ENUM:
274       g_hash_table_insert (scanner->struct_or_union_or_enum_table,
275                            g_strdup (symbol->ident),
276                            gi_source_symbol_ref (symbol));
277       break;
278     default:
279       break;
280     }
281 }
282
283 GSList *
284 gi_source_scanner_get_symbols (GISourceScanner  *scanner)
285 {
286   return g_slist_reverse (scanner->symbols);
287 }
288
289 GSList *
290 gi_source_scanner_get_comments(GISourceScanner  *scanner)
291 {
292   return g_slist_reverse (scanner->comments);
293 }