/* * Pure Data Packet header file. PF plugin system. * Copyright (c) by Tom Schouten * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file plugin.h * @brief PF Plugin System * * This file contains the c interface for defining pf extensions. * * A c extension is simply a function acting on the data stack ('s') * or the rest of the execution context ('vm') which returns a * pf error code. * * Always use the convenience macros for primitive words hiding the c prototype. * Inside the a PF_FUNCTION definition the forth macros are valid (VM_RS, ...) * - s = data stack * - vm = virtual machine, * * The virtual machine is the main access point to the execution * context (RS, dictionary, streams, ...) * */ #ifndef __pf_plugin_h_ #define __pf_plugin_h_ #include #include #include #include #include #include #include #include #include #include /* OBSOLETE */ struct pf_void { void (*destructor)(void *); // kills object when refcount == 0 int refcount; // replace with atomic code }; pf_word_type_t pf_plugin_new_void(pf_symbol_t *name); pf_symbol_t *pf_plugin_void_name(pf_word_type_t type); /** Prototype for an extension function. * All extensions (both functional and object methods) share the same c-interface. * PF uses multimethods. Object methods usually take the object they act on as first argument. */ typedef pf_error_t (*pf_function_t)(pf_stack_t *s, pf_vm_t *vm); /** * Add a function * Do not use this directly. use the PF_REGISTER_FUNCTION macro * which is valid inside a PF_FUNCTION definition. */ void pf_plugin_add_function(pf_vm_t *vm, ///< virtual machine (current execution context) pf_function_t f, ///< c primitive char *c_name, ///< unique C name char *forth_name, ///< unique forth name char *stackeffect ///< stack effect documentation string ); #define PF_FUNCTION(function) pf_error_t function (pf_stack_t *s, pf_vm_t *vm) ///< declare a pf primitive using the correct prototype #define PF_REGISTER_FUNCTION(function, name, docstring) {pf_plugin_add_function(vm, ((pf_function_t)function), #function, name, docstring);} ///< register a function in the current dictionary, together with a document string describing its action. #define PF_EXECUTE_FUNCTION(function) function(s, vm) ///< execute another primitive. /* static */ #ifdef PF_STATIC #define PF_PLUGIN(name) PF_FUNCTION(pf_plugin_setup_##name) ///< declare the plugin setup function #else #define PF_PLUGIN(name) PF_FUNCTION(pf_plugin_setup) ///< declare the plugin setup function #endif /* FIXME: autogen */ #define push_int PUSH_INT #define push_float PUSH_FLOAT #define push_symbol(x) PUSH_SYMBOL(pf_symbol(x)) #define push_string(x) PUSH_PACKET(pf_packet_stringf(x)) #define push_primitive PUSH_PRIMITIVE #endif