aboutsummaryrefslogtreecommitdiff
path: root/shared/common/messtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/common/messtree.c')
-rw-r--r--shared/common/messtree.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/shared/common/messtree.c b/shared/common/messtree.c
new file mode 100644
index 0000000..6d778aa
--- /dev/null
+++ b/shared/common/messtree.c
@@ -0,0 +1,144 @@
+/* Copyright (c) 2005 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* This module covers parsing of a single message received by an object
+ or used for creation of an object, as well as parsing of multiple messages
+ contained in an imported buffer, etc. */
+
+#include "m_pd.h"
+#include "common/loud.h"
+#include "messtree.h"
+
+#ifdef KRZYSZCZ
+#define MESSTREE_DEBUG
+#endif
+
+/* There are two different messtree structures: the compile-time input
+ (t_messslot/t_messnode) and the run-time one (t_messtree). The reasons are:
+ to allow plugins to extend a message tree, and to make the compile-time
+ input initializer-friendly. */
+
+struct _messtree
+{
+ t_messslot *mt_slot;
+ t_symbol *mt_selector;
+ t_messcall mt_method;
+ int mt_nonexclusive;
+ struct _messtree *mt_sublist;
+ struct _messtree *mt_next;
+};
+
+t_messtree *messtree_new(t_symbol *selector)
+{
+ t_messtree *mt = getbytes(sizeof(*mt));
+ mt->mt_slot = 0;
+ mt->mt_selector = selector;
+ mt->mt_method = 0; /* LATER define a default */
+ mt->mt_nonexclusive = 0;
+ mt->mt_sublist = 0;
+ mt->mt_next = 0;
+ return (mt);
+}
+
+static void messtree_addnode(t_messtree *mt, t_messnode *mn)
+{
+ /* LATER respect mn->mn_index */
+ t_messslot *ms;
+ int i;
+ for (i = 0, ms = mn->mn_table + mn->mn_nslots - 1;
+ i < mn->mn_nslots; i++, ms--)
+ {
+ t_messtree *bch = messtree_new(gensym(ms->ms_name));
+ bch->mt_slot = ms;
+ bch->mt_method = ms->ms_call;
+ bch->mt_nonexclusive = (ms->ms_flags & MESSTREE_NONEXCLUSIVE);
+ bch->mt_next = mt->mt_sublist;
+ mt->mt_sublist = bch;
+ if (ms->ms_subnode)
+ messtree_addnode(bch, ms->ms_subnode);
+ }
+}
+
+void messtree_add(t_messtree *mt, t_messnode *rootnode)
+{
+ messtree_addnode(mt, rootnode);
+}
+
+t_messtree *messtree_build(t_messslot *rootslot)
+{
+ t_messtree *mt = messtree_new(gensym(rootslot->ms_name));
+ mt->mt_slot = rootslot;
+ mt->mt_method = rootslot->ms_call;
+ mt->mt_nonexclusive = (rootslot->ms_flags & MESSTREE_NONEXCLUSIVE);
+ mt->mt_sublist = 0;
+ mt->mt_next = 0;
+ if (rootslot->ms_subnode)
+ messtree_addnode(mt, rootslot->ms_subnode);
+ return (mt);
+}
+
+int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp,
+ t_pd *target, t_symbol *s, int ac, t_atom *av)
+{
+ int result = MESSTREE_OK, nargpdummy;
+ t_messslot *mspdummy;
+ if (!msp)
+ msp = &mspdummy;
+ if (!nargp)
+ nargp = &nargpdummy;
+ if (s && s != mt->mt_selector)
+ {
+ loud_warning(target, (target ? 0 : "messtree"),
+ "unexpected selector \"%s\"", s->s_name);
+ *msp = 0;
+ *nargp = 0;
+ return (MESSTREE_CORRUPT);
+ }
+ if (ac && av->a_type == A_SYMBOL)
+ {
+ t_messtree *bch;
+ for (bch = mt->mt_sublist; bch; bch = bch->mt_next)
+ {
+ if (av->a_w.w_symbol == bch->mt_selector)
+ {
+ if (bch->mt_sublist)
+ return (messtree_doit(bch, msp, nargp, target,
+ av->a_w.w_symbol, ac - 1, av + 1));
+ else
+ {
+ if (target && bch->mt_method)
+ result = bch->mt_method(target, av->a_w.w_symbol,
+ ac - 1, av + 1);
+ *msp = (result == MESSTREE_OK ? bch->mt_slot : 0);
+ *nargp = ac - 1;
+ return (result);
+ }
+ }
+ }
+ if (mt->mt_nonexclusive)
+ {
+ if (target && mt->mt_method)
+ result = mt->mt_method(target, 0, ac, av); /* LATER rethink */
+ *msp = (result == MESSTREE_OK ? mt->mt_slot : 0);
+ *nargp = ac;
+ return (result);
+ }
+ else
+ {
+ loud_warning(target, (target ? 0 : "messtree"),
+ "unknown property \"%s\"", av->a_w.w_symbol->s_name);
+ *msp = 0;
+ *nargp = 0;
+ return (MESSTREE_UNKNOWN);
+ }
+ }
+ else
+ {
+ if (target && mt->mt_method)
+ result = mt->mt_method(target, 0, ac, av);
+ *msp = (result == MESSTREE_OK ? mt->mt_slot : 0);
+ *nargp = ac;
+ return (result);
+ }
+}