pool-0.2.2+git20210923.1.40cb82e/0000755002537200253720000000000013630166142015543 5ustar zmoelnigzmoelnigpool-0.2.2+git20210923.1.40cb82e/readme.txt0000644002537200253720000001273413630166142017550 0ustar zmoelnigzmoelnigpool - a hierarchical storage object for PD and Max/MSP Copyright (c) 2002-2020 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. Donations for further development of the package are highly appreciated. Visit https://www.paypal.com/xclick/business=gr%40grrrr.org&item_name=pool&no_note=1&tax=0¤cy_code=EUR ---------------------------------------------------------------------------- Goals/features of the package: - pool can store and retrieve key/value pairs, where a key can be any atom and the value can be any list of atoms - pool can manage folders. A folder name can be any atom. - pool objects can be named and then share their data space - clipboard operations are possible in a pool or among several pools - file operations can load/save data from disk ---------------------------------------------------------------------------- IMPORTANT INFORMATION for all PD users: Put the pd-msvc/pool.dll, pd-linux/pool.pd_linux or pd-darwin/pool.pd_darwin file into the extra folder of the PD installation, or use a -path or -lib option at PD startup to find the pool external. Put the help-pool.pd file into the doc\5.reference subfolder of your PD installation. ---------------------------------------------------------------------------- IMPORTANT INFORMATION for all Max/MSP users: For Mac OSX put the max-osx/pool.mxd file into the folder /Library/Application Support/Cycling '74/externals For Mac OS9 put the max-os9/pool.mxe file into the externals subfolder of your Max/MSP installation For Windows put the max-msvc\pool.mxe file into the folder C:\program files\common files\Cycling '74\externals (english version) Put the pool.help file into the max-help folder. ============================================================================ BUILDING from source -------------------- You will need the flext C++ layer for PD and Max/MSP externals to compile this. See http://grrrr.org/ext/flext Download and unzip, or git-clone the package. Pure data - any platform supporting gcc-compatible compilers ------------------------------------------------------------ The pd-lib-builder project (https://github.com/pure-data/pd-lib-builder) is used to compile the project. A git subtree of this project is already present. The compilation is done using the GNU make tool and it will need additional information about the location of the flext source files, and possibly, Pure data, if a specific version should be used. This could be an example: make CPPFLAGS="-I ../flext/source" PDDIR="../../pure-data" For OS X, further flags can be needed: CFLAGS="-mmacosx-version-min=10.9" LDFLAGS="-mmacosx-version-min=10.9" pd/Max - Windows - Microsoft Visual C, MinGW: ---------------------------------------------------------- Start a command shell with your eventual build environment (e.g. run vcvars32.bat for Microsoft Visual Studio) then run ..\flext\build.bat (you would have to substitute ..\flext with the respective path to the flext package) pd/Max - OSX/Linux - GCC: ------------------------- From a shell run bash ../flext/build.sh (you would have to substitute ../flext with the respective path to the flext package) ============================================================================ Version history: 0.2.2: - fixed UTF-8 file load/save bug - fixed serious bug with clearing values and dirs. e.g. "clrall" and "clrrec" messages. - fixed double-free for clearing dirs and values - re-introduced a help message - fixed bug in nested-dir XML saving - changed printrec/printroot to display empty folders - new curdir attribute for getting/setting the current directory - changed pool name searching with STL code (more efficient) - added success/error reporting for file operations (through attribute outlet) - fixed handling of non-ASCII-characters - XML files are now encoded UTF-8 - implemented output sorting (ogetall, ogetrec, ogetsub) - fixed some potential buffer overrun problems 0.2.1: - fixed "cntsub"... directories in current directory have been forgotten - store/create also empty dirs with file I/O - more inlined functions and better symbol handling - added "seti" message to set elements at index - added "clri" message to erase elements at index - fixed bad bug: pool::priv was not initialized - enhanced and optimized atom parsing - escaped symbols (with \) for whitespace support on store and load - escape symbols also with "" to help the load routine - improved reading of legacy data by Frank Barknecht - use statically allocated lists where feasible - bug fix: [reset( didn't reset the current dir - file loading: fixed recognition of stringified directory names 0.2.0: - attributes (pool,private,echodir,absdir) - added "geti" message for retrieval of a value at an index - fixed bug in "get" message if key not present - adapted source to flext 0.4.1 - register methods at class creation - extensive use of hashing for keys and directories - database can be saved/loaded as XML data - fixed bug with stored numbers starting with - or + - relative file names will be based on the folder of the current patcher - added printall, printrec, printroot messages for console printout - added mkchdir, mkchsub to create and change to directories at once - change storage object only when name has changed 0.1.0: - first public release --------------------------------------------------------------------------- general: - what is output as value if it is key only? (Max->nothing!) - XML format ok? pool-0.2.2+git20210923.1.40cb82e/license.txt0000644002537200253720000000373613630166142017737 0ustar zmoelnigzmoelnigpool - a hierarchical storage object for PD and MaxMSP Copyright (C) 2002-2003 Thomas Grill 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In the official pool distribution, the GNU General Public License is in the file gpl.txt --------------------------------------------------------- OTHER COPYRIGHT NOTICES --------------------------------------------------------- This package uses the flext C++ layer - See its license text below: --- flext ---------------------------------------------- flext - C++ layer for Max/MSP and pd (pure data) externals Copyright (C) 2001-2003 Thomas Grill 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In the official flext distribution, the GNU General Public License is in the file gpl.txt pool-0.2.2+git20210923.1.40cb82e/pd-lib-builder/0000755002537200253720000000000013630166142020336 5ustar zmoelnigzmoelnigpool-0.2.2+git20210923.1.40cb82e/pd-lib-builder/README.md0000644002537200253720000001024213630166142021614 0ustar zmoelnigzmoelnig ### Makefile.pdlibbuilder ### Helper makefile for Pure Data external libraries. Written by Katja Vetter March-June 2015 for the public domain and since then developed as a Pd community project. No warranties. Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's ShakeNMake. GNU make version >= 3.81 required. ### characteristics ### * defines build settings based on autodetected target platform * defines rules to build Pd class- or lib executables from C or C++ sources * defines rules for libdir installation * defines convenience targets for developer and user * evaluates implicit dependencies for non-clean builds ### basic usage ### In your Makefile, define your Pd lib name and class files, and include Makefile.pdlibbuilder at the end of the Makefile. Like so: # Makefile for mylib lib.name = mylib class.sources = myclass1.c myclass2.c datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt include Makefile.pdlibbuilder For files in class.sources it is assumed that class name == source file basename. The default target builds all classes as individual executables with Pd's default extension for the platform. For anything more than the most basic usage, read the documentation sections in Makefile.pdlibbuilder. ### paths ### Makefile.pdlibbuilder >= v0.4.0 supports pd path variables which can be defined not only as make command argument but also in the environment, to override platform-dependent defaults: PDDIR: Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. PDINCLUDEDIR: Directory where Pd API m_pd.h should be found, and other Pd header files. Overrides the default search path. PDBINDIR: Directory where pd.dll should be found for linking (Windows only). Overrides the default search path. PDLIBDIR: Root directory for installation of Pd library directories. Overrides the default install location. ### documentation ### This README.md provides only basic information. A large comment section inside Makefile.pdlibbuilder lists and explains the available user variables, default paths, and targets. The internal documentation reflects the exact functionality of the particular version. For suggestions about project maintenance and advanced compilation see tips-tricks.md. ### versioning ### The project is versioned in MAJOR.MINOR.BUGFIX format (see http://semver.org), and maintained at https://github.com/pure-data/pd-lib-builder. Pd lib developers are invited to regulary check for updates, and to contribute and discuss improvements here. If you really need to distribute a personalized version with your library, rename Makefile.pdlibbuilder to avoid confusion. ### examples ### The list of projects using pd-lib-builder can be helpful if you are looking for examples, from the simplest use case to more complex implementations. - helloworld: traditional illustration of simplest use case - pd-windowing: straightforward real world use case of a small library - pd-nilwind / pd-cyclone: more elaborate source tree - zexy: migrated from autotools to pd-lib-builder ### projects using pd-lib-builder ### non-exhaustive list https://github.com/pure-data/helloworld https://github.com/electrickery/pd-nilwind https://github.com/electrickery/pd-maxlib https://github.com/electrickery/pd-sigpack https://github.com/electrickery/pd-tof https://github.com/electrickery/pd-windowing https://github.com/electrickery/pd-smlib https://github.com/porres/pd-cyclone https://github.com/porres/pd-else https://github.com/porres/pd-psycho https://git.iem.at/pd/comport https://git.iem.at/pd/hexloader https://git.iem.at/pd/iemgui https://git.iem.at/pd/iemguts https://git.iem.at/pd/iemlib https://git.iem.at/pd/iemnet https://git.iem.at/pd/iem_ambi https://git.iem.at/pd/iem_tab https://git.iem.at/pd/iem_adaptfilt https://git.iem.at/pd/iem_roomsim https://git.iem.at/pd/iem_spec2 https://git.iem.at/pd/mediasettings https://git.iem.at/pd/zexy https://git.iem.at/pd-gui/punish https://github.com/residuum/PuRestJson https://github.com/libpd/abl_link https://github.com/wbrent/timbreID https://github.com/MetaluNet/moonlib pool-0.2.2+git20210923.1.40cb82e/pd-lib-builder/CHANGELOG.txt0000644002537200253720000000664313630166142022377 0ustar zmoelnigzmoelnigChangelog for Makefile.pdlibbuilder. v0.6.0, dated 2019-12-21 - detect target platform (OS and architecture) rather than build platform (#55) - introduce optional user variable 'PLATFORM' for cross compilation - no longer build OSX/MacOS fat binaries by default (#21, #50) - do build fat binaries when 'extension=d_fat' is specified for OSX/MacOS - fix bug where minimum OSX/MacOS version wasn't defined, and set it to 10.6 v0.5.1, dated 2018-03-15 Fixes and improvements for Windows builds: - properly evaluate variables 'PDDIR' and 'PDBINDIR' to find pd.dll - define default path of 32 bit Pd on 64 bit Windows - link C++ externals with standard C libs on Windows, they don't load otherwise - strip installed Windows binaries by default (issues #34, #39, #41, #42 respectively) Warning for all platforms: variable 'PD_PATH' is no longer supported, use the equivalent 'PDDIR'. v0.5.0, dated 2018-01-23 Implement target architecture detection for Windows builds, and set appropriate options for 32 and 64 bit (used to be for 32 bit only). (feature, issue #37 #38, merge commit 215bf3e) v0.4.4, dated 2016-11-22 Use variable 'system' when evaluating 'for{Linux,Darwin,Windows}' (bugfix, issue #31, commit 2c14110) v0.4.3, dated 2016-11-02 Replace flags '-fpic' by 'fPIC'. (bugfix, issue #29, commit 426b38b) v0.4.2, dated 2016-10-30 Fix issue where incorrect message about m_pd.h is given. (bugfix, commit 2e13d8f) v0.4.1, dated 2016-10-27 Respect cflag for minimum OSX version when defined by lib makefile. (bugfix, pull request #22, commit 48c4127) v0.4.0, dated 2016-10-14 Introduced path variables PDDIR, PDINCLUDEDIR, PDBINDIR, PDLIBDIR which can also be defined in environment. (feature, issue #27, commit b0dab72) v0.3.1, dated 2016-10-13 Fix bug where pd.dll wouldn't be found. (bugfix, commit a0c87be) v0.3.0, dated 2016-10-09 Variable 'PD_PATH' introduced for pd-extended / pd-l2ork compatibility. (feature, issue #26, commit 41e9743) v0.2.8, dated 2016-10-09 Allow installed files to contain weird characters (notably '$'). (bugfix, pull request #20, commit 5b920b1) v0.2.7, dated 2016-10-04 Remove all default pd search paths except vanilla's. (discussion, issue #25, commit a6a89dc) v0.2.6, dated 2016-09-20 Redefined dependency checking so it won't stall rebuilds on OSX. (bugfix, issue #16, commit 9fd1795) v0.2.5, dated 2016-06-26 Fixed dependency checking for object files in other directories. (bugfix, commit f06e550) v0.2.4, dated 2016-06-25 Fixed regression bug that disabled all dependency checking. (bugfix, commit 1d7bb5e) v0.2.3, dated 2016-03-29 Disabled dependency checking for OSX <= 10.5 because it stalled rebuilds. (bugfix, issue #16, commit eb614fd) v0.2.2, dated 2016-03-28 Removed target 'pre' because it forced rebuild of everything in 'all'. (bugfix, issue #17, commit c989c8e) v0.2.1, dated 2015-12-27 Implement / respect 'CPPFLAGS','CFLAGS'and 'LDFLAGS'. (bugfix, issue #5, commit 98f3582) v0.2.0, dated 2015-12-19 Added per-platform multiline defines 'forLinux', 'forDarwin', 'forWindows'. (feature, pull request #9, commit 3946ea5) v0.1.0, dated 2015-12-08 Added targets 'pre' and 'post' to automatically run before and after 'all'. (feature, pull request #4, commit a5678ac) v0.0.2, dated 2015-12-06 Improved methods for searching pd paths. (bugfix, commit ed37e6b) v0.0.1, dated 2015-10-31 Fixed expansion of variable 'lib.version'. (bugfix, issue #1, commit 974b617) v0.0.0, dated 2015-06-24 Initial version. (commit 16517a2) pool-0.2.2+git20210923.1.40cb82e/pd-lib-builder/tips-tricks.md0000644002537200253720000001625613630166142023146 0ustar zmoelnigzmoelnigpd-lib-builder cheatsheet ========================= # Creating special builds ## cross-compiling on linux x86_64 for other platforms Using pd-lib-builder >=0.6.0 we can define variable `PLATFORM` to specify a target triplet for cross-compilation. Example to build W32 binaries (assuming package `mingw-w64` is installed and a W32 package for Pd is unzipped into a path `${PDWIN32}`: make PLATFORM=x86_64-w64-mingw32 PDDIR="${PDWIN32}" #### older pd-lib-builder versions Using pd-lib-builder < 0.6.0, in the absence of variable `PLATFORM`, you would instead override variables `system`, `target.arch`, `CC` and / or `CXX`, `STRIP`. Example: make system=Windows target.arch=i686 CC=i686-w64-mingw32-gcc STRIP=i686-w64-mingw32-strip PDDIR="${PDWIN32}" #### toolchains Cross toolchains for relevant platforms in Debian Buster (install g++ with dependencies for a given platform to get the whole tool chain): - `arm-linux-gnueabihf` - `aarch64-linux-gnu` - `i686-linux-gnu` - `i686-w64-mingw32` and `x86_64-w64-mingw32` (install `mingw-w64`) OSX/MacOS cross tool chains are not distributed by Debian. Use project `osxcross` from Thomas Poechtraeger to create the tools. ## building double-precision externals At the time of writing (2018-02) there is no official Pd that supports double-precision numbers yet. However, if you do get hold of an experimental double-precision Pd, you can easily build your externals for 64-bit numbers: make CPPFLAGS="-DPD_FLOATSIZE=64" ## building externals for W64 (64-bit Windows) At the time of writing (2018-02) there is no official Pd that supports W64 yet. However, if you do get hold of an experimental W64 Pd, you can easily build your externals for this environment with make CPPFLAGS="-DPD_LONGINTTYPE=__int64" CC=x86_64-w64-mingw32-gcc To build a double-precision external for W64, use something like: make CPPFLAGS="-DPD_LONGINTTYPE=__int64 -DPD_FLOATSIZE=64" CC=x86_64-w64-mingw32-gcc ## TODO universal binaries on OSX # Project management In general it is advised to put the `Makefile.pdlibbuilder` into a separate subdirectory (e.g. `pd-lib-builder/`). This makes it much easier to update the `Makefile.pdlibbuilder` later You *should* also use a variable to the actual path of the Makefile.pdlibbuilder (even if you keep it in the root-directory), as this allows easy experimenting with newer (or older) (or site-specific) versions of the pd-lib-builder Makefile. ~~~make PDLIBBUILDER_DIR=pd-lib-builder/ include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder ~~~ ## Keeping pd-lib-builder up-to-date ### `git subtree` With git-subtrees, you make the pd-lib-builder repository (or any other repository for that matter) part of your own repository - with full history and everything - put nicely into a distinct subdirectory. Support for *manipulating* subtrees has been added with Git-v1.7.11 (May 2012). The nice thing however is, that from "outside" the subtree is part of your repository like any other directory. E.g. older versions of Git can clone your repository with the full subtree (and all it's history) just fine. You can also use git-archive to make a complete snapshot of your repository (including the subtree) - nice, if you e.g. want self-contained downloads of your project from git hosting platforms (like Github, Gitlab, Bitbucket,...) In short, `git subtree` is the better `git submodule`. So here's how to do it: #### Initial setup/check-out This will create a `pd-lib-builder/` directory containing the full history of the pd-lib-builder repository up to its release `v0.5.0` ~~~sh git subtree add --prefix=pd-lib-builder/ https://github.com/pure-data/pd-lib-builder v0.5.0 ~~~ This will automatically merge the `pd-lib-builder/` history into your current branch, so everything is ready to go. #### Cloning your repository with the subtree Nothing special, really. Just clone your repository as always: ~~~sh git clone https://git.example.org/pd/superbonk~.git ~~~ #### Updating the subtree Time passes and sooner or later you will find, that there is a shiny new pd-lib-builder with plenty of bugfixes and new features. To update your local copy to pd-lib-builder's current `master`, simply run: ~~~sh git subtree pull --prefix pd-lib-builder/ https://github.com/pure-data/pd-lib-builder master ~~~ #### Pulling the updated subtree into existing clones Again, nothing special. Just pull as always: ~~~sh git pull ~~~ #### Further reading More on the power of `git subtree` can be found online - https://medium.com/@v/git-subtrees-a-tutorial-6ff568381844 - https://www.atlassian.com/blog/git/alternatives-to-git-submodule-git-subtree - ... ### ~~`git submodule`~~ [DISCOURAGED] #### Initial setup/check-out To add a new submodule to your repository, just run `git submodule add` and commit the changes: ~~~sh git submodule add https://github.com/pure-data/pd-lib-builder git commit .gitmodules pd-lib-builder/ -m "Added pd-lib-builder as git-submodule" ~~~ #### Cloning your repository with the submodule When doing a fresh clone of your repository, pass the `--recursive` option to automatically fetch all submodules: ~~~sh git clone --recursive https://git.example.org/pd/superbonk~.git ~~~ If you've cloned non-recursively, you can initialize and update the submodules manually: ~~~sh git submodule init git submodule update ~~~ #### Updating the submodule Submodules are usually fixed to a given commit in their repository. To update the `pd-lib-builder` submodule to the current `master` do something like: ~~~sh cd pd-lib-builder git checkout master git pull cd .. git status pd-lib-builder git commit pd-lib-builder -m "Updated pd-lib-builder to current master" ~~~ #### Pulling the updated submodule into existing clones After you have pushed the submodule updates in your repository, other clones of the repository can be updated as follows: ~~~sh git pull ~~~ The above will make your repository aware, that the submodule is out-of-sync. ~~~sh $ LANG=C git status pd-lib-builder On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: pd-lib-builder (new commits) $ ~~~ In order to sync the submodule to the correct commit, run the following: ~~~sh git submodule update ~~~ #### Drawbacks `git submodule` has a number of drawbacks: - it requires special commands to synchronize the submodules, in addition to synching your repository. - you must make sure to use an URL for the submodule that is accessible to your potential users. e.g. using `git@github.com:pure-data/pd-lib-builder` is bad, because it requires everybody who wants to checkout your sources to have a github-account - even if they could checkout *your* repository anonymously. - submodules will be excluded from `git archive`. This means, that if you use a mainstream git provider (like Github, GitLab, Bitbucket,...) and make releases by creating a `git tag`, the automatically generated zipfiles with the sources will lack the submodule - and your users will not be able to compile your source code. In general, I would suggest to **avoid** `git submodule`, and instead use the better `git subtree` (above). pool-0.2.2+git20210923.1.40cb82e/pd-lib-builder/Makefile.pdlibbuilder0000644002537200253720000012660413630166142024447 0ustar zmoelnigzmoelnig# Makefile.pdlibbuilder dated 2019-12-21 version = 0.6.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. # Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's # ShakeNMake. # # Grab the newest version of Makefile.pdlibbuilder from # https://github.com/pure-data/pd-lib-builder/ # # GNU make version >= 3.81 required. # # #=== characteristics =========================================================== # # # - defines build settings based on autodetected OS and architecture # - defines rules to build Pd class- or lib executables from C or C++ sources # - defines rules for libdir installation # - defines convenience targets for developer and user # - evaluates implicit dependencies for non-clean builds # # #=== basic usage =============================================================== # # # In your Makefile, define your Pd lib name and class files, and include # Makefile.pdlibbuilder at the end of the Makefile. Like so: # # ________________________________________________________________________ # # # Makefile for mylib # # lib.name = mylib # # class.sources = myclass1.c myclass2.c # # datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt # # include Makefile.pdlibbuilder # ________________________________________________________________________ # # # For files in class.sources it is assumed that class basename == source file # basename. The default target builds all classes as individual executables # with Pd's default extension for the platform. For anything more than the # most basic usage, continue reading. # # #=== list of Makefile.pdlibbuilder API variables =============================== # # # Variables available for definition in your library Makefile: # # - lib.name # - lib.setup.sources # - class.sources # - common.sources # - shared.sources # - .class.sources # - .class.ldflags # - .class.ldlibs # - cflags # - ldflags # - ldlibs # - datafiles # - datadirs # - makefiles # - makefiledirs # - externalsdir # # Optional multiline defines evaluated per operating system: # # - forLinux # - forDarwin # - forWindows # # Variables available for your makefile or make command line: # # - make-lib-executable # - suppress-wunused # # Path variables for make command line or environment: # # - PDDIR # - PDINCLUDEDIR # - PDBINDIR # - PDLIBDIR # # Standard make variables for make command line or environment: # # - CPPFLAGS # - CFLAGS # - LDFLAGS # - CC # - CXX # - INSTALL # - STRIP # - DESTDIR # # Optional user variables for make command line or environment: # # - PLATFORM # # Deprecated path variables: # # - pdincludepath # - pdbinpath # - objectsdir # # #=== descriptions of Makefile.pdlibbuilder API variables ======================= # # # lib.name: # Name of the library directory as it will be installed / distributed. Also the # name of the lib executable in the case where all classes are linked into # a single binary. # # lib.setup.sources: # Source file(s) (C or C++) which must be compiled only when linking all classes # into a single lib binary. # # class.sources: # All sources files (C or C++) for which the condition holds that # class name == source file basename. # # .class.sources: # Source file(s) (C or C++) specific to class . Use this for # multiple-source classes or when class name != source file basename. # # common.sources: # Source file(s) which must be statically linked to each class in the library. # # shared.sources: # Source file(s) (C or C++) to build a shared dynamic link lib, to be linked # with all class executables. # # cflags, ldflags, ldlibs: # Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic # link libs) for the whole library. These flags are added to platform-specific # flags defined by Makefile.pdlibbuilder. # # .class.ldflags and .class.ldlibs: # Define ldflags resp. ldlibs specific to class . These flags are # added to platform-specific flags defined by Makefile.pdlibbuilder, and flags # defined in your Makefile for the whole library. Note: cflags can not be # defined per class in the current implementation. # # datafiles and datadirs: # All extra files you want to include in binary distributions of the # library: abstractions and help patches, example patches, meta patch, readme # and license texts, manuals, sound files, etcetera. Use 'datafiles' for all # files that should go into your lib rootdir and 'datadirs' for complete # directories you want to copy from source to distribution. # # forLinux, forDarwin, forWindows: # Shorthand for 'variable definitions for Linux only' etc. Use like: # define forLinux # cflags += -DLINUX # class.sources += linuxthing.c # endef # # makefiles and makefiledirs: # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # # make-lib-executable: # When this variable is defined 'yes' in your makefile or as command argument, # Makefile.pdlibbuilder will try to build all classes into a single library # executable (but it will force exit if lib.setup.sources is undefined). # If your makefile defines 'make-lib-executable=yes' as the library default, # this can still be overridden with 'make-lib-executable=no' as command argument # to build individual class executables (the Makefile.pdlibbuilder default.) # # suppress-wunused: # When this variable is defined ('yes' or any other value), -Wunused-variable, # -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, # but the other warnings from -Wall are retained. # # PDDIR: # Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and # PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. # # PDINCLUDEDIR: # Directory where Pd API m_pd.h should be found, and other Pd header files. # Overrides the default search path. # # PDBINDIR: # Directory where pd.dll should be found for linking (Windows only). Overrides # the default search path. # # PDLIBDIR: # Root directory for installation of Pd library directories. Overrides the # default install location. # # DESTDIR: # Prepended path component for staged install. # # PLATFORM: # Target platform for cross compilation in the form of GNU triplet: # cpu-vendor-os. Example: x86_64-w64-mingw32. This specifies the tool chain that # pdlibbuilder will use, if installed and locatable. System and architecture # will then be autodefined accordingly. In most cases no other variables need to # be overridden. # # CPPFLAGS: # Preprocessor flags which are not strictly required for building. # # CFLAGS: # Compiler flags which are not strictly required for building. Compiler flags # defined by Makefile.pdlibbuilder for warning, optimization and architecture # specification are overriden by CFLAGS. # # LDFLAGS: # Linker flags which are not strictly required for building. Linker flags # defined by Makefile.pdlibbuilder for architecture specification are overriden # by LDFLAGS. # # CC and CXX: # C and C++ compiler programs as defined in your build environment. # # INSTALL # Definition of install program. # # STRIP # Name of strip program. Default 'strip' can be overridden in cross compilation # environments. # # objectsdir: # Root directory for installation of Pd library directories, like PDLIBDIR but # not overridable by environment. Supported for compatibility with pd-extended # central makefile, but deprecated otherwise. # # pdincludepath, pdbinpath: # As PDINCLUDEDIR and PDBINDIR but not overridable by environment. Deprecated # as user variables. # # #=== paths ===================================================================== # # # Source files in directories other than current working directory must be # prefixed with their relative path. Do not rely on VPATH or vpath. # Object (.o) files are built in the directory of their source files. # Executables are built in current working directory. # # Default search path for m_pd.h and other API header files is platform # dependent, and overridable by PDINCLUDEDIR: # # Linux: /usr/include/pd # # OSX: /Applications/Pd*.app/Contents/Resources/src # # Windows: %PROGRAMFILES%/Pd/src # %PROGRAMFILES(X86)%/Pd/src (32 bit builds on 64 bit Windows) # # Default search path for binary pd.dll (Windows), overridable by PDBINDIR # # %PROGRAMFILES%/Pd/bin # %PROGRAMFILES(X86)%/Pd/bin (32 bit builds on 64 bit Windows) # # Default location to install pd libraries is platform dependent, and # overridable by PDLIBDIR: # # Linux: /usr/local/lib/pd-externals # OSX: ~/Library/Pd # Windows: %APPDATA%/Pd # # https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files # The rationale for not installing to ~/pd-externals by default on Linux # is that some people share the home dir between 32 and 64 bit installations. # # #=== targets =================================================================== # # # all: build $(executables) plus optional post target # post: target to build after $(executables) # alldebug: build all with -g option turned on for debug symbols # : force clean build of an individual class # .pre: make preprocessor output file in current working directory # .lst: make asm/source output file in current working directory # # install: install executables and data files # clean: remove build products from source tree # # help: print help text # vars: print makefile variables # allvars: print all variables # depend: print generated prerequisites # dumpmachine: print compiler output of option '-dumpmachine' # coffee: dummy target # # Variable $(executables) expands to class executables plus optional shared lib, # or alternatively to single lib executable when make-lib-executable=true. # Targets pre and post can be defined by library makefile. Make sure to include # Makefile.pdlibbuilder first so default target all will not be redefined. # # #=== Pd-extended libdir concept ================================================ # # # For libdir layout as conceived by Hans-Christoph Steiner, see: # # https://puredata.info/docs/developer/Libdir # # Files README.txt, LICENSE.txt and -meta.pd are part of the libdir # convention. Help patches for each class and abstraction are supposed to be # available. Makefile.pdlibbuilder does not force the presence of these files # however. It does not automatically include such files in libdir installations. # Data files you want to include in distributions must be defined explicitly in # your Makefile. # # #=== Makefile.pdlibbuilder syntax conventions ================================== # # # Makefile.pdlibbuilder variable names are lower case. Default make variables, # environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) # are upper case. Use target 'allvars' to print all variables and their values. # # 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. # Words in variables expressing a function or command are separated by dashes, # like in 'make-lib-executable'. # # #=== useful make options ======================================================= # # # Use 'make -d ' to print debug details of the make process. # Use 'make -p ' to print make's database. # # #=== TODO ====================================================================== # # # - decide whether to use -static-libgcc or shared dll in MinGW # - cygwin support # - android support # - figure out how to handle '$' in filenames # - add makefile template targets dpkg-source dist libdir distclean tags? # # #=== end of documentation sections ============================================= # # ################################################################################ ################################################################################ ################################################################################ # GNU make version 3.81 (2006) or higher is required because of the following: # - function 'info' # - variable '.DEFAULT_GOAL' # force exit when make version is < 3.81 ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) $(error GNU make version 3.81 or higher is required) endif # Relative path to externals root dir in multi-lib source tree like # pd-extended SVN. Default is parent of current working directory. May be # defined differently in including makefile. externalsdir ?= .. # variable you can use to check if Makefile.pdlibbuilder is already included Makefile.pdlibbuilder = true ################################################################################ ### variables: library name and version ######################################## ################################################################################ # strip possibles spaces from lib.name, they mess up calculated file names lib.name := $(strip $(lib.name)) # if meta file exists, check library version metafile := $(wildcard $(lib.name)-meta.pd) ifdef metafile lib.version := $(shell sed -n \ 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ $(metafile)) endif ################################################################################ ### variables: files ########################################################### ################################################################################ #=== sources =================================================================== # (re)define .class.sources using file names in class.sources define add-class-source $(notdir $(basename $v)).class.sources += $v endef $(foreach v, $(class.sources), $(eval $(add-class-source))) # derive class names from .class.sources variables sourcevariables := $(filter %.class.sources, $(.VARIABLES)) classes := $(basename $(basename $(sourcevariables))) # accumulate all source files specified in makefile classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) all.sources := $(classes.sources) $(lib.setup.sources) \ $(shared.sources) $(common.sources) #=== object files ============================================================== # construct object filenames from all C and C++ source file names classes.objects := $(addsuffix .o, $(basename $(classes.sources))) common.objects := $(addsuffix .o, $(basename $(common.sources))) shared.objects := $(addsuffix .o, $(basename $(shared.sources))) lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources))) all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ $(lib.setup.objects) #=== executables =============================================================== # use recursive variables here because executable extension is not yet known # construct class executable names from class names classes.executables = $(addsuffix .$(extension), $(classes)) # construct shared lib executable name if shared sources are defined ifdef shared.sources shared.lib = lib$(lib.name).$(shared.extension) else shared.lib = endif ################################################################################ ### target platform detection ################################################## ################################################################################ #=== target platform =========================================================== # PLATFORM: optional user variable to define target platform for cross # compilation. Redefine build tools accordingly. PLATFORM should match # the exact target prefix of tools present in $PATH, like x86_64-w64-mingw32, # x86_64-apple-darwin12 etc. Tool definitions are exported to ensure submakes # will get the same. ifneq ($(PLATFORM),) ifneq ($(findstring darwin, $(PLATFORM)),) export CC = $(PLATFORM)-cc export CXX = $(PLATFORM)-c++ export CPP = $(PLATFORM)-cc else export CC = $(PLATFORM)-gcc export CXX = $(PLATFORM)-g++ export CPP = $(PLATFORM)-cpp endif STRIP = $(PLATFORM)-strip endif # Let (native or cross-) compiler report target triplet and isolate individual # words therein to facilitate later processing. target.triplet := $(subst -, ,$(shell $(CC) -dumpmachine)) #=== operating system ========================================================== # The following systems are defined: Linux, Darwin, Windows. GNU and # GNU/kFreeBSD are treated as Linux to get the same options. ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) system = Linux endif ifneq ($(filter darwin%, $(target.triplet)),) system = Darwin endif ifneq ($(filter mingw% cygwin%, $(target.triplet)),) system = Windows endif # evaluate possible system-specific multiline defines from library makefile $(eval $(for$(system))) # TODO: Cygwin, Android #=== architecture ============================================================== # The following CPU names can be processed by pdlibbuilder: # i*86 Intel 32 bit # x86_64 Intel 64 bit # arm ARM 32 bit # aarch64 ARM 64 bit target.arch := $(firstword $(target.triplet)) ################################################################################ ### variables per platform ##################################################### ################################################################################ #=== flags per architecture ==================================================== # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, # arch.c.flags are overriden below. To see gcc's default architecture flags: # $ gcc -Q --help=target # ARMv6: Raspberry Pi 1st gen, not detectable from target.arch ifeq ($(shell uname), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard # ARMv7: Beagle, Udoo, RPi2 etc. else ifeq ($(target.arch), arm) arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard # ARMv8 64 bit, not tested yet else ifeq ($(target.arch), aarch64) arch.c.flags = -mcpu=cortex-a53 # Intel 32 bit, build with SSE and SSE2 instructions else ifneq ($(filter i%86, $(target.arch)),) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions else ifeq ($(target.arch), x86_64) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 # if none of the above architectures detected else arch.c.flags = endif #=== flags and paths for Linux ================================================= ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals pdincludepath := $(wildcard /usr/include/pd) extension = pd_linux cpp.flags := -DUNIX c.flags := -fPIC c.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags c.ldlibs := -lc -lm cxx.flags := -fPIC -fcheck-new cxx.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) endif #=== flags and paths for Darwin ================================================ # LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when # compiling with g++. ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd pdincludepath := $(firstword $(wildcard \ /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin cpp.flags := -DUNIX -DMACOSX -I /sw/include c.flags := c.ldflags := -undefined suppress -flat_namespace -bundle c.ldlibs := -lc cxx.ldflags := -undefined suppress -flat_namespace -bundle cxx.ldlibs := -lc shared.extension = dylib shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 ifneq ($(filter %g++, $(CXX)),) cxx.flags := -fcheck-new endif ifeq ($(extension), d_fat) arch := i386 x86_64 else arch := $(target.arch) endif ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) version.flag := $(filter -mmacosx-version-min=%, $(cflags)) else version.flag = -mmacosx-version-min=10.6 endif arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) arch.ld.flags := $(arch.c.flags) endif #=== flags and paths for Windows =============================================== # Standard paths on Windows contain spaces, and GNU make functions treat such # paths as lists, with unintended effects. Therefore we must use shell function # ls instead of make's wildcard when probing for a path, and use double quotes # when specifying a path in a command argument. # Default paths in Mingw / Mingw-w64 environments. 'PROGRAMFILES' is standard # location for builds with native architecture, 'ProgramFiles(x86)' for i686 # builds on x86_64 Windows (detection method by Lucas Cordiviola). Curly braces # required because of parentheses in variable name. ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd ifeq ($(target.arch), i686) programfiles := ${ProgramFiles(x86)} else programfiles := $(PROGRAMFILES) endif pdbinpath := $(programfiles)/Pd/bin pdincludepath := $(programfiles)/Pd/src endif # Store default path to pd.dll in PDBINDIR if the latter is not user-defined. # For include path this is done in the platform-independent paths section below, # but for PDBINDIR it is done here so ld flags can be evaluated as immediate # variables. ifeq ($(system), Windows) ifdef PDDIR PDBINDIR := $(PDDIR)/bin endif PDBINDIR ?= $(pdbinpath) endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) cpp.flags := -DMSW -DNT ifeq ($(target.arch), i686) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse else ifeq ($(target.arch), x86_64) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse else arch.c.flags = endif extension = dll c.flags := c.ldflags := -static-libgcc -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" stripflags = --strip-all endif #=== paths ===================================================================== # Platform-dependent default paths are specified above, but overridable. # Path variables in upper case can be defined as make command argument or in the # environment. Variable 'objectsdir' is supported for compatibility with # the build system that pd-l2ork has inherited from pd-extended. PDINCLUDEDIR ?= $(pdincludepath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) ifdef PDDIR PDINCLUDEDIR := $(wildcard $(PDDIR)/src) endif # base path where all components of the lib will be installed by default installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) # check if include path contains spaces (as is often the case on Windows) # if so, store the path so we can later do checks with it pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) #=== accumulated build flags =================================================== # From GNU make docs: 'Users expect to be able to specify CFLAGS freely # themselves.' So we use CFLAGS to define options which are not strictly # required for compilation: optimizations, architecture specifications, and # warnings. CFLAGS can be safely overriden using a make command argument. # Variables cflags, ldflags and ldlibs may be defined in including makefile. optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing # suppress -Wunused-variable & Co if you don't want to clutter a build log ifdef suppress-wunused warn.flags += $(addprefix -Wno-unused-, function parameter value variable) endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) # flags for dependency checking (cflags from makefile may define -I options) depcheck.flags := $(cpp.flags) $(cflags) # architecture specifications for linker are overridable by LDFLAGS LDFLAGS := $(arch.ld.flags) # now add the same ld flags to shared dynamic lib shared.ldflags := $(shared.ldflags) $(LDFLAGS) # accumulated flags for C compiler / linker c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) c.ldlibs := $(c.ldlibs) $(ldlibs) # accumulated flags for C++ compiler / linker cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) ################################################################################ ### variables: tools ########################################################### ################################################################################ # aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument compile-c := $(CC) compile-cxx := $(CXX) ################################################################################ ### checks ##################################################################### ################################################################################ # At this point most variables are defined. Now do some checks and info's # before rules begin. # print Makefile.pdlibbuilder version before possible termination $(info ++++ info: using Makefile.pdlibbuilder version $(version)) # Terminate if target triplet remained empty, to avoid all sorts of confusing # scenarios and spurious bugs. ifeq ($(target.triplet),) $(error Command "$(CC) -dumpmachine" did not return a target triplet, \ needed for a build. \ Is compiler "$(CC)" installed in your PATH? ($(PATH)). \ Does compiler "$(CC)" support option "-dumpmachine"?) endif # 'forward declaration' of default target, needed to do checks all: # To avoid unpredictable results, make sure the default target is not redefined # by including makefile. ifneq ($(.DEFAULT_GOAL), all) $(error Default target must be 'all'.) endif # find out which target(s) will be made ifdef MAKECMDGOALS goals := $(MAKECMDGOALS) else goals := all endif # store path to Pd API m_pd.h if it is found ifdef PDINCLUDEDIR mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") endif # store path to pd.dll; if not found, ls will give a useful error ifeq ($(system), Windows) pddll := $(shell ls "$(PDBINDIR)/pd.dll") endif # when making target all, check if m_pd.h is found and print info about it ifeq ($(goals), all) $(if $(mpdh), \ $(info ++++ info: using Pd API $(mpdh)), \ $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) endif # print target info $(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) # when installing, print installpath info $(if $(filter install install-lib, $(goals)), $(info ++++ info: \ installpath is '$(installpath)')) #=== define executables ======================================================== # By default we build class executables, and optionally a shared dynamic link # lib. When make-lib-executable=yes we build all classes into a single lib # executable, on the condition that variable lib.setup.sources is defined. ifeq ($(make-lib-executable),yes) $(if $(lib.setup.sources), ,\ $(error Can not build library blob because lib.setup.sources is undefined)) executables := $(lib.name).$(extension) else executables := $(classes.executables) $(shared.lib) endif ################################################################################ ### rules: special targets ##################################################### ################################################################################ # Disable built-in rules. If some target can't be built with the specified # rules, it should not be built at all. MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: .PHONY: all post build-lib \ $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help ################################################################################ ### rules: build targets ####################################################### ################################################################################ # Target all forces the build of targets [$(executables) post] in # deterministic order. Target $(executables) builds class executables plus # optional shared lib or alternatively a single lib executable when # make-lib-executable=true. Target post is optionally defined by # library makefile. all: post post: $(executables) all: $(info ++++info: target all in lib $(lib.name) completed) # build all with -g option turned on for debug symbols alldebug: c.flags += -g alldebug: cxx.flags += -g alldebug: all #=== class executable ========================================================== # recipe for linking objects in class executable # argument $1 = compiler type (c or cxx) # argument $2 = class basename define link-class $(compile-$1) \ $($1.ldflags) $($2.class.ldflags) \ -o $2.$(extension) \ $(addsuffix .o, $(basename $($2.class.sources))) \ $(addsuffix .o, $(basename $(common.sources))) \ $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) endef # general rule for linking object files in class executable %.$(extension): $(shared.lib) $(info ++++ info: linking objects in $@ for lib $(lib.name)) $(if $(filter %.cc %.cpp, $($*.class.sources)), \ $(call link-class,cxx,$*), \ $(call link-class,c,$*)) #=== library blob ============================================================== # build all classes into single executable build-lib: $(lib.name).$(extension) $(info ++++ info: library blob $(lib.name).$(extension) completed) # recipe for linking objects in lib executable # argument $1 = compiler type (c or cxx) define link-lib $(compile-$1) \ $($1.ldflags) $(lib.ldflags) \ -o $(lib.name).$(extension) $(all.objects) \ $($1.ldlibs) $(lib.ldlibs) endef # rule for linking objects in lib executable # declared conditionally to avoid name clashes ifeq ($(make-lib-executable),yes) $(lib.name).$(extension): $(all.objects) $(if $(filter %.cc %.cpp, $(all.sources)), \ $(call link-lib,cxx), \ $(call link-lib,c)) endif #=== shared dynamic lib ======================================================== # recipe for linking objects in shared executable # argument $1 = compiler type (c or cxx) define link-shared $(compile-$1) \ $(shared.ldflags) \ -o lib$(lib.name).$(shared.extension) $(shared.objects) \ $($1.ldlibs) $(shared.ldlibs) endef # rule for linking objects in shared executable # build recipe is in macro 'link-shared' lib$(lib.name).$(shared.extension): $(shared.objects) $(info ++++ info: linking objects in shared lib $@) $(if $(filter %.cc %.cpp, $(shared.sources)), \ $(call link-shared,cxx), \ $(call link-shared,c)) #=== object files ============================================================== # recipe to make .o file from source # argument $1 is compiler type (c or cxx) define make-object-file $(info ++++ info: making $@ in lib $(lib.name)) $(compile-$1) \ $($1.flags) \ -o $@ -c $< endef # Three rules to create .o files. These are double colon 'terminal' rules, # meaning they are the last in a rules chain. %.o:: %.c $(call make-object-file,c) %.o:: %.cc $(call make-object-file,cxx) %.o:: %.cpp $(call make-object-file,cxx) #=== explicit prerequisites for class executables ============================== # For class executables, prerequisite rules are declared in run time. Target # 'depend' prints these rules for debugging purposes. # declare explicit prerequisites rule like 'class: class.extension' # argument $v is class basename define declare-class-target $v: $v.$(extension) endef # declare explicit prerequisites rule like 'class.extension: object1.o object2.o' # argument $v is class basename define declare-class-executable-target $v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \ $(addsuffix .o, $(basename $(common.sources))) endef # evaluate explicit prerequisite rules for all classes $(foreach v, $(classes), $(eval $(declare-class-target))) $(foreach v, $(classes), $(eval $(declare-class-executable-target))) #=== implicit prerequisites for class executables ============================== # Evaluating implicit prerequisites (header files) with help from the # preprocessor is 'expensive' so this is done conditionally and selectively. # Note that it is also possible to trigger a build via install targets, in # which case implicit prerequisites are not checked. # When the Pd include path contains spaces it will mess up the implicit # prerequisites rules. disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) ifndef disable-dependency-tracking must-build-everything := $(filter all, $(goals)) must-build-class := $(filter $(classes), $(goals)) must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) endif # declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' # argument $1 is input source file(s) # dir is explicitly added because option -MM strips it by default define declare-object-target $(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1)) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything ifdef must-build-everything $(if $(wildcard $(all.objects)), \ $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) endif # evaluate implicit prerequisite rules when selectively building classes ifdef must-build-class $(foreach v, $(must-build-sources), \ $(eval $(call declare-object-target, $v))) $(foreach v, $(shared.sources), \ $(eval $(call declare-object-target, $v))) endif ################################################################################ ### rules: preprocessor and assembly files ##################################### ################################################################################ # Preprocessor and assembly output files for bug tracing etc. They are not part # of the build processes for executables. By default these files are created in # the current working directory. Dependency tracking is not performed, the build # is forced instead to make sure it's up to date. force: #=== preprocessor file ========================================================= # make preprocessor output file with extension .pre # argument $1 = compiler type (c or cxx) define make-preprocessor-file $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ in current working directory) $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) endef %.pre:: %.c force $(call make-preprocessor-file,c) %.pre:: %.cc force $(call make-preprocessor-file,cxx) %.pre:: %.cpp force $(call make-preprocessor-file,cxx) #=== assembly file ============================================================= # make C / assembly interleaved output file with extension .lst # argument $1 = compiler type (c or cxx) define make-assembly-file $(info ++++ info: making assembly output file $(notdir $*.lst) \ in current working directory) $(compile-$1) \ -c -Wa,-a,-ad -fverbose-asm \ $($1.flags) \ $< > $(notdir $*.lst) endef %.lst:: %.c force $(call make-assembly-file,c) %.lst:: %.cc force $(call make-assembly-file,cxx) %.lst:: %.cpp force $(call make-assembly-file,cxx) ################################################################################ ### rules: installation targets ################################################ ################################################################################ #=== strip ===================================================================== # Stripping of installed binaries will only be done when variable 'stripflags' # is defined non-empty. No default definition is provided except for Windows # where the unstripped binaries are large, especially in the case of Mingw-w64. # Note: while stripping all symbols ('-s' or '--strip-all') is possible for # Linux and Windows, in the case of OSX only non-global symbols can be stripped # (option '-x' or '--discard-all'). # Make definition of strip command overridable so it can be defined in an # environment for cross-compilation. STRIP ?= strip # Commands in 'strip-executables' will be executed conditionally in the rule for # target 'install-executables'. strip-executables = cd "$(installpath)" && \ $(foreach v, $(executables), $(STRIP) $(stripflags) '$v';) #=== install =================================================================== # Install targets depend on successful exit status of target all because nothing # must be installed in case of a build error. # -p = preserve time stamps # -m = set permission mode (as in chmod) # -d = create all components of specified directories INSTALL = install INSTALL_PROGRAM := $(INSTALL) -p -m 644 INSTALL_DATA := $(INSTALL) -p -m 644 INSTALL_DIR := $(INSTALL) -m 755 -d # strip spaces from file names executables := $(strip $(executables)) datafiles := $(strip $(datafiles)) datadirs := $(strip $(datadirs)) # Do not make any install sub-target with empty variable definition because the # install program would exit with an error. install: $(if $(executables), install-executables) install: $(if $(datafiles), install-datafiles) install: $(if $(datadirs), install-datadirs) install-executables: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(executables), \ $(INSTALL_PROGRAM) '$v' "$(installpath)";) $(info ++++ info: executables of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) $(if $(stripflags), $(strip-executables),) install-datafiles: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(datafiles), \ $(INSTALL_DATA) '$(v)' "$(installpath)";) $(info ++++ info: data files of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) install-datadirs: all $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) $(foreach v, $(datadirs), \ $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) $(info ++++ info: data directories of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) ################################################################################ ### rules: distribution targets ################################################ ################################################################################ # TODO # These targets are implemented in Makefile Template, but I have to figure out # how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. # make source package dist: @echo "target dist not yet implemented" # make Debian source package dpkg-source: @echo "target dpkg-source not yet implemented" $(ORIGDIR): $(DISTDIR): ################################################################################ ### rules: clean targets ####################################################### ################################################################################ # delete build products from build tree clean: rm -f $(all.objects) rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) rm -f *.pre *.lst # remove distribution directories and tarballs from build tree distclean: clean @echo "target distclean not yet implemented" ################################################################################ ### rules: submake targets ##################################################### ################################################################################ # Iterate over sub-makefiles or makefiles in other directories. # When 'continue-make=yes' is set, sub-makes will report 'true' to the parent # process regardless of their real exit status. This prevents the parent make # from being aborted by a sub-make error. Useful when you want to quickly find # out which sub-makes from a large set will succeed. ifeq ($(continue-make),yes) continue = || true endif # These targets will trigger sub-make processes for entries in 'makefiledirs' # and 'makefiles'. all alldebug install clean distclean dist dkpg-source: \ $(makefiledirs) $(makefiles) # this expands to identical rules for each entry in 'makefiledirs' $(makefiledirs): $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) # this expands to identical rules for each entry in 'makefiles' $(makefiles): $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) ################################################################################ ### rules: convenience targets ################################################# ################################################################################ #=== show variables ============================================================ # Several 'function' macro's cause errors when expanded within a rule or without # proper arguments. Variables which are set with the define directive are only # shown by name for that reason. functions = \ add-class-source \ declare-class-target \ declare-class-executable-target \ declare-object-target \ link-class \ link-lib \ link-shared \ make-object-file \ make-preprocessor-file \ make-assembly-file # show variables from makefiles vars: $(info ++++ info: showing makefile variables:) $(foreach v,\ $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ $(if $(filter file, $(origin $v)),\ $(info variable $v = $($v)))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo # show all variables allvars: $(info ++++ info: showing default, automatic and makefile variables:) $(foreach v, \ $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ $(info variable ($(origin $v)) $v = $($v))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo #=== show dependencies ========================================================= # show generated prerequisites rules depend: $(info ++++ info: generated prerequisite rules) $(foreach v, $(classes), $(info $(declare-class-target))) $(foreach v, $(classes), $(info $(declare-class-executable-target))) $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) @echo #=== show help text ============================================================ # brief info about targets and paths ifdef mpdh mpdhinfo := $(mpdh) else mpdhinfo := m_pd.h was not found. Is Pd installed? endif help: @echo @echo " Main targets:" @echo " all: build executables (default target)" @echo " install: install all components of the library" @echo " vars: print makefile variables for troubleshooting" @echo " allvars: print all variables for troubleshooting" @echo " help: print this help text" @echo @echo " Pd API m_pd.h:" @echo " $(mpdhinfo)" @echo " You may specify your preferred Pd include directory as argument" @echo " to the make command, like 'PDINCLUDEDIR=path/to/pd/src'." @echo @echo " Path for installation of your libdir(s):" @echo " $(PDLIBDIR)" @echo " Alternatively you may specify your path for installation as argument" @echo " to the make command, like 'PDLIBDIR=path/to/pd-externals'." @echo @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." @echo #=== platform test ============================================================= # This target can be used to test if the compiler for specified PLATFORM is # correctly defined and available. dumpmachine: @$(CC) -dumpmachine #=== dummy target ============================================================== coffee: @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." ################################################################################ ### end of rules sections ###################################################### ################################################################################ # for syntax highlighting in vim and github # vim: set filetype=make: pool-0.2.2+git20210923.1.40cb82e/pool-0.2.dtd0000644002537200253720000000021713630166142017506 0ustar zmoelnigzmoelnig pool-0.2.2+git20210923.1.40cb82e/pool.help0000755002537200253720000001654713630166142017406 0ustar zmoelnigzmoelnigpmaxqv2 r#NsvpatcherU1’~ t#PuoriginP] tvwindowwsetfontxSans Serif$A tyhiddenznewex~c) {sœ0-p tyzÇc) {œ tyz}z) {œ tyzú˜) }rœ tv~linecountR tyzG˜( pcontrol tv~Q tyz!˜! 1t1open tv~R rs¯ÖvN ty1inlet¤_P tvwx$@A t1commentYZˆ 1Unfortunately1Jitter1includes1an1example1file1that1is1named1"pool"1and1which1 could1!be1"found11#loaded1$prior1%to1&the1'external1("pool". t1Y/« 1)In1*case1+this11,a1-problem1.for1/you10,11just12rename1&13jitter-examples/other/pool.pat1%14some15other16name...17there118no19harm1:done101;since18151on1?it. t1@pop ty1Anewobjs™0 1Bp1Ctroubles t1ºgX 1Dclear1Evalue1Fat1Gindex tv~Q t1ÆU 1Hset1E1F1G t1Imessage›)" 1JgetiR t1Išf# 1KclriS tv~R t1]$ 1Lkey1Monly tv~Q t1Iâ^ 1H1NB tv~S t1Åð[ 1,1Obang11Poutput1.1&1E1Qof1Rundefined1Skeys tv~Q t1Iœ´0 1Tadd1N1Y tv~R t1ϲN 1H1E1Ubut1Vdon't1Woverwrite tv~Q t1I›   1Xget1YA t1I›ø 1X1Zu t1šÕˆ 1X1E1[(associated1%1\key) t1I›ä 1X1N t1IšG 1]clr1Y t1Iœ†0 1H1ZTU t1Iœž/ 1^setiR1N t1Iœl< 1H1Y1_yesR t1IœY1 1HQRS t1¾/P 1D1`pool1adata t1Iœ-  1breset t1œH{ 1H1cvalues1d(key11edata) t1ЇI 1fredefine1E tv~R t1¼Gd 1D1E1[1%1\ tv~Q t1Á)X 1X1E1F1G t1IND 1ggetmethods tzù½ 1hprint t1jR 1iordered1jversion t1I6ÿ4 1kogetrecR t1^”R 1i1j t1I6‘' 1logetall t1Vb 1m.... t1IaA 1ngetattributes t1M!0 1oprivate? t1I 7 1pgetprivate t1I&Œ2 1qgetabsdir t1= D 1X1`1rname t1I ( 1sgetpool t1I&U7 1tgetechodir t1jæ7 1uattributes t1Iøôª 1` t1ÜŠ‘ 1vcut1wall1c11xsubdirs t1Üw‘ 1ycopy1w1c11x t1À™™ 1zdepth1{(default=-1)1|may1!1}given t1ÜÃs 1~paste1U1V1replace t1Ù±– 1~1€clipboard1into1‚current1ƒdir t1Óõ‘ 1D1€1„(free1…memory) t1I¬ô# 1†clrclip t1I­Ã- 1‡pasteadd t1ÙZ‘ 1v1w1c1ˆin1‚1ƒ t1I­°  1~ tv~R t1ÀÓŒ 1z1{11‰mkdir1Šflag1‹(default1Œ1)1|1!1} tv~Q t1I­‰- 1cutrecQ t1I®v, 1Žcopyrec t1I®Y! 1cutall t1ÙF‘ 1y1w1c1ˆ1‚1ƒ t1I®E( 1copyall t1Ú(k 1v1E1%1€ t1I¯& 1v1Z tv~R t1Ù  1y1E1[1%1\1%1€ tv~Q t1I® ' 1y1Y t1Q| 1‘(optional1z1’argument) t1Cl 1“count1x t1IæF- 1”cntsubR t1dTl 1•default=-1...infinite t1I6F- 1–cntrecR tv~R t1[*_ 1O1F1—right1˜outlet1™signals1šend1Q1›list tv~Q t1I6)! 1œcntall t1cFl 1ƒ1z1|1!1} tvwx$@A t1ëÀ 1,1E11,1›1Q1atoms t1ÙÀ 1,1L11žone1Ÿatom tvwx$A t1I­ÊZ 1 ldrec1¡data.txtRP tv~R t1¿¨Ÿ 1z1{11‰1Š1‹1Œ1|1!1} t1ú‘{ 1¢load1a11‚1ƒ11x tv~Q t1I®–H 1 1¡ t1ú‚y 1¢1a11‚1ƒ t1I®‚F 1£lddir1¡ t1à7 1E t1ÿÏ7 1L t1ÿ½7 1¤directory tv~R t1ýcq 1¥save1a1Q1‚1ƒ11x tv~Q t1I®gK 1¦svrec1¡ t1ûUq 1¥1a1Q1‚1ƒ t1I®UI 1§svdir1¡ tv~R t1#{ 1z1|1!1}1¨(default=1)101©-1..infinite tv~Q t1Içú7 1ªrmsub1«fld2 t1ûz 1¬remove1­relative1®subdir t1Içæ" 1¯rmdir t1 çq 1¬1°absolute1ƒ t1Iæ’6 1±chsub1²fld1 t1“z 1³change1%1­1® t1Iæ3 1´getsubÿÿ t1¯_ 1³1%1µparent1ƒ t1Iæµ 1¶updir t1Iæ 1·chdir t1Iæ`7 1¸mksub1« t1_i 1¹make1­1® t1IæN7 1‰1² t1 O[ 1¹1°1ƒ t1€q 1³1%1°1ƒ t1l 1X1x t1/9P 1X141ºinfo t1I7 1»help t1 ;l 1¼(always1½absolute) t1 -l 1X1‚1ƒ t1Iæ,# 1¾getdir t1dïl 1• t1I6á- 1¿getrecR tv~R t1\Ä_ 1O1F1—1˜1™1š1Q1› tv~Q t1I7Ä# 1¿ tv~R t17ªq 1X1w1c1ˆ1‚1ƒ11x tv~Q t1I6x! 1Àgetall t16hŒ 1X1w1c1ˆ1‚1ƒ t1I6K# 1Áclrrec tv~R t1ZF[ 1D1w1c11x tv~Q t1I70  1Âclrall t1ù>W 1¢111` t1I®=C 1¢1¡ t1ù-P 1¥1`1%1 t1I®,F 1¥1¡ t1Iû 1` t1Iä= 1`1Ãmypool t1I&|3 1Äabsdir1Å$1 t1Ætoggle|_P tv~R t1dx 1Çreport1°1Èdirectories1É(default) tv~Q t1I&E7 1Êechodir1Å t1ÆE_P t1INͯ 1O t1I\¼¡ 1O t1Ij«’ 1” t1I@Þ¾ P rs(7¾- tvwx$A tzåO 11H tz»¦< 1Ëprepend1H t1˜»Á_P t1Ã+_P tz–< 1Ë1H tzox< 1Ë1H tzD`< 1Ë1H tz$K< 1Ë1H t1˜–À_P t1˜mÁ_P t1˜HÂ_P t1˜#Â_P t1ž*_P t1o+_P t1H-_P t1%-_P t1Ìconnect_PTP t1ÌXPTP t1ÌPPXP t1ÌQPYP t1Ì_PUP t1ÌYPUP t1Ì_PVP t1ÌZPVP t1ÌRPZP t1ÌSP[P t1Ì[PWP t1Ì_PWP t1Ì\P^P t1Ì^P]P t1ÌSP_P t1@ t1A@–C 1B1H tvwx$`A tz@yB1` 1Í#B1Îcolor^ tvwx$A t1]W=1`1Ï-1,1Ðhierarchical1Ñstorage1Òobject101Ó(C)2002-20081ÔThomas1ÕGrill tvwx$A tv~R t1-d 1Öecho1‚1ƒ1F1×every1Øcommand t1Ê 1H1`1r1Ù(data11Úshared1Ûamong1`1Üobjects) tv~Q t12üP 1Ýor1H1%1Þprivate tvwx$@A tv~S t1ŠÑ 1È101L11a1c1|1ßconsist1Q1àany1áatoms:1âsymbols101ãintegers11äfloats tvwx$A tv~R t1Z)[ 1D1w1c1ˆ1‚1ƒ t1^w_ 1O1F1—1˜1™1š1Q1› tv~Q t1cál 1ƒ1z1|1!1} tv~R t1½d 1z1|1!1}1¨ tv~Q t1þ¬7 1Ø tv~R t1 Åd 1¢R1ålevels1ædeep11V1çcreate1èdirs t1ƒy 1r1Q1`1|1!1}1éas1êargument1ë(see1`1ìattribute) tvwx$@A tv~Q t1ÇÔ 1,1¤1ípath11,1›1Q1 tvwx$A t16d 1“1c tv~S t1œd 1+11îalso1ïused1.1ðsaving1Q1ƒ1ñnames!1òsee1¥1ófunctions t1ôuser1õpanel© Éý 1ö#X1÷brgbíò» 1ö1øfrgbPPP 1ö1ùborderP 1ö1úroundedP 1ö1ûshadowP 1ö1: t1übackground tvwx$ A t1©äÐ 1w1&1ýfile-op1þmessages1ÿare2available2with2appended2x2(like2savex)1.2XML2format t1ô1õ©(ÊØ 1ö1÷íò» 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: tvwx$A tv~Q t1$z 1`2has182 inlets/outlets? 1Í1Î^ t1$ˆd 2 CLICK2 HERE 1Í1Î^ t1ô2 ubutton"zuPP t1ô1õà(º9 1ö1÷íò» 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: t1ü t1ô1õ\„Ý 1ö1÷ÊõÌ 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: t1ü t1ô1õ–)T 1ö1÷íò» 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: t1ü t1ô1õ])|T 1ö1÷íò» 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: t1ü t1ô1õ3) 8 1ö1÷íò» 1ö1øPPP 1ö1ùP 1ö1úP 1ö1ûP 1ö1: t1ü t1Ì P!P t1Ì#P$P ty1ÌšP¢P ty1ÌP¢P ty1Ì›P¢P ty1Ì”P¢P ty1Ì“P¢P ty1Ì‘P¢P ty1Ì–P¢P ty1ÌŽP¢P ty1ÌP¢P ty1̘P¢P ty1ÌP¢P ty1ÌŒP¢P ty1ÌŠP¢P ty1Ì!P¢P ty1ÌxP¢P ty1Ì$P¢P ty1Ì{P¢P ty1Ì%P¢P ty1Ì&P¢P ty1ÌyP¢P ty1Ì|P¢P ty1Ì8P¢P ty1Ì…P¢P ty1Ì~P¢P t2 fastenTvP«9«9ðýð t1ÌP„P ty1Ì¡PP t1ÌPP t1ÌPP t1ÌQQ t1ÌQP t1ÌRR t1ÌRP t1ÌSS t1ÌSP t1ÌTT ty1Ì+P£P ty1Ì-P£P ty1Ì/P£P ty1Ì€P£P ty1Ì1P£P ty1Ì3P£P ty1Ì‚P£P ty1Ì5P£P ty1Ì=P£P ty1Ì?P£P ty1Ì@P£P ty1ÌEP£P ty1ÌAP£P ty1ÌGP£P ty1ÌIP£P ty1ÌCP£P ty1Ì_P£P ty1Ì[P£P ty1Ì]P£P ty1ÌUPŸP ty1ÌŸP P ty1Ì PžP ty1Ì'P¤P ty1Ì)P¤P ty1ÌKP¤P ty1ÌMP¤P ty1ÌRP¤P ty1ÌTP¤P ty1ÌWP¤P ty1ÌbP¤P ty1ÌdP¤P ty1ÌfP¤P ty1ÌhP¤P ty1ÌiP¤P ty1ÌjP¤P ty1ÌnP¤P ty1ÌoP¤P t1@ pool-0.2.2+git20210923.1.40cb82e/pool-help.pd0000644002537200253720000002443513630166142017777 0ustar zmoelnigzmoelnig#N canvas 24 27 968 789 12; #X msg 296 105 set 1 2 3; #X obj 238 631 print K; #X msg 607 211 getall; #X msg 296 134 set A k g; #X obj 189 660 print V; #X obj 287 605 print D; #X msg 296 164 set A l m; #X msg 297 195 set 2 34; #X msg 427 297 clr A; #X msg 429 105 get A; #X msg 429 130 get 2; #X msg 31 132 echodir \$1; #X obj 31 111 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 31 213 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 31 234 absdir \$1; #X text 426 277 clear value; #X text 425 83 get value; #X text 360 605 directory (abs or rel to current); #X text 264 661 data value; #X text 310 631 data key; #X msg 32 314 pool pool1; #X msg 33 343 pool; #X text 77 343 set to private; #X msg 33 405 reset; #X text 32 384 clear all pool data; #X msg 608 111 clrall; #X text 599 89 clear all values in dir; #X text 607 190 get all values in dir; #X text 175 500 pool name can be given as argument; #X text 598 136 clear all values and dirs; #X msg 606 158 clrrec; #X msg 605 258 getrec; #X text 605 236 get all values in dir and subdirs; #X text 670 289 bang at EOL; #X text 673 208 bang at EOL; #X text 670 257 depth may be given; #X text 34 291 set pool name; #X text 30 89 at each command; #X text 30 73 echo current dir; #X text 295 82 set values; #X text 26 194 (default on); #X text 18 178 report absolute dirs; #X msg 34 452 help; #X text 77 453 get some info; #X text 670 274 default=-1 (= infinite); #X msg 609 340 cntall; #X text 675 338 count all values in dir; #X msg 609 366 cntrec; #X text 677 364 ... and subdirs; #X text 673 378 (depth may be given); #N canvas 472 45 444 655 dirs 0; #X msg 111 40 mkdir fld1; #X msg 113 135 chdir; #X msg 109 331 updir; #X msg 110 468 getsub -1; #X text 112 20 make absolute dir; #X text 111 64 make relative dir; #X msg 112 85 mksub fld2; #X text 111 117 change to absolute dir; #X msg 112 178 chsub fld2; #X text 110 159 change to relative dir; #X text 105 312 change to upper dir; #X text 106 364 remove absolute dir; #X msg 107 383 rmdir fld1; #X msg 109 422 rmsub fld2; #X text 108 403 remove relative dir; #X text 108 450 get subdirs; #X text 250 494 -1 ... infinite; #X text 166 327 depth may be given; #X text 167 343 default=1; #X text 208 463 depth may be given; #X text 206 479 default=1; #X text 107 491 count subdirs; #X msg 110 512 cntsub -1; #X msg 110 572 getdir; #X text 109 552 get current dir; #X text 175 572 always absolute; #X obj 13 252 s \$0-pool; #X msg 111 231 mkchdir fld1; #X text 112 211 make and change to absolute dir; #X msg 109 276 mkchsub fld2; #X text 110 256 make and change to relative dir; #X connect 0 0 26 0; #X connect 1 0 26 0; #X connect 2 0 26 0; #X connect 3 0 26 0; #X connect 6 0 26 0; #X connect 8 0 26 0; #X connect 12 0 26 0; #X connect 13 0 26 0; #X connect 22 0 26 0; #X connect 23 0 26 0; #X connect 27 0 26 0; #X connect 29 0 26 0; #X restore 715 490 pd dirs; #X text 714 469 directory operations; #N canvas 0 22 845 610 file 0; #X text 117 207 save dir and subdirs; #X text 117 165 save data in current dir; #X text 117 253 load data into current dir; #X text 115 300 load data into current dir and below; #X text 132 340 depth (default -1) and; #X text 134 356 mkdir flag (default 1) can be given; #X text 117 37 save all; #X text 117 81 load all (add to existing data); #X text 22 12 file operations; #X obj 22 188 s \$0-pool; #X text 473 209 save dir and subdirs; #X text 473 167 save data in current dir; #X text 473 255 load data into current dir; #X text 471 302 load data into current dir and below; #X text 488 342 depth (default -1) and; #X text 490 358 mkdir flag (default 1) can be given; #X text 473 39 save all; #X text 473 83 load all (add to existing data); #X obj 378 190 s \$0-pool; #X text 444 12 XML format; #X msg 120 54 save pool.dat; #X msg 118 100 load pool.dat; #X msg 117 184 svdir pool.dat; #X msg 117 226 svrec pool.dat; #X msg 116 272 lddir pool.dat; #X msg 116 319 ldrec pool.dat; #X msg 476 56 savex pool.xml; #X msg 474 102 loadx pool.xml; #X msg 473 186 svxdir pool.xml; #X msg 473 228 svxrec pool.xml; #X msg 472 274 ldxdir pool.xml; #X msg 472 321 ldxrec pool.xml; #X text 26 398 If the file name is given without a path specification the folder containing the current patcher will be used.; #X text 27 451 The attribute outlet reports if file saving/loading has been successful \, by outputting the message tag and a boolean flag.; #X text 29 517 Please note: the absdir flag is also used for paths written into the files. With absdir=1 absolute paths are written \, absdir=0 means relative paths.; #X connect 20 0 9 0; #X connect 21 0 9 0; #X connect 22 0 9 0; #X connect 23 0 9 0; #X connect 24 0 9 0; #X connect 25 0 9 0; #X connect 26 0 18 0; #X connect 27 0 18 0; #X connect 28 0 18 0; #X connect 29 0 18 0; #X connect 30 0 18 0; #X connect 31 0 18 0; #X restore 715 600 pd file; #X text 713 577 file operations; #X text 713 634 clipboard operations; #N canvas 0 22 545 593 clip 0; #X text 97 56 copy value associated to key into clipboard; #X msg 100 77 copy A; #X msg 98 119 cut B; #X text 96 101 cut value associated to key into clipboard; #X msg 96 401 paste; #X msg 98 179 copyall; #X text 95 158 copy all values in current dir into clipboard; #X msg 97 221 cutall; #X text 95 201 cut all values in current dir into clipboard; #X text 94 263 copy all values in current dir into clipboard; #X text 94 306 cut all values in current dir into clipboard; #X msg 97 284 copyrec; #X text 194 285 depth may be given (default=-1); #X text 193 326 depth may be given (default=-1); #X msg 96 326 cutrec 1; #X text 194 345 1..only with first level subdirs; #X text 96 379 paste clipboard contents into current directory; #X text 167 397 depth (default -1) and; #X text 169 413 mkdir flag (default 1) can be given; #X text 183 448 depth (default -1) and; #X text 185 466 mkdir flag (default 1) can be given; #X msg 95 453 pasteadd; #X text 95 431 paste but don't replace; #X msg 94 521 clrclip; #X text 171 520 clear clipboard (free memory); #X text 22 12 clipboard operations (this is an internal clipboard...) ; #X obj 4 193 s \$0-pool; #X connect 1 0 26 0; #X connect 2 0 26 0; #X connect 4 0 26 0; #X connect 5 0 26 0; #X connect 7 0 26 0; #X connect 11 0 26 0; #X connect 14 0 26 0; #X connect 21 0 26 0; #X connect 23 0 26 0; #X restore 714 655 pd clip; #X text 715 439 more commands:; #X obj 237 444 r \$0-pool; #X text 174 517 data is shared among pool objects with the same name ; #X obj 26 10 cnv 15 850 45 empty empty pool 10 22 0 24 -260818 -1 0 ; #X obj 386 553 print A; #X text 458 552 attributes; #X msg 34 490 getattributes; #X msg 139 132 getechodir; #X msg 130 234 getabsdir; #X msg 141 314 getpool; #X msg 297 345 add 2 14; #X obj 260 478 pool @valcnt 10 @dircnt 5; #X text 330 425 expected value and directory counts; #X text 330 440 can be given for optimal performance; #X msg 429 155 get 3; #X msg 295 222 set 3 -1 1; #X msg 32 518 getmethods; #X text 328 454 (see attributes in properties dialog); #X text 713 687 console printout; #N canvas 0 22 612 291 print 0; #X obj 21 231 s \$0-pool; #X msg 109 80 printall; #X msg 109 132 printrec; #X text 110 60 print all values in dir; #X text 109 112 print values in dir and subdirs; #X text 190 133 (depth may be given); #X text 22 12 print-to-console operations; #X text 201 183 (depth may be given); #X msg 109 181 printroot; #X text 109 161 print values in dir and subdirs (starting from root) ; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 8 0 0 0; #X restore 715 708 pd print; #X text 272 33 http://grrrr.org; #X msg 428 225 geti \$1; #X text 426 185 get indexed element; #X obj 427 205 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 256; #X text 297 323 set but don't replace; #X text 294 256 set value at index; #X msg 295 276 seti 3 Uhu; #X text 424 343 clear value at index; #X msg 425 363 clri 2; #X text 713 523 output ordering; #N canvas 285 155 534 455 ordered 0; #X obj 24 284 s \$0-pool; #X msg 112 191 ogetall; #X msg 110 287 ogetrec; #X text 113 171 get all values in dir (ordered); #X text 109 244 get all values in dir und subdirs; #X text 185 311 bang at EOL; #X text 107 262 (ordered); #X text 109 365 get subdirs (ordered); #X msg 110 389 ogetsub; #X text 385 400 (-1..infinite); #X text 183 189 index \, direction may be given; #X text 28 10 ordered output sorts by key or value ascending or descending ; #X text 28 71 index > 0 sort by atom \, at indexed position; #X text 28 53 index = 0 sort by key (default); #X text 30 100 direction = 0... ascending (default); #X text 30 118 direction != 0... descending; #X text 183 290 depth default to -1 (= infinite); #X text 183 273 depth \, index \, direction may be given; #X text 208 381 depth \, index \, direction may be given; #X text 206 401 depth defaults to 1; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 8 0 0 0; #X restore 714 544 pd ordered; #X text 35 699 NOTE: pool is currently not reentrant! This means that you should not input data as a direct reaction upon output.; #X text 32 733 (this only applies to pools of the same name); #X obj 340 579 print C; #X text 412 579 command; #X obj 294 552 route bang; #X obj 499 666 print ------------; #X text 503 646 separator on bang; #X text 272 13 a hierarchical storage object \, (C)2002-2008 Thomas Grill; #X connect 0 0 67 0; #X connect 2 0 67 0; #X connect 3 0 67 0; #X connect 6 0 67 0; #X connect 7 0 67 0; #X connect 8 0 67 0; #X connect 9 0 67 0; #X connect 10 0 67 0; #X connect 11 0 67 0; #X connect 12 0 11 0; #X connect 13 0 14 0; #X connect 14 0 67 0; #X connect 20 0 67 0; #X connect 21 0 67 0; #X connect 23 0 67 0; #X connect 25 0 67 0; #X connect 30 0 67 0; #X connect 31 0 67 0; #X connect 42 0 67 0; #X connect 45 0 67 0; #X connect 47 0 67 0; #X connect 57 0 67 0; #X connect 62 0 67 0; #X connect 63 0 67 0; #X connect 64 0 67 0; #X connect 65 0 67 0; #X connect 66 0 67 0; #X connect 67 0 4 0; #X connect 67 1 1 0; #X connect 67 2 5 0; #X connect 67 3 91 0; #X connect 67 4 60 0; #X connect 70 0 67 0; #X connect 71 0 67 0; #X connect 72 0 67 0; #X connect 77 0 67 0; #X connect 79 0 77 0; #X connect 82 0 67 0; #X connect 84 0 67 0; #X connect 91 0 92 0; #X connect 91 1 89 0; pool-0.2.2+git20210923.1.40cb82e/source/0000755002537200253720000000000013630166142017043 5ustar zmoelnigzmoelnigpool-0.2.2+git20210923.1.40cb82e/source/Makefile.am0000755002537200253720000000121713630166142021103 0ustar zmoelnigzmoelnig# # automake template # # shared library to be built lib_LTLIBRARIES = @PACKAGE_NAME@.la @PACKAGE_NAME@_la_SOURCES = pool.h main.cpp pool.cpp data.cpp @PACKAGE_NAME@_la_CXXFLAGS = @EXT_CFLAGS@ $(patsubst %,-I%,@INCLUDEDIRS@) # -module allows to avoid lib prefix for libraries # -shrext sets shared library extension as given by @EXTENSION@ # -avoid-version avoids the creation of symlinks to versions of a shared library @PACKAGE_NAME@_la_LDFLAGS = @EXT_LDFLAGS@ -no-undefined -module -shrext @EXTENSION@ -avoid-version $(patsubst %,-L%,@LIBDIRS@) $(patsubst %,-l%,@libs@) $(patsubst %,-framework %,@FRAMEWORKS@) #@PACKAGE_NAME@_la_LIBADD = @libs@ pool-0.2.2+git20210923.1.40cb82e/source/pool.cpp0000644002537200253720000006777113630166142020542 0ustar zmoelnigzmoelnig/* pool - hierarchical storage object for PD and Max/MSP Copyright (c) 2002-2019 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. */ #include "pool.h" #include #include #include #include #include #if FLEXT_OS == FLEXT_OS_WIN #include // for charset conversion functions #else static bool WCStoUTF8(char *sdst,const wchar_t *src,int dstlen) { unsigned char *dst = (unsigned char *)sdst; unsigned char *max = dst+dstlen; for(;;) { wchar_t ud = *(src++); if(ud < 128) { if(dst+1 >= max) return false; *(dst++) = (unsigned char)ud; } else if(ud < 2048) { if(dst+2 >= max) return false; *(dst++) = 192+(unsigned char)(ud/64); *(dst++) = 128+(unsigned char)(ud%64); } else if(ud < 65535) { if(dst+3 >= max) return false; *(dst++) = 224+(unsigned char)(ud/4096); *(dst++) = 128+(unsigned char)((ud/64)%64); *(dst++) = 128+(unsigned char)(ud%64); } else if(ud < 2097151) { if(dst+4 >= max) return false; *(dst++) = 240+(unsigned char)(ud/262144); *(dst++) = 128+(unsigned char)((ud/4096)%64); *(dst++) = 128+(unsigned char)((ud/64)%64); *(dst++) = 128+(unsigned char)(ud%64); } else if(ud < 67108863) { if(dst+5 >= max) return false; *(dst++) = 248+(unsigned char)(ud/16777216); *(dst++) = 128+(unsigned char)((ud/262144)%64); *(dst++) = 128+(unsigned char)((ud/4096)%64); *(dst++) = 128+(unsigned char)((ud/64)%64); *(dst++) = 128+(unsigned char)(ud%64); } else { if(dst+6 >= max) return false; *(dst++) = 252+(unsigned char)(ud/1073741824); *(dst++) = 128+(unsigned char)((ud/16777216)%64); *(dst++) = 128+(unsigned char)((ud/262144)%64); *(dst++) = 128+(unsigned char)((ud/4096)%64); *(dst++) = 128+(unsigned char)((ud/64)%64); *(dst++) = 128+(unsigned char)(ud%64); } if(!ud) break; } return true; } static bool UTF8toWCS(wchar_t *dst,const char *ssrc,int dstlen) { const unsigned char *src = (const unsigned char *)ssrc; wchar_t *max = dst+dstlen; for(;;) { if(*src < 128) { *dst = *(src++); if(!*dst) break; } else if(*src < 224) { *dst = wchar_t(src[0]-192)*64+wchar_t(src[1]-128); src += 2; } else if(*src < 240) { *dst = wchar_t(src[0]-224)*4096+wchar_t(src[1]-128)*64+wchar_t(src[2]-128); src += 3; } else if(*src < 248) { *dst = wchar_t(src[0]-240)*262144+wchar_t(src[1]-128)*4096+wchar_t(src[2]-128)*64+wchar_t(src[3]-128); src += 4; } else if(*src < 252) { *dst = wchar_t(src[0]-248)*16777216+wchar_t(src[1]-128)*262144+wchar_t(src[2]-128)*4096+wchar_t(src[3]-128)*64+wchar_t(src[4]-128); src += 5; } else if(*src < 254) { *dst = wchar_t(src[0]-252)*1073741824+wchar_t(src[1]-128)*16777216+wchar_t(src[2]-128)*262144+wchar_t(src[3]-128)*4096+wchar_t(src[4]-128)*64+wchar_t(src[5]-128); src += 6; } else // invalid string return false; if(++dst >= max) return false; } return true; } #endif using namespace std; inline int compare(int a,int b) { return a == b?0:(a < b?-1:1); } inline int compare(float a,float b) { return a == b?0:(a < b?-1:1); } static int compare(const t_symbol *a,const t_symbol *b) { if(a == b) return 0; else return strcmp(flext::GetString(a),flext::GetString(b)); } static int compare(const t_atom &a,const t_atom &b) { if(flext::GetType(a) == flext::GetType(b)) { switch(flext::GetType(a)) { case A_FLOAT: return compare(flext::GetFloat(a),flext::GetFloat(b)); #if FLEXT_SYS == FLEXT_SYS_MAX case A_LONG: return compare(flext::GetInt(a),flext::GetInt(b)); #endif case A_SYMBOL: return compare(flext::GetSymbol(a),flext::GetSymbol(b)); #if FLEXT_SYS == FLEXT_SYS_PD case A_POINTER: return flext::GetPointer(a) == flext::GetPointer(b)?0:(flext::GetPointer(a) < flext::GetPointer(b)?-1:1); #endif default: FLEXT_LOG("pool - atom comparison: type not handled"); return -1; } } else return flext::GetType(a) < flext::GetType(b)?-1:1; } poolval::poolval(const t_atom &k,AtomList *d): data(d),nxt(NULL) { SetAtom(key,k); } poolval::~poolval() { if(data) delete data; FLEXT_ASSERT(nxt == NULL); } poolval &poolval::Set(AtomList *d) { if(data) delete data; data = d; return *this; } poolval *poolval::Dup() const { return new poolval(key,data?new Atoms(*data):NULL); } pooldir::pooldir(const t_atom &d,pooldir *p,int vcnt,int dcnt): parent(p),nxt(NULL),vals(NULL),dirs(NULL), vbits(Int2Bits(vcnt)),dbits(Int2Bits(dcnt)), vsize(1<nxt; d->nxt = NULL; delete d; } while((d = d1) != NULL); dirs[i].d = NULL; dirs[i].cnt = 0; } } } if(!dironly && vals) { for(int i = 0; i < vsize; ++i) { poolval *v = vals[i].v,*v1; if(v) { do { v1 = v->nxt; v->nxt = NULL; delete v; } while((v = v1) != NULL); vals[i].v = NULL; vals[i].cnt = 0; } } } } void pooldir::Reset(bool realloc) { Clear(true,false); if(dirs) delete[] dirs; if(vals) delete[] vals; if(realloc) { dirs = new direntry[dsize]; ZeroMem(dirs,dsize*sizeof *dirs); vals = new valentry[vsize]; ZeroMem(vals,vsize*sizeof *vals); } else dirs = NULL,vals = NULL; } pooldir *pooldir::AddDir(int argc,const t_atom *argv,int vcnt,int dcnt) { if(!argc) return this; int c = 1,dix = DIdx(argv[0]); pooldir *prv = NULL,*ix = dirs[dix].d; for(; ix; prv = ix,ix = ix->nxt) { c = compare(argv[0],ix->dir); if(c <= 0) break; } if(c || !ix) { pooldir *nd = new pooldir(argv[0],this,vcnt,dcnt); nd->nxt = ix; if(prv) prv->nxt = nd; else dirs[dix].d = nd; dirs[dix].cnt++; ix = nd; } return ix->AddDir(argc-1,argv+1); } pooldir *pooldir::GetDir(int argc,const t_atom *argv,bool rmv) { if(!argc) return this; int c = 1,dix = DIdx(argv[0]); pooldir *prv = NULL,*ix = dirs[dix].d; for(; ix; prv = ix,ix = ix->nxt) { c = compare(argv[0],ix->dir); if(c <= 0) break; } if(c || !ix) return NULL; else { if(argc > 1) return ix->GetDir(argc-1,argv+1,rmv); else if(rmv) { pooldir *nd = ix->nxt; if(prv) prv->nxt = nd; else dirs[dix].d = nd; dirs[dix].cnt--; ix->nxt = NULL; return ix; } else return ix; } } bool pooldir::DelDir(int argc,const t_atom *argv) { pooldir *pd = GetDir(argc,argv,true); if(pd && pd != this) { delete pd; return true; } else return false; } void pooldir::SetVal(const t_atom &key,AtomList *data,bool over) { int c = 1,vix = VIdx(key); poolval *prv = NULL,*ix = vals[vix].v; for(; ix; prv = ix,ix = ix->nxt) { c = compare(key,ix->key); if(c <= 0) break; } if(c || !ix) { // no existing data found if(data) { poolval *nv = new poolval(key,data); nv->nxt = ix; if(prv) prv->nxt = nv; else vals[vix].v = nv; vals[vix].cnt++; } } else if(over) { // data exists... only set if overwriting enabled if(data) ix->Set(data); else { // delete key poolval *nv = ix->nxt; if(prv) prv->nxt = nv; else vals[vix].v = nv; vals[vix].cnt--; ix->nxt = NULL; delete ix; } } } bool pooldir::SetVali(int rix,AtomList *data) { poolval *prv = NULL,*ix = NULL; int vix; for(vix = 0; vix < vsize; ++vix) if(rix > vals[vix].cnt) rix -= vals[vix].cnt; else { ix = vals[vix].v; for(; ix && rix; prv = ix,ix = ix->nxt) --rix; if(ix && !rix) break; } if(ix) { // data exists... overwrite it if(data) ix->Set(data); else { // delete key poolval *nv = ix->nxt; if(prv) prv->nxt = nv; else vals[vix].v = nv; vals[vix].cnt--; ix->nxt = NULL; delete ix; } return true; } else return false; } poolval *pooldir::RefVal(const t_atom &key) { int c = 1,vix = VIdx(key); poolval *ix = vals[vix].v; for(; ix; ix = ix->nxt) { c = compare(key,ix->key); if(c <= 0) break; } return c || !ix?NULL:ix; } poolval *pooldir::RefVali(int rix) { for(int vix = 0; vix < vsize; ++vix) if(rix > vals[vix].cnt) rix -= vals[vix].cnt; else { poolval *ix = vals[vix].v; for(; ix && rix; ix = ix->nxt) --rix; if(ix && !rix) return ix; } return NULL; } flext::AtomList *pooldir::PeekVal(const t_atom &key) { poolval *ix = RefVal(key); return ix?ix->data:NULL; } flext::AtomList *pooldir::GetVal(const t_atom &key,bool cut) { int c = 1,vix = VIdx(key); poolval *prv = NULL,*ix = vals[vix].v; for(; ix; prv = ix,ix = ix->nxt) { c = compare(key,ix->key); if(c <= 0) break; } if(c || !ix) return NULL; else { AtomList *ret; if(cut) { poolval *nv = ix->nxt; if(prv) prv->nxt = nv; else vals[vix].v = nv; vals[vix].cnt--; ix->nxt = NULL; ret = ix->data; ix->data = NULL; delete ix; } else ret = new Atoms(*ix->data); return ret; } } int pooldir::CntAll() const { int cnt = 0; for(int vix = 0; vix < vsize; ++vix) cnt += vals[vix].cnt; return cnt; } int pooldir::PrintAll(char *buf,int len) const { int offs = strlen(buf); int cnt = 0; for(int vix = 0; vix < vsize; ++vix) { poolval *ix = vals[vix].v; for(int i = 0; ix; ++i,ix = ix->nxt) { PrintAtom(ix->key,buf+offs,len-offs); strcat(buf+offs," , "); int l = strlen(buf+offs)+offs; ix->data->Print(buf+l,len-l); post(buf); } cnt += vals[vix].cnt; } buf[offs] = 0; return cnt; } int pooldir::GetKeys(AtomList &keys) { int cnt = CntAll(); keys(cnt); for(int vix = 0; vix < vsize; ++vix) { poolval *ix = vals[vix].v; for(int i = 0; ix; ++i,ix = ix->nxt) SetAtom(keys[i],ix->key); } return cnt; } int pooldir::GetAll(t_atom *&keys,Atoms *&lst,bool cut) { int cnt = CntAll(); keys = new t_atom[cnt]; lst = new Atoms[cnt]; for(int i = 0,vix = 0; vix < vsize; ++vix) { poolval *ix = vals[vix].v; for(; ix; ++i) { SetAtom(keys[i],ix->key); lst[i] = *ix->data; if(cut) { poolval *t = ix; vals[vix].v = ix = ix->nxt; vals[vix].cnt--; t->nxt = NULL; delete t; } else ix = ix->nxt; } } return cnt; } int pooldir::CntSub() const { int cnt = 0; for(int dix = 0; dix < dsize; ++dix) cnt += dirs[dix].cnt; return cnt; } int pooldir::GetSub(const t_atom **&lst) { const int cnt = CntSub(); lst = new const t_atom *[cnt]; for(int i = 0,dix = 0; i < cnt; ++dix) { pooldir *ix = dirs[dix].d; for(; ix; ix = ix->nxt) lst[i++] = &ix->dir; } return cnt; } bool pooldir::Paste(const pooldir *p,int depth,bool repl,bool mkdir) { bool ok = true; for(int vi = 0; vi < p->vsize; ++vi) { for(poolval *ix = p->vals[vi].v; ix; ix = ix->nxt) { SetVal(ix->key,new Atoms(*ix->data),repl); } } if(ok && depth) { for(int di = 0; di < p->dsize; ++di) { for(pooldir *dix = p->dirs[di].d; ok && dix; dix = dix->nxt) { pooldir *ndir = mkdir?AddDir(1,&dix->dir):GetDir(1,&dix->dir); if(ndir) { ok = ndir->Paste(dix,depth > 0?depth-1:depth,repl,mkdir); } } } } return ok; } bool pooldir::Copy(pooldir *p,int depth,bool cut) { bool ok = true; if(cut) { for(int vi = 0; vi < vsize; ++vi) { for(poolval *ix = vals[vi].v; ix; ix = ix->nxt) p->SetVal(ix->key,ix->data); vals[vi].cnt = 0; vals[vi].v = NULL; } } else { for(int vi = 0; vi < vsize; ++vi) { for(poolval *ix = vals[vi].v; ix; ix = ix->nxt) { p->SetVal(ix->key,new Atoms(*ix->data)); } } } if(ok && depth) { for(int di = 0; di < dsize; ++di) { for(pooldir *dix = dirs[di].d; ok && dix; dix = dix->nxt) { pooldir *ndir = p->AddDir(1,&dix->dir); if(ndir) ok = dix->Copy(ndir,depth > 0?depth-1:depth,cut); else ok = false; } } } return ok; } static bool _isspace(char c) { return c > 0 && isspace(c); } static const char *ReadAtom(const char *c,t_atom &a,bool utf8) { // skip leading whitespace (NON-ASCII character are < 0) while(*c && _isspace(*c)) ++c; if(!*c) return NULL; char tmp[1024]; char *m = tmp; // write position bool issymbol; if(*c == '"') { issymbol = true; ++c; } else issymbol = false; // go to next whitespace for(bool escaped = false;; ++c) if(*c == '\\') { if(escaped) { *m++ = *c; escaped = false; } else escaped = true; } else if(*c == '"' && issymbol && !escaped) { // end of string ++c; FLEXT_ASSERT(!*c || _isspace(*c)); *m = 0; break; } else if(!*c || (_isspace(*c) && !escaped)) { *m = 0; break; } else { *m++ = *c; escaped = false; } // save character and set delimiter float fres; // first try float #if 0 if(!issymbol && sscanf(tmp,"%f",&fres) == 1) { #else char *endp; // see if it's a float - thanks to Frank Barknecht fres = (float)strtod(tmp,&endp); if(!issymbol && !*endp && endp != tmp) { #endif int ires = (int)fres; // try a cast if(fres == ires) flext::SetInt(a,ires); else flext::SetFloat(a,fres); } // no, it's a symbol else { const char *c; if(utf8) { #if FLEXT_OS == FLEXT_OS_WIN wchar_t wtmp[1024]; int err = MultiByteToWideChar(CP_UTF8,0,tmp,strlen(tmp),wtmp,1024); if(!err) return NULL; err = WideCharToMultiByte(CP_ACP,0,wtmp,err,tmp,1024,NULL,FALSE); if(!err) return NULL; tmp[err] = 0; c = tmp; #else wchar_t wtmp[1024]; size_t len = mbstowcs(wtmp,tmp,1024); if(len < 0) return NULL; if(!WCStoUTF8(tmp,wtmp,sizeof(tmp))) return NULL; c = tmp; #endif } else c = tmp; flext::SetString(a,c); } return c; } static bool ParseAtoms(const char *tmp,flext::AtomList &l,bool utf8) { FLEXT_ASSERT(tmp); vector atoms; while(*tmp) { t_atom at; tmp = ReadAtom(tmp,at,utf8); if(!tmp) break; atoms.push_back(at); } l(atoms.size(),&atoms[0]); return true; } static bool ParseAtoms(string &s,flext::AtomList &l,bool utf8) { return ParseAtoms((char *)s.c_str(),l,utf8); } static bool ReadAtoms(istream &is,flext::AtomList &l,char del,bool utf8) { vector tmp; for(;;) { char c = is.get(); if(is.eof() || c == del) break; tmp.push_back(c); } tmp.push_back(0); // end-of-string marker return is.good() && ParseAtoms(&tmp[0],l,utf8); } static bool WriteAtom(ostream &os,const t_atom &a,bool utf8) { if(flext::IsFloat(a)) os << flext::GetFloat(a); else if(flext::IsInt(a)) os << flext::GetInt(a); else if(flext::IsSymbol(a)) { const char *c = flext::GetString(a); if(utf8) { #if FLEXT_OS == FLEXT_OS_WIN char tmp[1024]; wchar_t wtmp[1024]; int err = MultiByteToWideChar(CP_ACP,0,c,strlen(c),wtmp,sizeof(wtmp)/sizeof(*wtmp)); if(!err) return false; err = WideCharToMultiByte(CP_UTF8,0,wtmp,err,tmp,sizeof(tmp),NULL,FALSE); if(!err) return false; tmp[err] = 0; c = tmp; #else char tmp[1024]; wchar_t wtmp[1024]; if(!UTF8toWCS(wtmp,c,sizeof(wtmp)/sizeof(*wtmp))) return false; size_t len = wcstombs(tmp,wtmp,sizeof(tmp)); if(len < 0) return false; c = tmp; #endif } os << '"'; for(; *c; ++c) { // escape some special characters if(_isspace(*c) || *c == '\\' || *c == ',' || *c == '"') os << '\\'; os << *c; } os << '"'; } else FLEXT_ASSERT(false); return true; } static void WriteAtoms(ostream &os,const flext::AtomList &l,bool utf8) { for(int i = 0; i < l.Count(); ++i) { WriteAtom(os,l[i],utf8); if(i < l.Count()-1) os << ' '; } } bool pooldir::LdDir(istream &is,int depth,bool mkdir) { for(int i = 1; !is.eof(); ++i) { Atoms d,k,*v = new Atoms; bool r = ReadAtoms(is,d,',',false) && ReadAtoms(is,k,',',false) && ReadAtoms(is,*v,'\n',false); if(r) { if(depth < 0 || d.Count() <= depth) { pooldir *nd = mkdir?AddDir(d):GetDir(d); if(nd) { if(k.Count() == 1) { nd->SetVal(k[0],v); v = NULL; } else if(k.Count() > 1) post("pool - file format invalid: key must be a single word"); } #ifdef FLEXT_DEBUG else post("pool - directory was not found",i); #endif } } else if(!is.eof()) post("pool - format mismatch encountered, skipped line %i",i); if(v) delete v; } return true; } bool pooldir::SvDir(ostream &os,int depth,const AtomList &dir) { int cnt = 0; for(int vi = 0; vi < vsize; ++vi) { for(poolval *ix = vals[vi].v; ix; ix = ix->nxt) { WriteAtoms(os,dir,false); os << " , "; WriteAtom(os,ix->key,false); os << " , "; WriteAtoms(os,*ix->data,false); os << endl; ++cnt; } } if(!cnt) { // no key/value pairs present -> force empty directory WriteAtoms(os,dir,false); os << " , ," << endl; } if(depth) { // save sub-directories int nd = depth > 0?depth-1:-1; for(int di = 0; di < dsize; ++di) { for(pooldir *ix = dirs[di].d; ix; ix = ix->nxt) { ix->SvDir(os,nd,Atoms(dir).Append(ix->dir)); } } } return true; } class xmltag { public: string tag,attr; bool Ok() const { return tag.length() > 0; } bool operator ==(const char *t) const { return !tag.compare(t); } void Clear() { #if defined(_MSC_VER) && (_MSC_VER < 0x1200) // incomplete STL implementation tag = ""; attr = ""; #else tag.clear(); attr.clear(); #endif } enum { t_start,t_end,t_empty } type; }; static bool gettag(istream &is,xmltag &tag) { static const char *commstt = ""; for(;;) { // eat whitespace while(_isspace(is.peek())) is.get(); // no tag begin -> break if(is.peek() != '<') break; is.get(); // swallow < char tmp[1024],*t = tmp; // parse for comment start const char *c = commstt; while(*++c) { if(*c != is.peek()) break; *(t++) = is.get(); } if(!*c) { // is comment char cmp[2] = {0,0}; // set to some unusual initial value for(int ic = 0; ; ic = (++ic)%2) { char c = is.get(); if(c == '>') { // if third character is > then check also the former two int i; for(i = 0; i < 2 && cmp[(ic+i)%2] == commend[i]; ++i) {} if(i == 2) break; // match: comment end found! } else cmp[ic] = c; } } else { // parse until > with consideration of "s bool intx = false; for(;;) { *t = is.get(); if(*t == '"') intx = !intx; else if(*t == '>' && !intx) { *t = 0; break; } t++; } // look for tag slashes char *tb = tmp,*te = t-1,*tf; for(; _isspace(*tb); ++tb) {} if(*tb == '/') { // slash at the beginning -> end tag tag.type = xmltag::t_end; for(++tb; _isspace(*tb); ++tb) {} } else { for(; _isspace(*te); --te) {} if(*te == '/') { // slash at the end -> empty tag for(--te; _isspace(*te); --te) {} tag.type = xmltag::t_empty; } else // no slash -> begin tag tag.type = xmltag::t_start; } // copy tag text without slashes for(tf = tb; tf <= te && *tf && !_isspace(*tf); ++tf) {} tag.tag.assign(tb,tf-tb); while(_isspace(*tf)) ++tf; tag.attr.assign(tf,te-tf+1); return true; } } tag.Clear(); return false; } static void getvalue(istream &is,string &s) { char tmp[1024],*t = tmp; bool intx = false; for(;;) { char c = is.peek(); if(c == '"') intx = !intx; else if(c == '<' && !intx) break; *(t++) = is.get(); } *t = 0; s = tmp; } bool pooldir::LdDirXMLRec(istream &is,int depth,bool mkdir,AtomList &d) { Atoms k,v; bool inval = false,inkey = false,indata = false; int cntval = 0; while(!is.eof()) { xmltag tag; gettag(is,tag); if(!tag.Ok()) { // look for value string s; getvalue(is,s); if(s.length() && ( (!inval && inkey && d.Count()) || /* dir */ (inval && (inkey || indata)) /* value */ ) ) { bool ret = true; if(indata) { if(v.Count()) post("pool - XML load: value data already given, ignoring new data"); else ret = ParseAtoms(s,v,true); } else // inkey if(inval) { if(k.Count()) post("pool - XML load, value key already given, ignoring new key"); else ret = ParseAtoms(s,k,true); } else { t_atom &dkey = d[d.Count()-1]; FLEXT_ASSERT(IsSymbol(dkey)); const char *ds = GetString(dkey); FLEXT_ASSERT(ds); if(*ds) post("pool - XML load: dir key already given, ignoring new key"); else ReadAtom(s.c_str(),dkey,true); ret = true; } if(!ret) post("pool - error interpreting XML value (%s)",s.c_str()); } else post("pool - error reading XML data"); } else if(tag == "dir") { if(tag.type == xmltag::t_start) { // warn if last directory key was not given if(d.Count() && GetSymbol(d[d.Count()-1]) == sym__) post("pool - XML load: dir key must be given prior to subdirs, ignoring items"); Atoms dnext(d.Count()+1); // copy existing dir dnext.Set(d.Count(),d.Atoms(),0,false); // initialize current dir key as empty SetSymbol(dnext[d.Count()],sym__); // read next level LdDirXMLRec(is,depth,mkdir,dnext); } else if(tag.type == xmltag::t_end) { if(!cntval && mkdir) { // no values have been found in dir -> make empty dir AddDir(d); } // break tag loop break; } } else if(tag == "value") { if(tag.type == xmltag::t_start) { inval = true; ++cntval; k.Clear(); v.Clear(); } else if(tag.type == xmltag::t_end) { // set value after tag closing, but only if level <= depth if(depth < 0 || d.Count() <= depth) { int fnd; for(fnd = d.Count()-1; fnd >= 0; --fnd) if(GetSymbol(d[fnd]) == sym__) break; // look if last dir key has been given if(fnd >= 0) { if(fnd == d.Count()-1) post("pool - XML load: dir key must be given prior to values"); // else: one directory level has been left unintialized, ignore items } else { // only use first word of key if(k.Count() == 1) { pooldir *nd = mkdir?AddDir(d):GetDir(d); if(nd) nd->SetVal(k[0],new Atoms(v)); else post("pool - XML load: value key must be exactly one word, value not stored"); } } } inval = false; } } else if(tag == "key") { if(tag.type == xmltag::t_start) { inkey = true; } else if(tag.type == xmltag::t_end) { inkey = false; } } else if(tag == "data") { if(!inval) post("pool - XML tag not within "); if(tag.type == xmltag::t_start) { indata = true; } else if(tag.type == xmltag::t_end) { indata = false; } } else if(!d.Count() && tag == "pool" && tag.type == xmltag::t_end) { // break tag loop break; } #ifdef FLEXT_DEBUG else { post("pool - unknown XML tag '%s'",tag.tag.c_str()); } #endif } return true; } bool pooldir::LdDirXML(istream &is,int depth,bool mkdir) { while(!is.eof()) { xmltag tag; if(!gettag(is,tag)) break; if(tag == "pool") { if(tag.type == xmltag::t_start) { Atoms empty; // must be a separate definition for gcc LdDirXMLRec(is,depth,mkdir,empty); } else post("pool - pool not initialized yet"); } else if(tag == "!DOCTYPE") { // ignore } #ifdef FLEXT_DEBUG else { post("pool - unknown XML tag '%s'",tag.tag.c_str()); } #endif } return true; } static void indent(ostream &s,int cnt) { for(int i = 0; i < cnt; ++i) s << '\t'; } bool pooldir::SvDirXML(ostream &os,int depth,const AtomList &dir,int ind) { int i,lvls = ind?(dir.Count()?1:0):dir.Count(); for(i = 0; i < lvls; ++i) { indent(os,ind+i); os << "" << endl; indent(os,ind+i+1); os << ""; WriteAtom(os,dir[ind+i],true); os << "" << endl; } for(int vi = 0; vi < vsize; ++vi) { for(poolval *ix = vals[vi].v; ix; ix = ix->nxt) { indent(os,ind+lvls); os << ""; WriteAtom(os,ix->key,true); os << ""; WriteAtoms(os,*ix->data,true); os << "" << endl; } } if(depth) { int nd = depth > 0?depth-1:-1; for(int di = 0; di < dsize; ++di) { for(pooldir *ix = dirs[di].d; ix; ix = ix->nxt) { ix->SvDirXML(os,nd,Atoms(dir).Append(ix->dir),ind+lvls); } } } for(i = lvls-1; i >= 0; --i) { indent(os,ind+i); os << "" << endl; } return true; } unsigned int pooldir::FoldBits(unsigned long h,int bits) { if(!bits) return 0; const int hmax = (1<>i)&hmax; return ret; } int pooldir::Int2Bits(unsigned long n) { int b; for(b = 0; n; ++b) n >>= 1; return b; } pool-0.2.2+git20210923.1.40cb82e/source/main.cpp0000644002537200253720000010610013630166142020471 0ustar zmoelnigzmoelnig/* pool - hierarchical storage object for PD and Max/MSP Copyright (c) 2002-2019 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. */ #include "pool.h" #include #include #define POOL_VERSION "0.2.2" #define VCNT 32 #define DCNT 8 class pool: public flext_base { FLEXT_HEADER_S(pool,flext_base,setup) public: pool(int argc,const t_atom *argv); virtual ~pool(); static void setup(t_classid); virtual bool Init(); pooldata *Pool() { return pl; } protected: // switch to other pool void ms_pool(const AtomList &l); void mg_pool(AtomList &l); void mg_priv(bool &p) const { p = pl && pl->Private(); } // print some help message static void m_help() { post("pool " POOL_VERSION " - hierarchical storage object, (C)2002-2019 Thomas Grill"); } // clear all data in pool void m_reset(); // handle directories void m_getdir(); void m_mkdir(int argc,const t_atom *argv,bool abs = true,bool chg = false); // make (and change) to dir void m_mkchdir(int argc,const t_atom *argv) { m_mkdir(argc,argv,true,true); } // make and change to dir void m_chdir(int argc,const t_atom *argv,bool abs = true); // change to dir void m_rmdir(int argc,const t_atom *argv,bool abs = true); // remove dir void m_updir(int argc,const t_atom *argv); // one or more levels up void ms_curdir(const AtomList &l) { m_chdir(l.Count(),l.Atoms()); } void m_mksub(int argc,const t_atom *argv) { m_mkdir(argc,argv,false); } void m_mkchsub(int argc,const t_atom *argv) { m_mkdir(argc,argv,false,true); } void m_chsub(int argc,const t_atom *argv) { m_chdir(argc,argv,false); } void m_rmsub(int argc,const t_atom *argv) { m_rmdir(argc,argv,false); } // handle data void m_set(int argc,const t_atom *argv) { set(argc,argv,true); } void m_seti(int argc,const t_atom *argv); // set value at index void m_add(int argc,const t_atom *argv) { set(argc,argv,false); } void m_clr(int argc,const t_atom *argv); void m_clri(int ix); // clear value at index void m_clrall(); // only values void m_clrrec(); // also subdirectories void m_clrsub(); // only subdirectories void m_get(int argc,const t_atom *argv); void m_geti(int ix); // get value at index void m_getall(); // only values void m_getrec(int argc,const t_atom *argv); // also subdirectories void m_getsub(int argc,const t_atom *argv); // only subdirectories void m_ogetall(int argc,const t_atom *argv); // only values (ordered) void m_ogetrec(int argc,const t_atom *argv); // also subdirectories (ordered) void m_ogetsub(int argc,const t_atom *argv); // only subdirectories (ordered) void m_cntall(); // only values void m_cntrec(int argc,const t_atom *argv); // also subdirectories void m_cntsub(int argc,const t_atom *argv); // only subdirectories // print directories void m_printall(); // print values in current dir void m_printrec(int argc,const t_atom *argv,bool fromroot = false); // print values recursively void m_printroot() { m_printrec(0,NULL,true); } // print values recursively from root // cut/copy/paste void m_paste(int argc,const t_atom *argv) { paste(thisTag(),argc,argv,true); } // paste contents of clipboard void m_pasteadd(int argc,const t_atom *argv) { paste(thisTag(),argc,argv,false); } // paste but don't replace void m_clrclip(); // clear clipboard void m_cut(int argc,const t_atom *argv) { copy(thisTag(),argc,argv,true); } // cut value into clipboard void m_copy(int argc,const t_atom *argv) { copy(thisTag(),argc,argv,false); } // copy value into clipboard void m_cutall() { copyall(thisTag(),true,0); } // cut all values in current directory into clipboard void m_copyall() { copyall(thisTag(),false,0); } // copy all values in current directory into clipboard void m_cutrec(int argc,const t_atom *argv) { copyrec(thisTag(),argc,argv,true); } // cut directory (and subdirs) into clipboard void m_copyrec(int argc,const t_atom *argv) { copyrec(thisTag(),argc,argv,false); } // cut directory (and subdirs) into clipboard // load/save from/to file void m_load(int argc,const t_atom *argv) { load(argc,argv,false); } void m_save(int argc,const t_atom *argv) { save(argc,argv,false); } void m_loadx(int argc,const t_atom *argv) { load(argc,argv,true); } // XML void m_savex(int argc,const t_atom *argv) { save(argc,argv,true); } // XML // load directories void m_lddir(int argc,const t_atom *argv) { lddir(argc,argv,false); } // load values into current dir void m_ldrec(int argc,const t_atom *argv) { ldrec(argc,argv,false); } // load values recursively void m_ldxdir(int argc,const t_atom *argv) { lddir(argc,argv,true); } // load values into current dir (XML) void m_ldxrec(int argc,const t_atom *argv) { ldrec(argc,argv,true); } // load values recursively (XML) // save directories void m_svdir(int argc,const t_atom *argv) { svdir(argc,argv,false); } // save values in current dir void m_svrec(int argc,const t_atom *argv) { svrec(argc,argv,false); } // save values recursively void m_svxdir(int argc,const t_atom *argv) { svdir(argc,argv,true); } // save values in current dir (XML) void m_svxrec(int argc,const t_atom *argv) { svrec(argc,argv,true); } // save values recursively (XML) private: static bool KeyChk(const t_atom &a); static bool ValChk(int argc,const t_atom *argv); static bool ValChk(const AtomList &l) { return ValChk(l.Count(),l.Atoms()); } void ToOutAtom(int ix,const t_atom &a); static const t_symbol *sym_echo; static const t_symbol *sym_error; enum get_t { get_norm,get_cnt,get_print }; void set(int argc,const t_atom *argv,bool over); void getdir(const t_symbol *tag); int getrec(const t_symbol *tag,int level,int order,bool rev,get_t how /*= get_norm*/,const AtomList &rdir); int getsub(const t_symbol *tag,int level,int order,bool rev,get_t how /*= get_norm*/,const AtomList &rdir); void paste(const t_symbol *tag,int argc,const t_atom *argv,bool repl); void copy(const t_symbol *tag,int argc,const t_atom *argv,bool cut); void copyall(const t_symbol *tag,bool cut,int lvls); void copyrec(const t_symbol *tag,int argc,const t_atom *argv,bool cut); void load(int argc,const t_atom *argv,bool xml); void save(int argc,const t_atom *argv,bool xml); void lddir(int argc,const t_atom *argv,bool xml); // load values into current dir void ldrec(int argc,const t_atom *argv,bool xml); // load values recursively void svdir(int argc,const t_atom *argv,bool xml); // save values in current dir void svrec(int argc,const t_atom *argv,bool xml); // save values recursively void echodir() { if(echo) getdir(sym_echo); } bool absdir,echo; int vcnt,dcnt; pooldata *pl; Atoms curdir; pooldir *clip; static const t_symbol *holdname; // used during initialization of new object (between constructor and Init method) typedef std::map PoolMap; static PoolMap poolmap; void SetPool(const t_symbol *s); void FreePool(); static pooldata *GetPool(const t_symbol *s); static void RmvPool(pooldata *p); string MakeFilename(const char *fn) const; FLEXT_CALLVAR_V(mg_pool,ms_pool) FLEXT_ATTRGET_V(curdir) FLEXT_CALLSET_V(ms_curdir) FLEXT_ATTRVAR_B(absdir) FLEXT_ATTRVAR_B(echo) FLEXT_CALLGET_B(mg_priv) FLEXT_ATTRVAR_I(vcnt) FLEXT_ATTRVAR_I(dcnt) FLEXT_CALLBACK(m_help) FLEXT_CALLBACK(m_reset) FLEXT_CALLBACK(m_getdir) FLEXT_CALLBACK_V(m_mkdir) FLEXT_CALLBACK_V(m_chdir) FLEXT_CALLBACK_V(m_mkchdir) FLEXT_CALLBACK_V(m_updir) FLEXT_CALLBACK_V(m_rmdir) FLEXT_CALLBACK_V(m_mksub) FLEXT_CALLBACK_V(m_chsub) FLEXT_CALLBACK_V(m_mkchsub) FLEXT_CALLBACK_V(m_rmsub) FLEXT_CALLBACK_V(m_set) FLEXT_CALLBACK_V(m_seti) FLEXT_CALLBACK_V(m_add) FLEXT_CALLBACK_V(m_clr) FLEXT_CALLBACK_I(m_clri) FLEXT_CALLBACK(m_clrall) FLEXT_CALLBACK(m_clrrec) FLEXT_CALLBACK(m_clrsub) FLEXT_CALLBACK_V(m_get) FLEXT_CALLBACK_I(m_geti) FLEXT_CALLBACK(m_getall) FLEXT_CALLBACK_V(m_getrec) FLEXT_CALLBACK_V(m_getsub) FLEXT_CALLBACK_V(m_ogetall) FLEXT_CALLBACK_V(m_ogetrec) FLEXT_CALLBACK_V(m_ogetsub) FLEXT_CALLBACK(m_cntall) FLEXT_CALLBACK_V(m_cntrec) FLEXT_CALLBACK_V(m_cntsub) FLEXT_CALLBACK(m_printall) FLEXT_CALLBACK_V(m_printrec) FLEXT_CALLBACK(m_printroot) FLEXT_CALLBACK_V(m_paste) FLEXT_CALLBACK_V(m_pasteadd) FLEXT_CALLBACK(m_clrclip) FLEXT_CALLBACK_V(m_copy) FLEXT_CALLBACK_V(m_cut) FLEXT_CALLBACK(m_copyall) FLEXT_CALLBACK(m_cutall) FLEXT_CALLBACK_V(m_copyrec) FLEXT_CALLBACK_V(m_cutrec) FLEXT_CALLBACK_V(m_load) FLEXT_CALLBACK_V(m_save) FLEXT_CALLBACK_V(m_lddir) FLEXT_CALLBACK_V(m_ldrec) FLEXT_CALLBACK_V(m_svdir) FLEXT_CALLBACK_V(m_svrec) FLEXT_CALLBACK_V(m_loadx) FLEXT_CALLBACK_V(m_savex) FLEXT_CALLBACK_V(m_ldxdir) FLEXT_CALLBACK_V(m_ldxrec) FLEXT_CALLBACK_V(m_svxdir) FLEXT_CALLBACK_V(m_svxrec) }; FLEXT_NEW_V("pool",pool) pool::PoolMap pool::poolmap; const t_symbol *pool::sym_echo,*pool::sym_error; const t_symbol *pool::holdname; void pool::setup(t_classid c) { post(""); pool::m_help(); post(""); sym_echo = MakeSymbol("echo"); sym_error = MakeSymbol("error"); FLEXT_CADDATTR_VAR(c,"pool",mg_pool,ms_pool); FLEXT_CADDATTR_VAR(c,"curdir",curdir,ms_curdir); FLEXT_CADDATTR_VAR1(c,"absdir",absdir); FLEXT_CADDATTR_VAR1(c,"echodir",echo); FLEXT_CADDATTR_GET(c,"private",mg_priv); FLEXT_CADDATTR_VAR1(c,"valcnt",vcnt); FLEXT_CADDATTR_VAR1(c,"dircnt",dcnt); FLEXT_CADDMETHOD_(c,0,"help",m_help); FLEXT_CADDMETHOD_(c,0,"reset",m_reset); FLEXT_CADDMETHOD_(c,0,"getdir",m_getdir); FLEXT_CADDMETHOD_(c,0,"mkdir",m_mkdir); FLEXT_CADDMETHOD_(c,0,"chdir",m_chdir); FLEXT_CADDMETHOD_(c,0,"mkchdir",m_mkchdir); FLEXT_CADDMETHOD_(c,0,"rmdir",m_rmdir); FLEXT_CADDMETHOD_(c,0,"updir",m_updir); FLEXT_CADDMETHOD_(c,0,"mksub",m_mksub); FLEXT_CADDMETHOD_(c,0,"chsub",m_chsub); FLEXT_CADDMETHOD_(c,0,"mkchsub",m_mkchsub); FLEXT_CADDMETHOD_(c,0,"rmsub",m_rmsub); FLEXT_CADDMETHOD_(c,0,"set",m_set); FLEXT_CADDMETHOD_(c,0,"seti",m_seti); FLEXT_CADDMETHOD_(c,0,"add",m_add); FLEXT_CADDMETHOD_(c,0,"clr",m_clr); FLEXT_CADDMETHOD_(c,0,"clri",m_clri); FLEXT_CADDMETHOD_(c,0,"clrall",m_clrall); FLEXT_CADDMETHOD_(c,0,"clrrec",m_clrrec); FLEXT_CADDMETHOD_(c,0,"clrsub",m_clrsub); FLEXT_CADDMETHOD_(c,0,"get",m_get); FLEXT_CADDMETHOD_(c,0,"geti",m_geti); FLEXT_CADDMETHOD_(c,0,"getall",m_getall); FLEXT_CADDMETHOD_(c,0,"getrec",m_getrec); FLEXT_CADDMETHOD_(c,0,"getsub",m_getsub); FLEXT_CADDMETHOD_(c,0,"ogetall",m_ogetall); FLEXT_CADDMETHOD_(c,0,"ogetrec",m_ogetrec); FLEXT_CADDMETHOD_(c,0,"ogetsub",m_ogetsub); FLEXT_CADDMETHOD_(c,0,"cntall",m_cntall); FLEXT_CADDMETHOD_(c,0,"cntrec",m_cntrec); FLEXT_CADDMETHOD_(c,0,"cntsub",m_cntsub); FLEXT_CADDMETHOD_(c,0,"printall",m_printall); FLEXT_CADDMETHOD_(c,0,"printrec",m_printrec); FLEXT_CADDMETHOD_(c,0,"printroot",m_printroot); FLEXT_CADDMETHOD_(c,0,"paste",m_paste); FLEXT_CADDMETHOD_(c,0,"pasteadd",m_pasteadd); FLEXT_CADDMETHOD_(c,0,"clrclip",m_clrclip); FLEXT_CADDMETHOD_(c,0,"cut",m_cut); FLEXT_CADDMETHOD_(c,0,"copy",m_copy); FLEXT_CADDMETHOD_(c,0,"cutall",m_cutall); FLEXT_CADDMETHOD_(c,0,"copyall",m_copyall); FLEXT_CADDMETHOD_(c,0,"cutrec",m_cutrec); FLEXT_CADDMETHOD_(c,0,"copyrec",m_copyrec); FLEXT_CADDMETHOD_(c,0,"load",m_load); FLEXT_CADDMETHOD_(c,0,"save",m_save); FLEXT_CADDMETHOD_(c,0,"lddir",m_lddir); FLEXT_CADDMETHOD_(c,0,"ldrec",m_ldrec); FLEXT_CADDMETHOD_(c,0,"svdir",m_svdir); FLEXT_CADDMETHOD_(c,0,"svrec",m_svrec); FLEXT_CADDMETHOD_(c,0,"loadx",m_loadx); FLEXT_CADDMETHOD_(c,0,"savex",m_savex); FLEXT_CADDMETHOD_(c,0,"ldxdir",m_ldxdir); FLEXT_CADDMETHOD_(c,0,"ldxrec",m_ldxrec); FLEXT_CADDMETHOD_(c,0,"svxdir",m_svxdir); FLEXT_CADDMETHOD_(c,0,"svxrec",m_svxrec); } pool::pool(int argc,const t_atom *argv): absdir(true),echo(false), pl(NULL), clip(NULL), vcnt(VCNT),dcnt(DCNT) { holdname = argc >= 1 && IsSymbol(argv[0])?GetSymbol(argv[0]):NULL; AddInAnything("Commands in"); AddOutList(); AddOutAnything(); AddOutList(); AddOutAnything(); } pool::~pool() { FreePool(); } bool pool::Init() { if(flext_base::Init()) { SetPool(holdname); return true; } else return false; } void pool::SetPool(const t_symbol *s) { if(s) { if(pl) { // check if new symbol equals the current one if(pl->sym == s) return; else FreePool(); } pl = GetPool(s); } else { if(pl) { // if already private no need to allocate new storage if(pl->Private()) return; else FreePool(); } pl = new pooldata(NULL,vcnt,dcnt); } } void pool::FreePool() { curdir(); // reset current directory if(pl) { if(!pl->Private()) RmvPool(pl); else delete pl; pl = NULL; } if(clip) { delete clip; clip = NULL; } } void pool::ms_pool(const AtomList &l) { const t_symbol *s = NULL; if(l.Count()) { if(l.Count() > 1) post("%s - pool: superfluous arguments ignored",thisName()); s = GetASymbol(l[0]); if(!s) post("%s - pool: invalid pool name, pool set to private",thisName()); } SetPool(s); } void pool::mg_pool(AtomList &l) { if(!pl || pl->Private()) l(); else { l(1); SetSymbol(l[0],pl->sym); } } void pool::m_reset() { curdir(); pl->Reset(); } void pool::getdir(const t_symbol *tag) { ToSysAnything(3,tag,0,NULL); ToSysList(2,curdir); } void pool::m_getdir() { getdir(thisTag()); } void pool::m_mkdir(int argc,const t_atom *argv,bool abs,bool chg) { // const char *nm = chg?"mkchdir":"mkdir"; if(!ValChk(argc,argv)) post("%s - %s: invalid directory name",thisName(),GetString(thisTag())); else { Atoms ndir; if(abs) ndir(argc,argv); else (ndir = curdir).Append(argc,argv); if(!pl->MkDir(ndir,vcnt,dcnt)) { post("%s - %s: directory couldn't be created",thisName(),GetString(thisTag())); } else if(chg) // change to newly created directory curdir = ndir; } echodir(); } void pool::m_chdir(int argc,const t_atom *argv,bool abs) { if(!ValChk(argc,argv)) post("%s - %s: invalid directory name",thisName(),GetString(thisTag())); else { Atoms prv(curdir); if(abs) curdir(argc,argv); else curdir.Append(argc,argv); if(!pl->ChkDir(curdir)) { post("%s - %s: directory couldn't be changed",thisName(),GetString(thisTag())); curdir = prv; } } echodir(); } void pool::m_updir(int argc,const t_atom *argv) { int lvls = 1; if(argc > 0) { if(CanbeInt(argv[0])) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); lvls = GetAInt(argv[0]); if(lvls < 0) post("%s - %s: invalid level specification - set to 1",thisName(),GetString(thisTag())); } else post("%s - %s: invalid level specification - set to 1",thisName(),GetString(thisTag())); } Atoms prv(curdir); if(lvls > curdir.Count()) { post("%s - %s: level exceeds directory depth - corrected",thisName(),GetString(thisTag())); curdir(); } else curdir.Part(0,curdir.Count()-lvls); if(!pl->ChkDir(curdir)) { post("%s - %s: directory couldn't be changed",thisName(),GetString(thisTag())); curdir = prv; } echodir(); } void pool::m_rmdir(int argc,const t_atom *argv,bool abs) { if(abs) curdir(argc,argv); else curdir.Append(argc,argv); if(!pl->RmDir(curdir)) post("%s - %s: directory couldn't be removed",thisName(),GetString(thisTag())); curdir(); echodir(); } void pool::set(int argc,const t_atom *argv,bool over) { if(!argc || !KeyChk(argv[0])) post("%s - %s: invalid key",thisName(),GetString(thisTag())); else if(!ValChk(argc-1,argv+1)) { post("%s - %s: invalid data values",thisName(),GetString(thisTag())); } else if(!pl->Set(curdir,argv[0],new AtomList(argc-1,argv+1),over)) post("%s - %s: value couldn't be set",thisName(),GetString(thisTag())); echodir(); } void pool::m_seti(int argc,const t_atom *argv) { if(!argc || !CanbeInt(argv[0])) post("%s - %s: invalid index",thisName(),GetString(thisTag())); else if(!ValChk(argc-1,argv+1)) { post("%s - %s: invalid data values",thisName(),GetString(thisTag())); } else if(!pl->Seti(curdir,GetAInt(argv[0]),new Atoms(argc-1,argv+1))) post("%s - %s: value couldn't be set",thisName(),GetString(thisTag())); echodir(); } void pool::m_clr(int argc,const t_atom *argv) { if(!argc || !KeyChk(argv[0])) post("%s - %s: invalid key",thisName(),GetString(thisTag())); else { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(!pl->Clr(curdir,argv[0])) post("%s - %s: value couldn't be cleared",thisName(),GetString(thisTag())); } echodir(); } void pool::m_clri(int ix) { if(ix < 0) post("%s - %s: invalid index",thisName(),GetString(thisTag())); else { if(!pl->Clri(curdir,ix)) post("%s - %s: value couldn't be cleared",thisName(),GetString(thisTag())); } echodir(); } void pool::m_clrall() { if(!pl->ClrAll(curdir,false)) post("%s - %s: values couldn't be cleared",thisName(),GetString(thisTag())); echodir(); } void pool::m_clrrec() { if(!pl->ClrAll(curdir,true)) post("%s - %s: values couldn't be cleared",thisName(),GetString(thisTag())); echodir(); } void pool::m_clrsub() { if(!pl->ClrAll(curdir,true,true)) post("%s - %s: directories couldn't be cleared",thisName(),GetString(thisTag())); echodir(); } void pool::m_get(int argc,const t_atom *argv) { if(!argc || !KeyChk(argv[0])) post("%s - %s: invalid key",thisName(),GetString(thisTag())); else { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); poolval *r = pl->Ref(curdir,argv[0]); ToSysAnything(3,thisTag(),0,NULL); if(absdir) ToSysList(2,curdir); else ToSysList(2,0,NULL); if(r) { ToOutAtom(1,r->key); ToSysList(0,*r->data); } else { ToSysBang(1); ToSysBang(0); } } echodir(); } void pool::m_geti(int ix) { if(ix < 0) post("%s - %s: invalid index",thisName(),GetString(thisTag())); else { poolval *r = pl->Refi(curdir,ix); ToSysAnything(3,thisTag(),0,NULL); if(absdir) ToSysList(2,curdir); else ToSysList(2,0,NULL); if(r) { ToOutAtom(1,r->key); ToSysList(0,*r->data); } else { ToSysBang(1); ToSysBang(0); } } echodir(); } // ---- some sorting stuff ---------------------------------- inline bool smaller(const t_atom &a,const t_atom &b,int index) { return a < b; } inline void swap(t_atom &a,t_atom &b) { t_atom c = a; a = b; b = c; } inline bool smaller(const t_atom *a,const t_atom *b,int index) { return *a < *b; } inline void swap(t_atom *a,t_atom *b) { t_atom *c = a; a = b; b = c; } inline bool smaller(const Atoms &a,const Atoms &b,int index) { if(a.Count()-1 < index) return true; else if(b.Count()-1 < index) return false; else return a[index] < b[index]; } inline void swap(Atoms &a,Atoms &b) { Atoms c(a); a = b; b = c; } inline bool smaller(const Atoms *a,const Atoms *b,int index) { return smaller(*a,*b,index); } inline void swap(Atoms *a,Atoms *b) { Atoms *c = a; a = b; b = c; } template void sift(T1 *a,T2 *b,int start,int count,int index,bool rev) { int root = start; // Point to a root node int child; while((child = root * 2 + 1) < count) { // While the root has child(ren) point to its left child // If the child has a sibling and the child's value is less than its sibling's... if(child < count-1 && smaller(a[child],a[child+1],index) != rev) child++; // ... point to the right child instead if(smaller(a[root],a[child],index) == rev) break; // If the value in root is less than in child... swap(a[root], a[child]); // ... swap the values in root and child and... if(b) swap(b[root], b[child]); root = child; // ... make root point to its child } } template void heapsort(T1 *a,T2 *b,int count,int index,bool rev) { int start = count/2-1; int end = count-1; for(; start >= 0; start--) sift(a, b, start, count, index, rev); for(; end > 0; --end) { swap(a[end], a[0]); if(b) swap(b[end], b[0]); sift(a, b, 0, end, index, rev); } } template static void orderpairs(T1 *keys,T2 *atoms,int count,int index,bool rev) { FLEXT_ASSERT(index >= 0); if(!count) return; if(index) heapsort(atoms,keys,count,index-1,rev); else heapsort(keys,atoms,count,0,rev); } // ---- sorting stuff ends ---------------------------------- int pool::getrec(const t_symbol *tag,int level,int order,bool rev,get_t how,const AtomList &rdir) { Atoms gldir(curdir); gldir.Append(rdir); int ret = 0; switch(how) { case get_cnt: ret = pl->CntAll(gldir); break; case get_print: ret = pl->PrintAll(gldir); break; case get_norm: { t_atom *k; Atoms *r; int cnt = pl->GetAll(gldir,k,r); if(!k) { FLEXT_ASSERT(!k); post("%s - %s: error retrieving values",thisName(),GetString(tag)); } else { FLEXT_ASSERT(r); if(order >= 0) orderpairs(k,r,cnt,order,rev); for(int i = 0; i < cnt; ++i) { ToSysAnything(3,tag,0,NULL); ToSysList(2,absdir?gldir:rdir); ToOutAtom(1,k[i]); ToSysList(0,r[i]); } delete[] k; delete[] r; } ret = cnt; } } if(level != 0) { const t_atom **r; int cnt = pl->GetSub(gldir,r); if(!r) post("%s - %s: error retrieving directories",thisName(),GetString(tag)); else { if(order >= 0) orderpairs(r,(Atoms *)NULL,cnt,order,rev); int lv = level > 0?level-1:-1; for(int i = 0; i < cnt; ++i) { Atoms l(rdir); l.Append(*r[i]); ret += getrec(tag,lv,order,rev,how,l); } delete[] r; } } return ret; } void pool::m_getall() { AtomList l; getrec(thisTag(),0,-1,false,get_norm,l); ToSysBang(3); echodir(); } void pool::m_ogetall(int argc,const t_atom *argv) { int index = 0; if(argc) { if(!CanbeInt(*argv) || (index = GetAInt(*argv)) < 0) { index = 0; post("%s - %s: invalid sort index specification - set to 0",thisName(),GetString(thisTag())); } --argc,++argv; } bool rev = false; if(argc) { if(!CanbeBool(*argv)) post("%s - %s: invalid sort direction specification - set to forward",thisName(),GetString(thisTag())); else rev = GetABool(*argv); --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; getrec(thisTag(),0,index,rev,get_norm,l); ToSysBang(3); echodir(); } void pool::m_getrec(int argc,const t_atom *argv) { int lvls = -1; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = -1; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; getrec(thisTag(),lvls,-1,false,get_norm,l); ToSysBang(3); echodir(); } void pool::m_ogetrec(int argc,const t_atom *argv) { int lvls = -1; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = -1; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } int index = 0; if(argc) { if(!CanbeInt(*argv) || (index = GetAInt(*argv)) < 0) { index = 0; post("%s - %s: invalid sort index specification - set to 0",thisName(),GetString(thisTag())); } --argc,++argv; } bool rev = false; if(argc) { if(!CanbeBool(*argv)) post("%s - %s: invalid sort direction specification - set to forward",thisName(),GetString(thisTag())); else rev = GetABool(*argv); --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; getrec(thisTag(),lvls,index,rev,get_norm,l); ToSysBang(3); echodir(); } int pool::getsub(const t_symbol *tag,int level,int order,bool rev,get_t how,const AtomList &rdir) { Atoms gldir(curdir); gldir.Append(rdir); int ret = 0; const t_atom **r = NULL; // CntSub is not used here because it doesn't allow checking for valid directory int cnt = pl->GetSub(gldir,r); if(!r) post("%s - %s: error retrieving directories",thisName(),GetString(tag)); else { if(order >= 0) orderpairs(r,(Atoms *)NULL,cnt,order,rev); int lv = level > 0?level-1:-1; for(int i = 0; i < cnt; ++i) { Atoms ndir(absdir?gldir:rdir); ndir.Append(*r[i]); ++ret; if(how == get_norm) { ToSysAnything(3,tag,0,NULL); ToSysList(2,curdir); ToSysList(1,ndir); ToSysBang(0); } if(level != 0) { AtomList l(rdir); l.Append(*r[i]); ret += getsub(tag,lv,order,rev,how,l); } } delete[] r; } return ret; } void pool::m_getsub(int argc,const t_atom *argv) { int lvls = 0; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = 0; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; getsub(thisTag(),lvls,-1,false,get_norm,l); ToSysBang(3); echodir(); } void pool::m_ogetsub(int argc,const t_atom *argv) { int lvls = 0; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = 0; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } int index = 0; if(argc) { if(!CanbeInt(*argv) || (index = GetAInt(*argv)) < 0) { index = 0; post("%s - %s: invalid sort index specification - set to 0",thisName(),GetString(thisTag())); } --argc,++argv; } bool rev = false; if(argc) { if(!CanbeBool(*argv)) post("%s - %s: invalid sort direction specification - set to forward",thisName(),GetString(thisTag())); else rev = GetABool(*argv); --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; getsub(thisTag(),lvls,index,rev,get_norm,l); ToSysBang(3); echodir(); } void pool::m_cntall() { AtomList l; int cnt = getrec(thisTag(),0,-1,false,get_cnt,l); ToSysSymbol(3,thisTag()); ToSysBang(2); ToSysBang(1); ToSysInt(0,cnt); echodir(); } void pool::m_cntrec(int argc,const t_atom *argv) { int lvls = -1; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = -1; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; int cnt = getrec(thisTag(),lvls,-1,false,get_cnt,l); ToSysSymbol(3,thisTag()); ToSysBang(2); ToSysBang(1); ToSysInt(0,cnt); echodir(); } void pool::m_cntsub(int argc,const t_atom *argv) { int lvls = 0; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = 0; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(thisTag()),lvls); } --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); AtomList l; int cnt = getsub(thisTag(),lvls,-1,false,get_cnt,l); ToSysSymbol(3,thisTag()); ToSysBang(2); ToSysBang(1); ToSysInt(0,cnt); echodir(); } void pool::m_printall() { AtomList l; int cnt = getrec(thisTag(),0,-1,false,get_print,l); post(""); } void pool::m_printrec(int argc,const t_atom *argv,bool fromroot) { const t_symbol *tag = thisTag(); int lvls = -1; if(argc) { if(!CanbeInt(*argv) || (lvls = GetAInt(*argv)) < -1) { lvls = 0; post("%s - %s: invalid level specification - set to %i",thisName(),GetString(tag),lvls); } --argc,++argv; } if(argc) post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag)); Atoms svdir(curdir); if(fromroot) curdir.Clear(); AtomList l; int cnt = getrec(tag,lvls,-1,false,get_print,l); post(""); curdir = svdir; } void pool::paste(const t_symbol *tag,int argc,const t_atom *argv,bool repl) { if(clip) { bool mkdir = true; int depth = -1; if(argc >= 1) { if(CanbeInt(argv[0])) depth = GetAInt(argv[1]); else post("%s - %s: invalid depth argument - set to -1",thisName(),GetString(tag)); if(argc >= 2) { if(CanbeBool(argv[1])) mkdir = GetABool(argv[1]); else post("%s - %s: invalid mkdir argument - set to true",thisName(),GetString(tag)); if(argc > 2) post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag)); } } pl->Paste(curdir,clip,depth,repl,mkdir); } else post("%s - %s: clipboard is empty",thisName(),GetString(tag)); echodir(); } void pool::m_clrclip() { if(clip) { delete clip; clip = NULL; } } void pool::copy(const t_symbol *tag,int argc,const t_atom *argv,bool cut) { if(!argc || !KeyChk(argv[0])) post("%s - %s: invalid key",thisName(),GetString(tag)); else { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag)); m_clrclip(); clip = pl->Copy(curdir,argv[0],cut); if(!clip) post("%s - %s: Copying into clipboard failed",thisName(),GetString(tag)); } echodir(); } void pool::copyall(const t_symbol *tag,bool cut,int depth) { m_clrclip(); clip = pl->CopyAll(curdir,depth,cut); if(!clip) post("%s - %s: Copying into clipboard failed",thisName(),GetString(tag)); echodir(); } void pool::copyrec(const t_symbol *tag,int argc,const t_atom *argv,bool cut) { int lvls = -1; if(argc > 0) { if(CanbeInt(argv[0])) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag)); lvls = GetAInt(argv[0]); } else post("%s - %s: invalid level specification - set to infinite",thisName(),GetString(tag)); } copyall(tag,cut,lvls); } void pool::load(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; if(argc > 0) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(IsString(argv[0])) flnm = GetString(argv[0]); } bool ok = false; if(!flnm) post("%s - %s: no filename given",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->LoadXML(file.c_str()):pl->Load(file.c_str()); if(!ok) post("%s - %s: error loading data",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } void pool::save(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; if(argc > 0) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(IsString(argv[0])) flnm = GetString(argv[0]); } bool ok = false; if(!flnm) post("%s - %s: no filename given",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->SaveXML(file.c_str()):pl->Save(file.c_str()); if(!ok) post("%s - %s: error saving data",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } void pool::lddir(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; if(argc > 0) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(IsString(argv[0])) flnm = GetString(argv[0]); } bool ok = false; if(!flnm) post("%s - %s: invalid filename",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->LdDirXML(curdir,file.c_str(),0):pl->LdDir(curdir,file.c_str(),0); if(!ok) post("%s - %s: directory couldn't be loaded",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } void pool::ldrec(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; int depth = -1; bool mkdir = true; if(argc >= 1) { if(IsString(argv[0])) flnm = GetString(argv[0]); if(argc >= 2) { if(CanbeInt(argv[1])) depth = GetAInt(argv[1]); else post("%s - %s: invalid depth argument - set to -1",thisName(),GetString(thisTag())); if(argc >= 3) { if(CanbeBool(argv[2])) mkdir = GetABool(argv[2]); else post("%s - %s: invalid mkdir argument - set to true",thisName(),GetString(thisTag())); if(argc > 3) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); } } } bool ok = false; if(!flnm) post("%s - %s: invalid filename",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->LdDirXML(curdir,file.c_str(),depth,mkdir):pl->LdDir(curdir,file.c_str(),depth,mkdir); if(!ok) post("%s - %s: directory couldn't be saved",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } void pool::svdir(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; if(argc > 0) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(IsString(argv[0])) flnm = GetString(argv[0]); } bool ok = false; if(!flnm) post("%s - %s: invalid filename",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->SvDirXML(curdir,file.c_str(),0,absdir):pl->SvDir(curdir,file.c_str(),0,absdir); if(!ok) post("%s - %s: directory couldn't be saved",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } void pool::svrec(int argc,const t_atom *argv,bool xml) { const char *flnm = NULL; if(argc > 0) { if(argc > 1) post("%s - %s: superfluous arguments ignored",thisName(),GetString(thisTag())); if(IsString(argv[0])) flnm = GetString(argv[0]); } bool ok = false; if(!flnm) post("%s - %s: invalid filename",thisName(),GetString(thisTag())); else { string file(MakeFilename(flnm)); ok = xml?pl->SvDirXML(curdir,file.c_str(),-1,absdir):pl->SvDir(curdir,file.c_str(),-1,absdir); if(!ok) post("%s - %s: directory couldn't be saved",thisName(),GetString(thisTag())); } t_atom at; SetBool(at,ok); ToOutAnything(GetOutAttr(),thisTag(),1,&at); echodir(); } bool pool::KeyChk(const t_atom &a) { return IsSymbol(a) || IsFloat(a) || IsInt(a); } bool pool::ValChk(int argc,const t_atom *argv) { for(int i = 0; i < argc; ++i) { const t_atom &a = argv[i]; if(!IsSymbol(a) && !IsFloat(a) && !IsInt(a)) return false; } return true; } void pool::ToOutAtom(int ix,const t_atom &a) { if(IsSymbol(a)) ToSysSymbol(ix,GetSymbol(a)); else if(IsFloat(a)) ToSysFloat(ix,GetFloat(a)); else if(IsInt(a)) ToSysInt(ix,GetInt(a)); else post("%s - %s type not supported!",thisName(),GetString(thisTag())); } pooldata *pool::GetPool(const t_symbol *s) { PoolMap::iterator it = poolmap.find(s); pooldata *p; if(it != poolmap.end()) p = it->second; else poolmap[s] = p = new pooldata(s); p->Push(); return p; } void pool::RmvPool(pooldata *p) { FLEXT_ASSERT(p->sym); PoolMap::iterator it = poolmap.find(p->sym); FLEXT_ASSERT(it != poolmap.end()); FLEXT_ASSERT(p == it->second); if(!p->Pop()) { poolmap.erase(it); delete p; } } string pool::MakeFilename(const char *fn) const { #if FLEXT_SYS == FLEXT_SYS_PD // / and \ must not be mixed! // (char *) type casts for BorlandC++ char *sl = strchr((char *)fn,'/'); if(!sl) sl = strchr((char *)fn,'\\'); if(!sl || (sl != fn #if FLEXT_OS == FLEXT_OS_WIN && sl[-1] != ':' // look for drive specification with ":/" or ":\\" #endif )) { // prepend absolute canvas path if filename has no absolute path const char *p = GetString(canvas_getdir(thisCanvas())); return string(p)+'/'+fn; } else return fn; #else #pragma message("Relative file paths not implemented") return fn; #endif } pool-0.2.2+git20210923.1.40cb82e/source/data.cpp0000644002537200253720000001116313630166142020462 0ustar zmoelnigzmoelnig/* pool - hierarchical storage object for PD and Max/MSP Copyright (c) 2002-2019 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. */ #include "pool.h" #include #include #include #include using namespace std; pooldata::pooldata(const t_symbol *s,int vcnt,int dcnt): sym(s),nxt(NULL),refs(0), root(nullatom,NULL,vcnt,dcnt) { FLEXT_LOG1("new pool %s",sym?flext_base::GetString(sym):""); } pooldata::~pooldata() { FLEXT_LOG1("free pool %s",sym?flext_base::GetString(sym):""); } const t_atom pooldata::nullatom = { A_NULL }; int pooldata::GetAll(const AtomList &d,t_atom *&keys,Atoms *&lst) { pooldir *pd = root.GetDir(d); if(pd) return pd->GetAll(keys,lst); else { keys = NULL; lst = NULL; return 0; } } int pooldata::PrintAll(const AtomList &d) { char tmp[1024]; d.Print(tmp,sizeof tmp); pooldir *pd = root.GetDir(d); strcat(tmp," , "); int cnt = pd?pd->PrintAll(tmp,sizeof tmp):0; if(!cnt) post(tmp); return cnt; } int pooldata::GetSub(const AtomList &d,const t_atom **&dirs) { pooldir *pd = root.GetDir(d); if(pd) return pd->GetSub(dirs); else { dirs = NULL; return 0; } } bool pooldata::Paste(const AtomList &d,const pooldir *clip,int depth,bool repl,bool mkdir) { pooldir *pd = root.GetDir(d); return pd && pd->Paste(clip,depth,repl,mkdir); } pooldir *pooldata::Copy(const AtomList &d,const t_atom &key,bool cut) { pooldir *pd = root.GetDir(d); if(pd) { AtomList *val = pd->GetVal(key,cut); if(val) { pooldir *ret = new pooldir(nullatom,NULL,pd->VSize(),pd->DSize()); ret->SetVal(key,val); return ret; } else return NULL; } else return NULL; } pooldir *pooldata::CopyAll(const AtomList &d,int depth,bool cut) { pooldir *pd = root.GetDir(d); if(pd) { // What sizes should we choose here? pooldir *ret = new pooldir(nullatom,NULL,pd->VSize(),pd->DSize()); if(pd->Copy(ret,depth,cut)) return ret; else { delete ret; return NULL; } } else return NULL; } static const char *CnvFlnm(char *dst,const char *src,int sz) { #if FLEXT_SYS == FLEXT_SYS_PD && FLEXT_OS == FLEXT_OS_WIN int i,cnt = strlen(src); if(cnt >= sz-1) return NULL; for(i = 0; i < cnt; ++i) dst[i] = src[i] != '/'?src[i]:'\\'; dst[i] = 0; return dst; #else return src; #endif } bool pooldata::LdDir(const AtomList &d,const char *flnm,int depth,bool mkdir) { pooldir *pd = root.GetDir(d); if(pd) { char tmp[1024]; // CnvFlnm checks for size of string buffer const char *t = CnvFlnm(tmp,flnm,sizeof tmp); if(t) { ifstream file(t); return file.good() && pd->LdDir(file,depth,mkdir); } else return false; } else return false; } bool pooldata::SvDir(const AtomList &d,const char *flnm,int depth,bool absdir) { pooldir *pd = root.GetDir(d); if(pd) { char tmp[1024]; // CnvFlnm checks for size of string buffer const char *t = CnvFlnm(tmp,flnm,sizeof tmp); if(t) { ofstream file(t); Atoms tmp; if(absdir) tmp = d; return file.good() && pd->SvDir(file,depth,tmp); } else return false; } else return false; } bool pooldata::LdDirXML(const AtomList &d,const char *flnm,int depth,bool mkdir) { pooldir *pd = root.GetDir(d); if(pd) { char tmp[1024]; // CnvFlnm checks for size of string buffer const char *t = CnvFlnm(tmp,flnm,sizeof tmp); if(t) { ifstream file(t); bool ret = file.good() != 0; if(ret) { file.getline(tmp,sizeof tmp); ret = !strncmp(tmp,"LdDirXML(file,depth,mkdir); return ret; } } return false; } bool pooldata::SvDirXML(const AtomList &d,const char *flnm,int depth,bool absdir) { pooldir *pd = root.GetDir(d); if(pd) { char tmp[1024]; // CnvFlnm checks for size of string buffer const char *t = CnvFlnm(tmp,flnm,sizeof tmp); if(t) { ofstream file(t); Atoms tmp; if(absdir) tmp = d; if(file.good()) { file << "" << endl; file << "" << endl; file << "" << endl; bool ret = pd->SvDirXML(file,depth,tmp); file << "" << endl; return ret; } } } return false; } pool-0.2.2+git20210923.1.40cb82e/source/pool.h0000644002537200253720000001435413630166142020174 0ustar zmoelnigzmoelnig/* pool - hierarchical storage object for PD and Max/MSP Copyright (c) 2002-2019 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. */ #ifndef __POOL_H #define __POOL_H #define FLEXT_ATTRIBUTES 1 #include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif #include using namespace std; typedef flext::AtomListStatic<8> Atoms; class poolval: public flext { public: poolval(const t_atom &key,AtomList *data); ~poolval(); poolval &Set(AtomList *data); poolval *Dup() const; t_atom key; AtomList *data; poolval *nxt; }; class pooldir: public flext { public: pooldir(const t_atom &dir,pooldir *parent,int vcnt,int dcnt); ~pooldir(); void Clear(bool rec,bool dironly = false); void Reset(bool realloc = true); bool Empty() const { return !dirs && !vals; } bool HasDirs() const { return dirs != NULL; } bool HasVals() const { return vals != NULL; } pooldir *GetDir(int argc,const t_atom *argv,bool cut = false); pooldir *GetDir(const AtomList &d,bool cut = false) { return GetDir(d.Count(),d.Atoms(),cut); } bool DelDir(int argc,const t_atom *argv); bool DelDir(const AtomList &d) { return DelDir(d.Count(),d.Atoms()); } pooldir *AddDir(int argc,const t_atom *argv,int vcnt = 0,int dcnt = 0); pooldir *AddDir(const AtomList &d,int vcnt = 0,int dcnt = 0) { return AddDir(d.Count(),d.Atoms(),vcnt,dcnt); } void SetVal(const t_atom &key,AtomList *data,bool over = true); bool SetVali(int ix,AtomList *data); void ClrVal(const t_atom &key) { SetVal(key,NULL); } bool ClrVali(int ix) { return SetVali(ix,NULL); } AtomList *PeekVal(const t_atom &key); AtomList *GetVal(const t_atom &key,bool cut = false); int CntAll() const; int GetAll(t_atom *&keys,Atoms *&lst,bool cut = false); int PrintAll(char *buf,int len) const; int GetKeys(AtomList &keys); int CntSub() const; int GetSub(const t_atom **&dirs); poolval *RefVal(const t_atom &key); poolval *RefVali(int ix); bool Paste(const pooldir *p,int depth,bool repl,bool mkdir); bool Copy(pooldir *p,int depth,bool cur); bool LdDir(istream &is,int depth,bool mkdir); bool LdDirXML(istream &is,int depth,bool mkdir); bool SvDir(ostream &os,int depth,const AtomList &dir = AtomList()); bool SvDirXML(ostream &os,int depth,const AtomList &dir = AtomList(),int ind = 0); int VSize() const { return vsize; } int DSize() const { return dsize; } protected: int VIdx(const t_atom &v) const { return FoldBits(AtomHash(v),vbits); } int DIdx(const t_atom &d) const { return FoldBits(AtomHash(d),dbits); } t_atom dir; pooldir *nxt; pooldir *parent; const int vbits,dbits,vsize,dsize; static unsigned int FoldBits(unsigned long h,int bits); static int Int2Bits(unsigned long n); struct valentry { int cnt; poolval *v; }; struct direntry { int cnt; pooldir *d; }; valentry *vals; direntry *dirs; private: bool LdDirXMLRec(istream &is,int depth,bool mkdir,AtomList &d); }; class pooldata: public flext { public: pooldata(const t_symbol *s = NULL,int vcnt = 0,int dcnt = 0); ~pooldata(); bool Private() const { return sym == NULL; } void Push() { ++refs; } bool Pop() { return --refs > 0; } void Reset() { root.Reset(); } bool MkDir(const AtomList &d,int vcnt = 0,int dcnt = 0) { root.AddDir(d,vcnt,dcnt); return true; } bool ChkDir(const AtomList &d) { return root.GetDir(d) != NULL; } bool RmDir(const AtomList &d) { return root.DelDir(d); } bool Set(const AtomList &d,const t_atom &key,AtomList *data,bool over = true) { pooldir *pd = root.GetDir(d); if(!pd) return false; pd->SetVal(key,data,over); return true; } bool Seti(const AtomList &d,int ix,AtomList *data) { pooldir *pd = root.GetDir(d); if(!pd) return false; pd->SetVali(ix,data); return true; } bool Clr(const AtomList &d,const t_atom &key) { pooldir *pd = root.GetDir(d); if(!pd) return false; pd->ClrVal(key); return true; } bool Clri(const AtomList &d,int ix) { pooldir *pd = root.GetDir(d); if(!pd) return false; pd->ClrVali(ix); return true; } bool ClrAll(const AtomList &d,bool rec,bool dironly = false) { pooldir *pd = root.GetDir(d); if(!pd) return false; pd->Clear(rec,dironly); return true; } AtomList *Peek(const AtomList &d,const t_atom &key) { pooldir *pd = root.GetDir(d); return pd?pd->PeekVal(key):NULL; } AtomList *Get(const AtomList &d,const t_atom &key) { pooldir *pd = root.GetDir(d); return pd?pd->GetVal(key):NULL; } poolval *Ref(const AtomList &d,const t_atom &key) { pooldir *pd = root.GetDir(d); return pd?pd->RefVal(key):NULL; } poolval *Refi(const AtomList &d,int ix) { pooldir *pd = root.GetDir(d); return pd?pd->RefVali(ix):NULL; } int CntAll(const AtomList &d) { pooldir *pd = root.GetDir(d); return pd?pd->CntAll():0; } int PrintAll(const AtomList &d); int GetAll(const AtomList &d,t_atom *&keys,Atoms *&lst); int CntSub(const AtomList &d) { pooldir *pd = root.GetDir(d); return pd?pd->CntSub():0; } int GetSub(const AtomList &d,const t_atom **&dirs); bool Paste(const AtomList &d,const pooldir *clip,int depth = -1,bool repl = true,bool mkdir = true); pooldir *Copy(const AtomList &d,const t_atom &key,bool cut); pooldir *CopyAll(const AtomList &d,int depth,bool cut); bool LdDir(const AtomList &d,const char *flnm,int depth,bool mkdir = true); bool SvDir(const AtomList &d,const char *flnm,int depth,bool absdir); bool Load(const char *flnm) { AtomList l; return LdDir(l,flnm,-1); } bool Save(const char *flnm) { AtomList l; return SvDir(l,flnm,-1,true); } bool LdDirXML(const AtomList &d,const char *flnm,int depth,bool mkdir = true); bool SvDirXML(const AtomList &d,const char *flnm,int depth,bool absdir); bool LoadXML(const char *flnm) { AtomList l; return LdDirXML(l,flnm,-1); } bool SaveXML(const char *flnm) { AtomList l; return SvDirXML(l,flnm,-1,true); } int refs; const t_symbol *sym; pooldata *nxt; pooldir root; private: static const t_atom nullatom; }; #endif pool-0.2.2+git20210923.1.40cb82e/gpl.txt0000644002537200253720000004313113630166142017070 0ustar zmoelnigzmoelnig GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pool-0.2.2+git20210923.1.40cb82e/Makefile0000644002537200253720000000051113630166142017200 0ustar zmoelnigzmoelnigNAME=pool cflags=-DFLEXT_INLINE -DFLEXT_ATTRIBUTES=1 # source files $(NAME).class.sources = $(wildcard source/*.cpp) # help files datafiles = $(wildcard pd/*-help.pd) # include Makefile.pdlibbuilder from submodule directory 'pd-lib-builder' PDLIBBUILDER_DIR=./pd-lib-builder/ include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder pool-0.2.2+git20210923.1.40cb82e/pool.vcproj0000644002537200253720000002620213630166142017743 0ustar zmoelnigzmoelnig pool-0.2.2+git20210923.1.40cb82e/package.txt0000644002537200253720000000014113630166142017673 0ustar zmoelnigzmoelnigNAME=pool SRCDIR=source PRECOMPILE=pool.h SRCS= main.cpp data.cpp pool.cpp HDRS= pool.h