From 0026d4caf3df60ba961576283f6bc5932bddd208 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 3 Feb 2006 17:10:35 +0000 Subject: I backported [list] from 0.39.2, you have to load it as library to make it work properly svn path=/trunk/; revision=4541 --- externals/build/src/list.c | 421 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 externals/build/src/list.c (limited to 'externals/build') diff --git a/externals/build/src/list.c b/externals/build/src/list.c new file mode 100644 index 00000000..a90a7783 --- /dev/null +++ b/externals/build/src/list.c @@ -0,0 +1,421 @@ +/* Copyright (c) 1997- Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +/* #include */ +#ifdef _WIN32 +#include +#else +#include +#endif + +extern t_pd *newest; + +#define HAVE_ALLOCA 1 /* LATER this should be set by configure script! */ +#define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */ + +/* the "list" object family. + + list append - append a list to another + list prepend - prepend a list to another + list split - first n elements to first outlet, rest to second outlet + list trim - trim off "list" selector + list length - output number of items in list + list nth - nth item in list, counting from zero + +Not sure we need these: + list cat - build a list by accumulating elements + list foreach - spit out elements of a list one by one + list array - get items from a named array as a list + list reverse - permute elements of a list back to front + list pack - synonym for 'pack' + list unpack - synonym for 'unpack' + list first - output first n elements. + list last - output last n elements +*/ + +/* -------------- utility functions: storage, copying -------------- */ + /* List element for storage. Keep an atom and, in case it's a pointer, + an associated 'gpointer' to protect against stale pointers. */ +typedef struct _listelem +{ + t_atom l_a; + t_gpointer l_p; +} t_listelem; + +typedef struct _alist +{ + t_pd l_pd; /* object to point inlets to */ + int l_n; /* number of items */ + t_listelem *l_vec; /* pointer to items */ +} t_alist; + +#if 0 /* probably won't use this version... */ +#ifdef HAVE_ALLOCA +#define LIST_ALLOCA(x, n) ( \ + (x).l_n = (n), \ + (x).l_vec = (t_listelem *)((n) < LIST_NGETBYTE ? \ + alloca((n) * sizeof(t_listelem)) : getbytes((n) * sizeof(t_listelem)))) \ +#define LIST_FREEA(x) ( \ + ((x).l_n < LIST_NGETBYTE || + (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem)), 0))) + +#else +#define LIST_ALLOCA(x, n) ( \ + (x).l_n = (n), \ + (x).l_vec = (t_listelem *)getbytes((n) * sizeof(t_listelem))) +#define LIST_FREEA(x) (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem))) +#endif +#endif + +#if HAVE_ALLOCA +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + +static void atoms_copy(int argc, t_atom *from, t_atom *to) +{ + int i; + for (i = 0; i < argc; i++) + to[i] = from[i]; +} + +/* ------------- fake class to divert inlets to ----------------- */ + +t_class *alist_class; + +static void alist_init(t_alist *x) +{ + x->l_pd = alist_class; + x->l_n = 0; + x->l_vec = 0; +} + +static void alist_clear(t_alist *x) +{ + int i; + for (i = 0; i < x->l_n; i++) + { + if (x->l_vec[i].l_a.a_type == A_POINTER) + gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer); + } + if (x->l_vec) + freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec)); +} + +static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + alist_clear(x); + if (!(x->l_vec = (t_listelem *)getbytes(argc * sizeof(*x->l_vec)))) + { + x->l_n = 0; + error("list_alloc: out of memory"); + return; + } + x->l_n = argc; + for (i = 0; i < argc; i++) + { + x->l_vec[i].l_a = argv[i]; + if (x->l_vec[i].l_a.a_type == A_POINTER) + gpointer_copy(x->l_vec[i].l_a.a_w.w_gpointer, &x->l_vec[i].l_p); + } +} + +static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + alist_clear(x); + if (!(x->l_vec = (t_listelem *)getbytes((argc+1) * sizeof(*x->l_vec)))) + { + x->l_n = 0; + error("list_alloc: out of memory"); + return; + } + x->l_n = argc+1; + SETSYMBOL(&x->l_vec[0].l_a, s); + for (i = 0; i < argc; i++) + { + x->l_vec[i+1].l_a = argv[i]; + if (x->l_vec[i+1].l_a.a_type == A_POINTER) + gpointer_copy(x->l_vec[i+1].l_a.a_w.w_gpointer, &x->l_vec[i+1].l_p); + } +} + +static void alist_toatoms(t_alist *x, t_atom *to) +{ + int i; + for (i = 0; i < x->l_n; i++) + to[i] = x->l_vec[i].l_a; +} + +static void alist_setup(void) +{ + alist_class = class_new(gensym("list inlet"), + 0, 0, sizeof(t_alist), 0, 0); + class_addlist(alist_class, alist_list); + class_addanything(alist_class, alist_anything); +} + +/* ------------- list append --------------------- */ + +t_class *list_append_class; + +typedef struct _list_append +{ + t_object x_obj; + t_alist x_alist; +} t_list_append; + +static void *list_append_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_append *x = (t_list_append *)pd_new(list_append_class); + alist_init(&x->x_alist); + alist_list(&x->x_alist, 0, argc, argv); + outlet_new(&x->x_obj, &s_list); + inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0); + return (x); +} + +static void list_append_list(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc; + ATOMS_ALLOCA(outv, outc); + atoms_copy(argc, argv, outv); + alist_toatoms(&x->x_alist, outv+argc); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void list_append_anything(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc + 1; + ATOMS_ALLOCA(outv, outc); + SETSYMBOL(outv, s); + atoms_copy(argc, argv, outv + 1); + alist_toatoms(&x->x_alist, outv + 1 + argc); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void list_append_free(t_list_append *x) +{ + alist_clear(&x->x_alist); +} + +static void list_append_setup(void) +{ + list_append_class = class_new(gensym("list append"), + (t_newmethod)list_append_new, (t_method)list_append_free, + sizeof(t_list_append), 0, A_GIMME, 0); + class_addlist(list_append_class, list_append_list); + class_addanything(list_append_class, list_append_anything); + class_sethelpsymbol(list_append_class, &s_list); +} + +/* ------------- list prepend --------------------- */ + +t_class *list_prepend_class; + +typedef struct _list_prepend +{ + t_object x_obj; + t_alist x_alist; +} t_list_prepend; + +static void *list_prepend_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_prepend *x = (t_list_prepend *)pd_new(list_prepend_class); + alist_init(&x->x_alist); + alist_list(&x->x_alist, 0, argc, argv); + outlet_new(&x->x_obj, &s_list); + inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0); + return (x); +} + +static void list_prepend_list(t_list_prepend *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc; + ATOMS_ALLOCA(outv, outc); + alist_toatoms(&x->x_alist, outv); + atoms_copy(argc, argv, outv + x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void list_prepend_anything(t_list_prepend *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc + 1; + ATOMS_ALLOCA(outv, outc); + alist_toatoms(&x->x_alist, outv); + SETSYMBOL(outv + x->x_alist.l_n, s); + atoms_copy(argc, argv, outv + x->x_alist.l_n + 1); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void list_prepend_free(t_list_prepend *x) +{ + alist_clear(&x->x_alist); +} + +static void list_prepend_setup(void) +{ + list_prepend_class = class_new(gensym("list prepend"), + (t_newmethod)list_prepend_new, (t_method)list_prepend_free, + sizeof(t_list_prepend), 0, A_GIMME, 0); + class_addlist(list_prepend_class, list_prepend_list); + class_addanything(list_prepend_class, list_prepend_anything); + class_sethelpsymbol(list_prepend_class, &s_list); +} + +/* ------------- list split --------------------- */ + +t_class *list_split_class; + +typedef struct _list_split +{ + t_object x_obj; + t_float x_f; + t_outlet *x_out1; + t_outlet *x_out2; + t_outlet *x_out3; +} t_list_split; + +static void *list_split_new(t_floatarg f) +{ + t_list_split *x = (t_list_split *)pd_new(list_split_class); + x->x_out1 = outlet_new(&x->x_obj, &s_list); + x->x_out2 = outlet_new(&x->x_obj, &s_list); + x->x_out3 = outlet_new(&x->x_obj, &s_list); + floatinlet_new(&x->x_obj, &x->x_f); + x->x_f = f; + return (x); +} + +static void list_split_list(t_list_split *x, t_symbol *s, + int argc, t_atom *argv) +{ + int n = x->x_f; + if (n < 0) + n = 0; + if (argc >= n) + { + outlet_list(x->x_out2, &s_list, argc-n, argv+n); + outlet_list(x->x_out1, &s_list, n, argv); + } + else outlet_list(x->x_out3, &s_list, argc, argv); +} + +static void list_split_anything(t_list_split *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + ATOMS_ALLOCA(outv, argc+1); + SETSYMBOL(outv, s); + atoms_copy(argc, argv, outv + 1); + list_split_list(x, &s_list, argc+1, outv); + ATOMS_FREEA(outv, argc+1); +} + +static void list_split_setup(void) +{ + list_split_class = class_new(gensym("list split"), + (t_newmethod)list_split_new, 0, + sizeof(t_list_split), 0, A_DEFFLOAT, 0); + class_addlist(list_split_class, list_split_list); + class_addanything(list_split_class, list_split_anything); + class_sethelpsymbol(list_split_class, &s_list); +} + +/* ------------- list trim --------------------- */ + +t_class *list_trim_class; + +typedef struct _list_trim +{ + t_object x_obj; +} t_list_trim; + +static void *list_trim_new( void) +{ + t_list_trim *x = (t_list_trim *)pd_new(list_trim_class); + outlet_new(&x->x_obj, &s_list); + return (x); +} + +static void list_trim_list(t_list_trim *x, t_symbol *s, + int argc, t_atom *argv) +{ + if (argc < 1 || argv[0].a_type != A_SYMBOL) + outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv); + else outlet_anything(x->x_obj.ob_outlet, argv[0].a_w.w_symbol, + argc-1, argv+1); +} + +static void list_trim_anything(t_list_trim *x, t_symbol *s, + int argc, t_atom *argv) +{ + outlet_anything(x->x_obj.ob_outlet, s, argc, argv); +} + +static void list_trim_setup(void) +{ + list_trim_class = class_new(gensym("list trim"), + (t_newmethod)list_trim_new, 0, + sizeof(t_list_trim), 0, 0); + class_addlist(list_trim_class, list_trim_list); + class_addanything(list_trim_class, list_trim_anything); + class_sethelpsymbol(list_trim_class, &s_list); +} + +/* ------------- list ------------------- */ + +static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + if (!argc || argv[0].a_type != A_SYMBOL) + newest = list_append_new(s, argc, argv); + else + { + t_symbol *s2 = argv[0].a_w.w_symbol; + if (s2 == gensym("append")) + newest = list_append_new(s, argc-1, argv+1); + else if (s2 == gensym("prepend")) + newest = list_prepend_new(s, argc-1, argv+1); + else if (s2 == gensym("split")) + newest = list_split_new(atom_getfloatarg(1, argc, argv)); + else if (s2 == gensym("trim")) + newest = list_trim_new(); + else + { + error("list %s: unknown function", s2->s_name); + newest = 0; + } + } + return (newest); +} + +void list_setup(void) +{ + alist_setup(); + list_append_setup(); + list_prepend_setup(); + list_split_setup(); + list_trim_setup(); + class_addcreator((t_newmethod)list_new, &s_list, A_GIMME, 0); + post("Info: this [list] has been backported from Pd 0.39.2"); +} -- cgit v1.2.1