output_object.c 11 KB
Newer Older
Lauri Alanko's avatar
Lauri Alanko committed
1
#include "output.h"
2
#include "marshall.h"
Lauri Alanko's avatar
Lauri Alanko committed
3

4 5 6 7
PNode* p_self_name(Member* o){
	return p_c_ident(DEF(o->my_class)->type->name);
}

8
PNode* p_object_member(Member* m){
Lauri Alanko's avatar
Lauri Alanko committed
9
	DataMember* d;
10
	if(m->membertype != MEMBER_DATA)
11
		return p_nil;
Lauri Alanko's avatar
Lauri Alanko committed
12
	d=(DataMember*)m;
13 14
	if(d->kind!=DATA_DIRECT)
		return p_nil;
15 16 17
	return p_fmt("\t~ ~;\n",
		     p_type(&d->type),
		     p_c_ident(m->name));
Lauri Alanko's avatar
Lauri Alanko committed
18 19
}

20 21 22 23 24 25 26 27
PNode* p_object_body(ObjectDef* o){
	return p_fmt("struct _~ {\n"
		     "\t~ parent;\n"
		     "~"
		     "};\n",
		     p_primtype(DEF(o)->type),
		     p_primtype(o->parent),
		     p_for(o->members, p_object_member, p_nil));
Lauri Alanko's avatar
Lauri Alanko committed
28 29
}

30
PNode* p_object_decl(ObjectDef* o){
Lauri Alanko's avatar
Lauri Alanko committed
31
	PrimType* n=DEF(o)->type;
Lauri Alanko's avatar
Lauri Alanko committed
32
	return p_fmt("typedef struct _~ ~;\n",
33 34 35 36 37
		     p_primtype(n),
		     p_primtype(n));
}

PNode* p_class_member(Member* m){
Lauri Alanko's avatar
Lauri Alanko committed
38
	ParamOptions o = {TRUE,FALSE,TRUE};
39
	if(m->membertype == MEMBER_DATA){
40
		DataMember* d=(DataMember*)m;
41 42 43 44 45 46
		if(d->kind != DATA_STATIC_VIRTUAL)
			return p_nil;
		else
			return p_fmt("\t~ ~;\n",
				     p_type(&d->type),
				     p_c_ident(m->name));
47
	}else if (m->membertype == MEMBER_METHOD){
48
		Method* d=(Method*)m;
49 50 51 52 53 54 55 56 57 58 59 60 61
		FunParams* p;
		PNode* parnode;
		
		if(d->kind==METH_STATIC ||
		   d->kind==METH_DIRECT)
			return p_nil;
		p=fparams("tp",
			  &m->my_class->self_type[d->self_const],
			  p_nil, p_nil,
			  d->params);
		parnode=p_params(p, &o);
		fparams_free(p);
		return p_fmt("\t~ (*~) (~);\n",
62 63
			     p_type(&d->ret_type),
			     p_c_ident(m->name),
64
			     parnode);
65 66
	}else
		return p_nil;
Lauri Alanko's avatar
Lauri Alanko committed
67 68
}

69 70 71
PNode* p_class_name(PrimType* o){
	return p_fmt("~Class",
		     p_primtype(o));
Lauri Alanko's avatar
Lauri Alanko committed
72 73
}

74 75 76
PNode* p_impl_name(ObjectDef* o){
	return p_fmt("~Impl",
		     p_primtype(DEF(o)->type));
Lauri Alanko's avatar
Lauri Alanko committed
77 78
}

79 80 81 82 83 84 85 86
PNode* p_class_body(ObjectDef* o){
	return p_fmt("struct _~ {\n"
		     "\t~ parent_class;\n"
		     "~"
		     "};\n",
		     p_class_name(DEF(o)->type),
		     p_class_name(o->parent),
		     p_for(o->members, p_class_member, p_nil));
Lauri Alanko's avatar
Lauri Alanko committed
87 88
}

