aboutsummaryrefslogtreecommitdiff
path: root/pd/src/m_pd.c
diff options
context:
space:
mode:
authorGuenter Geiger <ggeiger@users.sourceforge.net>2002-07-29 17:06:19 +0000
committerGuenter Geiger <ggeiger@users.sourceforge.net>2002-07-29 17:06:19 +0000
commit57045df5fe3ec557e57dc7434ac1a07b5521bffc (patch)
tree7174058b41b73c808107c7090d9a4e93ee202341 /pd/src/m_pd.c
parentda38b3424229e59f956252c3d89895e43e84e278 (diff)
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
Diffstat (limited to 'pd/src/m_pd.c')
-rw-r--r--pd/src/m_pd.c296
1 files changed, 296 insertions, 0 deletions
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 <stdlib.h>
+#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();
+}
+