X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/40647d7b7b7fbeae828e0a032a3c3a5f204cdfa8..f31590988781d77ff5249987801d03a986368ca2:/src/main.c diff --git a/src/main.c b/src/main.c index 07158f5..3a16554 100644 --- a/src/main.c +++ b/src/main.c @@ -60,14 +60,17 @@ static int arguments = 0; /* number of named arguments */ static int overrides = 0; /* number of override functions */ static int privates = 0; /* number of private data members */ -FILE *out; -FILE *outh; +FILE *out = NULL; +FILE *outh = NULL; +FILE *outph = NULL; gboolean no_touch_headers = FALSE; gboolean for_cpp = FALSE; gboolean exit_on_warn = FALSE; gboolean exit_on_error = TRUE; gboolean got_error = FALSE; +gboolean always_private_header = FALSE; +gboolean no_private_header = FALSE; void print_error(int is_warn, char *error,int line) @@ -182,15 +185,27 @@ make_bases(void) } static void -print_type(FILE *fp, Type *t) +print_type(FILE *fp, Type *t, gboolean postfix_to_stars) { char *s; int i; + int extra; + s = remove_sep(t->name); out_printf(fp,"%s ",s); g_free(s); + + extra = 0; + if(postfix_to_stars) { + 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 */ + for(p=t->postfix; p && *p; p++) + if(*p == '[') extra++; + } - for(i=0;istars;i++) + for(i=0;i<(t->stars+extra);i++) out_printf(fp,"*"); } @@ -202,7 +217,7 @@ print_method(FILE *fp, char *typeprefix, char *nameprefix, GList *li; out_printf(fp,"%s",typeprefix); - print_type(fp,m->mtype); + print_type(fp,m->mtype,TRUE); if(no_funcbase) out_printf(fp,"%s%s%s(", nameprefix,m->id,namepostfix); @@ -213,12 +228,15 @@ print_method(FILE *fp, char *typeprefix, char *nameprefix, if(m->args) { for(li=m->args;li;li=g_list_next(li)) { FuncArg *arg = li->data; - print_type(fp,arg->atype); + print_type(fp,arg->atype,FALSE); if(li->next) - out_printf(fp,"%s, ",arg->name); + out_printf(fp,"%s%s, ",arg->name, + arg->atype->postfix? + arg->atype->postfix:""); else - out_printf(fp,"%s",arg->name); - + out_printf(fp,"%s%s",arg->name, + arg->atype->postfix? + arg->atype->postfix:""); } if(m->vararg) out_printf(fp,", ..."); @@ -291,17 +309,13 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) } static void -put_variable(Variable *v, FILE *fp, int priv) +put_variable(Variable *v, FILE *fp) { - if(v->scope == PRIVATE_SCOPE) { - if(!priv) return; - } else { - if(priv) return; - } - out_printf(fp,"\t"); - print_type(fp,v->vtype); - out_printf(fp,"%s;\n",v->id); + print_type(fp,v->vtype,FALSE); + out_printf(fp,"%s%s;\n",v->id, + v->vtype->postfix? + v->vtype->postfix:""); } static void @@ -368,7 +382,7 @@ make_func_arg(char *typename, int is_class, char *name) else tn = g_strdup(typename); - type = new_type(1,tn); + type = new_type(1,tn,NULL); node = new_funcarg((Type *)type,name,NULL); return g_list_prepend(NULL, node); } @@ -397,7 +411,7 @@ make_inits(Class *cl) } if(!got_class_init) { node = new_method(CLASS_INIT_METHOD, - (Type *)new_type(0,g_strdup("void")), + (Type *)new_type(0,g_strdup("void"),NULL), NULL,NULL,g_strdup("class_init"), make_func_arg(cl->otype,TRUE,g_strdup("c")), NULL, NULL,0,0,FALSE); @@ -405,7 +419,7 @@ make_inits(Class *cl) } if(!got_init) { node = new_method(INIT_METHOD, - (Type *)new_type(0,g_strdup("void")), + (Type *)new_type(0,g_strdup("void"),NULL), NULL,NULL,g_strdup("init"), make_func_arg(cl->otype,FALSE,g_strdup("o")), NULL, NULL,0,0,FALSE); @@ -439,7 +453,7 @@ make_destroy(Class *cl) } if(!got_destroy) { node = new_method(OVERRIDE_METHOD, - (Type *)new_type(0,g_strdup("void")), + (Type *)new_type(0,g_strdup("void"),NULL), g_strdup("Gtk:Object"), NULL,g_strdup("destroy"), make_func_arg("Gtk:Object",FALSE,g_strdup("o")), @@ -478,14 +492,14 @@ add_signal_prots(Method *m) g_hash_table_insert(marsh,m,s); out_printf(out,"\ntypedef "); - print_type(out,m->mtype); + print_type(out,m->mtype,TRUE); out_printf(out,"(*%s) (",s); for(li=m->args;li;li=g_list_next(li)) { FuncArg *arg = li->data; - print_type(out,arg->atype); - out_printf(out,", "); + print_type(out,arg->atype,TRUE); + out_printf(out,", "); } out_printf(out,"gpointer);\n"); @@ -511,7 +525,7 @@ add_signal_prots(Method *m) else { FuncArg *fa = ali->data; out_printf(out, ",\n\t\t("); - print_type(out,fa->atype); + print_type(out,fa->atype,TRUE); out_printf(out, ")GTK_VALUE_%s(args[%d])", (char *)li->data,i); } @@ -523,7 +537,7 @@ add_signal_prots(Method *m) } else { int i; out_printf(out, "\t%s rfunc;\n\t",s); - print_type(out,m->mtype); + print_type(out,m->mtype,TRUE); out_printf(out, " *retval;\n\n" "\trfunc = (%s)func;\n\n" "\tretval = GTK_RETLOC_%s(args[%d]);\n\n" @@ -540,7 +554,7 @@ add_signal_prots(Method *m) else { FuncArg *fa = ali->data; out_printf(out, ",\n\t\t("); - print_type(out,fa->atype); + print_type(out,fa->atype,TRUE); out_printf(out, ")GTK_VALUE_%s(args[%d])", (char *)li->data,i); } @@ -981,7 +995,7 @@ print_checks(Method *m, FuncArg *fa) out_printf(out,");\n"); else { out_printf(out,", ("); - print_type(out,m->mtype); + print_type(out,m->mtype,TRUE); out_printf(out,")%s);\n", m->onerror?m->onerror:"0"); } @@ -1080,7 +1094,7 @@ put_method(Method *m) } else { GList *li; out_printf(out,"\t"); - print_type(out,m->mtype); + print_type(out,m->mtype,TRUE); out_printf(out,"return_val;\n"); print_preconditions(m); out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n" @@ -1133,7 +1147,7 @@ put_method(Method *m) out_printf(out,");\n" "\telse\n" "\t\treturn ("); - print_type(out,m->mtype); + print_type(out,m->mtype,TRUE); out_printf(out,")(%s);\n}\n", m->onerror?m->onerror:"0"); } @@ -1442,7 +1456,7 @@ count_privates(Class *c) static void open_files(void) { - char *outfile,*outfileh; + char *outfile,*outfileh,*outfileph; if(!for_cpp) outfile = g_strconcat(filebase,".c",NULL); @@ -1452,6 +1466,13 @@ open_files(void) outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL); else outfileh = g_strconcat(filebase,".h",NULL); + + if((privates>0 || always_private_header) && + !no_private_header) + outfileph = g_strconcat(filebase,"-private.h",NULL); + else + outfileph = NULL; + out = fopen(outfile,"w"); if(!out) { @@ -1461,6 +1482,12 @@ open_files(void) if(!outh) { g_error("Cannot open outfile: %s",outfileh); } + if(outfileph) { + outph = fopen(outfileph,"w"); + if(!outph) { + g_error("Cannot open outfile: %s",outfileh); + } + } } static void @@ -1469,10 +1496,14 @@ generate_outfiles(void) char *p; GList *li; time_t curtime; + gboolean found_header; 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)); @@ -1480,18 +1511,50 @@ generate_outfiles(void) g_strup(p); out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n" "#include \n\n",p,p); + if(outph) + out_printf(outph,"#ifndef __%s_PRIVATE_H__\n" + "#define __%s_PRIVATE_H__\n\n" + "#include \"%s.h\"\n\n",p,p,filebase); g_free(p); - if(!for_cpp) + if(!for_cpp) { out_printf(outh,"#ifdef __cplusplus\n" "extern \"C\" {\n" "#endif /* __cplusplus */\n\n"); + if(outph) + out_printf(outph,"#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif /* __cplusplus */\n\n"); + } p = g_strconcat(filebase,".h",NULL); - if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) + found_header = TRUE; + if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) { out_printf(out,"#include \"%s.h\"\n\n",filebase); + found_header = FALSE; + } g_free(p); + /* if we are creating a private header see if it was included */ + if(outph) { + p = g_strconcat(filebase,"-private.h",NULL); + if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) { + out_printf(out,"#include \"%s-private.h\"\n\n", + filebase); + if(found_header) + print_error(TRUE, + "Implicit private header include " + "added to top of\n" + "\tsource file, while public " + "header is at a custom location, " + "you should\n" + "\texplicitly include " + "the private header below the " + "public one.", 0); + } + g_free(p); + } + for(li=nodes;li;li=g_list_next(li)) { Node *node = li->data; if(node->type == CCODE_NODE) { @@ -1533,26 +1596,39 @@ generate_outfiles(void) typebase,ptypebase); for(l=c->nodes;l;l=g_list_next(l)) { Node *n = l->data; - if(n->type == VARIABLE_NODE) - put_variable((Variable *)n,outh,FALSE); + Variable *v = (Variable *)n; + if(n->type == VARIABLE_NODE && + v->scope == PUBLIC_SCOPE) + put_variable((Variable *)n,outh); } if(privates>0) out_printf(outh,"\t%sPrivate *_priv;\n",typebase); out_printf(outh,"};\n"); if(privates>0) { - out_printf(out,"struct _%sPrivate {\n", + FILE *outfp; + + /* if we are to stick this into the private + header, otherwise stick it directly into the + C file */ + if(outph) + outfp = outph; + else + outfp = out; + + out_printf(outfp,"struct _%sPrivate {\n", typebase); for(l=c->nodes;l;l=l->next) { Node *n = l->data; - if(n->type == VARIABLE_NODE) { - Variable *v = (Variable *)n; - out_addline_infile(out,v->line_no); - put_variable(v,out,TRUE); + 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(out); - out_printf(out,"};\n"); + out_addline_outfile(outfp); + out_printf(outfp,"};\n"); } out_printf(outh,"\ntypedef struct _%sClass %sClass;\n", @@ -1630,6 +1706,13 @@ generate_outfiles(void) "}\n" "#endif /* __cplusplus */\n"); out_printf(outh,"\n#endif"); + if(outph) { + if(!for_cpp) + out_printf(outph,"\n#ifdef __cplusplus\n" + "}\n" + "#endif /* __cplusplus */\n"); + out_printf(outph,"\n#endif"); + } } #if 0 @@ -1647,12 +1730,17 @@ print_help(void) { fprintf(stderr,"Gob version %s\n\n",VERSION); fprintf(stderr,"Options:\n" - "\t--help,-h,-? Display this help\n" - "\t--exit-on-warn,-w Exit with an error on warnings\n" - "\t--no-exit-on-warn Don't exit on warnings [default]\n" - "\t--for-cpp Create C++ files\n" - "\t--no-touch-headers Don't touch headers unless they " - "really changed\n"); + "\t--help,-h,-? Display this help\n" + "\t--exit-on-warn,-w Exit with an error on warnings\n" + "\t--no-exit-on-warn Don't exit on warnings [default]\n" + "\t--for-cpp Create C++ files\n" + "\t--no-touch-headers Don't touch headers unless they " + "really changed\n" + "\t--always-private-header Always create a private header " + "file, even if it would be empty\n" + "\t--no-private-header Don't create a private header, " + "put private structure inside c " + "file\n"); } static void @@ -1685,6 +1773,12 @@ parse_options(int argc, char *argv[]) for_cpp = TRUE; } else if(strcmp(argv[i],"--no-touch-headers")==0) { no_touch_headers = TRUE; + } else if(strcmp(argv[i],"--always-private-header")==0) { + no_private_header = FALSE; + always_private_header = TRUE; + } else if(strcmp(argv[i],"--no-private-header")==0) { + always_private_header = FALSE; + no_private_header = TRUE; } else if(strcmp(argv[i],"--")==0) { /*further arguments are files*/ no_opts = TRUE;