89 90 91 92
PNode* p_class_decl(ObjectDef* o){
	return p_fmt("typedef struct _~ ~;\n",
		     p_class_name(DEF(o)->type),
		     p_class_name(DEF(o)->type));
Lauri Alanko's avatar
Lauri Alanko committed
93 94
}

95

96
PNode* p_real_varname(PrimType* t, PNode* name){
97 98
	return p_fmt("~_real",
		     p_varname(t, name));
99 100
}	

101

Lauri Alanko's avatar
Lauri Alanko committed
102 103 104 105 106 107 108 109 110 111
PNode* p_signal_handler_type(Method* s){
	Member* m=MEMBER(s);
	return p_fmt("~Handler_~",
		     p_primtype(DEF(m->my_class)->type),
		     p_c_ident(m->name));
}


void output_connector(PRoot* out, Method* m){
	FunParams* par=fparams("t",
112 113 114
			       &MEMBER(m)->my_class->self_type[m->self_const],
			       p_self_name(MEMBER(m)),
			       p_nil);
Lauri Alanko's avatar
Lauri Alanko committed
115 116 117 118 119 120

	output_func(out, "functions",
		    &m->ret_type,
		    p_varname(DEF(MEMBER(m)->my_class)->type,
			      p_fmt("connect_~",
				    p_c_ident(MEMBER(m)->name))),
121
		    p_fmt("\n\t~ handler,\n\tgpointer user_data",
Lauri Alanko's avatar
Lauri Alanko committed
122 123 124 125 126 127 128
			  p_signal_handler_type(m)),
		    par,
		    p_fmt("\t~gtk_signal_connect((GtkObject*)~,\n"
			  "\t\t\"~\",\n"
			  "\t\t(GtkSignalFunc)handler,\n"
			  "\t\tuser_data);\n",
			  m->ret_type.prim?p_str("return "):p_nil,
129
			  p_self_name(MEMBER(m)),
Lauri Alanko's avatar
Lauri Alanko committed
130
			  p_str(MEMBER(m)->name)));
131
	output_var_import(out, DEF(MEMBER(m)->my_class)->type,
132 133
			  p_fmt("connect_~",
				p_c_ident(MEMBER(m)->name)));
Lauri Alanko's avatar
Lauri Alanko committed
134 135
}
		    
136 137 138 139 140
PNode* p_param_marshtype(gpointer p){
	Param* param=p;
	return p_fmt(",\n\t\t~",
		     p_gtktype(&param->type));
}
Lauri Alanko's avatar
Lauri Alanko committed
141 142
	

