aboutsummaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
authorN.N. <krzyszcz@users.sourceforge.net>2005-11-21 22:16:37 +0000
committerN.N. <krzyszcz@users.sourceforge.net>2005-11-21 22:16:37 +0000
commitc2014a0a771e621cec552c6ee88daddcb46d13fe (patch)
tree183540090b25920599d86cddfa03e37cefe45dec /shared
parenta1ef2f36df1754e1146a8ed50c9ac6a1b0f33697 (diff)
cyclone alpha55 (see notes.txt for cyclone and shared)
svn path=/trunk/externals/miXed/; revision=4011
Diffstat (limited to 'shared')
-rw-r--r--shared/Makefile.dirs2
-rw-r--r--shared/common/Makefile.sources1
-rw-r--r--shared/common/fitter.c237
-rw-r--r--shared/common/fitter.h6
-rw-r--r--shared/common/loud.c16
-rw-r--r--shared/common/loud.h2
-rw-r--r--shared/common/messtree.c144
-rw-r--r--shared/common/messtree.h47
-rw-r--r--shared/common/os.c99
-rw-r--r--shared/common/os.h15
-rw-r--r--shared/common/port.c6
-rw-r--r--shared/common/qtree.c208
-rw-r--r--shared/common/qtree.h11
-rw-r--r--shared/getridof.baddeps5
-rw-r--r--shared/hammer/gui.c4
-rw-r--r--shared/notes.txt21
-rw-r--r--shared/shared.h13
-rw-r--r--shared/unstable/fragile.c6
-rw-r--r--shared/unstable/fragile.h1
-rw-r--r--shared/unstable/loader.c220
-rw-r--r--shared/unstable/loader.h7
21 files changed, 880 insertions, 191 deletions
diff --git a/shared/Makefile.dirs b/shared/Makefile.dirs
index 0d88ac0..5764f41 100644
--- a/shared/Makefile.dirs
+++ b/shared/Makefile.dirs
@@ -1 +1 @@
-MIXED_DIRS = common hammer sickle toxy xeq unstable
+MIXED_DIRS = common hammer sickle toxy unstable
diff --git a/shared/common/Makefile.sources b/shared/common/Makefile.sources
index 33bf597..72977d2 100644
--- a/shared/common/Makefile.sources
+++ b/shared/common/Makefile.sources
@@ -6,6 +6,7 @@ fitter.c \
grow.c \
lex.c \
loud.c \
+messtree.c \
mifi.c \
os.c \
patchvalue.c \
diff --git a/shared/common/fitter.c b/shared/common/fitter.c
index faba970..48e5653 100644
--- a/shared/common/fitter.c
+++ b/shared/common/fitter.c
@@ -17,107 +17,156 @@
/* FIXME compatibility mode should be a standard Pd feature. When it is,
it will be possible to simplify the implementation. Until then,
- we have to handle multiple copies of the 'fittermode_value' variable
+ we have to handle multiple copies of the 'fitterstate_mode' variable
(coming from different externals), and the only way is multicasting
- through a symbol (#compatibility). */
-static t_symbol *fittermode_value = 0;
-
-typedef struct _fittermode_client
-{
- t_class *fc_owner;
- t_canvas *fc_canvas;
- t_fittermode_callback fc_callback;
- struct _fittermode_client *fc_next;
-} t_fittermode_client;
-
-static t_fittermode_client *fittermode_clients = 0;
-static t_class *fittermode_class = 0;
-static t_pd *fittermode_target = 0;
-static int fittermode_ready = 0;
-static t_symbol *fitterps_hashcompatibility = 0;
+ through a symbol (#miXed). */
+static t_symbol *fitterstate_mode = 0;
+
+/* FIXME keep state in an extensible fitterstate_dictionary */
+static t_symbol *fitterstate_test = 0;
+
+typedef struct _fitterstate_client
+{
+ t_class *fc_owner;
+ t_canvas *fc_canvas;
+ t_fitterstate_callback fc_callback;
+ struct _fitterstate_client *fc_next;
+} t_fitterstate_client;
+
+static t_fitterstate_client *fitterstate_clients = 0;
+static t_class *fitterstate_class = 0;
+static t_pd *fitterstate_target = 0;
+static int fitterstate_ready = 0;
+static t_symbol *fitterps_hashmiXed = 0;
+static t_symbol *fitterps_mode = 0;
+static t_symbol *fitterps_test = 0;
static t_symbol *fitterps_max = 0;
static t_symbol *fitterps_none = 0;
-/* read access (query), only from fittermode_dosetup() */
-static void fittermode_bang(t_pd *x)
+/* read access (query), called only from fitterstate_dosetup()
+ or through "#miXed" */
+static void fitterstate_bang(t_pd *x)
{
- if (fitterps_hashcompatibility)
+ if (fitterps_hashmiXed)
{
- if (fittermode_ready /* do not reply to own request */
- && fitterps_hashcompatibility->s_thing)
- /* this proliferates for the third and subsequent
- fittermode_dosetup() calls... */
- pd_symbol(fitterps_hashcompatibility->s_thing,
- fittermode_value);
+ if (fitterstate_ready /* do not reply to own request */
+ && fitterps_hashmiXed->s_thing)
+ {
+ t_atom atout[2];
+ /* these proliferate for the third and subsequent
+ fitterstate_dosetup() calls... */
+ SETSYMBOL(&atout[0], fitterps_mode);
+ SETSYMBOL(&atout[1], fitterstate_mode);
+ typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout);
+ SETSYMBOL(&atout[0], fitterps_test);
+ SETSYMBOL(&atout[1], fitterstate_test);
+ typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout);
+ }
}
- else loudbug_bug("fittermode_bang");
+ else loudbug_bug("fitterstate_bang");
}
-/* read access (reply), only from fitter_dosetup() */
-static void fittermode_symbol(t_pd *x, t_symbol *s)
+/* read access (query), called only through "#miXed" */
+static void fitterstate_symbol(t_pd *x, t_symbol *s)
{
- if (!s || s == &s_)
+ if (fitterstate_ready && fitterps_hashmiXed && fitterps_hashmiXed->s_thing)
{
- loudbug_bug("fittermode_symbol");
- s = fitterps_none;
+ t_atom atout[2];
+ if (s == fitterps_mode)
+ {
+ SETSYMBOL(&atout[0], fitterps_mode);
+ SETSYMBOL(&atout[1], fitterstate_mode);
+ typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout);
+ }
+ else if (s == fitterps_test)
+ {
+ SETSYMBOL(&atout[0], fitterps_test);
+ SETSYMBOL(&atout[1], fitterstate_test);
+ typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout);
+ }
+ else post("\"%s\": no such key in the miXed state",
+ (s ? s->s_name : "???"));
}
- fittermode_value = s;
+ else loudbug_bug("fitterstate_symbol");
}
-/* write access, only from fitter_setmode() */
-static void fittermode_set(t_pd *x, t_symbol *s)
+/* read access (reply), called only from fitter_dosetup() or through "#miXed" */
+static void fitterstate_reply(t_pd *x, t_symbol *s1, t_symbol *s2)
{
- t_fittermode_client *fc;
- fittermode_value = s;
- for (fc = fittermode_clients; fc; fc = fc->fc_next)
+ if (!s2 || s2 == &s_)
+ {
+ loudbug_bug("fitterstate_reply");
+ s2 = fitterps_none;
+ }
+ if (s1 == fitterps_mode)
+ fitterstate_mode = s2;
+ else if (s1 == fitterps_test)
+ fitterstate_test = s2;
+}
+
+/* write access, called only from fitter_setmode() or through "#miXed" */
+static void fitterstate_set(t_pd *x, t_symbol *s1, t_symbol *s2)
+{
+ t_fitterstate_client *fc;
+ if (s1 == fitterps_mode)
+ fitterstate_mode = s2;
+ else if (s1 == fitterps_test)
+ fitterstate_test = s2;
+ for (fc = fitterstate_clients; fc; fc = fc->fc_next)
if (fc->fc_callback)
fc->fc_callback();
}
-static void fittermode_dosetup(int noquery)
+static void fitterstate_dosetup(int noquery)
{
- if (fittermode_class || fittermode_target)
- loudbug_bug("fittermode_dosetup");
- fitterps_hashcompatibility = gensym("#compatibility");
+ if (fitterstate_class || fitterstate_target)
+ loudbug_bug("fitterstate_dosetup");
+ fitterps_hashmiXed = gensym("#miXed");
+ fitterps_mode = gensym("mode");
+ fitterps_test = gensym("test");
fitterps_max = gensym("max");
fitterps_none = gensym("none");
- fittermode_value = fitterps_none;
- fittermode_class = class_new(fitterps_hashcompatibility,
- 0, 0, sizeof(t_pd),
- CLASS_PD | CLASS_NOINLET, 0);
- class_addbang(fittermode_class, fittermode_bang);
- class_addsymbol(fittermode_class, fittermode_symbol);
- class_addmethod(fittermode_class,
- (t_method)fittermode_set,
- gensym("set"), A_SYMBOL, 0);
- fittermode_target = pd_new(fittermode_class);
- pd_bind(fittermode_target, fitterps_hashcompatibility);
+ fitterstate_mode = fitterps_none;
+ fitterstate_test = fitterps_none;
+ fitterstate_class = class_new(fitterps_hashmiXed,
+ 0, 0, sizeof(t_pd),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(fitterstate_class, fitterstate_bang);
+ class_addsymbol(fitterstate_class, fitterstate_symbol);
+ class_addmethod(fitterstate_class,
+ (t_method)fitterstate_reply,
+ gensym("reply"), A_SYMBOL, A_SYMBOL, 0);
+ class_addmethod(fitterstate_class,
+ (t_method)fitterstate_set,
+ gensym("set"), A_SYMBOL, A_SYMBOL, 0);
+ fitterstate_target = pd_new(fitterstate_class);
+ pd_bind(fitterstate_target, fitterps_hashmiXed);
if (!noquery)
- pd_bang(fitterps_hashcompatibility->s_thing);
- fittermode_ready = 1;
+ pd_bang(fitterps_hashmiXed->s_thing);
+ fitterstate_ready = 1;
}
-void fitter_setup(t_class *owner, t_fittermode_callback callback)
+void fitter_setup(t_class *owner, t_fitterstate_callback callback)
{
- if (!fittermode_class)
- fittermode_dosetup(0);
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
if (callback)
{
- t_fittermode_client *fc = getbytes(sizeof(*fc));
+ t_fitterstate_client *fc = getbytes(sizeof(*fc));
fc->fc_owner = owner;
fc->fc_canvas = 0; /* a global client */
fc->fc_callback = callback;
- fc->fc_next = fittermode_clients;
- fittermode_clients = fc;
+ fc->fc_next = fitterstate_clients;
+ fitterstate_clients = fc;
}
}
void fitter_drop(t_class *owner)
{
- if (fittermode_class && fitterps_hashcompatibility->s_thing)
+ if (fitterstate_class && fitterps_hashmiXed->s_thing)
{
- t_fittermode_client *fcp = 0,
- *fc = fittermode_clients;
+ t_fitterstate_client *fcp = 0,
+ *fc = fitterstate_clients;
while (fc)
{
if (fc->fc_owner == owner)
@@ -125,7 +174,7 @@ void fitter_drop(t_class *owner)
if (fcp)
fcp->fc_next = fc->fc_next;
else
- fittermode_clients = fc->fc_next;
+ fitterstate_clients = fc->fc_next;
break;
}
fcp = fc;
@@ -139,48 +188,72 @@ void fitter_drop(t_class *owner)
else loudbug_bug("fitter_drop 2");
}
+t_float *fitter_getfloat(t_symbol *s)
+{
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
+ loudbug_bug("fitter_getfloat");
+ return (0);
+}
+
+t_symbol *fitter_getsymbol(t_symbol *s)
+{
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
+ if (s == fitterps_mode)
+ return (fitterstate_mode);
+ else if (s == fitterps_test)
+ return (fitterstate_test);
+ else
+ {
+ loudbug_bug("fitter_getsymbol");
+ return (0);
+ }
+}
+
void fitter_setmode(t_symbol *s)
{
if (!s || s == &s_)
s = fitterps_none;
post("setting compatibility mode to '%s'", s->s_name);
- if (!fittermode_class)
- fittermode_dosetup(1);
- if (fitterps_hashcompatibility->s_thing)
+ if (!fitterstate_class)
+ fitterstate_dosetup(1);
+ if (fitterps_hashmiXed->s_thing)
{
- t_atom at;
- SETSYMBOL(&at, s);
- typedmess(fitterps_hashcompatibility->s_thing, gensym("set"), 1, &at);
+ t_atom atout[2];
+ SETSYMBOL(&atout[0], fitterps_mode);
+ SETSYMBOL(&atout[1], s);
+ typedmess(fitterps_hashmiXed->s_thing, gensym("set"), 2, atout);
}
else loudbug_bug("fitter_setmode");
}
t_symbol *fitter_getmode(void)
{
- if (!fittermode_class)
- fittermode_dosetup(0);
- return (fittermode_value);
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
+ return (fitterstate_mode);
}
void fittermax_set(void)
{
- if (!fittermode_class)
- fittermode_dosetup(0);
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
fitter_setmode(fitterps_max);
}
int fittermax_get(void)
{
- if (!fittermode_class)
- fittermode_dosetup(0);
- return (fittermode_value == fitterps_max);
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
+ return (fitterstate_mode == fitterps_max);
}
void fittermax_warning(t_class *c, char *fmt, ...)
{
- if (!fittermode_class)
- fittermode_dosetup(0);
- if (fittermode_value == fitterps_max)
+ if (!fitterstate_class)
+ fitterstate_dosetup(0);
+ if (fitterstate_mode == fitterps_max)
{
char buf[MAXPDSTRING];
va_list ap;
diff --git a/shared/common/fitter.h b/shared/common/fitter.h
index 2e5c24d..a6797e5 100644
--- a/shared/common/fitter.h
+++ b/shared/common/fitter.h
@@ -5,10 +5,12 @@
#ifndef __FITTER_H__
#define __FITTER_H__
-typedef void (*t_fittermode_callback)(void);
+typedef void (*t_fitterstate_callback)(void);
-void fitter_setup(t_class *owner, t_fittermode_callback callback);
+void fitter_setup(t_class *owner, t_fitterstate_callback callback);
void fitter_drop(t_class *owner);
+t_float *fitter_getfloat(t_symbol *s);
+t_symbol *fitter_getsymbol(t_symbol *s);
void fitter_setmode(t_symbol *s);
t_symbol *fitter_getmode(void);
void fittermax_set(void);
diff --git a/shared/common/loud.c b/shared/common/loud.c
index e1e921d..7129962 100644
--- a/shared/common/loud.c
+++ b/shared/common/loud.c
@@ -88,12 +88,18 @@ void loud_errand(t_pd *x, char *fmt, ...)
va_end(ap);
}
-void loud_syserror(t_pd *x, char *msg)
+void loud_syserror(t_pd *x, char *fmt, ...)
{
- if (msg)
- loud_error(x, "%s (%s)", msg, strerror(errno));
- else
- loud_error(x, strerror(errno));
+ if (fmt)
+ {
+ char buf[MAXPDSTRING];
+ va_list ap;
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap);
+ loud_error(x, "%s (%s)", buf, strerror(errno));
+ va_end(ap);
+ }
+ else loud_error(x, strerror(errno));
}
void loud_nomethod(t_pd *x, t_symbol *s)
diff --git a/shared/common/loud.h b/shared/common/loud.h
index 297b9c1..9497e0d 100644
--- a/shared/common/loud.h
+++ b/shared/common/loud.h
@@ -18,7 +18,7 @@ int shared_matchignorecase(char *test, char *pattern);
char *loud_ordinal(int n);
void loud_error(t_pd *x, char *fmt, ...);
void loud_errand(t_pd *x, char *fmt, ...);
-void loud_syserror(t_pd *x, char *msg);
+void loud_syserror(t_pd *x, char *fmt, ...);
void loud_nomethod(t_pd *x, t_symbol *s);
void loud_messarg(t_pd *x, t_symbol *s);
int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess);
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);
+ }
+}
diff --git a/shared/common/messtree.h b/shared/common/messtree.h
new file mode 100644
index 0000000..a3a3326
--- /dev/null
+++ b/shared/common/messtree.h
@@ -0,0 +1,47 @@
+/* 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. */
+
+#ifndef __MESSTREE_H__
+#define __MESSTREE_H__
+
+typedef int (*t_messcall)(t_pd *, t_symbol *, int, t_atom *);
+typedef char *t_messarg;
+
+typedef struct _messslot
+{
+ char *ms_name;
+ t_messcall ms_call;
+ char *ms_argument;
+ int ms_flags;
+ struct _messnode *ms_subnode;
+} t_messslot;
+
+typedef struct _messnode /* a parser's symbol definition, sort of... */
+{
+ t_messslot *mn_table;
+ int mn_nslots;
+ int mn_index;
+} t_messnode;
+
+EXTERN_STRUCT _messtree;
+#define t_messtree struct _messtree
+
+#define MESSTREE_NSLOTS(slots) (sizeof(slots)/sizeof(*(slots)))
+
+enum { MESSTREE_OK, /* done current message parsing, parse next */
+ MESSTREE_CONTINUE, /* continue current message parsing */
+ MESSTREE_UNKNOWN, /* current message unknown, parse next */
+ MESSTREE_CORRUPT, /* current message corrupt, parse next */
+ MESSTREE_FATAL /* exit parsing */
+};
+
+#define MESSTREE_NONEXCLUSIVE 1
+
+t_messtree *messtree_new(t_symbol *selector);
+void messtree_add(t_messtree *mt, t_messnode *rootnode);
+t_messtree *messtree_build(t_messslot *rootslot);
+int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp,
+ t_pd *target, t_symbol *s, int ac, t_atom *av);
+
+#endif
diff --git a/shared/common/os.c b/shared/common/os.c
index 9129f82..408fdfb 100644
--- a/shared/common/os.c
+++ b/shared/common/os.c
@@ -6,6 +6,7 @@
#include <io.h>
#else
#include <unistd.h>
+#include <dirent.h>
#endif
#include <stdlib.h>
#include <stdio.h>
@@ -233,3 +234,101 @@ FILE *filewrite_open(char *filename, t_canvas *cv, int textmode)
sys_bashfilename(path, path);
return (fopen(path, (textmode ? "w" : "wb")));
}
+
+/* FIXME add MSW */
+
+struct _osdir
+{
+#ifndef MSW
+ DIR *dir_handle;
+ struct dirent *dir_entry;
+#endif
+ int dir_flags;
+};
+
+/* returns 0 on error, a caller is then expected to call
+ loud_syserror(owner, "cannot open \"%s\"", dirname) */
+t_osdir *osdir_open(char *dirname)
+{
+#ifndef MSW
+ DIR *handle = opendir(dirname);
+ if (handle)
+ {
+#endif
+ t_osdir *dp = getbytes(sizeof(*dp));
+#ifndef MSW
+ dp->dir_handle = handle;
+ dp->dir_entry = 0;
+#endif
+ dp->dir_flags = 0;
+ return (dp);
+#ifndef MSW
+ }
+ else return (0);
+#endif
+}
+
+void osdir_setmode(t_osdir *dp, int flags)
+{
+ if (dp)
+ dp->dir_flags = flags;
+}
+
+void osdir_close(t_osdir *dp)
+{
+ if (dp)
+ {
+#ifndef MSW
+ closedir(dp->dir_handle);
+#endif
+ freebytes(dp, sizeof(*dp));
+ }
+}
+
+void osdir_rewind(t_osdir *dp)
+{
+ if (dp)
+ {
+#ifndef MSW
+ rewinddir(dp->dir_handle);
+ dp->dir_entry = 0;
+#endif
+ }
+}
+
+char *osdir_next(t_osdir *dp)
+{
+#ifndef MSW
+ if (dp)
+ {
+ while (dp->dir_entry = readdir(dp->dir_handle))
+ {
+ if (!dp->dir_flags ||
+ (dp->dir_entry->d_type == DT_REG
+ && (dp->dir_flags & OSDIR_FILEMODE)) ||
+ (dp->dir_entry->d_type == DT_DIR
+ && (dp->dir_flags & OSDIR_DIRMODE)))
+ return (dp->dir_entry->d_name);
+ }
+ }
+#endif
+ return (0);
+}
+
+int osdir_isfile(t_osdir *dp)
+{
+#ifndef MSW
+ return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_REG);
+#else
+ return (0);
+#endif
+}
+
+int osdir_isdir(t_osdir *dp)
+{
+#ifndef MSW
+ return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_DIR);
+#else
+ return (0);
+#endif
+}
diff --git a/shared/common/os.h b/shared/common/os.h
index f3dde89..7bf3c9a 100644
--- a/shared/common/os.h
+++ b/shared/common/os.h
@@ -5,9 +5,24 @@
#ifndef __OS_H__
#define __OS_H__
+EXTERN_STRUCT _osdir;
+#define t_osdir struct _osdir
+
+#define OSDIR_FILEMODE 1
+#define OSDIR_DIRMODE 2
+
int ospath_length(char *path, char *cwd);
char *ospath_absolute(char *path, char *cwd, char *result);
+
FILE *fileread_open(char *filename, t_canvas *cv, int textmode);
FILE *filewrite_open(char *filename, t_canvas *cv, int textmode);
+t_osdir *osdir_open(char *dirname);
+void osdir_setmode(t_osdir *dp, int flags);
+void osdir_close(t_osdir *dp);
+void osdir_rewind(t_osdir *dp);
+char *osdir_next(t_osdir *dp);
+int osdir_isfile(t_osdir *dp);
+int osdir_isdir(t_osdir *dp);
+
#endif
diff --git a/shared/common/port.c b/shared/common/port.c
index 5845210..fe58b6e 100644
--- a/shared/common/port.c
+++ b/shared/common/port.c
@@ -35,8 +35,10 @@
#define PORT_INISTACK 256 /* LATER rethink */
#define PORT_INISIZE 512 /* LATER rethink */
-enum { PORT_OK,
- PORT_NEXT, /* next line, please */
+/* FIXME use messtree api */
+
+enum { PORT_OK, /* MESSTREE_CONTINUE */
+ PORT_NEXT, /* next line, please: MESSTREE_OK */
PORT_UNKNOWN, PORT_CORRUPT, PORT_FATAL };
/* cf binport.c */
diff --git a/shared/common/qtree.c b/shared/common/qtree.c
index 3d35769..b749b3a 100644
--- a/shared/common/qtree.c
+++ b/shared/common/qtree.c
@@ -294,7 +294,7 @@ static t_qnode *qtree_postinserthook(t_qnode *np)
(which means foundp returns 1), a new node is inserted, unless hook is
either empty, or returns null. Hook's nonempty return is the parent
for the new node. It is expected to have no more than one child. */
-static t_qnode *qtree_doinsert(t_qtree *tree, double key,
+static t_qnode *qtree_doinsert(t_qtree *tree, double key, t_qnode *preexisting,
t_qtree_inserthook hook, int *foundp)
{
t_qnode *np, *parent, *result;
@@ -302,11 +302,18 @@ static t_qnode *qtree_doinsert(t_qtree *tree, double key,
*foundp = 0;
if (!(np = tree->t_root))
{
- if (!(np = getbytes(tree->t_nodesize)))
+ if (!(np = (tree->t_nodesize > 0 ?
+ getbytes(tree->t_nodesize) : preexisting)))
+ {
+ if (tree->t_nodesize == 0)
+ loudbug_bug("qtree_insert, node not supplied");
return (0);
+ }
np->n_key = key;
np->n_black = 1;
+ np->n_left = np->n_right = np->n_parent = 0;
tree->t_root = tree->t_first = tree->t_last = np;
+ np->n_prev = np->n_next = 0;
return (np);
}
@@ -343,8 +350,13 @@ static t_qnode *qtree_doinsert(t_qtree *tree, double key,
addit:
/* parent has no more than one child, new node becomes
parent's immediate successor or predecessor */
- if (!(np = getbytes(tree->t_nodesize)))
+ if (!(np = (tree->t_nodesize > 0 ?
+ getbytes(tree->t_nodesize) : preexisting)))
+ {
+ if (tree->t_nodesize == 0)
+ loudbug_bug("qtree_insert, node not supplied");
return (0);
+ }
np->n_key = key;
np->n_parent = parent;
if (leftchild)
@@ -440,7 +452,8 @@ void qtree_delete(t_qtree *tree, t_qnode *gone)
of gone's parent (if any). Successor always exists in this context,
and it has no left child. The simplistic scheme is to replace
gone's fields with successor's fields, and delete the successor.
- We cannot do so, however, because successor may be pointed at... */
+ We cannot do so, however, because 1. nodes may be caller-owned
+ (nodesize == 0), 2. successor may be pointed at... */
t_qnode *successor = gone->n_next;
child = successor->n_right;
successor->n_left = gone->n_left;
@@ -624,7 +637,8 @@ void qtree_delete(t_qtree *tree, t_qnode *gone)
child->n_black = 1;
}
done:
- freebytes(gone, tree->t_nodesize);
+ if (tree->t_nodesize)
+ freebytes(gone, tree->t_nodesize);
#ifdef QTREE_DEBUG
qtree_verify(tree);
#endif
@@ -638,41 +652,189 @@ t_qnode *qtree_search(t_qtree *tree, double key)
return (np);
}
-t_qnode *qtree_closest(t_qtree *tree, double key, int geqflag)
+/* Returns the greatest node <= key, if any (may return null).
+ If deltap is not null, it will hold the abs diff (key - node.n_key). */
+t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap)
{
t_qnode *np, *parent;
if (!(np = tree->t_root))
return (0);
do
if (np->n_key == key)
+ {
+ if (deltap)
+ *deltap = 0.;
return (np);
- else
- parent = np;
+ }
+ else parent = np;
+ while (np = (key < np->n_key ? np->n_left : np->n_right));
+ if (np = (key < parent->n_key ? parent->n_prev : parent))
+ {
+ if (deltap)
+ *deltap = key - np->n_key;
+ return (np);
+ }
+ else return (0);
+}
+
+/* Returns the smallest node >= key, if any (may return null).
+ If deltap is not null, it will hold the abs diff (node.n_key - key). */
+t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap)
+{
+ t_qnode *np, *parent;
+ if (!(np = tree->t_root))
+ return (0);
+ do
+ if (np->n_key == key)
+ {
+ if (deltap)
+ *deltap = 0.;
+ return (np);
+ }
+ else parent = np;
while (np = (key < np->n_key ? np->n_left : np->n_right));
- if (geqflag)
- return (key > parent->n_key ? parent->n_next : parent);
+ if (np = (key > parent->n_key ? parent->n_next : parent))
+ {
+ if (deltap)
+ *deltap = np->n_key - key;
+ return (np);
+ }
+ else return (0);
+}
+
+/* Returns the smallest node >= key or the greatest node <= key, whichever
+ makes the smallest abs diff, |key - node.n_key|. Returns null only for
+ an empty tree. If deltap is not null, it will hold the signed diff
+ (negative for an undernode, i.e. when node < key). */
+t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap)
+{
+ t_qnode *np, *parent;
+ if (!(np = tree->t_root))
+ return (0);
+ do
+ if (np->n_key == key)
+ {
+ if (deltap)
+ *deltap = 0.;
+ return (np);
+ }
+ else parent = np;
+ while (np = (key < np->n_key ? np->n_left : np->n_right));
+ if (key > parent->n_key)
+ {
+ if (np = parent->n_next)
+ {
+ double delta1 = key - parent->n_key;
+ double delta2 = np->n_key - key;
+ if (delta1 < delta2)
+ {
+ if (deltap)
+ *deltap = -delta1;
+ return (parent);
+ }
+ else
+ {
+ if (deltap)
+ *deltap = delta2;
+ return (np);
+ }
+ }
+ else
+ {
+ if (deltap)
+ *deltap = parent->n_key - key;
+ return (parent);
+ }
+ }
else
- return (key < parent->n_key ? parent->n_prev : parent);
+ {
+ if (np = parent->n_prev)
+ {
+ double delta1 = key - np->n_key;
+ double delta2 = parent->n_key - key;
+ if (delta1 < delta2)
+ {
+ if (deltap)
+ *deltap = -delta1;
+ return (np);
+ }
+ else
+ {
+ if (deltap)
+ *deltap = delta2;
+ return (parent);
+ }
+ }
+ else
+ {
+ if (deltap)
+ *deltap = parent->n_key - key;
+ return (parent);
+ }
+ }
}
-t_qnode *qtree_insert(t_qtree *tree, double key, int *foundp)
+t_qnode *qtree_insert(t_qtree *tree, double key,
+ t_qnode *preexisting, int *foundp)
{
- return (qtree_doinsert(tree, key, 0, foundp));
+ int found;
+ return (qtree_doinsert(tree, key, preexisting, 0,
+ (foundp ? foundp : &found)));
}
-t_qnode *qtree_multiinsert(t_qtree *tree, double key, int fifoflag)
+t_qnode *qtree_multiinsert(t_qtree *tree, double key,
+ t_qnode *preexisting, int fifoflag)
{
int found;
- return (qtree_doinsert(tree, key, (fifoflag ?
- qtree_postinserthook :
- qtree_preinserthook), &found));
+ return (qtree_doinsert(tree, key, preexisting,
+ (fifoflag ?
+ qtree_postinserthook :
+ qtree_preinserthook), &found));
+}
+
+t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode)
+{
+ if (tree->t_nodesize)
+ {
+ loudbug_bug("qtree_override 1");
+ return (0);
+ }
+ else
+ {
+ newnode->n_key = oldnode->n_key;
+ newnode->n_black = oldnode->n_black;
+ if (newnode->n_left = oldnode->n_left)
+ newnode->n_left->n_parent = newnode;
+ if (newnode->n_right = oldnode->n_right)
+ newnode->n_right->n_parent = newnode;
+ if (newnode->n_parent = oldnode->n_parent)
+ {
+ if (oldnode == newnode->n_parent->n_left)
+ newnode->n_parent->n_left = newnode;
+ else if (oldnode == newnode->n_parent->n_right)
+ newnode->n_parent->n_right = newnode;
+ else
+ loudbug_bug("qtree_override 2");
+ }
+ if (newnode->n_prev = oldnode->n_prev)
+ newnode->n_prev->n_next = newnode;
+ if (newnode->n_next = oldnode->n_next)
+ newnode->n_next->n_prev = newnode;
+ if (tree->t_root == oldnode)
+ tree->t_root = newnode;
+ if (tree->t_first == oldnode)
+ tree->t_first = newnode;
+ if (tree->t_last == oldnode)
+ tree->t_last = newnode;
+ return (newnode);
+ }
}
t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f,
int replaceflag)
{
int found;
- t_qnode *np = qtree_doinsert(tree, key, 0, &found);
+ t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found);
if (np && (!found || replaceflag))
{
if (tree->t_valuetype == QTREETYPE_FLOAT)
@@ -695,7 +857,7 @@ t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s,
int replaceflag)
{
int found;
- t_qnode *np = qtree_doinsert(tree, key, 0, &found);
+ t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found);
if (np && (!found || replaceflag))
{
if (tree->t_valuetype == QTREETYPE_SYMBOL)
@@ -718,7 +880,7 @@ t_qnode *qtree_insertatom(t_qtree *tree, double key, t_atom *ap,
int replaceflag)
{
int found;
- t_qnode *np = qtree_doinsert(tree, key, 0, &found);
+ t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found);
if (np && (!found || replaceflag))
{
if (tree->t_valuetype == QTREETYPE_ATOM)
@@ -771,11 +933,11 @@ void qtree_initcustom(t_qtree *tree, size_t nodesize, int freecount)
void qtree_clear(t_qtree *tree, int freecount)
{
t_qnode *np, *next = tree->t_first;
- while (next)
+ while (np = next)
{
- np = next;
next = next->n_next;
- freebytes(np, tree->t_nodesize);
+ if (tree->t_nodesize)
+ freebytes(np, tree->t_nodesize);
}
qtree_doinit(tree, tree->t_valuetype, tree->t_nodesize, 0);
}
diff --git a/shared/common/qtree.h b/shared/common/qtree.h
index 97c2906..18e4098 100644
--- a/shared/common/qtree.h
+++ b/shared/common/qtree.h
@@ -60,10 +60,15 @@ typedef struct _qtree
typedef void (*t_qnode_vshowhook)(t_qnode *, char *, unsigned);
t_qnode *qtree_search(t_qtree *tree, double key);
-t_qnode *qtree_closest(t_qtree *tree, double key, int geqflag);
+t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap);
+t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap);
+t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap);
-t_qnode *qtree_insert(t_qtree *tree, double key, int *foundp);
-t_qnode *qtree_multiinsert(t_qtree *tree, double key, int fifoflag);
+t_qnode *qtree_insert(t_qtree *tree, double key,
+ t_qnode *preexisting, int *foundp);
+t_qnode *qtree_multiinsert(t_qtree *tree, double key,
+ t_qnode *preexisting, int fifoflag);
+t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode);
t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f,
int replaceflag);
t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s,
diff --git a/shared/getridof.baddeps b/shared/getridof.baddeps
index 7286cd6..2886622 100644
--- a/shared/getridof.baddeps
+++ b/shared/getridof.baddeps
@@ -3,8 +3,10 @@ Some are inevitable, but others can, and should be removed.
unstable/fragile -> common/loud
unstable/fringe -> unstable/forky
+unstable/loader -> common/os common/loud
common/props -> common/grow common/loud
common/vefl -> common/loud, unstable/fragile
+common/messtree -> common/loud
common/qtree -> common/loud
common/binport -> common/lex
common/port -> common/loud, common/grow, common/binport,
@@ -14,6 +16,7 @@ sickle/sic -> common/loud
sickle/arsic -> common/loud, common/vefl, sickle/sic, unstable/fragile
toxy/plusbob -> common/loud
toxy/scriptlet -> common/loud, common/grow, common/props
-xeq/squ* -> common/loud, common/fi, common/mifi, common/qtree, xeq/squ*
+xeq/squ* -> common/loud, common/dict, common/qtree, common/messtree,
+ common/mifi, xeq/squ*
vex/hyphen -> common/dict
vex/sofi -> vex/bifi
diff --git a/shared/hammer/gui.c b/shared/hammer/gui.c
index 388b14b..104af3a 100644
--- a/shared/hammer/gui.c
+++ b/shared/hammer/gui.c
@@ -4,6 +4,10 @@
/* FIXME use guiconnect */
+/* LATER revisit tracking the mouse state within the focusless pd-gui
+ (event bindings are local only in tk8.4, and there is no other call
+ to XQueryPointer() but from winfo pointer). */
+
#include <stdio.h>
#include <string.h>
#include "m_pd.h"
diff --git a/shared/notes.txt b/shared/notes.txt
index a823fad..43f4867 100644
--- a/shared/notes.txt
+++ b/shared/notes.txt
@@ -1,10 +1,29 @@
TODO for root and shared
* fitter: abstraction-scoped, class-selective compatibility control
- * fitter: mode list
+ * fitter: fittterstate map
* hammerfile, hammergui: version control
DONE for root and shared
+with cyclone alpha55
+ * new module: messtree
+ * qtree:
+ . nodes of a custom tree may be caller-owned: a caller may pass 0 as
+ nodesize to qtree_initcustom() and pass pre-allocated nodes to
+ insert/multiinsert calls
+ . new calls: qtree_override(), qtree_closestunder(), qtree_closestover()
+ . all "closest" calls report a diff between key requested and key found
+ * os: new calls (dummy under MSW, though): osdir_open(), osdir_setmode(),
+ osdir_close(), osdir_rewind(), osdir_next(), osdir_isfile(), osdir_isdir()
+ * loader: new calls, unstable_dirload_lib(), unstable_dirload_all()
+ * fitter:
+ . added "test" hook (as a first step towards a fittterstate map)
+ . new calls: fitter_getfloat(), fitter_getsymbol()
+ * fragile: new call fragile_class_getexterndir()
+ * loud: loud_syserror() accepts a format string
+ * support for building into subdirectory of the main bin directory
+ (so that a library may automatically load all its plugin externals)
+
with toxy alpha18
* plusbob: stubifying t_plusbob, in order to minimize memory leak to 4 words
diff --git a/shared/shared.h b/shared/shared.h
index a812ffe..0e60dbd 100644
--- a/shared/shared.h
+++ b/shared/shared.h
@@ -164,8 +164,21 @@ typedef union _shared_floatint
#define SHARED_2PI 6.28318530718
#ifndef PD_BADFLOAT
+#ifdef __i386__
#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
(((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
+#else
+#define PD_BADFLOAT(f) 0
+#endif
+#endif
+
+#ifndef PD_BIGORSMALL
+#ifdef __i386__
+#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
+ (((*(unsigned int*)&(f))&0x60000000)==0x60000000))
+#else
+#define PD_BIGORSMALL(f) 0
+#endif
#endif
#endif
diff --git a/shared/unstable/fragile.c b/shared/unstable/fragile.c
index e65e6d4..82d5065 100644
--- a/shared/unstable/fragile.c
+++ b/shared/unstable/fragile.c
@@ -10,6 +10,12 @@
#include "unstable/pd_imp.h"
#include "unstable/fragile.h"
+/* this one rather belongs to fringe.c... */
+t_symbol *fragile_class_getexterndir(t_class *c)
+{
+ return (c->c_externdir);
+}
+
int fragile_class_count(void)
{
return (pd_objectmaker->c_nmethod);
diff --git a/shared/unstable/fragile.h b/shared/unstable/fragile.h
index 1e2ea0e..9a5587d 100644
--- a/shared/unstable/fragile.h
+++ b/shared/unstable/fragile.h
@@ -5,6 +5,7 @@
#ifndef __FRAGILE_H__
#define __FRAGILE_H__
+t_symbol *fragile_class_getexterndir(t_class *c);
int fragile_class_count(void);
int fragile_class_getnames(t_atom *av, int maxnames);
void fragile_class_raise(t_symbol *cname, t_newmethod thiscall);
diff --git a/shared/unstable/loader.c b/shared/unstable/loader.c
index 91b7ff3..4872500 100644
--- a/shared/unstable/loader.c
+++ b/shared/unstable/loader.c
@@ -1,12 +1,10 @@
-/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others.
+/* Copyright (c) 1997-2005 Miller Puckette, 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 is just a not-yet-in-the-API-sys_load_lib() duplication
(modulo differentiating the error return codes). LATER use the original. */
-#include "loader.h"
-
#ifdef __linux__
#include <dlfcn.h>
#endif
@@ -22,8 +20,11 @@
#include <mach-o/dyld.h>
#endif
#include <string.h>
-#include "m_pd.h"
#include <stdio.h>
+#include "m_pd.h"
+#include "common/loud.h"
+#include "common/os.h"
+#include "loader.h"
typedef void (*t_xxx)(void);
@@ -48,92 +49,175 @@ static char sys_dllextent[] =
".dll";
#endif
-int unstable_load_lib(char *dirname, char *classname)
+static int unstable_doload_lib(char *dirname, char *classname)
{
- char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING],
- *nameptr, *lastdot;
+ char symname[MAXPDSTRING], filename[MAXPDSTRING], *lastdot;
void *dlobj;
t_xxx makeout;
- int fd;
#ifdef NT
HINSTANCE ntdll;
#endif
-#if 0
- fprintf(stderr, "lib %s %s\n", dirname, classname);
-#endif
- if ((fd = open_via_path(dirname, classname, sys_dllextent,
- dirbuf, &nameptr, MAXPDSTRING, 1)) < 0)
- {
- return (LOADER_NOFILE);
- }
- else
- {
- close(fd);
- /* refabricate the pathname */
- strcpy(filename, dirbuf);
- strcat(filename, "/");
- strcat(filename, nameptr);
- /* extract the setup function name */
- if (lastdot = strrchr(nameptr, '.'))
- *lastdot = 0;
+ /* refabricate the pathname */
+ strcpy(filename, dirname);
+ strcat(filename, "/");
+ strcat(filename, classname);
+ /* extract the setup function name */
+ if (lastdot = strrchr(classname, '.'))
+ *lastdot = 0;
#ifdef MACOSX
- strcpy(symname, "_");
- strcat(symname, nameptr);
+ strcpy(symname, "_");
+ strcat(symname, classname);
#else
- strcpy(symname, nameptr);
+ strcpy(symname, classname);
#endif
- /* if the last character is a tilde, replace with "_tilde" */
- if (symname[strlen(symname) - 1] == '~')
- strcpy(symname + (strlen(symname) - 1), "_tilde");
- /* and append _setup to form the C setup function name */
- strcat(symname, "_setup");
+ /* if the last character is a tilde, replace with "_tilde" */
+ if (symname[strlen(symname) - 1] == '~')
+ strcpy(symname + (strlen(symname) - 1), "_tilde");
+ /* and append _setup to form the C setup function name */
+ strcat(symname, "_setup");
#ifdef __linux__
- dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
- if (!dlobj)
- {
- post("%s: %s", filename, dlerror());
- return (LOADER_BADFILE);
- }
- makeout = (t_xxx)dlsym(dlobj, symname);
+ dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
+ if (!dlobj)
+ {
+ post("%s: %s", filename, dlerror());
+ return (LOADER_BADFILE);
+ }
+ makeout = (t_xxx)dlsym(dlobj, symname);
#endif
#ifdef NT
- sys_bashfilename(filename, filename);
- ntdll = LoadLibrary(filename);
- if (!ntdll)
- {
+ sys_bashfilename(filename, filename);
+ ntdll = LoadLibrary(filename);
+ if (!ntdll)
+ {
+ post("%s: couldn't load", filename);
+ return (LOADER_BADFILE);
+ }
+ makeout = (t_xxx)GetProcAddress(ntdll, symname);
+#endif
+#ifdef MACOSX
+ {
+ NSObjectFileImage image;
+ void *ret;
+ NSSymbol s;
+ if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess )
+ {
post("%s: couldn't load", filename);
return (LOADER_BADFILE);
}
- makeout = (t_xxx)GetProcAddress(ntdll, symname);
-#endif
-#ifdef MACOSX
- {
- NSObjectFileImage image;
- void *ret;
- NSSymbol s;
- if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess )
- {
- post("%s: couldn't load", filename);
- return (LOADER_BADFILE);
- }
- ret = NSLinkModule( image, filename,
- NSLINKMODULE_OPTION_BINDNOW
- + NSLINKMODULE_OPTION_PRIVATE);
+ ret = NSLinkModule( image, filename,
+ NSLINKMODULE_OPTION_BINDNOW
+ + NSLINKMODULE_OPTION_PRIVATE);
- s = NSLookupSymbolInModule(ret, symname);
+ s = NSLookupSymbolInModule(ret, symname);
- if (s)
- makeout = (t_xxx)NSAddressOfSymbol( s);
- else makeout = 0;
- }
-#endif
+ if (s)
+ makeout = (t_xxx)NSAddressOfSymbol( s);
+ else makeout = 0;
}
+#endif
if (!makeout)
{
- post("load_object: Symbol \"%s\" not found", symname);
- return (LOADER_NOENTRY);
+ post("load_object: Symbol \"%s\" not found", symname);
+ return (LOADER_NOENTRY);
}
(*makeout)();
return (LOADER_OK);
}
+
+/* start searching from dirname, then search the path */
+int unstable_load_lib(char *dirname, char *classname)
+{
+ char dirbuf[MAXPDSTRING], *nameptr;
+ int fd;
+ if ((fd = open_via_path(dirname, classname, sys_dllextent,
+ dirbuf, &nameptr, MAXPDSTRING, 1)) < 0)
+ {
+ return (LOADER_NOFILE);
+ }
+ else
+ {
+ close(fd);
+ return (unstable_doload_lib(dirbuf, nameptr));
+ }
+}
+
+/* only dirname is searched */
+int unstable_dirload_lib(char *dirname, char *classname)
+{
+ if (strlen(dirname) + strlen(classname) + strlen(sys_dllextent) + 3 <
+ MAXPDSTRING)
+ {
+ char namebuf[MAXPDSTRING], *slash, *nameptr;
+ strcpy(namebuf, dirname);
+ if (*dirname && namebuf[strlen(namebuf)-1] != '/')
+ strcat(namebuf, "/");
+ strcat(namebuf, classname);
+ strcat(namebuf, sys_dllextent);
+ slash = strrchr(namebuf, '/');
+ if (slash)
+ {
+ *slash = 0;
+ nameptr = slash + 1;
+ }
+ else nameptr = namebuf;
+ return (unstable_doload_lib(namebuf, nameptr));
+ }
+ else return (LOADER_FAILED);
+}
+
+/* return the number of successfully loaded libraries, or -1 on error */
+int unstable_dirload_all(char *dirname, int beloud, int withclasses)
+{
+ t_osdir *dp = osdir_open(dirname);
+ if (dp)
+ {
+ int result = 0;
+ char namebuf[MAXPDSTRING], *name;
+ osdir_setmode(dp, OSDIR_FILEMODE);
+ while (name = osdir_next(dp))
+ {
+ int namelen = strlen(name), extlen = strlen(sys_dllextent);
+ if ((namelen -= extlen) > 0 &&
+ strcmp(name + namelen, sys_dllextent) == 0)
+ {
+ strncpy(namebuf, name, namelen);
+ namebuf[namelen] = 0;
+ if (zgetfn(&pd_objectmaker, gensym(namebuf)))
+ {
+ if (beloud)
+ loud_warning(0, "xeq", "plugin \"%s\" already loaded",
+ namebuf);
+ }
+ else
+ {
+ int err;
+ if (beloud)
+ post("loading xeq plugin \"%s\"", namebuf);
+ err = unstable_dirload_lib(dirname, namebuf);
+ if (err == LOADER_NOFILE)
+ {
+ if (beloud)
+ loud_error(0, "xeq plugin \"%s\" disappeared",
+ namebuf);
+ }
+ else if (!zgetfn(&pd_objectmaker, gensym(namebuf)))
+ {
+ if (beloud)
+ loud_error(0, "library \"%s\" not compatible",
+ namebuf);
+ }
+ else result++;
+ }
+ }
+ }
+ osdir_close(dp);
+ return (result);
+ }
+ else
+ {
+ if (beloud)
+ loud_syserror(0, "cannot open \"%s\"", dirname);
+ return (-1);
+ }
+}
diff --git a/shared/unstable/loader.h b/shared/unstable/loader.h
index e9766ac..7c18036 100644
--- a/shared/unstable/loader.h
+++ b/shared/unstable/loader.h
@@ -1,12 +1,15 @@
-/* Copyright (c) 2003 krzYszcz and others.
+/* Copyright (c) 2003-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. */
#ifndef __LOADER_H__
#define __LOADER_H__
-enum { LOADER_OK, LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY };
+enum { LOADER_OK, LOADER_FAILED,
+ LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY };
int unstable_load_lib(char *dirname, char *classname);
+int unstable_dirload_lib(char *dirname, char *classname);
+int unstable_dirload_all(char *dirname, int beloud, int withclasses);
#endif