github.com/256dpi/max-go@v0.7.0/lib/max/ext_mess.h (about)

     1  #ifndef _EXT_MESS_H_
     2  #define _EXT_MESS_H_
     3  
     4  #include "ext_prefix.h"
     5  #include "ext_common.h"
     6  
     7  BEGIN_USING_C_LINKAGE
     8  
     9  #if C74_PRAGMA_STRUCT_PACKPUSH
    10      #pragma pack(push, 2)
    11  #elif C74_PRAGMA_STRUCT_PACK
    12      #pragma pack(2)
    13  #endif
    14  	
    15  #include "max_types.h"
    16  
    17  /* mess.h -- define a symbol table and message-passing system.  */
    18  
    19  
    20  /**	Function pointer type for generic methods.
    21  	@ingroup datatypes
    22  */
    23  
    24  
    25  typedef void *(*method)(void *);
    26  
    27  typedef long (*t_intmethod)(void *);
    28  
    29  // First cast to void* to trigger errors if arg is float, double, or larger than a pointer.
    30  // Then cast to t_ptr_int as that's the type we specify for each arg, avoid warnings.
    31  #define CALL_METHOD_ARG(p) (t_ptr_int)(void*)(p)
    32  /**	Function pointer type for methods returning a long.
    33  	@ingroup datatypes
    34  */
    35  #define CALL_METHOD_0(m) ((void*(*)())(m))()
    36  #define CALL_METHOD_1(m, p1) ((void*(*)(t_ptr_int))(m))(CALL_METHOD_ARG(p1))
    37  #define CALL_METHOD_2(m, p1, p2) ((void*(*)(t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2))
    38  #define CALL_METHOD_3(m, p1, p2, p3) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3))
    39  #define CALL_METHOD_4(m, p1, p2, p3, p4) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4))
    40  #define CALL_METHOD_5(m, p1, p2, p3, p4, p5) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5))
    41  #define CALL_METHOD_6(m, p1, p2, p3, p4, p5, p6) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5), CALL_METHOD_ARG(p6))
    42  #define CALL_METHOD_7(m, p1, p2, p3, p4, p5, p6, p7) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5), CALL_METHOD_ARG(p6), CALL_METHOD_ARG(p7))
    43  #define CALL_METHOD_8(m, p1, p2, p3, p4, p5, p6, p7, p8) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5), CALL_METHOD_ARG(p6), CALL_METHOD_ARG(p7), CALL_METHOD_ARG(p8))
    44  #define CALL_METHOD_9(m, p1, p2, p3, p4, p5, p6, p7, p8, p9) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5), CALL_METHOD_ARG(p6), CALL_METHOD_ARG(p7), CALL_METHOD_ARG(p8), CALL_METHOD_ARG(p9))
    45  #define CALL_METHOD_10(m, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) ((void*(*)(t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int, t_ptr_int))(m))(CALL_METHOD_ARG(p1), CALL_METHOD_ARG(p2), CALL_METHOD_ARG(p3), CALL_METHOD_ARG(p4), CALL_METHOD_ARG(p5), CALL_METHOD_ARG(p6), CALL_METHOD_ARG(p7), CALL_METHOD_ARG(p8), CALL_METHOD_ARG(p9), CALL_METHOD_ARG(p10))
    46  
    47  #define _GET_CALL_METHOD_MACRO_INDEX(_method, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
    48  #define GET_CALL_METHOD_MACRO_INDEX(...) C74_EXPAND(_GET_CALL_METHOD_MACRO_INDEX(__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
    49  
    50  #define GET_CALL_METHOD_MACRO_NAME(...) C74_JOIN_2(CALL_METHOD_, GET_CALL_METHOD_MACRO_INDEX(__VA_ARGS__))
    51  
    52  #define CALL_METHOD(...) C74_EXPAND(GET_CALL_METHOD_MACRO_NAME(__VA_ARGS__) ( __VA_ARGS__ ))
    53  
    54  #define CALL_METHOD_SAFE(rt, sig, m, ...) (((rt (*)sig)m)(__VA_ARGS__))
    55  
    56  // Forward declarations of important Max types
    57  
    58  typedef struct _atomarray t_atomarray;
    59  
    60  // eventually convert all externals to use explicit types instead of void*
    61  // can define C74_USE_STRICT_TYPES=1 to enable for specific externals to test
    62  #if !defined(_MAX_CORE_H_) && !defined(C74_USE_STRICT_TYPES)
    63  #define C74_USE_STRICT_TYPES 0
    64  #else
    65  #define C74_USE_STRICT_TYPES 1
    66  #endif
    67  
    68  #if C74_USE_STRICT_TYPES
    69  
    70  typedef struct _outlet t_outlet;
    71  typedef struct _inlet t_inlet;
    72  typedef struct _binbuf t_binbuf;
    73  typedef struct _qelem t_qelem;
    74  typedef struct _scheduler t_scheduler;
    75  typedef struct _clock t_clock;
    76  typedef struct _setclock t_setclock;
    77  typedef struct _toolfile t_toolfile;
    78  
    79  #else
    80  
    81  typedef void t_outlet;
    82  typedef void t_inlet;
    83  typedef void t_binbuf;
    84  typedef void t_qelem;
    85  typedef void t_scheduler;
    86  typedef void t_clock;
    87  typedef void t_setclock;
    88  typedef void t_toolfile;
    89  
    90  #endif // #if !C74_USE_STRICT_TYPES
    91  
    92  /** The symbol.
    93  	
    94  	Note: You should <em>never</em> manipulate the s_name field of the #t_symbol directly!
    95  	Doing so will corrupt Max's symbol table.  
    96  	Instead, <em>always</em> use gensym() to get a symbol with the desired string 
    97  	contents for the s_name field.
    98  
    99  	@ingroup symbol	
   100  */
   101  typedef struct symbol
   102  {
   103  	char *s_name;			///< name: a c-string
   104  	struct object *s_thing;	///< possible binding to a t_object
   105  } t_symbol;
   106  
   107  #ifdef C74_DEFINE_DEPRECATED_TYPES
   108  C74_DEPRECATED( typedef struct symbol Symbol );
   109  #endif
   110  
   111  #define CAREFUL
   112  
   113  /**	Magic number used to determine if memory pointed to by a #t_object* is valid.	
   114  	@ingroup obj
   115  */
   116  enum {
   117  	MAGIC = 1758379419L,	/* random (but odd) */
   118  	OB_MAGIC = MAGIC
   119  };
   120  
   121  /** function version of NOGOOD test is potentially more reliable
   122  */
   123  long object_isnogood(void *x);
   124  
   125  #ifdef  WIN_VERSION
   126  /**	Returns true if a pointer is not a valid object. 
   127  	@ingroup obj
   128  */
   129  #ifdef _DEBUG
   130  #define NOGOOD(x) object_isnogood(x)
   131  #else
   132  #define NOGOOD(x) ( IsBadReadPtr((void *)(x),sizeof(struct object)) || ((struct object *)(x))->o_magic != MAGIC )
   133  #endif
   134  
   135  #else
   136  /**	Returns true if a pointer is not a valid object. 
   137  	@ingroup obj
   138  */
   139  #define NOGOOD(x) ( (!(x)) || ((struct object *)(x))->o_magic != MAGIC )
   140  #endif
   141  
   142  #define OB_INVALID NOGOOD
   143  
   144  /**	Maximum number of arguments that can be passed as a typed-list rather than using #A_GIMME.  It is generally recommended to use #A_GIMME. 
   145  	@ingroup obj
   146  */
   147  enum {
   148  	MSG_MAXARG = 7
   149  };
   150  
   151  
   152  /** A list of symbols and their corresponding methods,
   153   	complete with typechecking information.	
   154  	@ingroup obj
   155  */
   156  typedef struct messlist
   157  {
   158  	struct symbol *m_sym;		///< Name of the message
   159  	method m_fun;				///< Method associated with the message
   160  	char m_type[MSG_MAXARG + 1];	///< Argument type information
   161  } t_messlist;
   162  
   163  #ifdef C74_DEFINE_DEPRECATED_TYPES
   164  C74_DEPRECATED( typedef struct messlist Messlist );
   165  #endif
   166  
   167  /**	The tiny object structure sits at the head of any object to which you may
   168   	pass messages (and which you may feed to freeobject()).
   169  	In general, you should use #t_object instead.
   170  	@ingroup obj
   171  */
   172  typedef struct tinyobject
   173  {
   174  	struct messlist *t_messlist;	///< list of messages and methods 
   175  									// (also used as freelist link)
   176  #ifdef CAREFUL
   177  	long t_magic;					///< magic number
   178  #endif
   179  } t_tinyobject;
   180  
   181  #ifdef C74_DEFINE_DEPRECATED_TYPES
   182  C74_DEPRECATED( typedef struct tinyobject Tinyobject );
   183  #endif
   184  
   185  
   186  /** The structure for the head of any object which wants to have inlets or outlets,
   187  	or support attributes.
   188  	@ingroup obj
   189  */
   190  typedef struct object
   191  {
   192  	struct messlist *o_messlist;	///<  list of messages and methods. The -1 entry of the message list of an object contains a pointer to its #t_class entry.
   193  									// (also used as freelist link)
   194  #ifdef CAREFUL
   195  	t_ptr_int o_magic;					///< magic number
   196  #endif
   197  	t_inlet *o_inlet;			///<  list of inlets
   198  	t_outlet *o_outlet;		///<  list of outlets
   199  } t_object;
   200  
   201  #ifdef C74_DEFINE_DEPRECATED_TYPES
   202  C74_DEPRECATED( typedef struct object Object );
   203  #endif
   204  
   205  /** 
   206  	The data structure for a Max class. This struct is provided for debugging convenience, 
   207  	but should be considered opaque and is subject to change without notice.
   208  					
   209  	@ingroup class
   210  */
   211  typedef struct maxclass
   212  {
   213  	struct symbol *c_sym;			///< symbol giving name of class
   214  	struct object **c_freelist;		// linked list of free ones
   215  	method c_freefun;				// function to call when freeing
   216  	t_getbytes_size c_size;			// size of an instance
   217  	char c_tiny;					// flag indicating tiny header
   218  	char c_noinlet;					// flag indicating no first inlet for patcher
   219  	struct symbol *c_filename;		///< name of file associated with this class
   220  	t_messlist *c_newmess;			// constructor method/type information
   221  	method c_menufun;				// function to call when creating from object pallette (default constructor)
   222  	long c_flags;					// class flags used to determine context in which class may be used
   223  	long c_messcount;				// size of messlist array
   224  	t_messlist *c_messlist;			// messlist arrray
   225  	void *c_attributes;				// t_hashtab object
   226  	void *c_extra;					// t_hashtab object
   227  	long c_obexoffset;				// if non zero, object struct contains obex pointer at specified byte offset
   228  	void *c_methods;				// methods t_hashtab object
   229  	method c_attr_get;				// if not set, NULL, if not present CLASS_NO_METHOD
   230  	method c_attr_gettarget;		// if not set, NULL, if not present CLASS_NO_METHOD
   231  	method c_attr_getnames;			// if not set, NULL, if not present CLASS_NO_METHOD
   232  	struct maxclass *c_superclass;	// a superclass point if this is a derived class
   233  } t_class;
   234  
   235  #ifdef C74_DEFINE_DEPRECATED_TYPES
   236  C74_DEPRECATED( typedef struct maxclass Maxclass );
   237  #endif
   238  
   239  
   240  /** Class flags. If not box or polyglot, class is only accessible in C via known interface
   241  	@ingroup class
   242  */
   243  typedef enum {
   244  	CLASS_FLAG_BOX =					0x00000001L,	///< for use in a patcher
   245  	CLASS_FLAG_POLYGLOT =				0x00000002L,	///< for use by any text language (c/js/java/etc)
   246  	CLASS_FLAG_NEWDICTIONARY =			0x00000004L,	///< dictionary based constructor
   247  	CLASS_FLAG_REGISTERED =				0x00000008L,	///< for backward compatible messlist implementation (once reg'd can't grow)
   248  	CLASS_FLAG_UIOBJECT =				0x00000010L,	///< for objects that don't go inside a newobj box. 
   249  	CLASS_FLAG_ALIAS =					0x00000020L,	///< for classes that are just copies of some other class (i.e. del is a copy of delay)
   250  	CLASS_FLAG_MULTITOUCH =				0x00000040L,	///< sent multitouch version of mouse messages
   251  	CLASS_FLAG_DO_NOT_PARSE_ATTR_ARGS =	0x00000080L, 	///< override dictionary based constructor attr arg parsing
   252  	CLASS_FLAG_DO_NOT_ZERO =			0x00000100L, 	///< don't zero the object struct on construction (for efficiency)
   253  	CLASS_FLAG_NOATTRIBUTES =			0x00010000L,	///< for efficiency
   254  	CLASS_FLAG_OWNATTRIBUTES =			0x00020000L,	///< for classes which support a custom attr interface (e.g. jitter)
   255  	CLASS_FLAG_PARAMETER =				0x00040000L,	///< for classes which have a parameter
   256  	CLASS_FLAG_RETYPEABLE =				0x00080000L,	///< object box can be retyped without recreating the object
   257  	CLASS_FLAG_OBJECT_METHOD =			0x00100000L,	///< objects of this class may have object specific methods
   258  	CLASS_FLAG_VISUALIZER =				0x00200000L,	///< objects of this class are signal visualizers
   259  	CLASS_FLAG_USES_PROXIES =			0x00400000L, 	///< objects of this class might use proxies (set automatically in proxy_new)
   260  	CLASS_FLAG_OWN_DATA =				0x00800000L,	///< objects of this class save data in their own format
   261  	CLASS_FLAG_DYNAMICCOLOR =			0x01000000L		///< objects which contain colors supporting dynamic colors (set automatically in class_attr_dynamiccolor_init)
   262  } e_max_class_flags;
   263  
   264  
   265  /** the list of officially recognized types, including pseudotypes for
   266  	commas and semicolons.  Used in two places: 1. the reader, when it reads
   267  	a string, returns long, float, sym, comma, semi, or dollar;
   268  	and 2. each object method comes with an array of them saying what types
   269  	it needs, from among long, float, sym, obj, gimme, and cant.
   270  	
   271  	@ingroup atom
   272  	
   273  	@remark	While these values are defined in an enum, you should use a long to represent the value.
   274  			Using the enum type creates ambiguity in struct size and is subject to various inconsistent 
   275  			compiler settings.
   276  */
   277  typedef enum {
   278  	A_NOTHING = 0,	///< no type, thus no atom
   279  	A_LONG,			///< long integer
   280  	A_FLOAT,		///< 32-bit float
   281  	A_SYM,			///< t_symbol pointer
   282  	A_OBJ,			///< t_object pointer (for argtype lists; passes the value of sym)
   283  	A_DEFLONG,		///< long but defaults to zero
   284  	A_DEFFLOAT,		///< float, but defaults to zero
   285  	A_DEFSYM,		///< symbol, defaults to ""
   286  	A_GIMME,		///< request that args be passed as an array, the routine will check the types itself.
   287  	A_CANT,			///< cannot typecheck args
   288  	A_SEMI,			///< semicolon
   289  	A_COMMA,		///< comma
   290  	A_DOLLAR,		///< dollar
   291  	A_DOLLSYM,		///< dollar
   292  	A_GIMMEBACK,	///< request that args be passed as an array, the routine will check the types itself. can return atom value in final atom ptr arg. function returns long error code 0 = no err. see gimmeback_meth typedef
   293  
   294  	A_DEFER	=		0x41,	///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred.
   295  	A_USURP =		0x42,	///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred and multiple calls within one servicing of the queue are filtered down to one call.
   296  	A_DEFER_LOW =	0x43,	///< A special signature for declaring methods. This is like A_GIMME, but the call is deferref to the back of the queue.
   297  	A_USURP_LOW =	0x44	///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred to the back of the queue and multiple calls within one servicing of the queue are filtered down to one call.
   298  } e_max_atomtypes;
   299  
   300  
   301  /**	Defines the largest possible string size for an atom
   302  	@ingroup atom */
   303  enum {
   304  	ATOM_MAX_STRLEN = 32768
   305  };
   306  
   307  /** Union for packing any of the datum defined in #e_max_atomtypes.
   308  	@ingroup atom
   309  */
   310  union word		
   311  {
   312  	t_atom_long w_long;			///< long integer
   313  	t_atom_float w_float;	///< 32-bit float
   314  	struct symbol *w_sym;	///< pointer to a symbol in the Max symbol table
   315  	struct object *w_obj;	///< pointer to a #t_object or other generic pointer
   316  };
   317  
   318  
   319  /** An atom is a typed datum.
   320  	@ingroup atom
   321  */
   322  typedef struct atom		// and an atom which is a typed datum
   323  {
   324  	short			a_type;	
   325  	union word		a_w;
   326  } t_atom;
   327  
   328  #ifdef C74_DEFINE_DEPRECATED_TYPES
   329  C74_DEPRECATED( typedef struct atom Atom );
   330  #endif
   331  
   332  /**	Function pointer type for methods with no arguments.
   333  	@ingroup datatypes
   334  */
   335  typedef void *(*zero_meth)(void *x);
   336  
   337  
   338  /**	Function pointer type for methods with a single argument.
   339  	@ingroup datatypes
   340  */
   341  typedef void *(*one_meth)(void *x, void *z);
   342  
   343  
   344  /**	Function pointer type for methods with two arguments.
   345  	@ingroup datatypes
   346  */
   347  typedef void *(*two_meth)(void *x, void *z, void *a);
   348  
   349  
   350  /**	Function pointer type for methods that pass back a result value through the last parameter as a #t_atom, 
   351  	and return an error.
   352  	@ingroup datatypes
   353  */
   354  typedef long *(*gimmeback_meth)(void *x, t_symbol *s, long ac, t_atom *av, t_atom *rv);
   355  
   356  
   357  
   358  // legacy macros...
   359  
   360  #define ob_messlist(x) (((struct object *)(x))->o_messlist - 1)
   361  #define ob_class(x) ((struct maxclass *) \
   362  	(((struct object *)(x))->o_messlist[-1].m_sym))
   363  #define ob_name(x) (ob_class(x)->c_sym->s_name)
   364  #define ob_sym(x) (ob_class(x)->c_sym)
   365  #define ob_filename(x) (ob_class(x)->c_filename->s_name)
   366  #define ob_filesym(x) (ob_class(x)->c_filename)
   367  #define OB_MESS0(x, y) (CALL_METHOD(getfn((struct object *)x, y), (struct object *)x))
   368  #define mess0 OB_MESS0
   369  // #define OB_MESS1(x, y, z1) (*(getfn((struct object *)x, y)))((struct object *)x, z1)
   370  #define OB_MESS1(x, y, z1) (CALL_METHOD(getfn((struct object *)x, y), (struct object *)x, z1))
   371  #define mess1 OB_MESS1
   372  //#define OB_MESS2(x, y, z1,z2) (*(getfn((struct object *)x, y)))((struct object *)x, z1,z2)
   373  #define OB_MESS2(x, y, z1,z2) (CALL_METHOD((getfn((struct object *)x, y)), (struct object *)x, z1, z2))
   374  #define mess2 OB_MESS2
   375  #define mess3(x, y, z1,z2,z3) (CALL_METHOD(getfn((struct object *)x, y), x, z1, z2, z3))
   376  #define mess4(x, y, z1,z2,z3,z4) (CALL_METHOD(getfn((struct object *)x, y), x, z1,z2,z3,z4))
   377  #define mess5(x, y, z1,z2,z3,z4,z5) (CALL_METHOD(getfn((struct object *)x, y), x, z1,z2,z3,z4,z5))
   378  #define floatmess1(x,y,z1)  ((floatmeth)(*(getfn((struct object *)x, y))))((struct object *)x, z1)
   379  #define NIL ((void *)0)
   380  #define A_SETCOMMA(ap) ((ap)->a_type = A_COMMA)
   381  #define A_SETSEMI(ap) ((ap)->a_type = A_SEMI)
   382  #define A_SETSYM(ap, x) ((ap)->a_type = A_SYM, (ap)->a_w.w_sym = (x))
   383  #define A_SETOBJ(ap, x) ((ap)->a_type = A_OBJ, (ap)->a_w.w_obj = (x))
   384  #define A_SETLONG(ap, x) ((ap)->a_type = A_LONG, (ap)->a_w.w_long = (x))
   385  #define A_SETFLOAT(ap, x) ((ap)->a_type = A_FLOAT, (ap)->a_w.w_float = (x))
   386  #define A_SETDOLLAR(ap, x) ((ap)->a_type = A_DOLLAR, (ap)->a_w.w_long = (x))
   387  #define A_SETDOLLSYM(ap,x) ((ap)->a_type = A_DOLLSYM, (ap)->a_w.w_sym = (x))
   388  
   389  #if C74_PRAGMA_STRUCT_PACKPUSH
   390      #pragma pack(pop)
   391  #elif C74_PRAGMA_STRUCT_PACK
   392      #pragma pack()
   393  #endif
   394  
   395  END_USING_C_LINKAGE
   396  
   397  #endif /* _EXT_MESS_H_ */