143
void output_method(PRoot* out, Method* m){
Lauri Alanko's avatar
Lauri Alanko committed
144
	PrimType* t=DEF(MEMBER(m)->my_class)->type;
145 146 147 148 149
	PNode* name=p_c_ident(MEMBER(m)->name);
	MethodKind k=m->kind;
	ParamOptions o={TRUE, TRUE, FALSE};
	FunParams* par;
	PNode* dispatch;
150
	GSList* params;
151 152 153 154 155 156
	
	if(k == METH_STATIC)
		par = fparams("p", m->params);
	else
		par = fparams("tp",
			       &MEMBER(m)->my_class->self_type[m->self_const],
157 158 159
			      p_self_name(MEMBER(m)),
			      p_nil,
			      m->params);
160
	
161
	switch(k){
Lauri Alanko's avatar
Lauri Alanko committed
162
		SignalType* sig;
163 164 165
	case METH_EMIT_PRE:
	case METH_EMIT_POST:
	case METH_EMIT_BOTH:
Lauri Alanko's avatar
Lauri Alanko committed
166
		sig=sig_type(m);
167
		output_var(out, NULL,
168
			   p_str("guint"),
169
			   p_signal_id(m));
Lauri Alanko's avatar
Lauri Alanko committed
170 171
		o.names=FALSE;
		o.types=TRUE;
172
		pr_put(out, "source_sigtypes", sig);
173 174 175 176 177 178 179 180 181 182 183 184
		pr_put(out, "member_class_init",
		       p_fmt("\t~ =\n"
			     "\tgtk_signal_new(\"~\",\n"
			     "\t\tGTK_RUN_~,\n"
			     "\t\tobklass->type,\n"
			     "\t\tGTK_SIGNAL_OFFSET (~, ~),\n"
			     "\t\t~,\n"
			     "\t\t~,\n"
			     "\t\t~"
			     "~);\n"
			     "\tgtk_object_class_add_signals(obklass,\n"
			     "\t\t&~,\n"
185
			     "\t\t1);\n",
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
			     p_signal_id(m),
			     p_str(MEMBER(m)->name),
			     p_str(m->kind==METH_EMIT_PRE
				   ?"FIRST"
				   :m->kind==METH_EMIT_POST
				   ?"LAST"
				   :"BOTH"),
			     p_class_name(t),
			     name,
			     p_signal_demarshaller_name(sig),
			     p_gtktype(&m->ret_type),
			     p_prf("%d", g_slist_length(m->params)),
			     p_for(m->params, p_param_marshtype, p_nil),
			     p_signal_id(m)));
		
201 202 203 204
		pr_put(out, "functions",
		       p_fmt("typedef ~ (*~)("
			     "~,\n"
			     "\tgpointer);\n",
Lauri Alanko's avatar
Lauri Alanko committed
205 206 207 208 209 210
			     p_type(&m->ret_type),
			     p_signal_handler_type(m),
			     p_params(par, &o)));
		output_connector(out, m);
		o.names=TRUE;
		o.types=FALSE;
211
		dispatch=p_sig_marshalling(m);
212 213
		break;
	case METH_STATIC:
214 215
	case METH_DIRECT:{
		PNode* impl_name;
Lauri Alanko's avatar
Lauri Alanko committed
216 217
		o.names=TRUE;
		o.types=FALSE;
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

		impl_name=p_fmt("~_~",
				p_c_macro(t->name),
				p_c_macro(MEMBER(m)->name));
				
		dispatch=p_fmt("#ifdef ~\n"
			       "\t~~ (~);\n"
			       "#else\n"
			       "\tg_error(\"Not implemented: ~.~.~\");\n"
			       "#endif\n",
			       impl_name,
			       m->ret_type.prim
			       ? p_str("return ")
			       : p_nil,
			       impl_name,
			       p_params(par, &o),
			       p_str(t->module->package->name),
			       p_str(t->name),
			       p_str(MEMBER(m)->name));
		
238
		break;
239
	}
240
	case METH_VIRTUAL:
241
		dispatch=p_fmt("\t~((~*)((GtkObject*) ~)->klass)->~ (~);\n",
242 243 244
			       m->ret_type.prim?
			       p_str("return "):
			       p_nil,
Lauri Alanko's avatar
Lauri Alanko committed
245 246 247
			       p_class_name(DEF(MEMBER(m)->my_class)->type),
			       p_c_ident(t->name),
			       name,
248 249 250
			       p_params(par, &o));
		break;
	}
Lauri Alanko's avatar
Lauri Alanko committed
251
	output_func
252 253 254 255 256 257
	(out,
	 m->prot==METH_PUBLIC?"functions":"protected",
	 &m->ret_type,
	 p_varname(t, name),
	 p_nil,
	 par, 
258
	 dispatch);
259 260

	output_var_import(out, t, name);
261 262 263 264 265 266 267 268
	for(params = m->params; params; params = params->next)
		pr_put(out,
		       m->prot==METH_PUBLIC?"func_depends":"prot_depends",
		       ((Param*)(params->data))->type.prim->module);
	
		
	
	
269 270
	
	fparams_free(par);
271 272
}

