From 57045df5fe3ec557e57dc7434ac1a07b5521bffc Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 29 Jul 2002 17:06:19 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r58, which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=59 --- pd/src/m_pd.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 pd/src/m_pd.c (limited to 'pd/src/m_pd.c') diff --git a/pd/src/m_pd.c b/pd/src/m_pd.c new file mode 100644 index 00000000..713d65ad --- /dev/null +++ b/pd/src/m_pd.c @@ -0,0 +1,296 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include "m_imp.h" + + /* FIXME no out-of-memory testing yet! */ + +t_pd *pd_new(t_class *c) +{ + t_pd *x; + if (!c) + bug ("pd_new: apparently called before setup routine"); + x = (t_pd *)t_getbytes(c->c_size); + *x = c; + if (c->c_patchable) + { + ((t_object *)x)->ob_inlet = 0; + ((t_object *)x)->ob_outlet = 0; + } + return (x); +} + +void pd_free(t_pd *x) +{ + t_class *c = *x; + if (c->c_freemethod) (*(t_gotfn)(c->c_freemethod))(x); + if (c->c_patchable) + { + while (((t_object *)x)->ob_outlet) + outlet_free(((t_object *)x)->ob_outlet); + while (((t_object *)x)->ob_inlet) + inlet_free(((t_object *)x)->ob_inlet); + if (((t_object *)x)->ob_binbuf) + binbuf_free(((t_object *)x)->ob_binbuf); + } + if (c->c_size) t_freebytes(x, c->c_size); +} + +/* deal with several objects bound to the same symbol. If more than one, we +actually bind a collection object to the symbol, which forwards messages sent +to the symbol. */ + +static t_class *bindlist_class; + +typedef struct _bindelem +{ + t_pd *e_who; + struct _bindelem *e_next; +} t_bindelem; + +typedef struct _bindlist +{ + t_pd b_pd; + t_bindelem *b_list; +} t_bindlist; + +static void bindlist_bang(t_bindlist *x) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_bang(e->e_who); +} + +static void bindlist_float(t_bindlist *x, t_float f) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_float(e->e_who, f); +} + +static void bindlist_symbol(t_bindlist *x, t_symbol *s) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_symbol(e->e_who, s); +} + +static void bindlist_pointer(t_bindlist *x, t_gpointer *gp) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_pointer(e->e_who, gp); +} + +static void bindlist_list(t_bindlist *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_list(e->e_who, s, argc, argv); +} + +static void bindlist_anything(t_bindlist *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_typedmess(e->e_who, s, argc, argv); +} + +void m_pd_setup(void) +{ + bindlist_class = class_new(gensym("bindlist"), 0, 0, + sizeof(t_bindlist), CLASS_PD, 0); + class_addbang(bindlist_class, bindlist_bang); + class_addfloat(bindlist_class, (t_method)bindlist_float); + class_addsymbol(bindlist_class, bindlist_symbol); + class_addpointer(bindlist_class, bindlist_pointer); + class_addlist(bindlist_class, bindlist_list); + class_addanything(bindlist_class, bindlist_anything); +} + +void pd_bind(t_pd *x, t_symbol *s) +{ + if (s->s_thing) + { + if (*s->s_thing == bindlist_class) + { + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem)); + e->e_next = b->b_list; + e->e_who = x; + b->b_list = e; + } + else + { + t_bindlist *b = (t_bindlist *)pd_new(bindlist_class); + t_bindelem *e1 = (t_bindelem *)getbytes(sizeof(t_bindelem)); + t_bindelem *e2 = (t_bindelem *)getbytes(sizeof(t_bindelem)); + b->b_list = e1; + e1->e_who = x; + e1->e_next = e2; + e2->e_who = s->s_thing; + e2->e_next = 0; + s->s_thing = &b->b_pd; + } + } + else s->s_thing = x; +} + +void pd_unbind(t_pd *x, t_symbol *s) +{ + if (s->s_thing == x) s->s_thing = 0; + else if (s->s_thing && *s->s_thing == bindlist_class) + { + /* bindlists always have at least two elements... if the number + goes down to one, get rid of the bindlist and bind the symbol + straight to the remaining element. */ + + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e, *e2; + if ((e = b->b_list)->e_who == x) + { + b->b_list = e->e_next; + freebytes(e, sizeof(t_bindelem)); + } + else for (e = b->b_list; e2 = e->e_next; e = e2) + if (e2->e_who == x) + { + e->e_next = e2->e_next; + freebytes(e2, sizeof(t_bindelem)); + break; + } + if (!b->b_list->e_next) + { + s->s_thing = b->b_list->e_who; + freebytes(b->b_list, sizeof(t_bindelem)); + pd_free(&b->b_pd); + } + } + else pd_error(x, "%s: couldn't unbind", s->s_name); +} + +void zz(void) {} + +t_pd *pd_findbyclass(t_symbol *s, t_class *c) +{ + t_pd *x = 0; + + if (!s->s_thing) return (0); + if (*s->s_thing == c) return (s->s_thing); + if (*s->s_thing == bindlist_class) + { + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e, *e2; + int warned = 0; + for (e = b->b_list; e; e = e->e_next) + if (*e->e_who == c) + { + if (x && !warned) + { + zz(); + post("warning: %s: multiply defined", s->s_name); + warned = 1; + } + x = e->e_who; + } + } + return x; +} + +/* stack for maintaining bindings for the #X symbol during nestable loads. +*/ + +typedef struct _gstack +{ + t_pd *g_what; + t_symbol *g_loadingabstraction; + struct _gstack *g_next; +} t_gstack; + +static t_gstack *gstack_head = 0; +static t_pd *lastpopped; +static t_symbol *pd_loadingabstraction; + +int pd_setloadingabstraction(t_symbol *sym) +{ + t_gstack *foo = gstack_head; + for (foo = gstack_head; foo; foo = foo->g_next) + if (foo->g_loadingabstraction == sym) + return (1); + pd_loadingabstraction = sym; + return (0); +} + +void pd_pushsym(t_pd *x) +{ + t_gstack *y = (t_gstack *)t_getbytes(sizeof(*y)); + y->g_what = s__X.s_thing; + y->g_next = gstack_head; + y->g_loadingabstraction = pd_loadingabstraction; + pd_loadingabstraction = 0; + gstack_head = y; + s__X.s_thing = x; +} + +void pd_popsym(t_pd *x) +{ + if (!gstack_head || s__X.s_thing != x) bug("gstack_pop"); + else + { + t_gstack *headwas = gstack_head; + s__X.s_thing = headwas->g_what; + gstack_head = headwas->g_next; + t_freebytes(headwas, sizeof(*headwas)); + lastpopped = x; + } +} + +void pd_doloadbang(void) +{ + if (lastpopped) + pd_vmess(lastpopped, gensym("loadbang"), ""); + lastpopped = 0; +} + +void pd_bang(t_pd *x) +{ + (*(*x)->c_bangmethod)(x); +} + +void pd_float(t_pd *x, t_float f) +{ + (*(*x)->c_floatmethod)(x, f); +} + +void pd_pointer(t_pd *x, t_gpointer *gp) +{ + (*(*x)->c_pointermethod)(x, gp); +} + +void pd_symbol(t_pd *x, t_symbol *s) +{ + (*(*x)->c_symbolmethod)(x, s); +} + +void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + (*(*x)->c_listmethod)(x, &s_list, argc, argv); +} + +void mess_init(void); +void obj_init(void); +void conf_init(void); +void glob_init(void); + +void pd_init(void) +{ + mess_init(); + obj_init(); + conf_init(); + glob_init(); +} + -- cgit v1.2.1