diff options
Diffstat (limited to 'src/arguments.c')
-rw-r--r-- | src/arguments.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/arguments.c b/src/arguments.c new file mode 100644 index 0000000..c5ba961 --- /dev/null +++ b/src/arguments.c @@ -0,0 +1,152 @@ + + + #include "m_pd.h" + +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) + +#define TOKEN 0 +#define COMMA 1 +#define ALL 2 + +static t_class *arguments_class; + + +typedef struct _arguments +{ + t_object x_obj; + t_outlet* outlet; + t_canvas* canvas; + t_symbol* s_comma; + int mode; + char token; + int size; + int ac; + t_atom* av; +} t_arguments; + + +// Prepends the proper selector +static void arguments_output(t_outlet* o, int argc, t_atom* argv) { + + if (!argc) outlet_bang(o); + else if (IS_A_SYMBOL(argv,0)) outlet_anything(o,atom_getsymbol(argv),argc-1,argv+1); + else if (IS_A_FLOAT(argv,0) && argc==1) outlet_float(o,atom_getfloat(argv)); + else outlet_anything(o,&s_list,argc,argv); +} + + +static int next_token(char tag, int ac, t_atom *av, int* ac_a, t_atom ** av_a, int* iter) { + int i; + + if ( ac == 0 || *iter >= ac) { + *ac_a = 0; + *av_a = NULL; + return 0; + } + + for ( i= *iter + 1; i < ac; i++ ) { + if ( (av+i)->a_type == A_SYMBOL + && (atom_getsymbol(av+i))->s_name[0] == tag) break; + } + *ac_a = i - *iter; + *av_a = av + *iter; + *iter = i; + + return (*ac_a); +} + +// Dump arguments +static void arguments_bang(t_arguments *x) { + + + + + if ( x->mode == TOKEN ) { + int ac_a; + t_atom* av_a; + t_symbol* selector_a; + int iter = 0 ; + while ( next_token(x->token, x->ac, x->av, &ac_a, &av_a,&iter)) { + arguments_output(x->outlet,ac_a,av_a); + } + } else if (x->mode == COMMA) { + // we are trusting the system that the commas are split from the + // neighboring floats and symbols + int ac = x->ac; + t_atom* av = x->av; + t_symbol* selector; + + int i =0; + int j; + for (j=0; j<ac; j++) { + if ( (IS_A_SYMBOL(av,j) && atom_getsymbol(av+j)==x->s_comma ) ) { + if ( (j != i) ) arguments_output(x->outlet, j - i, av+i); + + i = j+1; + } + } + // Output any leftovers + if ( j != i) arguments_output(x->outlet, ac-i, av+i); + } else { //x->mode = ALL + arguments_output(x->outlet, x->ac, x->av); + } +} + + +static void arguments_free(t_arguments *x) +{ + freebytes(x->av,x->ac*sizeof(*(x->av))); +} + +static void copy_atoms(t_atom *src, t_atom *dst, int n) +{ + while(n--) + *dst++ = *src++; +} + + + +static void *arguments_new(t_symbol *selector, int argc, t_atom* argv) { + t_arguments *x = (t_arguments *)pd_new(arguments_class); + + x->s_comma = gensym(","); + + if ( argc && IS_A_SYMBOL(argv,0) ) { + t_symbol* s = atom_getsymbol(argv); + if ( s == gensym("comma") || s == x->s_comma ) { + x->mode = COMMA; + post("COMMA"); + } else { + x->mode = TOKEN; + x->token = s->s_name[0]; + post("TOKEN: %c",x->token); + } + } else { + post("ALL"); + x->mode = ALL; + } + + + int ac; + t_atom* av; + canvas_getargs(&ac, &av); + + x->ac = ac; + x->av = getbytes(x->ac * sizeof(*(x->av))); + copy_atoms(av,x->av,x->ac); + + x->outlet = outlet_new(&x->x_obj, &s_anything); + + return (x); +} + +void arguments_setup(void) { + arguments_class = class_new(gensym("arguments"), + (t_newmethod)arguments_new, (t_method)arguments_free, + sizeof(t_arguments), 0, A_GIMME, 0); + + class_addbang(arguments_class, arguments_bang); + + +} |