[PD-cvs] pd/src kernel.c, 1.1.2.9, 1.1.2.10 makefile.in, 1.4.4.2.2.21.2.15, 1.4.4.2.2.21.2.16 m_class.c, 1.3.4.7.2.22.2.17, NONE

Mathieu Bouchard matju at users.sourceforge.net
Thu Dec 28 01:30:44 CET 2006


Update of /cvsroot/pure-data/pd/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9536

Modified Files:
      Tag: desiredata
	kernel.c makefile.in 
Removed Files:
      Tag: desiredata
	m_class.c 
Log Message:
m_class.c merged into kernel.c


Index: makefile.in
===================================================================
RCS file: /cvsroot/pure-data/pd/src/makefile.in,v
retrieving revision 1.4.4.2.2.21.2.15
retrieving revision 1.4.4.2.2.21.2.16
diff -C2 -d -r1.4.4.2.2.21.2.15 -r1.4.4.2.2.21.2.16
*** makefile.in	20 Dec 2006 06:24:18 -0000	1.4.4.2.2.21.2.15
--- makefile.in	28 Dec 2006 00:30:42 -0000	1.4.4.2.2.21.2.16
***************
*** 29,33 ****
  
  # from pd miller
! SRC += m_class.c m_binbuf.c m_sched.c \
         s_main.c s_inter.c s_loader.c s_path.c s_audio.c s_midi.c \
         d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
--- 29,33 ----
  
  # from pd miller
! SRC += m_binbuf.c m_sched.c \
         s_main.c s_inter.c s_loader.c s_path.c s_audio.c s_midi.c \
         d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \

--- m_class.c DELETED ---

Index: kernel.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/Attic/kernel.c,v
retrieving revision 1.1.2.9
retrieving revision 1.1.2.10
diff -C2 -d -r1.1.2.9 -r1.1.2.10
*** kernel.c	27 Dec 2006 23:30:34 -0000	1.1.2.9
--- kernel.c	28 Dec 2006 00:30:42 -0000	1.1.2.10
***************
*** 1001,1004 ****
--- 1001,1751 ----
  }
  
