/* GOB C Preprocessor * Copyright (C) 1999-2000 the Free Software Foundation. * Copyright (C) 2000 Eazel, Inc. * * Author: George Lebl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "config.h" #include #include #include #include "treefuncs.h" #include "main.h" #include "util.h" void print_error(gboolean is_warn, char *error, int line) { char *w; if(is_warn) w = "Warning:"; else { w = "Error:"; got_error = TRUE; } if(line>0) fprintf(stderr, "%s:%d: %s %s\n", filename, line, w, error); else fprintf(stderr, "%s: %s %s\n", filename, w, error); if((!is_warn || exit_on_warn) && exit_on_error) exit(1); } char * remove_sep(char *base) { char *p; char *s = g_strdup(base); while((p = strchr(s, ':'))) strcpy(p,p+1); return s; } char * replace_sep(const char *base, char r) { char *p; char *s = g_strdup(base); while((p=strchr(s,':'))) *p = r; if(*s == r) { p = g_strdup(s+1); g_free(s); return p; } return s; } /*separate the namespace part and then replace rest of separators with r*/ void separns_replace_sep(const char *base, char **ns, char **name, char r) { char *p; char *s = g_strdup(base); *ns = NULL; if((p=strchr(s,':')) && p!=s) { *p = '\0'; *ns = g_strdup(s); p = g_strdup(p+1); g_free(s); s = p; } while((p=strchr(s,':'))) *p = r; if(*s == r) { *name = g_strdup(s+1); g_free(s); } else *name = s; } /* make a macro with some prefix before the name but after namespace */ char * make_pre_macro(const char *base, const char *pre) { char *ns, *name; char *s; char **v = NULL; if(strchr(base, ' ')) { int i; v = g_strsplit(base, " ", 0); for(i = 0; v[i] != NULL; i++) { if(*v[i] && strcmp(v[i], "const") != 0) { base = v[i]; break; } } } separns_replace_sep(base, &ns, &name, '_'); if(ns) s = g_strconcat(ns, "_", pre, "_", name,NULL); else s = g_strconcat(pre, "_", name, NULL); g_strup(s); g_free(ns); g_free(name); g_strfreev(v); return s; } /* here we will find out how inconsistent gtk really is :) */ /* the commented out types mean that these types don't actually exist. so we "emulate them" with an equivalent */ typedef struct _OurGtkType OurGtkType; struct _OurGtkType { gboolean simple; char *gtkname; char *typename; int special; }; const OurGtkType our_gtk_type_table[] = { { TRUE, "NONE", "void ", -1 }, { TRUE, "CHAR", "gchar ", -1 }, { TRUE, "UCHAR", "guchar ", -1 }, { TRUE, "BOOL", "gboolean ", -1 }, { TRUE, "INT", "gint ", -1 }, { TRUE, "UINT", "guint ", -1 }, { TRUE, "LONG", "glong ", -1 }, { TRUE, "ULONG", "gulong ", -1 }, { TRUE, "FLOAT", "gfloat ", -1 }, { TRUE, "DOUBLE", "gdouble ", -1 }, { TRUE, "STRING", /*"GtkString"*/"gchar *", -1 }, { TRUE, "ENUM", /*"GtkEnum"*/"gint ", -1 }, { TRUE, "FLAGS", /*"GtkFlags"*/"guint ", -1 }, { TRUE, "BOXED", /*"GtkBoxed"*/"gpointer ", -1 }, { TRUE, "POINTER", "gpointer ", -1 }, { TRUE, "OBJECT", "GtkObject *", -1 }, { FALSE, "SIGNAL", /*"GtkSignal"*/"___twopointertype ", SPECIAL_2POINTER }, { FALSE, "ARGS", /*"GtkArgs"*/"___intpointertype ", SPECIAL_INT_POINTER }, { FALSE, "CALLBACK", /*"GtkCallback"*/"___threepointertype ", SPECIAL_3POINTER }, { FALSE, "C_CALLBACK", /*"GtkCCallback"*/"___twopointertype ", SPECIAL_2POINTER }, { FALSE, "FOREIGN", /*"GtkForeign"*/"___twopointertype ", SPECIAL_2POINTER }, { FALSE, NULL, NULL } }; static GHashTable *type_hash = NULL; static void init_type_hash(void) { int i; if(type_hash) return; type_hash = g_hash_table_new(g_str_hash, g_str_equal); for(i=0; our_gtk_type_table[i].gtkname; i++) g_hash_table_insert(type_hash, our_gtk_type_table[i].gtkname, (gpointer)&our_gtk_type_table[i]); } const char * get_cast(char *type, gboolean simple_only) { OurGtkType *gtype; init_type_hash(); gtype = g_hash_table_lookup(type_hash, type); if(!gtype || (simple_only && !gtype->simple)) return NULL; return gtype->typename; } static void mask_special_array(char *type, gboolean *special_array, gboolean *any_special) { OurGtkType *gtype; init_type_hash(); gtype = g_hash_table_lookup(type_hash, type); if(gtype && gtype->special >= 0) { special_array[gtype->special] = TRUE; *any_special = TRUE; } } gboolean setup_special_array(Class *c, gboolean *special_array) { GList *li; gboolean any_special = FALSE; memset(special_array, 0, sizeof(gboolean)*SPECIAL_LAST); for(li=c->nodes; li; li=g_list_next(li)) { Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; GList *l; if(m->method != SIGNAL_LAST_METHOD && m->method != SIGNAL_FIRST_METHOD) continue; for(l=m->gtktypes; l; l=l->next) mask_special_array(l->data, special_array, &any_special); } else if(n->type == ARGUMENT_NODE) { Argument *a = (Argument *)n; mask_special_array(a->gtktype, special_array, &any_special); } } return any_special; } /* get the id without the first underscore, but only if we're removing them */ char * get_real_id(char *id) { if(!no_kill_underscores && id[0] == '_' && id[1] != '\0') return &id[1]; else return id; }