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_ */