+ /* 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.  */
+ 
+ #define PD_CLASS_DEF
+ #include "desire.h"
+ #include "s_stuff.h"
+ #include <stdlib.h>
+ #ifdef UNISTD
+ #include <unistd.h>
+ #endif
+ #ifdef MSW
+ #include <io.h>
+ #endif
+ 
+ #include <stdio.h> /* grrrr: for sprintf */
+ #include <stdarg.h>
+ #include <string.h>
+ #include <pthread.h> /* tb: for hashtable locking */
+ 
+ #ifdef QUALIFIED_NAME
+ static char *pd_library_name = 0;
+ void pd_set_library_name(char *libname){
+   pd_library_name=libname;
+ }
+ #endif
+ 
+ t_hash *class_table=0;
+ 
+ static t_symbol *class_loadsym;     /* name under which an extern is invoked */
+ static void pd_defaultfloat(t_pd *x, t_float f);
+ static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+ t_pd pd_objectmaker;    /* factory for creating "object" boxes */
+ t_pd pd_canvasmaker;    /* factory for creating canvases */
+ 
+ static t_symbol *class_extern_dir = &s_;
+ 
+ static void pd_defaultanything(t_pd *x, t_symbol *s, int argc, t_atom *argv) {
+     pd_error(x, "%s: no method for '%s'", (*x)->name->s_name, s->s_name);
+ }
+ 
+ static void pd_defaultbang(t_pd *x) {
+     t_class *c = pd_class(x);
+     if (c->listmethod != pd_defaultlist) c->listmethod(x,0,0,0);
+     else c->anymethod(x,&s_bang,0,0);
+ }
+ 
+ static void pd_defaultfloat(t_pd *x, t_float f) {
+     t_class *c = pd_class(x); t_atom at; SETFLOAT(&at, f);
+     if (c->listmethod != pd_defaultlist) c->listmethod(x,0,1,&at); else c->anymethod(x,&s_float,1,&at);
+ }
+ static void pd_defaultsymbol(t_pd *x, t_symbol *s) {
+     t_class *c = pd_class(x); t_atom at; SETSYMBOL(&at, s);
+     if (c->listmethod != pd_defaultlist) c->listmethod(x,0,1,&at); else c->anymethod(x,&s_symbol,1,&at);
+ }
+ static void pd_defaultpointer(t_pd *x, t_gpointer *gp) {
+     t_class *c = pd_class(x); t_atom at; SETPOINTER(&at, gp);
+     if (c->listmethod != pd_defaultlist) c->listmethod(x,0,1,&at); else c->anymethod(x,&s_pointer,1,&at);
+ }
+ 
+ 
+ void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
+ static void class_nosavefn(t_gobj *z, t_binbuf *b);
+ 
+ /* handle "list" messages to Pds without explicit list methods defined. */
+ static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv) {
+     t_class *c = pd_class(x);
+     /* a list with no elements is handled by the 'bang' method if one exists. */
+     if (argc == 0 && c->bangmethod != pd_defaultbang) {c->bangmethod(x); return;}
+     /* a list with one element which is a number can be handled by a
+        "float" method if any is defined; same for "symbol", "pointer". */
+     if (argc == 1) {
+ #define HANDLE(A,M,D,F) if (argv->a_type==A && c->M != D) {c->M(x, argv->a_w.F); return;}
+ 	HANDLE(A_FLOAT  ,floatmethod  ,pd_defaultfloat  ,w_float)
+ 	HANDLE(A_SYMBOL ,symbolmethod ,pd_defaultsymbol ,w_symbol)
+ 	HANDLE(A_POINTER,pointermethod,pd_defaultpointer,w_gpointer)
+     }
+     /* Next try for an "anything" method; if the object is patchable (i.e.,
+        can have proper inlets) send it on to obj_list which will unpack the
+        list into the inlets. otherwise gove up and complain. */
+     if (c->anymethod != pd_defaultanything) c->anymethod(x,&s_list,argc,argv);
+     else if (c->patchable) obj_list((t_object *)x, s, argc, argv);
+     else pd_defaultanything(x, &s_list, argc, argv);
+ }
+ 
+     /* for now we assume that all "gobjs" are text unless explicitly
+     overridden later by calling class_setbehavior().  I'm not sure
+     how to deal with Pds that aren't gobjs; shouldn't there be a
+     way to check that at run time?  Perhaps the presence of a "newmethod"
+     should be our cue, or perhaps the "tiny" flag.  */
+ 
+     /* another matter.  This routine does two unrelated things: it creates
+     a Pd class, but also adds a "new" method to create an instance of it.
+     These are combined for historical reasons and for brevity in writing
+     objects.  To avoid adding a "new" method send a null function pointer.
+     To add additional ones, use class_addcreator below.  Some "classes", like
+     "select", are actually two classes of the same name, one for the single-
+     argument form, one for the multiple one; see select_setup() to find out
+     how this is handled.  */
+ 
+ extern void text_save(t_gobj *z, t_binbuf *b);
+ 
+ t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod,
+     size_t size, int flags, t_atomtype type1, ...)
+ {
+     va_list ap;
+     t_atomtype vec[MAXPDARG+1], *vp = vec;
+     int count = 0;
+     t_class *c;
+ #ifdef QUALIFIED_NAME
+     t_symbol *S=gensym(s->s_name);
+ #endif
+     int typeflag = flags & CLASS_TYPEMASK;
+     if (!typeflag) typeflag = CLASS_PATCHABLE;
+     *vp = type1;
+ 
+     va_start(ap, type1);
+     while (*vp) {
+         if (count == MAXPDARG) {
+             error("class %s: sorry: only %d creation args allowed", s->s_name, MAXPDARG);
+             break;
+         }
+         vp++;
+         count++;
+         *vp = va_arg(ap, t_atomtype);
+     }
+     va_end(ap);
+ 
+ #ifdef QUALIFIED_NAME
+     if (pd_library_name) {
+       char namespacename[MAXPDSTRING];
+       sprintf(namespacename, "%s%s%s", pd_library_name, QUALIFIED_NAME, s->s_name);
+       s=gensym(namespacename);
+     }
+ #endif
+ 
+     if (pd_objectmaker && newmethod) {
+         /* add a "new" method by the name specified by the object */
+         class_addmethod(pd_objectmaker, (t_method)newmethod, s, vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
+         if (class_loadsym) {
+             /* if we're loading an extern it might have been invoked by a
+             longer file name; in this case, make this an admissible name too. */
+             char *loadstring = class_loadsym->s_name,
+                 l1 = strlen(s->s_name), l2 = strlen(loadstring);
+             if (l2 > l1 && !strcmp(s->s_name, loadstring + (l2 - l1)))
+                 class_addmethod(pd_objectmaker, (t_method)newmethod, class_loadsym,
+                     vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
+         }
+     }
+     c = (t_class *)t_getbytes(sizeof(*c));
+     c->name = c->helpname = s;
+     c->size = size;
+     c->methods = (t_methodentry *)t_getbytes(0);
+     c->nmethod = 0;
+     c->freemethod = (t_method)freemethod;
+     c->bangmethod = pd_defaultbang;
+     c->pointermethod = pd_defaultpointer;
+     c->floatmethod = pd_defaultfloat;
+     c->symbolmethod = pd_defaultsymbol;
+     c->listmethod = pd_defaultlist;
+     c->anymethod = pd_defaultanything;
+     c->firstin = ((flags & CLASS_NOINLET) == 0);
+     c->firsttip = gensym("?");
+     c->fields = (t_symbol **)malloc(sizeof(t_symbol *)*31);
+     c->nfields = 0;
+     c->patchable = (typeflag == CLASS_PATCHABLE);
+     c->gobj = (typeflag >= CLASS_GOBJ);
+     c->drawcommand = 0;
+     c->floatsignalin = 0;
+     c->externdir = class_extern_dir;
+     c->savefn = (typeflag == CLASS_PATCHABLE ? text_save : class_nosavefn);
+ #ifdef QUALIFIED_NAME
+     c->helpname = S;
+     // like a class_addcreator
+     if (pd_library_name && newmethod) {
+       class_addmethod(pd_objectmaker, (t_method)newmethod, S, vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
+     }
+ #endif
+     hash_set(class_table, c->name, c);
+     return c;
+ }
+ 
+ /* add a creation method, which is a function that returns a Pd object
+    suitable for putting in an object box.  We presume you've got a class it
+    can belong to, but this won't be used until the newmethod is actually
+    called back (and the new method explicitly takes care of this.) */
+ void class_addcreator(t_newmethod newmethod, t_symbol *s, t_atomtype type1, ...) {
+     va_list ap;
+     t_atomtype vec[MAXPDARG+1], *vp = vec;
+     int count = 0;
+     *vp = type1;
+     va_start(ap, type1);
+     while (*vp) {
+         if (count == MAXPDARG) {
+             error("class %s: sorry: only %d creation args allowed", s->s_name, MAXPDARG);
+             break;
+         }
+         vp++;
+         count++;
+         *vp = va_arg(ap, t_atomtype);
+     }
+     va_end(ap);
+     class_addmethod(pd_objectmaker, (t_method)newmethod, s, vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
+ 
+ #ifdef QUALIFIED_NAME
+     if (pd_library_name) {
+       char namespacename[MAXPDSTRING];
+       sprintf(namespacename, "%s%s%s", pd_library_name, QUALIFIED_NAME, s->s_name);
+       s=gensym(namespacename);
+     }
+     class_addmethod(pd_objectmaker, (t_method)newmethod, s, vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
+ #endif
+     hash_set(class_table,s,0);
+ }
+ 
+ void class_addmethod2(t_class *c, t_method fn, t_symbol *sel, const char *fmt) {
+     t_methodentry *m;
+     int argtype = *fmt++;
+     int nargs;
+     /* "signal" method specifies that we take audio signals but
+        that we don't want automatic float to signal conversion.  This
+        is obsolete; you should now use the CLASS_MAINSIGNALIN macro. */
+     if (sel == &s_signal) {
+         if (c->floatsignalin) post("warning: signal method overrides class_mainsignalin");
+         c->floatsignalin = -1;
+     }
+     /* check for special cases.  "Pointer" is missing here so that
+        pd_objectmaker's pointer method can be typechecked differently.  */
+     if      (sel == &s_bang)   {if (argtype) goto phooey; class_addbang(c, fn);}
+     else if (sel == &s_float)  {if (argtype!='f' || *fmt) goto phooey; class_doaddfloat(c,fn);}
+     else if (sel == &s_symbol) {if (argtype!='s' || *fmt) goto phooey; class_addsymbol(c, fn);}
+     else if (sel == &s_list)   {if (argtype!='*')         goto phooey; class_addlist(c, fn);}
+     else if (sel == &s_anything) {if (argtype != A_GIMME) goto phooey; class_addanything(c, fn);}
+     else {
+         c->methods = (t_methodentry *)t_resizebytes(c->methods,
+             c->nmethod * sizeof(*c->methods), (c->nmethod+1) * sizeof(*c->methods));
+         m = c->methods + c->nmethod;
+         c->nmethod++;
+         m->me_name = sel;
+         m->me_fun = (t_gotfn)fn;
+         nargs = 0;
+         while (argtype && nargs < MAXPDARG) {
+ 	    t_atomtype t;
+ 	    switch(argtype) {
+ 		case 'f': t=A_FLOAT;    break;
+ 		case 's': t=A_SYMBOL;   break;
+ 		case 'p': t=A_POINTER;  break;
+ 		case ';': t=A_SEMI;     break;
+ 		case ',': t=A_COMMA;    break;
+ 		case 'F': t=A_DEFFLOAT; break;
+ 		case 'S': t=A_DEFSYMBOL;break;
+ 		case '$': t=A_DOLLAR;   break;
+ 		case '@': t=A_DOLLSYM;  break;
+ 		case '*': t=A_GIMME;    break;
+ 		case '!': t=A_CANT;     break;
+ 		default: goto phooey;
+ 	    };
+             m->me_arg[nargs++] = t;
+             argtype = *fmt++;
+         }
+         if (argtype != A_NULL)
+             error("%s_%s: only 5 arguments are typecheckable; use A_GIMME", c->name->s_name, sel->s_name);
+         m->me_arg[nargs] = A_NULL;
+     }
+     return;
+ phooey:
+     bug("class_addmethod: %s_%s: bad argument types\n", c->name->s_name, sel->s_name);
+ }
+ 
+ void class_addmethod(t_class *c, t_method fn, t_symbol *sel, t_atomtype arg1, ...) 
+ {
+     char fmt[42],*f=fmt;
+     int t;
+     va_list ap;
+     va_start(ap,arg1);
+     t=arg1;
+     for(;;) {
+ 	if (!t) break;
+ 	if (t>A_CANT) {error("class_addmethod: ARRGH! t=%d",t); return;}
+ 	*f++ = " fsp;,FS$@*!"[t];
+ 	t=va_arg(ap, t_atomtype);
+     }
+     *f = 0;
+     va_end(ap);
+     class_addmethod2(c,fn,sel,fmt);
+ }
+ 
+ /* see also the "class_addfloat", etc.,  macros in m_pd.h */
+ #undef class_addbang
+ #undef class_addpointer
+ #undef class_addsymbol
+ #undef class_addlist
+ #undef class_addanything
+ void class_addbang(    t_class *c, t_method fn) {   c->bangmethod = (t_bangmethod)fn;}
+ void class_addpointer( t_class *c, t_method fn) {c->pointermethod = (t_pointermethod)fn;}
+ void class_doaddfloat( t_class *c, t_method fn) {  c->floatmethod = (t_floatmethod)fn;}
+ void class_addsymbol(  t_class *c, t_method fn)  {c->symbolmethod = (t_symbolmethod)fn;}
+ void class_addlist(    t_class *c, t_method fn)    {c->listmethod = (t_listmethod)fn;}
+ void class_addanything(t_class *c, t_method fn) {    c->anymethod = (t_anymethod)fn;}
+ 
+ char *class_getname(t_class *c)     {return c->name->s_name;}
+ char *class_gethelpname(t_class *c) {return c->helpname->s_name;}
+ void class_sethelpsymbol(t_class *c, t_symbol *s) {c->helpname = s;}
+ void class_setdrawcommand(t_class *c) {c->drawcommand = 1;}
+ int  class_isdrawcommand( t_class *c) {return c->drawcommand;}
+ void class_setnotice(t_class *c, t_notice notice) {c->notice = notice;}
+ 
+ static void pd_floatforsignal(t_pd *x, t_float f) {
+     int offset = (*x)->floatsignalin;
+     if (offset > 0)
+         *(t_sample *)(((char *)x) + offset) = f;
+     else
+         pd_error(x, "%s: float unexpected for signal input", (*x)->name->s_name);
+ }
+ 
+ void class_domainsignalin(t_class *c, int onset) {
+     if (onset <= 0) onset = -1;
+     else {
+         if (c->floatmethod != pd_defaultfloat)
+             post("warning: %s: float method overwritten", c->name->s_name);
+         c->floatmethod = (t_floatmethod)pd_floatforsignal;
+     }
+     c->floatsignalin = onset;
+ }
+ 
+ void class_set_extern_dir(t_symbol *s) {class_extern_dir = s;}
+ char *class_gethelpdir(t_class *c) {return c->externdir->s_name;}
+ 
+ static void class_nosavefn(t_gobj *z, t_binbuf *b) {
+     bug("save function called but not defined");
+ }
+ 
+ void class_setsavefn(t_class *c, t_savefn f) {c->savefn = f;}
+ t_savefn class_getsavefn(t_class *c) {return  c->savefn;}
+ 
+ /* ---------------- the symbol table ------------------------ */
+ 
+ /* tb: new 16 bit hash table: multiplication hash */
+ #ifndef NEWHASH
+ #define HASHSIZE 1024
+ #else 
+ #define HASHSIZE 65536
+ #define HASHFACTOR 40503 /* donald knuth: (sqrt(5) - 1)/2*pow(2,16) */
+ #endif
+ 
+ #ifdef NEWHASH
+ static short hash(char *s, size_t n) {
+     unsigned short hash1 = 0, hash2 = 0;
+ #else
+ static int hash(char *s, size_t n) {
+     unsigned int hash1 = 0, hash2 = 0;
+ #endif
+     char *s2 = s;
+     while (n) {
+         hash1 += *s2;
+         hash2 += hash1;
+         s2++;
+ 	n--;
+     }
+     return hash2;
+ }
+ 
+ /* tb: made dogensym() threadsafe
+  * supported by vibrez.net */
+ t_symbol *dogensym(char *s, size_t n, t_symbol *oldsym) {
+     static t_symbol *symhash[HASHSIZE];
+ #ifdef THREADSAFE_GENSYM
+     static pthread_mutex_t hash_lock = PTHREAD_MUTEX_INITIALIZER;
+ #endif
+     t_symbol **sym1, *sym2;
+ #ifdef NEWHASH
+     unsigned short hash2 = hash(s,n);
+ #else
+     unsigned int   hash2 = hash(s,n);
+ #endif
+ #ifdef NEWHASH
+ 	hash2 = hash2 * HASHFACTOR;
+ 	sym1 = symhash + hash2;
+ #else
+ 	sym1 = symhash + (hash2 & (HASHSIZE-1));
+ #endif
+     while (sym2 = *sym1) {
+         if (!strcmp(sym2->s_name, s)) return sym2;
+         sym1 = &sym2->s_next;
+     }
+ #ifdef THREADSAFE_GENSYM
+     pthread_mutex_lock(&hash_lock);
+     /* tb: maybe another thread added the symbol to the hash table; double check */
+     while (sym2 = *sym1) 
+     {
+         if (!strcmp(sym2->s_name, s)) 
+ 		{
+ 			pthread_mutex_unlock(&hash_lock);
+ 			return(sym2);
+ 		}
+         sym1 = &sym2->s_next;
+     }
+ #endif
+ 
+     if (oldsym) sym2 = oldsym;
+     else {
+         sym2 = (t_symbol *)t_getbytes(sizeof(*sym2));
+         sym2->s_name = (char *)t_getbytes(n+1);
+         sym2->s_next = 0;
+         sym2->s_thing = 0;
+         memcpy(sym2->s_name, s, n);
+ 	sym2->s_name[n]=0;
+ 	sym2->s_size=n;
+     }
+     *sym1 = sym2;
+ #ifdef THREADSAFE_GENSYM
+ 	pthread_mutex_unlock(&hash_lock);
+ #endif
+     return sym2;
+ }
+ 
+ t_symbol *gensym(char *s) {return dogensym(s,strlen(s),0);}
+ t_symbol *gensym2(char *s, size_t n) {return dogensym(s,n,0);}
+ 
+ static int tryingalready;
+ 
+ void canvas_popabstraction(t_canvas *x);
+ extern t_pd *newest;
+ 
+ t_symbol* pathsearch(t_symbol *s,char* ext);
+ int pd_setloadingabstraction(t_symbol *sym);
+ 
+ 
+ /* replace everything but [a-zA-Z0-9_] by "0x%x" */
+ static char *alternative_classname(char*classname) {
+   char *altname=(char*)getbytes(sizeof(char)*MAXPDSTRING);
+   int count=0;
+   int i=0;
+   for(i=0; i<MAXPDSTRING; i++) altname[i]=0;
+   i=0;
+   while(*classname) {
+       char c=*classname;
+       if((c>=48 && c<=57) || (c>=65 && c<=90) || (c>=97 && c<=122) || c==95) {
+           altname[i]=c;
+           i++;
+       } else {
+           sprintf(altname+i, "0x%02x", c);
+           i+=4;
+           count++;
+       }
+       classname++;
+     }
+   if(count>0)return altname;
+   /* seems like the given classname is fine as can be */
+   freebytes(altname, sizeof(char)*MAXPDSTRING);
+   return 0;
+ }
+ 
+ 
+     /* this routine is called when a new "object" is requested whose class Pd
+     doesn't know.  Pd tries to load it as an extern, then as an abstraction. */
+ void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv)
+ {
+     t_pd *current;
+     int fd;
+     char dirbuf[MAXPDSTRING], *nameptr;
+     if (tryingalready) return;
+     newest = 0;
+     class_loadsym = s;
+     if (sys_load_lib(canvas_getcurrent(), s->s_name))
+     {
+         tryingalready = 1;
+         typedmess((t_pd *)dummy, s, argc, argv);
+         tryingalready = 0;
+         return;
+     }
+     class_loadsym = 0;
+     current = s__X.s_thing;
+     if ((fd = canvas_open(canvas_getcurrent(), s->s_name, ".pd",  dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
+         (fd = canvas_open(canvas_getcurrent(), s->s_name, ".pat", dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0) {
+         close(fd);
+         if (!pd_setloadingabstraction(s)) {
+             canvas_setargs(argc, argv); /* bug fix by Krzysztof Czaja */
+             binbuf_evalfile(gensym(nameptr), gensym(dirbuf));
+             if (s__X.s_thing != current)
+                 canvas_popabstraction((t_canvas *)(s__X.s_thing));
+             canvas_setargs(0, 0);
+         }
+         else error("%s: can't load abstraction within itself\n", s->s_name);
+     }
+     else newest = 0;
+ }
+ 
+ t_symbol  s_pointer =   {"pointer", 0, 0};
+ t_symbol  s_float =     {"float", 0, 0};
+ t_symbol  s_symbol =    {"symbol", 0, 0};
+ t_symbol  s_bang =      {"bang", 0, 0};
+ t_symbol  s_list =      {"list", 0, 0};
+ t_symbol  s_anything =  {"anything", 0, 0};
+ t_symbol  s_signal =    {"signal", 0, 0};
+ t_symbol  s__N =        {"#N", 0, 0};
+ t_symbol  s__X =        {"#X", 0, 0};
+ t_symbol  s_x =         {"x", 0, 0};
+ t_symbol  s_y =         {"y", 0, 0};
+ t_symbol  s_ =          {"", 0, 0};
+ 
+ static t_symbol *symlist[] = { &s_pointer, &s_float, &s_symbol, &s_bang,
+     &s_list, &s_anything, &s_signal, &s__N, &s__X, &s_x, &s_y, &s_};
+ 
+ void mess_init(void) {
+     t_symbol **sp;
+     int i;
+     if (pd_objectmaker) return;
+     for (i = sizeof(symlist)/sizeof(*symlist), sp = symlist; i--; sp++)
+         (void) dogensym((*sp)->s_name, strlen((*sp)->s_name), *sp);
+     pd_objectmaker = class_new(gensym("objectmaker"), 0, 0, sizeof(t_pd), CLASS_DEFAULT, A_NULL);
+     pd_canvasmaker = class_new(gensym("canvasmaker"), 0, 0, sizeof(t_pd), CLASS_DEFAULT, A_NULL);
+     pd_bind(&pd_canvasmaker, &s__N);
+     class_addanything(pd_objectmaker, (t_method)new_anything);
+ }
+ 
+ t_pd *newest;
+ 
+ /* This is externally available, but note that it might later disappear; the
+ whole "newest" thing is a hack which needs to be redesigned. */
+ t_pd *pd_newest(void) {return newest;}
+ 
+     /* horribly, we need prototypes for each of the artificial function
+     calls in typedmess(), to keep the compiler quiet. */
+ typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv);
+ typedef void(*t_messgimme)(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+ 
+ #define REST t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5
+ typedef t_pd *(*t_fun0)(REST);
+ typedef t_pd *(*t_fun1)(t_int i1, REST);
+ typedef t_pd *(*t_fun2)(t_int i1, t_int i2, REST);
+ typedef t_pd *(*t_fun3)(t_int i1, t_int i2, t_int i3, REST);
+ typedef t_pd *(*t_fun4)(t_int i1, t_int i2, t_int i3, t_int i4, REST);
+ typedef t_pd *(*t_fun5)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, REST);
+ typedef t_pd *(*t_fun6)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, t_int i6, REST);
+ #undef REST
+ 
+ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv) {
+     t_class *c = *x;
+     t_methodentry *m;
+     t_atomtype *wp, wanttype;
+     int i;
+     t_int ai[MAXPDARG+1], *ap = ai;
+     t_floatarg ad[MAXPDARG+1], *dp = ad;
+     int narg = 0;
+     t_pd *bonzo;
+     /* check for messages that are handled by fixed slots in the class
+        structure.  We don't catch "pointer" though so that sending "pointer"
+        to pd_objectmaker doesn't require that we supply a pointer value. */
+     if (s == &s_float) {
+         if (!argc) c->floatmethod(x, 0.);
+         else if (argv->a_type == A_FLOAT) c->floatmethod(x, argv->a_w.w_float);
+         else goto badarg;
+         return;
+     }
+     if (s == &s_bang) {c->bangmethod(x); return;}
+     if (s == &s_list) {c->listmethod(x,s,argc,argv); return;}
+     if (s == &s_symbol) {
+ 	c->symbolmethod(x, argc && argv->a_type==A_SYMBOL ? argv->a_w.w_symbol : &s_);
+         return;
+     }
+     for (i = c->nmethod, m = c->methods; i--; m++) if (m->me_name == s) {
+         wp = m->me_arg;
+         if (*wp == A_GIMME) {
+             if (x == &pd_objectmaker) pd_set_newest(((t_newgimme)(m->me_fun))(s, argc, argv));
+             else                                ((t_messgimme)(m->me_fun))(x, s, argc, argv);
+             return;
+         }
+         if (argc > MAXPDARG) argc = MAXPDARG;
+         if (x != &pd_objectmaker) *(ap++) = (t_int)x, narg++;
+         while (wanttype = *wp++) {
+             switch (wanttype) {
+             case A_POINTER:
+                 if (!argc) goto badarg;
+                 else {
+                     if (argv->a_type!=A_POINTER) goto badarg;
+                     *ap = (t_int)(argv->a_w.w_gpointer);
+                     argc--;
+                     argv++;
+                 }
+                 narg++;
+                 ap++;
+                 break;
+             case A_FLOAT:
+                 if (!argc) goto badarg;
+             case A_DEFFLOAT:
+                 if (!argc) *dp = 0;
+                 else {
+                     if (argv->a_type!=A_FLOAT) goto badarg;
+                     *dp = argv->a_w.w_float;
+                     argc--;
+                     argv++;
+                 }
+                 dp++;
+                 break;
+             case A_SYMBOL:
+                 if (!argc) goto badarg;
+             case A_DEFSYM:
+                 if (!argc) *ap = (t_int)(&s_);
+                 else {
+                     if (argv->a_type == A_SYMBOL) *ap = (t_int)(argv->a_w.w_symbol);
+                     /* if it's an unfilled "dollar" argument it appears
+                        as zero here; cheat and bash it to the null
+                        symbol.  Unfortunately, this lets real zeros
+                        pass as symbols too, which seems wrong... */
+                     else if (x == &pd_objectmaker && argv->a_type == A_FLOAT
+                         && argv->a_w.w_float == 0)
+                         *ap = (t_int)(&s_);
+                     else goto badarg;
+                     argc--;
+                     argv++;
+                 }
+                 narg++;
+                 ap++;
+             }
+         }
+         switch (narg) {
+ #define REST ad[0],ad[1],ad[2],ad[3],ad[4]
+         case 0 : bonzo = ((t_fun0)(m->me_fun))(                                    REST); break;
+         case 1 : bonzo = ((t_fun1)(m->me_fun))(ai[0],                              REST); break;
+         case 2 : bonzo = ((t_fun2)(m->me_fun))(ai[0],ai[1],                        REST); break;
+         case 3 : bonzo = ((t_fun3)(m->me_fun))(ai[0],ai[1],ai[2],                  REST); break;
+         case 4 : bonzo = ((t_fun4)(m->me_fun))(ai[0],ai[1],ai[2],ai[3],            REST); break;
+         case 5 : bonzo = ((t_fun5)(m->me_fun))(ai[0],ai[1],ai[2],ai[3],ai[4],      REST); break;
+         case 6 : bonzo = ((t_fun6)(m->me_fun))(ai[0],ai[1],ai[2],ai[3],ai[4],ai[5],REST); break;
+         default: bonzo = 0;
+         }
+         if (x == &pd_objectmaker) pd_set_newest(bonzo);
+         return;
+     }
+     c->anymethod(x, s, argc, argv);
+     return;
+ badarg:
+     pd_error(x, "Bad arguments for message '%s' to object '%s'", s->s_name, c->name->s_name);
+ }
+ 
+ void pd_vmess(t_pd *x, t_symbol *sel, char *fmt, ...) {
+     va_list ap;
+     t_atom arg[MAXPDARG], *at =arg;
+     int nargs = 0;
+     char *fp = fmt;
+ 
+     va_start(ap, fmt);
+     while (1) {
+         if (nargs > MAXPDARG) {
+             pd_error(x, "pd_vmess: only %d allowed", MAXPDARG);
+             break;
+         }
+         switch(*fp++) {
+         case 'f': SETFLOAT(at, va_arg(ap, double)); break;
+         case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
+         case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
+         case 'p': SETPOINTER(at, va_arg(ap, t_gpointer *)); break;
+         default: goto done;
+         }
+         at++;
+         nargs++;
+     }
+ done:
+     va_end(ap);
+     typedmess(x, sel, nargs, arg);
+ }
+ 
+ void pd_forwardmess(t_pd *x, int argc, t_atom *argv) {
+     if (argc) {
+         t_atomtype t = argv->a_type;
+         if (t == A_SYMBOL) pd_typedmess(x, argv->a_w.w_symbol, argc-1, argv+1);
+         else if (t == A_POINTER) {
+             if (argc == 1) pd_pointer(x, argv->a_w.w_gpointer); else pd_list(x, &s_list, argc, argv);
+         }
+ 	else if (t == A_FLOAT) {
+             if (argc == 1)   pd_float(x, argv->a_w.w_float);    else pd_list(x, &s_list, argc, argv);
+         }
+         else bug("pd_forwardmess");
+     }
+ }
+ 
+ void nullfn(void) {}
+ 
+ t_gotfn getfn(t_pd *x, t_symbol *s) {
+     t_class *c = *x;
+     t_methodentry *m;
+     int i;
+     for (i = c->nmethod, m = c->methods; i--; m++) if (m->me_name == s) return m->me_fun;
+     pd_error(x, "%s: no method for message '%s'", c->name->s_name, s->s_name);
+     return((t_gotfn)nullfn);
+ }
+ 
+ t_gotfn zgetfn(t_pd *x, t_symbol *s) {
+     t_class *c = *x;
+     t_methodentry *m;
+     int i;
+     for (i = c->nmethod, m = c->methods; i--; m++) if (m->me_name == s) return m->me_fun;
+     return 0;
+ }
+ 
+ void class_settip(t_class *x,t_symbol* s) {x->firsttip = s;}
+ 
+ /* must be called only once */
+ void class_setfieldnames(t_class *x, const char *s) {
+     char foo[64];
+     while (*s) {
+ 	char *t = strchr(s,' ');
+ 	int i = t-s;
+ 	if (!t) return;
+ 	memcpy(foo,s,i);
+ 	foo[i]=0;
+ 	x->fields[x->nfields++] = gensym(foo);
+ 	s=s+i+1;
+     }
+ }
+ 
+ int class_getfieldindex(t_class *x, const char *s) {
+ 	t_symbol *sy = gensym((char *)s);
+ 	int i;
+ 	for (i=0; i<x->nfields; i++) if (x->fields[i]==sy) return i;
+ 	return -1;
+ }
+ 
+ /* O(n) asymptotic time :-} */
+ /* only looks for already loaded classes though. */
+ 
+ t_class *class_find (t_symbol *s) {return hash_get(class_table,s);}
+ 
+ void glob_update_class_info (t_pd *bogus, t_symbol *s, t_symbol *cb_recv, t_symbol *cb_sel) {
+     t_class *c = class_find(s);
+     if (!c) { post("class not found!"); return; }
+     sys_vgui("global class_info; set class_info(%s) [list "
+                 "helpname \"%s\" externdir \"%s\" size \"%d\" "
+ /*
+     t_methodentry *c_methods; int c_nmethod;
+     t_method c_freemethod;
+     t_savefn c_savefn;
+     int c_floatsignalin;
+ */
+     "gobj \"%d\" patchable \"%d\" firstin \"%d\" "
+     "firsttip \"%s\" methods {",s->s_name,c->helpname->s_name,c->externdir->s_name,
+ 	c->size,c->gobj,c->patchable,c->firstin,c->firsttip->s_name);
+     if (c->   bangmethod != pd_defaultbang)     sys_vgui("<bang> ");
+     if (c->pointermethod != pd_defaultpointer)  sys_vgui("<pointer> ");
+     if (c->  floatmethod != pd_defaultfloat)    sys_vgui("<float> ");
+     if (c-> symbolmethod != pd_defaultsymbol)   sys_vgui("<symbol> ");
+     if (c->   listmethod != pd_defaultlist)     sys_vgui("<list> ");
+     if (c->    anymethod != pd_defaultanything) sys_vgui("<any> ");
+     {int i; for (i=0; i<c->nmethod; i++) sys_vgui("%s ",c->methods[i].me_name->s_name);}
+     sys_vgui("}]; %s %s %s\n",cb_recv->s_name, cb_sel->s_name, s->s_name);
+ }
  
  void mess_init(void);





More information about the Pd-cvs mailing list