2 * Copyright (C) 1999-2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
4 * Copyright (C) 2022 Nick Bowler
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
30 #include "treefuncs.h"
36 error_print(int type, int line, const char *error)
39 const char *fname = NULL;
52 g_assert_not_reached();
58 fprintf(stderr, "%s:%d: %s %s\n", fname, line, w, error);
60 fprintf(stderr, "%s: %s %s\n", fname, w, error);
61 if (exit_on_error && got_error)
66 error_printf(int type, int line, const char *error, ...)
72 s = g_strdup_vprintf(error, ap);
75 error_print(type, line, s);
81 remove_sep(const char *base)
84 char *s = g_strdup(base);
87 /* don't eat C++ :: thingies */
88 if (for_cpp && strstr (s, "::") != NULL)
91 for(p=(char *)base;*p;p++){
100 replace_sep(const char *base, char r)
103 char *s = g_strdup(base);
105 /* don't eat C++ :: thingies */
106 if (for_cpp && strstr (s, "::") != NULL)
110 while ((p=strchr(s,':')) != NULL) {
118 while ((p=strchr(s,':')) != NULL)
129 /*separate the namespace part and then replace rest of
132 separns_replace_sep(const char *base, char **ns, char **name, char r)
135 char *s = g_strdup(base);
139 /* don't eat C++ :: thingies */
140 if (for_cpp && strstr (s, "::") != NULL) {
145 if((p=strchr(s,':')) && p!=s) {
152 while((p=strchr(s,':')))
155 *name = g_strdup(s+1);
161 /* make a macro with some prefix before the name but after
164 make_pre_macro(const char *base, const char *pre)
170 if(strchr(base, ' ')) {
172 v = g_strsplit(base, " ", 0);
173 for(i = 0; v[i] != NULL; i++) {
174 if(*v[i] && strcmp(v[i], "const") != 0) {
181 separns_replace_sep(base, &ns, &name, '_');
183 s = g_strconcat(ns, "_", pre, "_", name,NULL);
185 s = g_strconcat(pre, "_", name, NULL);
197 /* here we will find out how inconsistent gtk really is :) */
198 /* the commented out types mean that these types don't actually
199 exist. so we "emulate them" with an equivalent */
200 typedef struct _OurGtkType OurGtkType;
209 const OurGtkType our_gtk_type_table[] = {
210 { TRUE, "NONE", "void ", "void", NULL, -1 },
211 { TRUE, "CHAR", "gchar ", "gchar", NULL, -1 },
212 { TRUE, "UCHAR", "guchar ", "guchar", NULL, -1 },
213 { TRUE, "UNICHAR", "gunichar ", "gunichar", NULL, -1 },
214 { TRUE, "BOOLEAN", "gboolean ", "gboolean", NULL, -1 },
215 { TRUE, "INT", "gint ", "gint", NULL, -1 },
216 { TRUE, "UINT", "guint ", "guint", NULL, -1 },
217 { TRUE, "LONG", "glong ", "glong", NULL, -1 },
218 { TRUE, "ULONG", "gulong ", "gulong", NULL, -1 },
219 { TRUE, "INT64", "gint64 ", "gint64", NULL, -1 },
220 { TRUE, "UINT64", "guint64 ", "guint64", NULL, -1 },
221 { TRUE, "ENUM", /*"enum"*/"gint ", "gint", NULL, -1 },
222 { TRUE, "FLAGS", /*"flags"*/"guint ", "guint", NULL, -1 },
223 { TRUE, "FLOAT", "gfloat ", "gfloat", NULL, -1 },
224 { TRUE, "DOUBLE", "gdouble ", "gdouble", NULL, -1 },
225 { TRUE, "STRING", /*"string"*/"gchar *", "gchar", "*", -1 },
226 { TRUE, "POINTER", "gpointer ", "gpointer", NULL, -1 },
227 { TRUE, "BOXED", /*"boxed"*/"gpointer ", "gpointer", NULL, -1 },
228 { TRUE, "OBJECT", "GObject *", "GObject", "*", -1 },
229 { TRUE, "PARAM", "GParamSpec *", "GParamSpec", "*", -1 },
231 /* FIXME: VALUE_ARRAY, CLOSURE */
232 /* Note that those have some issues with g_value_ calls etc... so
233 * we can't just add them */
235 /* Do we need this??? */
237 { FALSE, "SIGNAL", /*"GtkSignal"*/"___twopointertype ",
239 { FALSE, "ARGS", /*"GtkArgs"*/"___intpointertype ",
240 SPECIAL_INT_POINTER },
241 { FALSE, "CALLBACK", /*"GtkCallback"*/"___threepointertype ",
243 { FALSE, "C_CALLBACK", /*"GtkCCallback"*/"___twopointertype ",
245 { FALSE, "FOREIGN", /*"GtkForeign"*/"___twopointertype ",
249 { FALSE, NULL, NULL }
252 static GHashTable *type_hash = NULL;
259 if(type_hash) return;
261 type_hash = g_hash_table_new(g_str_hash, g_str_equal);
263 for(i=0; our_gtk_type_table[i].gtkname; i++)
264 g_hash_table_insert(type_hash,
265 our_gtk_type_table[i].gtkname,
266 (gpointer)&our_gtk_type_table[i]);
270 get_cast (const char *type, gboolean simple_only)
276 if(strncmp(type, "BOXED_", 6) == 0)
277 gtype = g_hash_table_lookup (type_hash, "BOXED");
279 gtype = g_hash_table_lookup (type_hash, type);
290 get_tree_type (const char *type, gboolean simple_only)
297 gtype = g_hash_table_lookup (type_hash, type);
304 node = node_new (TYPE_NODE,
305 "name", gtype->type_name,
306 "pointer", gtype->type_pointer,
313 mask_special_array (const char *type, gboolean *special_array, gboolean *any_special)
319 gtype = g_hash_table_lookup(type_hash, type);
321 if(gtype && gtype->special >= 0) {
322 special_array[gtype->special] = TRUE;
328 setup_special_array(Class *c, gboolean *special_array)
331 gboolean any_special = FALSE;
333 memset(special_array, 0, sizeof(gboolean)*SPECIAL_LAST);
335 for(li=c->nodes; li; li=g_list_next(li)) {
337 if(n->type == METHOD_NODE) {
338 Method *m = (Method *)n;
340 if(m->method != SIGNAL_LAST_METHOD &&
341 m->method != SIGNAL_FIRST_METHOD)
344 for(l=m->gtktypes; l; l=l->next)
345 mask_special_array(l->data, special_array,
347 } else if(n->type == ARGUMENT_NODE) {
348 Argument *a = (Argument *)n;
349 mask_special_array(a->gtktype, special_array,
358 get_type (const Type *t, gboolean postfix_to_stars)
365 s = remove_sep(t->name);
366 gs = g_string_new(s);
370 if (postfix_to_stars) {
372 /*XXX: this is ugly perhaps we can do this whole postfix thing
373 in a nicer way, we just count the number of '[' s and from
374 that we deduce the number of dimensions, so that we can print
376 for (p = t->postfix; p && *p; p++)
377 if(*p == '[') extra++;
379 g_string_append_c(gs, ' ');
381 if (t->pointer != NULL) {
382 g_string_append (gs, t->pointer);
383 for (i=0; i < extra; i++)
384 g_string_append_c (gs, '*');
385 g_string_append_c (gs, ' ');
388 g_string_free(gs, FALSE);
392 #if HAVE_G_ASCII_STRCASECMP
393 char *gob_strup(char *str)
397 for (s = str; *s; s++)
398 *s = g_ascii_toupper(*s);
403 char *gob_strdown(char *str)
407 for (s = str; *s; s++)
408 *s = g_ascii_tolower(*s);
415 gob_str_delete_quotes(char *str)
434 make_me_type (const char *type, const char *alt)
437 return g_strdup (alt);
438 /* HACK! just in case someone made this
439 * work with 2.0.0 by using the TYPE
441 if ((strstr (type, "_TYPE_") != NULL ||
442 strstr (type, "TYPE_") == type) &&
443 strchr (type, ':') == NULL)
444 return g_strdup (type);
445 return make_pre_macro (type, "TYPE");