273
void output_data_member(PRoot* out, DataMember* m){
274
	PrimType* t=DEF(MEMBER(m)->my_class)->type;
275
	PNode* name = p_c_ident(MEMBER(m)->name);
276
	PNode* self = p_self_name(MEMBER(m));
277

278
	
279
	switch(m->prot){
280
		FunParams* par;
281
	case DATA_READWRITE: {
282
		par=fparams("tt", &MEMBER(m)->my_class->self_type[FALSE],
283
			    self,
284 285 286 287
			    p_nil,
			    &m->type,
			    name,
			    p_nil);
288
		output_var_import(out, t, p_fmt("set_~", name));
289 290 291 292 293 294
		output_func(out,
			    "functions",
			    NULL,
			    p_varname(t, p_fmt("set_~", name)),
			    p_nil,
			    par,
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
			    p_fmt("~"
				  "\t~->~ = ~;\n",
				  (m->type.prim->kind==TYPE_OBJECT
				   && m->type.indirection==1)
				  ?m->type.notnull
				  ?p_fmt("\tgtk_object_ref "
					 "((GtkObject*) ~);\n"
					 "\tgtk_object_unref "
					 "((GtkObject*) ~->~);\n",
					 name,
					 self,
					 name)
				  :p_fmt("\tif(~)\n"
					 "\t\tgtk_object_ref "
					 "((GtkObject*) ~);\n"
					 "\tif(~->~)\n"
					 "\t\tgtk_object_unref "
					 "((GtkObject*) ~->~);\n",
					 name,
					 name,
					 self,
					 name,
					 self,
					 name)
				  :p_nil,
				  self,
321 322
				  name,
				  name));
323
		fparams_free(par);
324 325 326
	}
	/* fall through */
	case DATA_READONLY:
327
		pr_put(out, "func_depends", m->type.prim->module);
328
		par=fparams("t", &MEMBER(m)->my_class->self_type[TRUE],
329
			    self,
330
			    p_nil);
331
		output_var_import(out, t, name);
332 333
		output_func(out,
			    "functions",
Lauri Alanko's avatar
Lauri Alanko committed
334
			    &m->type,
335 336 337
			    p_varname(t, name),
			    p_nil,
			    par,
338 339
			    p_fmt("\treturn ~->~;\n",
				  self,
340
				  name));
341
		fparams_free(par);
342
		/* fall through */
343
	case DATA_PROTECTED:
344
		pr_put(out, "prot_depends", m->type.prim->module);
345 346
	}
}
Lauri Alanko's avatar
Lauri Alanko committed
347

348
	
349
void output_member(PRoot* out, Member* m){
350 351
	switch(m->membertype){
	case MEMBER_METHOD:
352
		output_method(out, (Method*)m);
353 354
		break;
	case MEMBER_DATA:
355
		output_data_member(out, (DataMember*)m);
356 357 358
		break;
	}
}
359 360 361 362 363

void output_member_cb(gpointer a, gpointer b){
	output_member(b, a);
}

364
void output_class_macros(PRoot* out, ObjectDef* o){
Lauri Alanko's avatar
Lauri Alanko committed
365
	PrimType* t=DEF(o)->type;
366 367
	pr_put(out, "type",
	       p_fmt("#define ~(o) GTK_CHECK_TYPE(o, ~)\n"
368 369 370 371 372
		     "#define ~(o) GTK_CHECK_CAST(o, ~, ~)\n",
		     p_macro_name(t, "is", NULL),
		     p_macro_name(t, "type", NULL),
		     p_macro_name(t, NULL, NULL),
		     p_macro_name(t, "type", NULL),
373 374 375
		     p_primtype(t)));
	output_macro_import(out, t, "is", NULL);
	output_macro_import(out, t, NULL, NULL);
Lauri Alanko's avatar
Lauri Alanko committed
376 377
}

