]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 2.0.13
[gob-dx.git] / src / main.c
index f62f2f7065eda2c5c16720b8d6b3c003801af61a..186ac59cd794a3828e0a2a968fea8dfed9c1ae17 100644 (file)
@@ -25,6 +25,7 @@
 #include <glib.h>
 #include <time.h>
 #include <stdio.h>
+#include <errno.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -54,6 +55,9 @@ extern GHashTable *gtk_doc_hash;
 
 char *filebase;
 char *fullfilebase;
+static char *outfilebase;
+static char *outfilehbase;
+static char *outfilephbase;
 static char *funcbase;
 static char *pfuncbase;
 static char *macrobase;
@@ -77,6 +81,7 @@ static int protecteds = 0; /* number of protected methods */
 static int unreftors = 0; /* number of variable unreffing destructors */
 static int destructors = 0; /* number of variable non-unreffing destructors */
 static int initializers = 0; /* number of variable initializers */
+static int glade_widgets = 0; /* number of glade widgets */
 static gboolean overrode_get_type = FALSE; /* provided your won _get_type */
 
 static gboolean made_aliases = FALSE;  /* if we made any shorthand aliases
@@ -98,6 +103,7 @@ FILE *outh = NULL;
 FILE *outph = NULL;
 FILE *devnull = NULL;
 
+gboolean no_touch = FALSE;
 gboolean no_touch_headers = FALSE;
 gboolean for_cpp = FALSE;
 gboolean no_gnu = FALSE;
@@ -110,6 +116,7 @@ gboolean no_write = FALSE;
 gboolean no_lines = FALSE;
 gboolean no_self_alias = FALSE;
 gboolean always_private_struct = FALSE;
+gint prealloc = 0;
 
 gboolean use_m4 = FALSE; /* preprocess sources with m4 */
 gboolean use_m4_clean = FALSE; /* preprocess sources with m4, no m4 flags */
@@ -735,6 +742,8 @@ print_signal_marsal_args (const Method *m)
                        if (strcmp (li->data, "UNICHAR") == 0)
                                /* hack because glib is braindamaged */
                                get_func = g_strdup ("g_value_get_uint");
+                       else if (strncmp(li->data, "BOXED_", 6) == 0)
+                               get_func = g_strdup ("g_value_get_boxed");
                        else
                                get_func = g_strdup_printf
                                        ("g_value_get_%s", (char *)li->data);
@@ -1070,17 +1079,17 @@ add_get_type(void)
                   "\t\t\t(GClassFinalizeFunc) NULL,\n"
                   "\t\t\tNULL /* class_data */,\n"
                   "\t\t\tsizeof (%s),\n"
-                  "\t\t\t0 /* n_preallocs */,\n"
+                  "\t\t\t%d /* n_preallocs */,\n"
                   "\t\t\t(GInstanceInitFunc) %s_init,\n"
                   "\t\t\tNULL\n"
                   "\t\t};\n\n",
-                  funcbase, typebase, funcbase, typebase, funcbase);
+                  funcbase, typebase, funcbase, typebase, prealloc, funcbase);
 
        add_interface_infos ();
 
        out_printf (out,
-                   "\t\ttype = g_type_register_static (%s, \"%s\", &info, (GTypeFlags)0);\n",
-                   pmacrotype, typebase);
+                   "\t\ttype = g_type_register_static (%s, \"%s\", &info, (GTypeFlags)%s);\n",
+                   pmacrotype, typebase, ((Class *)class)->abstract ? "G_TYPE_FLAG_ABSTRACT" : "0");
 
        add_interfaces ();
 
@@ -1306,9 +1315,16 @@ add_signals(Class *c)
                
                if( ! is_none) {
                        GList *l;
-                       for(l = m->gtktypes->next; l != NULL; l = l->next)
-                               out_printf(out, ",\n\t\t\tG_TYPE_%s",
-                                       (char *)l->data);
+                       char  *t;
+                       for(l = m->gtktypes->next; l != NULL; l = l->next) {
+                               char *str = l->data;
+                               if (strncmp (str, "BOXED_", 6) == 0)
+                                       t = g_strdup (&(str[6]));
+                               else
+                                       t = g_strconcat ("G_TYPE_", str, NULL);
+                               out_printf (out, ",\n\t\t\t%s", t);
+                               g_free (t);
+                       }
                }
 
                out_printf(out, ");\n");
@@ -1428,8 +1444,8 @@ make_argument (Argument *a)
        char *argflags[] = {
                "CONSTRUCT",
                "CONSTRUCT_ONLY",
-               "CHILD_ARG",
-               "MASK",
+               "LAX_VALIDATION",
+               "PRIVATE",
                NULL
        };
 
