aboutsummaryrefslogtreecommitdiff
path: root/tcl_class.c
diff options
context:
space:
mode:
authormescalinum <mescalinum@users.sourceforge.net>2011-10-14 21:32:49 +0000
committermescalinum <mescalinum@users.sourceforge.net>2011-10-14 21:32:49 +0000
commit9ea4e9fc1b4775a0e6b1c387a2a0965686c1c20e (patch)
tree1e34e08655343287c27aed8ecfc1ff7a1f630191 /tcl_class.c
parent27e3734f86554c31a4593b998ca5312cf1b1af5b (diff)
reorder tcl land into namespaces and streamline and standardize syntax
svn path=/trunk/externals/loaders/tclpd/; revision=15600
Diffstat (limited to 'tcl_class.c')
-rw-r--r--tcl_class.c99
1 files changed, 64 insertions, 35 deletions
diff --git a/tcl_class.c b/tcl_class.c
index c0c7485..6e700c2 100644
--- a/tcl_class.c
+++ b/tcl_class.c
@@ -136,6 +136,8 @@ t_class* tclpd_class_new(const char* name, int flags) {
class_table_add(name, c);
class_addanything(c, tclpd_anything);
+
+ // is this really necessary given that there is already a 'anything' handler?
class_addmethod(c, (t_method)tclpd_loadbang, gensym("loadbang"), A_NULL);
// always set save function. it will call the default if
@@ -145,7 +147,7 @@ t_class* tclpd_class_new(const char* name, int flags) {
// check if properties function exists in tcl space.
char buf[80];
int res_i;
- snprintf(buf, 80, "llength [info procs ::%s_object_properties]", name);
+ snprintf(buf, 80, "llength [info procs ::%s::properties]", name);
if(Tcl_Eval(tcl_for_pd, buf) == TCL_OK) {
Tcl_Obj* res = Tcl_GetObjResult(tcl_for_pd);
if(Tcl_GetIntFromObj(tcl_for_pd, res, &res_i) == TCL_OK) {
@@ -196,31 +198,37 @@ t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) {
x->x_glist = (t_glist*)canvas_getcurrent();
x->classname = Tcl_NewStringObj(name, -1);
- char s[64];
- snprintf(s, 64, "tclpd:%s:x%lx", name, objectSequentialId++);
- x->self = Tcl_NewStringObj(s, -1);
-
- // the lifetime of x->classname and x->self is greater than this
+ char so[64];
+ snprintf(so, 64, "tclpd.%s.x%lx", name, objectSequentialId++);
+ x->self = Tcl_NewStringObj(so, -1);
+ char sd[64];
+ snprintf(sd, 64, "::%s::dispatcher", name);
+ x->dispatcher = Tcl_NewStringObj(sd, -1);
+
+ // the lifetime of x->{classname,self,dispatcher} is greater than this
// function, hence they get an extra Tcl_IncrRefCount here:
// (see tclpd_free())
Tcl_IncrRefCount(x->classname);
Tcl_IncrRefCount(x->self);
+ Tcl_IncrRefCount(x->dispatcher);
// store in object table (for later lookup)
- if(!object_table_get(s))
- object_table_add(s, x);
+ if(!object_table_get(so))
+ object_table_add(so, x);
// build constructor command
- Tcl_Obj *av[ac+2]; InitArray(av, ac+2, NULL);
- av[0] = x->classname;
+ Tcl_Obj *av[ac+3]; InitArray(av, ac+3, NULL);
+ av[0] = x->dispatcher;
Tcl_IncrRefCount(av[0]);
av[1] = x->self;
Tcl_IncrRefCount(av[1]);
+ av[2] = Tcl_NewStringObj("constructor", -1);
+ Tcl_IncrRefCount(av[2]);
for(int i=0; i<ac; i++) {
// NOTE: pd_to_tcl already calls Tcl_IncrRefCount
// so there is no need to call it here:
- if(pd_to_tcl(&at[i], &av[2+i]) == TCL_ERROR) {
+ if(pd_to_tcl(&at[i], &av[3+i]) == TCL_ERROR) {
#ifdef DEBUG
post("tclpd_new: failed conversion (pd_to_tcl)");
#endif
@@ -229,20 +237,20 @@ t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) {
}
// call constructor
- if(Tcl_EvalObjv(tcl_for_pd, ac+2, av, 0) != TCL_OK) {
+ if(Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0) != TCL_OK) {
goto error;
}
// decrement reference counter
- for(int i = 0; i < (ac+2); i++)
+ for(int i = 0; i < (ac+3); i++)
Tcl_DecrRefCount(av[i]);
return x;
error:
tclpd_interp_error(NULL, TCL_ERROR);
- for(int i = 0; i < (ac+2); i++) {
- if(!av[i]) break;
+ for(int i = 0; i < (ac+3); i++) {
+ if(!av[i]) break; // XXX: I don't remind why I add this
Tcl_DecrRefCount(av[i]);
}
pd_free((t_pd*)x);
@@ -251,25 +259,30 @@ error:
void tclpd_free(t_tcl* x) {
// build destructor command
- Tcl_Obj *sym = Tcl_NewStringObj(Tcl_GetStringFromObj(x->classname, NULL), -1);
- Tcl_AppendToObj(sym, "_destructor", -1);
- Tcl_Obj *av[2]; InitArray(av, 2, NULL);
- av[0] = sym;
+ Tcl_Obj *av[3]; InitArray(av, 3, NULL);
+ av[0] = x->dispatcher;
Tcl_IncrRefCount(av[0]);
av[1] = x->self;
Tcl_IncrRefCount(av[1]);
+ av[2] = Tcl_NewStringObj("destructor", -1);
+ Tcl_IncrRefCount(av[2]);
+
// call destructor
- if(Tcl_EvalObjv(tcl_for_pd, 2, av, 0) != TCL_OK) {
+ if(Tcl_EvalObjv(tcl_for_pd, 3, av, 0) != TCL_OK) {
#ifdef DEBUG
- post("tclpd_free: failed");
+ post("tclpd_free: failed to call destructor");
#endif
}
+
+ // decrement reference counter
Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
+ Tcl_DecrRefCount(av[2]);
// here ends the lifetime of x->classname and x->self
Tcl_DecrRefCount(x->self);
Tcl_DecrRefCount(x->classname);
+ Tcl_DecrRefCount(x->dispatcher);
#ifdef DEBUG
post("tclpd_free called");
#endif
@@ -280,30 +293,34 @@ void tclpd_anything(t_tcl* x, t_symbol* s, int ac, t_atom* at) {
}
void tclpd_inlet_anything(t_tcl* x, int inlet, t_symbol* s, int ac, t_atom* at) {
- // proxy method - format: <self> <inlet#> <selector> ...
- Tcl_Obj* av[ac+3]; InitArray(av, ac+3, NULL);
+ // proxy method - format: <classname> <self> method <inlet#> <selector> args...
+ Tcl_Obj* av[ac+5]; InitArray(av, ac+5, NULL);
int result;
- av[0] = x->self;
+ av[0] = x->dispatcher;
Tcl_IncrRefCount(av[0]);
- av[1] = Tcl_NewIntObj(inlet);
+ av[1] = x->self;
Tcl_IncrRefCount(av[1]);
- av[2] = Tcl_NewStringObj(s->s_name, -1);
+ av[2] = Tcl_NewStringObj("method", -1);
Tcl_IncrRefCount(av[2]);
+ av[3] = Tcl_NewIntObj(inlet);
+ Tcl_IncrRefCount(av[3]);
+ av[4] = Tcl_NewStringObj(s->s_name, -1);
+ Tcl_IncrRefCount(av[4]);
for(int i=0; i<ac; i++) {
- if(pd_to_tcl(&at[i], &av[3+i]) == TCL_ERROR) {
+ if(pd_to_tcl(&at[i], &av[5+i]) == TCL_ERROR) {
#ifdef DEBUG
post("pd_to_tcl: tclpd_inlet_anything: failed during conversion. check memory leaks!");
#endif
goto error;
}
}
- result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0);
+ result = Tcl_EvalObjv(tcl_for_pd, ac+5, av, 0);
if(result != TCL_OK) {
goto error;
}
- for(int i=0; i < (ac+3); i++)
+ for(int i=0; i < (ac+5); i++)
Tcl_DecrRefCount(av[i]);
// OK
@@ -311,7 +328,7 @@ void tclpd_inlet_anything(t_tcl* x, int inlet, t_symbol* s, int ac, t_atom* at)
error:
tclpd_interp_error(x, TCL_ERROR);
- for(int i=0; i < (ac+3); i++) {
+ for(int i=0; i < (ac+5); i++) {
if(!av[i]) break;
Tcl_DecrRefCount(av[i]);
}
@@ -385,12 +402,13 @@ void tclpd_save(t_gobj* z, t_binbuf* b) {
t_tcl* x = (t_tcl*)z;
- av[0] = x->self;
+ av[0] = x->dispatcher;
Tcl_IncrRefCount(av[0]);
- av[1] = Tcl_NewStringObj("object", -1);
+ av[1] = x->self;
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("save", -1);
Tcl_IncrRefCount(av[2]);
+
int result = Tcl_EvalObjv(tcl_for_pd, 3, av, 0);
if(result == TCL_OK) {
res = Tcl_GetObjResult(tcl_for_pd);
@@ -429,6 +447,7 @@ void tclpd_save(t_gobj* z, t_binbuf* b) {
pd_error(x, "Tcl: object save: failed");
tclpd_interp_error(x, result);
}
+
Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
@@ -436,23 +455,33 @@ void tclpd_save(t_gobj* z, t_binbuf* b) {
void tclpd_properties(t_gobj* z, t_glist* owner) {
Tcl_Obj* av[3]; InitArray(av, 3, NULL);
- Tcl_Obj* res;
t_tcl* x = (t_tcl*)z;
- av[0] = x->self;
+ av[0] = x->dispatcher;
Tcl_IncrRefCount(av[0]);
- av[1] = Tcl_NewStringObj("object", -1);
+ av[1] = x->self;
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("properties", -1);
Tcl_IncrRefCount(av[2]);
+
int result = Tcl_EvalObjv(tcl_for_pd, 3, av, 0);
if(result != TCL_OK) {
//res = Tcl_GetObjResult(tcl_for_pd);
pd_error(x, "Tcl: object properties: failed");
tclpd_interp_error(x, result);
}
+
Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
}
+
+void tclpd_class_namespace_init(const char* classname) {
+ char cmd[256];
+ snprintf(cmd, 256, "if [namespace exists ::%s] "
+ "{namespace delete ::%s}; "
+ "namespace eval ::%s {}",
+ classname, classname, classname);
+ Tcl_Eval(tcl_for_pd, cmd);
+}