X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/e10d6e307623d0952f6e1f5d9fee8720ddab4808..96e3b08533ea7fc6bd4b4de58849da0dec72411c:/src/util.c diff --git a/src/util.c b/src/util.c index 2eda8b0..5d891a2 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,6 @@ /* GOB C Preprocessor * Copyright (C) 1999-2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. * * Author: George Lebl * @@ -20,47 +21,82 @@ */ #include "config.h" +#include #include #include #include +#include "treefuncs.h" #include "main.h" #include "util.h" void -print_error(int is_warn, char *error,int line) +error_print(int type, int line, const char *error) { - char *w; - if(is_warn) + const char *w = NULL; + + switch(type) { + case GOB_WARN: w = "Warning:"; - else { + break; + case GOB_ERROR: w = "Error:"; got_error = TRUE; + break; + default: + g_assert_not_reached(); } - if(line>0) - fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error); + 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) + fprintf(stderr, "%s: %s %s\n", filename, w, error); + if(exit_on_error && + (type == GOB_ERROR || + (type == GOB_WARN && exit_on_warn))) exit(1); } +void +error_printf(int type, int line, const char *error, ...) +{ + va_list ap; + char *s; + + va_start(ap, error); + s = g_strdup_vprintf(error, ap); + va_end(ap); + + error_print(type, line, s); + + g_free(s); +} + char * -remove_sep(char *base) +remove_sep(const char *base) { char *p; char *s = g_strdup(base); - while((p=strchr(s,':'))) - strcpy(p,p+1); + + /* don't eat C++ :: thingies */ + if (for_cpp && strstr (s, "::") != NULL) + return s; + + while((p = strchr(s, ':'))) + strcpy(p, p+1); return s; } char * -replace_sep(char *base, char r) +replace_sep(const char *base, char r) { char *p; char *s = g_strdup(base); + + /* don't eat C++ :: thingies */ + if (for_cpp && strstr (s, "::") != NULL) + return s; + while((p=strchr(s,':'))) *p = r; if(*s == r) { @@ -74,11 +110,19 @@ replace_sep(char *base, char r) /*separate the namespace part and then replace rest of separators with r*/ void -separns_replace_sep(char *base, char **ns, char **name, char r) +separns_replace_sep(const char *base, char **ns, char **name, char r) { char *p; char *s = g_strdup(base); + *ns = NULL; + + /* don't eat C++ :: thingies */ + if (for_cpp && strstr (s, "::") != NULL) { + *name = s; + return; + } + if((p=strchr(s,':')) && p!=s) { *p = '\0'; *ns = g_strdup(s); @@ -98,21 +142,35 @@ separns_replace_sep(char *base, char **ns, char **name, char r) /* make a macro with some prefix before the name but after namespace */ char * -make_pre_macro(char *base, char *pre) +make_pre_macro(const char *base, const char *pre) { - char *s1,*s2; + char *ns, *name; char *s; + char **v = NULL; - separns_replace_sep(base,&s1,&s2,'_'); - if(s1) - s = g_strconcat(s1,"_",pre,"_",s2,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,"_",s2,NULL); + s = g_strconcat(pre, "_", name, NULL); g_strup(s); - g_free(s1); - g_free(s2); + g_free(ns); + g_free(name); + + g_strfreev(v); return s; } @@ -120,48 +178,191 @@ make_pre_macro(char *base, char *pre) /* 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 */ -const struct { +typedef struct _OurGtkType OurGtkType; +struct _OurGtkType { gboolean simple; char *gtkname; - char *typename; -} our_gtk_type_table[] = { - { TRUE, "NONE", "void " }, - { TRUE, "CHAR", "gchar " }, - { TRUE, "UCHAR", "guchar " }, - { TRUE, "BOOL", "gboolean " }, - { TRUE, "INT", "gint " }, - { TRUE, "UINT", "guint " }, - { TRUE, "LONG", "glong " }, - { TRUE, "ULONG", "gulong " }, - { TRUE, "FLOAT", "gfloat " }, - { TRUE, "DOUBLE", "gdouble " }, - { TRUE, "STRING", /*"GtkString"*/"gchar *" }, - { TRUE, "ENUM", /*"GtkEnum"*/"gint " }, - { TRUE, "FLAGS", /*"GtkFlags"*/"guint " }, - { TRUE, "BOXED", /*"GtkBoxed"*/"gpointer " }, - { TRUE, "POINTER", "gpointer " }, - { TRUE, "OBJECT", "GtkObject *" }, - { FALSE, "SIGNAL", /*"GtkSignal"*/"___twopointertype " }, - { FALSE, "ARGS", /*"GtkArgs"*/"___twopointertype " }, - { FALSE, "CALLBACK", /*"GtkCallback"*/"___threepointertype " }, - { FALSE, "C_CALLBACK", /*"GtkCCallback"*/"___twopointertype " }, - { FALSE, "FOREIGN", /*"GtkForeign"*/"___twopointertype " }, + char *cast; + char *type_name; + char *type_pointer; + int special; +}; +const OurGtkType our_gtk_type_table[] = { + { TRUE, "NONE", "void ", "void", NULL, -1 }, + { TRUE, "CHAR", "gchar ", "gchar", NULL, -1 }, + { TRUE, "UCHAR", "guchar ", "guchar", NULL, -1 }, + { TRUE, "UNICHAR", "gunichar ", "gunichar", NULL, -1 }, + { TRUE, "BOOLEAN", "gboolean ", "gboolean", NULL, -1 }, + { TRUE, "INT", "gint ", "gint", NULL, -1 }, + { TRUE, "UINT", "guint ", "guint", NULL, -1 }, + { TRUE, "LONG", "glong ", "glong", NULL, -1 }, + { TRUE, "ULONG", "gulong ", "gulong", NULL, -1 }, + { TRUE, "INT64", "gint64 ", "gint64", NULL, -1 }, + { TRUE, "UINT64", "guint64 ", "guint64", NULL, -1 }, + { TRUE, "ENUM", /*"enum"*/"gint ", "gint", NULL, -1 }, + { TRUE, "FLAGS", /*"flags"*/"guint ", "guint", NULL, -1 }, + { TRUE, "FLOAT", "gfloat ", "gfloat", NULL, -1 }, + { TRUE, "DOUBLE", "gdouble ", "gdouble", NULL, -1 }, + { TRUE, "STRING", /*"string"*/"gchar *", "gchar", "*", -1 }, + { TRUE, "POINTER", "gpointer ", "gpointer", NULL, -1 }, + { TRUE, "BOXED", /*"boxed"*/"gpointer ", "gpointer", NULL, -1 }, + { TRUE, "OBJECT", "GObject *", "GObject", "*", -1 }, + { TRUE, "PARAM", "GParamSpec *", "GParamSpec", "*", -1 }, + + /* FIXME: VALUE_ARRAY, CLOSURE */ + /* Note that those have some issues with g_value_ calls etc... so + * we can't just add them */ + + /* Do we need this??? */ +#if 0 + { 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 }, +#endif { FALSE, NULL, NULL } }; -const char * -get_cast(char *type, gboolean simple_only) +static GHashTable *type_hash = NULL; + +static void +init_type_hash(void) { int i; - for(i=0;our_gtk_type_table[i].gtkname;i++) { - if(strcmp(our_gtk_type_table[i].gtkname,type)==0) { - if(simple_only && - !our_gtk_type_table[i].simple) - return NULL; - return our_gtk_type_table[i].typename; + + 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 (const char *type, gboolean simple_only) +{ + OurGtkType *gtype; + + init_type_hash (); + + gtype = g_hash_table_lookup (type_hash, type); + + if (gtype == NULL || + (simple_only && + ! gtype->simple)) + return NULL; + + return gtype->cast; +} + +Type * +get_tree_type (const char *type, gboolean simple_only) +{ + OurGtkType *gtype; + Node *node; + + init_type_hash (); + + gtype = g_hash_table_lookup (type_hash, type); + + if (gtype == NULL || + (simple_only && + ! gtype->simple)) + return NULL; + + node = node_new (TYPE_NODE, + "name", gtype->type_name, + "pointer", gtype->type_pointer, + NULL); + + return (Type *)node; +} + +static void +mask_special_array (const 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 NULL; + + return any_special; +} + +char * +get_type (const Type *t, gboolean postfix_to_stars) +{ + char *s; + int i; + int extra; + GString *gs; + + s = remove_sep(t->name); + gs = g_string_new(s); + g_free(s); + + extra = 0; + if (postfix_to_stars) { + const char *p; + /*XXX: this is ugly perhaps we can do this whole postfix thing + in a nicer way, we just count the number of '[' s and from + that we deduce the number of dimensions, so that we can print + that many stars */ + for (p = t->postfix; p && *p; p++) + if(*p == '[') extra++; + } + g_string_append_c(gs, ' '); + + if (t->pointer != NULL) { + g_string_append (gs, t->pointer); + for (i=0; i < extra; i++) + g_string_append_c (gs, '*'); + g_string_append_c (gs, ' '); + } + + return g_string_free (gs, FALSE); }