@@ -1459,13 +1475,7 @@ make_argument (Argument *a)
                        if(strcmp(argflags[i], flag)==0)
                                break;
                }
-               /* if we haven't found it in our list */
-               if( ! argflags[i]) {
-                       error_printf(GOB_WARN, a->line_no,
-                                    "Unknown flag '%s' used, "
-                                    "perhaps it was misspelled", flag);
-               }
-               g_string_sprintfa(flags, " | G_PARAM_%s", flag);
+               g_string_sprintfa(flags, " | %s%s", argflags[i] ? "G_PARAM_" : "", flag);
        }
 
        g_string_append (flags, ")");
@@ -1625,8 +1635,8 @@ make_property (Property *p)
                char *argflags[] = {
                        "CONSTRUCT",
                        "CONSTRUCT_ONLY",
-                       "CHILD_ARG",
-                       "MASK",
+                       "LAX_VALIDATION",
+                       "PRIVATE",
                        NULL
                };
 
@@ -1655,13 +1665,7 @@ make_property (Property *p)
                                if(strcmp(argflags[i], flag)==0)
                                        break;
                        }
-                       /* if we haven't found it in our list */
-                       if( ! argflags[i]) {
-                               error_printf(GOB_WARN, p->line_no,
-                                            "Unknown flag '%s' used, "
-                                            "perhaps it was misspelled", flag);
-                       }
-                       g_string_sprintfa(flags, " | G_PARAM_%s", flag);
+                       g_string_sprintfa(flags, " | %s%s", argflags[i] ? "G_PARAM_" : "", flag);
                }
 
                g_string_append (flags, ")");
