Core: tdata, sexpr split;
This commit is contained in:
		
							parent
							
								
									08b3807d09
								
							
						
					
					
						commit
						e628f4a2fb
					
				
							
								
								
									
										320
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								INSTALL
									
									
									
									
									
								
							| @ -1,8 +1,8 @@ | ||||
| Installation Instructions | ||||
| ************************* | ||||
| 
 | ||||
| Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, | ||||
| Inc. | ||||
|    Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software | ||||
| Foundation, Inc. | ||||
| 
 | ||||
|    Copying and distribution of this file, with or without modification, | ||||
| are permitted in any medium without royalty provided the copyright | ||||
| @ -12,97 +12,96 @@ without warranty of any kind. | ||||
| Basic Installation | ||||
| ================== | ||||
| 
 | ||||
|    Briefly, the shell commands `./configure; make; make install' should | ||||
| configure, build, and install this package.  The following | ||||
| more-detailed instructions are generic; see the `README' file for | ||||
|    Briefly, the shell command './configure && make && make install' | ||||
| should configure, build, and install this package.  The following | ||||
| more-detailed instructions are generic; see the 'README' file for | ||||
| instructions specific to this package.  Some packages provide this | ||||
| `INSTALL' file but do not implement all of the features documented | ||||
| 'INSTALL' file but do not implement all of the features documented | ||||
| below.  The lack of an optional feature in a given package is not | ||||
| necessarily a bug.  More recommendations for GNU packages can be found | ||||
| in *note Makefile Conventions: (standards)Makefile Conventions. | ||||
| 
 | ||||
|    The `configure' shell script attempts to guess correct values for | ||||
|    The 'configure' shell script attempts to guess correct values for | ||||
| various system-dependent variables used during compilation.  It uses | ||||
| those values to create a `Makefile' in each directory of the package. | ||||
| It may also create one or more `.h' files containing system-dependent | ||||
| definitions.  Finally, it creates a shell script `config.status' that | ||||
| those values to create a 'Makefile' in each directory of the package. | ||||
| It may also create one or more '.h' files containing system-dependent | ||||
| definitions.  Finally, it creates a shell script 'config.status' that | ||||
| you can run in the future to recreate the current configuration, and a | ||||
| file `config.log' containing compiler output (useful mainly for | ||||
| debugging `configure'). | ||||
| file 'config.log' containing compiler output (useful mainly for | ||||
| debugging 'configure'). | ||||
| 
 | ||||
|    It can also use an optional file (typically called `config.cache' | ||||
| and enabled with `--cache-file=config.cache' or simply `-C') that saves | ||||
| the results of its tests to speed up reconfiguring.  Caching is | ||||
| disabled by default to prevent problems with accidental use of stale | ||||
| cache files. | ||||
|    It can also use an optional file (typically called 'config.cache' and | ||||
| enabled with '--cache-file=config.cache' or simply '-C') that saves the | ||||
| results of its tests to speed up reconfiguring.  Caching is disabled by | ||||
| default to prevent problems with accidental use of stale cache files. | ||||
| 
 | ||||
|    If you need to do unusual things to compile the package, please try | ||||
| to figure out how `configure' could check whether to do them, and mail | ||||
| diffs or instructions to the address given in the `README' so they can | ||||
| to figure out how 'configure' could check whether to do them, and mail | ||||
| diffs or instructions to the address given in the 'README' so they can | ||||
| be considered for the next release.  If you are using the cache, and at | ||||
| some point `config.cache' contains results you don't want to keep, you | ||||
| some point 'config.cache' contains results you don't want to keep, you | ||||
| may remove or edit it. | ||||
| 
 | ||||
|    The file `configure.ac' (or `configure.in') is used to create | ||||
| `configure' by a program called `autoconf'.  You need `configure.ac' if | ||||
| you want to change it or regenerate `configure' using a newer version | ||||
| of `autoconf'. | ||||
|    The file 'configure.ac' (or 'configure.in') is used to create | ||||
| 'configure' by a program called 'autoconf'.  You need 'configure.ac' if | ||||
| you want to change it or regenerate 'configure' using a newer version of | ||||
| 'autoconf'. | ||||
| 
 | ||||
|    The simplest way to compile this package is: | ||||
| 
 | ||||
|   1. `cd' to the directory containing the package's source code and type | ||||
|      `./configure' to configure the package for your system. | ||||
|   1. 'cd' to the directory containing the package's source code and type | ||||
|      './configure' to configure the package for your system. | ||||
| 
 | ||||
|      Running `configure' might take a while.  While running, it prints | ||||
|      Running 'configure' might take a while.  While running, it prints | ||||
|      some messages telling which features it is checking for. | ||||
| 
 | ||||
|   2. Type `make' to compile the package. | ||||
|   2. Type 'make' to compile the package. | ||||
| 
 | ||||
|   3. Optionally, type `make check' to run any self-tests that come with | ||||
|   3. Optionally, type 'make check' to run any self-tests that come with | ||||
|      the package, generally using the just-built uninstalled binaries. | ||||
| 
 | ||||
|   4. Type `make install' to install the programs and any data files and | ||||
|   4. Type 'make install' to install the programs and any data files and | ||||
|      documentation.  When installing into a prefix owned by root, it is | ||||
|      recommended that the package be configured and built as a regular | ||||
|      user, and only the `make install' phase executed with root | ||||
|      user, and only the 'make install' phase executed with root | ||||
|      privileges. | ||||
| 
 | ||||
|   5. Optionally, type `make installcheck' to repeat any self-tests, but | ||||
|   5. Optionally, type 'make installcheck' to repeat any self-tests, but | ||||
|      this time using the binaries in their final installed location. | ||||
|      This target does not install anything.  Running this target as a | ||||
|      regular user, particularly if the prior `make install' required | ||||
|      regular user, particularly if the prior 'make install' required | ||||
|      root privileges, verifies that the installation completed | ||||
|      correctly. | ||||
| 
 | ||||
|   6. You can remove the program binaries and object files from the | ||||
|      source code directory by typing `make clean'.  To also remove the | ||||
|      files that `configure' created (so you can compile the package for | ||||
|      a different kind of computer), type `make distclean'.  There is | ||||
|      also a `make maintainer-clean' target, but that is intended mainly | ||||
|      source code directory by typing 'make clean'.  To also remove the | ||||
|      files that 'configure' created (so you can compile the package for | ||||
|      a different kind of computer), type 'make distclean'.  There is | ||||
|      also a 'make maintainer-clean' target, but that is intended mainly | ||||
|      for the package's developers.  If you use it, you may have to get | ||||
|      all sorts of other programs in order to regenerate files that came | ||||
|      with the distribution. | ||||
| 
 | ||||
|   7. Often, you can also type `make uninstall' to remove the installed | ||||
|   7. Often, you can also type 'make uninstall' to remove the installed | ||||
|      files again.  In practice, not all packages have tested that | ||||
|      uninstallation works correctly, even though it is required by the | ||||
|      GNU Coding Standards. | ||||
| 
 | ||||
|   8. Some packages, particularly those that use Automake, provide `make | ||||
|   8. Some packages, particularly those that use Automake, provide 'make | ||||
|      distcheck', which can by used by developers to test that all other | ||||
|      targets like `make install' and `make uninstall' work correctly. | ||||
|      targets like 'make install' and 'make uninstall' work correctly. | ||||
|      This target is generally not run by end users. | ||||
| 
 | ||||
| Compilers and Options | ||||
| ===================== | ||||
| 
 | ||||
|    Some systems require unusual options for compilation or linking that | ||||
| the `configure' script does not know about.  Run `./configure --help' | ||||
| the 'configure' script does not know about.  Run './configure --help' | ||||
| for details on some of the pertinent environment variables. | ||||
| 
 | ||||
|    You can give `configure' initial values for configuration parameters | ||||
| by setting variables in the command line or in the environment.  Here | ||||
| is an example: | ||||
|    You can give 'configure' initial values for configuration parameters | ||||
| by setting variables in the command line or in the environment.  Here is | ||||
| an example: | ||||
| 
 | ||||
|      ./configure CC=c99 CFLAGS=-g LIBS=-lposix | ||||
| 
 | ||||
| @ -113,21 +112,21 @@ Compiling For Multiple Architectures | ||||
| 
 | ||||
|    You can compile the package for more than one kind of computer at the | ||||
| same time, by placing the object files for each architecture in their | ||||
| own directory.  To do this, you can use GNU `make'.  `cd' to the | ||||
| own directory.  To do this, you can use GNU 'make'.  'cd' to the | ||||
| directory where you want the object files and executables to go and run | ||||
| the `configure' script.  `configure' automatically checks for the | ||||
| source code in the directory that `configure' is in and in `..'.  This | ||||
| is known as a "VPATH" build. | ||||
| the 'configure' script.  'configure' automatically checks for the source | ||||
| code in the directory that 'configure' is in and in '..'.  This is known | ||||
| as a "VPATH" build. | ||||
| 
 | ||||
|    With a non-GNU `make', it is safer to compile the package for one | ||||
|    With a non-GNU 'make', it is safer to compile the package for one | ||||
| architecture at a time in the source code directory.  After you have | ||||
| installed the package for one architecture, use `make distclean' before | ||||
| installed the package for one architecture, use 'make distclean' before | ||||
| reconfiguring for another architecture. | ||||
| 
 | ||||
|    On MacOS X 10.5 and later systems, you can create libraries and | ||||
| executables that work on multiple system types--known as "fat" or | ||||
| "universal" binaries--by specifying multiple `-arch' options to the | ||||
| compiler but only a single `-arch' option to the preprocessor.  Like | ||||
| "universal" binaries--by specifying multiple '-arch' options to the | ||||
| compiler but only a single '-arch' option to the preprocessor.  Like | ||||
| this: | ||||
| 
 | ||||
|      ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ | ||||
| @ -136,105 +135,104 @@ this: | ||||
| 
 | ||||
|    This is not guaranteed to produce working output in all cases, you | ||||
| may have to build one architecture at a time and combine the results | ||||
| using the `lipo' tool if you have problems. | ||||
| using the 'lipo' tool if you have problems. | ||||
| 
 | ||||
| Installation Names | ||||
| ================== | ||||
| 
 | ||||
|    By default, `make install' installs the package's commands under | ||||
| `/usr/local/bin', include files under `/usr/local/include', etc.  You | ||||
| can specify an installation prefix other than `/usr/local' by giving | ||||
| `configure' the option `--prefix=PREFIX', where PREFIX must be an | ||||
|    By default, 'make install' installs the package's commands under | ||||
| '/usr/local/bin', include files under '/usr/local/include', etc.  You | ||||
| can specify an installation prefix other than '/usr/local' by giving | ||||
| 'configure' the option '--prefix=PREFIX', where PREFIX must be an | ||||
| absolute file name. | ||||
| 
 | ||||
|    You can specify separate installation prefixes for | ||||
| architecture-specific files and architecture-independent files.  If you | ||||
| pass the option `--exec-prefix=PREFIX' to `configure', the package uses | ||||
| pass the option '--exec-prefix=PREFIX' to 'configure', the package uses | ||||
| PREFIX as the prefix for installing programs and libraries. | ||||
| Documentation and other data files still use the regular prefix. | ||||
| 
 | ||||
|    In addition, if you use an unusual directory layout you can give | ||||
| options like `--bindir=DIR' to specify different values for particular | ||||
| kinds of files.  Run `configure --help' for a list of the directories | ||||
| you can set and what kinds of files go in them.  In general, the | ||||
| default for these options is expressed in terms of `${prefix}', so that | ||||
| specifying just `--prefix' will affect all of the other directory | ||||
| options like '--bindir=DIR' to specify different values for particular | ||||
| kinds of files.  Run 'configure --help' for a list of the directories | ||||
| you can set and what kinds of files go in them.  In general, the default | ||||
| for these options is expressed in terms of '${prefix}', so that | ||||
| specifying just '--prefix' will affect all of the other directory | ||||
| specifications that were not explicitly provided. | ||||
| 
 | ||||
|    The most portable way to affect installation locations is to pass the | ||||
| correct locations to `configure'; however, many packages provide one or | ||||
| correct locations to 'configure'; however, many packages provide one or | ||||
| both of the following shortcuts of passing variable assignments to the | ||||
| `make install' command line to change installation locations without | ||||
| 'make install' command line to change installation locations without | ||||
| having to reconfigure or recompile. | ||||
| 
 | ||||
|    The first method involves providing an override variable for each | ||||
| affected directory.  For example, `make install | ||||
| affected directory.  For example, 'make install | ||||
| prefix=/alternate/directory' will choose an alternate location for all | ||||
| directory configuration variables that were expressed in terms of | ||||
| `${prefix}'.  Any directories that were specified during `configure', | ||||
| but not in terms of `${prefix}', must each be overridden at install | ||||
| time for the entire installation to be relocated.  The approach of | ||||
| makefile variable overrides for each directory variable is required by | ||||
| the GNU Coding Standards, and ideally causes no recompilation. | ||||
| However, some platforms have known limitations with the semantics of | ||||
| shared libraries that end up requiring recompilation when using this | ||||
| method, particularly noticeable in packages that use GNU Libtool. | ||||
| '${prefix}'.  Any directories that were specified during 'configure', | ||||
| but not in terms of '${prefix}', must each be overridden at install time | ||||
| for the entire installation to be relocated.  The approach of makefile | ||||
| variable overrides for each directory variable is required by the GNU | ||||
| Coding Standards, and ideally causes no recompilation.  However, some | ||||
| platforms have known limitations with the semantics of shared libraries | ||||
| that end up requiring recompilation when using this method, particularly | ||||
| noticeable in packages that use GNU Libtool. | ||||
| 
 | ||||
|    The second method involves providing the `DESTDIR' variable.  For | ||||
| example, `make install DESTDIR=/alternate/directory' will prepend | ||||
| `/alternate/directory' before all installation names.  The approach of | ||||
| `DESTDIR' overrides is not required by the GNU Coding Standards, and | ||||
|    The second method involves providing the 'DESTDIR' variable.  For | ||||
| example, 'make install DESTDIR=/alternate/directory' will prepend | ||||
| '/alternate/directory' before all installation names.  The approach of | ||||
| 'DESTDIR' overrides is not required by the GNU Coding Standards, and | ||||
| does not work on platforms that have drive letters.  On the other hand, | ||||
| it does better at avoiding recompilation issues, and works well even | ||||
| when some directory options were not specified in terms of `${prefix}' | ||||
| at `configure' time. | ||||
| when some directory options were not specified in terms of '${prefix}' | ||||
| at 'configure' time. | ||||
| 
 | ||||
| Optional Features | ||||
| ================= | ||||
| 
 | ||||
|    If the package supports it, you can cause programs to be installed | ||||
| with an extra prefix or suffix on their names by giving `configure' the | ||||
| option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. | ||||
| with an extra prefix or suffix on their names by giving 'configure' the | ||||
| option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. | ||||
| 
 | ||||
|    Some packages pay attention to `--enable-FEATURE' options to | ||||
| `configure', where FEATURE indicates an optional part of the package. | ||||
| They may also pay attention to `--with-PACKAGE' options, where PACKAGE | ||||
| is something like `gnu-as' or `x' (for the X Window System).  The | ||||
| `README' should mention any `--enable-' and `--with-' options that the | ||||
|    Some packages pay attention to '--enable-FEATURE' options to | ||||
| 'configure', where FEATURE indicates an optional part of the package. | ||||
| They may also pay attention to '--with-PACKAGE' options, where PACKAGE | ||||
| is something like 'gnu-as' or 'x' (for the X Window System).  The | ||||
| 'README' should mention any '--enable-' and '--with-' options that the | ||||
| package recognizes. | ||||
| 
 | ||||
|    For packages that use the X Window System, `configure' can usually | ||||
|    For packages that use the X Window System, 'configure' can usually | ||||
| find the X include and library files automatically, but if it doesn't, | ||||
| you can use the `configure' options `--x-includes=DIR' and | ||||
| `--x-libraries=DIR' to specify their locations. | ||||
| you can use the 'configure' options '--x-includes=DIR' and | ||||
| '--x-libraries=DIR' to specify their locations. | ||||
| 
 | ||||
|    Some packages offer the ability to configure how verbose the | ||||
| execution of `make' will be.  For these packages, running `./configure | ||||
| execution of 'make' will be.  For these packages, running './configure | ||||
| --enable-silent-rules' sets the default to minimal output, which can be | ||||
| overridden with `make V=1'; while running `./configure | ||||
| overridden with 'make V=1'; while running './configure | ||||
| --disable-silent-rules' sets the default to verbose, which can be | ||||
| overridden with `make V=0'. | ||||
| overridden with 'make V=0'. | ||||
| 
 | ||||
| Particular systems | ||||
| ================== | ||||
| 
 | ||||
|    On HP-UX, the default C compiler is not ANSI C compatible.  If GNU | ||||
| CC is not installed, it is recommended to use the following options in | ||||
|    On HP-UX, the default C compiler is not ANSI C compatible.  If GNU CC | ||||
| is not installed, it is recommended to use the following options in | ||||
| order to use an ANSI C compiler: | ||||
| 
 | ||||
|      ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" | ||||
| 
 | ||||
| and if that doesn't work, install pre-built binaries of GCC for HP-UX. | ||||
| 
 | ||||
|    HP-UX `make' updates targets which have the same time stamps as | ||||
| their prerequisites, which makes it generally unusable when shipped | ||||
| generated files such as `configure' are involved.  Use GNU `make' | ||||
| instead. | ||||
|    HP-UX 'make' updates targets which have the same time stamps as their | ||||
| prerequisites, which makes it generally unusable when shipped generated | ||||
| files such as 'configure' are involved.  Use GNU 'make' instead. | ||||
| 
 | ||||
|    On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot | ||||
| parse its `<wchar.h>' header file.  The option `-nodtk' can be used as | ||||
| a workaround.  If GNU CC is not installed, it is therefore recommended | ||||
| to try | ||||
| parse its '<wchar.h>' header file.  The option '-nodtk' can be used as a | ||||
| workaround.  If GNU CC is not installed, it is therefore recommended to | ||||
| try | ||||
| 
 | ||||
|      ./configure CC="cc" | ||||
| 
 | ||||
| @ -242,26 +240,26 @@ and if that doesn't work, try | ||||
| 
 | ||||
|      ./configure CC="cc -nodtk" | ||||
| 
 | ||||
|    On Solaris, don't put `/usr/ucb' early in your `PATH'.  This | ||||
|    On Solaris, don't put '/usr/ucb' early in your 'PATH'.  This | ||||
| directory contains several dysfunctional programs; working variants of | ||||
| these programs are available in `/usr/bin'.  So, if you need `/usr/ucb' | ||||
| in your `PATH', put it _after_ `/usr/bin'. | ||||
| these programs are available in '/usr/bin'.  So, if you need '/usr/ucb' | ||||
| in your 'PATH', put it _after_ '/usr/bin'. | ||||
| 
 | ||||
|    On Haiku, software installed for all users goes in `/boot/common', | ||||
| not `/usr/local'.  It is recommended to use the following options: | ||||
|    On Haiku, software installed for all users goes in '/boot/common', | ||||
| not '/usr/local'.  It is recommended to use the following options: | ||||
| 
 | ||||
|      ./configure --prefix=/boot/common | ||||
| 
 | ||||
| Specifying the System Type | ||||
| ========================== | ||||
| 
 | ||||
|    There may be some features `configure' cannot figure out | ||||
|    There may be some features 'configure' cannot figure out | ||||
| automatically, but needs to determine by the type of machine the package | ||||
| will run on.  Usually, assuming the package is built to be run on the | ||||
| _same_ architectures, `configure' can figure that out, but if it prints | ||||
| _same_ architectures, 'configure' can figure that out, but if it prints | ||||
| a message saying it cannot guess the machine type, give it the | ||||
| `--build=TYPE' option.  TYPE can either be a short name for the system | ||||
| type, such as `sun4', or a canonical name which has the form: | ||||
| '--build=TYPE' option.  TYPE can either be a short name for the system | ||||
| type, such as 'sun4', or a canonical name which has the form: | ||||
| 
 | ||||
|      CPU-COMPANY-SYSTEM | ||||
| 
 | ||||
| @ -270,101 +268,101 @@ where SYSTEM can have one of these forms: | ||||
|      OS | ||||
|      KERNEL-OS | ||||
| 
 | ||||
|    See the file `config.sub' for the possible values of each field.  If | ||||
| `config.sub' isn't included in this package, then this package doesn't | ||||
|    See the file 'config.sub' for the possible values of each field.  If | ||||
| 'config.sub' isn't included in this package, then this package doesn't | ||||
| need to know the machine type. | ||||
| 
 | ||||
|    If you are _building_ compiler tools for cross-compiling, you should | ||||
| use the option `--target=TYPE' to select the type of system they will | ||||
| use the option '--target=TYPE' to select the type of system they will | ||||
| produce code for. | ||||
| 
 | ||||
|    If you want to _use_ a cross compiler, that generates code for a | ||||
| platform different from the build platform, you should specify the | ||||
| "host" platform (i.e., that on which the generated programs will | ||||
| eventually be run) with `--host=TYPE'. | ||||
| eventually be run) with '--host=TYPE'. | ||||
| 
 | ||||
| Sharing Defaults | ||||
| ================ | ||||
| 
 | ||||
|    If you want to set default values for `configure' scripts to share, | ||||
| you can create a site shell script called `config.site' that gives | ||||
| default values for variables like `CC', `cache_file', and `prefix'. | ||||
| `configure' looks for `PREFIX/share/config.site' if it exists, then | ||||
| `PREFIX/etc/config.site' if it exists.  Or, you can set the | ||||
| `CONFIG_SITE' environment variable to the location of the site script. | ||||
| A warning: not all `configure' scripts look for a site script. | ||||
|    If you want to set default values for 'configure' scripts to share, | ||||
| you can create a site shell script called 'config.site' that gives | ||||
| default values for variables like 'CC', 'cache_file', and 'prefix'. | ||||
| 'configure' looks for 'PREFIX/share/config.site' if it exists, then | ||||
| 'PREFIX/etc/config.site' if it exists.  Or, you can set the | ||||
| 'CONFIG_SITE' environment variable to the location of the site script. | ||||
| A warning: not all 'configure' scripts look for a site script. | ||||
| 
 | ||||
| Defining Variables | ||||
| ================== | ||||
| 
 | ||||
|    Variables not defined in a site shell script can be set in the | ||||
| environment passed to `configure'.  However, some packages may run | ||||
| environment passed to 'configure'.  However, some packages may run | ||||
| configure again during the build, and the customized values of these | ||||
| variables may be lost.  In order to avoid this problem, you should set | ||||
| them in the `configure' command line, using `VAR=value'.  For example: | ||||
| them in the 'configure' command line, using 'VAR=value'.  For example: | ||||
| 
 | ||||
|      ./configure CC=/usr/local2/bin/gcc | ||||
| 
 | ||||
| causes the specified `gcc' to be used as the C compiler (unless it is | ||||
| causes the specified 'gcc' to be used as the C compiler (unless it is | ||||
| overridden in the site shell script). | ||||
| 
 | ||||
| Unfortunately, this technique does not work for `CONFIG_SHELL' due to | ||||
| an Autoconf bug.  Until the bug is fixed you can use this workaround: | ||||
| Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an | ||||
| Autoconf limitation.  Until the limitation is lifted, you can use this | ||||
| workaround: | ||||
| 
 | ||||
|      CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash | ||||
|      CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash | ||||
| 
 | ||||
| `configure' Invocation | ||||
| 'configure' Invocation | ||||
| ====================== | ||||
| 
 | ||||
|    `configure' recognizes the following options to control how it | ||||
|    'configure' recognizes the following options to control how it | ||||
| operates. | ||||
| 
 | ||||
| `--help' | ||||
| `-h' | ||||
|      Print a summary of all of the options to `configure', and exit. | ||||
| '--help' | ||||
| '-h' | ||||
|      Print a summary of all of the options to 'configure', and exit. | ||||
| 
 | ||||
| `--help=short' | ||||
| `--help=recursive' | ||||
| '--help=short' | ||||
| '--help=recursive' | ||||
|      Print a summary of the options unique to this package's | ||||
|      `configure', and exit.  The `short' variant lists options used | ||||
|      only in the top level, while the `recursive' variant lists options | ||||
|      also present in any nested packages. | ||||
|      'configure', and exit.  The 'short' variant lists options used only | ||||
|      in the top level, while the 'recursive' variant lists options also | ||||
|      present in any nested packages. | ||||
| 
 | ||||
| `--version' | ||||
| `-V' | ||||
|      Print the version of Autoconf used to generate the `configure' | ||||
| '--version' | ||||
| '-V' | ||||
|      Print the version of Autoconf used to generate the 'configure' | ||||
|      script, and exit. | ||||
| 
 | ||||
| `--cache-file=FILE' | ||||
| '--cache-file=FILE' | ||||
|      Enable the cache: use and save the results of the tests in FILE, | ||||
|      traditionally `config.cache'.  FILE defaults to `/dev/null' to | ||||
|      traditionally 'config.cache'.  FILE defaults to '/dev/null' to | ||||
|      disable caching. | ||||
| 
 | ||||
| `--config-cache' | ||||
| `-C' | ||||
|      Alias for `--cache-file=config.cache'. | ||||
| '--config-cache' | ||||
| '-C' | ||||
|      Alias for '--cache-file=config.cache'. | ||||
| 
 | ||||
| `--quiet' | ||||
| `--silent' | ||||
| `-q' | ||||
| '--quiet' | ||||
| '--silent' | ||||
| '-q' | ||||
|      Do not print messages saying which checks are being made.  To | ||||
|      suppress all normal output, redirect it to `/dev/null' (any error | ||||
|      suppress all normal output, redirect it to '/dev/null' (any error | ||||
|      messages will still be shown). | ||||
| 
 | ||||
| `--srcdir=DIR' | ||||
| '--srcdir=DIR' | ||||
|      Look for the package's source code in directory DIR.  Usually | ||||
|      `configure' can determine that directory automatically. | ||||
|      'configure' can determine that directory automatically. | ||||
| 
 | ||||
| `--prefix=DIR' | ||||
|      Use DIR as the installation prefix.  *note Installation Names:: | ||||
|      for more details, including other options available for fine-tuning | ||||
|      the installation locations. | ||||
| '--prefix=DIR' | ||||
|      Use DIR as the installation prefix.  *note Installation Names:: for | ||||
|      more details, including other options available for fine-tuning the | ||||
|      installation locations. | ||||
| 
 | ||||
| `--no-create' | ||||
| `-n' | ||||
| '--no-create' | ||||
| '-n' | ||||
|      Run the configure checks, but stop before creating any output | ||||
|      files. | ||||
| 
 | ||||
| `configure' also accepts some other, not widely useful, options.  Run | ||||
| `configure --help' for more details. | ||||
| 
 | ||||
| 'configure' also accepts some other, not widely useful, options.  Run | ||||
| 'configure --help' for more details. | ||||
|  | ||||
| @ -6,7 +6,7 @@ else | ||||
| EXAMPLES =  | ||||
| endif | ||||
| 
 | ||||
| SUBDIRS = include tdata sxt sexpr sxmp tools man $(EXAMPLES) | ||||
| SUBDIRS = include sxt sxmp tools man $(EXAMPLES) | ||||
| 
 | ||||
| libsxmpdocdir = ${prefix}/doc/libsxmp | ||||
| libsxmpdoc_DATA = \
 | ||||
|  | ||||
							
								
								
									
										106
									
								
								autogen.sh
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								autogen.sh
									
									
									
									
									
								
							| @ -1,103 +1,9 @@ | ||||
| #!/bin/sh | ||||
| # Run this to generate all the initial makefiles, etc. | ||||
| 
 | ||||
| srcdir=`dirname $0` | ||||
| test -z "$srcdir" && srcdir=. | ||||
| echo "Generating configure files... may take a while." | ||||
| 
 | ||||
| DIE=0 | ||||
| 
 | ||||
| (test -f $srcdir/configure.ac) || { | ||||
|     echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" | ||||
|     echo " top-level package directory" | ||||
|     exit 1 | ||||
| } | ||||
| 
 | ||||
| (autoconf --version) < /dev/null > /dev/null 2>&1 || { | ||||
|   echo | ||||
|   echo "**Error**: You must have \`autoconf' installed." | ||||
|   echo "Download the appropriate package for your distribution," | ||||
|   echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" | ||||
|   DIE=1 | ||||
| } | ||||
| 
 | ||||
