gimp/tools/gcg/output.c

385 lines
8.1 KiB
C

#include <stdio.h>
#include "output.h"
#include <stdarg.h>
#include <ctype.h>
PNode* p_c_ident(Id id){
PNode* n;
gint i = 0;
GString* s = g_string_new(NULL);
for(i = 0; id[i]; i++){
if(!isalnum(id[i]) || (i && isupper(id[i])))
g_string_append_c(s, '_');
if(isalnum(id[i]))
g_string_append_c(s, tolower(id[i]));
}
n = p_str(s->str);
g_string_free(s, TRUE);
return n;
}
PNode* p_c_macro(Id id){
PNode* n;
gint i = 0;
GString* s = g_string_new(NULL);
for(i = 0; id[i]; i++){
if(!isalnum(id[i]) || (i && isupper(id[i])))
g_string_append_c(s, '_');
if(isalnum(id[i]))
g_string_append_c(s, toupper(id[i]));
}
n = p_str(s->str);
g_string_free(s, TRUE);
return n;
}
PNode* p_param(FunParams* p, ParamOptions* o){
return p_fmt("~~~~~~",
o->first ? p_nil : p_str(","),
!o->first && !(o->types && o->names) ? p_str(" ") : p_nil,
(o->types && o->names) ? p_str("\n\t") : p_nil,
o->types ? p_type(&p->type) : p_nil,
o->types && o->names ? p_str(" ") : p_nil,
o->names ? p->name : p_nil);
}
PNode* p_header(Module* m, Id suffix){
Id base = m->package->headerbase;
Id hdr = m->header;
Id name = m->package->name;
return p_fmt("~~",
base
? (base[0]
? p_fmt("~/", p_str(base))
: p_nil)
: ((name && name[0])
? p_fmt("~/", p_c_ident(name))
: p_nil),
hdr
? p_str(hdr)
: p_fmt("~~",
p_c_ident(m->name),
p_str(suffix)));
}
PNode* p_prot_header(Module* m){
return p_header(m, ".p.h");
}
PNode* p_type_header(Module* m){
return p_header(m, ".t.h");
}
PNode* p_func_header(Module* m){
return p_header(m, ".h");
}
PNode* p_import_header(Module* m){
if(m->header)
return p_nil;
else
return p_header(m, ".i.h");
}
PNode* p_type_include(Module* m){
return p_fmt("#include <~>\n",
p_type_header(m));
}
PNode* p_prot_include(Module* m){
return p_fmt("#include <~>\n",
p_prot_header(m));
}
PNode* p_func_include(Module* m){
return p_fmt("#include <~>\n",
p_func_header(m));
}
PNode* p_import_include(Module* m){
PNode* hdr = p_import_header(m);
if(hdr == p_nil)
return p_nil;
else
return p_fmt("#include <~>\n", hdr);
}
PNode* p_params(FunParams* args, ParamOptions* opt){
ParamOptions o=*opt;
PNode* n=p_nil;
while(args){
n=p_fmt("~~", n, p_param(args, &o));
args=args->next;
o.first=FALSE;
}
if(n==p_nil)
if(opt->first)
return p_str("void");
else
return p_nil;
else
return n;
}
PNode* p_prim_varname(PrimType* t){
return p_c_ident(t->name);
}
PNode* p_primtype(PrimType* t){
return p_fmt("~~",
p_str(t->module->package->name),
p_str(t->name));
}
PNode* p_cast(PNode* force_type, PNode* expression){
return p_fmt("((~)~)",
force_type,
expression);
}
PNode* p_type(Type* t){
if(t && t->prim){
PNode* node;
gint i=t->indirection;
node=p_fmt("~~",
t->is_const ? p_str("const ") : p_nil,
p_primtype(t->prim));
while(i--)
node=p_fmt("~~", node, p_str("*"));
/* file_add_dep(s, t->prim->decl_header);*/
return node;
}else
return p_str("void");
}
PNode* p_self_type(ObjectDef* o, PBool const_self){
return p_fmt("~~*",
(const_self ? p_str("const ") : p_nil),
p_primtype(DEF(o)->type));
}
PNode* p_varname(PrimType* t, PNode* name){
return p_fmt("~_~_~",
p_c_ident(t->module->package->name),
p_c_ident(t->name),
name);
}
PNode* p_internal_varname(PrimType* t, PNode* name){
return p_fmt("_~",
p_varname(t, name));
}
PNode* p_type_guard(Type* t, PNode* var){
PrimType* p=t->prim;
/*
if(t->notnull && (p->indirection>1 || p->kind!=GTK_TYPE_OBJECT))
return p_fmt("\tg_assert (~);\n", var);
else if(p->kind==GTK_TYPE_OBJECT)
return p_fmt("\tg_assert (~
kind !=
*/
return p_fmt("~~",
(t->indirection && t->notnull
? p_fmt("\tg_assert (~);\n", var)
: p_nil),
((t->indirection==1 && p->kind == TYPE_OBJECT)
? (t->notnull
? p_fmt("\tg_assert (~(~));\n",
p_macro_name(p, "is", NULL),
var)
: p_fmt("\tg_assert (!~ || ~(~));\n",
var,
p_macro_name(p, "is", NULL),
var))
: (t->indirection==0
? ((p->kind == TYPE_ENUM)
? p_fmt("\tg_assert (~ <= ~);\n",
var,
p_macro_name(p, NULL, "last"))
: ((p->kind == TYPE_FLAGS)
? p_fmt("\tg_assert ((~ << 1) < ~);\n",
var,
p_macro_name(p, NULL, "last"))
: p_nil))
: p_nil)));
}
PNode* p_type_guards(FunParams* args){
PNode* p=p_nil;
while(args){
p=p_fmt("~~", p, p_type_guard(&args->type, args->name));
args=args->next;
}
return p;
}
PNode* p_prototype(Type* rettype, PNode* name,
PNode* args1,
FunParams* args2){
ParamOptions o;
o.first = !args1 || args1 == p_nil;
o.names = TRUE;
o.types = TRUE;
return p_fmt("~ ~ (~~)",
p_type(rettype),
name,
args1,
p_params(args2, &o));
}
void output_var_alias(PRoot* out, PrimType* t, PNode* basename){
pr_put(out, "import_alias",
p_fmt("#define ~ ~_~\n",
basename,
p_c_ident(t->module->package->name),
basename));
}
void output_type_alias(PRoot* out, PrimType* t, PNode* basename){
pr_put(out, "import_alias",
p_fmt("typedef ~~ ~;\n",
p_str(t->module->package->name),
basename,
basename));
}
void output_func(PRoot* out,
Id tag,
Type* rettype,
PNode* name,
PNode* args1,
FunParams* args2,
PNode* body){
pr_put(out, tag ? tag : "source_head",
p_fmt("~~;\n",
tag
? p_nil
: p_str("static "),
p_prototype(rettype, name, args1, args2)));
pr_put(out, "source",
p_fmt("~~{\n"
"~"
"~"
"}\n\n",
tag
? p_nil
: p_str("static "),
p_prototype(rettype, name, args1, args2),
p_type_guards(args2),
body));
}
PNode* p_macro_name(PrimType* t, Id mid, Id post){
return p_fmt("~~_~~",
p_c_macro(t->module->package->name),
mid ? p_fmt("_~", p_c_macro(mid)) : p_nil,
p_c_macro(t->name),
post ? p_fmt("_~", p_c_macro(post)) : p_nil);
}
void output_var(PRoot* out, Id tag, PNode* type, PNode* name){
if(tag)
pr_put(out, tag,
p_fmt("extern ~ ~;\n",
type,
name));
pr_put(out, "source_head",
p_fmt("~~ ~;\n",
tag?p_nil:p_str("static "),
type,
name));
}
void output_def(PRoot* out, Def* d){
PrimType* t=d->type;
PNode* type_var=p_internal_varname(t, p_str("type"));
/* GTK_TYPE_FOO macro */
pr_put(out, "type", p_str("\n\n"));
pr_put(out, "source", p_str("\n"));
pr_put(out, "protected", p_str("\n\n"));
pr_put(out, "source_head", p_str("\n"));
pr_put(out, "type", p_fmt("#define ~ \\\n"
" (~ ? (void)0 : ~ (), ~)\n",
p_macro_name(t, "type", NULL),
type_var,
p_internal_varname(t, p_str("init_type")),
type_var));
output_macro_import(out, t, "type", NULL);
output_type_import(out, t->module->package, p_str(t->name));
output_var(out, "type",
p_str("GtkType"),
type_var);
switch(d->type->kind){
case TYPE_OBJECT:
output_object(out, d);
break;
case TYPE_ENUM:
output_enum(out, d);
break;
case TYPE_FLAGS:
output_flags(out, d);
break;
default:
;
}
}
void output_type_import(PRoot* out, Package* pkg, PNode* body){
#if 1
pr_put(out, "import_alias",
p_fmt("#define ~ ~~\n",
body,
p_str(pkg->name),
body));
#else
pr_put(out, "import_alias",
p_fmt("typedef ~~ ~;\n",
p_str(pkg->name),
body,
body));
#endif
}
void output_macro_import(PRoot* out, PrimType* t, Id mid, Id post){
pr_put(out, "import_alias",
p_fmt("#define ~~~ ~\n",
mid ? p_fmt("~_", p_c_macro(mid)) : p_nil,
p_c_macro(t->name),
post ? p_fmt("_~", p_c_macro(post)) : p_nil,
p_macro_name(t, mid, post)));
}
void output_var_import(PRoot* out, PrimType* t, PNode* body){
pr_put(out, "import_alias",
p_fmt("#define ~_~ ~\n",
p_c_ident(t->name),
body,
p_varname(t, body)));
}
/*
void add_dep(PRoot* out, Id tag, PrimType* type){
pr_put(out, tag, type->module);
}
PNode* p_deps(Id tag){
return p_col(tag, p_dep, NULL);
}
*/