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