@@ -2011,6 +2015,9 @@ static void
 print_initializer(Method *m, Variable *v)
 {
        char *root;
+       
+       if(v->glade_widget)
+               return;
 
        if(v->initializer == NULL)
                return;
@@ -2024,8 +2031,13 @@ print_initializer(Method *m, Variable *v)
        if(v->initializer_line > 0)
                out_addline_infile(out, v->initializer_line);
 
-       out_printf(out, "\t%s->%s = %s;\n",
+       if (v->initializer_simple)
+               out_printf(out, "\t%s->%s = %s;\n",
                   root, v->id, v->initializer);
+       else if (!strcmp(v->id, "_glade_xml"))
+               out_printf(out,v->initializer, ((FuncArg *)m->args->data)->name);
+       else
+               out_printf(out,v->initializer);
 
        if(v->initializer_line > 0)
                out_addline_outfile(out);
@@ -2033,6 +2045,28 @@ print_initializer(Method *m, Variable *v)
        g_free(root);
 }
 
+static void
+print_glade_widget(Method *m, Variable *v)
+{
+       char *root;
+  char *cast;
+       
+       if(!v->glade_widget)
+               return;
+
+       if(v->scope == PRIVATE_SCOPE)
+               root = g_strconcat(((FuncArg *)m->args->data)->name,
+                                  "->_priv", NULL);
+       else
+               root = g_strdup(((FuncArg *)m->args->data)->name);
+
+       cast = get_type(v->vtype, FALSE);
+       out_printf(out, "\t%s->%s = (%s)glade_xml_get_widget(%s->_glade_xml, \"%s\");\n",
+                  root, v->id, cast, root, v->id);
+
+       g_free(root);
+}
+       
 static void
 print_destructor (Variable *v)
 {
@@ -2250,9 +2284,10 @@ add_inits(Class *c)
                                   c->otype);
                        if (privates > 0) {
                                out_printf(out, "\t%s->_priv = "
-                                               "G_TYPE_INSTANCE_GET_PRIVATE(%s,TYPE_SELF,%sPrivate);\n",
+                                               "G_TYPE_INSTANCE_GET_PRIVATE(%s,%s,%sPrivate);\n",
                                                ((FuncArg *)m->args->data)->name,
                                                ((FuncArg *)m->args->data)->name,
+                                               macrotype,
                                                typebase);
                        } else if(always_private_struct) {
                                out_printf(out, "\t%s->_priv = NULL;\n",
@@ -2271,6 +2306,19 @@ add_inits(Class *c)
                                        print_initializer(m, v);
                                }
                        }
+                       if(glade_widgets > 0) {
+                               GList *li;
+                               for(li = ((Class *)class)->nodes;
+                                   li != NULL;
+                                   li = li->next) {
+                                       Node *n = li->data;
+                                       Variable *v = (Variable *)n;
+                                       if(n->type != VARIABLE_NODE ||
+                                          v->scope == CLASS_SCOPE)
+                                               continue;
+                                       print_glade_widget(m, v);
+                               }
+                       }
                } else if(m->method == CLASS_INIT_METHOD) {
                        gboolean did_base_obj = FALSE;
 
@@ -2683,12 +2731,15 @@ put_signal_args (Method *m)
             li != NULL && ali != NULL;
             li = li->next, ali = ali->next, i++) {
                FuncArg *fa = li->data;
-               char *cast = g_strdup (get_cast (ali->data, FALSE));
+               char *str = ali->data;
+               char *cast = g_strdup (get_cast (str, FALSE));
                /* FIXME: This code is so fucking ugly it hurts */
                gboolean do_static = 
-                       (strcmp ((char *)ali->data, "STRING") == 0 ||
-                        strcmp ((char *)ali->data, "BOXED") == 0);
+                       (strcmp  (str, "STRING") == 0 ||
+                        strcmp  (str, "BOXED") == 0 ||
+                        strncmp (str, "BOXED_", 6) == 0);
                char *set_func;
+               char *t;
 
                if (cast == NULL) {
                        cast = get_type (fa->atype, TRUE);
@@ -2697,18 +2748,26 @@ put_signal_args (Method *m)
                   the we know all the types */
                g_assert (cast != NULL);
 
+               if (strncmp (str, "BOXED_", 6) == 0)
+                       t = g_strdup (&(str[6]));
+               else
+                       t = g_strconcat ("G_TYPE_", str, NULL);
+
                out_printf (out,
                            "\t___param_values[%d].g_type = 0;\n"
-                           "\tg_value_init (&___param_values[%d], G_TYPE_%s);\n",
-                           i, i, (char *)ali->data);
+                           "\tg_value_init (&___param_values[%d], %s);\n",
+                           i, i, t);
+               g_free (t);
 
-               if (strcmp (ali->data, "UNICHAR") == 0)
+               if (strcmp (str, "UNICHAR") == 0)
                        /* hack because glib is braindamaged */
                        set_func = g_strdup ("g_value_set_uint");
+               else if (strncmp (str, "BOXED_", 6) == 0)
+                       set_func = g_strdup ("g_value_set_static_boxed");
                else
                        set_func = g_strdup_printf ("g_value_set%s_%s",
                                                    do_static ? "_static" : "",
-                                                   (char *)ali->data);
+                                                   str);
                gob_strdown (set_func);
 
                out_printf (out, "\t%s (&___param_values[%d], (%s) %s);\n\n",
@@ -3016,14 +3075,11 @@ open_files(void)
 {
        char *outfile, *outfileh, *outfileph;
 
-       if ( ! for_cpp)
-               outfile = g_strconcat (fullfilebase, ".c", NULL);
-       else
-               outfile = g_strconcat (fullfilebase, ".cc", NULL);
-       if (no_touch_headers)
-               outfileh = g_strconcat (fullfilebase, ".h#gob#", NULL);
-       else
-               outfileh = g_strconcat (fullfilebase, ".h", NULL);
+       outfilebase = g_strconcat (fullfilebase, for_cpp ? ".cc" : ".c", NULL);
+       outfile = g_strconcat(outfilebase, no_touch ? "#gob#" : "", NULL);
+
+       outfilehbase = g_strconcat (fullfilebase, ".h");
+       outfileh = g_strconcat(outfilehbase, no_touch_headers ? "#gob#" : "", NULL);
 
        if ((privates > 0 || protecteds > 0 ||
             private_header == PRIVATE_HEADER_ALWAYS) &&
@@ -3031,8 +3087,10 @@ open_files(void)
                char sep[2] = {0,0};
                if (file_sep != 0)
                        sep[0] = file_sep;
-               outfileph = g_strconcat (fullfilebase, sep, "private.h", NULL);
+               outfilephbase = g_strconcat (fullfilebase, sep, "private.h", NULL);
+               outfileph = g_strconcat (outfilephbase, no_touch ? "#gob#" : "", NULL);
        } else {
+               outfilephbase = NULL;
                outfileph = NULL;
        }
 
@@ -3257,6 +3315,12 @@ print_class_block(Class *c)
        char *s;
        gboolean printed_private = FALSE;
 
+       if (c->glade_xml)
+       {
+               out_printf(outph ? outph : outh, "#include <gtk/gtk.h>\n");
+               out_printf(outph ? outph : outh, "#include <glade/glade-xml.h>\n\n");
+       }
+       
        if(any_special) {
                out_printf(out, "/* utility types we may need */\n");
                if(special_array[SPECIAL_2POINTER])
@@ -3383,16 +3447,19 @@ print_class_block(Class *c)
 
                out_printf (outfp, "struct _%sPrivate {\n",
                            typebase);
-               for(li=c->nodes; li; li=li->next) {
-                       Node *n = li->data;
-                       Variable *v = (Variable *)n;
-                       if(n->type == VARIABLE_NODE &&
-                          v->scope == PRIVATE_SCOPE) {
-                               out_addline_infile(outfp, v->line_no);
-                               put_variable(v, outfp);
+               if (privates > 0)
+               {
+                for(li=c->nodes; li; li=li->next) {
+                        Node *n = li->data;
+                        Variable *v = (Variable *)n;
+                        if(n->type == VARIABLE_NODE &&
+                                       v->scope == PRIVATE_SCOPE) {
+                                out_addline_infile(outfp, v->line_no);
+                                put_variable(v, outfp);
+                        }
                        }
+                       out_addline_outfile(outfp);
                }
-               out_addline_outfile(outfp);
                out_printf(outfp, "};\n");
        }
 
@@ -3538,6 +3605,43 @@ print_class_block(Class *c)
                    no_gnu ? "" : " G_GNUC_UNUSED",
                    typebase, typebase, typebase, funcbase);
 
+       if (c->glade_xml)
+       {
+               out_printf (out, "/* a function to connect glade callback */\n");
+               out_printf (out,"static void\n"
+                           "___glade_xml_connect_foreach(const gchar *handler_name,\n"
+                           "GObject *object,\n"
+                           "const gchar *signal_name,\n"
+                           "const gchar *signal_data,\n"
+                           "GObject *connect_object,\n"
+                           "gboolean after,\n"
+                           "gpointer user_data)\n"
+                           "{\n"
+                           "\tstatic GModule * allsymbols = NULL;\n"
+                           "   \n"
+                           "\tif (!allsymbols) allsymbols = g_module_open(NULL, 0);\n"
+                           "\tif (allsymbols) {\n"
+                           "\t\tgchar * func_name = g_strdup_printf(\"%s_%%s\", handler_name);\n"
+                           "\t\tGCallback func;\n"
+                           "\n"
+                           "\t\tif (!g_module_symbol(allsymbols, func_name, (gpointer)&func)){\n"
+                           "\t\t\tif (!g_module_symbol(allsymbols, handler_name, (gpointer)&func)) {\n"
+                           "\t\t\t\tg_warning(\"could not find signal handler '%%s'.\", func_name);\n"
+                           "\t\t\t\tg_free(func_name);\n"
+                           "\t\t\t\treturn;\n"
+                           "\t\t\t}\n"
+                           "\t\t}\n"
+                           "\t\tif (after)\n"
+                           "\t\t\tg_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);\n"
+                           "\t\telse\n"
+                           "\t\t\tg_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_SWAPPED);\n"
+                           "\t\tg_free(func_name);\n"
+                           "\t}\n"
+                           "}\n"
+                           "\n",
+                           funcbase);
+       }
+
        if (need_dispose)
                add_dispose (c);
 
@@ -3600,16 +3704,13 @@ print_more_useful_macros (void)
 static void
 print_file_comments(void)
 {
-       time_t curtime;
-       time(&curtime);
        out_printf(outh, "/* Generated by GOB (v%s)"
                   "   (do not edit directly) */\n\n", VERSION);
        if(outph)
                out_printf(outph, "/* Generated by GOB (v%s)"
                           "   (do not edit directly) */\n\n", VERSION);
-       out_printf(out, "/* Generated by GOB (v%s) on %s"
-                  "   (do not edit directly) */\n\n",
-                  VERSION, ctime(&curtime));
+       out_printf(out, "/* Generated by GOB (v%s)"
+                  "   (do not edit directly) */\n\n", VERSION);
 
        out_printf(out, "/* End world hunger, donate to the World Food Programme, http://www.wfp.org */\n\n");
 }
@@ -4000,6 +4101,9 @@ print_help(void)
                "\t--no-extern-c           Never print extern \"C\" into the "
                                          "header\n"
                "\t--no-gnu                Never use GNU extentions\n"
+               "\t--no-touch              Don't touch output files unless they "
+                                         "really\n"
+               "\t                        changed (implies --no-touch-headers)\n"
                "\t--no-touch-headers      Don't touch headers unless they "
                                          "really changed\n"
                "\t--always-private-header Always create a private header "
@@ -4097,6 +4201,9 @@ parse_options(int argc, char *argv[])
                        exit_on_warn = FALSE;
                } else if(strcmp(argv[i], "--for-cpp")==0) {
                        for_cpp = TRUE;
+               } else if(strcmp(argv[i], "--no-touch")==0) {
+                       no_touch = TRUE;
+                       no_touch_headers = TRUE;
                } else if(strcmp(argv[i], "--no-touch-headers")==0) {
                        no_touch_headers = TRUE;
                } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
@@ -4208,35 +4315,79 @@ parse_options(int argc, char *argv[])
 #endif
 }
 
-/* this is a somewhat ugly hack, but it appears to work */
 static void
-compare_and_move_header(void)
+compare_and_move (const char *old_filename)
 {
-       char *hfnew = g_strconcat(fullfilebase, ".h#gob#", NULL);
-       char *hf = g_strconcat(fullfilebase, ".h", NULL);
-       struct stat s;
-       if(stat(hf, &s) == 0) {
-               char *s;
-               s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
-               if(system(s) == 0) {
-                       if(unlink(hfnew) != 0)
-                               error_printf(GOB_ERROR, 0,
-                                            "Can't remove new header file");
-                       g_free(hfnew);
-                       g_free(hf);
-                       g_free(s);
-                       return;
+       char *new_filename = g_strconcat (old_filename, "#gob#", NULL);
+       FILE *old_f;
+       gboolean equal = FALSE;
+
+       old_f = fopen (old_filename, "r");
+       if (old_f) {
+               FILE *new_f;
+               gboolean error = FALSE;
+
+               new_f = fopen (new_filename, "r");
+               if (new_f) {
+                       char new_buf[1024];
+                       char old_buf[1024];
+
+                       while (TRUE) {
+                               size_t new_n;
+                               size_t old_n;
+
+                               new_n = fread (new_buf, 1, sizeof (new_buf), new_f);
+                               if (ferror (new_f)) {
+                                       error = TRUE;
+                                       error_printf (GOB_ERROR, 0,
+                                                     "Can't read %s: %s",
+                                                     new_filename,
+                                                     g_strerror (errno));
+                                       break;
+                               }
+
+                               old_n = fread (old_buf, 1, sizeof (old_buf), old_f);
+                               if (ferror (old_f)
+                                   || feof (new_f) != feof (old_f)
+                                   || new_n != old_n
+                                   || memcmp (new_buf, old_buf, new_n) != 0)
+                                       break;
+
+                               if (feof (new_f)) {
+                                       equal = TRUE;
+                                       break;
+                               }
+                       }
+               } else
+                       error_printf (GOB_ERROR, 0, "Can't open %s: %s",
+                                     new_filename, g_strerror (errno));
+
+               fclose (old_f);
+               fclose (new_f);
+
+               if (error)
+                       goto end;
+
+               if (! equal && unlink (old_filename) != 0) {
+                       error_printf (GOB_ERROR, 0, "Can't remove %s: %s",
+                                     old_filename, g_strerror (errno));
+                       goto end;
                }
-               g_free(s);
-               if(unlink(hf) != 0)
-                       error_printf(GOB_ERROR, 0,
-                                    "Can't remove old header file");
        }
-       if(rename(hfnew, hf) != 0)
-               error_printf(GOB_ERROR, 0,
-                            "Can't rename new header file");
-       g_free(hfnew);
-       g_free(hf);
+
+       if (equal) {
+               if (unlink (new_filename) != 0)
+                       error_printf (GOB_ERROR, 0, "Can't remove %s: %s",
+                                     new_filename, g_strerror (errno));
+       } else {
+               if (rename (new_filename, old_filename) != 0)
+                       error_printf (GOB_ERROR, 0, "Can't rename %s to %s: %s",
+                                     new_filename, old_filename,
+                                     g_strerror (errno));
+       }
+
+ end:
+       g_free (new_filename);
 }
 
 int
@@ -4290,6 +4441,7 @@ main(int argc, char *argv[])
        unreftors = count_unreftors ((Class *)class);
        destructors = count_destructors ((Class *)class);
        initializers = count_initializers ((Class *)class);
+       glade_widgets = count_glade_widgets ((Class *)class);
        overrode_get_type = find_get_type ((Class *)class);
 
        make_bases ();
@@ -4337,9 +4489,15 @@ main(int argc, char *argv[])
                        fclose (outph);
        }
 
-       if (no_touch_headers &&
-           ! no_write)
-               compare_and_move_header ();
+       if (! no_write) {
+               if (no_touch) {
+                       compare_and_move (outfilebase);
+                       if (outfilephbase)
+                               compare_and_move (outfilephbase);
+               }
+               if (no_touch_headers)
+                       compare_and_move (outfilehbase);
+       }
        
        return 0;
 }