]> git.draconx.ca Git - gob-dx.git/blob - src/util.c
Release 1.0.5
[gob-dx.git] / src / util.c
1 /* GOB C Preprocessor
2  * Copyright (C) 1999-2000 the Free Software Foundation.
3  * Copyright (C) 2000 Eazel, Inc.
4  *
5  * Author: George Lebl
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the  Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20  * USA.
21  */
22
23 #include "config.h"
24 #include <string.h>
25 #include <stdio.h>
26 #include <glib.h>
27
28 #include "treefuncs.h"
29 #include "main.h"
30
31 #include "util.h"
32
33 void
34 error_print(int type, int line, const char *error)
35 {
36         char *w = NULL;
37
38         switch(type) {
39         case GOB_WARN:
40                 w = "Warning:";
41                 break;
42         case GOB_ERROR:
43                 w = "Error:";
44                 got_error = TRUE;
45                 break;
46         default:
47                 g_assert_not_reached();
48         }
49         if(line > 0)
50                 fprintf(stderr, "%s:%d: %s %s\n", filename, line, w, error);
51         else
52                 fprintf(stderr, "%s: %s %s\n", filename, w, error);
53         if(exit_on_error &&
54            (type == GOB_ERROR ||
55             (type == GOB_WARN && exit_on_warn)))
56                 exit(1);
57 }
58
59 void
60 error_printf(int type, int line, const char *error, ...)
61 {
62         va_list ap;
63         char *s;
64
65         va_start(ap, error);
66         s = g_strdup_vprintf(error, ap);
67         va_end(ap);
68
69         error_print(type, line, s);
70
71         g_free(s);
72 }
73
74 char *
75 remove_sep(const char *base)
76 {
77         char *p;
78         char *s = g_strdup(base);
79         while((p = strchr(s, ':')))
80                 strcpy(p, p+1);
81         return s;
82 }
83
84 char *
85 replace_sep(const char *base, char r)
86 {
87         char *p;
88         char *s = g_strdup(base);
89         while((p=strchr(s,':')))
90                 *p = r;
91         if(*s == r) {
92                 p = g_strdup(s+1);
93                 g_free(s);
94                 return p;
95         }
96         return s;
97 }
98
99 /*separate the namespace part and then replace rest of
100   separators with r*/
101 void
102 separns_replace_sep(const char *base, char **ns, char **name, char r)
103 {
104         char *p;
105         char *s = g_strdup(base);
106         *ns = NULL;
107         if((p=strchr(s,':')) && p!=s) {
108                 *p = '\0';
109                 *ns = g_strdup(s);
110                 p = g_strdup(p+1);
111                 g_free(s);
112                 s = p;
113         }
114         while((p=strchr(s,':')))
115                 *p = r;
116         if(*s == r) {
117                 *name = g_strdup(s+1);
118                 g_free(s);
119         } else
120                 *name = s;
121 }
122
123 /* make a macro with some prefix before the name but after
124    namespace */
125 char *
126 make_pre_macro(const char *base, const char *pre)
127 {
128         char *ns, *name;
129         char *s;
130         char **v = NULL;
131
132         if(strchr(base, ' ')) {
133                 int i;
134                 v = g_strsplit(base, " ", 0);
135                 for(i = 0; v[i] != NULL; i++) {
136                         if(*v[i] && strcmp(v[i], "const") != 0) {
137                                 base = v[i];
138                                 break;
139                         }
140                 }
141         }
142
143         separns_replace_sep(base, &ns, &name, '_');
144         if(ns)
145                 s = g_strconcat(ns, "_", pre, "_", name,NULL);
146         else
147                 s = g_strconcat(pre, "_", name, NULL);
148
149         g_strup(s);
150         
151         g_free(ns);
152         g_free(name);
153
154         g_strfreev(v);
155
156         return s;
157 }
158
159 /* here we will find out how inconsistent gtk really is :) */
160 /* the commented out types mean that these types don't actually
161    exist. so we "emulate them" with an equivalent */
162 typedef struct _OurGtkType OurGtkType;
163 struct _OurGtkType {
164         gboolean simple;
165         char *gtkname;
166         char *typename;
167         int special;
168 };
169 const OurGtkType our_gtk_type_table[] = {
170         { TRUE, "NONE",         "void ", -1 },
171         { TRUE, "CHAR",         "gchar ", -1 },
172         { TRUE, "UCHAR",        "guchar ", -1 },
173         { TRUE, "BOOL",         "gboolean ", -1 },
174         { TRUE, "INT",          "gint ", -1 },
175         { TRUE, "UINT",         "guint ", -1 },
176         { TRUE, "LONG",         "glong ", -1 },
177         { TRUE, "ULONG",        "gulong ", -1 },
178         { TRUE, "FLOAT",        "gfloat ", -1 },
179         { TRUE, "DOUBLE",       "gdouble ", -1 },
180         { TRUE, "STRING",       /*"GtkString"*/"gchar *", -1 },
181         { TRUE, "ENUM",         /*"GtkEnum"*/"gint ", -1 },
182         { TRUE, "FLAGS",        /*"GtkFlags"*/"guint ", -1 },
183         { TRUE, "BOXED",        /*"GtkBoxed"*/"gpointer ", -1 },
184         { TRUE, "POINTER",      "gpointer ", -1 },
185         { TRUE, "OBJECT",       "GtkObject *", -1 },
186         { FALSE, "SIGNAL",      /*"GtkSignal"*/"___twopointertype ",
187                 SPECIAL_2POINTER },
188         { FALSE, "ARGS",        /*"GtkArgs"*/"___intpointertype ",
189                 SPECIAL_INT_POINTER },
190         { FALSE, "CALLBACK",    /*"GtkCallback"*/"___threepointertype ",
191                 SPECIAL_3POINTER },
192         { FALSE, "C_CALLBACK",  /*"GtkCCallback"*/"___twopointertype ",
193                 SPECIAL_2POINTER },
194         { FALSE, "FOREIGN",     /*"GtkForeign"*/"___twopointertype ",
195                 SPECIAL_2POINTER },
196
197         { FALSE, NULL, NULL }
198 };
199
200 static GHashTable *type_hash = NULL;
201
202 static void
203 init_type_hash(void)
204 {
205         int i;
206
207         if(type_hash) return;
208
209         type_hash = g_hash_table_new(g_str_hash, g_str_equal);
210
211         for(i=0; our_gtk_type_table[i].gtkname; i++)
212                 g_hash_table_insert(type_hash,
213                                     our_gtk_type_table[i].gtkname,
214                                     (gpointer)&our_gtk_type_table[i]);
215 }
216
217 const char *
218 get_cast(char *type, gboolean simple_only)
219 {
220         OurGtkType *gtype;
221
222         init_type_hash();
223
224         gtype = g_hash_table_lookup(type_hash, type);
225
226         if(!gtype ||
227            (simple_only &&
228             !gtype->simple))
229                 return NULL;
230
231         return gtype->typename;
232 }
233
234 static void
235 mask_special_array(char *type, gboolean *special_array, gboolean *any_special)
236 {
237         OurGtkType *gtype;
238
239         init_type_hash();
240
241         gtype = g_hash_table_lookup(type_hash, type);
242
243         if(gtype && gtype->special >= 0) {
244                 special_array[gtype->special] = TRUE;
245                 *any_special = TRUE;
246         }
247 }
248
249 gboolean
250 setup_special_array(Class *c, gboolean *special_array)
251 {
252         GList *li;
253         gboolean any_special = FALSE;
254
255         memset(special_array, 0, sizeof(gboolean)*SPECIAL_LAST);
256
257         for(li=c->nodes; li; li=g_list_next(li)) {
258                 Node *n = li->data;
259                 if(n->type == METHOD_NODE) {
260                         Method *m = (Method *)n;
261                         GList *l;
262                         if(m->method != SIGNAL_LAST_METHOD &&
263                            m->method != SIGNAL_FIRST_METHOD)
264                                 continue;
265
266                         for(l=m->gtktypes; l; l=l->next)
267                                 mask_special_array(l->data, special_array,
268                                                    &any_special);
269                 } else if(n->type == ARGUMENT_NODE) {
270                         Argument *a = (Argument *)n;
271                         mask_special_array(a->gtktype, special_array,
272                                            &any_special);
273                 }
274         }
275
276         return any_special;
277 }
278
279 /* get the id without the first underscore, but only if we're removing them */
280 const char *
281 get_real_id(const char *id)
282 {
283         if( ! no_kill_underscores &&
284             id[0] == '_' &&
285             id[1] != '\0')
286                 return &id[1];
287         else
288                 return id;
289 }