378
void output_object_type_init(PRoot* out, ObjectDef* o){
Lauri Alanko's avatar
Lauri Alanko committed
379
	PrimType* t=DEF(o)->type;
380 381 382
	PNode* type_var=p_internal_varname(t, p_str("type"));
	output_func(out,
		    "type",
383
		    NULL,
384 385 386
		    p_internal_varname(t, p_str("init_type")),
		    p_nil,
		    NULL,
Lauri Alanko's avatar
Lauri Alanko committed
387
		    p_fmt("\tstatic GtkTypeInfo info = {\n"
388 389 390 391 392 393 394 395 396
			  "\t\t\"~\",\n"
			  "\t\tsizeof (~),\n"
			  "\t\tsizeof (~),\n"
			  "\t\t(GtkClassInitFunc) ~,\n"
			  "\t\t(GtkObjectInitFunc) ~,\n"
			  "\t\tNULL,\n"
			  "\t\tNULL,\n"
			  "\t\tNULL,\n"
			  "\t};\n"
397
			  "\tif (!~)\n"
398
			  "\t\t~ = gtk_type_unique (~, &info);\n",
399 400
			  p_primtype(t),
			  p_primtype(t),
401 402 403 404 405
			  p_class_name(t),
			  p_varname(t, p_str("class_init")),
			  p_varname(t, p_str("init")),
			  type_var,
			  type_var,
406
			  p_macro_name(o->parent, "type", NULL),
407 408 409
			  type_var));
}

410

Lauri Alanko's avatar
Lauri Alanko committed
411
void output_object_init(PRoot* out, ObjectDef* o){
412
	PrimType* t = DEF(o)->type;
Lauri Alanko's avatar
Lauri Alanko committed
413 414
	output_func(out, NULL,
		    NULL,
415
		    p_varname(t, p_str("init")),
Lauri Alanko's avatar
Lauri Alanko committed
416 417
		    p_fmt("~ ~",
			  p_type(&o->self_type[FALSE]),
418
			  p_c_ident(t->name)),
Lauri Alanko's avatar
Lauri Alanko committed
419
		    NULL,
420 421 422 423 424 425 426 427
		    p_fmt("\t(void) ~;\n"
			  "#ifdef ~_INIT\n"
			  "\t~_INIT (~);\n"
			  "#endif\n",
			  p_c_ident(t->name),
			  p_c_macro(t->name),
			  p_c_macro(t->name),
			  p_c_ident(t->name)));
Lauri Alanko's avatar
Lauri Alanko committed
428
}
429 430

void output_class_init(PRoot* out, ObjectDef* o){
431
	PrimType* t = DEF(o)->type;
432 433
	output_func(out, NULL,
		    NULL,
434
		    p_varname(t, p_str("class_init")),
435
		    p_fmt("~* klass",
436
			  p_class_name(t)),
437
		    NULL,
438 439 440
		    p_fmt("\tGtkObjectClass* obklass = "
			  "(GtkObjectClass*) klass;\n"
			  "~"
441
			  "\t(void) obklass;\n"
Lauri Alanko's avatar
Lauri Alanko committed
442
			  "~"
443 444 445
			  "#ifdef ~_CLASS_INIT\n"
			  "\t~_CLASS_INIT (klass);\n"
			  "#endif\n",
446 447
			  p_col("class_init_head", NULL),
			  p_col("member_class_init", NULL),
448 449
			  p_c_macro(t->name),
			  p_c_macro(t->name)));
450
}
451

452 453
void output_object(PRoot* out, Def* d){
	ObjectDef* o = (ObjectDef*)d;
454
	pr_put(out, "func_depends", d->type->module);
455 456 457
	pr_put(out, "func_parent_depends", o->parent->module);
	pr_put(out, "prot_parent_depends", o->parent->module);
	pr_put(out, "source_prot_depends", d->type->module);
458
	pr_put(out, "import_depends", o->parent->module);
459
	output_object_type_init(out, o);
460
	output_class_init(out, o);
Lauri Alanko's avatar
Lauri Alanko committed
461
	output_object_init(out, o);
462 463 464
	pr_put(out, "protected", p_class_decl(o));
	pr_put(out, "protected", p_class_body(o));
	pr_put(out, "type", p_object_decl(o));
465
	output_class_macros(out, o);
466
	pr_put(out, "protected", p_object_body(o));
467 468
	g_slist_foreach(o->members, output_member_cb, out);
}