| (grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { | ||||
|   (libtool --version) < /dev/null > /dev/null 2>&1 || { | ||||
|     echo | ||||
|     echo "**Error**: You must have \`libtool' installed." | ||||
|     echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" | ||||
|     DIE=1 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| (automake --version) < /dev/null > /dev/null 2>&1 || { | ||||
|   echo | ||||
|   echo "**Error**: You must have \`automake' installed." | ||||
|   echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" | ||||
|   DIE=1 | ||||
|   NO_AUTOMAKE=yes | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # if no automake, don't bother testing for aclocal | ||||
| test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { | ||||
|   echo | ||||
|   echo "**Error**: Missing \`aclocal'.  The version of \`automake'" | ||||
|   echo "installed doesn't appear recent enough." | ||||
|   echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" | ||||
|   DIE=1 | ||||
| } | ||||
| 
 | ||||
| if test "$DIE" -eq 1; then | ||||
|   exit 1 | ||||
| fi | ||||
| 
 | ||||
| if test -z "$*"; then | ||||
|   echo "**Warning**: I am going to run \`configure' with no arguments." | ||||
|   echo "If you wish to pass any to it, please specify them on the" | ||||
|   echo \`$0\'" command line." | ||||
|   echo | ||||
| fi | ||||
| 
 | ||||
| case $CC in | ||||
| xlc ) | ||||
|   am_opt=--include-deps;; | ||||
| esac | ||||
| 
 | ||||
| for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print` | ||||
| do  | ||||
|   dr=`dirname $coin` | ||||
|   if test -f $dr/NO-AUTO-GEN; then | ||||
|     echo skipping $dr -- flagged as no auto-gen | ||||
|   else | ||||
|     echo processing $dr | ||||
|     ( cd $dr | ||||
| 
 | ||||
|       aclocalinclude="$ACLOCAL_FLAGS" | ||||
| 
 | ||||
|       if grep "^LT_INIT" configure.ac >/dev/null; then | ||||
| 	if test -z "$NO_LIBTOOLIZE" ; then  | ||||
| 	  echo "Running libtoolize..." | ||||
| 	  libtoolize --force --copy | ||||
| 	fi | ||||
|       fi | ||||
|       echo "Running aclocal $aclocalinclude ..." | ||||
|       aclocal $aclocalinclude | ||||
|       if grep "^A[CM]_CONFIG_HEADER" configure.ac >/dev/null; then | ||||
| 	echo "Running autoheader..." | ||||
| 	autoheader | ||||
|       fi | ||||
|       echo "Running automake --gnu $am_opt ..." | ||||
|       automake --add-missing --copy --gnu $am_opt | ||||
|       echo "Running autoconf ..." | ||||
|       autoconf | ||||
|     ) | ||||
|   fi | ||||
| done | ||||
| 
 | ||||
| if test x$NOCONFIGURE = x; then | ||||
|   echo Running $srcdir/configure "$@" ... | ||||
|   $srcdir/configure "$@" \ | ||||
|   && echo Now type \`make\' to compile. || exit 1 | ||||
| else | ||||
|   echo Skipping configure process. | ||||
| fi | ||||
| autoreconf --install --force && \ | ||||
|   echo "Preparing was successful if there was no error messages above." && \ | ||||
|   echo "Now type:" && \ | ||||
|   echo "  ./configure && make"  && \ | ||||
|   echo "Run './configure --help' for more information" | ||||
|  | ||||
							
								
								
									
										26
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								configure.ac
									
									
									
									
									
								
							| @ -2,8 +2,6 @@ dnl Process this file with autoconf to produce a configure script. | ||||
| 
 | ||||
| AC_INIT(libsxmp, m4_esyscmd([tr -d '\n' < VERSION.sxmp])) | ||||
| AC_SUBST([LIBSXT_VERSION], m4_esyscmd([tr -d '\n' < sxt/VERSION])) | ||||
| AC_SUBST([LIBTDATA_VERSION], m4_esyscmd([tr -d '\n' < tdata/VERSION])) | ||||
| AC_SUBST([LIBSEXPR_VERSION], m4_esyscmd([tr -d '\n' < sexpr/VERSION])) | ||||
| 
 | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| 
 | ||||
| @ -27,24 +25,6 @@ if test "${ac_cv_sizeof_uintptr_t}" = "4"; then | ||||
|    AC_DEFINE([BUILD_HOST_32BIT], 1, [Define to 1 if host is 32bit]) | ||||
| fi | ||||
| 
 | ||||
| dnl  ************************************** | ||||
| dnl ***** tests for compiler built-ins ***** | ||||
| dnl  ************************************** | ||||
| 
 | ||||
| AC_CACHE_CHECK([for __sync_bool_compare_and_swap_8], | ||||
| [ctrie_cv_func___sync_bool_compare_and_swap_8], | ||||
| [AC_LINK_IFELSE([ | ||||
| typedef unsigned int uint64  __attribute__ ((mode (DI))); | ||||
| uint64 i; | ||||
| int main() { return __sync_bool_compare_and_swap (&i, 0, 1); } | ||||
| ], | ||||
| [ctrie_cv_func___sync_bool_compare_and_swap_8=yes], | ||||
| [ctrie_cv_func___sync_bool_compare_and_swap_8=no])]) | ||||
| if test "$ctrie_cv_func___sync_bool_compare_and_swap_8" = "yes"; then | ||||
|   AC_DEFINE([HAVE__SYNC_BOOL_COMPARE_AND_SWAP_8], 1, | ||||
|     [Define to 1 if the compiler provides the __sync_bool_compare_and_swap function for uint64]) | ||||
| fi | ||||
| 
 | ||||
| dnl  ***************** | ||||
| dnl ***** options ***** | ||||
| dnl  ***************** | ||||
| @ -73,6 +53,8 @@ AM_CONDITIONAL(BUILD_SMPF_EXAMPLE, test "x$enable_build_smpf_example" = "xyes") | ||||
| dnl checking fpr dependencies | ||||
| 
 | ||||
| PKG_CHECK_MODULES(OPENSSL, [openssl]) | ||||
| PKG_CHECK_MODULES(LIBTDATA, [libtdata >= 0.2.2]) | ||||
| PKG_CHECK_MODULES(LIBSEXPR, [libsexpr >= 1.3.1]) | ||||
| 
 | ||||
| case $host_os in  | ||||
| 	linux*) 	WIN32=no | ||||
| @ -106,10 +88,6 @@ sxt/libsxt.pc | ||||
| sxt/Makefile | ||||
| sxmp/libsxmp.pc | ||||
| sxmp/Makefile | ||||
| sexpr/Makefile | ||||
| sexpr/libsexpr.pc | ||||
| tdata/Makefile | ||||
| tdata/libtdata.pc | ||||
| include/Makefile | ||||
| man/Makefile | ||||
| tools/Makefile | ||||
|  | ||||
| @ -1,7 +1,3 @@ | ||||
| nobase_include_HEADERS = sxmp/sxmp.h sxmp/errno.h sxmp/limits.h sxmp/version.h \
 | ||||
| 	sexpr/cstring.h sexpr/faststack.h sexpr/sexp_errors.h sexpr/sexp.h \
 | ||||
| 	sexpr/sexp_memory.h sexpr/sexp_ops.h sexpr/sexp_vis.h \
 | ||||
| 	tdata/bitwise.h tdata/idx_allocator.h tdata/macro.h tdata/tree.h \
 | ||||
| 	tdata/usrtc.h tdata/list.h tdata/ctrie.h \
 | ||||
| 	sxt/sxtkey.h sxt/lcrypt.h sxt/fe25519.h sxt/ge25519.h \
 | ||||
| 	sxt/sc25519.h | ||||
|  | ||||
| @ -1,142 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| /**
 | ||||
|  * cstring.h : c string library to make Ron happy.  Wrapper around plain | ||||
|  * C strings that handles automatically growing the string as data is | ||||
|  * concattenated to the end.  (note: this is an improved version of cstring | ||||
|  * from supermon.  Migrate it into that library eventually... ) | ||||
|  * | ||||
|  * -matt sottile | ||||
|  */ | ||||
| #ifndef __CSTRING_H__ | ||||
| #define __CSTRING_H__ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * Structure wrapping the character pointer and size counters (allocated vs. | ||||
|  * actual used). | ||||
|  */ | ||||
| typedef struct __cstring { | ||||
|   /**
 | ||||
|    * Base address of the string. | ||||
|    */ | ||||
|   char *base;  | ||||
| 
 | ||||
|   /**
 | ||||
|    * Size of the memory allocated and pointed to by the base pointer. | ||||
|    */ | ||||
|   size_t len; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Current size of the string stored in the buffer.  len >= curlen | ||||
|    * always, and when len < curlen would be true after a concat operation, | ||||
|    * we realloc bigger space to keep len >= curlen. | ||||
|    */ | ||||
|   size_t curlen;  | ||||
| } CSTRING; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif /* __cplusplus */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * Set the growth size.  Values less than one are ignored. | ||||
|    */ | ||||
|   void sgrowsize(size_t s); | ||||
|    | ||||
|   /**
 | ||||
|    * Allocate a new CSTRING of the given size. | ||||
|    * A NULL return value indicates that something went wrong and that | ||||
|    * sexp_errno should be checked for the cause. | ||||
|    */ | ||||
|   CSTRING *snew(size_t s); | ||||
|    | ||||
|   /**
 | ||||
|    * Concatenate the second argument to the CSTRING passed in the first. | ||||
|    * The second argument must be a pointer to a null terminated string. | ||||
|    * A NULL return value indicates that something went wrong and that | ||||
|    * sexp_errno should be checked for the cause.  The contents of s are | ||||
|    * left alone.  As such, the caller should check the pointer returned | ||||
|    * before overwriting the value of s, as this may result in a memory | ||||
|    * leak if an error condition occurs. | ||||
|    */ | ||||
|   CSTRING *sadd(CSTRING *s, char *a); | ||||
|    | ||||
|   /**
 | ||||
|    * Append a character to the end of the CSTRING. | ||||
|    * A NULL return value indicates that something went wrong and that | ||||
|    * sexp_errno should be checked for the cause.  The contents of s are | ||||
|    * left alone.  As such, the caller should check the pointer returned | ||||
|    * before overwriting the value of s, as this may result in a memory | ||||
|    * leak if an error condition occurs. | ||||
|    */ | ||||
|   CSTRING *saddch(CSTRING *s, char a); | ||||
|    | ||||
|   /**
 | ||||
|    * Trim the allocated memory to precisely the string length plus one char | ||||
|    * to hold the null terminator | ||||
|    * A NULL return value indicates that something went wrong and that | ||||
|    * sexp_errno should be checked for the cause.  The contents of s are | ||||
|    * left alone.  As such, the caller should check the pointer returned | ||||
|    * before overwriting the value of s, as this may result in a memory | ||||
|    * leak if an error condition occurs. | ||||
|    */ | ||||
|   CSTRING *strim(CSTRING *s); | ||||
|    | ||||
|   /**
 | ||||
|    * Return the base pointer of the CSTRING.  NULL either means the base | ||||
|    * pointer was null, or the CSTRING itself was NULL. | ||||
|    */ | ||||
|   char *toCharPtr(CSTRING *s); | ||||
|    | ||||
|   /**
 | ||||
|    * Set the current length to zero, effectively dumping the string without | ||||
|    * deallocating it so we can use it later without reallocating any memory. | ||||
|    */ | ||||
|   void sempty(CSTRING *s); | ||||
|    | ||||
|   /**
 | ||||
|    * Destroy the CSTRING struct and the data it points at. | ||||
|    */ | ||||
|   void sdestroy(CSTRING *s); | ||||
|    | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif /* __cplusplus */ | ||||
| 
 | ||||
| #endif /* __CSTRING_H__ */ | ||||
| @ -1,152 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| /**
 | ||||
|  * \file faststack.h | ||||
|  * | ||||
|  * \brief Implementation of a fast stack with smart memory management. | ||||
|  */ | ||||
| #ifndef __FASTSTACK_H__ | ||||
| #define __FASTSTACK_H__ | ||||
| 
 | ||||
| /**
 | ||||
|  * Structure representing a single level in the stack.  Has a pointer to the | ||||
|  * level above and below itself and a pointer to a generic blob of data | ||||
|  * associated with this level. | ||||
|  */ | ||||
| typedef struct stack_level { | ||||
|   /**
 | ||||
|    * Pointer to the level above this one.  If NULL, then this level is the | ||||
|    * top of the stack.  If above is non-NULL, this level *may* be the top, | ||||
|    * but all that can be guaranteed is that there are other allocated | ||||
|    * but potentially unused levels above this one. | ||||
|    */ | ||||
|   struct stack_level *above; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to the level below this one.  If NULL, then this level is the | ||||
|    * bottom. | ||||
|    */ | ||||
|   struct stack_level *below; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to some data associated with this level.  User is responsible | ||||
|    * for knowing what to cast the \c void \c * pointer into. | ||||
|    */ | ||||
|   void *data; | ||||
| } stack_lvl_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * Wrapper around the stack levels - keeps a pointer to the current top and | ||||
|  * bottom of the stack and a count of the current height.  This allows the top | ||||
|  * to have non-null above pointer resulting from previously allocated stack | ||||
|  * levels that may be recycled later without \c malloc overhead. | ||||
|  */ | ||||
| typedef struct stack_wrapper { | ||||
|   /**
 | ||||
|    * The top of the stack.  If this is NULL, the stack is empty. | ||||
|    */ | ||||
|   stack_lvl_t *top; | ||||
|    | ||||
|   /**
 | ||||
|    * The bottom of the stack.  If this is NULL, the stack is empty. | ||||
|    */ | ||||
|   stack_lvl_t *bottom; | ||||
| 
 | ||||
|   /**
 | ||||
|    * The current height of the stack, in terms of allocated and used levels. | ||||
|    */ | ||||
|   int height; | ||||
| } faststack_t; | ||||
| 
 | ||||
| /** functions **/ | ||||
| 
 | ||||
| /* this is for C++ */ | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
|   /**
 | ||||
|    * Return a pointer to an empty stack structure.  If the return value is | ||||
|    * NULL, one should check sexp_errno to determine why. | ||||
|    */ | ||||
|   faststack_t *make_stack(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Given a stack structure, destroy it and free all of the stack levels. | ||||
|    * <B>Important note</B> : This function <I>does not</I> free the data | ||||
|    * pointed to from each level of the stack - the user is responsible | ||||
|    * for freeing this data themselves before calling this function to | ||||
|    * prevent memory leakage. | ||||
|    */ | ||||
|   void destroy_stack(faststack_t *s); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Given a stack, push a new level on referring to the data pointer. | ||||
|    * If a new level cannot be allocated, NULL is returned and sexp_errno | ||||
|    * is set with the appropriate error condition.  Memory allocation errors | ||||
|    * will result in SEXP_ERR_MEMORY, while a null stack will result in | ||||
|    * SEXP_ERR_BAD_STACK. | ||||
|    */ | ||||
|   faststack_t *push(faststack_t *cur_stack, void *data); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Given a stack, pop a level off and return a pointer to that level. | ||||
|    * The user is responsible for extracting the data, but the stack_lvl_t | ||||
|    * structures pointed to from the level (above and below) should be left | ||||
|    * alone.  If NULL is returned, either the stack contained nothing, or | ||||
|    * the incoming stack s was NULL.  Consult sexp_errno to determine which | ||||
|    * was the case -- SEXP_ERR_BAD_STACK indicates a null stack was passed in. | ||||
|    */ | ||||
|   stack_lvl_t *pop(faststack_t *s); | ||||
|    | ||||
| /* this is for C++ */ | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Given a stack \a s, examine the data pointer at the top. | ||||
|  */ | ||||
| #define top_data(s) (s->top->data) | ||||
| 
 | ||||
| /**
 | ||||
|  * Given a stack \a s, check to see if the stack is empty or not.  Value | ||||
|  * is boolean true or false. | ||||
|  */ | ||||
| #define empty_stack(s) (s->top == NULL) | ||||
| 
 | ||||
| #endif /* __FASTSTACK_H__ */ | ||||
| @ -1,806 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #ifndef __SEXP_H__ | ||||
| #define __SEXP_H__ | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> /* for BUFSIZ only */ | ||||
| #include "faststack.h" | ||||
| #include "cstring.h" | ||||
| #include "sexp_memory.h" | ||||
| #include "sexp_errors.h" | ||||
| 
 | ||||
| /* doxygen documentation groups defined here */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \defgroup IO I/O routines | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \defgroup parser Parser routines | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \mainpage A small and quick S-expression parsing library. | ||||
|  * | ||||
|  * \section intro Introduction | ||||
|  *  | ||||
|  * This library was created to provide s-expression parsing and manipulation | ||||
|  * facilities to C and C++ programs.  The primary goals were speed and | ||||
|  * efficiency - low memory impact, and the highest speed we could achieve in | ||||
|  * parsing.  Suprisingly, no other libraries on the net were found that were | ||||
|  * not bloated with features or involved embedding a full-fledged LISP or | ||||
|  * Scheme interpreter into our programs.  So, this library evolved to fill | ||||
|  * this gap.  As such, it does not guarantee that every valid LISP | ||||
|  * expression is parseable, and many features that are not required aren't | ||||
|  * implemented.  See Rivest's S-expression library for an example of a much | ||||
|  * more featureful library. | ||||
|  * | ||||
|  * What features does this library include?  At the heart of the code is a | ||||
|  * continuation-based parser implementing a basic parser state machine. | ||||
|  * Continuations allow users to accumulate multiple streams of characters, | ||||
|  * and parse each stream simultaneously.  A continuation allows the parser | ||||
|  * to stop midstream, start working on a new expression, and return to the | ||||
|  * first without corruption of complex state management in the users code. | ||||
|  * No threads, no forking, nothing more than a data structure that must be | ||||
|  * passed in and captured as data becomes available to parse.  Once an | ||||
|  * expression has been parsed, a simple structure is returned that | ||||
|  * represents the "abstract syntax tree" of the parsed expression.  For the | ||||
|  * majority of users, the parser and this data structure will be all that | ||||
|  * they will ever need to see.  For convenience reasons, other functions | ||||
|  * such as I/O wrappers and AST traversal routines have been included, but | ||||
|  * they are not required if users don't wish to use them. | ||||
|  * | ||||
|  * \section credits Credits | ||||
|  * | ||||
|  * SFSEXP: Small, Fast S-Expression Library version 1.2, October 2007 \n | ||||
|  * Written by Matthew Sottile (mjsottile@gmail.com) | ||||
|  *  | ||||
|  * \section license License Information | ||||
|  * | ||||
|  * Copyright (2003-2006). The Regents of the University of California. This | ||||
|  * material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
|  * Alamos National Laboratory, which is operated by the University of | ||||
|  * California for the U.S. Department of Energy. The U.S. Government has rights | ||||
|  * to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
|  * THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
|  * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
|  * derivative works, such modified software should be clearly marked, so as not | ||||
|  * to confuse it with the version available from LANL. | ||||
|  *  | ||||
|  * Additionally, this library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2.1 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  *  | ||||
|  * This library 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 Lesser General Public License | ||||
|  * for more details. | ||||
|  *  | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
|  *  | ||||
|  * LA-CC-04-094 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \file sexp.h | ||||
|  * | ||||
|  * \brief API for a small, fast and portable s-expression parser library. | ||||
|  */ | ||||
| 
 | ||||
| /*==============*/ | ||||
| /* ENUMERATIONS */ | ||||
| /*==============*/ | ||||
| 
 | ||||
| /**
 | ||||
|  * An element in an s-expression can be one of three types: a <i>value</i> | ||||
|  * represents an atom with an associated text value.  A <i>list</i> | ||||
|  * represents an s-expression, and the element contains a pointer to | ||||
|  * the head element of the associated s-expression. | ||||
|  */ | ||||
| typedef enum {  | ||||
|   /**
 | ||||
|    * An atom of some type.  See atom type (aty) field of element structure | ||||
|    * for details as to which atom type this is. | ||||
|    */ | ||||
|   SEXP_VALUE, | ||||
| 
 | ||||
|   /**
 | ||||
|    * A list.  This means the element points to an element representing the | ||||
|    * head of a list. | ||||
|    */ | ||||
|   SEXP_LIST | ||||
| } elt_t;  | ||||
| 
 | ||||
| /**
 | ||||
|  * For an element that represents a value, the value can be interpreted | ||||
|  * as a more specific type.  A <i>basic</i> value is a simple string with | ||||
|  * no whitespace (and therefore no quotes required).  A <i>double quote</i> | ||||
|  * value, or <i>dquote</i>, is one that contains characters (such as | ||||
|  * whitespace) that requires quotation marks to contain the string.  A | ||||
|  * <i>single quote</i> value, or <i>squote</i>, represents an element that is | ||||
|  * prefaced with a single tick-mark.  This can be either an atom or | ||||
|  * s-expression, and the result is that the parser does not attempt to parse | ||||
|  * the element following the tick mark.  It is simply stored as text.  This | ||||
|  * is similar to the meaning of a tick mark in the Scheme or LISP family | ||||
|  * of programming languages.  Finally, <i>binary</I> allows raw binary to | ||||
|  * be stored within an atom.  Note that if the binary type is used, the data | ||||
|  * is stored in bindata with the length in binlength.  Otherwise, the data | ||||
|  * us stored in the val field with val_used and val_allocated tracking the | ||||
|  * size of the value string and the total memory allocated for it. | ||||
|  */ | ||||
| typedef enum {  | ||||
|   /**
 | ||||
|    * Basic, unquoted value. | ||||
|    */ | ||||
|   SEXP_BASIC,  | ||||
| 
 | ||||
|   /**
 | ||||
|    * Single quote (tick-mark) value - contains a string representing | ||||
|    * a non-parsed portion of the s-expression. | ||||
|    */ | ||||
|   SEXP_SQUOTE,  | ||||
| 
 | ||||
|   /**
 | ||||
|    * Double-quoted string.  Similar to a basic value, but potentially | ||||
|    * containing white-space. | ||||
|    */ | ||||
|   SEXP_DQUOTE, | ||||
| 
 | ||||
|   /**
 | ||||
|    * Binary data.  This is used when the specialized parser is active | ||||
|    * and supports inlining of binary blobs of data inside an expression. | ||||
|    */ | ||||
|   SEXP_BINARY | ||||
| } atom_t; | ||||
| 
 | ||||
| /*============*/ | ||||
| /* STRUCTURES */ | ||||
| /*============*/ | ||||
| 
 | ||||
| /**
 | ||||
|  * An s-expression is represented as a linked structure of elements, | ||||
|  * where each element is either an <I>atom</I> or <I>list</I>.  An | ||||
|  * atom corresponds to a string, while a list corresponds to an | ||||
|  * s-expression.  The following grammar represents our definition of | ||||
|  * an s-expression:<P> | ||||
|  * | ||||
|  * <pre> | ||||
|  * sexpr  ::= ( sx ) | ||||
|  * sx     ::= atom sxtail | sexpr sxtail | 'sexpr sxtail | 'atom sxtail | NULL | ||||
|  * sxtail ::= sx | NULL | ||||
|  * atom   ::= quoted | value | ||||
|  * quoted ::= "ws_string" | ||||
|  * value  ::= nws_string | ||||
|  * </pre> | ||||
|  * <P> | ||||
|  * | ||||
|  * An atom can either be a quoted string, which is a string containing | ||||
|  * whitespace (possibly) surrounded by double quotes, or a non-whitespace | ||||
|  * string that does not require surrounding quotes.  An element representing | ||||
|  * an atom will have a type of <i>value</i> and data stored in the <i>val</i> | ||||
|  * field.  An element of type <i>list</i> represents an s-expression | ||||
|  * corresponding to <i>sexpr</i> in the grammar, and will have a pointer to | ||||
|  * the head of the appropriate s-expression.  Details regarding these fields | ||||
|  * and their values given with the fields themselves.  Notice that a single | ||||
|  * quote can appear directly before an s-expression or atom, similar to the | ||||
|  * use in LISP.   | ||||
|  */ | ||||
| typedef struct elt { | ||||
|   /**
 | ||||
|    * The element has a type that determines how the structure is used. | ||||
|    * If the type is <B>SEXP_VALUE</B>, then a programmer knows that | ||||
|    * either the val field or bindata field is meaningful dependin on | ||||
|    * the value of the aty field, and contains the data associated with | ||||
|    * this element of the s-expression.  If the type is | ||||
|    * <B>SEXP_LIST</B>, then the list field contains a pointer to the | ||||
|    * s-expression element representing the head of the list.  For each | ||||
|    * case, the field for the opposite case contains no meaningful data | ||||
|    * and using them in any way is likely to cause an error. | ||||
|    */ | ||||
|   elt_t ty; | ||||
| 
 | ||||
|   /**
 | ||||
|    * If the type of the element is <B>SEXP_VALUE</B> and the aty field | ||||
|    * is not <B>SEXP_BINARY</B>, this field will contain the actual data | ||||
|    * represented by this element. | ||||
|    */ | ||||
|   char  *val; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Number of bytes allocated for val. | ||||
|    */ | ||||
|   size_t   val_allocated; | ||||
|    | ||||
|   /**
 | ||||
|    * Number of bytes used in val (<= val_allocated). | ||||
|    */ | ||||
|   size_t   val_used; | ||||
|    | ||||
|   /**
 | ||||
|    * If the type of the element is <B>SEXP_LIST</B>, this field will contain | ||||
|    * a pointer to the head element of the list. | ||||
|    */ | ||||
|   struct elt *list; | ||||
| 
 | ||||
|   /**
 | ||||
|    * The <I>next</I> field is a pointer to the next element in the current | ||||
|    * expression.  If this element is the last element in the s-expression, | ||||
|    * this field will be <I>NULL</I>. | ||||
|    */ | ||||
|   struct elt *next; | ||||
| 
 | ||||
|   /**
 | ||||
|    * For elements that represent <I>values</I>, this field will specify the | ||||
|    * specific type of value that it represents.  This can be used by | ||||
|    * functions to determine how this value should be printed (ie: how it | ||||
|    * should be quoted) or interpreted (ie: interpreting s-expressions that | ||||
|    * are prefixed with a tick-mark.).  This value also indicates whether or | ||||
|    * not the programmer should look in the val field or bindata field for | ||||
|    * the atom data. | ||||
|    */ | ||||
|   atom_t aty; | ||||
| 
 | ||||
|   /**
 | ||||
|    * For elements that represent <i>binary</I> blobs, this field will | ||||
|    * point to a memory location where the data resides.  The length | ||||
|    * of this memory blob is the next field.  char* implies byte sized | ||||
|    * elements.  This is only used in INLINE_BINARY parser mode. | ||||
|    * <B>IMPORTANT NOTE</B>: The data in this field is freed on a | ||||
|    * destroy_sexp() call, so users should copy it to memory they allocate | ||||
|    * if they wish it to persist after the sexp_t has been freed.  | ||||
|    */ | ||||
|   char *bindata; | ||||
| 
 | ||||
|   /** 
 | ||||
|    * The length of the data pointed at by bindata in bytes. | ||||
|    */ | ||||
|   size_t binlength; | ||||
| } sexp_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * parser mode flag used by continuation to toggle special parser | ||||
|  * behaviour. | ||||
|  */ | ||||
| typedef enum { | ||||
|   /**
 | ||||
|    * normal (LISP-style) s-expression parser behaviour. | ||||
|    */ | ||||
|   PARSER_NORMAL, | ||||
| 
 | ||||
|   /**
 | ||||
|    * treat atoms beginning with \#b\# as inlined binary data.  everything | ||||
|    * else is treated the same as in PARSER_NORMAL mode. | ||||
|    */ | ||||
|   PARSER_INLINE_BINARY, | ||||
| 
 | ||||
|   /**
 | ||||
|    * if the event_handlers field in the continuation contains a non-null | ||||
|    * value, the handlers specified in the parser_event_handlers_t struct | ||||
|    * will be called as appropriate, but the parser will not allocate a | ||||
|    * structure composed of sexp_t structs.  Note that if the event_handlers | ||||
|    * is set to null and this mode is selected, the user would be better off | ||||
|    * not calling anything in the first place, as they are telling the parser | ||||
|    * to walk the string, but do nothing productive in the process. | ||||
|    */ | ||||
|   PARSER_EVENTS_ONLY | ||||
| } parsermode_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * Some users would prefer to, instead of parsing a full string and walking | ||||
|  * a potentially huge sexp_t structure, use an XML SAX-style parser where | ||||
|  * events are triggered as certain parts of the s-expression are encountered. | ||||
|  * This structure contains a set of function pointers that are called by | ||||
|  * the parser as it hits expression start and end, and completes reading | ||||
|  * atoms and binary data.  NOTE: The parser_event_handler struct that is | ||||
|  * a field in the continuation data structure is NOT freed by | ||||
|  * destroy_continuation since structs for callbacks are ALWAYS malloc'd | ||||
|  * by the user, not the library. | ||||
|  */ | ||||
| typedef struct parser_event_handlers { | ||||
|   /**
 | ||||
|    * The start_sexpr function pointer is called when an open parenthesis | ||||
|    * is encountered starting an expression. | ||||
|    */ | ||||
|   void (* start_sexpr)(); | ||||
|   | ||||
|   /**
 | ||||
|    * The end_sexpr function pointer is called when an close parenthesis | ||||
|    * is encountered ending an expression. | ||||
|    */ | ||||
|   void (* end_sexpr)(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * The characters function pointer is called when an atom is completely | ||||
|    * parsed.  The function must take three arguments: a pointer to the | ||||
|    * atom data, the number of elements the atom contains, and the | ||||
|    * specific type of atom that the data represents. | ||||
|    */ | ||||
|   void (* characters)(const char *data, size_t len, atom_t aty); | ||||
| 
 | ||||
|   /**
 | ||||
|    * The binary function pointer is called when the parser is functioning | ||||
|    * in INLINE_BINARY mode and binary data is encountered.  The function | ||||
|    * must take two arguments: a pointer to the beginning of the binary data | ||||
|    * and the number of bytes of data present. | ||||
|    */ | ||||
|   void (* binary)(const char *data, size_t len); | ||||
| } parser_event_handlers_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * A continuation is used by the parser to save and restore state between | ||||
|  * invocations to support partial parsing of strings.  For example, if we | ||||
|  * pass the string "(foo bar)(goo car)" to the parser, we want to be able | ||||
|  * to retrieve each s-expression one at a time - it would be difficult to | ||||
|  * return all s-expressions at once without knowing how many there are in | ||||
|  * advance (this would require more memory management than we want...). | ||||
|  * So, by using a continuation-based parser, we can call it with this string | ||||
|  * and have it return a continuation when it has parsed the first  | ||||
|  * s-expression.  Once we have processed the s-expression (accessible | ||||
|  * through the <i>last_sexpr</i> field of the continuation), we can call | ||||
|  * the parser again with the same string and continuation, and it will be | ||||
|  * able to pick up where it left off.<P> | ||||
|  * | ||||
|  * We use continuations instead of a state-ful parser to allow multiple | ||||
|  * concurrent strings to be parsed by simply maintaining a set of | ||||
|  * continuations.  Manipulating continuations by hand is required if the | ||||
|  * continuation-based parser is called directly.  This is <b>not | ||||
|  * recommended</b> unless you are willing to deal with potential errors and | ||||
|  * are willing to learn exactly how the continuation relates to the | ||||
|  * internals of the parser.  A simpler approach is to use either the | ||||
|  * <i>parse_sexp</i> function that simply returns an s-expression without | ||||
|  * exposing the continuations, or the <i>iparse_sexp</i> function that | ||||
|  * allows iteratively popping one s-expression at a time from a string | ||||
|  * containing one or more s-expressions.  Refer to the documentation for | ||||
|  * each parsing function for further details on behavior and usage. | ||||
|  */ | ||||
| typedef struct pcont { | ||||
|   /**
 | ||||
|    * The parser stack used for iterative parsing. | ||||
|    */ | ||||
|   faststack_t *stack; | ||||
| 
 | ||||
|   /**
 | ||||
|    * The last full s-expression encountered by the parser.  If this is | ||||
|    * NULL, the parser has not encountered a full s-expression and more | ||||
|    * data is required for the current s-expression being parsed.  If this | ||||
|    * is non-NULL, then the parser has encountered one s-expression and may | ||||
|    * be partially through parsing the next s-expression. | ||||
|    */ | ||||
|   sexp_t     *last_sexp; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to a temporary buffer used to store atom values during parsing. | ||||
|    */ | ||||
|   char        *val; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Current number of bytes allocated for val. | ||||
|    */ | ||||
|   size_t          val_allocated; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Current number of used bytes in val. | ||||
|    */ | ||||
|   size_t          val_used; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to the character following the last character in the current | ||||
|    * atom value being parsed. | ||||
|    */ | ||||
|   char        *vcur; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to the last character to examine in the string being parsed. | ||||
|    * When the parser is called with the continuation, this is the first | ||||
|    * character that will be processed.  If this is NULL, the parser will | ||||
|    * start parsing at the beginning of the string passed into the parser. | ||||
|    */ | ||||
|   char        *lastPos; | ||||
| 
 | ||||
|   /**
 | ||||
|    * This is a pointer to the beginning of the current string being | ||||
|    * processed.  lastPos is a pointer to some value inside the string | ||||
|    * that this points to. | ||||
|    */ | ||||
|   char        *sbuffer; | ||||
| 
 | ||||
|   /**
 | ||||
|    * This is the depth of parenthesis (the number of left parens encountered) | ||||
|    * that the parser is currently working with. | ||||
|    */ | ||||
|   unsigned int depth; | ||||
| 
 | ||||
|   /**
 | ||||
|    * This is the depth of parenthesis encountered after a single quote (tick) | ||||
|    * if the character immediately following the tick was a left paren. | ||||
|    */ | ||||
|   unsigned int qdepth; | ||||
| 
 | ||||
|   /**
 | ||||
|    * This is the state ID of the current state of the parser in the | ||||
|    * DFA representing the parser.  The current parser is a DFA based parser | ||||
|    * to simplify restoring the proper state from a continuation. | ||||
|    */ | ||||
|   unsigned int state; | ||||
| 
 | ||||
|   /**
 | ||||
|    * This is a flag indicating whether the next character to be processed | ||||
|    * should be assumed to have been prefaced with a '\' character to escape | ||||
|    * it. | ||||
|    */ | ||||
|   unsigned int esc; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Flag whether or not we are processing an atom that was preceeded by | ||||
|    * a single quote. | ||||
|    */ | ||||
|   unsigned int squoted; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Error code.  Used to indicate that the continuation being returned does | ||||
|    * not represent a successful parsing and thus the contents aren't of much | ||||
|    * value.   | ||||
|    */ | ||||
|   sexp_errcode_t error; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Mode.  The parsers' specialized behaviours can be activated by | ||||
|    * tweaking the mode setting.  There are currently two available: | ||||
|    * normal and inline_binary.  Inline_binary treats atoms that start | ||||
|    * with \#b\# specially, assuming that they have the structure: | ||||
|    * | ||||
|    *    \#b\#s\#data | ||||
|    * | ||||
|    * Where s is a positive (greater than 0) integer representing the length | ||||
|    * of the data, and data is s bytes of binary data following the \# | ||||
|    * sign.  After the s bytes, it is assumed normal s-expression data | ||||
|    * continues. | ||||
|    */ | ||||
|   parsermode_t mode; | ||||
| 
 | ||||
|   /* -----------------------------------------------------------------
 | ||||
|    * These fields below are related to dealing with INLINE_BINARY mode | ||||
|    * ----------------------------------------------------------------- */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * Length to expect of the current binary data being read in. | ||||
|    * this also corresponds to the size of the memory allocated for | ||||
|    * reading this binary data into. | ||||
|    */ | ||||
|   size_t binexpected; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Number of bytes of the binary blob that have already been read in. | ||||
|    */ | ||||
|   size_t binread; | ||||
|    | ||||
|   /**
 | ||||
|    * Pointer to the memory containing the binary data being read in. | ||||
|    */ | ||||
|   char *bindata; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Pointer to a structure holding handlers for sexpr events.  NULL for | ||||
|    * normal parser operation.  This field is NOT freed by | ||||
|    * destroy_continuation and must be free'd by the user.  This is because | ||||
|    * these are malloc'd outside the library ALWAYS, so they are the user's | ||||
|    * responsibility. | ||||
|    */ | ||||
|   parser_event_handlers_t *event_handlers; | ||||
| } pcont_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup IO | ||||
|  * This structure is a wrapper around a standard I/O file descriptor and | ||||
|  * the parsing infrastructure (continuation and a buffer) required to | ||||
|  * parse off of it.  This is used so that routines can hide the loops and | ||||
|  * details required to accumulate up data read off of the file descriptor | ||||
|  * and parse expressions individually out of it. | ||||
|  */ | ||||
| typedef struct sexp_iowrap { | ||||
|   /**
 | ||||
|    * Continuation used to parse off of the file descriptor. | ||||
|    */ | ||||
|   pcont_t *cc; | ||||
| 
 | ||||
|   /**
 | ||||
|    * The file descriptor.  Currently CANNOT be a socket since implementation | ||||
|    * uses read(), not recv(). | ||||
|    */ | ||||
|   int fd; | ||||
| 
 | ||||
|   /**
 | ||||
|    * Buffer to read data into before parsing. | ||||
|    */ | ||||
|   char buf[BUFSIZ]; | ||||
|    | ||||
|   /**
 | ||||
|    * Byte count for last read.  If it is -1, there was an error.  Otherwise, | ||||
|    * it will be a value from 0 to BUFSIZ. | ||||
|    */ | ||||
|   size_t cnt; | ||||
| } sexp_iowrap_t; | ||||
| 
 | ||||
| /*========*/ | ||||
| /* GLOBAL */ | ||||
| /*========*/ | ||||
| 
 | ||||
| /**
 | ||||
|  * Global value indicating the most recent error condition encountered. | ||||
|  * This value can be reset to SEXP_ERR_OK by calling sexp_errno_reset(). | ||||
|  */ | ||||
| extern sexp_errcode_t sexp_errno; | ||||
| 
 | ||||
| /*===========*/ | ||||
| /* FUNCTIONS */ | ||||
| /*===========*/ | ||||
| 
 | ||||
| /* this is for C++ users */ | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|   /**
 | ||||
|    * \ingroup parser | ||||
|    * Set the parameters on atom value buffer allocation and growth sizes. | ||||
|    * This is an important point for performance tuning, as many factors in | ||||
|    * the expected expression structure must be taken into account such as: | ||||
|    * | ||||
|    *   - Average size of atom values | ||||
|    *   - Variance in sizes of atom values | ||||
|    *   - Amount of memory that is tolerably ''wasted'' (allocated but not | ||||
|    *     used) | ||||
|    * | ||||
|    * The \a ss parameter specifies the initial size of all atom buffers. | ||||
|    * Ideally, this should be sufficiently large to capture MOST atom values, | ||||
|    * or at least close enough such that one growth is required.  The | ||||
|    * \a gs parameter specifies the number of bytes to increase the buffer size | ||||
|    * by when space is exhausted.  A safe choice for parameter sizes would | ||||
|    * be on the order of the average size for \a ss, and one standard | ||||
|    * deviation for \a gs.  This ensures that 50% of all expressions are | ||||
|    * guaranteed to fit in the initial buffer, and rougly 80-90% will fit in | ||||
|    * one growth.  If memory is not an issue, choosing ss to be the mean plus | ||||
|    * one standard deviation will capture 80-90% of expressions in the initial | ||||
|    * buffer, and a gs of one standard deviation will capture nearly all | ||||
|    * expressions. | ||||
|    * | ||||
|    * Note: These parameters can be tuned at runtime as needs change, and they | ||||
|    * will be applied to all expressions and expression elements parsed after | ||||
|    * they are modified.  They will not be applied retroactively to expressions | ||||
|    * that have already been parsed. | ||||
|    */ | ||||
|   sexp_errcode_t set_parser_buffer_params(size_t ss, size_t gs); | ||||
| 
 | ||||
|   /**
 | ||||
|    * return an allocated sexp_t.  This structure may be an already allocated | ||||
|    * one from the stack or a new one if none are available.  Use this instead | ||||
|    * of manually mallocing if you want to avoid excessive mallocs.  <I>Note: | ||||
|    * Mallocing your own expressions is fine - you can even use  | ||||
|    * sexp_t_deallocate to deallocate them and put them in the pool.</I> | ||||
|    * Also, if the stack has not been initialized yet, this does so. | ||||
|    */ | ||||
|   sexp_t *sexp_t_allocate(void); | ||||
| 
 | ||||
|   /**
 | ||||
|    * given a malloc'd sexp_t element, put it back into the already-allocated | ||||
|    * element stack.  This method will allocate a stack if one has not been | ||||
|    * allocated already. | ||||
|    */ | ||||
|   void sexp_t_deallocate(sexp_t *s); | ||||
|    | ||||
|   /**
 | ||||
|    * In the event that someone wants us to release ALL of the memory used | ||||
|    * between calls by the library, they can free it.  If you don't call | ||||
|    * this, the caches will be persistent for the lifetime of the library | ||||
|    * user.  Note that in the event of an error condition resulting in | ||||
|    * sexp_errno being set, the user might consider calling this to clean up | ||||
|    * any memory that may be lingering around that should be cleaned up. | ||||
|    */ | ||||
|   void sexp_cleanup(void); | ||||
| 
 | ||||
|   /**
 | ||||
|    * print a sexp_t struct as a string in the LISP style.  If the buffer | ||||
|    * is large enough and the conversion is successful, the return value | ||||
|    * represents the length of the string contained in the buffer.  If the | ||||
|    * buffer was too small, or some other error occurred, the return | ||||
|    * value is -1 and the contents of the buffer should not be assumed to | ||||
|    * contain any useful information.  When the return value is -1, the | ||||
|    * caller should check the contents of sexp_errno for details on what | ||||
|    * error may have occurred. | ||||
|    */ | ||||
|   int print_sexp(char *loc, size_t size, const sexp_t *e); | ||||
| 
 | ||||
|   /**
 | ||||
|    * print a sexp_t structure to a buffer, growing it as necessary instead | ||||
|    * of relying on fixed size buffers like print_sexp.  Important argument | ||||
|    * to tune for performance reasons is <tt>ss</tt> - the | ||||
|    * buffer start size.  The growsize used by the CSTRING routines also should | ||||
|    * be considered for tuning via the sgrowsize() function.  This routine no | ||||
|    * longer requires the user to specify the growsize, and uses the current | ||||
|    * setting without changing it. | ||||
|    */ | ||||
|   int print_sexp_cstr(CSTRING **s, const sexp_t *e, size_t ss); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Allocate a new sexp_t element representing a list. | ||||
|    */ | ||||
|   sexp_t *new_sexp_list(sexp_t *l); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Allocate a new sexp_t element representing a raw binary atom. | ||||
|    * This element will contain a pointer to the raw binary data | ||||
|    * provided, as well as the binary data length.  The character | ||||
|    * atom fields will be NULL and the corresponding val | ||||
|    * length and allocation size will be set to zero since this | ||||
|    * element is carrying a binary pointer only. | ||||
|    */ | ||||
|   sexp_t *new_sexp_binary_atom(char *data, size_t binlength); | ||||
|    | ||||
|   /**
 | ||||
|    * Allocate a new sexp_t element representing a value.  The user must | ||||
|    * specify the precise type of the atom.  This used to default to | ||||
|    * SEXP_BASIC, but this can lead to errors if the user did not expect this | ||||
|    * assumption.  By explicitly passing in the atom type, the caller should | ||||
|    * ensure that the data in the buffer is valid given the requested atom | ||||
|    * type.  For performance reasons, such checks are left to the caller if | ||||
|    * they are desired, and not performed in the library if they are not | ||||
|    * wanted. | ||||
|    */ | ||||
|   sexp_t *new_sexp_atom(const char *buf, size_t bs, atom_t aty); | ||||
|      | ||||
|   /** 
 | ||||
|    * create an initial continuation for parsing the given string  | ||||
|    */ | ||||
|   pcont_t *init_continuation(char *str); | ||||
| 
 | ||||
|   /**
 | ||||
|    * destroy a continuation.  This involves cleaning up what it contains, | ||||
|    * and cleaning up the continuation itself. | ||||
|    */ | ||||
|   void destroy_continuation (pcont_t * pc); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup IO | ||||
|    * create an IO wrapper structure around a file descriptor.  A NULL return | ||||
|    * value indicates some problem occurred allocating the wrapper, so the | ||||
|    * user should check the value of sexp_errno for further information. | ||||
|    */ | ||||
|   sexp_iowrap_t *init_iowrap(int fd); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup IO | ||||
|    * destroy an IO wrapper structure.  The file descriptor wrapped in the | ||||
|    * wrapper will <B>not</B> be closed, so the caller is responsible | ||||
|    * for manually calling close on the file descriptor. | ||||
|    */ | ||||
|   void destroy_iowrap(sexp_iowrap_t *iow); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup IO  | ||||
|    * given and IO wrapper handle, read one s-expression | ||||
|    * off of it.  this expression may be contained in a continuation, | ||||
|    * so there is no guarantee that under the covers an IO read | ||||
|    * actually is occuring.  A return value of NULL can either indicate | ||||
|    * a parser error or no more data on the input IO handle.  In the | ||||
|    * event that NULL is returned, the user should check to see if | ||||
|    * sexp_errno contains SEXP_ERR_IO_EMPTY (no more data) or a more | ||||
|    * problematic error. | ||||
|    */ | ||||
|   sexp_t *read_one_sexp(sexp_iowrap_t *iow); | ||||
|    | ||||
|   /** 
 | ||||
|    * \ingroup parser | ||||
|    * wrapper around parser for compatibility.  | ||||
|    */ | ||||
|   sexp_t *parse_sexp(char *s, size_t len); | ||||
| 
 | ||||
|   /** 
 | ||||
|    * \ingroup parser | ||||
|    * wrapper around parser for friendlier continuation use  | ||||
|    * pre-condition : continuation (cc) is NON-NULL!  | ||||
|    */ | ||||
|   sexp_t *iparse_sexp(char *s, size_t len, pcont_t *cc); | ||||
|    | ||||
|   /**
 | ||||
|    * \ingroup parser | ||||
|    * given a LISP style s-expression string, parse it into a set of | ||||
|    * connected sexp_t structures.  | ||||
|    */ | ||||
|   pcont_t *cparse_sexp(char *s, size_t len, pcont_t *pc); | ||||
|    | ||||
|   /**
 | ||||
|    * given a sexp_t structure, free the memory it uses (and recursively free | ||||
|    * the memory used by all sexp_t structures that it references).  Note | ||||
|    * that this will call the deallocation routine for sexp_t elements. | ||||
|    * This means that memory isn't freed, but stored away in a cache of | ||||
|    * pre-allocated elements.  This is an optimization to speed up the | ||||
|    * parser to eliminate wasteful free and re-malloc calls.  Note: If using | ||||
|    * inlined binary mode, this will free the data pointed to by the bindata | ||||
|    * field.  So, if you care about the data after the lifetime of the | ||||
|    * s-expression, make sure to make a copy before cleaning up the sexpr. | ||||
|    */ | ||||
|   void destroy_sexp(sexp_t *s); | ||||
| 
 | ||||
|   /**
 | ||||
|    * reset the value of sexp_errno to SEXP_ERR_OK. | ||||
|    */ | ||||
|   void reset_sexp_errno(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * print the contents of the parser continuation stack to a buffer. | ||||
|    * this is useful if an expression is partially parsed and the caller | ||||
|    * realizes that something is wrong with it.  with this routine, | ||||
|    * the caller can reconstruct the expression parsed so far and use it | ||||
|    * for error reporting.  this works with fixed size buffers allocated | ||||
|    * by the caller.  there is not a CSTRING-based version currently. | ||||
|    */ | ||||
|   void print_pcont(pcont_t * pc, char * buf, size_t buflen); | ||||
| 
 | ||||
| /* this is for C++ users */ | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* sexp helpers */ | ||||
| #define SEXP_IS_LIST(sx) \ | ||||
|         ((sx)->ty == SEXP_LIST) ? 1 : 0 | ||||
| 
 | ||||
| #define SEXP_IS_TYPE(sx,type) \ | ||||
|         ((sx)->ty == SEXP_VALUE && (sx)->aty == (type)) ? 1 : 0 | ||||
| 
 | ||||
| #define SEXP_ITERATE_LIST(lst, iter, ind) \ | ||||
|         for((ind) = 0, (iter) = (lst)->list; (ind) < sexp_list_length(lst); \ | ||||
|             (ind)++, (iter) = (iter)->next) | ||||
| 
 | ||||
| /* additional functions to work with sexp */ | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| int sexp_list_cdr(sexp_t *expr, sexp_t **sx); | ||||
| int sexp_list_car(sexp_t *expr, sexp_t **sx); | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #include "sexp_ops.h" | ||||
| 
 | ||||
| #endif /* __SEXP_H__ */ | ||||
| 
 | ||||
| @ -1,148 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #ifndef __SEXP_ERRORS_H__ | ||||
| #define __SEXP_ERRORS_H__ | ||||
| 
 | ||||
| /**
 | ||||
|  * \file sexp_errors.h | ||||
|  * | ||||
|  * \brief Error conditions are enumerated here along with any routines for | ||||
|  *        translating error codes to human readable messages. | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Error codes used by the library are defined in this enumeration.  They | ||||
|  * are either used as values for the error field within the continuation | ||||
|  * structures, or as return values for functions with a return type of | ||||
|  * sexp_errcode_t. | ||||
|  */ | ||||
| typedef enum { | ||||
|   /**
 | ||||
|    * no error. | ||||
|    */ | ||||
|   SEXP_ERR_OK = 0, | ||||
| 
 | ||||
|   /**
 | ||||
|    * memory error.  malloc/realloc/calloc failures may result in this error | ||||
|    * code.  this can either result from the system calls failing, or in the | ||||
|    * limited memory mode of the library, the memory limit being exceeded. | ||||
|    * In limited memory mode, if this error condition is present, one should | ||||
|    * check the memory limits that were in place during the erroneous call. | ||||
|    */ | ||||
|   SEXP_ERR_MEMORY, | ||||
| 
 | ||||
|   /**
 | ||||
|    * badly formed expression.  Missing, misplaced, or mismatched parenthesis | ||||
|    * will result in this error. | ||||
|    */ | ||||
|   SEXP_ERR_BADFORM, | ||||
| 
 | ||||
|   /**
 | ||||
|    * a sexp_t that is inconsistent will result in this error code.  An example | ||||
|    * is a SEXP_BASIC sexp_t with a null val field but a non-zero val_used | ||||
|    * value.  Similar cases exist for SEXP_DQUOTE, SQUOTE, and BINARY types. | ||||
|    * This value is also used in the parser to flag a case where an inlined | ||||
|    * binary block is given a negative length. | ||||
|    */ | ||||
|   SEXP_ERR_BADCONTENT, | ||||
| 
 | ||||
|   /**
 | ||||
|    * if a null string is passed into the parser, this error occurs. | ||||
|    */ | ||||
|   SEXP_ERR_NULLSTRING, | ||||
| 
 | ||||
|   /**
 | ||||
|    * general IO related errors, such as failure of fopen().  these are | ||||
|    * basically non-starters with respect to getting the IO routines going. | ||||
|    */ | ||||
|   SEXP_ERR_IO, | ||||
| 
 | ||||
|   /**
 | ||||
|    * I/O routines that return NULL may simply have nothing to read.  This is | ||||
|    * sometimes an error condition if the io wrapper continuation contains a | ||||
|    * partially complete s-expression, but nothing more is present (yet) on the | ||||
|    * file descriptor. | ||||
|    */ | ||||
|   SEXP_ERR_IO_EMPTY, | ||||
| 
 | ||||
|   /**
 | ||||
|    * when running the library under limited memory (ie, _SEXP_LIMIT_MEMORY_ | ||||
|    * defined at build time), this error will be produced when the memory | ||||
|    * limit is exceeded. | ||||
|    */ | ||||
|   SEXP_ERR_MEM_LIMIT, | ||||
| 
 | ||||
|   /**
 | ||||
|    * buffer for unparsing is full. | ||||
|    */ | ||||
|   SEXP_ERR_BUFFER_FULL, | ||||
| 
 | ||||
|   /**
 | ||||
|    * routines that take parameters such as memory limits, growth sizes, or | ||||
|    * default sizes, can produce this error if a bad value has been passed in. | ||||
|    * this error usually will indicate that the parameters were bad and the | ||||
|    * default values were used instead (ie, it is non-fatal.). | ||||
|    */ | ||||
|   SEXP_ERR_BAD_PARAM, | ||||
| 
 | ||||
|   /**
 | ||||
|    * bad stack state encountered. | ||||
|    */ | ||||
|   SEXP_ERR_BAD_STACK, | ||||
| 
 | ||||
|   /**
 | ||||
|    * unknown parser state | ||||
|    */ | ||||
|   SEXP_ERR_UNKNOWN_STATE, | ||||
| 
 | ||||
|   /**
 | ||||
|    * parsing is incomplete and need more data to complete it. | ||||
|    */ | ||||
|   SEXP_ERR_INCOMPLETE, | ||||
| 
 | ||||
|   /**
 | ||||
|    * this error code indicates that an atom was created with | ||||
|    * the incorrect constructor.  For example, attempting to | ||||
|    * create a binary mode atom with the new_sexp_atom | ||||
|    * constructor intended for text atoms will cause this to | ||||
|    * be set. | ||||
|    */ | ||||
|   SEXP_ERR_BAD_CONSTRUCTOR | ||||
| 
 | ||||
| } sexp_errcode_t; | ||||
| 
 | ||||
| #endif /* __SEXP_ERRORS_H__ */ | ||||
| @ -1,160 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #ifndef __SEXP_MEMORY_H__ | ||||
| #define __SEXP_MEMORY_H__ | ||||
| 
 | ||||
| /**
 | ||||
|  * \file sexp_memory.h | ||||
|  * | ||||
|  * \brief Wrappers around basic memory allocation/deallocation routines to | ||||
|  *        allow memory usage limiting.  Only enabled if _SEXP_LIMIT_MEMORY_ | ||||
|  *        is defined when building the library, otherwise the routines | ||||
|  *        are defined to be the standard malloc/calloc/realloc/free  | ||||
|  *        functions. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| #ifdef _SEXP_LIMIT_MEMORY_ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
|   /**
 | ||||
|    * \defgroup memory Memory management routines. | ||||
|    */ | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Wrapper around malloc, will check and increment memory usage | ||||
|    * counters if space is available.  Returns NULL if no memory left | ||||
|    * to use, otherwise returns whatever malloc returns.   | ||||
|    * Due to the fact that NULL could mean either the memory limit was exceeded | ||||
|    * or the system call returned NULL, the user must check sexp_errno to | ||||
|    * determine the root cause. | ||||
|    */ | ||||
|   void *sexp_malloc(size_t size); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory  | ||||
|    * Wrapper around calloc, will check and increment memory usage | ||||
|    * counters if space is available.  Returns NULL if no memory left | ||||
|    * to use, otherwise returns whatever calloc returns | ||||
|    * Due to the fact that NULL could mean either the memory limit was exceeded | ||||
|    * or the system call returned NULL, the user must check sexp_errno to | ||||
|    * determine the root cause. | ||||
|    */ | ||||
|   void *sexp_calloc(size_t count, size_t size); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Wrapper around free.  Instead of trusting sizeof(ptr) to return the | ||||
|    * proper value, we explicitly pass the size of memory associated with | ||||
|    * ptr.  Decrements memory usage counter and frees ptr. | ||||
|    */ | ||||
|   void sexp_free(void *ptr, size_t size); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Wrapper around realloc.  Instead of trusting sizeof(ptr) to return the | ||||
|    * proper value, we explicitly pass the size of memory associated with | ||||
|    * ptr as the oldsize.  Increments the memory usage counter by  | ||||
|    * (size-oldsize) if enough space available for realloc.   | ||||
|    * Returns NULL if no memory left to use, otherwise returns whatever  | ||||
|    * realloc returns. | ||||
|    * Due to the fact that NULL could mean either the memory limit was exceeded | ||||
|    * or the system call returned NULL, the user must check sexp_errno to | ||||
|    * determine the root cause. | ||||
|    */ | ||||
|   void *sexp_realloc(void *ptr, size_t size, size_t oldsize); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Return the memory limit imposed by the library if memory limiting was | ||||
|    * enabled at compile time. | ||||
|    */ | ||||
|   size_t get_sexp_max_memory(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Return the amount of memory used. | ||||
|    */ | ||||
|   size_t get_sexp_used_memory(); | ||||
| 
 | ||||
|   /**
 | ||||
|    * \ingroup memory | ||||
|    * Set the memory limit if memory limiting was enabled.  If the new value | ||||
|    * is zero or less, -1 is returned and sexp_errno is set.  Similarly, if  | ||||
|    * the new value is less than the current amount used by the library, | ||||
|    * -1 is returned and sexp_errno is set.  If the new value is valid, the | ||||
|    * new value is returned. | ||||
|    */ | ||||
|   int set_sexp_max_memory(size_t newsize); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup memory | ||||
|  * _SEXP_LIMIT_MEMORY_ not defined.  This is a macro that maps to calloc(). | ||||
|  */ | ||||
| #define sexp_calloc(count,size) calloc(count,size) | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup memory | ||||
|  * _SEXP_LIMIT_MEMORY_ not defined.  This is a macro that maps to malloc(). | ||||
|  */ | ||||
| #define sexp_malloc(size) malloc(size) | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup memory | ||||
|  * _SEXP_LIMIT_MEMORY_ not defined.  This is a macro that maps to free(). | ||||
|  */ | ||||
| #define sexp_free(ptr,size) free(ptr) | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup memory | ||||
|  * _SEXP_LIMIT_MEMORY_ not defined.  This is a macro that maps to realloc(). | ||||
|  */ | ||||
| #define sexp_realloc(ptr,size,oldsize) realloc((ptr),(size)) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __SEXP_MEMORY_H__ */ | ||||
| @ -1,133 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #ifndef __SEXP_OPS_H__ | ||||
| #define __SEXP_OPS_H__ | ||||
| 
 | ||||
| /**
 | ||||
|  * \file sexp_ops.h | ||||
|  * | ||||
|  * \brief A collection of useful operations to perform on s-expressions. | ||||
|  * | ||||
|  * A set of routines for operating on s-expressions.   | ||||
|  */ | ||||
| 
 | ||||
| #include "sexp.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
|   /*========*/ | ||||
|   /* MACROS */ | ||||
|   /*========*/ | ||||
|    | ||||
|   /**
 | ||||
|    * Return the head of a list \a s by reference, not copy. | ||||
|    */ | ||||
| #define hd_sexp(s) ((s)->list) | ||||
|    | ||||
|   /**
 | ||||
|    * Return the tail of a list \a s by reference, not copy. | ||||
|    */ | ||||
| #define tl_sexp(s) ((s)->list->next)  | ||||
|    | ||||
|   /**
 | ||||
|    * Return the element following the argument \a s. | ||||
|    */ | ||||
| #define next_sexp(s) ((s)->next) | ||||
|    | ||||
|   /**
 | ||||
|    * Reset the continuation \a c by setting the \c lastPos pointer to | ||||
|    * \c NULL. | ||||
|    */ | ||||
| #define reset_pcont(c) ((c)->lastPos = NULL) | ||||
| 
 | ||||
|   /**
 | ||||
|    * Find an atom in a sexpression data structure and return a pointer to | ||||
|    * it.  Return NULL if the string doesn't occur anywhere as an atom.  | ||||
|    * This is a depth-first search algorithm. | ||||
|    * | ||||
|    * \param name   Value to search for. | ||||
|    * \param start  Root element of the s-expression to search from. | ||||
|    * \return       If the value is found, return a pointer to the first | ||||
|    *               occurrence in a depth-first traversal.  NULL if not found. | ||||
|    */ | ||||
|   sexp_t *find_sexp(const char *name, sexp_t *start); | ||||
|      | ||||
|   /**
 | ||||
|    * Breadth first search for s-expressions.  Depth first search will find | ||||
|    * the first occurance of a string in an s-expression by basically finding | ||||
|    * the earliest occurance in the string representation of the expression | ||||
|    * itself.  Breadth first search will find the first occurance of a string | ||||
|    * in relation to the structure of the expression itself (IE: the instance | ||||
|    * with the lowest depth will be found). | ||||
|    *  | ||||
|    * \param name  Value to search for. | ||||
|    * \param start Root element of the s-expression to search from. | ||||
|    * \return      If the value is found, return a pointer to the first | ||||
|    *              occurrence in a breadth-first traversal.  NULL if not found. | ||||
|    */ | ||||
|   sexp_t *bfs_find_sexp(const char *name, sexp_t *start); | ||||
| 
 | ||||
|   /**
 | ||||
|    * Given an s-expression, determine the length of the list that it encodes. | ||||
|    * A null expression has length 0.  An atom has length 1.  A list has | ||||
|    * length equal to the number of sexp_t elements from the list head | ||||
|    * to the end of the ->next linked list from that point. | ||||
|    * | ||||
|    * \param sx S-expression input. | ||||
|    * \return   Number of sexp_t elements at the same level as sx, 0 for | ||||
|    *           NULL, 1 for an atom. | ||||
|    */ | ||||
|   int sexp_list_length(const sexp_t *sx); | ||||
|    | ||||
|   /**
 | ||||
|    * Copy an s-expression.  This is a deep copy - so the resulting s-expression | ||||
|    * shares no pointers with the original.  The new one can be changed without | ||||
|    * damaging the contents of the original. | ||||
|    * | ||||
|    * \param sx S-expression to copy. | ||||
|    * \return   A pointer to a copy of sx.  This is a deep copy, so no memory | ||||
|    *           is shared between the original and the returned copy. | ||||
|    */ | ||||
|   sexp_t *copy_sexp(const sexp_t *sx); | ||||
|    | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __SEXP_OPS_H__ */ | ||||
| @ -1,65 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| /**
 | ||||
|  * \defgroup viz Visualization and debugging routines | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * \file sexp_vis.h | ||||
|  * | ||||
|  * \brief API for emitting graphviz data structure visualizations. | ||||
|  */ | ||||
| #ifndef __SEXP_VIS_H__ | ||||
| #define __SEXP_VIS_H__ | ||||
| 
 | ||||
| /**
 | ||||
|  * \ingroup viz | ||||
|  * | ||||
|  * Given a s-expression and a filename, this routine creates a DOT-file that | ||||
|  * can be used to generate a visualization of the s-expression data structure. | ||||
|  * This is useful for debugging to ensure that the structure is correct and | ||||
|  * follows what was expected by the programmer.  Non-trivial s-expressions | ||||
|  * can yield very large visualizations though.  Sometimes it is more | ||||
|  * practical to visualize a portion of the structure if one knows where a bug | ||||
|  * is likely to occur. | ||||
|  * | ||||
|  * \param sx     S-expression data structure to create a DOT file based on. | ||||
|  * \param fname  Filename of the DOT file to emit. | ||||
|  */ | ||||
| sexp_errcode_t sexp_to_dotfile(const sexp_t *sx, const char *fname); | ||||
| 
 | ||||
| #endif /* __SEXP_VIS_H__ */ | ||||
| @ -1,429 +0,0 @@ | ||||
| /*
 | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser 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. | ||||
|  * | ||||
|  * (c) Copyright 2006,2007,2008 Jari OS Core Team <http://jarios.org>
 | ||||
|  * (c) Copyright 2008 Dmitry Gromada <gromada82@gmail.com> | ||||
|  * (c) Copyright 2010 Alexander Vdolainen <vdo@askele.com> | ||||
|  * | ||||
|  * (c) Copyright 2012 - 2013 Askele Oy <http://askele.com>
 | ||||
|  * | ||||
|  * Implements bitwise operations with multiword bitmaps | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __BITWISE_H__ | ||||
| #define __BITWISE_H__ | ||||
| 
 | ||||
| /* TODO: add arch deps */ | ||||
| //#include <arch/bitwise.h>
 | ||||
| 
 | ||||
| /* TODO: add linux headers tests */ | ||||
| #include <asm-generic/bitsperlong.h> | ||||
| 
 | ||||
| #ifdef __BITS_PER_LONG | ||||
| #define BITS_PER_LONG  __BITS_PER_LONG | ||||
| #endif | ||||
| 
 | ||||
| #if BITS_PER_LONG == 64 | ||||
| #define TYPE_LONG_SHIFT  6 | ||||
| #endif | ||||
| 
 | ||||
| #if BITS_PER_LONG == 32 | ||||
| #define TYPE_LONG_SHIFT  5 | ||||
| #endif | ||||
| 
 | ||||
| typedef struct __bitmap { | ||||
|   int nwords; | ||||
|   unsigned long *map; | ||||
| } bitmap_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void bit_set(void *bitmap, int bit) | ||||
|  * Set bit number @a bit in the bitmap @a bitmap | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param[out] bitmap - A pointer to the bitmap | ||||
|  * @param bit - Number of bit to set | ||||
|  */ | ||||
| #ifndef ARCH_BIT_SET | ||||
| static inline void bit_set(void *bitmap, int bit) | ||||
| { | ||||
|   *(unsigned long *)bitmap |= (1 << bit); | ||||
| } | ||||
| #else | ||||
| #define bit_set(bitmap, bit) arch_bit_set(bitmap, bit) | ||||
| #endif /* ARCH_BIT_SET */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void bit_clear(void *bitmap, int bit) | ||||
|  * Clear bit number @a bit in the bitmap @a bitmap | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param[out] bitmap - A pointer to the bitmap | ||||
|  * @param bit - Number of bit to clear | ||||
|  */ | ||||
| #ifndef ARCH_BIT_CLEAR | ||||
| static inline void bit_clear(void *bitmap, int bit) | ||||
| { | ||||
|   *(unsigned long *)bitmap &= ~(1 << bit); | ||||
| } | ||||
| #else | ||||
| #define bit_clear(bitmap, bit) arch_bit_clear(bitmap, bit) | ||||
| #endif /* ARCH_BIT_CLEAR */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void bit_toggle(void *bitmap, int bit) | ||||
|  * Toggle bit @a bit in the bitmap @a bitmap. | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param[out] bitmap - A pointer to the bitmap. | ||||
|  * @param bit - Number of bit to toggle | ||||
|  */ | ||||
| #ifndef ARCH_BIT_TOGGLE | ||||
| static inline void bit_toggle(void *bitmap, int bit) | ||||
| { | ||||
|   *(unsigned long *)bitmap ^= (1 << bit); | ||||
| } | ||||
| #else | ||||
| #define bit_toggle(bitmap, bit) arch_bit_toggle(bitmap, bit) | ||||
| #endif /* ARCH_BIT_TOGGLE */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline int bit_test(void *bitmap, int bitno) | ||||
|  * Test if bit with number @a bitno is set in the bitmap @a bitmap. | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap. | ||||
|  * @param bitno - Number of bit to test | ||||
|  * @return 1 if bit is set and 0 otherwise | ||||
|  */ | ||||
| #ifndef ARCH_BIT_TEST | ||||
| static inline int bit_test(void *bitmap, int bitno) | ||||
| { | ||||
|   return ((*(unsigned long *)bitmap & (1 << bitno)) >> bitno); | ||||
| } | ||||
| #else | ||||
| #define bit_test(bitmap, bitno) arch_bit_test(bitmap, bitno) | ||||
| #endif /* ARCH_BIT_TEST */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline int bit_test_and_set(void *bitmap, int bitno) | ||||
|  * @brief Get old value of bit with number @a bitno and set @a bitno bit in the bitmap | ||||
|  * | ||||
|  * This function is similar to bit_set() except it copies old bit value before | ||||
|  * setting it to 1 and return that value after needed bit was setted. | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bitno  - The number of bit to test and set | ||||
|  * @return Old value of bit with number @a bitno | ||||
|  */ | ||||
| #ifndef ARCH_BIT_TEST_AND_SET | ||||
| static inline int bit_test_and_set(void *bitmap, int bitno) | ||||
| { | ||||
|   int val = (*(unsigned long *)bitmap & (1 << bitno)); | ||||
|   *(unsigned long *)bitmap |= (1 << bitno); | ||||
| 
 | ||||
|   return val; | ||||
| } | ||||
| #else | ||||
| #define bit_test_and_set(bitmap, bitno) arch_bit_test_and_set(bitmap, bitno) | ||||
| #endif /* ARCH_BIT_TEST_AND_SET */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline int bit_test_and_reset(void *bitmap, int bitno) | ||||
|  * @brief Get old value of bit with number @a bitno and clear @a bitno bit in the bitmap | ||||
|  * | ||||
|  * This function is similar to bit_clear() except it copies old bit value before | ||||
|  * setting it to 1 and return that value after needed bit was setted. | ||||
|  * @note The limit of @a bitmap = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bitno  - The number of bit to test and set | ||||
|  * @return Old value of bit with number @a bitno | ||||
|  */ | ||||
| #ifndef ARCH_BIT_TEST_AND_RESET | ||||
| static inline int bit_test_and_reset(void *bitmap, int bitno) | ||||
| { | ||||
|   int val = (*(unsigned long *)bitmap & (1 << bitno)); | ||||
|   *(unsigned long *)bitmap &= ~(1 << bitno); | ||||
| 
 | ||||
|   return val; | ||||
| } | ||||
| #else | ||||
| #define bit_test_and_reset(bitmap, bitno) arch_bit_test_and_reset(bitmap, bitno) | ||||
| #endif /* ARCH_BIT_TEST_AND_RESET */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline long bit_find_lsf(unsigned long word) | ||||
|  * Find first set least significant bit. | ||||
|  * | ||||
|  * @param word - Where to search | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| #ifndef ARCH_BIT_FIND_LSF | ||||
| static inline long bit_find_lsf(unsigned long word) | ||||
| { | ||||
|   long c = -1; | ||||
| 
 | ||||
|   for (; word; c++, word >>= 1) { | ||||
|     if ((word & 0x01)) { | ||||
|       c++; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return c; | ||||
| } | ||||
| #else | ||||
| #define bit_find_lsf(word) arch_bit_find_lsf(word) | ||||
| #endif /* ARCH_BIT_FIND_LSF */ | ||||
| 
 | ||||
| #ifndef ARCH_ZERO_BIT_FIND_LSF | ||||
| #define zero_bit_find_lsf(word) bit_find_lsf(~(word)) | ||||
| #else | ||||
| #define zero_bit_find_lsf(word) arch_zero_bit_find_lsf(word) | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline long bit_find_msf(unsigned long word) | ||||
|  * Find most significant set bit in the @a word. | ||||
|  * | ||||
|  * @param word - Where to search. | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| #ifndef ARCH_BIT_FIND_MSF | ||||
| static inline long bit_find_msf(unsigned long word) | ||||
| { | ||||
|   long c = -1; | ||||
| 
 | ||||
|   while (word) { | ||||
|     c++; | ||||
|     word >>= 1; | ||||
|   } | ||||
| 
 | ||||
|   return c; | ||||
| } | ||||
| #else | ||||
| #define bit_find_msf(word) arch_bit_find_msf(word) | ||||
| #endif /* ARCH_BIT_FIND_MSF */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline long bit_find_lsfz(unsigned long word) | ||||
|  * Find first zero least significant bit. | ||||
|  * | ||||
|  * @param word - Where to search | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| #ifndef ARCH_BIT_FIND_LSFZ | ||||
| static inline long bit_find_lsfz(unsigned long word) | ||||
| { | ||||
|   long c = -1; | ||||
| 
 | ||||
|   word = ~word; | ||||
|    | ||||
|   for (; word; c++, word >>= 1) { | ||||
|     if ((word & 0x01)) { | ||||
|       c++; | ||||
|       break; | ||||
|     }       | ||||
|   } | ||||
|    | ||||
|   return c; | ||||
| } | ||||
| #else | ||||
| #define bit_find_lsfz(word) arch_bit_find_lsfz(word) | ||||
| #endif /* ARCH_BIT_FIND_LSFZ */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline long bit_find_msfz(unsigned long word) | ||||
|  * Find most significant zero bit in the @a word. | ||||
|  * | ||||
|  * @param word - Where to search. | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| #ifndef ARCH_BIT_FIND_MSFZ | ||||
| static inline long bit_find_msfz(unsigned long word) | ||||
| { | ||||
|   long c = -1; | ||||
| 
 | ||||
|   word = ~word; | ||||
| 
 | ||||
|   while (word) { | ||||
|     c++; | ||||
|     word >>= 1; | ||||
|   } | ||||
| 
 | ||||
|   return c; | ||||
| } | ||||
| #else | ||||
| #define bit_find_msfz(word) arch_bit_find_msfz(word) | ||||
| #endif /* ARCH_BIT_FIND_MSFZ */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void bits_or(void *word, unsigned long flags) | ||||
|  * Executes logical OR with @a word and @a flags and writes result to @a word | ||||
|  * @note The limit of @a word = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param[out] word - A pointer to memory results will be written to | ||||
|  * @param flsgs - Flags that will be OR'ed with @a word | ||||
|  */ | ||||
| #ifndef ARCH_BITS_OR | ||||
| static inline void bits_or(void *word, unsigned long flags) | ||||
| { | ||||
|   *(unsigned long *)word |= flags; | ||||
| } | ||||
| #define bits_or(word, flags) panic("bits_or uniplemented") | ||||
| #else | ||||
| #define bits_or(word, flags) arch_bits_or(word, flags) | ||||
| #endif /* ARCH_BITS_OR */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void bits_and(void *word, unsigned long mask) | ||||
|  * Executes logical AND with @a word and @a mask and writes result to @a word. | ||||
|  * @note The limit of @a word = sizeof(unsigned long) | ||||
|  * | ||||
|  * @param[out] word - A pointer to memory results will be written to | ||||
|  * @param mask - A mask that will be AND'ed with @a word | ||||
|  */ | ||||
| #ifndef ARCH_BITS_AND | ||||
| static inline void bits_and(void *word, unsigned long mask) | ||||
| { | ||||
|   *(unsigned long *)word &= mask; | ||||
| } | ||||
| #else | ||||
| #define bits_and(word, mask) arch_bits_and(word, mask) | ||||
| #endif /* ARCH_BITS_AND */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize multiword bitmap | ||||
|  * | ||||
|  * @param map - pointer to the multiword bitmap | ||||
|  * @param bitno - memory size in bits to allocate | ||||
|  * | ||||
|  * @return 0 on success, -1 if can't allocate memory | ||||
|  */ | ||||
| int init_bitmap(bitmap_t *bitmap, int nbits); | ||||
| 
 | ||||
| /*
 | ||||
|  * Free memory taken by multiword bitmap | ||||
|  * | ||||
|  * @param bitmap - bitmap to free | ||||
|  */ | ||||
| void free_bitmap(bitmap_t *map); | ||||
| 
 | ||||
| /**
 | ||||
|  * Set bit number @a bit in the bitmap @a bitmap | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bit - Number of bit to set | ||||
|  */ | ||||
| void bit_set_multi(bitmap_t *bitmap, int bitno); | ||||
| 
 | ||||
| /**
 | ||||
|  * test bit of a multiword bitmap | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bitno  - The number of bit to test | ||||
|  * | ||||
|  * @return value of the specified bit | ||||
|  */ | ||||
| int bit_test_multi(bitmap_t *bitmap, int bitno); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Get old value of bit with number @a bitno and set @a bitno bit in the bitmap | ||||
|  * | ||||
|  * This function is similar to bit_set() except it copies old bit value before | ||||
|  * setting it to 1 and return that value after needed bit was setted. | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bitno  - The number of bit to test and set | ||||
|  * | ||||
|  * @return Old value of bit with number @a bitno or -1 if bitno is illegal | ||||
|  */ | ||||
| int bit_test_and_set_multi(bitmap_t *bitmap, int bitno); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Get old value of bit with number @a bitno and clear @a bitno bit in the bitmap | ||||
|  * | ||||
|  * This function is similar to bit_set() except it copies old bit value before | ||||
|  * setting it to 1 and return that value after needed bit was setted. | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bitno  - The number of bit to test and set | ||||
|  * | ||||
|  * @return Old value of bit with number @a bitno or -1 if bitno is illegal | ||||
|  */ | ||||
| int bit_test_and_reset_multi(bitmap_t *bitmap, int bitno); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Clear bit number @a bit in the bitmap @a bitmap | ||||
|  * | ||||
|  * @param bitmap - A pointer to the bitmap | ||||
|  * @param bit - Number of bit to clear | ||||
|  */ | ||||
| void bit_clear_multi(bitmap_t *bitmap, int bitno); | ||||
| 
 | ||||
| /*
 | ||||
|  * Set multiple bits in the multiword bitmap | ||||
|  * | ||||
|  * @param bitmap - pointer to the multimap bitmap | ||||
|  * @param start_bit - bit to set from | ||||
|  * int end_bit - bit to set upto | ||||
|  */ | ||||
| void bitrange_set_multi(bitmap_t *bitmap, int start_bit, int end_bit); | ||||
| 
 | ||||
| /*
 | ||||
|  * Clear multiple bits in the multiword bitmap | ||||
|  * | ||||
|  * @param bitmap - pointer to the multimap bitmap | ||||
|  * @param start_bit - bit to clear from | ||||
|  * int end_bit - bit to clear upto | ||||
|  */ | ||||
| void bitrange_clear_multi(bitmap_t *bitmap, int start_bit, int end_bit); | ||||
| 
 | ||||
| /**
 | ||||
|  * Find most significant set bit in multimap word which from the 0 bit | ||||
|  * upto @end_bit | ||||
|  * | ||||
|  * @param word - Where to search. | ||||
|  * @param end_bit - most bit to search upto | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| int bit_find_msf_multi(bitmap_t *bitmap, int mbit); | ||||
| 
 | ||||
| /**
 | ||||
|  * Find first set least significant bit. | ||||
|  * | ||||
|  * @param word - Where to search | ||||
|  * @param sbit - least bit to search from | ||||
|  * @return Found bit number on success, negative value on failure. | ||||
|  */ | ||||
| int bit_find_lsf_multi(bitmap_t *bitmap, int lbit); | ||||
| 
 | ||||
| #ifndef ARCH_BIT_TEST_AND_CLEAR | ||||
| static inline int bit_test_and_clear(void *bitmap, int bitno) | ||||
| { | ||||
|   int val = bit_test(bitmap, bitno); | ||||
|   bit_clear(bitmap, bitno); | ||||
|   return val; | ||||
| } | ||||
| #else | ||||
| #define bit_test_and_clear(bitmap, bitno) arch_bit_test_and_clear(bitmap, bitno) | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __BITWISE_H__ */ | ||||
| @ -1,42 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * cas.c | ||||
|  * Copyright (C) 2015 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __TDATA_CTRIE_H__ | ||||
| #define __TDATA_CTRIE_H__ | ||||
| 
 | ||||
| #include "../config.h" | ||||
| 
 | ||||
| /* flags */ | ||||
| #define CTRIE_FLAG_RO  (1 << 1) | ||||
| 
 | ||||
| /* structure Ctrie (flags is also underlying node type) */ | ||||
| typedef struct __ctrie_type { | ||||
|   int flags; | ||||
|   void **root; | ||||
| }__attribute__((packed)) ctrie_t; | ||||
| 
 | ||||
| /* structure SNode (key-value node) */ | ||||
| typedef struct __ctrie_snode { | ||||
| 	ct_key_t key; | ||||
| 	void *value; | ||||
| }__attribute__((packed)) ct_snode_t; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif /* __TDATA_CTRIE_H__ */ | ||||
| @ -1,130 +0,0 @@ | ||||
| /*
 | ||||
|  * This library is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2.1 of | ||||
|  * the License. | ||||
|  * | ||||
|  * This library 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * (c) Copyright 2006,2007,2008 MString Core Team <http://mstring.jarios.org>
 | ||||
|  * (c) Copyright 2009 Dan Kruchinin <dan.kruchinin@gmail.com> | ||||
|  * (c) Copyright 2009 Alfeiks Kaanoken <madtirra@jarios.org> (libc adaptation) | ||||
|  * (c) Copyright 2009 Dmitry Gromada <gromada@jarios.org> (locking added) | ||||
|  * (c) Copyright 2013 Alexander Vdolainen <vdo@askele.com> (verios changes to make it run on linux) | ||||
|  * | ||||
|  * (c) Copyright 2012 - 2013 Askele Oy <http://askele.com>
 | ||||
|  * | ||||
|  * Index allocator | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @file include/libdata/idx_allocator.h | ||||
|  * @brief Index allocator API and definitions | ||||
|  * | ||||
|  * Index allocator is a quite simple bitmaps based data | ||||
|  * structure allowing to allocate non-negative integers | ||||
|  * from an ordered continuous numbers set. | ||||
|  * It may be useful for dynamic allocation of pids, uids and | ||||
|  * other identifiers that must be unique. | ||||
|  * Any identifier from a given set may be allocated, deallocated and reserved | ||||
|  * (which prevents its allocation). | ||||
|  * Note, there is no any sence to use index allocator for relatively | ||||
|  * small(for example for sets containing less than 1024 items) identifier sets. | ||||
|  * Allocator uses *at least* BYTES_PER_ITEM + sizeof(ulong_t) bytes for its internal bitmaps. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __IDX_ALLOCATOR_H__ | ||||
| #define __IDX_ALLOCATOR_H__ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <pthread.h> | ||||
| 
 | ||||
| typedef unsigned long ulong_t; | ||||
| 
 | ||||
| #define BYTES_PER_ITEM 64 /**< Number of bytes per one entry of a second-level bitmap */ | ||||
| #define WORDS_PER_ITEM (BYTES_PER_ITEM / sizeof(ulong_t)) /**< Number of machine words(ulong_t) per second-level bitmap item */ | ||||
| #define IDX_INVAL    ~0UL /**< Invalid index value */ | ||||
| 
 | ||||
| #define ida_lock_init(lock)     pthread_mutex_init(lock, NULL) | ||||
| #define ida_lock_destroy(lock)  pthread_mutex_destroy(lock); | ||||
| #define ida_lock(a)             pthread_mutex_lock(&a->lock) | ||||
| #define ida_unlock(a)           pthread_mutex_unlock(&a->lock) | ||||
| #define ida_lockable(a)         (a->lck) | ||||
| 
 | ||||
| typedef pthread_mutex_t ida_lock_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * @struct idx_allocator_t | ||||
|  * @brief Index allocator structure | ||||
|  */ | ||||
| typedef struct __idx_allocator { | ||||
|   int size;            /**< Total number of words used for second-level bitmap */ | ||||
|   ulong_t max_id;      /**< Maximum index value(exclusive) */ | ||||
|   ulong_t *main_bmap;  /**< First-level(main) bitmap that splits second-level bitmap on several parts */ | ||||
|   ulong_t *ids_bmap;   /**< Second-level bitmap whose each bit corresponds to particular unique identifier */ | ||||
|   ida_lock_t lock; | ||||
|   int lck; | ||||
| } idx_allocator_t; | ||||
| 
 | ||||
| #define idx_allocator_initialized(ida)  (((idx_allocator_t*)(ida))->max_id) | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Initialize an index allocator. | ||||
|  * @param ida     - A pointer to particular index allocator | ||||
|  * @param idx_max - Maximum index value. | ||||
|  * @lockable - flag to indicate the allocator must support locking itself | ||||
|  */ | ||||
| int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Destroy index allocator. | ||||
|  * | ||||
|  * This function frees space used by allocator's internal | ||||
|  * bitmaps. After it is called, allocator can not be used. | ||||
|  * | ||||
|  * @param ida - A pointer to praticular index allocator. | ||||
|  */ | ||||
| void idx_allocator_destroy(idx_allocator_t *ida); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Allocate new index from an allocator's set. | ||||
|  * @param ida - A pointer to target index allocator. | ||||
|  * @return Valid index value on success, IDX_INVAL on error. | ||||
|  * @see IDX_INVAL | ||||
|  * @see idx_reserve | ||||
|  * @see idx_free | ||||
|  */ | ||||
| ulong_t idx_allocate(idx_allocator_t *ida); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Reserves particular index number. | ||||
|  * | ||||
|  * This action prevents named index number from | ||||
|  * allocation. Index allocator skips reserved indices until | ||||
|  * they are fried with idx_free | ||||
|  * | ||||
|  * @param ida - A pointer to particular index allocator. | ||||
|  * @param idx - Number of index to reserve. | ||||
|  * @see idx_free | ||||
|  * @see idx_allocate | ||||
|  */ | ||||
| void idx_reserve(idx_allocator_t *ida, ulong_t idx); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Free back index @a idx to named allocator @a ida. | ||||
|  * @param ida - Allocator index will be freed back to. | ||||
|  * @param idx - An index to free. | ||||
|  * @see idx_allocate | ||||
|  * @see idx_reserve | ||||
|  */ | ||||
| void idx_free(idx_allocator_t *ida, ulong_t idx); | ||||
| 
 | ||||
| #endif /* __IDX_ALLOCATOR_H__ */ | ||||
| @ -1,428 +0,0 @@ | ||||
| /*
 | ||||
|  * Typical data structures used. | ||||
|  * This library is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2.1 of | ||||
|  * the License. | ||||
|  * | ||||
|  * This library 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * (c) 2013-2014, 2015 Copyright Askele, inc. <http://askele.com>
 | ||||
|  * (c) 2013-2014, 2015 Copyright Askele Ingria, inc. <http://askele-ingria.com>
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __TDATA_LIST_H__ | ||||
| #define __TDATA_LIST_H__ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #define __MILESTONE ((unsigned long)0x123) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def MILESTONES_SEQ(num) ((void *)__MILESTONE##num) | ||||
|  * @brief Easy way to define next item in milestones sequence | ||||
|  * @pararm num - number of milestone in sequence | ||||
|  */ | ||||
| #define MILESTONES_SEQ(num) ((void *)(__MILESTONE + (num))) | ||||
| 
 | ||||
| /* milestones for list's next and prev pointers respectively */ | ||||
| #define MLST_LIST_NEXT MILESTONES_SEQ(1) | ||||
| #define MLST_LIST_PREV MILESTONES_SEQ(2) | ||||
| 
 | ||||
| #ifndef offsetof | ||||
| #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef container_of | ||||
| #define container_of(PTR, TYPE, MEMBER) \ | ||||
|   ((TYPE *)((char *)(PTR) - offsetof(TYPE, MEMBER))) | ||||
| #endif | ||||
| 
 | ||||
| /* init root node of non containerized double linked non cyclic list */ | ||||
| #define nclist_init_root(root)                  \ | ||||
| do {                                            \ | ||||
|   root->next = NULL;                            \ | ||||
|   root->prev = root;                            \ | ||||
| } while (0) | ||||
| 
 | ||||
| /* add to tail of non containerized double linked non cyclic list */ | ||||
| #define nclist_add2tail(root,node)              \ | ||||
| do {                                            \ | ||||
|   typeof(root) __tail = (root)->prev;           \ | ||||
|                                                 \ | ||||
|   __tail->next = node;                          \ | ||||
|   node->prev = __tail;                          \ | ||||
|   node->next = NULL;                            \ | ||||
|   (root)->prev = node;                          \ | ||||
| } while (0) | ||||
| 
 | ||||
| #define nclist_for_each(root, node)             \ | ||||
|   for (node = root; node != NULL; node = node->next) | ||||
| 
 | ||||
| /**
 | ||||
|  * @typedef struct __list_node list_node_t | ||||
|  * @struct __list_node | ||||
|  * @brief List node | ||||
|  */ | ||||
| typedef struct __list_node { | ||||
|   struct __list_node *next; | ||||
|   struct __list_node *prev; | ||||
| } list_node_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * @typedef struct __list_head list_head_t | ||||
|  * @struct __list_head | ||||
|  * @brief List head | ||||
|  * Actually list_head_t is the same as list_node_t, but | ||||
|  * they have different types though. That was done to prevent | ||||
|  * potentional errors(notice that list head is a stub, it's never | ||||
|  * tied with any real data and it's used only to determine where list | ||||
|  * starts and where it ends) | ||||
|  */ | ||||
| typedef struct __list_head { | ||||
|   list_node_t head; /**< Head element of the list */ | ||||
| } list_head_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * @def LIST_DEFINE(name) | ||||
|  * @brief Define and initialize list head with name @a name | ||||
|  * @param name - name of variable | ||||
|  */ | ||||
| #define LIST_DEFINE(name)                                       \ | ||||
|   list_head_t name = { .head = { &(name).head, &(name).head } } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_init_head(list_head_t *lst) | ||||
|  * @brief Initialize list head | ||||
|  * @param lst - a pointer to list head. | ||||
|  */ | ||||
| static inline void list_init_head(list_head_t *lst) | ||||
| { | ||||
|   lst->head.next = lst->head.prev = &lst->head; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_init_node(list_node_t *node) | ||||
|  * @brief Initialize list node | ||||
|  * @param node - a pointer to free(unattached from list) node. | ||||
|  */ | ||||
| static inline void list_init_node(list_node_t *node) | ||||
| { | ||||
|   node->next = MLST_LIST_NEXT; | ||||
|   node->prev = MLST_LIST_PREV; | ||||
| } | ||||
| 
 | ||||
| static inline bool list_node_next_isbound(list_node_t *node) | ||||
| { | ||||
|   return (node->next == MLST_LIST_NEXT); | ||||
| } | ||||
| 
 | ||||
| static inline bool list_node_prev_isbound(list_node_t *node) | ||||
| { | ||||
|   return (node->prev == MLST_LIST_PREV); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_entry(lst, nptr) | ||||
|  * @brief Get item that holds @a nptr node | ||||
|  * @param list - A pointer to the list | ||||
|  * @param nptr - A pointer to the node | ||||
|  * @return A pointer to the object given node contains | ||||
|  */ | ||||
| #define list_entry(node, type, member)                 \ | ||||
|   container_of(node, type, member) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_head(lst) | ||||
|  * @brief Get head of the list | ||||
|  * @param lst - a pointer to list_head_t | ||||
|  * @return A pointer to header list_node_t | ||||
|  */ | ||||
| #define list_head(lst)                          \ | ||||
|   (&(lst)->head) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_node_first(lst) | ||||
|  * @brief Get list's first node | ||||
|  * @param list - A pointer to the list_head_t | ||||
|  * @return A pointer to the list first node | ||||
|  */ | ||||
| #define list_node_first(lst)                    \ | ||||
|   ((lst)->head.next) | ||||
| 
 | ||||
| /**
 | ||||
|  * list_first_entry - get the first element from a list | ||||
|  * @lst: the list head to take the element from. | ||||
|  * @type:	the type of the struct this is embedded in. | ||||
|  * @member:	the name of the list_struct within the struct. | ||||
|  * | ||||
|  * Note, that list is expected to be not empty. | ||||
|  */ | ||||
| #define list_first_entry(lst, type, member) \ | ||||
| 	list_entry((lst)->head.next, type, member) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_node_last(lst) | ||||
|  * @brief Get list's last node | ||||
|  * @param list - A pointer to the list_head_t | ||||
|  * @return A pointer to the list last node | ||||
|  */ | ||||
| #define list_node_last(lst)                     \ | ||||
|   ((lst)->head.prev) | ||||
| 
 | ||||
| /**
 | ||||
|  * list_last_entry - get the last element from a list | ||||
|  * @lst: the list head to take the element from. | ||||
|  * @type:	the type of the struct this is embedded in. | ||||
|  * @member:	the name of the list_struct within the struct. | ||||
|  * | ||||
|  * Note, that list is expected to be not empty. | ||||
|  */ | ||||
| #define list_last_entry(lst, type, member)      \ | ||||
| 	list_entry((lst)->head.prev, type, member) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_add2head(lst, new) | ||||
|  * @brief Add a node @a new to the head of the list | ||||
|  * @param lst - A pointer to the list | ||||
|  * @param new - A pointer to the list node | ||||
|  */ | ||||
| #define list_add2head(lst, new)                 \ | ||||
|   list_add(list_node_first(lst), new) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_add2tail(lst, new) | ||||
|  * @brief Add a node @a new to the tail of the list | ||||
|  * @param lst - A pointer to the list | ||||
|  * @param new - A pointer to node to add | ||||
|  */ | ||||
| #define list_add2tail(lst, new)                         \ | ||||
|   list_add(list_head(lst), new) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_delfromhead(lst) | ||||
|  * @brief Remove first element of the list | ||||
|  * @param lst - A pointer to the list | ||||
|  */ | ||||
| #define list_delfromhead(lst)					\ | ||||
|   list_del(list_node_first(lst)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_delfromtail(lst) | ||||
|  * @brief Remove the last element of the list | ||||
|  * @param list - A pointer to the list | ||||
|  */ | ||||
| #define list_delfromtail(lst)					\ | ||||
|   list_del(list_node_last(lst)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_del(del) | ||||
|  * @brief Remove node @a del from the list | ||||
|  * @param del - A node to remove | ||||
|  */ | ||||
| #define list_del(del)                           \ | ||||
|   (list_del_range(del, del)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_add(before, new, after) | ||||
|  * @param after  - will be the next node after @a new | ||||
|  * @param new    - node to insert | ||||
|  */ | ||||
| #define list_add(after, new)                        \ | ||||
|   (list_add_range(new, new, (after)->prev, after)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_move2head(to, from) | ||||
|  * @brief Move all nodes from list @a from to the head of list @a to | ||||
|  * @param to   - destination list | ||||
|  * @param from - source list | ||||
|  */ | ||||
| #define list_move2head(to, from)                \ | ||||
|   (list_move(list_head(to), list_node_first(to), from)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_move2tail(to, from) | ||||
|  * @brief Move all nodes from list @a from to the tail of list @a to | ||||
|  * @param to   - destination list | ||||
|  * @param from - source list | ||||
|  */ | ||||
| #define list_move2tail(to, from)                \ | ||||
|   (list_move(list_node_last(to), list_head(to), from)) | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_for_each(lst, liter) | ||||
|  * @brief Iterate through each element of the list | ||||
|  * @param lst   - A pointer to list head | ||||
|  * @param liter - A pointer to list which will be used for iteration | ||||
|  */ | ||||
| #define list_for_each(lst, liter)                                       \ | ||||
|   for (liter = list_node_first(lst);                                    \ | ||||
|        (liter) != list_head(lst); (liter) = (liter)->next) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_for_each_safe(lst, liter, save) | ||||
|  * @brief Safe iteration through the list @a lst | ||||
|  * | ||||
|  * This iteration wouldn't be broken even if @a liter will be removed | ||||
|  * from the list | ||||
|  * | ||||
|  * @param lst   - A pointer to the list head | ||||
|  * @param liter - A pointer to list node which will be used for iteration | ||||
|  * @param save  - The same | ||||
|  */ | ||||
| #define list_for_each_safe(lst, liter, save)                            \ | ||||
|   for (liter = list_node_first(lst), save = (liter)->next;              \ | ||||
|        (liter) != list_head(lst); (liter) = (save),                     \ | ||||
|          (save) = (liter)->next) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_for_each_entry(lst, iter, member) | ||||
|  * @brief Iterate through each list node member | ||||
|  * @param lst    - a pointer list head | ||||
|  * @param iter   - a pointer to list entry using as iterator | ||||
|  * @param member - name of list node member in the parent structure | ||||
|  */ | ||||
| #define list_for_each_entry(lst, iter, member)                         \ | ||||
|   for (iter = list_entry(list_node_first(lst), typeof(*iter), member); \ | ||||
|        &iter->member != list_head(lst);                                \ | ||||
|        iter = list_entry(iter->member.next, typeof(*iter), member)) | ||||
| 
 | ||||
| /**
 | ||||
|  * @def list_for_each_entry(lst, iter, member) | ||||
|  * @brief Iterate through each list node member and calls specified function with argument | ||||
|  *        pointing to a list entry | ||||
|  * | ||||
|  * @param lst    - a pointer list head | ||||
|  * @param iter   - a pointer to list entry using as iterator | ||||
|  * @param member - name of list node member in the parent structure | ||||
|  * @param fn     - function doing some actins against each entry of the list | ||||
|  */ | ||||
| #define list_do_for_each_entry(lst, type, member, fn)                   \ | ||||
| {                                                                       \ | ||||
|   type *t;                                                              \ | ||||
|   list_node_t *node, *save;                                             \ | ||||
|                                                                         \ | ||||
|   list_for_each_safe(lst, node, save) {                                 \ | ||||
|     t = container_of(node, type, member);                               \ | ||||
|     fn(t);                                                              \ | ||||
|   }                                                                     \ | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline int list_is_empty(list_t *list) | ||||
|  * @brief Determines if list @a list is empty | ||||
|  * @param list - A pointer to list to test | ||||
|  * @return True if list is empty, false otherwise | ||||
|  */ | ||||
| static inline int list_is_empty(list_head_t *list) | ||||
| { | ||||
|   return (list_node_first(list) == list_head(list)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_add_range(list_node_t *first, list_node_t *last, | ||||
|  *                                list_node_t *prev, list_node_t *next) | ||||
|  * @brief Insert a range of nodes from @a frist to @a last after @a prev and before @a last | ||||
|  * @param first - first node of range | ||||
|  * @param last  - last node of range | ||||
|  * @param prev  - after this node a range will be inserted | ||||
|  * @param next  - before this node a range will be inserted | ||||
|  */ | ||||
| static inline void list_add_range(list_node_t *first, list_node_t *last, | ||||
|                                   list_node_t *prev, list_node_t *next) | ||||
| { | ||||
|   next->prev = last; | ||||
|   last->next = next; | ||||
|   prev->next = first; | ||||
|   first->prev = prev; | ||||
| } | ||||
| 
 | ||||
| /* for internal usage */ | ||||
| static inline void __list_del_range(list_node_t *first, list_node_t *last) | ||||
| { | ||||
|   first->prev->next = last->next; | ||||
|   last->next->prev = first->prev; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline list_del_range(list_node_t *first, list_node_t *last) | ||||
|  * @brief Delete nodes from @a first to @a last from list. | ||||
|  * @param fist - first node to delete | ||||
|  * @param last - last node to delete | ||||
|  */ | ||||
| static inline void list_del_range(list_node_t *first, list_node_t *last) | ||||
| { | ||||
|   __list_del_range(first, last); | ||||
|   first->prev = MLST_LIST_PREV; | ||||
|   last->next = MLST_LIST_NEXT; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_cut_sublist(list_node_t *first, list_node_t *last) | ||||
|  * @brief Cut a "sublist" started from @a first and ended with @a last | ||||
|  * | ||||
|  * A @e "sublist" is similar to ordinary list except it hasn't a head. | ||||
|  * In other words it's a cyclic list in which all nodes are equitable. | ||||
|  * | ||||
|  * @param first - From this node sublist will be cutted | ||||
|  * @param last  - The last node in the cutted sequence | ||||
|  */ | ||||
| static inline void list_cut_sublist(list_node_t *first, list_node_t *last) | ||||
| { | ||||
|   __list_del_range(first, last); | ||||
|   first->prev = last; | ||||
|   last->next = first; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_cut_head(list_head_t *head) | ||||
|  * @brief Cut a head from the list and make a "sublist" | ||||
|  * @param head - List's head that will be cutted. | ||||
|  * @see list_cut_sublist | ||||
|  * @see list_set_head | ||||
|  */ | ||||
| static inline void list_cut_head(list_head_t *head) | ||||
| { | ||||
|   list_cut_sublist(list_node_first(head), list_node_last(head)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_cut_head(list_head_t *head) | ||||
|  * @brief Attach a head to the sublist @a cyclist | ||||
|  * @param new_head - A head that will be attached | ||||
|  * @param cyclist  - "sublist" | ||||
|  * @see list_cut_sublist | ||||
|  * @see list_set_head | ||||
|  */ | ||||
| static inline void list_set_head(list_head_t *new_head, list_node_t *cyclist) | ||||
| { | ||||
|   list_add_range(cyclist, cyclist->prev, | ||||
|                  list_node_first(new_head), list_node_last(new_head)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @fn static inline void list_move(list_node_t *prev, list_node_t *next, list_head_t *from) | ||||
|  * @brief Insert nodes of list @a from after @a prev and before @a next | ||||
|  * @param prev - a node after which nodes of @a from will be inserted | ||||
|  * @param next - a node before which nodes of @a from will be inserted | ||||
|  */ | ||||
| static inline void list_move(list_node_t *prev, list_node_t *next, list_head_t *from) | ||||
| { | ||||
|   list_add_range(list_node_first(from), list_node_last(from), | ||||
|                  prev, next); | ||||
|   list_init_head(from); | ||||
| } | ||||
| 
 | ||||
| #endif /* __TDATA_LIST_H__ */ | ||||
| 
 | ||||
| @ -1,45 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * macro.h | ||||
|  * Copyright (C) 2006-2013 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __MACRO_H__ | ||||
| #define __MACRO_H__ | ||||
| 
 | ||||
| /*this macros just for better source code look and feel*/ | ||||
| 
 | ||||
| #define left usrtc_left | ||||
| #define right usrtc_right | ||||
| #define parent usrtc_parent | ||||
| #define next usrtc_right | ||||
| #define prev usrtc_left | ||||
| #define data usrtc_data | ||||
| #define key usrtc_node_key | ||||
| #define rb_color usrtc_rb_color | ||||
| #define impl_specific usrtc_impldata | ||||
| 
 | ||||
| #define futable usrtc_futable | ||||
| #define nodecount usrtc_nodecount | ||||
| #define maxcount usrtc_maxcount | ||||
| #define dupes_allowed usrtc_dupes_allowed | ||||
| #define sentinel usrtc_sentinel | ||||
| #define compare usrtc_compare | ||||
| #define node_alloc usrtc_node_alloc | ||||
| #define node_free usrtc_node_free | ||||
| #define context usrtc_context | ||||
| 
 | ||||
| #endif /*__MACRO_H__*/ | ||||
| @ -1,47 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * tree.h | ||||
|  * Copyright (C) 2006-2013 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __TREE_H__ | ||||
| #define __TREE_H__ | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| 
 | ||||
| #define tree_root_priv(T) ((T)->sentinel.left) | ||||
| #define tree_null_priv(L) (&(L)->sentinel) | ||||
| #define TREE_DEPTH_MAX 64 | ||||
| 
 | ||||
| /*tree functions*/ | ||||
| void usrtc_tree_init(usrtc_t *us); | ||||
| void usrtc_tree_insert(usrtc_t *us, usrtc_node_t *node, const void *key); | ||||
| void usrtc_tree_delete(usrtc_t *us, usrtc_node_t *node, usrtc_node_t **pswap, | ||||
| 											 usrtc_node_t **pchild); | ||||
| usrtc_node_t *usrtc_tree_lookup(usrtc_t *us, const void *key); | ||||
| usrtc_node_t *usrtc_tree_lower_bound(usrtc_t *us, const void *key); | ||||
| usrtc_node_t *usrtc_tree_upper_bound(usrtc_t *us, const void *key); | ||||
| usrtc_node_t *usrtc_tree_first(usrtc_t *us); | ||||
| usrtc_node_t *usrtc_tree_last(usrtc_t *us); | ||||
| usrtc_node_t *usrtc_tree_next(usrtc_t *us, usrtc_node_t *curr); | ||||
| usrtc_node_t *usrtc_tree_prev(usrtc_t *us, usrtc_node_t *curr); | ||||
| void usrtc_tree_convert_to_list(usrtc_t *us); | ||||
| void usrtc_tree_convert_from_list(usrtc_t *us); | ||||
| void usrtc_tree_rotate_left(usrtc_node_t *child, usrtc_node_t *parent); | ||||
| void usrtc_tree_rotate_right(usrtc_node_t *child, usrtc_node_t *parent); | ||||
| 
 | ||||
| 
 | ||||
| #endif /*__TREE_H__*/ | ||||
| @ -1,145 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * usrtc.h | ||||
|  * Copyright (C) 2006-2013 Askele inc. <http://askele.com>
 | ||||
|  * Copyright (C) 2015-2016 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __USRTC_H__ | ||||
| #define __USRTC_H__ | ||||
| 
 | ||||
| #define USRTC_COUNT_T_MAX  ((1 << (sizeof(unsigned long)*(sizeof(char) << 1)))-1) | ||||
| 
 | ||||
| /*count and some misc typedefs*/ | ||||
| typedef unsigned long usrtc_count_t; | ||||
| typedef unsigned int usrtc_impl_id_t; | ||||
| 
 | ||||
| /* implementations ids,
 | ||||
|  * if you want to add some | ||||
|  * add the id here, don't forget to do it. | ||||
|  */ | ||||
| #define USRTC_LIST      0 | ||||
| #define USRTC_BST       1 | ||||
| #define USRTC_REDBLACK  2 | ||||
| #define USRTC_SPLAY     3 | ||||
| #define USRTC_AVL       4 | ||||
| 
 | ||||
| typedef enum { | ||||
|   usrtc_lst, | ||||
|   usrtc_bst, | ||||
|   usrtc_other | ||||
| } usrtc_impltype_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|   usrtc_red, | ||||
|   usrtc_black | ||||
| } usrtc_rb_color_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|   usrtc_balanced, | ||||
|   usrtc_leftheavy, | ||||
|   usrtc_rightheavy | ||||
| } usrtc_avl_balance_t; | ||||
| 
 | ||||
| /* used for the specific implementation features */ | ||||
| typedef union { | ||||
|   int usrtc_dummy; | ||||
|   usrtc_rb_color_t usrtc_rb_color; | ||||
|   usrtc_avl_balance_t usrtc_avl_balance; | ||||
| } usrtc_impldata_t; | ||||
| 
 | ||||
| /* universal node */ | ||||
| typedef struct __usrtc_node_t { | ||||
|   struct __usrtc_node_t *usrtc_left; | ||||
|   struct __usrtc_node_t *usrtc_right; | ||||
|   struct __usrtc_node_t *usrtc_parent; | ||||
|   void *usrtc_data; | ||||
|   const void *usrtc_node_key; | ||||
|   usrtc_impldata_t usrtc_impldata; | ||||
| } usrtc_node_t; | ||||
| 
 | ||||
| typedef long (*usrtc_compare_t)(const void*, const void*); | ||||
| typedef usrtc_node_t *(*usrtc_node_alloc_t)(void *); | ||||
| typedef void (*usrtc_node_free_t)(void *, usrtc_node_t *); | ||||
| 
 | ||||
| typedef struct __usrtc_t { | ||||
| 	struct __usrtc_functions_t *usrtc_futable; | ||||
| 	usrtc_count_t usrtc_nodecount; | ||||
| 	usrtc_count_t usrtc_maxcount; | ||||
| 	int usrtc_dupes_allowed; | ||||
| 	usrtc_node_t usrtc_sentinel; | ||||
| 	usrtc_compare_t usrtc_compare; | ||||
| 	usrtc_node_alloc_t usrtc_node_alloc; | ||||
| 	usrtc_node_free_t usrtc_node_free; | ||||
| 	void *usrtc_context; | ||||
| } usrtc_t; | ||||
| 
 | ||||
| typedef struct __usrtc_functions_t { | ||||
| 	void (*usrtc_init)(usrtc_t *); | ||||
| 	void (*usrtc_insert)(usrtc_t *, usrtc_node_t *, const void *); | ||||
| 	void (*usrtc_delete)(usrtc_t *, usrtc_node_t *); | ||||
| 	usrtc_node_t *(*usrtc_lookup)(usrtc_t *, const void *); | ||||
| 	usrtc_node_t *(*usrtc_lower_bound)(usrtc_t *, const void *); | ||||
| 	usrtc_node_t *(*usrtc_upper_bound)(usrtc_t *, const void *); | ||||
| 	usrtc_node_t *(*usrtc_first)(usrtc_t *); | ||||
| 	usrtc_node_t *(*usrtc_last)(usrtc_t *); | ||||
| 	usrtc_node_t *(*usrtc_next)(usrtc_t *, usrtc_node_t *); | ||||
| 	usrtc_node_t *(*usrtc_prev)(usrtc_t *, usrtc_node_t *); | ||||
| 	void (*usrtc_convert_to_list)(usrtc_t *); | ||||
| 	void (*usrtc_convert_from_list)(usrtc_t *); | ||||
| 	usrtc_impltype_t usrtc_type; | ||||
| } usrtc_functions_t; | ||||
| 
 | ||||
| /*basic rtc functions*/ | ||||
| void usrtc_init(usrtc_t *us,int impl,usrtc_count_t maxcount,usrtc_compare_t compare); | ||||
| usrtc_t *usrtc_create(int impl,usrtc_count_t maxcount,usrtc_compare_t compare); | ||||
| void usrtc_destroy(usrtc_t *us); | ||||
| 
 | ||||
| void usrtc_convert_to(usrtc_t *us,int impl); | ||||
| 
 | ||||
| usrtc_count_t usrtc_count(usrtc_t *us); | ||||
| int usrtc_isempty(usrtc_t *us); | ||||
| int usrtc_isfull(usrtc_t *us); | ||||
| 
 | ||||
| int usrtc_alloc_insert(usrtc_t *us,const void *key,void *data); | ||||
| void usrtc_delete_free(usrtc_t *us,usrtc_node_t *node); | ||||
| 
 | ||||
| void usrtc_set_allocator(usrtc_t *us,usrtc_node_alloc_t alloc,usrtc_node_free_t n_free,void *context); | ||||
| void usrtc_allow_dupes(usrtc_t *ud); | ||||
| 
 | ||||
| /*basic node functions*/ | ||||
| void usrtc_node_init(usrtc_node_t *node,void *data); | ||||
| usrtc_node_t *usrtc_node_create(void *data); | ||||
| void usrtc_node_destroy(usrtc_node_t *node); | ||||
| void *usrtc_node_getdata(usrtc_node_t *node); | ||||
| void usrtc_node_setdata(usrtc_node_t *node,void *data); | ||||
| const void *usrtc_node_getkey(usrtc_node_t *node); | ||||
| 
 | ||||
| /*rtc wrappers for the specific data structure functions*/ | ||||
| void usrtc_insert(usrtc_t *us,usrtc_node_t *node,const void *key); | ||||
| void usrtc_delete(usrtc_t *us,usrtc_node_t *node); | ||||
| 
 | ||||
| usrtc_node_t *usrtc_lookup(usrtc_t *us,const void *key); | ||||
| 
 | ||||
| usrtc_node_t *usrtc_lower_bound(usrtc_t *us,const void *key); | ||||
| usrtc_node_t *usrtc_upper_bound(usrtc_t *us,const void *key); | ||||
| 
 | ||||
| usrtc_node_t *usrtc_first(usrtc_t *us); | ||||
| usrtc_node_t *usrtc_last(usrtc_t *us); | ||||
| usrtc_node_t *usrtc_next(usrtc_t *us,usrtc_node_t *node); | ||||
| usrtc_node_t *usrtc_prev(usrtc_t *us,usrtc_node_t *node); | ||||
| 
 | ||||
| #endif /*__USRTC_H__*/ | ||||
| @ -1,38 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in
 | ||||
| 
 | ||||
| AM_CPPFLAGS = \
 | ||||
| 	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
 | ||||
| 	-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
 | ||||
| 	-DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \
 | ||||
| 	-I../include | ||||
| 
 | ||||
| #if WIN32
 | ||||
| #AM_CPPFLAGS + = -I../../include
 | ||||
| #endif
 | ||||
| 
 | ||||
| AM_CFLAGS =\
 | ||||
| 	 -Wall\
 | ||||
| 	 -g | ||||
| 
 | ||||
| lib_LTLIBRARIES = libsexpr.la | ||||
| 
 | ||||
| 
 | ||||
| libsexpr_la_SOURCES = \
 | ||||
| 	cstring.c event_temp.c faststack.c io.c \
 | ||||
| 	parser.c sexp.c sexp_memory.c sexp_ops.c sexp_vis.c | ||||
| 
 | ||||
| libsexpr_la_LDFLAGS =  | ||||
| 
 | ||||
| libsexpr_la_LIBADD =  | ||||
| 
 | ||||
| ##include_HEADERS = \
 | ||||
| ##	../include/sexpr/cstring.h ../include/sexpr/faststack.h ../include/sexpr/sexp_errors.h \
 | ||||
| ##	../include/sexpr/sexp.h ../include/sexpr/sexp_memory.h ../include/sexpr/sexp_ops.h \
 | ||||
| ##	../include/sexpr/sexp_vis.h
 | ||||
| 
 | ||||
| pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = libsexpr.pc | ||||
| 
 | ||||
| EXTRA_DIST = \
 | ||||
| 	libsexpr.pc.in | ||||
| 
 | ||||
| @ -1,3 +0,0 @@ | ||||
| 1.3.1 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										220
									
								
								sexpr/cstring.c
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								sexpr/cstring.c
									
									
									
									
									
								
							| @ -1,220 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| /**
 | ||||
|  * Implementation of stuff in cstring.h to make ron happy  | ||||
|  */ | ||||
| #include <sexpr/cstring.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sexpr/sexp_memory.h> | ||||
| #include <sexpr/sexp.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * growth size for cstrings -- default is 8k.  use sgrowsize() to adjust.  | ||||
|  */ | ||||
| static size_t cstring_growsize = 8192; | ||||
| 
 | ||||
| void sgrowsize(size_t s) { | ||||
|   if (s < 1)  | ||||
|     return; | ||||
| 
 | ||||
|   cstring_growsize = s; | ||||
| } | ||||
| 
 | ||||
| CSTRING *snew(size_t s) { | ||||
|   CSTRING *cs; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   cs = (CSTRING *)sexp_malloc(sizeof(CSTRING)); | ||||
| #else | ||||
|   cs = sexp_malloc(sizeof(CSTRING)); | ||||
| #endif | ||||
|   if (cs == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   cs->len = s; | ||||
|   cs->curlen = 0; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   cs->base = (char *)sexp_calloc(sizeof(char),s); | ||||
| #else | ||||
|   cs->base = sexp_calloc(sizeof(char),s); | ||||
| #endif | ||||
|   if (cs->base == NULL) { | ||||
|     sexp_free(cs,sizeof(CSTRING)); | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   return cs; | ||||
| } | ||||
| 
 | ||||
| CSTRING *sadd(CSTRING *s, char *a) { | ||||
|   size_t alen; | ||||
|   char *newbase; | ||||
| 
 | ||||
|   /* no string, so bail */ | ||||
|   if (s == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* nothing to add, return s */ | ||||
|   if (a  == NULL) { | ||||
|     return s; | ||||
|   } | ||||
| 
 | ||||
|   alen = strlen(a); | ||||
| 
 | ||||
|   if (s->curlen + alen >= s->len) { | ||||
| #ifdef __cplusplus | ||||
|     newbase = (char *)sexp_realloc(s->base, | ||||
|                                    s->len+cstring_growsize+alen, | ||||
|                                    s->len); | ||||
| #else | ||||
|     newbase = sexp_realloc(s->base, | ||||
|                            s->len+cstring_growsize+alen, | ||||
|                            s->len); | ||||
| #endif | ||||
|      | ||||
|     /* do NOT destroy s anymore.  if realloc fails, the original data is
 | ||||
|        still valid, so just report the error to sexp_errno and return NULL. | ||||
|     */ | ||||
|     if (newbase == NULL) { | ||||
|       sexp_errno = SEXP_ERR_MEMORY;       | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     s->len += cstring_growsize + alen; | ||||
|     s->base = newbase; | ||||
|   } | ||||
| 
 | ||||
|   memcpy(&s->base[s->curlen],a,alen); | ||||
|   s->curlen += alen; | ||||
|   s->base[s->curlen] = 0; | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| CSTRING *saddch(CSTRING *s, char a) { | ||||
|   char *newbase; | ||||
| 
 | ||||
|   if (s == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   if (s->curlen + 1 >= s->len) { | ||||
| #ifdef __cplusplus | ||||
|     newbase = (char *)sexp_realloc(s->base, | ||||
|                                    s->len+cstring_growsize+1, | ||||
|                                    s->len); | ||||
| #else | ||||
|     newbase = sexp_realloc(s->base, | ||||
|                            s->len+cstring_growsize+1, | ||||
|                            s->len); | ||||
| #endif | ||||
| 
 | ||||
|     /* do NOT destroy s anymore.  if realloc fails, the original data is
 | ||||
|        still valid, so just report the error to sexp_errno and return NULL. | ||||
|     */ | ||||
|     if (newbase == NULL) { | ||||
|       sexp_errno = SEXP_ERR_MEMORY;       | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     s->len += cstring_growsize+1; | ||||
|     s->base = newbase; | ||||
|   } | ||||
| 
 | ||||
|   s->base[s->curlen] = a; | ||||
|   s->curlen++; | ||||
|   s->base[s->curlen] = 0; | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| CSTRING *strim(CSTRING *s) { | ||||
|   char *newbase; | ||||
| 
 | ||||
|   if (s == NULL) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* no trimming necessary? */ | ||||
|   if (s->len == s->curlen+1) { | ||||
|     return s; | ||||
|   } | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   newbase = (char *)sexp_realloc(s->base, | ||||
|                                  s->curlen+1, | ||||
|                                  s->len); | ||||
| #else | ||||
|   newbase = sexp_realloc(s->base, | ||||
|                          s->curlen+1, | ||||
|                          s->len); | ||||
| #endif | ||||
| 
 | ||||
|   /* do NOT destroy s anymore.  if realloc fails, the original data is
 | ||||
|      still valid, so just report the error to sexp_errno and return NULL. | ||||
|   */ | ||||
|   if (newbase == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY;       | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   s->len = s->curlen+1; | ||||
|   s->base = newbase; | ||||
| 
 | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| char *toCharPtr(CSTRING *s) { | ||||
|   if (s == NULL) return NULL; | ||||
|   return s->base; | ||||
| } | ||||
| 
 | ||||
| void sempty(CSTRING *s) { | ||||
|   if (s == NULL) return; | ||||
|   s->curlen = 0; | ||||
| } | ||||
| 
 | ||||
| void sdestroy(CSTRING *s) { | ||||
|   if (s == NULL) return; | ||||
|   sexp_free(s->base,s->len); | ||||
|   sexp_free(s,sizeof(CSTRING)); | ||||
| } | ||||
| @ -1,891 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <assert.h> | ||||
| #include <sexpr/sexp.h> | ||||
| 
 | ||||
| static size_t sexp_val_start_size = 256; | ||||
| static size_t sexp_val_grow_size  = 64; | ||||
| 
 | ||||
| /*************************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * event parser : based on cparse_sexp from v1.91 of this file.  separate out | ||||
|  * in the event that the parser mode is PARSER_EVENTS_ONLY. | ||||
|  */ | ||||
| pcont_t * | ||||
| eparse_sexp (char *str, size_t len, pcont_t *lc) | ||||
| { | ||||
|   char *t, *s; | ||||
|   register size_t       binexpected = 0; | ||||
|   register size_t       binread = 0;  | ||||
|   register parsermode_t mode = PARSER_NORMAL; | ||||
|   register size_t       val_allocated = 0; | ||||
|   register unsigned int squoted = 0; | ||||
|   register size_t       val_used = 0; | ||||
|   register unsigned int state = 1; | ||||
|   register unsigned int depth = 0; | ||||
|   register unsigned int qdepth = 0; | ||||
|   register unsigned int elts = 0; | ||||
|   register unsigned int esc = 0; | ||||
|   pcont_t *cc; | ||||
|   char *val, *vcur, *bindata = NULL; | ||||
|   faststack_t *stack; | ||||
|   char *bufEnd; | ||||
|   int keepgoing = 1; | ||||
|   parser_event_handlers_t *event_handlers = NULL; | ||||
| 
 | ||||
|   /* make sure non-null string */ | ||||
|   if (str == NULL) { | ||||
|     lc->error = SEXP_ERR_NULLSTRING; | ||||
|     return lc; | ||||
|   } | ||||
|    | ||||
|   /* first, if we have a non null continuation passed in, restore state. */ | ||||
|   if (lc != NULL) { | ||||
|     cc = lc; | ||||
|     binexpected = cc->binexpected; | ||||
|     binread = cc->binread; | ||||
|     bindata = cc->bindata; | ||||
|     val_used = cc->val_used; | ||||
|     val_allocated = cc->val_allocated; | ||||
|     squoted = cc->squoted; | ||||
|     val = cc->val; | ||||
|     vcur = cc->vcur; | ||||
|     state = cc->state; | ||||
|     depth = cc->depth; | ||||
|     qdepth = cc->qdepth; | ||||
|     stack = cc->stack; | ||||
|     esc = cc->esc; | ||||
|     mode = cc->mode; | ||||
|     event_handlers = cc->event_handlers; | ||||
|     s = str; | ||||
|     if (cc->lastPos != NULL) | ||||
|       t = cc->lastPos; | ||||
|     else { | ||||
|       t = s; | ||||
|       cc->sbuffer = str; | ||||
|     } | ||||
|   } else { | ||||
|     /* new continuation... */ | ||||
| #ifdef __cplusplus | ||||
|     cc = (pcont_t *)sexp_malloc(sizeof(pcont_t)); | ||||
| #else | ||||
|     cc = sexp_malloc(sizeof(pcont_t)); | ||||
| #endif | ||||
|     assert(cc != NULL); | ||||
|      | ||||
|     cc->mode = mode; | ||||
| 
 | ||||
|     /* allocate atom buffer */ | ||||
| #ifdef __cplusplus | ||||
|     cc->val = val = (char *)sexp_malloc(sizeof(char)*sexp_val_start_size); | ||||
| #else | ||||
|     cc->val = val = sexp_malloc(sizeof(char)*sexp_val_start_size); | ||||
| #endif | ||||
|     assert(val != NULL); | ||||
|      | ||||
|     cc->val_used = val_used = 0; | ||||
|     cc->val_allocated = val_allocated = sexp_val_start_size; | ||||
| 
 | ||||
|     vcur = val; | ||||
|      | ||||
|     /* allocate stack */ | ||||
|     cc->stack = stack = make_stack(); | ||||
|     cc->bindata = NULL; | ||||
|     cc->binread = cc->binexpected = 0; | ||||
| 
 | ||||
|     /* event handlers are null */ | ||||
|     cc->event_handlers = NULL; | ||||
| 
 | ||||
|     /* t is temp pointer into s for current position */ | ||||
|     s = str; | ||||
|     t = s; | ||||
|     cc->sbuffer = str; | ||||
|   } | ||||
|    | ||||
|   bufEnd = cc->sbuffer+len; | ||||
| 
 | ||||
|   /* guard for loop - see end of loop for info.  Put it out here in the
 | ||||
|      event that we're restoring state from a continuation and need to | ||||
|      check before we start up. */ | ||||
|   if (state != 15 && t[0] == '\0') keepgoing = 0; | ||||
| 
 | ||||
|   /*==================*/ | ||||
|   /* main parser loop */ | ||||
|   /*==================*/ | ||||
|   while (keepgoing == 1 && t != bufEnd) | ||||
|     { | ||||
| 
 | ||||
|       /* based on the current state in the FSM, do something */ | ||||
|       switch (state) | ||||
| 	{ | ||||
| 	case 1: | ||||
| 	  switch (t[0]) | ||||
| 	    { | ||||
| 	      /* space,tab,CR,LF considered white space */ | ||||
| 	    case '\n': | ||||
| 	    case ' ': | ||||
| 	    case '\t': | ||||
| 	    case '\r':              | ||||
| 	      t++; | ||||
| 	      break; | ||||
|               /* semicolon starts a comment that extends until a \n is
 | ||||
|                  encountered. */ | ||||
|             case ';': | ||||
|               t++; | ||||
|               state = 11; | ||||
|               break; | ||||
| 	      /* enter state 2 for open paren */ | ||||
| 	    case '(': | ||||
| 	      state = 2; | ||||
| 	      t++; | ||||
|               if (event_handlers != NULL &&  | ||||
|                   event_handlers->start_sexpr != NULL) | ||||
|                 event_handlers->start_sexpr(); | ||||
| 	      break; | ||||
| 	      /* enter state 3 for close paren */ | ||||
| 	    case ')': | ||||
| 	      state = 3; | ||||
| 	      break;               | ||||
| 	      /* begin quoted string - enter state 5 */ | ||||
| 	    case '\"': | ||||
| 	      state = 5; | ||||
| 	      /* set cur pointer to beginning of val buffer */ | ||||
| 	      vcur = val; | ||||
| 	      t++; | ||||
| 	      break; | ||||
| 	      /* single quote - enter state 7 */ | ||||
| 	    case '\'': | ||||
| 	      state = 7; | ||||
| 	      t++; | ||||
| 	      break; | ||||
| 	      /* other characters are assumed to be atom parts */ | ||||
| 	    default: | ||||
| 	      /* set cur pointer to beginning of val buffer */ | ||||
| 	      vcur = val; | ||||
| 
 | ||||
|               /** NOTE: the following code originally required a transition
 | ||||
|                   to state 4 before processing the first atom character -- | ||||
|                   this required two iterations for the first character | ||||
|                   of each atom.  merging this into here allows us to process | ||||
|                   what we already know to be a valid atom character before | ||||
|                   entering state 4. **/ | ||||
| 	      vcur[0] = t[0]; | ||||
| 	      if (t[0] == '\\') esc = 1; | ||||
| 	      else esc = 0; | ||||
|               val_used++; | ||||
| 
 | ||||
|               if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|                 val = (char *)sexp_realloc(val, | ||||
|                                            val_allocated+sexp_val_grow_size, | ||||
|                                            val_allocated); | ||||
| #else | ||||
|                 val = sexp_realloc(val, | ||||
|                                    val_allocated+sexp_val_grow_size, | ||||
|                                    val_allocated); | ||||
| #endif | ||||
|                 assert(val != NULL); | ||||
|                 vcur = val + val_used; | ||||
|                 val_allocated += sexp_val_grow_size; | ||||
|               } else vcur++; | ||||
| 
 | ||||
|               /* if the atom starts with # and we're in inline
 | ||||
|                  binary mode, we need to go to state 12 to start | ||||
|                  checking for the #b# prefix.  otherwise, | ||||
|                  if it's not a # or we're just in normal mode, | ||||
|                  proceed to state 4 as usual. */ | ||||
|               if (t[0] == '#' && mode == PARSER_INLINE_BINARY) { | ||||
|                 state = 12; | ||||
|               } else { | ||||
|                 state = 4; | ||||
|               } | ||||
| 
 | ||||
|               t++; | ||||
| 	      break; | ||||
| 	    } | ||||
| 	  break; | ||||
| 	case 2: | ||||
| 	  /* open paren */ | ||||
| 	  depth++; | ||||
| 
 | ||||
| 	  elts++; | ||||
| 	   | ||||
| 	  if (stack->height < 1) | ||||
|             stack->height++; | ||||
| 
 | ||||
|           stack->height++; | ||||
| 	   | ||||
| 	  state = 1; | ||||
| 	  break; | ||||
| 	case 3: | ||||
| 	  /** close paren **/ | ||||
| 
 | ||||
|           /* check for close parens that were never opened. */ | ||||
|           if (depth == 0) { | ||||
|             cc->bindata = bindata; | ||||
|             cc->binread = binread; | ||||
|             cc->binexpected = binexpected; | ||||
| 	    cc->val = val; | ||||
|             cc->mode = mode; | ||||
|             cc->val_used = val_used; | ||||
|             cc->val_allocated = val_allocated; | ||||
| 	    cc->vcur = vcur; | ||||
| 	    cc->lastPos = t; | ||||
| 	    cc->depth = depth; | ||||
| 	    cc->qdepth = qdepth; | ||||
| 	    cc->state = 1; | ||||
| 	    cc->stack = stack; | ||||
| 	    cc->esc = 0; | ||||
| 	    cc->last_sexp = NULL; | ||||
|             cc->error = SEXP_ERR_BADFORM; | ||||
|             cc->event_handlers = event_handlers; | ||||
| 
 | ||||
| 	    return cc; | ||||
|           } | ||||
| 
 | ||||
| 	  t++; | ||||
| 	  depth--; | ||||
| 
 | ||||
|           stack->height--; | ||||
| 
 | ||||
|           if (event_handlers != NULL &&  | ||||
|               event_handlers->end_sexpr != NULL) | ||||
|             event_handlers->end_sexpr(); | ||||
| 
 | ||||
| 	  state = 1; | ||||
| 
 | ||||
| 	  /** if depth = 0 then we finished a sexpr, and we return **/ | ||||
| 	  if (depth == 0) { | ||||
|             cc->bindata = bindata; | ||||
|             cc->binread = binread; | ||||
|             cc->binexpected = binexpected; | ||||
|             cc->error = SEXP_ERR_OK; | ||||
|             cc->mode = mode; | ||||
| 	    cc->val = val; | ||||
|             cc->val_allocated = val_allocated; | ||||
|             cc->val_used = val_used; | ||||
| 	    cc->vcur = vcur; | ||||
| 	    cc->lastPos = t; | ||||
| 	    cc->depth = depth; | ||||
| 	    cc->qdepth = qdepth; | ||||
| 	    cc->state = 1; | ||||
| 	    cc->stack = stack; | ||||
| 	    cc->esc = 0; | ||||
|             cc->event_handlers = event_handlers; | ||||
| 	    cc->last_sexp = NULL; | ||||
|             stack->height = 0; | ||||
| 
 | ||||
| 	    return cc; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	case 4: /** parsing atom **/ | ||||
| 	  if (esc == 1 && (t[0] == '\"' || t[0] == '(' || | ||||
| 			   t[0] == ')' || t[0] == '\'' || | ||||
| 			   t[0] == '\\')) { | ||||
| 	    vcur--; /* back up to overwrite the \ */ | ||||
| 	    vcur[0] = t[0]; | ||||
| 	    vcur++; | ||||
| 	    t++; | ||||
| 	    esc = 0; | ||||
| 	    break; | ||||
| 	  } | ||||
| 
 | ||||
| 	  /* look at an ascii table - these ranges are the non-whitespace, non
 | ||||
| 	     paren and quote characters that are legal in atoms */ | ||||
| 	  if (!((t[0] >= '*' && t[0] <= '~') || | ||||
| 		((unsigned char)(t[0]) > 127) ||  | ||||
| 		(t[0] == '!') || | ||||
| 		(t[0] >= '#' && t[0] <= '&'))) | ||||
| 	    { | ||||
| 	      vcur[0] = '\0'; | ||||
|               val_used++; | ||||
| 
 | ||||
| 	      elts++; | ||||
| 
 | ||||
|               if (event_handlers != NULL && | ||||
|                   event_handlers->characters != NULL) { | ||||
|                 if (squoted != 0) | ||||
|                   event_handlers->characters(val,val_used,SEXP_SQUOTE); | ||||
|                 else | ||||
|                   event_handlers->characters(val,val_used,SEXP_BASIC); | ||||
|               } | ||||
| 
 | ||||
|               vcur = val; | ||||
|               val_used = 0; | ||||
| 
 | ||||
|               if (stack->height < 1) { | ||||
|                   /* looks like this expression was just a basic atom - so
 | ||||
|                      return it. */ | ||||
|                   cc->bindata = bindata; | ||||
|                   cc->binread = binread; | ||||
|                   cc->binexpected = binexpected; | ||||
|                   cc->mode = mode; | ||||
|                   cc->error = SEXP_ERR_OK; | ||||
|                   cc->val = val; | ||||
|                   cc->val_used = val_used; | ||||
|                   cc->val_allocated = val_allocated; | ||||
|                   cc->vcur = vcur; | ||||
|                   cc->squoted = 0; | ||||
|                   cc->lastPos = t; | ||||
|                   cc->depth = depth; | ||||
|                   cc->qdepth = qdepth; | ||||
|                   cc->state = 1; | ||||
|                   cc->stack = stack; | ||||
|                   cc->esc = 0; | ||||
|                   cc->last_sexp = NULL; | ||||
|                   cc->event_handlers = event_handlers; | ||||
| 
 | ||||
|                   return cc; | ||||
| 		} | ||||
| 
 | ||||
| 	      switch (t[0]) { | ||||
|               case ' ': | ||||
|               case '\t': | ||||
|               case '\n': | ||||
|               case '\r': | ||||
|                 /** NOTE: we know whitespace following atom, so spin ahead
 | ||||
|                     one and let state 1 do what it needs to for the next | ||||
|                     character. **/ | ||||
|                 state = 1; | ||||
|                 t++; | ||||
|                 squoted = 0; | ||||
|                 break; | ||||
|               case ')': | ||||
|                 squoted = 0; | ||||
|                 state = 3; | ||||
|                 break; | ||||
|               default: | ||||
|                 squoted = 0; | ||||
|                 state = 1; | ||||
|               } | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      vcur[0] = t[0]; | ||||
| 	      if (t[0] == '\\') esc = 1; | ||||
| 	      else esc = 0; | ||||
|               val_used++; | ||||
| 
 | ||||
|               if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|                 val = (char *)sexp_realloc(val, | ||||
|                                            val_allocated+sexp_val_grow_size, | ||||
|                                            val_allocated); | ||||
| #else | ||||
|                 val = sexp_realloc(val, | ||||
|                                    val_allocated+sexp_val_grow_size, | ||||
|                                    val_allocated); | ||||
| #endif | ||||
|                 assert(val != NULL); | ||||
|                 vcur = val + val_used; | ||||
|                 val_allocated += sexp_val_grow_size; | ||||
|               } else vcur++; | ||||
| 
 | ||||
| 	      t++; | ||||
| 	    } | ||||
| 	  break; | ||||
| 	case 5: | ||||
| 	  if (esc == 1 && (t[0] == '\"' || | ||||
| 			   t[0] == '\'' || | ||||
| 			   t[0] == '(' || | ||||
| 			   t[0] == ')' || | ||||
| 			   t[0] == '\\')) { | ||||
| 	    vcur--; | ||||
| 	    vcur[0] = t[0]; | ||||
| 	    vcur++; | ||||
|             /** NO NEED TO UPDATE VAL COUNTS **/ | ||||
| 	    t++; | ||||
| 	    esc = 0; | ||||
| 	  } | ||||
| 
 | ||||
| 	  if (t[0] == '\"') | ||||
| 	    { | ||||
| 	      state = 6; | ||||
| 
 | ||||
|               if (squoted == 1) { | ||||
|                 vcur[0] = '\"'; | ||||
|                 val_used++; | ||||
|                  | ||||
|                 if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|                   val = (char *)sexp_realloc(val, | ||||
|                                              val_allocated+sexp_val_grow_size, | ||||
|                                              val_allocated); | ||||
| #else | ||||
|                   val = sexp_realloc(val, | ||||
|                                      val_allocated+sexp_val_grow_size, | ||||
|                                      val_allocated); | ||||
| #endif | ||||
|                   assert(val != NULL); | ||||
|                   vcur = val + val_used; | ||||
|                   val_allocated += sexp_val_grow_size; | ||||
|                 } else vcur++; | ||||
|               } | ||||
| 
 | ||||
|               vcur[0] = '\0'; | ||||
| 
 | ||||
|               val_used++; | ||||
| 	      elts++; | ||||
| 
 | ||||
|               if (event_handlers != NULL && | ||||
|                   event_handlers->characters != NULL) { | ||||
|                 if (squoted == 1) | ||||
|                   event_handlers->characters(val,val_used,SEXP_SQUOTE); | ||||
|                 else | ||||
|                   event_handlers->characters(val,val_used,SEXP_DQUOTE); | ||||
|               } | ||||
| 
 | ||||
|               vcur = val; | ||||
|               val_used = 0; | ||||
| 	       | ||||
| 	      if (stack->height < 1) { | ||||
|                   /* looks like this expression was just a basic double
 | ||||
|                      quoted atom - so return it. */ | ||||
|                   t++; /* spin past the quote */ | ||||
| 
 | ||||
|                   cc->bindata = bindata; | ||||
|                   cc->binread = binread; | ||||
|                   cc->binexpected = binexpected; | ||||
|                   cc->mode = mode; | ||||
|                   cc->squoted = 0; | ||||
|                   cc->error = SEXP_ERR_OK; | ||||
|                   cc->val = val; | ||||
|                   cc->val_used = val_used; | ||||
|                   cc->val_allocated = val_allocated; | ||||
|                   cc->vcur = vcur; | ||||
|                   cc->lastPos = t++; | ||||
|                   cc->depth = depth; | ||||
|                   cc->qdepth = qdepth; | ||||
|                   cc->state = 1; | ||||
|                   cc->stack = stack; | ||||
|                   cc->esc = 0; | ||||
|                   cc->last_sexp = NULL; | ||||
|                   cc->event_handlers = event_handlers; | ||||
| 
 | ||||
|                   return cc; | ||||
| 		} | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      vcur[0] = t[0]; | ||||
|               val_used++; | ||||
| 
 | ||||
|               if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|                 val = (char *)sexp_realloc(val, | ||||
|                                            val_allocated+sexp_val_grow_size, | ||||
|                                            val_allocated); | ||||
| #else | ||||
|                 val = sexp_realloc(val, | ||||
|                                    val_allocated+sexp_val_grow_size, | ||||
|                                    val_allocated); | ||||
| #endif | ||||
|                 assert(val != NULL); | ||||
|                 vcur = val + val_used; | ||||
|                 val_allocated += sexp_val_grow_size; | ||||
|               } else vcur++; | ||||
| 
 | ||||
| 	      if (t[0] == '\\') {  | ||||
|                 esc = 1;   | ||||
| 	      } else  | ||||
|                 esc = 0; | ||||
| 	    } | ||||
| 
 | ||||
| 	  t++; | ||||
| 	  break; | ||||
| 	case 6: | ||||
| 	  vcur = val; | ||||
| 	  state = 1; | ||||
| 	  break; | ||||
| 	case 7: | ||||
| 	  if (t[0] == '\"') | ||||
| 	    { | ||||
| 	      state = 5; | ||||
| 	      vcur = val; | ||||
|               t++; | ||||
| 
 | ||||
|               vcur[0] = '\"'; | ||||
|               val_used++; | ||||
|                | ||||
|               if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|                 val = (char *)sexp_realloc(val, | ||||
|                                            val_allocated+sexp_val_grow_size, | ||||
|                                            val_allocated); | ||||
| #else | ||||
|                 val = sexp_realloc(val, | ||||
|                                    val_allocated+sexp_val_grow_size, | ||||
|                                    val_allocated); | ||||
| #endif | ||||
|                 assert(val != NULL); | ||||
|                 vcur = val + val_used; | ||||
|                 val_allocated += sexp_val_grow_size; | ||||
|               } else vcur++; | ||||
|                | ||||
|               squoted = 1; | ||||
| 	    } | ||||
| 	  else if (t[0] == '(') | ||||
| 	    { | ||||
| 	      vcur = val; | ||||
| 	      state = 8; | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      vcur = val; | ||||
| 	      state = 4; | ||||
|               squoted = 1; | ||||
| 	    } | ||||
| 	  break; | ||||
| 	case 8: | ||||
| 	  if (esc == 0) { | ||||
| 	    if (t[0] == '(') | ||||
| 	      { | ||||
| 		qdepth++; | ||||
| 	      } | ||||
| 	    else if (t[0] == ')') | ||||
| 	      { | ||||
| 		qdepth--; | ||||
| 		state = 9; | ||||
| 	      } | ||||
|             else if (t[0] == '\"') | ||||
|               { | ||||
|                 state = 10; | ||||
|               } | ||||
| 	  } else { | ||||
| 	    esc = 0; | ||||
| 	  } | ||||
| 	  vcur[0] = t[0]; | ||||
| 	  if (t[0] == '\\') esc = 1; | ||||
| 	  else esc = 0; | ||||
|           val_used++; | ||||
| 
 | ||||
|           if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|             val = (char *)sexp_realloc(val, | ||||
|                                        val_allocated+sexp_val_grow_size, | ||||
|                                        val_allocated); | ||||
| #else | ||||
|             val = sexp_realloc(val, | ||||
|                                val_allocated+sexp_val_grow_size, | ||||
|                                val_allocated); | ||||
| #endif | ||||
|             assert(val != NULL); | ||||
|             vcur = val + val_used; | ||||
|             val_allocated += sexp_val_grow_size; | ||||
|           } else vcur++; | ||||
| 
 | ||||
| 	  t++; | ||||
|           /* let it fall through to state 9 if we know we're transitioning
 | ||||
|              into that state */ | ||||
|           if (state != 9) | ||||
|             break; | ||||
| 	case 9: | ||||
| 	  if (qdepth == 0) | ||||
| 	    { | ||||
| 	      state = 1; | ||||
| 	      vcur[0] = '\0'; | ||||
| 
 | ||||
| 	      elts++; | ||||
| 
 | ||||
|               if (event_handlers != NULL && | ||||
|                   event_handlers->characters != NULL) | ||||
|                 event_handlers->characters(val,val_used,SEXP_SQUOTE); | ||||
| 
 | ||||
|               vcur = val; | ||||
|               val_used = 0; | ||||
| 	       | ||||
| 	      if (stack->height < 1) { | ||||
|                   /* looks like the whole expression was a single
 | ||||
|                      quoted value!  So return it. */ | ||||
|                   cc->bindata = bindata; | ||||
|                   cc->binread = binread; | ||||
|                   cc->binexpected = binexpected; | ||||
|                   cc->mode = mode; | ||||
|                   cc->error = SEXP_ERR_OK; | ||||
|                   cc->squoted = 0; | ||||
|                   cc->val = val; | ||||
|                   cc->val_used = val_used; | ||||
|                   cc->val_allocated = val_allocated; | ||||
|                   cc->vcur = vcur; | ||||
|                   cc->lastPos = t; | ||||
|                   cc->depth = depth; | ||||
|                   cc->qdepth = qdepth; | ||||
|                   cc->state = 1; | ||||
|                   cc->stack = stack; | ||||
|                   cc->esc = 0; | ||||
|                   cc->last_sexp = NULL; | ||||
|                   cc->event_handlers = event_handlers; | ||||
| 
 | ||||
|                   return cc; | ||||
| 		} | ||||
| 	    } | ||||
| 	  else | ||||
| 	    state = 8; | ||||
| 	  break; | ||||
|         case 10: | ||||
|           if (t[0] == '\"' && esc == 0) | ||||
|             { | ||||
|               state = 8; | ||||
|             } | ||||
|           vcur[0] = t[0]; | ||||
|           if (t[0] == '\\') esc = 1; | ||||
|           else esc = 0; | ||||
|           val_used++; | ||||
| 
 | ||||
|           if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|             val = (char *)sexp_realloc(val, | ||||
|                                        val_allocated+sexp_val_grow_size, | ||||
|                                        val_allocated); | ||||
| #else | ||||
|             val = sexp_realloc(val, | ||||
|                                val_allocated+sexp_val_grow_size, | ||||
|                                val_allocated); | ||||
| #endif | ||||
|             assert(val != NULL); | ||||
|             vcur = val + val_used; | ||||
|             val_allocated += sexp_val_grow_size; | ||||
|           } else vcur++; | ||||
| 
 | ||||
|           t++; | ||||
|           break; | ||||
|         case 11: | ||||
|           if (t[0] == '\n') { | ||||
|             state = 1; | ||||
|           } | ||||
|           t++; | ||||
|           break; | ||||
|         case 12: /* pre: we saw a # and we're in inline binary mode */ | ||||
|           if (t[0] == 'b') { | ||||
|             vcur[0] = t[0]; | ||||
|             if (t[0] == '\\') esc = 1; | ||||
|             else esc = 0; | ||||
|             val_used++; | ||||
|              | ||||
|             if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|               val = (char *)sexp_realloc(val, | ||||
|                                          val_allocated+sexp_val_grow_size, | ||||
|                                          val_allocated); | ||||
| #else | ||||
|               val = sexp_realloc(val, | ||||
|                                  val_allocated+sexp_val_grow_size, | ||||
|                                  val_allocated); | ||||
| #endif | ||||
|               assert(val != NULL); | ||||
|               vcur = val + val_used; | ||||
|               val_allocated += sexp_val_grow_size; | ||||
|             } else vcur++;          | ||||
|              | ||||
|             state = 13; /* so far, #b */ | ||||
|             t++; | ||||
|           } else { | ||||
|             state = 4; /* not #b, so plain ol' atom */ | ||||
|           } | ||||
| 
 | ||||
|           break; | ||||
| 
 | ||||
|         case 13: /* pre: we saw a #b and we're in inline binary mode */ | ||||
|           if (t[0] == '#') { | ||||
|             vcur[0] = t[0]; | ||||
|             if (t[0] == '\\') esc = 1; | ||||
|             else esc = 0; | ||||
|             val_used++; | ||||
|              | ||||
|             if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|               val = (char *)sexp_realloc(val, | ||||
|                                          val_allocated+sexp_val_grow_size, | ||||
|                                          val_allocated); | ||||
| #else | ||||
|               val = sexp_realloc(val, | ||||
|                                  val_allocated+sexp_val_grow_size, | ||||
|                                  val_allocated); | ||||
| #endif | ||||
|               assert(val != NULL); | ||||
|               vcur = val + val_used; | ||||
|               val_allocated += sexp_val_grow_size; | ||||
|             } else vcur++; | ||||
|                          | ||||
|             state = 14; /* so far, #b# - we're definitely in binary
 | ||||
|                            land now. */ | ||||
|             /* reset vcur to val, overwrite #b# with the size string. */ | ||||
|             vcur = val; | ||||
|             val_used = 0; | ||||
|             t++; | ||||
|           } else { | ||||
|             state = 4; /* not #b#, so plain ol' atom */ | ||||
|           } | ||||
| 
 | ||||
|           break; | ||||
|            | ||||
|         case 14: | ||||
|           /**
 | ||||
|            * so far we've read #b#.  Now, the steps of the process become: | ||||
|            * proceed to read bytes in until we see # again.  This will be | ||||
|            * an ASCII representation of the size.  At this point, we want | ||||
|            * to read as many bytes as specified by this size string after | ||||
|            * the #. | ||||
|            */ | ||||
|           if (t[0] == '#') { /* done with size string */ | ||||
|             t++; | ||||
|             state = 15; | ||||
|             vcur[0] = '\0'; | ||||
| 
 | ||||
|             binexpected = (size_t) atoi(val); | ||||
|             assert(binexpected > 0); | ||||
|             binread = 0; | ||||
| #ifdef __cplusplus | ||||
|             bindata = (char *)sexp_malloc(sizeof(char)*binexpected); | ||||
| #else | ||||
|             bindata = sexp_malloc(sizeof(char)*binexpected);             | ||||
| #endif | ||||
|             assert(bindata != NULL); | ||||
|           } else { /* still reading size string */ | ||||
|             vcur[0] = t[0]; | ||||
|             if (t[0] == '\\') esc = 1; | ||||
|             else esc = 0; | ||||
|             val_used++; | ||||
|              | ||||
|             if (val_used == val_allocated) { | ||||
| #ifdef __cplusplus | ||||
|               val = (char *)sexp_realloc(val, | ||||
|                                          val_allocated+sexp_val_grow_size, | ||||
|                                          val_allocated); | ||||
| #else | ||||
|               val = sexp_realloc(val, | ||||
|                                  val_allocated+sexp_val_grow_size, | ||||
|                                  val_allocated); | ||||
| #endif | ||||
|               assert(val != NULL); | ||||
|               vcur = val + val_used; | ||||
|               val_allocated += sexp_val_grow_size; | ||||
|             } else vcur++; | ||||
| 
 | ||||
|             t++; | ||||
|           } | ||||
| 
 | ||||
|           break; | ||||
| 
 | ||||
|         case 15: /* reading binary blob */ | ||||
|           bindata[binread] = t[0]; | ||||
|           binread++; | ||||
|           t++; | ||||
| 
 | ||||
|           if (binread == binexpected) { | ||||
|             /* state = 1 -- create a sexp_t and head back */ | ||||
| 
 | ||||
|             elts++; | ||||
| 
 | ||||
|             if (event_handlers != NULL && | ||||
|                 event_handlers->binary != NULL) | ||||
|               event_handlers->binary(bindata, binread); | ||||
| 
 | ||||
|             sexp_free(bindata,binread); | ||||
|             bindata = NULL; | ||||
|             binread = binexpected = 0; | ||||
|              | ||||
|             state = 1; | ||||
| 
 | ||||
|             val_used = 0; | ||||
|             vcur = val; | ||||
| 	       | ||||
|           } | ||||
| 
 | ||||
|           break; | ||||
| 
 | ||||
| 	default: | ||||
| 	  fprintf (stderr, "eparse_sexp: unknown parser state %d.\n", state); | ||||
| 	  break; | ||||
| 	} | ||||
| 
 | ||||
|       /* the null check used to be part of the guard on the while loop.
 | ||||
|          unfortunately, if we're in state 15, null is considered a | ||||
|          perfectly valid byte.  This means the length passed in better | ||||
|          be accurate for the parser to not walk off the end of the  | ||||
|          string! */ | ||||
|       if (state != 15 && t[0] == '\0') keepgoing = 0; | ||||
|     } | ||||
| 
 | ||||
|   if (depth == 0 && elts > 0) { | ||||
|     cc->bindata = bindata; | ||||
|     cc->binread = binread; | ||||
|     cc->binexpected = binexpected; | ||||
|     cc->mode = mode; | ||||
|     cc->error = SEXP_ERR_OK; | ||||
|     cc->val = val; | ||||
|     cc->squoted = squoted; | ||||
|     cc->val_used = val_used; | ||||
|     cc->val_allocated = val_allocated; | ||||
|     cc->vcur = vcur; | ||||
|     cc->lastPos = t; | ||||
|     cc->depth = depth; | ||||
|     cc->qdepth = qdepth; | ||||
|     cc->state = 1; | ||||
|     cc->stack = stack; | ||||
|     cc->esc = 0; | ||||
|     cc->event_handlers = event_handlers; | ||||
|     stack->height = 0; | ||||
|     cc->last_sexp = NULL; | ||||
|   } else { | ||||
|     cc->bindata = bindata; | ||||
|     cc->binread = binread; | ||||
|     cc->binexpected = binexpected; | ||||
|     cc->mode = mode; | ||||
|     cc->val = val; | ||||
|     cc->esc = esc; | ||||
|     cc->squoted = squoted; | ||||
|     cc->vcur = vcur; | ||||
|     cc->val_allocated = val_allocated; | ||||
|     cc->val_used = val_used; | ||||
|     if (t[0] == '\0' || t == bufEnd) | ||||
|       cc->lastPos = NULL; | ||||
|     else | ||||
|       cc->lastPos = t; | ||||
|     cc->depth = depth; | ||||
|     cc->qdepth = qdepth; | ||||
|     cc->state = state; | ||||
|     cc->stack = stack; | ||||
|     cc->last_sexp = NULL; | ||||
|     cc->event_handlers = event_handlers; | ||||
|     cc->error = SEXP_ERR_OK; | ||||
|   } | ||||
|    | ||||
|   return cc; | ||||
| } | ||||
| @ -1,221 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| /**
 | ||||
|  * faststack.c : implementation of fast stack. | ||||
|  * | ||||
|  * matt sottile / matt@lanl.gov | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <sexpr/faststack.h> | ||||
| #include <sexpr/sexp.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * create an empty stack. | ||||
|  */ | ||||
| faststack_t * | ||||
| make_stack () | ||||
| { | ||||
|   faststack_t *s; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   s = (faststack_t *)sexp_malloc (sizeof (faststack_t)); | ||||
| #else | ||||
|   s = sexp_malloc (sizeof (faststack_t)); | ||||
| #endif | ||||
| 
 | ||||
|   if (s == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   s->top = s->bottom = NULL; | ||||
|   s->height = 0; | ||||
| 
 | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * free all levels of a stack | ||||
|  */ | ||||
| void | ||||
| destroy_stack (faststack_t * s) | ||||
| { | ||||
|   stack_lvl_t *sl; | ||||
| 
 | ||||
|   /* return if stack is null.  no error condition - just return. */ | ||||
|   if (s == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   /* start at the bottom */ | ||||
|   sl = s->bottom; | ||||
| 
 | ||||
|   /* if bottom is null, no levels to free. just free stack itself then. */ | ||||
|   if (sl == NULL) { | ||||
|     sexp_free(s, sizeof(faststack_t)); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   /* go up to the top of the allocated stack */ | ||||
|   while (sl->above != NULL) | ||||
|     sl = sl->above; | ||||
| 
 | ||||
|   /* until we get to the bottom (where below is null), free the data
 | ||||
|      at each level and the level itself. */ | ||||
|   while (sl->below != NULL) | ||||
|     { | ||||
|       sl = sl->below; | ||||
|       sexp_free (sl->above, sizeof(stack_lvl_t)); | ||||
|     } | ||||
| 
 | ||||
|   /* free the bottom level */ | ||||
|   sexp_free (sl, sizeof(stack_lvl_t)); | ||||
| 
 | ||||
|   /* free the stack wrapper itself. */ | ||||
|   sexp_free (s, sizeof(faststack_t)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * push a level onto the cur_stack.  reuse levels that have | ||||
|  * been previously allocated, allocate a new one if none | ||||
|  * are available. | ||||
|  */ | ||||
| faststack_t * | ||||
| push (faststack_t * cur_stack, void *data) | ||||
| { | ||||
|   stack_lvl_t *top, *tmp; | ||||
| 
 | ||||
|   if (cur_stack == NULL) { | ||||
|     sexp_errno = SEXP_ERR_BAD_STACK; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   top = cur_stack->top; | ||||
| 
 | ||||
|   /* if top isn't null, try to push above it. */ | ||||
|   if (top != NULL) | ||||
|     { | ||||
|       /* if above isn't null, set the stack top to it and set the
 | ||||
|          data */ | ||||
|       if (top->above != NULL) | ||||
| 	{ | ||||
| 	  top = cur_stack->top = cur_stack->top->above; | ||||
| 	  top->data = data; | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  /* otherwise, allocate a new level. */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| 	  tmp = top->above = (stack_level *)sexp_malloc (sizeof (stack_lvl_t)); | ||||
| #else | ||||
| 	  tmp = top->above = sexp_malloc (sizeof (stack_lvl_t)); | ||||
| #endif | ||||
| 
 | ||||
|           if (tmp == NULL) { | ||||
| 	    sexp_errno = SEXP_ERR_MEMORY; | ||||
| 	    return NULL; | ||||
| 	  } | ||||
| 
 | ||||
| 	  tmp->below = cur_stack->top; | ||||
| 	  tmp->above = NULL; | ||||
| 	  cur_stack->top = tmp; | ||||
| 	  tmp->data = data; | ||||
| 	} | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (cur_stack->bottom != NULL) | ||||
| 	{ | ||||
| 	  cur_stack->top = cur_stack->bottom; | ||||
| 	  cur_stack->top->data = data; | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| #ifdef __cplusplus | ||||
| 	  tmp = cur_stack->top = | ||||
|             (stack_lvl_t *)sexp_malloc (sizeof (stack_lvl_t)); | ||||
| #else | ||||
| 	  tmp = cur_stack->top = sexp_malloc (sizeof (stack_lvl_t)); | ||||
| #endif | ||||
| 	  if (tmp == NULL) { | ||||
| 	    sexp_errno = SEXP_ERR_MEMORY; | ||||
| 	    return NULL; | ||||
| 	  } | ||||
| 
 | ||||
| 	  cur_stack->bottom = tmp; | ||||
| 	  tmp->above = NULL; | ||||
| 	  tmp->below = NULL; | ||||
| 	  tmp->data = data; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   cur_stack->height++; | ||||
| 
 | ||||
|   return cur_stack; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * pop the top of the stack, return the stack level that was | ||||
|  * popped of. | ||||
|  */ | ||||
| stack_lvl_t * | ||||
| pop (faststack_t * s) | ||||
| { | ||||
|   stack_lvl_t *top; | ||||
| 
 | ||||
|   if (s == NULL) { | ||||
|     sexp_errno = SEXP_ERR_BAD_STACK; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   top = s->top; | ||||
| 
 | ||||
|   /* if stack top isn't null, set the top pointer to the next
 | ||||
|      level down and return the old top. */ | ||||
|   if (top != NULL && s->height > 0) | ||||
|     { | ||||
|       s->top = s->top->below; | ||||
|       s->height--; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (s->height < 1) return NULL; | ||||
|     } | ||||
| 
 | ||||
|   return top; | ||||
| } | ||||
							
								
								
									
										139
									
								
								sexpr/io.c
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								sexpr/io.c
									
									
									
									
									
								
							| @ -1,139 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <fcntl.h> | ||||
| #ifndef WIN32 | ||||
| # include <unistd.h> | ||||
| #else | ||||
| # define ssize_t int | ||||
| # include <io.h> | ||||
| # include <sys/types.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sexpr/sexp.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * initialize an io-wrapper | ||||
|  */ | ||||
| sexp_iowrap_t *init_iowrap(int fd) { | ||||
|   sexp_iowrap_t *iow; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   iow = (sexp_iowrap_t *)sexp_calloc(1,sizeof(sexp_iowrap_t)); | ||||
| #else | ||||
|   iow = sexp_calloc(1,sizeof(sexp_iowrap_t)); | ||||
| #endif | ||||
| 
 | ||||
|   if (iow == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   iow->cc = NULL; | ||||
|   iow->fd = fd; | ||||
|   iow->cnt = 0; | ||||
|   iow->buf[0] = '\0'; | ||||
| 
 | ||||
|   return iow; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * | ||||
|  */ | ||||
| void destroy_iowrap(sexp_iowrap_t *iow) { | ||||
|   if (iow == NULL) return; /* idiot */ | ||||
| 
 | ||||
|   destroy_continuation(iow->cc); | ||||
|   sexp_free(iow, sizeof(sexp_iowrap_t)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * | ||||
|  */ | ||||
| sexp_t *read_one_sexp(sexp_iowrap_t *iow) { | ||||
|   sexp_t  *sx = NULL; | ||||
| 
 | ||||
|   if (iow == NULL)  | ||||
|     return NULL; | ||||
| 
 | ||||
|   /* check if we have more to parse from the continuation. */ | ||||
|   if (iow->cc != NULL && iow->cc->lastPos != NULL) { | ||||
|     iow->cc = cparse_sexp(iow->buf, iow->cnt, iow->cc); | ||||
| 
 | ||||
|     if (iow->cc == NULL) return NULL; /* cparse_sexp set sexp_errno */ | ||||
|     if (iow->cc->last_sexp != NULL) { | ||||
|       sx = iow->cc->last_sexp; | ||||
|       iow->cc->last_sexp = NULL; | ||||
|       return sx; | ||||
|     } | ||||
|     iow->cnt = 0; | ||||
|   } | ||||
| 
 | ||||
|   if (iow->cnt == 0) { | ||||
|     iow->cnt = (size_t) read(iow->fd,iow->buf,BUFSIZ); | ||||
| 
 | ||||
|     if (iow->cnt == 0) { | ||||
|       sexp_errno = SEXP_ERR_IO_EMPTY; | ||||
|       return NULL; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   iow->cc = cparse_sexp(iow->buf,iow->cnt,iow->cc); | ||||
| 
 | ||||
|   while (iow->cc->last_sexp == NULL) { | ||||
|     if (iow->cc->error != SEXP_ERR_OK) { | ||||
|       sexp_errno = iow->cc->error; | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     iow->cnt = (size_t) read(iow->fd,iow->buf,BUFSIZ); | ||||
| 
 | ||||
|     if (iow->cnt == 0) { | ||||
|       sexp_errno = SEXP_ERR_IO_EMPTY; | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|     iow->cc = cparse_sexp(iow->buf,iow->cnt,iow->cc); | ||||
|     iow->cnt = 0; | ||||
|   } | ||||
| 
 | ||||
|   sx = iow->cc->last_sexp; | ||||
|   iow->cc->last_sexp = NULL; | ||||
| 
 | ||||
|   return sx; | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| prefix=@prefix@ | ||||
| exec_prefix=@exec_prefix@ | ||||
| libdir=@libdir@ | ||||
| datarootdir=@datarootdir@ | ||||
| datadir=@datadir@ | ||||
| includedir=@includedir@ | ||||
| 
 | ||||
| Name: libsexpr | ||||
| Description: Small, fast s-expression handling library (so called sexpr). | ||||
| Version: @LIBSEXPR_VERSION@ | ||||
| Requires:  | ||||
| Libs: -L${libdir} -lsexpr | ||||
| Cflags: -I${includedir} | ||||
							
								
								
									
										1719
									
								
								sexpr/parser.c
									
									
									
									
									
								
							
							
						
						
									
										1719
									
								
								sexpr/parser.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										589
									
								
								sexpr/sexp.c
									
									
									
									
									
								
							
							
						
						
									
										589
									
								
								sexpr/sexp.c
									
									
									
									
									
								
							| @ -1,589 +0,0 @@ | ||||
| /**
 | ||||
| @Cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sexpr/sexp.h> | ||||
| #include <sexpr/faststack.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * global error code that can be set by sexp library calls.  default | ||||
|  * is SEXP_ERR_OK. | ||||
|  */ | ||||
| sexp_errcode_t sexp_errno = SEXP_ERR_OK; | ||||
| 
 | ||||
| void reset_sexp_errno() { | ||||
| 	sexp_errno = SEXP_ERR_OK; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Recursively walk an s-expression and free it. | ||||
|  */ | ||||
| void | ||||
| destroy_sexp (sexp_t * s) | ||||
| { | ||||
|   if (s == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   if (s->ty == SEXP_LIST) { | ||||
|     destroy_sexp (s->list); | ||||
|   } else if (s->ty == SEXP_VALUE) {     | ||||
|     if (s->aty == SEXP_BINARY && s->bindata != NULL) { | ||||
|       sexp_free(s->bindata, s->binlength);      | ||||
|     } else if (s->val != NULL) { | ||||
|       sexp_free(s->val, s->val_allocated); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   s->val = NULL; | ||||
|   s->bindata = NULL; | ||||
| 
 | ||||
|   destroy_sexp (s->next); | ||||
| 
 | ||||
|   s->next = s->list = NULL; | ||||
| 
 | ||||
|   sexp_t_deallocate(s); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Iterative method to walk sx and turn it back into the string | ||||
|  * representation of the s-expression.  Fills the buffer. | ||||
|  */ | ||||
| int | ||||
| print_sexp (char *buf, size_t size, const sexp_t * sx) | ||||
| { | ||||
|   int retval; | ||||
|   size_t sz; | ||||
|   char *b = buf, *tc; | ||||
|   size_t left = size; | ||||
|   int depth = 0; | ||||
|   faststack_t *stack; | ||||
|   stack_lvl_t *top; | ||||
|   sexp_t *tdata; | ||||
|   sexp_t *fakehead; | ||||
|   sexp_t tmp; | ||||
| 
 | ||||
|   if (sx == NULL) { | ||||
| 	buf[0] = '\0'; | ||||
| 	return 0; | ||||
|   } | ||||
| 
 | ||||
|   tmp = *sx; | ||||
|   tmp.next = tmp.list = NULL; | ||||
| 
 | ||||
|   fakehead = copy_sexp(&tmp); | ||||
| 
 | ||||
|   if (fakehead == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   fakehead->list = sx->list; | ||||
|   fakehead->next = NULL; /* this is the important part of fakehead */ | ||||
| 
 | ||||
|   stack = make_stack (); | ||||
|   if (stack == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     sexp_t_deallocate(fakehead); | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   push (stack, fakehead); | ||||
| 
 | ||||
|   while (stack->top != NULL) | ||||
|     { | ||||
|       top = stack->top; | ||||
|       tdata = (sexp_t *) top->data; | ||||
| 
 | ||||
|       if (tdata == NULL) | ||||
| 	{ | ||||
| 	  pop (stack); | ||||
| 
 | ||||
| 	  if (depth > 0) | ||||
| 	    { | ||||
| 	      b[0] = ')'; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	      depth--; | ||||
| 	      if (left == 0) | ||||
| 		{ | ||||
| 		  sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
| 
 | ||||
| 	  if (stack->top == NULL) | ||||
| 	    break; | ||||
| 
 | ||||
| 	  top = stack->top; | ||||
| 	  top->data = ((sexp_t *) top->data)->next; | ||||
| 	  if (top->data != NULL) | ||||
| 	    { | ||||
| 	      b[0] = ' '; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	      if (left == 0) | ||||
| 		{ | ||||
| 		  sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|       else if (tdata->ty == SEXP_VALUE) | ||||
| 	{ | ||||
| 	  if (tdata->aty == SEXP_DQUOTE) | ||||
| 	    { | ||||
| 	      b[0] = '\"'; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	    } | ||||
| 	  else if (tdata->aty == SEXP_SQUOTE) | ||||
| 	    { | ||||
| 	      b[0] = '\''; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	    } | ||||
| 
 | ||||
|           if (tdata->aty != SEXP_BINARY && tdata->val_used > 0) { | ||||
| 	    tc = tdata->val; | ||||
|             /* copy value into string */ | ||||
|             while (tc[0] != 0 && left > 0) | ||||
|               { | ||||
|                 /* escape characters that need escaping. */ | ||||
|                 if ((tc[0] == '\"' || tc[0] == '\\') && | ||||
|                     tdata->aty == SEXP_DQUOTE) | ||||
|                   { | ||||
|                     b[0] = '\\'; | ||||
|                     b++; | ||||
|                     left--; | ||||
|                     if (left == 0) break; | ||||
|                   } | ||||
|                  | ||||
|                 b[0] = tc[0]; | ||||
|                 b++; | ||||
|                 tc++; | ||||
|                 left--; | ||||
|                 if (left == 0) | ||||
|                   break; | ||||
|               } | ||||
|           } else { | ||||
|             if (left > 3) { | ||||
|               b[0] = '#'; b[1] = 'b'; b[2] = '#'; | ||||
|               b+=3; | ||||
|               left-=3; | ||||
| 
 | ||||
| #ifndef WIN32 | ||||
|               if ((size_t)(sz = snprintf(b,left,"%lu#",(unsigned long)tdata->binlength)) >= left) { | ||||
| #else | ||||
|               if ((sz = _snprintf(b,left,"%lu#",tdata->binlength)) >= left) { | ||||
| #endif | ||||
|                 left = 0; | ||||
|                 break; | ||||
|               } | ||||
|               b += sz; | ||||
|               left -= sz; | ||||
|                | ||||
|               if (left < tdata->binlength) { | ||||
|                 left = 0; | ||||
|                 break; | ||||
|               } | ||||
| 
 | ||||
| 	      if (tdata->binlength > 0) { | ||||
| 		memcpy(b,tdata->bindata,tdata->binlength); | ||||
| 		left -= tdata->binlength; | ||||
| 		b+=tdata->binlength; | ||||
| 	      } | ||||
| 
 | ||||
|               b[0] = ' '; | ||||
|               left--; | ||||
| 
 | ||||
|             } else { | ||||
|               left = 0;  | ||||
|               break; | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
| 	  if (tdata->aty == SEXP_DQUOTE && left > 0) | ||||
| 	    { | ||||
| 	      b[0] = '\"'; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	    } | ||||
| 
 | ||||
| 	  if (left == 0) | ||||
| 	    { | ||||
| 	      sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 	      break; | ||||
| 	    } | ||||
| 
 | ||||
| 	  top->data = ((sexp_t *) top->data)->next; | ||||
| 
 | ||||
| 	  if (top->data != NULL) | ||||
| 	    { | ||||
| 	      b[0] = ' '; | ||||
| 	      b++; | ||||
| 	      left--; | ||||
| 	      if (left == 0) | ||||
| 		{ | ||||
| 		  sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|       else if (tdata->ty == SEXP_LIST) | ||||
| 	{ | ||||
| 	  depth++; | ||||
| 	  b[0] = '('; | ||||
| 	  b++; | ||||
| 	  left--; | ||||
| 	  if (left == 0) | ||||
| 	    { | ||||
| 	      sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 	      break; | ||||
| 	    } | ||||
| 
 | ||||
| 	  push (stack, tdata->list); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  sexp_errno = SEXP_ERR_BADCONTENT; | ||||
| 	  destroy_stack (stack); | ||||
| 	  sexp_t_deallocate(fakehead); | ||||
| 	  return -1; | ||||
| 	} | ||||
| 
 | ||||
|     } | ||||
|   while (depth != 0) | ||||
|     { | ||||
|       b[0] = ')'; | ||||
|       b++; | ||||
|       left--; | ||||
|       depth--; | ||||
|       if (left == 0) | ||||
| 	{ | ||||
| 	  sexp_errno = SEXP_ERR_BUFFER_FULL; | ||||
| 	  break; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   if (left != 0) { | ||||
|     b[0] = 0; | ||||
|     retval = (int) (size-left); | ||||
|   } else { | ||||
|     b--; | ||||
|     b[0] = 0; | ||||
|     retval = -1; | ||||
|   } | ||||
| 
 | ||||
|   destroy_stack (stack); | ||||
|   sexp_t_deallocate(fakehead); | ||||
| 
 | ||||
|   return retval; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Iterative method to walk sx and turn it back into the string | ||||
|  * representation of the s-expression.  Fills the CSTRING that is | ||||
|  * passed in.  If *s == NULL (new CSTRING, never used), snew() is called | ||||
|  * and passed back.  If *s != NULL, *s is used as the CSTRING to print | ||||
|  * into.  In the last case, the recycled CSTRING must have sempty() called | ||||
|  * to reset the allocated vs. used counters to make it appear to be empty. | ||||
|  * the code will assume that sempty() was called by the user! | ||||
|  */ | ||||
| int | ||||
| print_sexp_cstr (CSTRING **s, const sexp_t *sx, size_t ss) | ||||
| { | ||||
|   int retval; | ||||
|   char *tc; | ||||
|   int depth = 0; | ||||
|   faststack_t *stack; | ||||
|   stack_lvl_t *top; | ||||
|   sexp_t *tdata; | ||||
|   sexp_t *fakehead; | ||||
|   CSTRING *_s = NULL; | ||||
|   char sbuf[32]; | ||||
|   unsigned int i; | ||||
|   sexp_t tmp; | ||||
| 
 | ||||
|   if (sx == NULL) { | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   if (*s == NULL) | ||||
|     _s = snew(ss); | ||||
|   else | ||||
|     _s = *s; | ||||
| 
 | ||||
|   tmp = *sx; | ||||
|   tmp.next = tmp.list = NULL; | ||||
| 
 | ||||
|   fakehead = copy_sexp(&tmp); | ||||
| 
 | ||||
|   if (fakehead == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   fakehead->list = sx->list; | ||||
|   fakehead->next = NULL; /* this is the important part of fakehead */ | ||||
| 
 | ||||
|   stack = make_stack (); | ||||
|   if (stack == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     sexp_t_deallocate(fakehead); | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   push (stack, fakehead); | ||||
| 
 | ||||
|   while (stack->top != NULL) | ||||
|     { | ||||
|       top = stack->top; | ||||
|       tdata = (sexp_t *) top->data; | ||||
| 
 | ||||
|       if (tdata == NULL) | ||||
| 	{ | ||||
| 	  pop (stack); | ||||
| 
 | ||||
| 	  if (depth > 0) | ||||
| 	    { | ||||
| 	      _s = saddch(_s, ')'); | ||||
| 	      depth--; | ||||
| 	    } | ||||
| 
 | ||||
| 	  if (stack->top == NULL) | ||||
| 	    break; | ||||
| 
 | ||||
| 	  top = stack->top; | ||||
| 	  top->data = ((sexp_t *) top->data)->next; | ||||
| 	  if (top->data != NULL) | ||||
| 	    { | ||||
| 	      _s = saddch(_s, ' '); | ||||
| 	    } | ||||
| 	} | ||||
|       else if (tdata->ty == SEXP_VALUE) | ||||
| 	{ | ||||
| 	  if (tdata->aty == SEXP_DQUOTE) | ||||
| 	    { | ||||
| 	      _s = saddch(_s,'\"'); | ||||
| 	    } | ||||
| 	  else if (tdata->aty == SEXP_SQUOTE) | ||||
| 	    { | ||||
| 	      _s = saddch(_s,'\''); | ||||
| 	    } | ||||
| 
 | ||||
|           if (tdata->aty == SEXP_BINARY) {	     | ||||
|             sprintf(sbuf,"#b#%lu#",(unsigned long)tdata->binlength); | ||||
| 
 | ||||
|             _s = sadd(_s,sbuf); | ||||
| 
 | ||||
|             for (i=0;i<tdata->binlength;i++) | ||||
|               _s = saddch(_s,tdata->bindata[i]); | ||||
|             _s = saddch(_s,' '); | ||||
|           } else { | ||||
| 	    if (tdata->val_used > 0) { | ||||
| 	      tc = tdata->val; | ||||
| 	       | ||||
| 	      /* copy value into string */ | ||||
| 	      while (tc[0] != 0) | ||||
| 		{ | ||||
| 		  /* escape characters that need escaping. */ | ||||
| 		  if ((tc[0] == '\"' || | ||||
| 		       tc[0] == '\\') && tdata->aty == SEXP_DQUOTE) | ||||
| 		    { | ||||
| 		      _s = saddch(_s,'\\'); | ||||
| 		    } | ||||
| 		   | ||||
| 		  _s = saddch(_s,tc[0]); | ||||
| 		  tc++; | ||||
| 		} | ||||
| 	    } | ||||
|           } | ||||
| 
 | ||||
| 	  if (tdata->aty == SEXP_DQUOTE) | ||||
| 	    { | ||||
| 	      _s = saddch(_s,'\"'); | ||||
| 	    } | ||||
| 
 | ||||
| 	  top->data = ((sexp_t *) top->data)->next; | ||||
| 
 | ||||
| 	  if (top->data != NULL) | ||||
| 	    { | ||||
| 	      _s = saddch(_s,' '); | ||||
| 	    } | ||||
| 	} | ||||
|       else if (tdata->ty == SEXP_LIST) | ||||
| 	{ | ||||
| 	  depth++; | ||||
| 	  _s = saddch(_s,'('); | ||||
| 	  push (stack, tdata->list); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  sexp_errno = SEXP_ERR_BADCONTENT; | ||||
| 	  destroy_stack (stack); | ||||
| 	  sexp_t_deallocate(fakehead); | ||||
| 	  return -1; | ||||
| 	} | ||||
| 
 | ||||
|     } | ||||
|   while (depth != 0) | ||||
|     { | ||||
|       _s = saddch(_s,')'); | ||||
|       depth--; | ||||
|     } | ||||
| 
 | ||||
|   *s = _s; | ||||
|   if (_s == NULL) | ||||
|     retval = 0; | ||||
|   else | ||||
|     retval = (int) _s->curlen; | ||||
| 
 | ||||
|   destroy_stack (stack); | ||||
|   sexp_t_deallocate(fakehead); | ||||
| 
 | ||||
|   return retval; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Allocate a new sexp_t element representing a list. | ||||
|  */ | ||||
| sexp_t *new_sexp_list(sexp_t *l) { | ||||
|   sexp_t *sx = sexp_t_allocate(); | ||||
| 
 | ||||
|   if (sx == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   sx->ty = SEXP_LIST; | ||||
| 
 | ||||
|   sx->list = l; | ||||
|   sx->next = NULL; | ||||
| 
 | ||||
|   sx->val = NULL; | ||||
|   sx->val_used = sx->val_allocated = 0; | ||||
| 
 | ||||
|   return sx; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * allocate a new sexp_t element representing a raw binary value | ||||
|  */ | ||||
| sexp_t *new_sexp_binary_atom(char *data, size_t binlength) { | ||||
|   sexp_t *sx = sexp_t_allocate(); | ||||
| 
 | ||||
|   if (sx == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   sx->ty = SEXP_VALUE; | ||||
|   sx->next = sx->list = NULL; | ||||
|   sx->aty = SEXP_BINARY; | ||||
|   sx->bindata = data; | ||||
|   sx->binlength = binlength; | ||||
|   sx->val = NULL; | ||||
|   sx->val_used = sx->val_allocated = 0; | ||||
| 
 | ||||
|   return sx; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * allocate a new sexp_t element representing a value  | ||||
|  */ | ||||
| sexp_t *new_sexp_atom(const char *buf, size_t bs, atom_t aty) { | ||||
|   sexp_t *sx = NULL; | ||||
| 
 | ||||
|   if (aty == SEXP_BINARY) { | ||||
|     sexp_errno = SEXP_ERR_BAD_CONSTRUCTOR; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   sx = sexp_t_allocate(); | ||||
| 
 | ||||
|   if (sx == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   sx->ty = SEXP_VALUE; | ||||
|   sx->aty = aty; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   sx->val = (char *)sexp_malloc(sizeof(char)*(bs+1)); | ||||
| #else | ||||
|   sx->val = sexp_malloc(sizeof(char)*(bs+1)); | ||||
| #endif | ||||
| 
 | ||||
|   if (sx->val == NULL) { | ||||
|     sexp_t_deallocate(sx); | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   sx->val_used = sx->val_allocated = bs+1; | ||||
| 
 | ||||
|   strcpy(sx->val,buf); | ||||
| 
 | ||||
|   sx->list = sx->next = NULL; | ||||
| 
 | ||||
|   return sx; | ||||
| } | ||||
| 
 | ||||
| /* sexp helpers */ | ||||
| int sexp_list_car(sexp_t *expr, sexp_t **sx) | ||||
| { | ||||
|   if (!SEXP_IS_LIST(expr) || expr->list->ty != SEXP_VALUE)    return 1; | ||||
| 
 | ||||
|   *sx = expr->list; | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int sexp_list_cdr(sexp_t *expr, sexp_t **sx) | ||||
| { | ||||
|   /* Dummy function. Can we do cdr properly? */ | ||||
|   if (!SEXP_IS_LIST(expr) || expr->list->ty != SEXP_VALUE)    return 1; | ||||
| 
 | ||||
|   if (!expr->list->next)    *sx = NULL; | ||||
|   else    *sx = expr->list->next; | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -1,125 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <sexpr/sexp.h> | ||||
| #include <sexpr/sexp_errors.h> | ||||
| #include <sexpr/sexp_memory.h> | ||||
| 
 | ||||
| #ifdef _SEXP_LIMIT_MEMORY_ | ||||
| 
 | ||||
| static size_t sexp_max_memory  = 32*1024*1024; /* default: 32MB */ | ||||
| static size_t sexp_used_memory = 0; | ||||
| 
 | ||||
| size_t get_sexp_max_memory() { | ||||
|   return sexp_max_memory; | ||||
| } | ||||
| 
 | ||||
| size_t get_sexp_used_memory() { | ||||
|   return sexp_used_memory; | ||||
| } | ||||
| 
 | ||||
| int set_sexp_max_memory(size_t newsize) { | ||||
|   if (newsize > 0) { | ||||
|     if (newsize < sexp_used_memory) { | ||||
|       sexp_errno = SEXP_ERR_BAD_PARAM; | ||||
|       return -1; | ||||
|     } else { | ||||
|       sexp_max_memory = newsize; | ||||
|     } | ||||
|   } else { | ||||
|     sexp_errno = SEXP_ERR_BAD_PARAM; | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   return sexp_max_memory; | ||||
| } | ||||
| 
 | ||||
| void *sexp_malloc(size_t size) { | ||||
|   void *ptr; | ||||
| 
 | ||||
|   if (sexp_used_memory+size > sexp_max_memory) { | ||||
|     sexp_errno = SEXP_ERR_MEM_LIMIT; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   ptr = malloc(size); | ||||
|   if (ptr != NULL) sexp_used_memory += size; | ||||
| 
 | ||||
|   return ptr; | ||||
| } | ||||
| 
 | ||||
| void *sexp_calloc(size_t count, size_t size) { | ||||
|   void *ptr; | ||||
| 
 | ||||
|   if (sexp_used_memory+(size*count) > sexp_max_memory) { | ||||
|     sexp_errno = SEXP_ERR_MEM_LIMIT; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   ptr = calloc(count, size); | ||||
|   if (ptr != NULL) sexp_used_memory += size*count; | ||||
| 
 | ||||
|   return ptr; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void sexp_free(void *ptr, size_t size) { | ||||
|   if (sexp_used_memory < size) { | ||||
|     fprintf(stderr,"ERROR: sexp_free called too many times!\n"); | ||||
|   } else { | ||||
|     sexp_used_memory -= size; | ||||
|   } | ||||
| 
 | ||||
|   free(ptr); | ||||
| } | ||||
| 
 | ||||
| void *sexp_realloc(void *ptr, size_t size, size_t oldsize) { | ||||
|   void *p; | ||||
| 
 | ||||
|   if (sexp_used_memory+(size-oldsize) > sexp_max_memory) { | ||||
|     sexp_errno = SEXP_ERR_MEM_LIMIT; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   p = realloc(ptr,size); | ||||
|   if (p != NULL) sexp_used_memory += size-oldsize; | ||||
| 
 | ||||
|   return p; | ||||
| } | ||||
| 
 | ||||
| #endif /* _SEXP_LIMIT_MEMORY_ */ | ||||
							
								
								
									
										224
									
								
								sexpr/sexp_ops.c
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								sexpr/sexp_ops.c
									
									
									
									
									
								
							| @ -1,224 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sexpr/sexp_ops.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * Given an s-expression, find the atom inside of it with the  | ||||
|  * value matchine name, and return a reference to it.  If the atom | ||||
|  * doesn't occur inside start, return NULL. | ||||
|  */ | ||||
| sexp_t * | ||||
| find_sexp (const char *name, sexp_t * start) | ||||
| { | ||||
|   sexp_t *temp; | ||||
| 
 | ||||
|   if (start == NULL) | ||||
|     return NULL; | ||||
| 
 | ||||
|   if (start->ty == SEXP_LIST) | ||||
|     { | ||||
|       temp = find_sexp (name, start->list); | ||||
|       if (temp == NULL) | ||||
| 	return find_sexp (name, start->next); | ||||
|       else | ||||
| 	return temp; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (start->val != NULL && strcmp (start->val, name) == 0) | ||||
| 	return start; | ||||
|       else | ||||
| 	return find_sexp (name, start->next); | ||||
|     } | ||||
| 
 | ||||
|   return NULL;			/* shouldn't get here */ | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Breadth first search - look at ->next before ->list when seeing list | ||||
|  * elements of an expression. | ||||
|  */ | ||||
| sexp_t *bfs_find_sexp(const char *str, sexp_t *sx) { | ||||
|   sexp_t *t = sx; | ||||
|   sexp_t *rt; | ||||
|    | ||||
|   if (sx == NULL) return NULL; | ||||
| 
 | ||||
|   while (t != NULL) { | ||||
|     if (t->ty == SEXP_VALUE) { | ||||
|       if (t->val != NULL) { | ||||
| 	if (strcmp(t->val,str) == 0) { | ||||
| 	  return t; | ||||
| 	} | ||||
|       } | ||||
|     }  | ||||
| 
 | ||||
|     t = t->next; | ||||
|   } | ||||
| 
 | ||||
|   t = sx; | ||||
|   while (t != NULL) { | ||||
|     if (t->ty == SEXP_LIST) { | ||||
|       rt = bfs_find_sexp(str,t->list); | ||||
|       if (rt != NULL) return rt; | ||||
|     } | ||||
|      | ||||
|     t = t->next; | ||||
|   } | ||||
| 
 | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Give the length of a s-expression list. | ||||
|  */ | ||||
| int sexp_list_length(const sexp_t *sx) { | ||||
|   int len = 0; | ||||
|   const sexp_t *t; | ||||
| 
 | ||||
|   if (sx == NULL) return 0; | ||||
| 
 | ||||
|   if (sx->ty == SEXP_VALUE) return 1; | ||||
| 
 | ||||
|   t = sx->list; | ||||
|    | ||||
|   while (t != NULL) { | ||||
|     len++; | ||||
|     t = t->next; | ||||
|   } | ||||
|   return len; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Copy an s-expression. | ||||
|  */ | ||||
| sexp_t *copy_sexp(const sexp_t *s) { | ||||
|   sexp_t *s_new; | ||||
| 
 | ||||
|   if (s == NULL) return NULL; | ||||
| 
 | ||||
|   s_new = sexp_t_allocate(); | ||||
|   if (s_new == NULL) { | ||||
|     sexp_errno = SEXP_ERR_MEMORY; | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* initialize fields to null and zero, and fill in only those necessary. */ | ||||
|   s_new->val_allocated = s_new->val_used = 0; | ||||
|   s_new->val = NULL; | ||||
|   s_new->list = s_new->next = NULL; | ||||
|   s_new->bindata = NULL; | ||||
|   s_new->binlength = 0; | ||||
| 
 | ||||
|   /* now start copying in data and setting appropriate fields. */ | ||||
|   s_new->ty = s->ty; | ||||
| 
 | ||||
|   /* values */ | ||||
|   if (s_new->ty == SEXP_VALUE) { | ||||
|     s_new->aty = s->aty; | ||||
| 
 | ||||
|     /* binary */ | ||||
|     if (s_new->aty == SEXP_BINARY) { | ||||
|       if (s->bindata == NULL && s->binlength > 0) { | ||||
| 	sexp_errno = SEXP_ERR_BADCONTENT; | ||||
| 	sexp_t_deallocate(s_new); | ||||
| 	return NULL; | ||||
|       } | ||||
|        | ||||
|       s_new->binlength = s->binlength; | ||||
|        | ||||
|       if (s->bindata == NULL) { | ||||
| 	s_new->bindata = NULL; | ||||
|       } else { | ||||
| 	/** allocate space **/ | ||||
| #ifdef __cplusplus | ||||
| 	s_new->bindata = (char *)sexp_malloc(sizeof(char)*s->binlength); | ||||
| #else | ||||
| 	s_new->bindata = sexp_malloc(sizeof(char)*s->binlength); | ||||
| #endif | ||||
|       } | ||||
| 
 | ||||
|       if (s_new->bindata == NULL) { | ||||
| 	sexp_errno = SEXP_ERR_MEMORY; | ||||
| 	sexp_t_deallocate(s_new); | ||||
| 	return NULL; | ||||
|       } | ||||
| 
 | ||||
|       memcpy(s_new->bindata,s->bindata,s->binlength*sizeof(char)); | ||||
| 
 | ||||
|     /* non-binary */  | ||||
|     } else { | ||||
|       if (s->val == NULL && (s->val_used > 0 || s->val_allocated > 0)) { | ||||
| 	sexp_errno = SEXP_ERR_BADCONTENT; | ||||
| 	sexp_t_deallocate(s_new); | ||||
| 	return NULL; | ||||
|       } | ||||
| 
 | ||||
|       s_new->val_used = s->val_used; | ||||
|       s_new->val_allocated = s->val_allocated; | ||||
| 
 | ||||
|       if (s->val == NULL) { | ||||
| 	s_new->val = NULL; | ||||
|       } else { | ||||
| 	/** allocate space **/ | ||||
| #ifdef __cplusplus | ||||
| 	s_new->val = (char *)sexp_calloc(1,sizeof(char)*s->val_allocated); | ||||
| #else | ||||
| 	s_new->val = sexp_calloc(1,sizeof(char)*s->val_allocated); | ||||
| #endif | ||||
| 
 | ||||
| 	if (s_new->val == NULL) { | ||||
| 	  sexp_errno = SEXP_ERR_MEMORY; | ||||
| 	  sexp_t_deallocate(s_new); | ||||
| 	  return NULL; | ||||
| 	} | ||||
| 
 | ||||
|   memcpy(s_new->val, s->val, sizeof(char)*s->val_used); | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     s_new->list = copy_sexp(s->list); | ||||
|   } | ||||
|    | ||||
|   s_new->next = copy_sexp(s->next); | ||||
| 
 | ||||
|   return s_new; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										124
									
								
								sexpr/sexp_vis.c
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								sexpr/sexp_vis.c
									
									
									
									
									
								
							| @ -1,124 +0,0 @@ | ||||
| /**
 | ||||
| @cond IGNORE | ||||
| 
 | ||||
| ====================================================== | ||||
|  SFSEXP: Small, Fast S-Expression Library version 1.2 | ||||
|  Written by Matthew Sottile (mjsottile@gmail.com) | ||||
| ====================================================== | ||||
| 
 | ||||
| Copyright (2003-2006). The Regents of the University of California. This | ||||
| material was produced under U.S. Government contract W-7405-ENG-36 for Los | ||||
| Alamos National Laboratory, which is operated by the University of | ||||
| California for the U.S. Department of Energy. The U.S. Government has rights | ||||
| to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR | ||||
| THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY | ||||
| LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce | ||||
| derivative works, such modified software should be clearly marked, so as not | ||||
| to confuse it with the version available from LANL. | ||||
| 
 | ||||
| Additionally, this library is free software; you can redistribute it and/or | ||||
| modify it under the terms of the GNU Lesser General Public License as | ||||
| published by the Free Software Foundation; either version 2.1 of the | ||||
| License, or (at your option) any later version. | ||||
| 
 | ||||
| This library 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 Lesser General Public License | ||||
| for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Lesser General Public License | ||||
| along with this library; if not, write to the Free Software Foundation, | ||||
| Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA | ||||
| 
 | ||||
| LA-CC-04-094 | ||||
| 
 | ||||
| @endcond | ||||
| **/ | ||||
| #include <sexpr/faststack.h> | ||||
| #include <sexpr/sexp.h> | ||||
| 
 | ||||
| void _sexp_to_dotfile(const sexp_t *sx, FILE *fp) { | ||||
|   const sexp_t *tmp; | ||||
| 
 | ||||
|   tmp = sx; | ||||
| 
 | ||||
|   while (tmp != NULL) { | ||||
|     fprintf(fp,"  sx%lu [shape=record,label=\"",(unsigned long)tmp); | ||||
|     if (tmp->ty == SEXP_VALUE) { | ||||
|       fprintf(fp,"{ <type> SEXP_VALUE | "); | ||||
|       switch (tmp->aty) { | ||||
|       case SEXP_BASIC: | ||||
| 	fprintf(fp,"SEXP_BASIC }"); | ||||
| 	break; | ||||
|       case SEXP_SQUOTE: | ||||
| 	fprintf(fp,"SEXP_SQUOTE }"); | ||||
| 	break; | ||||
|       case SEXP_DQUOTE: | ||||
| 	fprintf(fp,"SEXP_DQUOTE }"); | ||||
| 	break; | ||||
|       case SEXP_BINARY: | ||||
| 	fprintf(fp,"SEXP_BINARY }"); | ||||
| 	break; | ||||
|       default: | ||||
| 	fprintf(fp,"ATY Unknown }"); | ||||
| 	break; | ||||
|       } | ||||
|     } else | ||||
|       fprintf(fp,"<type> SEXP_LIST"); | ||||
| 
 | ||||
|     if (tmp->ty == SEXP_LIST) { | ||||
|       fprintf(fp,"| <list> list | <next> next\"];\n");	       | ||||
| 
 | ||||
|       if (tmp->list != NULL) { | ||||
| 	fprintf(fp,"  sx%lu:list -> sx%lu:type;\n", | ||||
|                 (unsigned long)tmp, | ||||
|                 (unsigned long)tmp->list); | ||||
| 	_sexp_to_dotfile(tmp->list,fp); | ||||
| 	if (tmp->next != NULL) | ||||
| 	  fprintf(fp,"  sx%lu:next -> sx%lu:type;\n", | ||||
|                   (unsigned long)tmp, | ||||
|                   (unsigned long)tmp->next); | ||||
| 	tmp = tmp->next; | ||||
|       } | ||||
|     } else { | ||||
|       if (tmp->aty == SEXP_BINARY) | ||||
| 	fprintf(fp,"| binlength=%lu | <next> next\"];\n", | ||||
| 		(unsigned long)tmp->binlength); | ||||
|       else  | ||||
| 	fprintf(fp,"| { va=%lu | vu=%lu } | val=%s | <next> next\"];\n", | ||||
| 		(unsigned long)tmp->val_allocated, | ||||
| 		(unsigned long)tmp->val_used, | ||||
| 		tmp->val); | ||||
| 
 | ||||
|       if (tmp->next != NULL)  | ||||
| 	fprintf(fp,"  sx%lu:next -> sx%lu:type;\n", | ||||
|                 (unsigned long)tmp, | ||||
|                 (unsigned long)tmp->next); | ||||
|       tmp = tmp->next; | ||||
| 
 | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| sexp_errcode_t sexp_to_dotfile(const sexp_t *sx, const char *fname) { | ||||
|   FILE *fp; | ||||
|   | ||||
|   if (sx == NULL || fname == NULL) { | ||||
|     return SEXP_ERR_NULLSTRING; | ||||
|   } | ||||
| 
 | ||||
|   fp = fopen(fname,"w+"); | ||||
|   if (fp == NULL) { | ||||
|     return SEXP_ERR_IO; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp,"digraph sexp {\n"); | ||||
| 
 | ||||
|   _sexp_to_dotfile(sx,fp); | ||||
| 
 | ||||
|   fprintf(fp,"}\n"); | ||||
| 
 | ||||
|   fclose(fp); | ||||
| 
 | ||||
|   return SEXP_ERR_OK; | ||||
| } | ||||
| @ -29,8 +29,8 @@ libsxmp_la_LIBADD += -lmman -luuid /mingw64/lib/libsexpr.a /mingw64/lib/libtdata | ||||
| 
 | ||||
| else | ||||
| 
 | ||||
| libsxmp_la_LIBADD += $(LIBUUID_LIBS) ../tdata/.libs/libtdata.la \
 | ||||
| 	../sexpr/.libs/libsexpr.la ../sxt/.libs/libsxt.la | ||||
| libsxmp_la_LIBADD += $(LIBUUID_LIBS) $(LIBTDATA_LIBS) \
 | ||||
| 	$(LIBSEXPR_LIBS) ../sxt/.libs/libsxt.la | ||||
| 
 | ||||
| endif !COND_WIN32 | ||||
| 
 | ||||
|  | ||||
| @ -30,7 +30,7 @@ libsxt_la_LIBADD += -lmman -luuid /mingw64/lib/libtdata.a | ||||
| 
 | ||||
| else | ||||
| 
 | ||||
| libsxt_la_LIBADD += $(LIBUUID_LIBS) ../tdata/.libs/libtdata.la | ||||
| libsxt_la_LIBADD += $(LIBUUID_LIBS) $(LIBTDATA_LIBS) | ||||
| 
 | ||||
| endif !COND_WIN32 | ||||
| 
 | ||||
|  | ||||
| @ -1,34 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in
 | ||||
| 
 | ||||
| AM_CPPFLAGS = \
 | ||||
| 	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
 | ||||
| 	-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
 | ||||
| 	-DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \
 | ||||
| 	$(LIBTDATA_CFLAGS) -I../include | ||||
| 
 | ||||
| AM_CFLAGS =\
 | ||||
| 	 -Wall\
 | ||||
| 	 -g | ||||
| 
 | ||||
| lib_LTLIBRARIES = libtdata.la | ||||
| 
 | ||||
| 
 | ||||
| libtdata_la_SOURCES = \
 | ||||
| 	avl.c lslist.c redblack.c splay.c \
 | ||||
| 	tree.c usrtc.c bitwise.c idx_allocator.c \
 | ||||
| 	cas.c | ||||
| 
 | ||||
| libtdata_la_LDFLAGS =  | ||||
| 
 | ||||
| libtdata_la_LIBADD =  | ||||
| 
 | ||||
| ##include_HEADERS = \
 | ||||
| ##	../include/tdata/macro.h ../include/tdata/tree.h ../include/tdata/usrtc.h \
 | ||||
| ##	../include/tdata/bitwise.h ../include/tdata/idx_allocator.h
 | ||||
| 
 | ||||
| pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = libtdata.pc | ||||
| 
 | ||||
| EXTRA_DIST = \
 | ||||
| 	libtdata.pc.in | ||||
| 
 | ||||
| @ -1,3 +0,0 @@ | ||||
| 0.2.3 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										328
									
								
								tdata/avl.c
									
									
									
									
									
								
							
							
						
						
									
										328
									
								
								tdata/avl.c
									
									
									
									
									
								
							| @ -1,328 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * avl.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <tdata/macro.h> | ||||
| #include <tdata/tree.h> | ||||
| 
 | ||||
| #define balance     usrtc_impldata.usrtc_avl_balance | ||||
| #define BALANCED    usrtc_balanced | ||||
| #define LEFTHEAVY   usrtc_leftheavy | ||||
| #define RIGHTHEAVY  usrtc_rightheavy | ||||
| 
 | ||||
| /*local functions prototypes*/ | ||||
| static void avl_init(usrtc_t *); | ||||
| static void avl_insert(usrtc_t *,usrtc_node_t *,const void *); | ||||
| static void avl_delete(usrtc_t *,usrtc_node_t *); | ||||
| static void avl_convert_from_list(usrtc_t *); | ||||
| 
 | ||||
| usrtc_functions_t usrtc_avl_fu = { | ||||
|   avl_init, | ||||
|   avl_insert, | ||||
|   avl_delete, | ||||
|   usrtc_tree_lookup, | ||||
|   usrtc_tree_lower_bound, | ||||
|   usrtc_tree_upper_bound, | ||||
|   usrtc_tree_first, | ||||
|   usrtc_tree_last, | ||||
|   usrtc_tree_next, | ||||
|   usrtc_tree_prev, | ||||
|   usrtc_tree_convert_to_list, | ||||
|   avl_convert_from_list, | ||||
|   usrtc_bst | ||||
| }; | ||||
| 
 | ||||
| /*internal use*/ | ||||
| static void rotate_left(usrtc_node_t **); | ||||
| static void rotate_right(usrtc_node_t **); | ||||
| static void fix_balance(usrtc_node_t **,usrtc_avl_balance_t ); | ||||
| static int insert(usrtc_t *,usrtc_node_t *,usrtc_node_t **,usrtc_node_t *); | ||||
| static usrtc_node_t *make_tree(usrtc_node_t **,usrtc_count_t ,int *,usrtc_node_t *); | ||||
| 
 | ||||
| /*implementation*/ | ||||
| static void avl_init(usrtc_t *us) | ||||
| { | ||||
|   usrtc_tree_init(us); | ||||
|   us->sentinel.balance=BALANCED; | ||||
| } | ||||
| 
 | ||||
| static void avl_insert(usrtc_t *us,usrtc_node_t *node,const void *key) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|    | ||||
|   node->key=key; | ||||
|   node->left=nil; | ||||
|   node->right=nil; | ||||
|   node->balance=BALANCED; | ||||
|    | ||||
|   if(insert(us,node,&nil->left,nil)) { | ||||
|     nil->balance=LEFTHEAVY; | ||||
|   } | ||||
|    | ||||
|   us->nodecount++; | ||||
| } | ||||
| 
 | ||||
| static void avl_delete(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *swap; | ||||
|   usrtc_node_t *child; | ||||
|   usrtc_node_t *parent; | ||||
| 
 | ||||
|   /*basic deletion*/ | ||||
|   usrtc_tree_delete(us,node,&swap,&child); | ||||
| 
 | ||||
|   /*implementation specific*/ | ||||
|   swap->balance=node->balance; | ||||
|   parent=child->parent; | ||||
| 
 | ||||
|   if(parent==nil) { | ||||
|     if(child==nil) { | ||||
|       parent->balance=BALANCED; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   while(parent!=nil) { | ||||
|     if((parent->left==nil) && (parent->right==nil)) { | ||||
|       if(child!=nil) | ||||
| 	return; | ||||
|       if(parent==BALANCED) | ||||
| 	return; | ||||
|       parent->balance=BALANCED; | ||||
|     } | ||||
|     else { | ||||
|       usrtc_node_t **pparent; | ||||
|       if(parent==parent->parent->left) | ||||
| 	pparent=&parent->parent->left; | ||||
|       else | ||||
| 	pparent=&parent->parent->right; | ||||
| 
 | ||||
|       if(child==parent->left) | ||||
| 	fix_balance(pparent,RIGHTHEAVY); | ||||
|       else { | ||||
| 	if(child!=parent->right) | ||||
| 	  return; | ||||
| 
 | ||||
| 	fix_balance(pparent,LEFTHEAVY); | ||||
|       } | ||||
| 
 | ||||
|       parent=*pparent; | ||||
|     } | ||||
| 
 | ||||
|     if(parent->balance==BALANCED) { | ||||
|       child=parent; | ||||
|       parent=child->parent; | ||||
|     } | ||||
|     else | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void avl_convert_from_list(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *root; | ||||
|   int height; | ||||
|    | ||||
|   if(us->nodecount==0) { | ||||
|     nil->balance=BALANCED; | ||||
|     return; | ||||
|   } | ||||
|    | ||||
|   root=make_tree(&nil->next,us->nodecount,&height,nil); | ||||
| 
 | ||||
|   if(nil->next!=nil) | ||||
|     return; | ||||
|    | ||||
|   nil->left=root; | ||||
|   root->parent=nil; | ||||
|   nil->balance=LEFTHEAVY; | ||||
| } | ||||
| 
 | ||||
| /*---*/ | ||||
| static void rotate_left(usrtc_node_t **top) | ||||
| { | ||||
|   usrtc_node_t *parent=*top; | ||||
|   usrtc_node_t *child=parent->right; | ||||
|    | ||||
|   child->parent=parent->parent; | ||||
|   parent->right=child->left; | ||||
|   parent->right->parent=parent; | ||||
|   child->left=parent; | ||||
|   parent->parent=child; | ||||
|   *top=child; | ||||
| } | ||||
| 
 | ||||
| static void rotate_right(usrtc_node_t **top) | ||||
| { | ||||
|   usrtc_node_t *parent=*top; | ||||
|   usrtc_node_t *child=parent->left; | ||||
|    | ||||
|   child->parent=parent->parent; | ||||
|   parent->left=child->right; | ||||
|   parent->left->parent=parent; | ||||
|   child->right=parent; | ||||
|   parent->parent=child; | ||||
|   *top=child; | ||||
| } | ||||
| 
 | ||||
| static void fix_balance(usrtc_node_t **pnode,usrtc_avl_balance_t bal) | ||||
| { | ||||
|   usrtc_node_t *node=*pnode; | ||||
|   usrtc_node_t *child; | ||||
|   usrtc_node_t *grandchild; | ||||
| 
 | ||||
|   if(node->balance==BALANCED) | ||||
|     node->balance=bal; | ||||
|   else if(node->balance!=bal) | ||||
|     node->balance=BALANCED; | ||||
|   else { | ||||
|     if(node->balance!=bal) | ||||
|       return; | ||||
| 
 | ||||
|     if(bal==LEFTHEAVY) { | ||||
|       child=node->left; | ||||
|       if(child->balance==LEFTHEAVY) { | ||||
| 	node->balance=BALANCED; | ||||
| 	child->balance=BALANCED; | ||||
| 	rotate_right(pnode); | ||||
|       } | ||||
|       else if(child->balance==BALANCED) { | ||||
| 	node->balance=LEFTHEAVY; | ||||
| 	child->balance=RIGHTHEAVY; | ||||
| 	rotate_right(pnode); | ||||
|       } | ||||
|       else { | ||||
| 	grandchild=child->right; | ||||
| 	if(grandchild->balance==LEFTHEAVY) { | ||||
| 	  node->balance=RIGHTHEAVY; | ||||
| 	  child->balance=BALANCED; | ||||
| 	} | ||||
| 	else if(grandchild->balance==RIGHTHEAVY) { | ||||
| 	  node->balance=BALANCED; | ||||
| 	  child->balance=LEFTHEAVY; | ||||
| 	} | ||||
| 	else { | ||||
| 	  node->balance=BALANCED; | ||||
| 	  child->balance=BALANCED; | ||||
| 	} | ||||
| 	grandchild->balance=BALANCED; | ||||
| 	rotate_left(&node->left); | ||||
| 	rotate_right(pnode); | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       child=node->right; | ||||
|       if(child->balance==RIGHTHEAVY) { | ||||
| 	node->balance=BALANCED; | ||||
| 	child->balance=BALANCED; | ||||
| 	rotate_left(pnode); | ||||
|       } | ||||
|       else if(child->balance==BALANCED) { | ||||
| 	node->balance=RIGHTHEAVY; | ||||
| 	child->balance=LEFTHEAVY; | ||||
| 	rotate_left(pnode); | ||||
|       } | ||||
|       else { | ||||
| 	grandchild=child->left; | ||||
| 	if(grandchild->balance==RIGHTHEAVY) { | ||||
| 	  node->balance=LEFTHEAVY; | ||||
| 	  child->balance=BALANCED; | ||||
| 	} | ||||
| 	else if(grandchild->balance==LEFTHEAVY) { | ||||
| 	  node->balance=BALANCED; | ||||
| 	  child->balance=RIGHTHEAVY; | ||||
| 	} | ||||
| 	else { | ||||
| 	  node->balance=BALANCED; | ||||
| 	  child->balance=BALANCED; | ||||
| 	} | ||||
| 	grandchild->balance=BALANCED; | ||||
| 	rotate_right(&node->right); | ||||
| 	rotate_left(pnode); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static int insert(usrtc_t *us,usrtc_node_t *what,usrtc_node_t **where,usrtc_node_t *parent) | ||||
| { | ||||
|   usrtc_node_t *here=*where; | ||||
|   int result; | ||||
| 
 | ||||
|   if(here==tree_null_priv(us)) { | ||||
|     *where=what; | ||||
|     what->parent=parent; | ||||
|     return 1; | ||||
|   } | ||||
|   else { | ||||
|     result=us->compare(what->key,here->key);	 | ||||
| 
 | ||||
|     if(result < 0) { | ||||
|       if(insert(us,what,&here->left,here)) { | ||||
| 	fix_balance(where,LEFTHEAVY); | ||||
| 	return ((*where)->balance!=BALANCED); | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       if(insert(us,what,&here->right,here)) { | ||||
| 	fix_balance(where,RIGHTHEAVY); | ||||
| 	return ((*where)->balance!=BALANCED); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *make_tree(usrtc_node_t **pnode,usrtc_count_t count, | ||||
| 			       int *pheight,usrtc_node_t *nil) | ||||
| { | ||||
|   usrtc_count_t leftcount; | ||||
|   int leftheight, rightheight; | ||||
|   usrtc_node_t *root; | ||||
|   usrtc_node_t *leftroot; | ||||
| 
 | ||||
|   if(count==0) { | ||||
|     *pheight=0; | ||||
|     return nil; | ||||
|   } | ||||
| 
 | ||||
|   leftcount=(count-1)/2; | ||||
|   leftroot=make_tree(pnode,leftcount,&leftheight,nil); | ||||
|   count-=leftcount; | ||||
| 
 | ||||
|   root=*pnode; | ||||
|   *pnode=root->next; | ||||
|   --count; | ||||
| 
 | ||||
|   root->left=leftroot; | ||||
|   leftroot->parent=root; | ||||
|   root->right=make_tree(pnode,count,&rightheight,nil); | ||||
|   root->right->parent=root; | ||||
| 
 | ||||
|   if(leftheight>rightheight) | ||||
|     return (void *)0; | ||||
| 
 | ||||
|   *pheight=rightheight+1; | ||||
|   root->balance=(leftheight==rightheight) ? BALANCED : RIGHTHEAVY; | ||||
| 
 | ||||
|   return root; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										201
									
								
								tdata/bitwise.c
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								tdata/bitwise.c
									
									
									
									
									
								
							| @ -1,201 +0,0 @@ | ||||
| /*
 | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser 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. | ||||
|  * | ||||
|  * (c) Copyright 2006,2007,2008 Jari OS Core Team <http://jarios.org>
 | ||||
|  * (c) Copyright 2008 Dmitry Gromada <gromada82@gmail.com> | ||||
|  * (c) Copyright 2010 Alexander Vdolainen <vdo@askele.com> | ||||
|  * | ||||
|  * (c) Copyright 2012 - 2013, 2014 Askele Oy <http://askele.com>
 | ||||
|  * | ||||
|  * Implements bitwise operations with multiword bitmaps | ||||
|  */ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <tdata/bitwise.h> | ||||
| 
 | ||||
| /* operation equivalent to division modulo number of power 2 */ | ||||
| #define MOD_POW2(var, pow) ((var) & ((pow) - 1)) | ||||
| 
 | ||||
| int init_bitmap(bitmap_t *bitmap, int nbits) | ||||
| { | ||||
|   int ret = 0; | ||||
|   int size = nbits >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   if (nbits < 0) | ||||
|     return -1; | ||||
| 
 | ||||
|   if (size << TYPE_LONG_SHIFT != nbits) | ||||
|      size++; | ||||
| 
 | ||||
|   bitmap->map = (unsigned long*)malloc(size * sizeof(unsigned long)); | ||||
|   if (bitmap->map == NULL) | ||||
|     ret = -1; | ||||
|   else | ||||
|      bitmap->nwords = size; | ||||
| 
 | ||||
|   memset(bitmap->map, 0, size * sizeof(unsigned long)); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void free_bitmap(bitmap_t *bitmap) | ||||
| { | ||||
|   if (bitmap->map) { | ||||
|     free(bitmap->map); | ||||
|     bitmap->map = NULL; | ||||
|   } | ||||
|   bitmap->nwords = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void bit_set_multi(bitmap_t *bitmap, int bitno) | ||||
| { | ||||
|   int i = bitno >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   return bit_set( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); | ||||
| } | ||||
| 
 | ||||
| int bit_test_and_set_multi(bitmap_t *bitmap, int bitno) | ||||
| { | ||||
|   int i = bitno >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   return bit_test_and_set( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); | ||||
| } | ||||
| 
 | ||||
| int bit_test_and_reset_multi(bitmap_t *bitmap, int bitno) | ||||
| { | ||||
|   int i = bitno >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   return bit_test_and_reset( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); | ||||
| } | ||||
| 
 | ||||
| void bit_clear_multi(bitmap_t *bitmap, int bitno) | ||||
| { | ||||
|   int i = bitno >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   return bit_clear( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); | ||||
| } | ||||
| 
 | ||||
| int bit_find_msf_multi(bitmap_t *bitmap, int mbit) | ||||
| { | ||||
|   int i, r; | ||||
|   unsigned long word; | ||||
| 
 | ||||
|   if (mbit < 0) | ||||
|     return -1; | ||||
|   else if (mbit >= bitmap->nwords * BITS_PER_LONG) | ||||
|     mbit = bitmap->nwords * BITS_PER_LONG - 1; | ||||
| 
 | ||||
|   i = mbit >> TYPE_LONG_SHIFT; | ||||
|   word = bitmap->map[i] & (~0UL >> ( BITS_PER_LONG - 1 - MOD_POW2(mbit, BITS_PER_LONG) )); | ||||
|   r = bit_find_msf(word); | ||||
| 
 | ||||
|   while ((r == -1) && (--i >= 0)) { | ||||
|     if (bitmap->map[i]) | ||||
|       r = bit_find_msf(bitmap->map[i]); | ||||
|   } | ||||
| 
 | ||||
|   r = (r == -1) ? r : (i * BITS_PER_LONG + r); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| int bit_find_lsf_multi(bitmap_t *bitmap, int lbit) | ||||
| { | ||||
|   int i, r; | ||||
|   unsigned long word; | ||||
| 
 | ||||
|   if (lbit >= bitmap->nwords * BITS_PER_LONG) | ||||
|     return -1; | ||||
|   else if (lbit < 0) | ||||
|     lbit = 0; | ||||
| 
 | ||||
|   i = lbit >> TYPE_LONG_SHIFT; | ||||
|   word = bitmap->map[i] & (~0UL << MOD_POW2(lbit, BITS_PER_LONG)); | ||||
|   r = bit_find_lsf(word); | ||||
| 
 | ||||
|   while ((r == -1) && (++i < bitmap->nwords)) { | ||||
|     if (bitmap->map[i]) | ||||
|       r = bit_find_lsf(bitmap->map[i]); | ||||
|   } | ||||
| 
 | ||||
|   r = (r == -1) ? r : (i * BITS_PER_LONG + r); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| int bit_test_multi(bitmap_t *bitmap, int bitno) | ||||
| { | ||||
|   int i = bitno >> TYPE_LONG_SHIFT; | ||||
| 
 | ||||
|   return bit_test( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); | ||||
| } | ||||
| 
 | ||||
| void bitrange_set_multi(bitmap_t *bitmap, int start_bit, int end_bit) | ||||
| { | ||||
|   int i1, i2; | ||||
|   unsigned long mask1, mask2, *p = bitmap->map; | ||||
| 
 | ||||
|   if (start_bit > end_bit) | ||||
|     return; | ||||
| 
 | ||||
|   i1 = start_bit >> TYPE_LONG_SHIFT; | ||||
|   mask1 = ~0UL << MOD_POW2(start_bit, BITS_PER_LONG); | ||||
| 
 | ||||
|   i2 = end_bit >> TYPE_LONG_SHIFT; | ||||
|   mask2 = ~0UL >> (BITS_PER_LONG - 1 - MOD_POW2(end_bit, BITS_PER_LONG)); | ||||
| 
 | ||||
|   if (i1 == i2) | ||||
|     p[i1] |= mask1 & mask2; | ||||
|   else { | ||||
|     p[i1++] |= mask1; | ||||
| 
 | ||||
|     if (i2 - i1 > 0) | ||||
|       memset( p + i1, 0xFF, (i2 - i1) * sizeof(unsigned long) ); | ||||
| 
 | ||||
|     p[i2] |= mask2; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void bitrange_clear_multi(bitmap_t *bitmap, int start_bit, int end_bit) | ||||
| { | ||||
|   int          i1, i2; | ||||
|   unsigned long mask1, mask2, *p = bitmap->map; | ||||
| 
 | ||||
|   if (start_bit > end_bit) | ||||
|     return; | ||||
| 
 | ||||
|   i1 = start_bit >> TYPE_LONG_SHIFT; | ||||
|   mask1 = ( 1UL << (start_bit & MOD_POW2(start_bit, BITS_PER_LONG)) ) - 1; | ||||
| 
 | ||||
|   i2 = end_bit >> TYPE_LONG_SHIFT; | ||||
|   mask2 = ~0UL << (MOD_POW2(end_bit, BITS_PER_LONG) + 1); | ||||
| 
 | ||||
|   if (i1 == i2) | ||||
|     p[i1] &= mask1 | mask2; | ||||
|   else { | ||||
|     p[i1++] &= mask1; | ||||
| 
 | ||||
|     if (i2 - i1 > 0) | ||||
|       memset(p + i1, 0, (i2 - i1) * sizeof(unsigned long)); | ||||
| 
 | ||||
|     p[i2] &= mask2; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										51
									
								
								tdata/cas.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								tdata/cas.c
									
									
									
									
									
								
							| @ -1,51 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * cas.c | ||||
|  * Copyright (C) 2015 Alexander Vdolainen <avdolainen@gmail.com> | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include "../config.h" | ||||
| 
 | ||||
| #if !defined (HAVE__SYNC_BOOL_COMPARE_AND_SWAP_8) | ||||
| #include <pthread.h> | ||||
| static pthread_mutex_t __sync_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
| #endif | ||||
| 
 | ||||
| #ifndef HAVE__SYNC_BOOL_COMPARE_AND_SWAP_8 | ||||
| _Bool __sync_bool_compare_and_swap_8 (uint64_t*, uint64_t, uint64_t) | ||||
| __attribute__ ((visibility ("hidden"))); | ||||
| 
 | ||||
| _Bool __sync_bool_compare_and_swap_8 (uint64_t* ptr, uint64_t old, uint64_t new) | ||||
| { | ||||
|   int i; | ||||
|   _Bool ret; | ||||
| 
 | ||||
|   i = pthread_mutex_lock(&__sync_lock); | ||||
| 
 | ||||
|   if(*ptr != old)    ret = 0; | ||||
|   else { | ||||
|     *ptr = new; | ||||
|     ret = 1; | ||||
|   } | ||||
| 
 | ||||
|   i = pthread_mutex_unlock(&__sync_lock); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| #endif | ||||
| @ -1,254 +0,0 @@ | ||||
| /*
 | ||||
|  * This library is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2.1 of | ||||
|  * the License. | ||||
|  * | ||||
|  * This library 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * (c) Copyright 2006,2007,2008 MString Core Team <http://mstring.jarios.org>
 | ||||
|  * (c) Copyright 2009 Dan Kruchinin <dan.kruchinin@gmail.com> | ||||
|  * (c) Copyright 2009 Alexander Vdolainen <madtirra@jarios.org> (libc adaptation) | ||||
|  * (c) Copyright 2009 Dmitry Gromada <gromada@jarios.org> (locking added) | ||||
|  * (c) Copyright 2013 Alexander Vdolainen <vdo@askele.com> (verios changes to make it run on linux) | ||||
|  * | ||||
|  * (c) Copyright 2012 - 2013, 2014 Askele Oy <http://askele.com>
 | ||||
|  * | ||||
|  * Index allocator | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <stddef.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| #include <sys/types.h> | ||||
| #include <tdata/bitwise.h> | ||||
| #include <tdata/idx_allocator.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Main idea of index allocator is quite simple: | ||||
|  * There is a group of tasks that requires dynamic allocation | ||||
|  * of unique non-negative integer identifiers. Where a set of such | ||||
|  * integers is relatively big (thousands of numbers), index allocator | ||||
|  * becomes a nifty solution. | ||||
|  * The core of allocator is two bitmaps. One of them called "indices bitmap" | ||||
|  * or "second level bitmap". Each bit of that bitmap corresponds to particular unique | ||||
|  * index. Since second-level bitmap is a large portion of continuous memory, searching | ||||
|  * of set/zero bit in it becomes relatively slow. For speeding-up search process we invented | ||||
|  * a first-level bitmap. Second-level array is splitted on groups each of them contains BYTES_PER_ITEM bytes. | ||||
|  * First-level(or main) bitmap establishes corresponding between particular group and its | ||||
|  * state(group may have free indices or not). | ||||
|  * So index allocation assumes at first searching of group index in a the first-level bitmap and only | ||||
|  * then searching an index in the second level bitmap starting from a group index. | ||||
|  */ | ||||
| 
 | ||||
| #define MIN_IDA_SIZE (WORDS_PER_ITEM * sizeof(ulong_t)) | ||||
| #define MAX_UNLOCKED_ATTEMPTS 3 | ||||
| 
 | ||||
| /* there macros defined only on new glibc (from 12-jul-2013), let's use our own */ | ||||
| #ifndef is_powerof2 | ||||
| #define is_powerof2(num) (((num) & ~((num) - 1)) == (num)) | ||||
| #endif | ||||
| #ifndef round_up_pow2 | ||||
| #define round_up_pow2(x) (!is_powerof2(x) ? (1 << (bit_find_msf(x) + 1)) : (x) ) | ||||
| #endif | ||||
| 
 | ||||
| static inline size_t __get_main_bmap_size(idx_allocator_t *ida) | ||||
| { | ||||
|   if (ida->ids_bmap != NULL) | ||||
|     return (round_up_pow2((ida->size * sizeof(ulong_t)) / BYTES_PER_ITEM)); | ||||
| 
 | ||||
|   return ida->size; | ||||
| } | ||||
| 
 | ||||
| ulong_t idx_allocate(idx_allocator_t *ida) | ||||
| { | ||||
|   ulong_t id = IDX_INVAL; | ||||
|   long fnfi = 0; | ||||
|   size_t i, main_offs = 0, main_sz; | ||||
|   int natm = 0;   /* attempt number */ | ||||
| 
 | ||||
|   main_sz = __get_main_bmap_size(ida) / sizeof(ulong_t); | ||||
|   i = 0; | ||||
| 
 | ||||
|   if (ida->ids_bmap != NULL) { | ||||
|     for (;;) { | ||||
|       while (i < main_sz) { | ||||
|         fnfi = zero_bit_find_lsf(ida->main_bmap[i]); | ||||
|         if (fnfi >= 0) { | ||||
|           fnfi = (fnfi * WORDS_PER_ITEM) + i * WORDS_PER_ITEM * BITS_PER_LONG; | ||||
|           main_offs = i; | ||||
|           break; | ||||
|         } | ||||
| 
 | ||||
|         i++; | ||||
|       } | ||||
|       if ((fnfi >= 0) && (fnfi < ida->size)) { | ||||
|         int res_id, j, total_sz; | ||||
| 
 | ||||
|         total_sz = fnfi + WORDS_PER_ITEM; | ||||
|         j = fnfi; | ||||
|         while (j < total_sz) { | ||||
|           res_id = zero_bit_find_lsf(ida->ids_bmap[j]); | ||||
|           if (res_id < 0) { | ||||
|             j++; | ||||
|             continue; | ||||
|           } | ||||
| 
 | ||||
|           if (ida_lockable(ida) /*&& atomic_test_and_set_bit(ida->ids_bmap + j, res_id)*/) { | ||||
|             natm++; | ||||
|             if (natm == MAX_UNLOCKED_ATTEMPTS) | ||||
|               ida_lock(ida); | ||||
|           } else { | ||||
|             bit_set(ida->ids_bmap + j, res_id); | ||||
|           } | ||||
| 
 | ||||
|           id = res_id + j * BITS_PER_LONG; | ||||
|           if (id >= ida->max_id) { | ||||
|             bit_clear(ida->ids_bmap + j, res_id); | ||||
|             id = IDX_INVAL; | ||||
|           } | ||||
| 
 | ||||
|           goto out; | ||||
|         } | ||||
| 
 | ||||
|         bit_set(ida->main_bmap + main_offs, | ||||
|                 (fnfi - (main_offs * WORDS_PER_ITEM * BITS_PER_LONG)) / WORDS_PER_ITEM); | ||||
|         if ((ida->main_bmap[i] & ~0UL) == ~0UL) | ||||
|           i++; | ||||
|       } | ||||
|       else | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     while (i < main_sz)  { | ||||
|       fnfi = zero_bit_find_lsf(ida->main_bmap[i]); | ||||
|       if (fnfi >= 0) { | ||||
|         bit_set(ida->main_bmap + i, fnfi); | ||||
|         id = fnfi + i * BITS_PER_LONG; | ||||
|         if (id >= ida->max_id) { | ||||
|           bit_clear(ida->main_bmap + i, fnfi); | ||||
|           id = IDX_INVAL; | ||||
|         } | ||||
| 
 | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       i++; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   out: | ||||
|   if (natm == MAX_UNLOCKED_ATTEMPTS) | ||||
|     ida_unlock(ida); | ||||
| 
 | ||||
|   return id; | ||||
| } | ||||
| 
 | ||||
| void idx_reserve(idx_allocator_t *ida, ulong_t idx) | ||||
| { | ||||
|   int start_id, bitno; | ||||
|   ulong_t *ptr; | ||||
| 
 | ||||
|   start_id = idx / BITS_PER_LONG; | ||||
|   bitno = idx - start_id * BITS_PER_LONG; | ||||
|   if (ida->ids_bmap != NULL) | ||||
|     ptr = ida->ids_bmap + start_id; | ||||
|   else | ||||
|     ptr = ida->main_bmap + start_id; | ||||
| 
 | ||||
|   if (bit_test_and_set(ptr, bitno)) { | ||||
|     printf("[libc warning] Detected an attempt to reserve already busy index %ld " | ||||
|            "[function: %s]!\n", idx, __FUNCTION__); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void idx_free(idx_allocator_t *ida, ulong_t idx) | ||||
| { | ||||
|   int start_id, bitno, main_id, main_bitno; | ||||
|   ulong_t *ptr; | ||||
| 
 | ||||
|   start_id = idx / BITS_PER_LONG; | ||||
|   bitno = idx - start_id * BITS_PER_LONG; | ||||
|   if (ida->ids_bmap != NULL) { | ||||
|     ptr = ida->ids_bmap + start_id; | ||||
|     main_id = start_id / WORDS_PER_ITEM; | ||||
|     main_bitno = start_id - main_id * WORDS_PER_ITEM; | ||||
|     bit_clear(ida->main_bmap + main_id, main_bitno); | ||||
|   } | ||||
|   else | ||||
|     ptr = ida->main_bmap + start_id; | ||||
| 
 | ||||
|   if (!bit_test_and_clear(ptr, bitno)) { | ||||
|     printf("[libc warning] Detected an attempt to free already fried index %ld " | ||||
|            "[function: %s]!\n", idx, __FUNCTION__); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable) | ||||
| { | ||||
|   size_t bmap_sz; | ||||
|   int err = -ENOMEM; | ||||
| 
 | ||||
|   bmap_sz = (round_up_pow2(idx_max) >> 3); | ||||
|   memset(ida, 0, sizeof(*ida)); | ||||
|   ida->size = bmap_sz / sizeof(ulong_t); | ||||
|   if (ida->size >= MIN_IDA_SIZE) { | ||||
|     ida->ids_bmap = malloc(bmap_sz); | ||||
|     if (!ida->ids_bmap) { | ||||
|       goto error; | ||||
|     } | ||||
| 
 | ||||
|     memset(ida->ids_bmap, 0, bmap_sz); | ||||
|   } | ||||
|   else | ||||
|     ida->size = (ida->size > 0) ? (ida->size * sizeof(ulong_t)) : sizeof(ulong_t); | ||||
| 
 | ||||
|   ida->main_bmap = malloc(__get_main_bmap_size(ida)); | ||||
|   if (!ida->main_bmap) { | ||||
|     goto error; | ||||
|   } | ||||
| 
 | ||||
| #if 0 | ||||
|   if (lockable && ida_lock_init(&ida->lock)) | ||||
|     goto error; | ||||
| #endif | ||||
|   ida->lck = 0; /* cutty, we don't use the lockable due to the very arch specifics */ | ||||
| 
 | ||||
|   memset(ida->main_bmap, 0, __get_main_bmap_size(ida)); | ||||
|   ida->max_id = idx_max; | ||||
|   return 0; | ||||
| 
 | ||||
|   error: | ||||
|   if (ida->ids_bmap) { | ||||
|     free(ida->ids_bmap); | ||||
|   } | ||||
|   if (ida->main_bmap) { | ||||
|     free(ida->main_bmap); | ||||
|   } | ||||
| 
 | ||||
|   return err; | ||||
| } | ||||
| 
 | ||||
| void idx_allocator_destroy(idx_allocator_t *ida) | ||||
| { | ||||
|   if (ida->ids_bmap != NULL) | ||||
|     free(ida->ids_bmap); | ||||
| 
 | ||||
|   free(ida->main_bmap); | ||||
| 
 | ||||
|   if (ida_lockable(ida)) | ||||
|     ida_lock_destroy(&ida->lock); | ||||
| } | ||||
| 
 | ||||
| @ -1,13 +0,0 @@ | ||||
| prefix=@prefix@ | ||||
| exec_prefix=@exec_prefix@ | ||||
| libdir=@libdir@ | ||||
| datarootdir=@datarootdir@ | ||||
| datadir=@datadir@ | ||||
| includedir=@includedir@ | ||||
| 
 | ||||
| Name: libtdata | ||||
| Description: Data structures C implementation. | ||||
| Version: @LIBTDATA_VERSION@ | ||||
| Requires:  | ||||
| Libs: -L${libdir} -ltdata | ||||
| Cflags: -I${includedir} | ||||
							
								
								
									
										174
									
								
								tdata/lslist.c
									
									
									
									
									
								
							
							
						
						
									
										174
									
								
								tdata/lslist.c
									
									
									
									
									
								
							| @ -1,174 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * lslist.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <tdata/macro.h> | ||||
| #include <tdata/usrtc.h> | ||||
| 
 | ||||
| #define list_first_priv(L) ((L)->sentinel.next) | ||||
| #define list_last_priv(L) ((L)->sentinel.prev) | ||||
| #define list_null_priv(L) (&(L)->sentinel) | ||||
| 
 | ||||
| /*function prototypes*/ | ||||
| static void list_init(usrtc_t *); | ||||
| static void list_insert(usrtc_t *,usrtc_node_t *,const void *); | ||||
| static void list_delete(usrtc_t *,usrtc_node_t *); | ||||
| static usrtc_node_t *list_lookup(usrtc_t *,const void *); | ||||
| static usrtc_node_t *list_lower_bound(usrtc_t *,const void *); | ||||
| static usrtc_node_t *list_upper_bound(usrtc_t *,const void *); | ||||
| static usrtc_node_t *list_first(usrtc_t *); | ||||
| static usrtc_node_t *list_last(usrtc_t *); | ||||
| static usrtc_node_t *list_next(usrtc_t *, usrtc_node_t *); | ||||
| static usrtc_node_t *list_prev(usrtc_t *, usrtc_node_t *); | ||||
| static void list_convert_to_list(usrtc_t *); | ||||
| static void list_convert_from_list(usrtc_t *); | ||||
| 
 | ||||
| usrtc_functions_t usrtc_list_fu = { | ||||
|     list_init, | ||||
|     list_insert, | ||||
|     list_delete, | ||||
|     list_lookup, | ||||
|     list_lower_bound, | ||||
|     list_upper_bound, | ||||
|     list_first, | ||||
|     list_last, | ||||
|     list_next, | ||||
|     list_prev, | ||||
|     list_convert_to_list, | ||||
|     list_convert_from_list, | ||||
|     usrtc_lst | ||||
| }; | ||||
| 
 | ||||
| static void insert_before(usrtc_t *,usrtc_node_t *,usrtc_node_t *); | ||||
| 
 | ||||
| /*implementation*/ | ||||
| static void list_init(usrtc_t *us) | ||||
| { | ||||
|   us->sentinel.next=&us->sentinel; | ||||
|   us->sentinel.prev=&us->sentinel; | ||||
| } | ||||
| 
 | ||||
| static void list_insert(usrtc_t *us,usrtc_node_t *newnode,const void *key) | ||||
| { | ||||
|   usrtc_node_t *succ; | ||||
|    | ||||
|   newnode->key=key; | ||||
|    | ||||
|   for(succ=list_first_priv(us);succ!=list_null_priv(us);succ=succ->next) { | ||||
|     if(us->compare(succ->key,key)>0) | ||||
|       break; | ||||
|   } | ||||
|    | ||||
|   insert_before(us,newnode,succ); | ||||
| } | ||||
| 
 | ||||
| static void list_delete(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *pred=node->prev; | ||||
|   usrtc_node_t *succ=node->next; | ||||
|    | ||||
|   pred->next=succ; | ||||
|   succ->prev=pred; | ||||
|   /*check node count*/ | ||||
|   us->nodecount--; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_lookup(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *node; | ||||
|    | ||||
|   for(node=list_first_priv(us);node!=list_null_priv(us);node=node->next) { | ||||
|     if(us->compare(node->key,key)==0) | ||||
|       return node; | ||||
|   } | ||||
|    | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_lower_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *node; | ||||
|    | ||||
|   for(node=list_first_priv(us);node!=list_null_priv(us);node=node->next) { | ||||
|     if(us->compare(node->key,key) >= 0) | ||||
|       return node; | ||||
|   } | ||||
|    | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_upper_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *node; | ||||
|    | ||||
|   for(node=list_first_priv(us);node!=list_null_priv(us);node=node->prev) { | ||||
|     if(us->compare(node->key,key) >= 0) | ||||
|       return node; | ||||
|   } | ||||
|    | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_first(usrtc_t *us) | ||||
| { | ||||
|   return (list_first_priv(us) == list_null_priv(us)) ? 0 : list_first_priv(us); | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_last(usrtc_t *us) | ||||
| { | ||||
|   return (list_last_priv(us) == list_null_priv(us)) ? 0 : list_last_priv(us); | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_next(usrtc_t *us, usrtc_node_t *node) | ||||
| { | ||||
|   return (node->next == list_null_priv(us)) ? 0 : node->next; | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *list_prev(usrtc_t *us, usrtc_node_t *node) | ||||
| { | ||||
|   return (node->prev == list_null_priv(us)) ? 0 : node->prev; | ||||
| } | ||||
| 
 | ||||
| static void list_convert_to_list(usrtc_t *us) | ||||
| { | ||||
|   /*dummy*/ | ||||
| } | ||||
| 
 | ||||
| static void list_convert_from_list(usrtc_t *us) | ||||
| { | ||||
|   /*dummy*/ | ||||
| } | ||||
| 
 | ||||
| /*internal function*/ | ||||
| static void insert_before(usrtc_t *us,usrtc_node_t *newnode,usrtc_node_t *succ) | ||||
| { | ||||
|   usrtc_node_t *pred=succ->prev; | ||||
|    | ||||
|   newnode->prev=pred; | ||||
|   newnode->next=succ; | ||||
|    | ||||
|   pred->next=newnode; | ||||
|   succ->prev=newnode; | ||||
|    | ||||
|   /*TODO: check for maxcount*/ | ||||
|   us->nodecount++; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										310
									
								
								tdata/redblack.c
									
									
									
									
									
								
							
							
						
						
									
										310
									
								
								tdata/redblack.c
									
									
									
									
									
								
							| @ -1,310 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * redblack.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <tdata/macro.h> | ||||
| #include <tdata/tree.h> | ||||
| 
 | ||||
| #define color usrtc_impldata.usrtc_rb_color | ||||
| 
 | ||||
| /*function prototypes*/ | ||||
| static void redblack_init(usrtc_t *); | ||||
| static void redblack_insert(usrtc_t *, usrtc_node_t *, const void *); | ||||
| static void redblack_delete(usrtc_t *, usrtc_node_t *); | ||||
| static void redblack_convert_from_list(usrtc_t *); | ||||
| 
 | ||||
| usrtc_functions_t usrtc_redblack_fu = { | ||||
|     redblack_init, | ||||
|     redblack_insert, | ||||
|     redblack_delete, | ||||
|     usrtc_tree_lookup, | ||||
|     usrtc_tree_lower_bound, | ||||
|     usrtc_tree_upper_bound, | ||||
|     usrtc_tree_first, | ||||
|     usrtc_tree_last, | ||||
|     usrtc_tree_next, | ||||
|     usrtc_tree_prev, | ||||
|     usrtc_tree_convert_to_list, | ||||
|     redblack_convert_from_list, | ||||
|     usrtc_bst | ||||
| }; | ||||
| 
 | ||||
| /*implementation*/ | ||||
| static void redblack_init(usrtc_t *us) | ||||
| { | ||||
|   usrtc_tree_init(us); | ||||
|   us->sentinel.color = usrtc_black; | ||||
| } | ||||
| 
 | ||||
| static void redblack_insert(usrtc_t *us, usrtc_node_t *node, const void *key) | ||||
| { | ||||
|   usrtc_node_t *parent; | ||||
| 
 | ||||
|   /* simple bt insert */ | ||||
|   usrtc_tree_insert(us,node,key); | ||||
| 
 | ||||
|   /* implementation specific insert */ | ||||
|   node->color = usrtc_red; | ||||
|   parent=node->parent; | ||||
|    | ||||
|   while(parent->color==usrtc_red) { | ||||
|     usrtc_node_t *grandpa=parent->parent; | ||||
|      | ||||
|     if(parent==grandpa->left) { | ||||
|       usrtc_node_t *uncle=grandpa->right; | ||||
|       if(uncle->color==usrtc_red) { /*red parent->red uncle*/ | ||||
| 	parent->color=usrtc_black; | ||||
| 	uncle->color=usrtc_black; | ||||
| 	grandpa->color=usrtc_red; | ||||
| 	node=grandpa; | ||||
| 	parent=grandpa->parent; | ||||
|       } else { /*red parent->black uncle */ | ||||
| 	if(node==parent->right) { | ||||
| 	  usrtc_tree_rotate_left(node,parent); | ||||
| 	  parent=node; | ||||
| 	  if(grandpa!=parent->parent) | ||||
| 	    return; | ||||
| 	} | ||||
| 	parent->color=usrtc_black; | ||||
| 	grandpa->color=usrtc_red; | ||||
| 	usrtc_tree_rotate_right(parent,grandpa); | ||||
| 	break; | ||||
|       } | ||||
|     } else { /*ooh,parent == parent->parent->right*/ | ||||
|       usrtc_node_t *uncle=grandpa->left; | ||||
|       if(uncle->color==usrtc_red) { | ||||
| 	parent->color=usrtc_black; | ||||
| 	uncle->color=usrtc_black; | ||||
| 	grandpa->color=usrtc_red; | ||||
| 	node=grandpa; | ||||
| 	parent=grandpa->parent; | ||||
|       } else { | ||||
| 	if(node==parent->left) { | ||||
| 	  usrtc_tree_rotate_right(node,parent); | ||||
| 	  parent=node; | ||||
| 
 | ||||
| 	  if(grandpa!=parent->parent) | ||||
| 	    return; | ||||
| 	} | ||||
| 	parent->color=usrtc_black; | ||||
| 	grandpa->color=usrtc_red; | ||||
| 	usrtc_tree_rotate_left(parent,grandpa); | ||||
| 	break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   tree_root_priv(us)->color=usrtc_black; | ||||
| } | ||||
| 
 | ||||
| static void redblack_delete(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *swap; | ||||
|   usrtc_node_t *child; | ||||
|   usrtc_rb_color_t savecolor; | ||||
| 
 | ||||
|   /*basic bt delete*/ | ||||
|   usrtc_tree_delete(us,node,&swap,&child); | ||||
|      | ||||
|   /*implementation specific deletion*/ | ||||
|   savecolor=node->color; | ||||
|   node->color=swap->color; | ||||
|   swap->color=savecolor; | ||||
| 
 | ||||
|   if(node->color==usrtc_black) { /*black*/ | ||||
|     usrtc_node_t *parent; | ||||
|     usrtc_node_t *sister; | ||||
| 
 | ||||
|     tree_root_priv(us)->color=usrtc_red; | ||||
| 
 | ||||
|     while(child->color==usrtc_black) { | ||||
|       parent=child->parent; | ||||
|       if(child==parent->left) { | ||||
| 	sister=parent->right; | ||||
| 	if(sister==tree_null_priv(us)) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if(sister->color==usrtc_red) { | ||||
| 	  sister->color=usrtc_black; | ||||
| 	  parent->color=usrtc_red; | ||||
| 	  usrtc_tree_rotate_left(sister,parent); | ||||
| 	  sister=parent->right; | ||||
| 
 | ||||
| 	  if(sister==tree_null_priv(us)) | ||||
| 	    return; | ||||
| 	} | ||||
| 	if(sister->left->color==usrtc_black && sister->right->color==usrtc_black) { | ||||
| 	  sister->color=usrtc_red; | ||||
| 	  child=parent; | ||||
| 	} else { | ||||
| 	  if(sister->right->color==usrtc_black) { | ||||
| 	    if(sister->left->color!=usrtc_red) | ||||
| 	      return; | ||||
| 
 | ||||
| 	    sister->left->color=usrtc_black; | ||||
| 	    sister->color=usrtc_red; | ||||
| 	    usrtc_tree_rotate_right(sister->left,sister); | ||||
| 	    sister=parent->right; | ||||
| 
 | ||||
| 	    if(sister==tree_null_priv(us)) | ||||
| 	      return; | ||||
| 	  } | ||||
| 	  sister->color=parent->color; | ||||
| 	  sister->right->color=usrtc_black; | ||||
| 	  parent->color=usrtc_black; | ||||
| 	  usrtc_tree_rotate_left(sister,parent); | ||||
| 	  break; | ||||
| 	} | ||||
|       } else {	/*!child == child->parent->right*/ | ||||
| 	if(child!=parent->right) | ||||
| 	  return; | ||||
| 
 | ||||
| 	sister=parent->left; | ||||
| 
 | ||||
| 	if(sister==tree_null_priv(us)) | ||||
| 	  return; | ||||
| 
 | ||||
| 	if(sister->color==usrtc_red) { | ||||
| 	  sister->color=usrtc_black; | ||||
| 	  parent->color=usrtc_red; | ||||
| 	  usrtc_tree_rotate_right(sister,parent); | ||||
| 	  sister = parent->left; | ||||
| 
 | ||||
| 	  if(sister==tree_null_priv(us)) | ||||
| 	    return; | ||||
| 	} | ||||
| 	if(sister->right->color==usrtc_black && sister->left->color==usrtc_black) { | ||||
| 	  sister->color=usrtc_red; | ||||
| 	  child=parent; | ||||
| 	} else { | ||||
| 	  if(sister->left->color == usrtc_black) { | ||||
| 	    if(sister->right->color!=usrtc_red) | ||||
| 	      return; | ||||
| 
 | ||||
| 	    sister->right->color=usrtc_black; | ||||
| 	    sister->color=usrtc_red; | ||||
| 	    usrtc_tree_rotate_left(sister->right, sister); | ||||
| 	    sister=parent->left; | ||||
| 
 | ||||
| 	    if(sister==tree_null_priv(us)) | ||||
| 	      return; | ||||
| 	  } | ||||
| 	  sister->color=parent->color; | ||||
| 	  sister->left->color=usrtc_black; | ||||
| 	  parent->color=usrtc_black; | ||||
| 	  usrtc_tree_rotate_right(sister,parent); | ||||
| 	  break; | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     child->color=usrtc_black; | ||||
|     tree_root_priv(us)->color=usrtc_black; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void redblack_convert_from_list(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *tree[TREE_DEPTH_MAX] = { NULL }; | ||||
|   usrtc_node_t *curr; | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *next; | ||||
|   usrtc_node_t *complete=NULL; | ||||
|   usrtc_count_t fullcount=(usrtc_count_t)USRTC_COUNT_T_MAX; | ||||
|   usrtc_count_t nodecount=us->nodecount; | ||||
|   usrtc_count_t botrowcount; | ||||
|   unsigned int baselevel=0; | ||||
|   unsigned int level=0; | ||||
|   unsigned int i; | ||||
| 
 | ||||
|   if(usrtc_red!=0 && usrtc_black!=1) | ||||
|     return; | ||||
| 
 | ||||
|   while(fullcount>=nodecount && fullcount) /*calc*/ | ||||
|     fullcount >>= 1; | ||||
| 
 | ||||
|   botrowcount=nodecount-fullcount; | ||||
| 
 | ||||
|   for(curr=nil->next;curr!=nil;curr=next) { | ||||
|     next=curr->next; | ||||
| 
 | ||||
|     if(complete==NULL && botrowcount--==0) { | ||||
|       baselevel=level=1; | ||||
|       complete=tree[0]; | ||||
| 
 | ||||
|       if(complete!=NULL) { | ||||
| 	tree[0]=NULL; | ||||
| 	complete->right=nil; | ||||
| 	while(tree[level]!=0) { | ||||
| 	  tree[level]->right=complete; | ||||
| 	  complete->parent=tree[level]; | ||||
| 	  complete=tree[level]; | ||||
| 	  tree[level++]=NULL; | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if(complete==NULL) { | ||||
|       curr->left=nil; | ||||
|       curr->right=nil; | ||||
|       curr->color=level%2; | ||||
|       complete=curr; | ||||
| 
 | ||||
|       if(level!=baselevel) | ||||
| 	return; | ||||
| 
 | ||||
|       while(tree[level]!=NULL) { | ||||
| 	tree[level]->right=complete; | ||||
| 	complete->parent=tree[level]; | ||||
| 	complete=tree[level]; | ||||
| 	tree[level++]=NULL; | ||||
|       } | ||||
|     } else { | ||||
|       curr->left=complete; | ||||
|       curr->color=(level+1)%2; | ||||
|       complete->parent=curr; | ||||
|       tree[level]=curr; | ||||
|       complete=NULL; | ||||
|       level=baselevel; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if(complete==NULL) | ||||
|     complete=nil; | ||||
| 
 | ||||
|   for (i=0;i<TREE_DEPTH_MAX;i++) { | ||||
|     if (tree[i]!=NULL) { | ||||
|       tree[i]->right=complete; | ||||
|       complete->parent=tree[i]; | ||||
|       complete=tree[i]; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   nil->right=nil; | ||||
|   nil->left=complete; | ||||
|   nil->color=usrtc_black; | ||||
|   complete->parent=nil; | ||||
|   complete->color=usrtc_black; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										143
									
								
								tdata/splay.c
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								tdata/splay.c
									
									
									
									
									
								
							| @ -1,143 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * splay.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <tdata/macro.h> | ||||
| #include <tdata/tree.h> | ||||
| 
 | ||||
| /*prototypes*/ | ||||
| static void splay_insert(usrtc_t *,usrtc_node_t *,const void *); | ||||
| static void splay_delete(usrtc_t *,usrtc_node_t *); | ||||
| static usrtc_node_t *splay_lookup(usrtc_t *,const void *); | ||||
| 
 | ||||
| usrtc_functions_t usrtc_splay_fu = { | ||||
|     usrtc_tree_init, | ||||
|     splay_insert, | ||||
|     splay_delete, | ||||
|     splay_lookup, | ||||
|     usrtc_tree_lower_bound, | ||||
|     usrtc_tree_upper_bound, | ||||
|     usrtc_tree_first, | ||||
|     usrtc_tree_last, | ||||
|     usrtc_tree_next, | ||||
|     usrtc_tree_prev, | ||||
|     usrtc_tree_convert_to_list, | ||||
|     usrtc_tree_convert_from_list, | ||||
|     usrtc_bst | ||||
| }; | ||||
| 
 | ||||
| static void right_zig_zig(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); | ||||
| static void left_zig_zig(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); | ||||
| static void right_zig_zag(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); | ||||
| static void left_zig_zag(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); | ||||
| static void splay_node(usrtc_t *,usrtc_node_t *); | ||||
| 
 | ||||
| /*implementation*/ | ||||
| 
 | ||||
| static void splay_insert(usrtc_t *us,usrtc_node_t *node,const void *key) | ||||
| { | ||||
|   usrtc_tree_insert(us,node,key); | ||||
|    | ||||
|   while(node!=tree_root_priv(us)) | ||||
|     splay_node(us,node); | ||||
| } | ||||
| 
 | ||||
| static void splay_delete(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *dummy; | ||||
|   usrtc_tree_delete(us,node,&dummy,&dummy); | ||||
| } | ||||
| 
 | ||||
| static usrtc_node_t *splay_lookup(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *node=usrtc_tree_lookup(us,key); | ||||
|    | ||||
|   if(node) | ||||
|     while(node!=tree_root_priv(us)) | ||||
|       splay_node(us,node); | ||||
|    | ||||
|   return node; | ||||
| } | ||||
| 
 | ||||
| static void right_zig_zig(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) | ||||
| { | ||||
|   usrtc_tree_rotate_right(parent,grandpa); | ||||
|   usrtc_tree_rotate_right(child,parent); | ||||
| } | ||||
| 
 | ||||
| static void left_zig_zig(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) | ||||
| { | ||||
|   usrtc_tree_rotate_left(parent,grandpa); | ||||
|   usrtc_tree_rotate_left(child,parent); | ||||
| } | ||||
| 
 | ||||
| static void right_zig_zag(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) | ||||
| { | ||||
|   usrtc_tree_rotate_right(child,parent); | ||||
|   usrtc_tree_rotate_left(child,grandpa); | ||||
| } | ||||
| 
 | ||||
| static void left_zig_zag(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) | ||||
| { | ||||
|   usrtc_tree_rotate_left(child,parent); | ||||
|   usrtc_tree_rotate_right(child,grandpa); | ||||
| } | ||||
| 
 | ||||
| static void splay_node(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *parent=node->parent; | ||||
|    | ||||
|   if(parent->left==node) { | ||||
|     if(parent==root) { | ||||
|       usrtc_tree_rotate_right(node,parent); | ||||
|     } else { | ||||
|       usrtc_node_t *grandpa=parent->parent; | ||||
|        | ||||
|       if(grandpa->left==parent) | ||||
| 	right_zig_zig(node,parent,grandpa); | ||||
|       else { | ||||
| 	if(grandpa->right!=parent) | ||||
| 	  return; | ||||
| 
 | ||||
| 	right_zig_zag(node,parent,grandpa); | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     if(parent->right!=node) | ||||
|       return; | ||||
|      | ||||
|     if(parent==root) { | ||||
|       usrtc_tree_rotate_left(node,parent); | ||||
|     } else { | ||||
|       usrtc_node_t *grandpa=parent->parent; | ||||
|        | ||||
|       if(grandpa->right==parent) { | ||||
| 	left_zig_zig(node,parent,grandpa); | ||||
|       } else { | ||||
| 	if(grandpa->left!=parent) | ||||
| 	  return; | ||||
| 
 | ||||
| 	left_zig_zag(node,parent,grandpa); | ||||
|       } | ||||
|     } | ||||
|      | ||||
|   } | ||||
| } | ||||
							
								
								
									
										492
									
								
								tdata/tree.c
									
									
									
									
									
								
							
							
						
						
									
										492
									
								
								tdata/tree.c
									
									
									
									
									
								
							| @ -1,492 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * tree.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <tdata/macro.h> | ||||
| #include <tdata/tree.h> | ||||
| 
 | ||||
| /*local functions prototypes*/ | ||||
| static void tree_delete(usrtc_t *, usrtc_node_t *); | ||||
| 
 | ||||
| usrtc_functions_t usrtc_tree_fu = { | ||||
|     usrtc_tree_init, | ||||
|     usrtc_tree_insert, | ||||
|     tree_delete, | ||||
|     usrtc_tree_lookup, | ||||
|     usrtc_tree_lower_bound, | ||||
|     usrtc_tree_upper_bound, | ||||
|     usrtc_tree_first, | ||||
|     usrtc_tree_last, | ||||
|     usrtc_tree_next, | ||||
|     usrtc_tree_prev, | ||||
|     usrtc_tree_convert_to_list, | ||||
|     usrtc_tree_convert_from_list, | ||||
|     usrtc_bst | ||||
| }; | ||||
| 
 | ||||
| /*implementation*/ | ||||
| 
 | ||||
| void usrtc_tree_init(usrtc_t *us) | ||||
| { | ||||
|   us->sentinel.left=&us->sentinel; | ||||
|   us->sentinel.right=&us->sentinel; | ||||
|   us->sentinel.parent=&us->sentinel; | ||||
| 
 | ||||
|   us->sentinel.impl_specific.usrtc_dummy=0; | ||||
|   us->sentinel.data=0; | ||||
|   us->sentinel.key=0; | ||||
| } | ||||
| 
 | ||||
| void usrtc_tree_insert(usrtc_t *us,usrtc_node_t *node,const void *key) | ||||
| { | ||||
|   usrtc_node_t *where=tree_root_priv(us); | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *parent=nil; | ||||
|   long res=-1; | ||||
| 
 | ||||
|   node->key=key; | ||||
| 
 | ||||
|   while(where!=nil) { | ||||
|     parent=where; | ||||
|     res=us->compare(key,where->key); | ||||
| 
 | ||||
|     if(us->dupes_allowed && !res) /*trying to put duplicate to the disabled dupe tree*/ | ||||
|       return; | ||||
| 
 | ||||
|     if(res<0) | ||||
|       where=where->left; | ||||
|     else | ||||
|       where=where->right; | ||||
|   } | ||||
| 
 | ||||
|   /*assert(where==nil);*/ | ||||
| 
 | ||||
|   if(res<0) | ||||
|     parent->left=node; | ||||
|   else | ||||
|     parent->right=node; | ||||
| 
 | ||||
|   node->parent=parent; | ||||
|   node->left=nil; | ||||
|   node->right=nil; | ||||
| 
 | ||||
|   us->nodecount++; | ||||
| } | ||||
| 
 | ||||
| void usrtc_tree_delete(usrtc_t *us,usrtc_node_t *node,usrtc_node_t **pswap,usrtc_node_t **pchild) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us);  | ||||
|   usrtc_node_t *child; | ||||
|   usrtc_node_t *delparent=node->parent; | ||||
|   usrtc_node_t *next=node; | ||||
|   usrtc_node_t *nextparent; | ||||
| 
 | ||||
|   if(node->left!=nil && node->right!=nil) { | ||||
|     next=usrtc_tree_next(us,node); | ||||
|     nextparent=next->parent; | ||||
| 
 | ||||
|     /*if(next!=nil && next->parent!=nil && next->parent==nil)
 | ||||
|       return;*/ | ||||
| 
 | ||||
|     child=next->right; | ||||
|     child->parent=nextparent; | ||||
| 
 | ||||
|     if(nextparent->left==next) | ||||
|       nextparent->left=child; | ||||
|     else { | ||||
|       //if(nextparent->right!=next)
 | ||||
|       //return;
 | ||||
|       nextparent->right=child; | ||||
|     } | ||||
| 
 | ||||
|     next->parent=delparent; | ||||
|     next->left=node->left; | ||||
|     next->right=node->right; | ||||
|     next->left->parent=next; | ||||
|     next->right->parent=next; | ||||
| 
 | ||||
|     if(delparent->left==node) { | ||||
|       delparent->left=next; | ||||
|     } else { | ||||
|       //if(delparent->right!=node)
 | ||||
|       //	return;
 | ||||
|       delparent->right = next; | ||||
|     } | ||||
| 
 | ||||
|   } else { | ||||
|     /*if(node==nil)
 | ||||
|       return; | ||||
|     if(node->left!=nil && node->right!=nil) | ||||
|     return;*/ | ||||
| 
 | ||||
|     child=(node->left!=nil) ? node->left : node->right; | ||||
| 
 | ||||
|     child->parent=delparent=node->parent; | ||||
| 
 | ||||
|     if(node==delparent->left) { | ||||
|       delparent->left=child; | ||||
|     } else { | ||||
|       /*if(node!=delparent->right)
 | ||||
| 	return;*/ | ||||
|       delparent->right=child; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   node->parent=0; | ||||
|   node->right=0; | ||||
|   node->left=0; | ||||
| 
 | ||||
|   us->nodecount--; | ||||
| 
 | ||||
|   *pswap = next; | ||||
|   *pchild = child; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_lookup(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *saved; | ||||
|   long res; | ||||
| 
 | ||||
|   while (root!=nil) { | ||||
|     res=us->compare(key,root->key); | ||||
|     if(res<0) | ||||
|       root=root->left; | ||||
|     else if(res>0) | ||||
|       root=root->right; | ||||
|     else { | ||||
|       if(!us->dupes_allowed) | ||||
| 				return root; /*no duplicates*/ | ||||
|       else { /*duplicate, then find left occurence*/ | ||||
| 				do { | ||||
| 					saved=root; | ||||
| 					root=root->left; | ||||
| 					while(root!=nil && us->compare(key,root->key)) | ||||
| 						root=root->right; | ||||
| 				} while(root!=nil); | ||||
| 				return saved; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_lower_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *tentative=NULL; | ||||
|   long res; | ||||
| 
 | ||||
|   while(root!=nil) { | ||||
|     res=us->compare(key,root->key); | ||||
| 
 | ||||
|     if(res>0) { | ||||
|       root=root->right; | ||||
|     } else if(res<0) { | ||||
|       tentative=root; | ||||
|       root=root->left; | ||||
|     } else { | ||||
|       if (!us->dupes_allowed) | ||||
| 				return root; | ||||
|       else { | ||||
| 				tentative=root; | ||||
| 				root=root->left; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return tentative; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_upper_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *tentative=NULL; | ||||
|   long res; | ||||
| 
 | ||||
|   while(root!=nil) { | ||||
|     res=us->compare(key,root->key); | ||||
| 
 | ||||
|     if(res>0) { | ||||
|       root=root->left; | ||||
|     } else if(res<0) { | ||||
|       tentative=root; | ||||
|       root=root->right; | ||||
|     } else { | ||||
|       if (!us->dupes_allowed) | ||||
| 				return root; | ||||
|       else { | ||||
| 				tentative=root; | ||||
| 				root=root->right; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return tentative; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_first(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *left; | ||||
| 
 | ||||
|   if(root!=nil) | ||||
|     while((left=root->left)!=nil) | ||||
|       root=left; | ||||
| 
 | ||||
|   return (root==nil) ? NULL : root; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_last(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *root=tree_root_priv(us); | ||||
|   usrtc_node_t *right; | ||||
| 
 | ||||
|   if(root!=nil) | ||||
|     while((right=root->right)!=nil) | ||||
|       root=right; | ||||
| 
 | ||||
|   return (root==nil) ? NULL : root; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_next(usrtc_t *us, usrtc_node_t *curr) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *parent; | ||||
|   usrtc_node_t *left; | ||||
| 
 | ||||
|   if(curr->right!=nil) { | ||||
|     curr=curr->right; | ||||
|     while((left=curr->left)!=nil) | ||||
|       curr=left; | ||||
|     return curr; | ||||
|   } | ||||
| 
 | ||||
|   parent=curr->parent; | ||||
| 
 | ||||
|   while(parent!=nil && curr==parent->right) { | ||||
|     curr=parent; | ||||
|     parent=curr->parent; | ||||
|   } | ||||
| 
 | ||||
|   return (parent==nil) ? NULL : parent; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_tree_prev(usrtc_t *us, usrtc_node_t *curr) | ||||
| { | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *parent; | ||||
|   usrtc_node_t *right; | ||||
| 
 | ||||
|   if(curr->left!=nil) { | ||||
|     curr=curr->left; | ||||
|     while((right=curr->right)!=nil) | ||||
|       curr=right; | ||||
|     return curr; | ||||
|   } | ||||
| 
 | ||||
|   parent=curr->parent; | ||||
| 
 | ||||
|   while(parent!=nil && curr==parent->left) { | ||||
|     curr=parent; | ||||
|     parent=curr->parent; | ||||
|   } | ||||
| 
 | ||||
|   return (parent==nil) ? NULL : parent; | ||||
| } | ||||
| 
 | ||||
| /*uff, convertation between trees and lists*/ | ||||
| void usrtc_tree_convert_to_list(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *node; | ||||
|   usrtc_node_t tempsentinel; | ||||
|   usrtc_node_t *nil=&tempsentinel; | ||||
|   usrtc_node_t *tail,*next; | ||||
|   usrtc_node_t *treenil=tree_null_priv(us); | ||||
| 
 | ||||
|   if(us->nodecount==0) /* no nodes */ | ||||
|     return; | ||||
| 
 | ||||
|   tempsentinel.next=nil; | ||||
|   tempsentinel.prev=nil; | ||||
| 
 | ||||
|   /* two passes */ | ||||
|   for(tail=nil,node=usrtc_tree_first(us);node!=0;tail=node,node=next) { | ||||
|     next=usrtc_tree_next(us,node); | ||||
|     node->prev=tail; | ||||
|   } | ||||
| 
 | ||||
|   nil->prev=tail; | ||||
| 
 | ||||
|   for(tail=nil,node=nil->prev;node!=nil;tail=node,node=node->prev) | ||||
|     node->next=tail; | ||||
| 
 | ||||
|   nil->next=tail; | ||||
| 
 | ||||
|   us->sentinel.next=tempsentinel.next; | ||||
|   us->sentinel.prev=tempsentinel.prev; | ||||
|   us->sentinel.next->prev=treenil; | ||||
|   us->sentinel.prev->next=treenil; | ||||
| } | ||||
| 
 | ||||
| void usrtc_tree_convert_from_list(usrtc_t *us) | ||||
| { | ||||
|   usrtc_node_t *tree[TREE_DEPTH_MAX]={ 0 }; | ||||
|   usrtc_node_t *curr; | ||||
|   usrtc_node_t *nil=tree_null_priv(us); | ||||
|   usrtc_node_t *next; | ||||
|   usrtc_node_t *complete=NULL; | ||||
|   usrtc_count_t fullcount=(usrtc_count_t)USRTC_COUNT_T_MAX; | ||||
|   usrtc_count_t nodecount=us->nodecount; | ||||
|   usrtc_count_t botrowcount; | ||||
|   int baselevel=0; | ||||
|   int level=0; | ||||
|   int i=0; | ||||
| 
 | ||||
|   while (fullcount>=nodecount && fullcount) /* calc */ | ||||
|     fullcount>>=1; | ||||
| 
 | ||||
|   botrowcount=nodecount-fullcount; | ||||
| 
 | ||||
|   for(curr=nil->next;curr!=nil;curr=next) { | ||||
|     next=curr->next; | ||||
| 
 | ||||
|     if(complete==NULL && botrowcount-- ==0) { | ||||
|       baselevel=level=1; | ||||
|       complete=tree[0]; | ||||
| 
 | ||||
|       if(complete!=NULL) { | ||||
| 				tree[0]=0; | ||||
| 				complete->right=nil; | ||||
| 				while(tree[level]!=NULL) { | ||||
| 					tree[level]->right=complete; | ||||
| 					complete->parent=tree[level]; | ||||
| 					complete=tree[level]; | ||||
| 					tree[level++]=0; | ||||
| 				} | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if(complete==NULL) { | ||||
|       curr->left=nil; | ||||
|       curr->right=nil; | ||||
|       complete=curr; | ||||
| 
 | ||||
|       if(level!=baselevel) | ||||
| 				return; | ||||
|       while(tree[level]!=NULL) { | ||||
| 				tree[level]->right=complete; | ||||
| 				complete->parent=tree[level]; | ||||
| 				complete=tree[level]; | ||||
| 				tree[level++]=0; | ||||
|       } | ||||
|     } else { | ||||
|       curr->left=complete; | ||||
|       complete->parent=curr; | ||||
|       tree[level]=curr; | ||||
|       complete=NULL; | ||||
|       level=baselevel; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if(complete==NULL) | ||||
|     complete=nil; | ||||
| 
 | ||||
|   for(i=0;i<TREE_DEPTH_MAX;i++) { | ||||
|     if(tree[i]!=NULL) { | ||||
|       tree[i]->right=complete; | ||||
|       complete->parent=tree[i]; | ||||
|       complete=tree[i]; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   nil->right=nil; | ||||
|   nil->left=complete; | ||||
|   complete->parent=nil; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void usrtc_tree_rotate_left(usrtc_node_t *child,usrtc_node_t *parent) | ||||
| { | ||||
|   usrtc_node_t *leftgrandchild; | ||||
|   usrtc_node_t *grandpa; | ||||
| 
 | ||||
|   if(parent->right!=child) | ||||
|     return; | ||||
| 
 | ||||
|   child=parent->right; | ||||
|   parent->right=leftgrandchild=child->left; | ||||
|   leftgrandchild->parent=parent; | ||||
| 
 | ||||
|   child->parent=grandpa=parent->parent; | ||||
| 
 | ||||
|   if(parent==grandpa->left) { | ||||
|     grandpa->left=child; | ||||
|   } else { | ||||
|     if(parent!=grandpa->right) | ||||
|       return; | ||||
|     grandpa->right=child; | ||||
|   } | ||||
| 
 | ||||
|   child->left=parent; | ||||
|   parent->parent=child; | ||||
| } | ||||
| 
 | ||||
| void usrtc_tree_rotate_right(usrtc_node_t *child,usrtc_node_t *parent) | ||||
| { | ||||
|   usrtc_node_t *rightgrandchild; | ||||
|   usrtc_node_t *grandpa; | ||||
| 
 | ||||
|   if(parent->left!=child) | ||||
|     return; | ||||
| 
 | ||||
|   parent->left=rightgrandchild=child->right; | ||||
|   rightgrandchild->parent=parent; | ||||
| 
 | ||||
|   child->parent=grandpa=parent->parent; | ||||
| 
 | ||||
|   if(parent==grandpa->right) { | ||||
|     grandpa->right=child; | ||||
|   } else { | ||||
|     if(parent!=grandpa->left) | ||||
|       return; | ||||
|     grandpa->left=child; | ||||
|   } | ||||
| 
 | ||||
|   child->right=parent; | ||||
|   parent->parent=child; | ||||
| } | ||||
| 
 | ||||
| /* local functions */ | ||||
| static void tree_delete(usrtc_t *us, usrtc_node_t *node) | ||||
| { | ||||
|   usrtc_node_t *dummy; | ||||
| 
 | ||||
|   usrtc_tree_delete(us, node, &dummy, &dummy); | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										244
									
								
								tdata/usrtc.c
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								tdata/usrtc.c
									
									
									
									
									
								
							| @ -1,244 +0,0 @@ | ||||
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ | ||||
| /*
 | ||||
|  * usrtc.c | ||||
|  * Copyright (C) 2006, 2013 Alexander Vdolainen <avdolainen@zoho.com> | ||||
|  * Copyright (C) 2006-2013, 2014 Askele inc. <http://askele.com>
 | ||||
|  * | ||||
|  * libtdata is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 2.1 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * libtdata 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 Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <tdata/macro.h> | ||||
| 
 | ||||
| /* so, if you want to add your implementation of the data
 | ||||
|  * structure please add this here, like the following. | ||||
|  */ | ||||
| 
 | ||||
| #define MAX_IMPL  4 | ||||
| 
 | ||||
| extern usrtc_functions_t usrtc_list_fu; | ||||
| extern usrtc_functions_t usrtc_tree_fu; | ||||
| extern usrtc_functions_t usrtc_redblack_fu; | ||||
| extern usrtc_functions_t usrtc_splay_fu; | ||||
| extern usrtc_functions_t usrtc_avl_fu; | ||||
| 
 | ||||
| static usrtc_functions_t *impl_table[] = { | ||||
|   &usrtc_list_fu,&usrtc_tree_fu, | ||||
|   &usrtc_redblack_fu,&usrtc_splay_fu, | ||||
|   &usrtc_avl_fu }; | ||||
| 
 | ||||
| static usrtc_node_t *default_node_alloc(void *context) | ||||
| { | ||||
|   return malloc(sizeof *default_node_alloc(context)); | ||||
| } | ||||
| 
 | ||||
| static void default_node_free(void *context,usrtc_node_t *node) | ||||
| { | ||||
|   free(node); | ||||
| } | ||||
| 
 | ||||
| void usrtc_init(usrtc_t *us,int impl,usrtc_count_t maxcount,usrtc_compare_t compare) | ||||
| { | ||||
|   if(!us) | ||||
|     return; | ||||
|   if(impl>MAX_IMPL) | ||||
|     return; | ||||
| 
 | ||||
|   us->nodecount=0; | ||||
|   us->maxcount=maxcount; | ||||
|   us->dupes_allowed=0; | ||||
|   us->compare=compare; | ||||
|   us->node_alloc=default_node_alloc; | ||||
|   us->node_free=default_node_free; | ||||
|   us->context=0; | ||||
|   us->futable=impl_table[impl]; | ||||
|   us->futable->usrtc_init(us); | ||||
| } | ||||
| 
 | ||||
| usrtc_t *usrtc_create(int impl,usrtc_count_t maxcount,usrtc_compare_t compare) | ||||
| { | ||||
|   usrtc_t *newrtc=(usrtc_t*)malloc(sizeof *newrtc); | ||||
|    | ||||
|   if(newrtc) | ||||
|     usrtc_init(newrtc,impl,maxcount,compare); | ||||
|    | ||||
|   return newrtc; | ||||
| } | ||||
| 
 | ||||
| void usrtc_destroy(usrtc_t *us) | ||||
| { | ||||
|   /*assert(usrtc_isempty(us));*/ | ||||
|   if(!us) | ||||
|     return; | ||||
| 
 | ||||
|   free(us); | ||||
| } | ||||
| 
 | ||||
| void usrtc_convert_to(usrtc_t *us,int impl) | ||||
| { | ||||
|   if(impl_table[impl]==us->futable) | ||||
|     return; | ||||
| 
 | ||||
|   if(us->futable->usrtc_type==usrtc_bst && (impl==USRTC_BST || impl==USRTC_SPLAY)) { | ||||
|     us->futable=impl_table[impl]; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   us->futable->usrtc_convert_to_list(us); | ||||
|   us->futable=impl_table[impl]; | ||||
| 
 | ||||
|   if(impl_table[impl]->usrtc_type==usrtc_lst) | ||||
|     return; | ||||
| 
 | ||||
|   us->futable->usrtc_convert_from_list(us); | ||||
| } | ||||
| 
 | ||||
| usrtc_count_t usrtc_count(usrtc_t *us) | ||||
| { | ||||
|   return us->nodecount; | ||||
| } | ||||
| 
 | ||||
| int usrtc_isempty(usrtc_t *us) | ||||
| { | ||||
|   return us->nodecount == 0; | ||||
| } | ||||
| 
 | ||||
| int usrtc_isfull(usrtc_t *us) | ||||
| { | ||||
|   return us->nodecount == us->maxcount; | ||||
| } | ||||
| 
 | ||||
| int usrtc_alloc_insert(usrtc_t *us,const void *key,void *data) | ||||
| { | ||||
|   usrtc_node_t *newnode=us->node_alloc(us->context); | ||||
|    | ||||
|   if(newnode!=NULL) { | ||||
|     newnode->data=data; | ||||
|     us->futable->usrtc_insert(us,newnode,key); | ||||
|   } | ||||
|    | ||||
|   return newnode!=NULL; | ||||
| } | ||||
| 
 | ||||
| void usrtc_delete_free(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   us->futable->usrtc_delete(us,node); | ||||
|   us->node_free(us->context,node); | ||||
| } | ||||
| 
 | ||||
| void usrtc_set_allocator(usrtc_t *us,usrtc_node_alloc_t alloc,usrtc_node_free_t n_free,void *context) | ||||
| { | ||||
|   us->node_alloc=alloc; | ||||
|   us->node_free=n_free; | ||||
|   us->context=context; | ||||
| } | ||||
| 
 | ||||
| void usrtc_allow_dupes(usrtc_t *us) | ||||
| { | ||||
|   /*assert(us->nodecount == 0);*/ | ||||
|   if(!us->nodecount) | ||||
|     return; | ||||
| 
 | ||||
|   us->dupes_allowed=1; | ||||
| } | ||||
| 
 | ||||
| void usrtc_node_init(usrtc_node_t *node,void *data) | ||||
| { | ||||
|   node->data=data; | ||||
|   node->impl_specific.usrtc_dummy=0; | ||||
|   node->left=NULL; | ||||
|   node->right=NULL; | ||||
|   node->parent=NULL; | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_node_create(void *data) | ||||
| { | ||||
|   usrtc_node_t *newnode=(usrtc_node_t*)malloc(sizeof *newnode); | ||||
|    | ||||
|   if(newnode!=NULL) | ||||
|     newnode->data=data; | ||||
|    | ||||
|   return newnode; | ||||
| } | ||||
| 
 | ||||
| void usrtc_node_destroy(usrtc_node_t *node) | ||||
| { | ||||
|   free(node); | ||||
| } | ||||
| 
 | ||||
| void *usrtc_node_getdata(usrtc_node_t *node) | ||||
| { | ||||
|   return node->data; | ||||
| } | ||||
| 
 | ||||
| void usrtc_node_setdata(usrtc_node_t *node,void *data) | ||||
| { | ||||
|   node->data=data; | ||||
| } | ||||
| 
 | ||||
| const void *usrtc_node_getkey(usrtc_node_t *node) | ||||
| { | ||||
|   return node->key; | ||||
| } | ||||
| 
 | ||||
| void usrtc_insert(usrtc_t *us,usrtc_node_t *node,const void *key) | ||||
| { | ||||
|   us->futable->usrtc_insert(us,node,key); | ||||
| } | ||||
| 
 | ||||
| void usrtc_delete(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   us->futable->usrtc_delete(us,node); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_lookup(usrtc_t *us,const void *key) | ||||
| { | ||||
|   return us->futable->usrtc_lookup(us,key); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_lower_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   return us->futable->usrtc_lower_bound(us,key); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_upper_bound(usrtc_t *us,const void *key) | ||||
| { | ||||
|   return us->futable->usrtc_upper_bound(us,key); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_first(usrtc_t *us) | ||||
| { | ||||
|   return us->futable->usrtc_first(us); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_last(usrtc_t *us) | ||||
| { | ||||
|   return us->futable->usrtc_last(us); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_next(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   return us->futable->usrtc_next(us,node); | ||||
| } | ||||
| 
 | ||||
| usrtc_node_t *usrtc_prev(usrtc_t *us,usrtc_node_t *node) | ||||
| { | ||||
|   return us->futable->usrtc_prev(us,node); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user