hexloader-v1.7/0000755000175000017500000000000012564447211013762 5ustar zmoelnigzmoelnighexloader-v1.7/hexloader-help.pd0000644000175000017500000000063512564445077017224 0ustar zmoelnigzmoelnig#N canvas 4 49 525 349 10; #X obj 394 83 hexloader; #X text 84 83 allows funny characters in Pd objectnames.; #X text 84 176 "hexloader" is not an object to be used within Pd \, but a *loader* \, that will allow you to use objects containing slightly weird characters \, like "<" or "/".; #X text 98 236 To use it \, add "hexloader" to the libraries to be loaded on startup \, or start Pd with "-lib hexloader".; hexloader-v1.7/Makefile0000644000175000017500000004116112564444603015427 0ustar zmoelnigzmoelnig## Pd library template version 1.0.14 # For instructions on how to use this template, see: # http://puredata.info/docs/developer/MakefileTemplate LIBRARY_NAME = hexloader # add your .c source files, one object per file, to the SOURCES # variable, help files will be included automatically, and for GUI # objects, the matching .tcl file too SOURCES = hexloader.c # list all pd objects (i.e. myobject.pd) files here, and their helpfiles will # be included automatically PDOBJECTS = # example patches and related files, in the 'examples' subfolder EXAMPLES = # manuals and related files, in the 'manual' subfolder MANUAL = # if you want to include any other files in the source and binary tarballs, # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included EXTRA_DIST = README.txt FAQ.txt # unit tests and related files here, in the 'unittests' subfolder UNITTESTS = #------------------------------------------------------------------------------# # # things you might need to edit if you are using other C libraries # #------------------------------------------------------------------------------# ALL_CFLAGS = -I"$(PD_INCLUDE)" ALL_LDFLAGS = SHARED_LDFLAGS = ALL_LIBS = #------------------------------------------------------------------------------# # # you shouldn't need to edit anything below here, if we did it right :) # #------------------------------------------------------------------------------# # these can be set from outside without (usually) breaking the build CFLAGS = -Wall -W -g LDFLAGS = LIBS = # get library version from meta file LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd) ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 644 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION) ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION) UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch SOURCES += $(SOURCES_iphoneos) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS) ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT) ALL_LIBS += -lc $(LIBS_iphoneos) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) else # Mac OS X SOURCES += $(SOURCES_macosx) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4 else SOURCES += $(SOURCES_iphoneos) # Starting with Xcode 4.0, the PowerPC compiler is not installed by default ifeq ($(wildcard /usr/llvm-gcc-4.2/libexec/gcc/powerpc*), ) FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.5 else FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 endif endif ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include # if the 'pd' binary exists, check the linking against it to aid with stripping BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -bundle $(BUNDLE_LOADER) \ -undefined dynamic_lookup -L/sw/lib SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0 ALL_LIBS += -lc $(LIBS_macosx) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif # Tho Android uses Linux, we use this fake uname to provide an easy way to # setup all this things needed to cross-compile for Android using the NDK ifeq ($(UNAME),ANDROID) CPU := arm SOURCES += $(SOURCES_android) EXTENSION = so SHARED_EXTENSION = so OS = android PD_PATH = /usr NDK_BASE := /opt/android-ndk NDK_PLATFORM_LEVEL ?= 5 NDK_ABI=arm NDK_COMPILER_VERSION = 4.6 NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_LEVEL)/arch-$(NDK_ABI) NDK_UNAME:=$(shell uname -s | tr '[A-Z]' '[a-z]') ifeq ($(NDK_ABI),x86) HOST = i686-linux-android NDK_TOOLCHAIN = $(NDK_ABI)-$(NDK_COMPILER_VERSION) else HOST = $(NDK_ABI)-linux-androideabi NDK_TOOLCHAIN = $(HOST)-$(NDK_COMPILER_VERSION) endif NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/$(NDK_TOOLCHAIN)/prebuilt/$(NDK_UNAME)-$(NDK_PROCESSOR) CC := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-gcc --sysroot=$(NDK_SYSROOT) LD := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-ld OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -rdynamic -shared SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared LIBS += -lc $(LIBS_android) STRIP := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-strip) \ --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU) # GNU/Hurd, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU/kFreeBSD) # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll SHARED_EXTENSION = dll OS = cygwin PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc -lpd $(LIBS_cygwin) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_windows) EXTENSION = dll SHARED_EXTENSION = dll OS = windows PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd) # MinGW doesn't seem to include cc so force gcc CC=gcc OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -mms-bitfields ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import SHARED_LDFLAGS += -shared ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS) ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS) ALL_LIBS := $(LIBS) $(ALL_LIBS) SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c) SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h) SHARED_LIB ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) .PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" %.$(EXTENSION): %.o $(SHARED_LIB) $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB) chmod a-x "$*.$(EXTENSION)" # this links everything into a single binary file $(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS) chmod a-x $(LIBRARY_NAME).$(EXTENSION) $(SHARED_LIB): $(SHARED_SOURCE:.c=.o) $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_LIBS) install: libdir_install # The meta and help files are explicitly installed to make sure they are # actually there. Those files are not optional, then need to be there. libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES))" || (\ $(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION)))) test -z "$(strip $(SHARED_LIB))" || \ $(INSTALL_DATA) $(SHARED_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) # install library linked as single binary single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) install-doc: $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \ $(INSTALL_DATA) $(HELPPATCHES) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt install-examples: test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \ done install-manual: test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \ done install-unittests: test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ done clean: -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o) -rm -f -- $(SOURCES:.c=.$(EXTENSION)) -rm -f -- $(LIBRARY_NAME).o -rm -f -- $(LIBRARY_NAME).$(EXTENSION) -rm -f -- $(SHARED_LIB) distclean: clean -rm -f -- $(DISTBINDIR).tar.gz -rm -rf -- $(DISTBINDIR) -rm -f -- $(DISTDIR).tar.gz -rm -rf -- $(DISTDIR) -rm -f -- $(ORIGDIR).tar.gz -rm -rf -- $(ORIGDIR) $(DISTBINDIR): $(INSTALL_DIR) $(DISTBINDIR) libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) # tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR) $(DISTDIR): $(INSTALL_DIR) $(DISTDIR) $(ORIGDIR): $(INSTALL_DIR) $(ORIGDIR) dist: $(DISTDIR) $(INSTALL_DATA) Makefile $(DISTDIR) $(INSTALL_DATA) README.txt $(DISTDIR) $(INSTALL_DATA) LICENSE.txt $(DISTDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR) test -z "$(strip $(ALLSOURCES))" || \ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR) test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \ $(INSTALL_DATA) $(LIBRARY_NAME).c $(DISTDIR) test -z "$(strip $(SHARED_HEADER))" || \ $(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR) test -z "$(strip $(SHARED_SOURCE))" || \ $(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) $(DISTDIR) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR) test -z "$(strip $(HELPPATCHES))" || \ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR) test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DISTDIR)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \ done test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DISTDIR)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \ done test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DISTDIR)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ done tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR) # make a Debian source package dpkg-source: debclean make distclean dist mv $(DISTDIR) $(ORIGDIR) tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR) rm -f -- $(DISTDIR).tar.gz rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) etags: TAGS TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags $(wildcard $(PD_INCLUDE)/*.h) etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl showsetup: @echo "CC: $(CC)" @echo "CFLAGS: $(CFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)" @echo "ALL_CFLAGS: $(ALL_CFLAGS)" @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)" @echo "ALL_LIBS: $(ALL_LIBS)" @echo "PD_INCLUDE: $(PD_INCLUDE)" @echo "PD_PATH: $(PD_PATH)" @echo "objectsdir: $(objectsdir)" @echo "LIBRARY_NAME: $(LIBRARY_NAME)" @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)" @echo "SOURCES: $(SOURCES)" @echo "SHARED_HEADER: $(SHARED_HEADER)" @echo "SHARED_SOURCE: $(SHARED_SOURCE)" @echo "SHARED_LIB: $(SHARED_LIB)" @echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)" @echo "PDOBJECTS: $(PDOBJECTS)" @echo "ALLSOURCES: $(ALLSOURCES)" @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))" @echo "UNAME: $(UNAME)" @echo "CPU: $(CPU)" @echo "pkglibdir: $(pkglibdir)" @echo "DISTDIR: $(DISTDIR)" @echo "ORIGDIR: $(ORIGDIR)" @echo "NDK_TOOLCHAIN: $(NDK_TOOLCHAIN)" @echo "NDK_BASE: $(NDK_BASE)" @echo "NDK_SYSROOT: $(NDK_SYSROOT)" hexloader-v1.7/LICENSE.txt0000644000175000017500000000304512564442623015611 0ustar zmoelnigzmoelnigThis software is copyrighted by IOhannes m zmölnig and others. The following terms (the "Standard Improved BSD License") apply to all files associated with the software unless explicitly disclaimed in individual files: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. hexloader-v1.7/README.txt0000644000175000017500000001124311674625147015470 0ustar zmoelnigzmoelnig--------- hexloader --------- (c) copyleft 2006-2007 IOhannes m zmölnig, IEM the problem ----------- when dealing with abstractions and single-file externals, we have a 1-to-1 correspondence between an objectclass and a file. examples: the [expr] object matches an external "./expr.pd_linux" the [zexy/nop~] object matches an abstraction "./zexy/nop~.pd" general: the object [] matches a file ".$EXT" when dealing with externals, the name of the objectclass is also to be found in the setup function within the external example: to load the "expr" external, Pd will look for a function "expr_setup()" within the file "./expr.pd_linux" general: the external "" has to provide a setup-function "void _setup(void)" this works fine, as long as there are no special characters involved: according to the above scheme, when loading the external "expr~" Pd should actually be looking for "expr~_setup()" within the file "./expr~.pd_linux"; unfortunately, the C-language (wherein most externals are written) does not allow function-names to use any characters other than "a-zA-Z0-9_". therefore the name "expr~_setup()" is invalid; therefore, Pd handles the case of the trailing "~" in a special way: it actually expands the "~" to "_tilde" and looks for "expr_tilde_setup()" general: the object [~] corresponds to an external "~.pd_linux" which offers a setupfunction "_tilde_setup()" unfortunately this doesn't work well for a larger number of characters forbidden in C-functionames. example: how should the setupfunction for an objectclass [~<~] be named? additionally, several filesystems have problems with certain characters. for instance, you cannot use the character '>' on FAT32 filesystems. but how do you then create a file for the objectclass [>~]? a solution ---------- one solution is to just forbid objects with weird (non alphanumerical) names. pretty frustrating another solution ---------------- use libraries with valid names that hold objects with weird names a better solution ----------------- another solution is to translate the forbidden characters into allowed ones. for instance, every ASCII-character can be called by it's name (e.g. 'a') as well as by it's numeric value "97" (or in hex: "0x61") the here-proposed solution is, to replace every illegal character by it's hexadecimal representation (in lowercase). examples: [>] corresponds to the file "0x3e.pd" [>~] corresponds to the file "0x3e0x7e.pd" or to "0x3e~.pd" [a>b] corresponds to the file "a0x3eb.pd" the same system can be applied to the setup-functions: examples: [a>b] has a setupfunction "a0x3eb_setup()" CAVEAT: C also forbids to start function names with numeric values. therefore, this is a nono: [>]'s setupfunction would be "0x3e_setup()" (ILLEGAL) we can simply fix this by putting the "setup()" in front: [>] has a setupfunction "setup_0x3e()" implementation -------------- the "hexloader" external adds the possibility to Pd use the proposed alternative naming scheme. just load the "hexloader" lib, and the next time you try to create the (yet unknown) object X, Pd will also look for several alternatives example: [>~] ">~.pd_linux" (filename ILLEGAL on SOME filesystems) >~_setup() (ILLEGAL functioname) setup_>~ (ILLEGAL functioname) 0x3e0x7e_setup() (ILLEGAL functioname) setup_0x3e0x7e() "0x3e~.pd_linux" 0x3e~_setup() (ILLEGAL functioname) setup_0x3e~() 0x3e0x7e_setup() (ILLEGAL functioname) setup_0x3e0x7e() "0x3e0x7e.pd_linux" 0x3e0x7e_setup() (ILLEGAL functioname) setup_0x3e0x7e() ">~.pd" (filename ILLEGAL on SOME filesystems) "0x3e~.pd" "0x3e0x7e.pd" the hexloader will try one alternative after another until it finds one that actually works (there is no problem in querying the ILLEGAL names, it is just impossible to create such filenames/setupfunctions) handling of "/" --------------- a special problem is the "/" character, as this might be a special character in the name of an object and the path-delimiter example: "a/b" might be a file "b" in the directory "a" or just "a/b" solution -------- hexloader treats the "/" in a special way, as it tries all possibilities example: [a/b} a/b (file "b" in directory "a") b_setup() setup_b() a0x2fb (file "a/b") a0x2fb_setup() setup_a0x2fb() CAVEATS ======= obviously the abstraction "0x3e.pd" can be addressed as both [>~] and [0x3e] this basically means, we have now an n-to-1 correspondence! in the case of externals this could be fixed by only using the "setup_*" naming scheme (instead of Pd's standard "*_setup()") for practical reasons this has been dumped (too many devs created the wrong setupfunction and couldn't tell why the externals would not load) hexloader-v1.7/hexloader-meta.pd0000644000175000017500000000026612564447055017220 0ustar zmoelnigzmoelnig#N canvas 15 49 200 200 10; #N canvas 25 49 420 300 META 1; #X text 13 41 NAME hexloader; #X text 10 25 AUTHOR zmoelnig@iem.at; #X text 10 10 VERSION v1.7; #X restore 10 10 pd META; hexloader-v1.7/FAQ.txt0000644000175000017500000000213611674625147015143 0ustar zmoelnigzmoelnig============================================ = things you might ask yourself frequently = ============================================ Q: what's this? A: please read the README.txt for an explanation Q: it doesn't work! A: try increasing the verbosity of Pd by adding the "-verbose" flag _multiple times_ to the startup flags; [hexloader] will become more talkative at verbosity-level 2, which will help you (or us) to find the source of your problem Q: hexloading abstraction does not work A1: it is not enabled by default! you can enable it by setting the HEXLOADER_PATCHES preprocessor-define either via the Makefile or within the source file. the reason why it is disabled is: A2: hexloading abstractions (as opposed to "externals" written in other languages (anything that uses the loader-mechanism; e.g. C or lua or python externals; but not Pd-abstractions)) is currently broken as it does not correctly resolve abstractions embedded within hexloaded abstractions. that's a problem of Pd's abstraction-loading mechanism which i would rather solve on the Pd-side hexloader-v1.7/hexloader.c0000644000175000017500000005636212564447034016120 0ustar zmoelnigzmoelnig/* * hexloader * Copyright (c) 2007-2009 IOhannes m zmölnig @ IEM * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," that comes with Pd. */ /* * this code adds an external "loader" to Miller S. Puckette's "pure data", * which allows the loading of libraries/externals with special characters * in the classname * * the infrastructure of this file is based on hcsteiner's "libdir" loader */ #ifdef __WIN32__ # define MSW #endif #include "m_pd.h" #if (PD_MINOR_VERSION >= 40) #if (PD_MINOR_VERSION < 42) // with 0.42 the loader_t made it into s_stuff.h # define MISSING_LOADER_T 1 #endif #include "s_stuff.h" #include "g_canvas.h" #include #include #include #ifdef DL_OPEN # include #endif #ifdef UNISTD # include # include #endif #ifdef _WIN32 # include # include #endif #ifdef __APPLE__ # include #endif /* for now hexloading abstractions does not work very well, * as it chokes when the hexloaded abstractions has nested abstractions * * if you really want to enable hexloading patches, * do so via the Makefile by defining HEXLOADER_PATCHES * */ //#define HEXLOADER_PATCHES #ifdef HEXLOADER_PATCHES void canvas_popabstraction(t_canvas *x); static void*hexloader_fakenew(t_symbol *s, int argc, t_atom *argv); t_pd pd_objectmaker; /* factory for creating "object" boxes */ #endif typedef struct _filepath { t_symbol*filename; t_symbol*pathname; } t_filepath; typedef void (*t_hexloader_setup)(void); #ifdef MISSING_LOADER_T /* definitions taken from s_loader.c, since they weren't in header orignally */ typedef int (*loader_t)(t_canvas *canvas, char *classname); void sys_register_loader(loader_t loader); void class_set_extern_dir(t_symbol *s); #endif /* ==================================================== */ typedef struct _hexloader { t_object x_obj; } t_hexloader; static t_class *hexloader_class; static char *version = "1.7"; static char*hex_dllextent[] = { #ifdef __FreeBSD__ ".b_i386", ".pd_freebsd", #endif #ifdef __linux__ # ifdef __x86_64__ ".l_ia64", # else ".l_i386", # endif ".pd_linux", #endif /* linux */ #ifdef __APPLE__ # ifndef MACOSX3 ".d_fat", # else ".d_ppc", # endif ".pd_darwin", #endif #ifdef __WIN32__ ".m_i386", ".dll", #endif 0}; /* zero-terminated list of extensions */ static char *patch_extent[]={ ".pd", ".pat", 0}; /** * object-names containing non-alphanumerics like [||~] * can (sometimes) be not represented on filesystems (e.g. * "|" is a forbidden character) and more often they * cannot be used to construct a valid setup-function * ("||~_setup" or "||_tilde_setup" are really bad). * the way the "~" is handled, is non-generic and thus * sub-optimal. * * as a solution me and hcs proposed an encoding into * alphanumeric-values, using a hexadecimal representation * of all characters but [0-9A-Za-z_] (e.g. "+" is ascii * 43 and is thus represented by "0x2b" (hex-value all * lowercase and prepended with "0x") * * e.g. if we have a new class "mtx_||", pd first attempts * to find a file called "mtx_||.dll". if it succeeds, it * will try to call the "mtx_||_setup()" function. * if that fails we suggest to try and call a function * "setup_mtx_0x7c0x7c()" (the keyword setup is now at the * beginning of the function-name, in order to prevent the * names starting with numbers and in order to distinguish * between the normal setup-methods). * if no "mtx_||.dll" can be found, pd should then search * for a file "mtx_0x7c0x7c.dll" (guaranteed to be * representable on any filesystem); search this file for * the 2 setup-functions. * if all fails try to find "mtx_||.pd" and then * "mtx_0x7c0x7c.pd" */ /* * ideally this loader could somehow call the object-instantiator recursively * but with changed classnames; * this would allow us to use the hexloader stuff for all kinds of other loaders * including abstractions */ /* -------------------- utilities --------------------- */ /* --- symlist_t: a linked list of symbols --- */ /* linked list of loaders */ typedef struct symlist_ { t_symbol* sym; struct symlist_ *next; } symlist_t; static symlist_t*g_abstractionclasses=NULL; static symlist_t*symlist_find(symlist_t*syms, t_symbol*sym) { symlist_t*dummy=syms; for(; dummy; dummy=dummy->next) { // post("checking '%s' vs '%s'", sym, dummy->sym); if (sym==dummy->sym) { // we already have this entry! // post("found sym %s=%s", sym, dummy->sym); return syms; } } return NULL; } static symlist_t*symlist_add(symlist_t*syms, t_symbol*sym) { symlist_t*dummy=syms; symlist_t*last=0; // symlist_print("adder contained:", syms); if(NULL==sym)return syms; if(!dummy) { dummy=(symlist_t*)getbytes(sizeof(symlist_t)); dummy->next=0; dummy->sym=sym; return dummy; } for(; dummy; dummy=dummy->next) { // post("checking '%s' vs '%s'", sym, dummy->sym); if (sym==dummy->sym) { // we already have this entry! // post("found sym %s=%s", sym, dummy->sym); return syms; } last=dummy; } dummy=last; dummy->next=(symlist_t*)getbytes(sizeof(symlist_t)); dummy=dummy->next; dummy->next=0; dummy->sym=sym; // symlist_print("adder contains::", syms); return syms; } /* --- namelist_t: a linked list of names --- */ /* linked list of loaders */ typedef struct namelist_ { char* name; struct namelist_ *next; } namelist_t; static void namelist_print(char*prefix, namelist_t*names) { for(; names; names=names->next) { if(prefix)startpost("%s:: ", prefix); post("%s",names->name); } } static namelist_t*namelist_add(namelist_t*names, char*name) { namelist_t*dummy=names; namelist_t*last=0; // namelist_print("adder contained:", names); if(name==0)return names; if(!dummy) { dummy=(namelist_t*)getbytes(sizeof(namelist_t)); dummy->next=0; dummy->name=name; return dummy; } for(; dummy; dummy=dummy->next) { // post("checking '%s' vs '%s'", name, dummy->name); if (!strncmp(name, dummy->name, MAXPDSTRING)) { // we already have this entry! // post("found name %s=%s", name, dummy->name); return names; } last=dummy; } dummy=last; dummy->next=(namelist_t*)getbytes(sizeof(namelist_t)); dummy=dummy->next; dummy->next=0; dummy->name=name; // namelist_print("adder contains::", names); return names; } static namelist_t*namelist_addlist(namelist_t*names, namelist_t*nl) { namelist_t*dummy=0; if(nl==0)return names; if(!names)return nl; /* try to add each entry in nl */ for(dummy=nl; dummy->next; dummy=dummy->next) { names=namelist_add(names, dummy->name); } return names; } static void namelist_clear(namelist_t*names) { namelist_t*dummy=0; while(names) { dummy=names->next; names->next=0; names->name=0; /* we dont care since the names are allocated in the symboltable anyhow */ freebytes(names, sizeof(namelist_t)); names=dummy; } } /* --- filelist_t: a linked list of filenames, each associated with a list of setupfunction names --- */ typedef struct filelist_ { char *name; namelist_t*setupfun; struct filelist_ *next; } filelist_t; static void filelist_print(char*prefix, filelist_t*files) { for(; files; files=files->next) { if(prefix)startpost("%s: ", prefix); post("%s",files->name); namelist_print("\t", files->setupfun); } } static filelist_t*filelist_add(filelist_t*files, char*name, namelist_t*setupfun) { filelist_t *last=0, *dummy=files; if(name==0)return files; if(!dummy) { dummy=(filelist_t*)getbytes(sizeof(filelist_t)); dummy->next=0; dummy->name=name; dummy->setupfun=namelist_addlist(0, setupfun); return dummy; } for(; dummy; dummy=dummy->next) { if (!strncmp(name, dummy->name, MAXPDSTRING)) { // we already have this entry! /* add additional setup-functions to this name */ dummy->setupfun=namelist_addlist(dummy->setupfun, setupfun); return files; } last=dummy; } dummy=last; /* this is a new entry, add it to the list */ dummy->next=(filelist_t*)getbytes(sizeof(filelist_t)); dummy=dummy->next; dummy->next=0; dummy->name=name; dummy->setupfun=namelist_addlist(0, setupfun); return files; } static filelist_t*filelist_addlist(filelist_t*files, filelist_t*nl) { filelist_t*dummy=0; if(nl==0)return files; if(!files)return nl; /* try to add each entry in nl */ for(dummy=nl; dummy->next; dummy=dummy->next) { files=filelist_add(files, dummy->name, dummy->setupfun); } return files; } static void filelist_clear(filelist_t*files) { filelist_t*dummy=0; while(files) { dummy=files->next; namelist_clear(files->setupfun); files->setupfun=0; files->name=0; /* we dont care since the files are allocated in the symboltable anyhow */ files->next=0; freebytes(files, sizeof(filelist_t)); files=dummy; } } /* ---------------- normalize names ------------------- */ /** * replace everything but [a-zA-Z0-9_] by "0x%x" * @return the normalized version of org */ static char*hexloader_normalize(char*org, int skipslash) { char*orgname=org; char altname[MAXPDSTRING]; t_symbol*s=0; int count=0; int i=0; for(i=0; i='0' && c<='9')|| /* [0-9] */ (c>='A' && c<='Z')|| /* [A-Z] */ (c>='a' && c<='z')||/* [a-z] */ (c=='_') || /* [_] */ (skipslash && c=='/') ) { altname[i]=c; i++; } else /* a "bad" character */ { sprintf(altname+i, "0x%02x", c); i+=4; count++; } orgname++; } s=gensym(altname); // post("normalize=%s", s->s_name); return s->s_name; } /** * replace only / \ : * ? " < > | by 0x%x since these are forbidden on some filesystems * @return the normalized version of org */ static char*hexloader_fsnormalize(char*org) { char*orgname=org; char altname[MAXPDSTRING]; t_symbol*s=0; char forbiddenchars[]={ // '/', '\\', ':', '*', '?', '"', '<', '>', '|', '\\', ':', '*', '?', '"', '<', '>', '|', 0}; int count=0; int i=0; for(i=0; is_name); return s->s_name; } static filelist_t*hexloader_deslashify(filelist_t*names, char*prefix, char*postfix) { filelist_t*result=names; int i=0; char*cp=0; char buf[MAXPDSTRING]; t_symbol*s; snprintf(buf, MAXPDSTRING, "%s%s", prefix, postfix); s=gensym(buf); result=filelist_add(result, s->s_name, 0); for(cp=postfix; *cp; cp++) { if(*cp=='/') { char *postfix2=postfix+i+1; char buf2[MAXPDSTRING]; snprintf(buf2, MAXPDSTRING, "%s", prefix); strncat(buf2, postfix, i); strcat(buf2, "/"); result=hexloader_deslashify(result, buf2, postfix2); snprintf(buf2, MAXPDSTRING, "%s", prefix); strncat(buf2, postfix, i); strcat(buf2, "0x2f"); result=hexloader_deslashify(result, buf2, postfix2); } i++; } return result; } static namelist_t*hexloader_fsnormalize_list(namelist_t*names, char*org) { char*simple=hexloader_fsnormalize(org); names=namelist_add(names, org); names=namelist_add(names, simple); return names; } /* ---------------- core code ------------------- */ static namelist_t*hexloader_getaltsetups(namelist_t*names, char*name) { char sbuf[MAXPDSTRING]; t_symbol*s; snprintf(sbuf, MAXPDSTRING, "%s_setup", name); s=gensym(sbuf); names=namelist_add(names, s->s_name); snprintf(sbuf, MAXPDSTRING, "setup_%s", name); s=gensym(sbuf); names=namelist_add(names, s->s_name); return names; } static namelist_t*hexloader_getaltsetup(namelist_t*names, char*name) { namelist_t*result=names; char*strippedname=name; char*cp=name; while(*cp++) { if(*cp=='/'){ strippedname=cp+1; } } result=hexloader_getaltsetups(result, strippedname); result=hexloader_getaltsetups(result, hexloader_normalize(strippedname, 0)); // post("added to %s\n", name); return result; } static filelist_t*hexloader_fillaltsetupfuns(filelist_t*files) { filelist_t*f; for(f=files; f; f=f->next) { f->setupfun=namelist_addlist(f->setupfun, hexloader_getaltsetup(f->setupfun, f->name)); } return files; } /** * @return a 0-terminated array of all filenames we consider to be alternative names and associated setup-functions */ static filelist_t*hexloader_getalternatives(char*org) { filelist_t*files=0; files=filelist_add(files, org, 0); files=filelist_add(files, hexloader_fsnormalize(org), 0); files=filelist_add(files, hexloader_normalize(org, 1),0); files=filelist_add(files, hexloader_normalize(org, 0),0); files=hexloader_deslashify(files, "", org); hexloader_fillaltsetupfuns(files); // filelist_print("ALTER: ", files); return files; } static int hexloader_doload(char*filename, char*setupfun) { t_hexloader_setup makeout=0; #ifdef DL_OPEN void *dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (!dlobj) { verbose(2, "%s: %s", filename, dlerror()); class_set_extern_dir(&s_); return (0); } makeout = (t_hexloader_setup)dlsym(dlobj, setupfun); #elif defined __WIN32__ HINSTANCE ntdll; sys_bashfilename(filename, filename); ntdll = LoadLibrary(filename); if (!ntdll) { verbose(2, "%s: couldn't load", filename); class_set_extern_dir(&s_); return (0); } makeout = (t_hexloader_setup)GetProcAddress(ntdll, setupfun); #else error("alas! somebody (you?) has compiled [hexloader] without support for loading externals...how should i load?"); #endif if (!makeout) { verbose(2, "hexload object: Symbol \"%s\" not found", setupfun); class_set_extern_dir(&s_); return 0; } (*makeout)(); return (1); } /** * open a file (given via pathname+filename) as dll and call various * setupfunctions (as can be calculated from the altnames array * @param pathname the path of the file * @param filename the name (without path) of the file * @param altnames a zero-terminated array of possible non-generic parts of the setup-function * @return 1 on success, 0 otherwise */ static int hexloader_loadfile(char*pathname, char*filename, namelist_t*altnames) { char setupfun[MAXPDSTRING]; char fullfile[MAXPDSTRING]; namelist_t*altname=altnames; sprintf(fullfile, "%s/%s", pathname, filename); while(altname) { verbose(0, "hexloader trying %s (%s)", fullfile, altname->name); if(hexloader_doload(fullfile, altname->name)) return 1; altname=altname->next; } return 0; } /** * try to open a file (given via pathname+filename) as a patcher * TODO: make this work.... * @param pathname the path of the file * @param filename the name (without path) of the file * @param altclassname the alternative classname we currently use... * @return 1 on success, 0 otherwise */ /* this only gets called if we have already found an abstraction-file */ static t_filepath*hexloader_loadpatch(char*pathname, char*filename, char*altclassname, char*realclassname) { char fullfile[MAXPDSTRING]; t_symbol*realname=gensym(realclassname); t_filepath*result=NULL; sprintf(fullfile, "%s/%s", pathname, filename); #ifdef HEXLOADER_PATCHES if(symlist_find(g_abstractionclasses, realname)) { // already in the list } else { class_addcreator((t_newmethod)hexloader_fakenew, realname, A_GIMME, 0); g_abstractionclasses=symlist_add(g_abstractionclasses, realname); } result=getbytes(sizeof(t_filepath)); result->filename=gensym(filename); result->pathname=gensym(pathname); #else error("BUG: hexloader not loading abstraction: %s (not yet implemented)", fullfile); #endif /* HEXLOADER_PATCHES */ return result; } /** * the actual loader: * example-nomenclature: * "class": the original class-name (e.g. containing weird characters) * "CLASS": the normalized class-name (with all weirdness replaced by hex-representations * "ext" : the external-extension (e.g. "dll" or "pd_linux" or...) * example: * trying to create an object [class] (and pd fails for whatever reasons, and thus callsus) * - search for a file "class.ext" in our search-path * + if found * try to call "class_setup()" function * if fails, try to call "setup_CLASS()" function * (if fails, try to call "CLASS_setup()" function) * - "class.ext" file not found * - search for a file "CLASS.ext" in our search-path * + if found * try to call "class_setup()" function * if fails, try to call "setup_CLASS()" function * (if fails, try to call "CLASS_setup()" function) * - if everything fails, return... * * @param canvas the context of the object to be created * @param classname the name of the object (external, library) to be created * @return 1 on success, 0 on failure */ static int hexloader_trylibraries(t_canvas*x, filelist_t*altnames0) { int fd = -1; char dirbuf[MAXPDSTRING]; char*nameptr; filelist_t*altnames=altnames0; /* try binaries */ while(altnames) { char*altname=altnames->name; int dll_index=0; char*dllextent=hex_dllextent[dll_index]; while(dllextent!=0) { if(NULL!=x) fd=canvas_open(x, altname, dllextent, dirbuf, &nameptr, MAXPDSTRING, 0); else fd = open_via_path(".", altname, dllextent, dirbuf, &nameptr, MAXPDSTRING, 0); if (fd >= 0) { close (fd); if(hexloader_loadfile(dirbuf, nameptr, altnames->setupfun)) { return 1; } } dll_index++; dllextent=hex_dllextent[dll_index]; } altnames=altnames->next; } return 0; } static t_filepath*hexloader_trypatches(t_canvas*x, filelist_t*altnames0, char*classname) { int fd = -1; char dirbuf[MAXPDSTRING]; char*nameptr; filelist_t*altnames=altnames0; /* try patches */ altnames=altnames0; while(altnames) { char*altname=altnames->name; int extindex=0; char*extent=patch_extent[extindex]; if(strcmp(altname, classname)) { /* we only try if it is worth trying... */ while(extent!=0) { if(NULL!=x) fd=canvas_open(x, altname, extent, dirbuf, &nameptr, MAXPDSTRING, 0); else fd = open_via_path(".", altname, extent, dirbuf, &nameptr, MAXPDSTRING, 0); if (fd >= 0) { close (fd); t_filepath*fp=hexloader_loadpatch(dirbuf, nameptr, altname, classname); if(fp) { return fp; } } extindex++; extent=patch_extent[extindex]; } } altnames=altnames->next; } return 0; } /** * this is the actual loader: * we first try to load an external with alternative (hexified) names * if this fails, we fall back to load a patch with these names */ static int hexloader_doloader(t_canvas *canvas, filelist_t*altnames0, char*classname) { t_filepath*fp=0; if(hexloader_trylibraries(canvas, altnames0)) return 1; fp=hexloader_trypatches(canvas, altnames0, classname); if(fp) { freebytes(fp, sizeof(t_filepath)); return 1; } return 0; } /** * recursive use of our powers: * try to load the object with alternative (hexified) names using other available loaders * when it comes to us, we just return 0... */ static int hexloader_callothers(t_canvas *canvas, filelist_t*altnames) { int result=0; while(altnames) { char*altname=altnames->name; verbose(2, "calling sys_load with '%s'", altname); result=sys_load_lib(canvas, altname); if(result==1) { return 1; } altnames=altnames->next; } return 0; } /** * the loader * * @param canvas the context of the object to be created * @param classname the name of the object (external, library) to be created * @return 1 on success, 0 on failure */ static int hexloader_loader(t_canvas *canvas, char *classname) { filelist_t*altnames=0; int result=0; static int already_loading=0; if(already_loading)return 0; already_loading=1; /* get alternatives */ altnames=hexloader_getalternatives(classname); /* try other loaders with our power */ if(result==0){ result=hexloader_callothers(canvas, altnames); } /* do the loading ourselves */ if(result==0) { result=hexloader_doloader(canvas, altnames, classname); } /* clean up */ filelist_clear(altnames); already_loading=0; return result; } #ifdef HEXLOADER_PATCHES static void*hexloader_fakenew(t_symbol*s, int argc, t_atom*argv) { t_pd*current = s__X.s_thing; t_filepath*fp=0; filelist_t*altnames=0; verbose(1, "hexloader: disguising as '%s'", s->s_name); if(!pd_objectmaker) { error("BUG: no pd_objectmaker found"); return 0; } /* get alternatives */ altnames=hexloader_getalternatives(s->s_name); /* do the loading */ fp=hexloader_trypatches(NULL, altnames, s->s_name); /* clean up */ filelist_clear(altnames); if(fp) { canvas_setargs(argc, argv); /* this fails when the object is loaded the first time * since m_class.c:new_anything() has set the "tryingalready" flag * the next time the object is created, it will work, since pd_objectmaker already knows about us and thus new_anything() never get's called */ /* ideas how to fix this: * - a simple hack is to register the abstractions to be hexloaded beforehand (but we have to know them before they are requested!) * - override the anything-method of pd_objectmaker "new_anything()" and call it ourselves (this makes the entire sys_loader hook absurd) * * claude's "abstraction caching" (http://lists.puredata.info/pipermail/pd-dev/2008-10/012334.html) works because he is injecting the code right * before sys_load_lib() and the "tryingalready" guards */ binbuf_evalfile(fp->filename, fp->pathname); freebytes(fp, sizeof(t_filepath)); if (s__X.s_thing != current) canvas_popabstraction((t_canvas *)(s__X.s_thing)); canvas_setargs(0, 0); return pd_newest(); } else return 0; } #endif /* HEXLOADER_PATCHES */ #endif /* PD_MINOR_VERSION>=40 */ static void*hexloader_new(t_symbol *s, int argc, t_atom *argv) { t_hexloader*x = (t_hexloader*)pd_new(hexloader_class); return (x); } void hexloader_setup(void) { /* relies on t.grill's loader functionality, fully added in 0.40 */ post("hexloader %s",version); post("\twritten by IOhannes m zmölnig, IEM "); post("\tcompiled on "__DATE__" at "__TIME__ " "); post("\tcompiled against Pd version %d.%d.%d.%s", PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION, PD_TEST_VERSION); #if (PD_MINOR_VERSION >= 40) sys_register_loader(hexloader_loader); #else error("to function, this needs to be compiled against Pd 0.40 or higher,\n"); error("\tor a version that has sys_register_loader()"); #endif hexloader_class = class_new(gensym("hexloader"), (t_newmethod)hexloader_new, 0, sizeof(t_hexloader), CLASS_NOINLET, A_GIMME, 0); }