Initial commit

All of the files from the tarball downloaded from SourceForge are
being checked in so there's a record of the changes made compared
to it (since I can't find the libcfu source repository). The
generated files will be removed in the following commit.
This commit is contained in:
Matthew Brush 2013-03-04 01:39:33 -08:00
commit f660e3460a
55 changed files with 25776 additions and 0 deletions

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
libcds was written by Don Owens <don@owensnet.com>

33
COPYING Normal file
View File

@ -0,0 +1,33 @@
Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

8
ChangeLog Normal file
View File

@ -0,0 +1,8 @@
Version 0.03
* Added command-line option processing
* Added libcfu-config
* Added a map function to cfulist: cfulist_map()
* Added cfulist_new_with_free_fn()
Version 0.02
* Fixed build problems on FreeBSD
* Corrected missing info direntry in the docs

229
INSTALL Normal file
View File

@ -0,0 +1,229 @@
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
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
you can run in the future to recreate the current configuration, and a
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.)
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
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
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only 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. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. 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
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.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
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:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
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 must use a version of `make' that
supports the `VPATH' variable, such as 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 `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have 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 reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' 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.
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'.
Optional Features
=================
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
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.
Specifying the System Type
==========================
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
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:
CPU-COMPANY-SYSTEM
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
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option 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'.
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.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
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:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--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
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--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
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

12
Makefile.am Normal file
View File

@ -0,0 +1,12 @@
SUBDIRS = src examples doc
if DEBUG
AM_CFLAGS = -Wall -W -Werror -DCFU_VERSION="\"@VERSION@\"" -DCFU_DEBUG=1
else
AM_CFLAGS = -Wall -W -Werror -DCFU_VERSION="\"@VERSION@\""
endif
LIBCFU_TYPE_u_int=@LIBCFU_TYPE_u_int@
INCLUDES = -I$(top_srcdir)/include
EXTRA_DIST = include/cfutypes.h.in include/cfu.h.in

554
Makefile.in Normal file
View File

@ -0,0 +1,554 @@
# Makefile.in generated by automake 1.9.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(top_srcdir)/configure \
$(top_srcdir)/include/cfu.h.in \
$(top_srcdir)/include/cfutypes.h.in AUTHORS COPYING ChangeLog \
INSTALL NEWS depcomp install-sh missing mkinstalldirs
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno configure.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES = include/cfutypes.h include/cfu.h
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
install-recursive installcheck-recursive installdirs-recursive \
pdf-recursive ps-recursive uninstall-info-recursive \
uninstall-recursive
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d $(distdir) \
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr $(distdir); }; }
DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUG_FALSE = @DEBUG_FALSE@
DEBUG_TRUE = @DEBUG_TRUE@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBCFU_TYPE_u_int = @LIBCFU_TYPE_u_int@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
SUBDIRS = src examples doc
@DEBUG_FALSE@AM_CFLAGS = -Wall -W -Werror -DCFU_VERSION="\"@VERSION@\""
@DEBUG_TRUE@AM_CFLAGS = -Wall -W -Werror -DCFU_VERSION="\"@VERSION@\"" -DCFU_DEBUG=1
INCLUDES = -I$(top_srcdir)/include
EXTRA_DIST = include/cfutypes.h.in include/cfu.h.in
all: all-recursive
.SUFFIXES:
am--refresh:
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
cd $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
cd $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
include/cfutypes.h: $(top_builddir)/config.status $(top_srcdir)/include/cfutypes.h.in
cd $(top_builddir) && $(SHELL) ./config.status $@
include/cfu.h: $(top_builddir)/config.status $(top_srcdir)/include/cfu.h.in
cd $(top_builddir) && $(SHELL) ./config.status $@
uninstall-info-am:
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
$(mkdir_p) $(distdir)/include
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(mkdir_p) "$(distdir)/$$subdir" \
|| exit 1; \
distdir=`$(am__cd) $(distdir) && pwd`; \
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
(cd $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$top_distdir" \
distdir="$$distdir/$$subdir" \
distdir) \
|| exit 1; \
fi; \
done
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r $(distdir)
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& cd $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
distuninstallcheck:
@cd $(distuninstallcheck_dir) \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
info: info-recursive
info-am:
install-data-am:
install-exec-am:
install-info: install-info-recursive
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-info-am
uninstall-info: uninstall-info-recursive
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
check-am clean clean-generic clean-recursive ctags \
ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \
dist-tarZ dist-zip distcheck distclean distclean-generic \
distclean-recursive distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-generic \
mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
uninstall uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

0
NEWS Normal file
View File

4
README Normal file
View File

@ -0,0 +1,4 @@
Libcfu is a library of thread-safe functions and data structures that
I have found useful. See the texinfo documentation for detailed
information.

4
acinclude.m4 Normal file
View File

@ -0,0 +1,4 @@
AC_DEFUN([LIBCFU_CHECK_TYPE], [
AC_CHECK_TYPE($1, LIBCFU_TYPE_$1="/* $1 is defined */",
LIBCFU_TYPE_$1="typedef $2 $1;")
])

1028
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

6860
configure vendored Executable file

File diff suppressed because it is too large Load Diff

59
configure.ac Normal file
View File

@ -0,0 +1,59 @@
AC_INIT(libcfu, 0.03)
AM_INIT_AUTOMAKE([dist-bzip2])
# AC_CONFIG_HEADERS(config.h)
LIBCFU_CHECK_TYPE(u_int, unsigned int)
AC_SUBST(LIBCFU_TYPE_u_int)
AC_PROG_CC
AC_PROG_RANLIB
dnl Check for pthread support
SAVECFLAGS="$CFLAGS"
SAVELIBS="$LIBS"
CFLAGS="-pthread $CFLAGS"
LIBS="-pthread $LIBS"
AC_CHECK_FUNC(pthread_mutex_init,,
CFLAGS="$SAVECFLAGS"
LIBS="$SAVELIBS"
AC_CHECK_LIB(pthread, pthread_mutex_init,,
AC_CHECK_LIB(pthreads, pthread_mutex_init,,
AC_MSG_ERROR([No pthreads support found.]))))
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h string.h sys/time.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_HEADER_TIME
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_MEMCMP
AC_CHECK_FUNCS([gettimeofday memset strcasecmp strncasecmp])
# AC_CONFIG_AUX_DIR
AC_ARG_ENABLE(debug,
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
esac],[debug=false])
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
AC_CONFIG_FILES([Makefile
src/Makefile
examples/Makefile
doc/Makefile
include/cfutypes.h
include/cfu.h])
AC_OUTPUT

479
depcomp Executable file
View File

@ -0,0 +1,479 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
# Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# `libtool' can also be set to `yes' or `no'.
if test -z "$depfile"; then
base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
dir=`echo "$object" | sed 's,/.*$,/,'`
if test "$dir" = "$object"; then
dir=
fi
# FIXME: should be _deps on DOS.
depfile="$dir.deps/$base"
fi
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test -f "$tmpdepfile"; then :
else
stripped=`echo "$stripped" | sed 's,^.*/,,'`
tmpdepfile="$stripped.u"
fi
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
if test -f "$tmpdepfile"; then
outname="$stripped.o"
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1="$dir.libs/$base.lo.d"
tmpdepfile2="$dir.libs/$base.d"
"$@" -Wc,-MD
else
tmpdepfile1="$dir$base.o.d"
tmpdepfile2="$dir$base.d"
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
if test -f "$tmpdepfile1"; then
tmpdepfile="$tmpdepfile1"
else
tmpdepfile="$tmpdepfile2"
fi
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0

13
doc/Makefile.am Normal file
View File

@ -0,0 +1,13 @@
MAKEINFO = case $@ in \
*.info) echo " INFO $@";; \
*.html) echo " HTML $@";; \
esac && @MAKEINFO@
TEXI2DVI = && case $@ in \
*.dvi) echo " DVI $@";; \
*.pdf) echo " PDF $@";; \
esac && texi2dvi --quiet
DVIPS = echo " PS $@" && dvips -q
info_TEXINFOS = libcfu.texi
.SILENT:

461
doc/Makefile.in Normal file
View File

@ -0,0 +1,461 @@
# Makefile.in generated by automake 1.9.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = doc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/stamp-vti $(srcdir)/version.texi mdate-sh \
texinfo.tex
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
SOURCES =
DIST_SOURCES =
INFO_DEPS = $(srcdir)/libcfu.info
am__TEXINFO_TEX_DIR = $(srcdir)
DVIS = libcfu.dvi
PDFS = libcfu.pdf
PSS = libcfu.ps
HTMLS = libcfu.html
TEXINFOS = libcfu.texi
TEXI2PDF = $(TEXI2DVI) --pdf --batch
MAKEINFOHTML = $(MAKEINFO) --html
AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
am__installdirs = "$(DESTDIR)$(infodir)"
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUG_FALSE = @DEBUG_FALSE@
DEBUG_TRUE = @DEBUG_TRUE@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBCFU_TYPE_u_int = @LIBCFU_TYPE_u_int@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = case $@ in \
*.info) echo " INFO $@";; \
*.html) echo " HTML $@";; \
esac && @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
TEXI2DVI = && case $@ in \
*.dvi) echo " DVI $@";; \
*.pdf) echo " PDF $@";; \
esac && texi2dvi --quiet
DVIPS = echo " PS $@" && dvips -q
info_TEXINFOS = libcfu.texi
all: all-am
.SUFFIXES:
.SUFFIXES: .dvi .html .info .pdf .ps .texi
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
.texi.info:
restore=: && backupdir="$(am__leading_dot)am$$$$" && \
am__cwd=`pwd` && cd $(srcdir) && \
rm -rf $$backupdir && mkdir $$backupdir && \
for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
done; \
cd "$$am__cwd"; \
if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
-o $@ $<; \
then \
rc=0; \
cd $(srcdir); \
else \
rc=$$?; \
cd $(srcdir) && \
$$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
fi; \
rm -rf $$backupdir; exit $$rc
.texi.dvi:
TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
$(TEXI2DVI) $<
.texi.pdf:
TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
$(TEXI2PDF) $<
.texi.html:
rm -rf $(@:.html=.htp)
if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
-o $(@:.html=.htp) $<; \
then \
rm -rf $@; \
if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \
else \
if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \
exit 1; \
fi
$(srcdir)/libcfu.info: libcfu.texi $(srcdir)/version.texi
libcfu.dvi: libcfu.texi $(srcdir)/version.texi
libcfu.pdf: libcfu.texi $(srcdir)/version.texi
libcfu.html: libcfu.texi $(srcdir)/version.texi
$(srcdir)/version.texi: $(srcdir)/stamp-vti
$(srcdir)/stamp-vti: libcfu.texi $(top_srcdir)/configure
@(dir=.; test -f ./libcfu.texi || dir=$(srcdir); \
set `$(SHELL) $(srcdir)/mdate-sh $$dir/libcfu.texi`; \
echo "@set UPDATED $$1 $$2 $$3"; \
echo "@set UPDATED-MONTH $$2 $$3"; \
echo "@set EDITION $(VERSION)"; \
echo "@set VERSION $(VERSION)") > vti.tmp
@cmp -s vti.tmp $(srcdir)/version.texi \
|| (echo "Updating $(srcdir)/version.texi"; \
cp vti.tmp $(srcdir)/version.texi)
-@rm -f vti.tmp
@cp $(srcdir)/version.texi $@
mostlyclean-vti:
-rm -f vti.tmp
maintainer-clean-vti:
-rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
.dvi.ps:
$(DVIPS) -o $@ $<
uninstall-info-am:
$(PRE_UNINSTALL)
@if (install-info --version && \
install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
list='$(INFO_DEPS)'; \
for file in $$list; do \
relfile=`echo "$$file" | sed 's|^.*/||'`; \
echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
done; \
else :; fi
@$(NORMAL_UNINSTALL)
@list='$(INFO_DEPS)'; \
for file in $$list; do \
relfile=`echo "$$file" | sed 's|^.*/||'`; \
relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
(if cd "$(DESTDIR)$(infodir)"; then \
echo " rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9])"; \
rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
else :; fi); \
done
dist-info: $(INFO_DEPS)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
list='$(INFO_DEPS)'; \
for base in $$list; do \
case $$base in \
$(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
esac; \
if test -f $$base; then d=.; else d=$(srcdir); fi; \
for file in $$d/$$base*; do \
relfile=`expr "$$file" : "$$d/\(.*\)"`; \
test -f $(distdir)/$$relfile || \
cp -p $$file $(distdir)/$$relfile; \
done; \
done
mostlyclean-aminfo:
-rm -rf libcfu.aux libcfu.cp libcfu.cps libcfu.fn libcfu.fns libcfu.ky \
libcfu.kys libcfu.log libcfu.pg libcfu.pgs libcfu.tmp \
libcfu.toc libcfu.tp libcfu.tps libcfu.vr libcfu.vrs \
libcfu.dvi libcfu.pdf libcfu.ps libcfu.html
maintainer-clean-aminfo:
@list='$(INFO_DEPS)'; for i in $$list; do \
i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
done
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$(top_distdir)" distdir="$(distdir)" \
dist-info
check-am: all-am
check: check-am
all-am: Makefile $(INFO_DEPS)
installdirs:
for dir in "$(DESTDIR)$(infodir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am: $(DVIS)
html: html-am
html-am: $(HTMLS)
info: info-am
info-am: $(INFO_DEPS)
install-data-am: install-info-am
install-exec-am:
install-info: install-info-am
install-info-am: $(INFO_DEPS)
@$(NORMAL_INSTALL)
test -z "$(infodir)" || $(mkdir_p) "$(DESTDIR)$(infodir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
list='$(INFO_DEPS)'; \
for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
esac; \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
$$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
if test -f $$ifile; then \
relfile=`echo "$$ifile" | sed 's|^.*/||'`; \
echo " $(INSTALL_DATA) '$$ifile' '$(DESTDIR)$(infodir)/$$relfile'"; \
$(INSTALL_DATA) "$$ifile" "$(DESTDIR)$(infodir)/$$relfile"; \
else : ; fi; \
done; \
done
@$(POST_INSTALL)
@if (install-info --version && \
install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
list='$(INFO_DEPS)'; \
for file in $$list; do \
relfile=`echo "$$file" | sed 's|^.*/||'`; \
echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
done; \
else : ; fi
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-aminfo \
maintainer-clean-generic maintainer-clean-vti
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-aminfo mostlyclean-generic mostlyclean-vti
pdf: pdf-am
pdf-am: $(PDFS)
ps: ps-am
ps-am: $(PSS)
uninstall-am: uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic dist-info \
distclean distclean-generic distdir dvi dvi-am html html-am \
info info-am install install-am install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-aminfo \
maintainer-clean-generic maintainer-clean-vti mostlyclean \
mostlyclean-aminfo mostlyclean-generic mostlyclean-vti pdf \
pdf-am ps ps-am uninstall uninstall-am uninstall-info-am
.SILENT:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

956
doc/libcfu.info Normal file
View File

@ -0,0 +1,956 @@
This is libcfu.info, produced by makeinfo version 4.7 from libcfu.texi.
Copyright (C) 2005 Don Owens
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with
the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
INFO-DIR-SECTION Libraries
START-INFO-DIR-ENTRY
* Libcfu: (libcfu). The cfu library.
END-INFO-DIR-ENTRY
This manual describes the external interface to libcfu version
0.03
Copyright (C) 2005 Don Owens All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with
the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File: libcfu.info, Node: Top, Next: Data structures, Prev: (dir), Up: (dir)
This manual describes the interface to libcfu version 0.03
Copyright (C) 2005 Don Owens
* Menu:
* Data structures::
* Conf:: For reading configuration files
* Options:: For parsing command-line arguments
* Thread queue:: For queueing up requests for a separate thread
* Timer:: An easy to use timer
* License:: License under which libcfu is distributed
* Concept index::
* Function index::

File: libcfu.info, Node: Data structures, Prev: Top, Up: Top
1 Data structures
*****************
* Menu:
* Hash table:: For key/value pairs
* Linked list:: For unordered data
* Strings:: For self-extending strings

File: libcfu.info, Node: Hash table, Next: Linked list, Prev: Data structures, Up: Data structures
1.1 Hash table
==============
-- Special Form: typedef u_int32_t (*cfuhash_function_t)(const void *
KEY, size_t LENGTH)
Prototype for a pointer to a hashing function.
-- Special Form: typedef void (*cfuhash_free_fn_t)(void * DATA)
Prototype for a pointer to a free function.
-- Special Form: typedef int (*cfuhash_remove_fn_t)(void * KEY, size_t
KEY_SIZE, void * DATA, size_t DATA_SIZE, void * ARG)
Prototype for a pointer to a function that determines whether or
not to remove an entry from the hash.
-- Special Form: typedef int (*cfuhash_foreach_fn_t)(void * KEY,
size_t KEY_SIZE, void * DATA, size_t DATA_SIZE, void * ARG)
Prototype for a pointer to a function to be called foreach
key/value pair in the hash by cfuhash_foreach(). The return
value should normally be zero. A non-zero return value means to
stop iterating over the key/value pairs.
-- Function: cfuhash_table_t * cfuhash_new (size_t SIZE, u_int32_t
FLAGS)
Creates a new hash table.
-- Function: cfuhash_table_t * cfuhash_new_with_initial_size (size_t
SIZE)
Creates a new hash table with the specified size (number of
buckets).
-- Function: cfuhash_table_t * cfuhash_new_with_flags (u_int32_t FLAGS)
Creates a new hash table with the specified flags. Pass zero for
flags if you want the defaults.
-- Function: cfuhash_table_t * cfuhash_new_with_free_fn (size_t SIZE,
u_int32_t FLAGS, cfuhash_free_fn_t FF)
Same as cfuhash_new() except automatically calls
cfuhash_set_free_fn().
-- Function: int cfuhash_copy (cfuhash_table_t * SRC, cfuhash_table_t
* DST)
Copies entries in src to dst
-- Function: cfuhash_table_t * cfuhash_merge (cfuhash_table_t * HT1,
cfuhash_table_t * HT2, u_int32_t FLAGS)
Returns a new hash containing entries from both hash tables. For
any entries with the same key, the one from ht2 wins.
-- Function: int cfuhash_set_hash_function (cfuhash_table_t * HT,
cfuhash_function_t HF)
Sets the hashing function to use when computing which bucket to add
entries to. It should return a 32-bit unsigned integer. By
default, Perl's hashing algorithm is used.
-- Function: int cfuhash_set_thresholds (cfuhash_table_t * HT, float
LOW, float HIGH)
Sets the thresholds for when to rehash. The ratio
num_entries/buckets is compared against low and high. If it is
below 'low' or above 'high', the hash will shrink or grow,
respectively, unless the flags say to do otherwise.
-- Function: int cfuhash_set_free_function (cfuhash_table_t * HT,
cfuhash_free_fn_t FF)
Sets the function to use when removing an entry from the hash,
i.e., when replacing an existing entry, deleting an entry, or
clearing the hash. It is passed the value of the entry as a void
*.
-- Function: u_int32_t cfuhash_get_flags (cfuhash_table_t * HT)
Returns the hash's flags. See below for flag definitions.
-- Function: u_int32_t cfuhash_set_flag (cfuhash_table_t * HT,
u_int32_t FLAG)
Sets a flag.
-- Function: u_int32_t cfuhash_clear_flag (cfuhash_table_t * HT,
u_int32_t NEW_FLAG)
Clears a flag.
-- Function: int cfuhash_get_data (cfuhash_table_t * HT, const void *
KEY, size_t KEY_SIZE, void ** DATA, size_t * DATA_SIZE)
Returns the value for the entry with given key. If key_size is -1,
key is assumed to be a null-terminated string. If data_size is
not NULL, the size of the value is placed into data_size.
-- Function: int cfuhash_exists_data (cfuhash_table_t * HT, const void
* KEY, size_t KEY_SIZE)
Returns 1 if an entry with the given key exists in the hash, 0
otherwise.
-- Function: int cfuhash_put_data (cfuhash_table_t * HT, const void *
KEY, size_t KEY_SIZE, void * DATA, size_t DATA_SIZE, void **
R)
Inserts the given data value into the hash and associates it with
key. If key_size is -1, key is assumed to be a null-terminated
string. If data_size is -1, it is assumed to be a null-terminated
string (it's length will be calculated using strlen). If
data_size is zero, it will be returned as zero when the value is
requested.
-- Function: void cfuhash_clear (cfuhash_table_t * HT)
Clears the hash table (deletes all entries).
-- Function: void * cfuhash_delete_data (cfuhash_table_t * HT, const
void * KEY, size_t KEY_SIZE)
Deletes the entry in the hash associated with key. If the entry
existed, it's value will be returned.
-- Function: void **cfuhash_keys_data (cfuhash_table_t * HT, size_t *
NUM_KEYS, size_t ** KEY_SIZES, int FAST)
Returns all the keys from the hash. The number of keys is placed
into the value pointed to by num_keys. If key_sizes is not NULL,
it will be set to an array of key sizes. If fast is zero, copies
of the keys are returned. Otherwise, pointers to the real keys
will be returned.
-- Function: int cfuhash_each_data (cfuhash_table_t * HT, void ** KEY,
size_t * KEY_SIZE, void ** DATA, size_t * DATA_SIZE)
Initializes a loop over all the key/value pairs in the hash. It
returns the first key/value pair (see cfuhash_next_data()). 1 is
returned if there are any entries in the hash. 0 is returned
otherwise.
-- Function: int cfuhash_next_data (cfuhash_table_t * HT, void ** KEY,
size_t * KEY_SIZE, void ** DATA, size_t * DATA_SIZE)
Gets the next key/value pair from the hash. You must initialize
the loop using cfuhash_each_data() before calling this function.
If a entry is left to return, 1 is returned from the function. 0
is returned if there are no more entries in the hash.
-- Function: size_t cfuhash_foreach_remove (cfuhash_table_t * HT,
cfuhash_remove_fn_t R_FN, cfuhash_free_fn_t FF, void * ARG)
Iterates over the key/value pairs in the hash, passing each one
to r_fn, and removes all entries for which r_fn returns true. If
ff is not NULL, it is the passed the data to be freed. arg is
passed to r_fn.
-- Function: size_t cfuhash_foreach (cfuhash_table_t * HT,
cfuhash_foreach_fn_t FE_FN, void * ARG)
Iterates over the key/value pairs in the hash, passing each one
to fe_fn, along with arg. This locks the hash, so do not call any
operations on the hash from within fe_fn unless you really know
what you're doing.
If the return value from fe_fn() is not zero, the iteration stops.
-- Function: int cfuhash_destroy (cfuhash_table_t * HT)
Frees all resources allocated by the hash.
-- Function: int cfuhash_destroy_with_free_fn (cfuhash_table_t * HT,
cfuhash_free_fn_t FF)
Frees all resources allocated by the hash. If ff is not NULL, it
is called for each hash entry with the value of the entry passed as
its only argument. If ff is not NULL, it overrides any function
set previously with cfuhash_set_free_function().
-- Function: int cfuhash_rehash (cfuhash_table_t * HT)
Rebuild the hash to better accomodate the number of entries. See
cfuhash_set_thresholds().
-- Function: size_t cfuhash_num_entries (cfuhash_table_t * HT)
Returns the number entries in the hash.
-- Function: size_t cfuhash_num_buckets (cfuhash_table_t * HT)
Returns the number of buckets allocated for the hash.
-- Function: size_t cfuhash_num_buckets_used (cfuhash_table_t * HT)
Returns the number of buckets actually used out of the total number
allocated for the hash.
-- Function: char * cfuhash_bencode_strings (cfuhash_table_t * HT)
Assumes all the keys and values are null-terminated strings and
returns a bencoded string representing the hash (see
http://www.bittorrent.com/protocol.html)
-- Function: int cfuhash_lock (cfuhash_table_t * HT)
Locks the hash. Use this with the each and next functions for
concurrency control. Note that the hash is locked automatically
when doing inserts and deletes, so if you lock the hash and then
try to insert something into it, you may get into a deadlock,
depending on your system defaults for how mutexes work.
-- Function: int cfuhash_unlock (cfuhash_table_t * HT)
Unlocks the hash. Use this with the each an next functions for
concurrency control. The caveat for cfuhash_lock() also applies to
this function.
-- Function: int cfuhash_pretty_print (cfuhash_table_t * HT, FILE * FP)
Pretty print the hash's key/value pairs to the stream fp. It is
assumed that all the keys and values are null-terminated strings.
These are like the _data versions of these functions, with the
following exceptions:
1) They assume that the key provided is a null-terminated string.
2) They don't worry about the size of the data.
3) Returned keys or values are the return value of the function.
-- Function: void * cfuhash_get (cfuhash_table_t * HT, const char *
KEY)
-- Function: int cfuhash_exists (cfuhash_table_t * HT, const char *
KEY);
-- Function: void * cfuhash_put (cfuhash_table_t * HT, const char *
KEY, void * DATA);
-- Function: void * cfuhash_delete (cfuhash_table_t * HT, const char *
KEY);
-- Function: int cfuhash_each (cfuhash_table_t * HT, char ** KEY, void
** DATA);
-- Function: int cfuhash_next (cfuhash_table_t * HT, char ** KEY, void
** DATA);
-- Function: void ** cfuhash_keys (cfuhash_table_t * HT, size_t *
NUM_KEYS, int FAST);
Valid flags for cfuhash_new() or cfuhash_set_flag):
-- CFUHASH_NOCOPY_KEYS:
Don't copy the key when adding an entry to the hash table.
-- CFUHASH_NO_LOCKING:
Don't not use any mutexes. Beware that this flag makes the hash
table non thread-safe.
-- CFUHASH_FROZEN:
Do not rehash (don't grow or shrink the number of buckets in the
hash table when the thresholds are reached).
-- CFUHASH_FROZEN_UNTIL_GROWS:
Do not rehash until the upper threshold is reached the first time
(useful for preallocating a large hash to avoid rehashing while
filling it).
-- CFUHASH_FREE_DATA:
Call free() on the values when cfuhash_destroy() is called.
-- CFUHASH_IGNORE_CASE:
Treat the keys case-insensitively.

File: libcfu.info, Node: Linked list, Next: Strings, Prev: Hash table, Up: Data structures
1.2 Linked list
===============
-- Special Form: typedef int (*cfulist_foreach_fn_t)(void * DATA,
size_t DATA_SIZE, void * ARG)
Function called for each element in the list when passed to
cfulist_foreach(). A non-zero return value means to stop
iteration.
-- Special Form: typedef void * (*cfulist_map_fn_t)(void *DATA, size_t
DATA_SIZE, void *ARG, size_t *NEW_DATA_SIZE)
Function called for each element in the list when passed to
cfulist_map(). The return value is used to build a new list.
-- Special Form: typedef void (*cfulist_free_fn_t)(void * DATA)
Function called to free the data in an element.
-- Function: cfulist_t * cfulist_new ();
Returns a new list.
-- Function: size_t cfulist_num_entries (cfulist_t *LIST)
Returns the number of entries in the list.
-- Function: int cfulist_push_data (cfulist_t * LIST, void * DATA,
size_t DATA_SIZE)
Push a value onto the end of the list.
-- Function: int cfulist_pop_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE)
Pop a value from the end of the list (removing it from the list).
-- Function: int cfulist_unshift_data (cfulist_t * LIST, void * DATA,
size_t DATA_SIZE)
Add a value at the beginning of the list.
-- Function: int cfulist_shift_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE)
Shift a value off the beginning of the list.
-- Function: int cfulist_enqueue_data (cfulist_t * LIST, void * DATA,
size_t DATA_SIZE)
Add a value at the end of the queue (equivalent to push)
-- Function: int cfulist_dequeue_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE)
Remove the value at the beginning of the list (equivalent to
shift).
-- Function: int cfulist_first_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE);
Return the first entry from the list (without removing it from the
list).
-- Function: int cfulist_last_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE);
Return the last entry from the list (without removing it from the
list).
-- Function: int cfulist_nth_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE, size_t N);
Return the nth entry from the list (without removing it from the
list). n starts at zero.
-- Function: void cfulist_reset_each (cfulist_t * LIST);
-- Function: int cfulist_each_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE);
-- Function: int cfulist_next_data (cfulist_t * LIST, void ** DATA,
size_t * DATA_SIZE);
-- Function: size_t cfulist_foreach (cfulist_t * LIST,
cfulist_foreach_fn_t FE_FN, void * ARG);
Calls fe_fn() for each element in the list. Also passes arg on each
call. Do not try to manipulate the list inside fe_fn(), as the
list will be locked.
If fe_fn() returns a non-zero value, the iteration over the
elements stops.
-- Function: cfulist_t * cfulist_map (cfulist_t *LIST,
cfulist_map_fn_t MAP_FN, void *ARG);
Creates a new list from the list passed in. Calls map_fn() on each
element in the list. The return value is placed in the
corresponding position in the new list.
-- Function: void cfulist_destroy (cfulist_t * LIST)
Free all resources used by the list.
-- Function: void cfulist_destroy (cfulist_t * LIST, cfulist_free_fn_t
FREE_FN)
Free all resources used by the list. If free_fn is not NULL, call
it for each element of the list, passing the data to it as a void
*.
When you don't care about the size of the data
-- Function: int cfulist_push (cfulist_t * LIST, void * DATA)
-- Function: void * cfulist_pop (cfulist_t * LIST);
-- Function: int cfulist_unshift (cfulist_t * LIST, void * DATA);
-- Function: void * cfulist_shift (cfulist_t * LIST);
-- Function: int cfulist_enqueue (cfulist_t * IST, void * DATA);
-- Function: void * cfulist_dequeue (cfulist_t * LIST);
Strings - assume data is a null-terminated string - size is
calculated by strlen(data) + 1
-- Function: int cfulist_push_string (cfulist_t * LIST, char * DATA)
-- Function: char * cfulist_pop_string (cfulist_t * LIST);
-- Function: int cfulist_unshift_string (cfulist_t * LIST, char *
DATA);
-- Function: char * cfulist_shift_string (cfulist_t * LIST);
-- Function: int cfulist_enqueue_string (cfulist_t * LIST, char *
DATA);
-- Function: char * cfulist_dequeue_string (cfulist_t * LIST);
-- Function: char * cfulist_join (cfulist_t * LIST, const char *
DELIMITER)

File: libcfu.info, Node: Strings, Prev: Linked list, Up: Data structures
1.3 Strings
===========
-- Function: cfustring_t * cfustring_new (size_t INITIAL_SIZE)
Returns a new String.
-- Function: cfustring_t * cfustring_new_from_string (const char *
STRING)
Returns a new String initalized with the given string.
-- Function: int cfustring_dup (cfustring_t * CFU_STR, const char *
STRING)
Overwrite anything currently in cfu_str with string.
-- Function: int cfustring_clear (cfustring_t * CFU_STR)
Truncate the string.
-- Function: int cfustring_append (cfustring_t * CFU_STR, const char *
STR)
Append str to the end of the buffer in cfu_str.
-- Function: char * cfustring_get_buffer (cfustring_t * CFU_STR)
Get the buffer used to hold the string. Do not free() it, as it is
used directly by cfustring and will be destroyed when
cfustring_destroy() is called.
-- Function: char * cfustring_get_buffer_copy (cfustring_t * CFU_STR)
Same as cfustring_get_buffer(), except return a copy of the string.
Caller is responsible for deallocating the buffer with free().
-- Function: cfustring_t ** cfustring_split (cfustring_t * CFU_STR,
size_t * NUM_STRINGS, size_t LIMIT, ...)
Split cfu_str on one or more delimiting strings, e.g.,
cfustring_split(cfu_str, 2, 0, "\r\n", "\n"). Use a limit > 0 if
you want to only get back a certain number of strings and ignore
any extra delimiters.
-- Function: char ** cfustring_split_to_c_str (cfustring_t * CFU_STR,
size_t * NUM_STRINGS, size_t LIMIT, ...)
Same as cfustring_split(), except return an array of C-strings.
Caller is responsible for deallocating the buffers.
-- Function: int cfustring_destroy (cfustring_t * CFU_STR)
Free all resources allocated by cfu_str.
-- Function: char * cfustring_dup_c_str (const char * STR)
Duplicate the C string str. Caller must free with free().
-- Function: char * cfustring_dup_c_str_n (const char * STR, size_t N)
Same as cfustring_dup_c_str(), but only copy at most n chars
-- Function: size_t cfustring_sprintf (cfustring_t * CFU_STR, const
char * FMT, ...);
Like sprintf(), but writes to a self-extending string.
-- Function: size_t cfustring_vsprintf (cfustring_t * CFU_STR, const
char * FMT, va_list AP);
Like vsprintf(), but writes to a self-extending string.
-- Function: char * cfustring_sprintf_c_str (const char * FMT, ...)
Similar to sprintf(), but allocates a C string of the appropriate
size for you and returns it.
-- Function: char ** cfustring_c_str_split (const char * C_STR, size_t
* NUM_STRINGS, size_t LIMIT, ...)
Like cfustring_split_to_c_str(), but split a char * instead of a
cfustring_t *.

File: libcfu.info, Node: Conf, Next: Options, Prev: Top, Up: Top
2 Conf
******
This needs to be better documented.
Apache-style conf files contain directives and containers.
Directives are simple one line specifications with or without
arguments, e.g.,
Doit Expires On LoadModule my_mod modules/my_mod.so
Containers have a type and a name associated with them and they in
turn contain directives and/or containers, e.g.,
<MyContainer test1> Expires Off <DB devdb>
DBHost db.example.com DBUser
test_user </DB> </MyContainer>
Values may be quoted, e.g.
DBUser "test user"
But must be specified on a single line. To escape quotes within a
quoted string, use the '\' character.
-- Function: int cfuconf_parse_file (char * FILE_PATH, cfuconf_t **
CONF, char ** ERROR)
Parse the apache-like conf file specified by file_path, returning
a pointer to a cfuconf_t structure in conf. Returns zero on
success, less than zero on error. If an error occurs and error
is not NULL, it will be set to an error message (which must be
free()'d by the caller).
-- Function: int cfuconf_parse_buffer (char * BUFFER, cfuconf_t **
CONF, char ** ERROR)
Same as cfuconf_parse_file(), except assume the contents of the
file are already in buffer.
-- Function: void cfuconf_destroy (cfuconf_t * CONF)
Free all resources used by the cfuconf_t structure
-- Function: cfuhash_table_t * cfuconf_get_containers (cfuconf_t *
CONF)
Get a hash of containers at the top level of conf
-- Function: cfuhash_table_t * cfuconf_get_directives (cfuconf_t *
CONF)
Get a hash of directives at the to level
-- Function: int cfuconf_get_directive_one_arg (cfuconf_t * CONF, char
* DIRECTIVE, char ** RVALUE)
Get the value of the given directive, assuming there is only one
argument
-- Function: int cfuconf_get_directive_two_args (cfuconf_t * CONF,
char * DIRECTIVE, char ** RVALUE, char ** RVALUE2)
Get the value of the given directive, assuming there are two
arguments
-- Function: int cfuconf_get_directive_n_args (cfuconf_t * CONF, char
* DIRECTIVE, size_t N, ...)
Get the value of the given directives, with n arguments

File: libcfu.info, Node: Options, Next: Thread queue, Prev: Conf, Up: Top
3 Options
*********
Command-line arguments can be parsed with the following:
cfuopt_t *opt = cfuopt_new();
cfuopt_add_entry(opt, "verbose|v!", &verbose, "Verbosity", "");
cfuopt_add_entry(opt, "file|f:s", &file, "File to load", "FILE");
cfuopt_add_entry(opt, "count|c|n=i", &count, "Count to run", "COUNT");
cfuopt_add_entry(opt, "scale|s:f", &scale, "Scaling factor", "SCALE");
cfuopt_parse(opt, &argc, &argv, &error);
/* do stuff here with the options */
cfuopt_destroy(opt);
free(file);
-- Function: cfuopt_t * cfuopt_new ()
Returns a new options context.
-- Function: void cfuopt_add_entry (cfuopt_t *CONTEXT, const char
*OPT_STR, void *ARG_DATA, const char *DESCRIPTION, const char
*ARG_DESCRIPTION)
Adds to the list of known options.
-- Function: void cfuopt_parse (cfuopt_t *CONTEXT, int *ARGC, char
***ARGV, char **ERROR)
Parses the command line and modifies argc and argv to account for
left over arguments.
-- Function: char * cfuopt_get_help_str (cfuopt_t *CONTEXT)
Returns a help string built from the entries added with
cfuopt_add_entry().
-- Function: void cfuopt_destroy (cfuopt_t *CONTEXT)
Frees up resources used by the option parser.

File: libcfu.info, Node: Thread queue, Next: Timer, Prev: Options, Up: Top
4 Thread queue
**************
cfuthread_queue provides a way to serialize requests for a resource
where you want the resource to be accessed from a single thread only.
For instance, for a database connection where making calls in separate
threads does not work properly, you can use cfuthread_queue.
cfuthread_queue_new() creates a new thread that waits for something to
be added to the queue. Once something is added, the thread will
process the data by calling the function you pass as an argument to the
cfuthread_queue_new() function.
-- Function: cfuthread_queue_t * cfuthread_queue_new
(cfuthread_queue_fn_t FN)
Creates a new thread queue structure that will run the given
function when a request is received.
-- Function: cfuthread_queue_t * cfuthread_queue_new_with_cleanup
(cfuthread_queue_fn_t FN, cfuthread_queue_init_t INIT_FN,
void * INIT_ARG, cfuthread_queue_cleanup_t CLEANUP_FN, void *
CLEANUP_ARG)
Same as cfuthread_queue_new(), but with an initialization
function that gets called with the argument init_arg when the
thread is created, and a cleanup function that gets called with
the argument cleanup_arg when the thread exits, e.g., when
cfuthread_queue_destroy() is called.
-- Function: void * cfuthread_queue_make_request (cfuthread_queue_t *
TQ, void * DATA)
Add a request to the queue. data will get passed to the function
fn given to cfuthread_queue_new when it reaches the front of the
queue.
-- Function: void cfuthread_queue_destroy (cfuthread_queue_t * TQ)
Free up resources used by the queue, in addition to canceling the
thread.

File: libcfu.info, Node: Timer, Next: License, Prev: Thread queue, Up: Top
5 Timer
*******
-- Function: cfutime_t *cfutime_new ();
Return a new cfutime structure.
-- Function: void cfutime_begin (cfutime_t *TIME)
Start the timer.
-- Function: void cfutime_end (cfutime_t * TIME)
Stop the timer.
-- Function: double cfutime_elapsed (cfutime_t * TIME)
Return the number of seconds elapsed as a double.
-- Function: void cfutime_free (cfutime_t * TIME)
Deallocate resources allocated for time.

File: libcfu.info, Node: License, Prev: Timer, Up: Top
License
*******
Copyright (C) 2005 Don Owens All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with
the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File: libcfu.info, Node: Concept index, Next: Function index, Prev: Top, Up: Top
Concept index
*************
[index]
* Menu:
* apache configuration file: Conf. (line 6)
* arguments: Options. (line 6)
* command-line arguments: Options. (line 6)
* configuration file: Conf. (line 6)
* data structures: Data structures. (line 6)
* hash tables: Hash table. (line 6)
* license: License. (line 6)
* linked list: Linked list. (line 6)
* options: Options. (line 6)
* queues: Linked list. (line 6)
* self-extending strings: Strings. (line 6)
* strings: Strings. (line 6)
* thread queue: Thread queue. (line 6)
* threading: Thread queue. (line 6)
* timer: Timer. (line 6)

File: libcfu.info, Node: Function index, Prev: Concept index, Up: Top
Function index
**************
[index]
* Menu:
* **cfuhash_keys_data: Hash table. (line 122)
* *cfutime_new: Timer. (line 7)
* cfuconf_destroy: Conf. (line 44)
* cfuconf_get_containers: Conf. (line 48)
* cfuconf_get_directive_n_args: Conf. (line 66)
* cfuconf_get_directive_one_arg: Conf. (line 56)
* cfuconf_get_directive_two_args: Conf. (line 61)
* cfuconf_get_directives: Conf. (line 52)
* cfuconf_parse_buffer: Conf. (line 39)
* cfuconf_parse_file: Conf. (line 30)
* cfuhash_bencode_strings: Hash table. (line 192)
* cfuhash_clear: Hash table. (line 112)
* cfuhash_clear_flag: Hash table. (line 86)
* cfuhash_copy: Hash table. (line 46)
* cfuhash_delete: Hash table. (line 236)
* cfuhash_delete_data: Hash table. (line 116)
* cfuhash_destroy: Hash table. (line 164)
* cfuhash_destroy_with_free_fn: Hash table. (line 169)
* cfuhash_each: Hash table. (line 239)
* cfuhash_each_data: Hash table. (line 131)
* cfuhash_exists: Hash table. (line 230)
* cfuhash_exists_data: Hash table. (line 97)
* cfuhash_foreach: Hash table. (line 155)
* cfuhash_foreach_remove: Hash table. (line 147)
* cfuhash_get: Hash table. (line 227)
* cfuhash_get_data: Hash table. (line 90)
* cfuhash_get_flags: Hash table. (line 78)
* cfuhash_keys: Hash table. (line 245)
* cfuhash_lock: Hash table. (line 198)
* cfuhash_merge: Hash table. (line 50)
* cfuhash_new: Hash table. (line 27)
* cfuhash_new_with_flags: Hash table. (line 36)
* cfuhash_new_with_free_fn: Hash table. (line 41)
* cfuhash_new_with_initial_size: Hash table. (line 31)
* cfuhash_next: Hash table. (line 242)
* cfuhash_next_data: Hash table. (line 139)
* cfuhash_num_buckets: Hash table. (line 184)
* cfuhash_num_buckets_used: Hash table. (line 187)
* cfuhash_num_entries: Hash table. (line 181)
* cfuhash_pretty_print: Hash table. (line 212)
* cfuhash_put: Hash table. (line 233)
* cfuhash_put_data: Hash table. (line 103)
* cfuhash_rehash: Hash table. (line 176)
* cfuhash_set_flag: Hash table. (line 82)
* cfuhash_set_free_function: Hash table. (line 71)
* cfuhash_set_hash_function: Hash table. (line 56)
* cfuhash_set_thresholds: Hash table. (line 63)
* cfuhash_unlock: Hash table. (line 206)
* cfulist_dequeue: Linked list. (line 112)
* cfulist_dequeue_data: Linked list. (line 49)
* cfulist_dequeue_string: Linked list. (line 129)
* cfulist_destroy: Linked list. (line 91)
* cfulist_each_data: Linked list. (line 71)
* cfulist_enqueue: Linked list. (line 110)
* cfulist_enqueue_data: Linked list. (line 45)
* cfulist_enqueue_string: Linked list. (line 127)
* cfulist_first_data: Linked list. (line 54)
* cfulist_foreach: Linked list. (line 77)
* cfulist_join: Linked list. (line 132)
* cfulist_last_data: Linked list. (line 59)
* cfulist_map: Linked list. (line 86)
* cfulist_new: Linked list. (line 21)
* cfulist_next_data: Linked list. (line 74)
* cfulist_nth_data: Linked list. (line 64)
* cfulist_num_entries: Linked list. (line 24)
* cfulist_pop: Linked list. (line 104)
* cfulist_pop_data: Linked list. (line 33)
* cfulist_pop_string: Linked list. (line 119)
* cfulist_push: Linked list. (line 102)
* cfulist_push_data: Linked list. (line 29)
* cfulist_push_string: Linked list. (line 117)
* cfulist_reset_each: Linked list. (line 68)
* cfulist_shift: Linked list. (line 108)
* cfulist_shift_data: Linked list. (line 41)
* cfulist_shift_string: Linked list. (line 124)
* cfulist_unshift: Linked list. (line 106)
* cfulist_unshift_data: Linked list. (line 37)
* cfulist_unshift_string: Linked list. (line 122)
* cfuopt_add_entry: Options. (line 25)
* cfuopt_destroy: Options. (line 37)
* cfuopt_get_help_str: Options. (line 33)
* cfuopt_new: Options. (line 20)
* cfuopt_parse: Options. (line 29)
* cfustring_append: Strings. (line 22)
* cfustring_c_str_split: Strings. (line 72)
* cfustring_clear: Strings. (line 18)
* cfustring_destroy: Strings. (line 50)
* cfustring_dup: Strings. (line 15)
* cfustring_dup_c_str: Strings. (line 53)
* cfustring_dup_c_str_n: Strings. (line 56)
* cfustring_get_buffer: Strings. (line 25)
* cfustring_get_buffer_copy: Strings. (line 31)
* cfustring_new: Strings. (line 7)
* cfustring_new_from_string: Strings. (line 11)
* cfustring_split: Strings. (line 37)
* cfustring_split_to_c_str: Strings. (line 45)
* cfustring_sprintf: Strings. (line 60)
* cfustring_sprintf_c_str: Strings. (line 67)
* cfustring_vsprintf: Strings. (line 64)
* cfuthread_queue_destroy: Thread queue. (line 40)
* cfuthread_queue_make_request: Thread queue. (line 34)
* cfuthread_queue_new: Thread queue. (line 17)
* cfuthread_queue_new_with_cleanup: Thread queue. (line 25)
* cfutime_begin: Timer. (line 10)
* cfutime_elapsed: Timer. (line 16)
* cfutime_end: Timer. (line 13)
* cfutime_free: Timer. (line 19)
* typedef <1>: Linked list. (line 8)
* typedef: Hash table. (line 8)

Tag Table:
Node: Top3327
Node: Data structures3837
Node: Hash table4065
Node: Linked list14625
Node: Strings19375
Node: Conf22220
Node: Options24608
Node: Thread queue25950
Node: Timer27721
Node: License28255
Node: Concept index29869
Node: Function index31103

End Tag Table

969
doc/libcfu.texi Normal file
View File

@ -0,0 +1,969 @@
\input texinfo
@c %**start of header
@iftex
@afourpaper
@setchapternewpage off
@end iftex
@setfilename libcfu.info
@settitle Libcfu Programmers Guide
@c %**end of header
@include version.texi
Copyright @copyright{} 2005 Don Owens
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
@ifinfo
@dircategory Libraries
@direntry
* Libcfu: (libcfu). The cfu library.
@end direntry
@end ifinfo
@ifinfo
This manual describes the external interface to libcfu version @value{VERSION}
Copyright @copyright{} 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
@end ifinfo
@titlepage
@title Libcfu Programmers Guide
@subtitle Version @value{VERSION}
@author Don Owens
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
@end titlepage
@node Top, Data structures, (dir), (dir)
@ifinfo
This manual describes the interface to libcfu version @value{VERSION}
Copyright @copyright{} 2005 Don Owens
@end ifinfo
@menu
* Data structures::
* Conf:: For reading configuration files
* Options:: For parsing command-line arguments
* Thread queue:: For queueing up requests for a separate thread
* Timer:: An easy to use timer
* License:: License under which libcfu is distributed
* Concept index::
* Function index::
@end menu
@node Data structures, , Top, Top
@chapter Data structures
@cindex data structures
@menu
* Hash table:: For key/value pairs
* Linked list:: For unordered data
* Strings:: For self-extending strings
@end menu
@node Hash table, Linked list, Data structures, Data structures
@section Hash table
@cindex hash tables
@defspec typedef u_int32_t (*cfuhash_function_t)(const void * @var{key}, size_t @var{length})
Prototype for a pointer to a hashing function.
@end defspec
@defspec typedef void (*cfuhash_free_fn_t)(void * @var{data})
Prototype for a pointer to a free function.
@end defspec
@defspec typedef int (*cfuhash_remove_fn_t)(void * @var{key}, size_t @var{key_size}, void * @var{data}, size_t @var{data_size}, void * @var{arg})
Prototype for a pointer to a function that determines whether or not to remove an entry from the hash.
@end defspec
@defspec typedef int (*cfuhash_foreach_fn_t)(void * @var{key}, size_t @var{key_size}, void * @var{data}, size_t @var{data_size}, void * @var{arg})
Prototype for a pointer to a function to be called foreach key/value
pair in the hash by cfuhash_foreach(). The return value should
normally be zero. A non-zero return value means to stop iterating
over the key/value pairs.
@end defspec
@deftypefun {cfuhash_table_t *} cfuhash_new (size_t @var{size}, u_int32_t @var{flags})
Creates a new hash table.
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuhash_new_with_initial_size (size_t @var{size})
Creates a new hash table with the specified size (number of
buckets).
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuhash_new_with_flags (u_int32_t @var{flags})
Creates a new hash table with the specified flags. Pass zero
for flags if you want the defaults.
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuhash_new_with_free_fn (size_t @var{size}, u_int32_t @var{flags}, cfuhash_free_fn_t @var{ff})
Same as cfuhash_new() except automatically calls cfuhash_set_free_fn().
@end deftypefun
@deftypefun {int} cfuhash_copy (cfuhash_table_t * @var{src}, cfuhash_table_t * @var{dst})
Copies entries in src to dst
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuhash_merge (cfuhash_table_t * @var{ht1}, cfuhash_table_t * @var{ht2}, u_int32_t @var{flags})
Returns a new hash containing entries from both hash tables.
For any entries with the same key, the one from ht2 wins.
@end deftypefun
@deftypefun {int} cfuhash_set_hash_function (cfuhash_table_t * @var{ht}, cfuhash_function_t @var{hf})
Sets the hashing function to use when computing which bucket to add
entries to. It should return a 32-bit unsigned integer. By
default, Perl's hashing algorithm is used.
@end deftypefun
@deftypefun {int} cfuhash_set_thresholds (cfuhash_table_t * @var{ht}, float @var{low}, float @var{high})
Sets the thresholds for when to rehash. The ratio
num_entries/buckets is compared against low and high. If it is
below 'low' or above 'high', the hash will shrink or grow,
respectively, unless the flags say to do otherwise.
@end deftypefun
@deftypefun {int} cfuhash_set_free_function (cfuhash_table_t * @var{ht}, cfuhash_free_fn_t @var{ff})
Sets the function to use when removing an entry from the hash,
i.e., when replacing an existing entry, deleting an entry, or
clearing the hash. It is passed the value of the entry as a
void *.
@end deftypefun
@deftypefun {u_int32_t} cfuhash_get_flags (cfuhash_table_t * @var{ht})
Returns the hash's flags. See below for flag definitions.
@end deftypefun
@deftypefun {u_int32_t} cfuhash_set_flag (cfuhash_table_t * @var{ht}, u_int32_t @var{flag})
Sets a flag.
@end deftypefun
@deftypefun {u_int32_t} cfuhash_clear_flag (cfuhash_table_t * @var{ht}, u_int32_t @var{new_flag})
Clears a flag.
@end deftypefun
@deftypefun {int} cfuhash_get_data (cfuhash_table_t * @var{ht}, const void * @var{key}, size_t @var{key_size}, void ** @var{data}, size_t * @var{data_size})
Returns the value for the entry with given key. If key_size is -1,
key is assumed to be a null-terminated string. If data_size is not
NULL, the size of the value is placed into data_size.
@end deftypefun
@deftypefun {int} cfuhash_exists_data (cfuhash_table_t * @var{ht}, const void * @var{key}, size_t @var{key_size})
Returns 1 if an entry with the given key exists in the hash, 0 otherwise.
@end deftypefun
@deftypefun {int} cfuhash_put_data (cfuhash_table_t * @var{ht}, const void * @var{key}, size_t @var{key_size}, void * @var{data}, size_t @var{data_size}, void ** @var{r})
Inserts the given data value into the hash and associates it with
key. If key_size is -1, key is assumed to be a null-terminated
string. If data_size is -1, it is assumed to be a null-terminated
string (it's length will be calculated using strlen). If
data_size is zero, it will be returned as zero when the value is
requested.
@end deftypefun
@deftypefun {void} cfuhash_clear (cfuhash_table_t * @var{ht})
Clears the hash table (deletes all entries).
@end deftypefun
@deftypefun {void *} cfuhash_delete_data (cfuhash_table_t * @var{ht}, const void * @var{key}, size_t @var{key_size})
Deletes the entry in the hash associated with key. If the entry
existed, it's value will be returned.
@end deftypefun
@deftypefun {void} **cfuhash_keys_data (cfuhash_table_t * @var{ht}, size_t * @var{num_keys}, size_t ** @var{key_sizes}, int @var{fast})
Returns all the keys from the hash. The number of keys is placed
into the value pointed to by num_keys. If key_sizes is not NULL,
it will be set to an array of key sizes. If fast is zero, copies
of the keys are returned. Otherwise, pointers to the real keys
will be returned.
@end deftypefun
@deftypefun {int} cfuhash_each_data (cfuhash_table_t * @var{ht}, void ** @var{key}, size_t * @var{key_size}, void ** @var{data}, size_t * @var{data_size})
Initializes a loop over all the key/value pairs in the hash. It
returns the first key/value pair (see cfuhash_next_data()). 1 is
returned if there are any entries in the hash. 0 is returned
otherwise.
@end deftypefun
@deftypefun {int} cfuhash_next_data (cfuhash_table_t * @var{ht}, void ** @var{key}, size_t * @var{key_size}, void ** @var{data}, size_t * @var{data_size})
Gets the next key/value pair from the hash. You must initialize
the loop using cfuhash_each_data() before calling this function.
If a entry is left to return, 1 is returned from the function. 0
is returned if there are no more entries in the hash.
@end deftypefun
@deftypefun {size_t} cfuhash_foreach_remove (cfuhash_table_t * @var{ht}, cfuhash_remove_fn_t @var{r_fn}, cfuhash_free_fn_t @var{ff}, void * @var{arg})
Iterates over the key/value pairs in the hash, passing each one
to r_fn, and removes all entries for which r_fn returns true.
If ff is not NULL, it is the passed the data to be freed. arg
is passed to r_fn.
@end deftypefun
@deftypefun {size_t} cfuhash_foreach (cfuhash_table_t * @var{ht}, cfuhash_foreach_fn_t @var{fe_fn}, void * @var{arg})
Iterates over the key/value pairs in the hash, passing each one
to fe_fn, along with arg. This locks the hash, so do not call
any operations on the hash from within fe_fn unless you really
know what you're doing.
If the return value from fe_fn() is not zero, the iteration stops.
@end deftypefun
@deftypefun {int} cfuhash_destroy (cfuhash_table_t * @var{ht})
Frees all resources allocated by the hash.
@end deftypefun
@deftypefun {int} cfuhash_destroy_with_free_fn (cfuhash_table_t * @var{ht}, cfuhash_free_fn_t @var{ff})
Frees all resources allocated by the hash. If ff is not NULL, it
is called for each hash entry with the value of the entry passed as
its only argument. If ff is not NULL, it overrides any function
set previously with cfuhash_set_free_function().
@end deftypefun
@deftypefun {int} cfuhash_rehash (cfuhash_table_t * @var{ht})
Rebuild the hash to better accomodate the number of entries. See
cfuhash_set_thresholds().
@end deftypefun
@deftypefun {size_t} cfuhash_num_entries (cfuhash_table_t * @var{ht})
Returns the number entries in the hash.
@end deftypefun
@deftypefun {size_t} cfuhash_num_buckets (cfuhash_table_t * @var{ht})
Returns the number of buckets allocated for the hash.
@end deftypefun
@deftypefun {size_t} cfuhash_num_buckets_used (cfuhash_table_t * @var{ht})
Returns the number of buckets actually used out of the total number
allocated for the hash.
@end deftypefun
@deftypefun {char *} cfuhash_bencode_strings (cfuhash_table_t * @var{ht})
Assumes all the keys and values are null-terminated strings and
returns a bencoded string representing the hash (see
http://www.bittorrent.com/protocol.html)
@end deftypefun
@deftypefun {int} cfuhash_lock (cfuhash_table_t * @var{ht})
Locks the hash. Use this with the each and next functions for
concurrency control. Note that the hash is locked automatically
when doing inserts and deletes, so if you lock the hash and then
try to insert something into it, you may get into a deadlock,
depending on your system defaults for how mutexes work.
@end deftypefun
@deftypefun {int} cfuhash_unlock (cfuhash_table_t * @var{ht})
Unlocks the hash. Use this with the each an next functions for
concurrency control. The caveat for cfuhash_lock() also applies to
this function.
@end deftypefun
@deftypefun {int} cfuhash_pretty_print (cfuhash_table_t * @var{ht}, FILE * @var{fp})
Pretty print the hash's key/value pairs to the stream fp. It is
assumed that all the keys and values are null-terminated strings.
@end deftypefun
These are like the _data versions of these functions, with the
following exceptions:
1) They assume that the key provided is a null-terminated string.
2) They don't worry about the size of the data.
3) Returned keys or values are the return value of the function.
@deftypefun {void *} cfuhash_get (cfuhash_table_t * @var{ht}, const char * @var{key})
@end deftypefun
@deftypefun int cfuhash_exists (cfuhash_table_t * @var{ht}, const char * @var{key});
@end deftypefun
@deftypefun {void *} cfuhash_put (cfuhash_table_t * @var{ht}, const char * @var{key}, void * @var{data});
@end deftypefun
@deftypefun {void *} cfuhash_delete (cfuhash_table_t * @var{ht}, const char * @var{key});
@end deftypefun
@deftypefun int cfuhash_each (cfuhash_table_t * @var{ht}, char ** @var{key}, void ** @var{data});
@end deftypefun
@deftypefun int cfuhash_next (cfuhash_table_t * @var{ht}, char ** @var{key}, void ** @var{data});
@end deftypefun
@deftypefun {void **} cfuhash_keys (cfuhash_table_t * @var{ht}, size_t * @var{num_keys}, int @var{fast});
@end deftypefun
Valid flags for cfuhash_new() or cfuhash_set_flag):
@defvr CFUHASH_NOCOPY_KEYS
Don't copy the key when adding an entry to the hash table.
@end defvr
@defvr CFUHASH_NO_LOCKING
Don't not use any mutexes. Beware that this flag makes the hash
table non thread-safe.
@end defvr
@defvr CFUHASH_FROZEN
Do not rehash (don't grow or shrink the number of buckets in the hash
table when the thresholds are reached).
@end defvr
@defvr CFUHASH_FROZEN_UNTIL_GROWS
Do not rehash until the upper threshold is reached the first time
(useful for preallocating a large hash to avoid rehashing while
filling it).
@end defvr
@defvr CFUHASH_FREE_DATA
Call free() on the values when cfuhash_destroy() is called.
@end defvr
@defvr CFUHASH_IGNORE_CASE
Treat the keys case-insensitively.
@end defvr
@node Linked list, Strings, Hash table, Data structures
@section Linked list
@cindex linked list
@cindex queues
@defspec typedef int (*cfulist_foreach_fn_t)(void * @var{data}, size_t @var{data_size}, void * @var{arg})
Function called for each element in the list when passed to
cfulist_foreach(). A non-zero return value means to stop iteration.
@end defspec
@defspec typedef {void *} (*cfulist_map_fn_t)(void *@var{data}, size_t @var{data_size}, void *@var{arg}, size_t *@var{new_data_size})
Function called for each element in the list when passed to
cfulist_map(). The return value is used to build a new list.
@end defspec
@defspec typedef void (*cfulist_free_fn_t)(void * @var{data})
Function called to free the data in an element.
@end defspec
@deftypefun {cfulist_t *} cfulist_new ();
Returns a new list.
@end deftypefun
@deftypefun {size_t} cfulist_num_entries (cfulist_t *@var{list})
Returns the number of entries in the list.
@end deftypefun
@deftypefun {int} cfulist_push_data (cfulist_t * @var{list}, void * @var{data}, size_t @var{data_size})
Push a value onto the end of the list.
@end deftypefun
@deftypefun {int} cfulist_pop_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size})
Pop a value from the end of the list (removing it from the list).
@end deftypefun
@deftypefun {int} cfulist_unshift_data (cfulist_t * @var{list}, void * @var{data}, size_t @var{data_size})
Add a value at the beginning of the list.
@end deftypefun
@deftypefun {int} cfulist_shift_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size})
Shift a value off the beginning of the list.
@end deftypefun
@deftypefun {int} cfulist_enqueue_data (cfulist_t * @var{list}, void * @var{data}, size_t @var{data_size})
Add a value at the end of the queue (equivalent to push)
@end deftypefun
@deftypefun {int} cfulist_dequeue_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size})
Remove the value at the beginning of the list (equivalent to shift).
@end deftypefun
@deftypefun int cfulist_first_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size});
Return the first entry from the list (without removing it from the list).
@end deftypefun
@deftypefun int cfulist_last_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size});
Return the last entry from the list (without removing it from the list).
@end deftypefun
@deftypefun int cfulist_nth_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size}, size_t @var{n});
Return the nth entry from the list (without removing it from the list). n starts at zero.
@end deftypefun
@deftypefun void cfulist_reset_each (cfulist_t * @var{list});
@end deftypefun
@deftypefun int cfulist_each_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size});
@end deftypefun
@deftypefun int cfulist_next_data (cfulist_t * @var{list}, void ** @var{data}, size_t * @var{data_size});
@end deftypefun
@deftypefun size_t cfulist_foreach (cfulist_t * @var{list}, cfulist_foreach_fn_t @var{fe_fn}, void * @var{arg});
Calls fe_fn() for each element in the list. Also passes arg on each
call. Do not try to manipulate the list inside fe_fn(), as the list
will be locked.
If fe_fn() returns a non-zero value, the iteration over the elements stops.
@end deftypefun
@deftypefun {cfulist_t *}cfulist_map (cfulist_t *@var{list}, cfulist_map_fn_t @var{map_fn}, void *@var{arg});
Creates a new list from the list passed in. Calls map_fn() on each
element in the list. The return value is placed in the corresponding
position in the new list.
@end deftypefun
@deftypefun {void} cfulist_destroy (cfulist_t * @var{list})
Free all resources used by the list.
@end deftypefun
@deftypefun {void} cfulist_destroy (cfulist_t * @var{list}, cfulist_free_fn_t @var{free_fn})
Free all resources used by the list. If free_fn is not NULL, call it
for each element of the list, passing the data to it as a void *.
@end deftypefun
When you don't care about the size of the data
@deftypefun {int} cfulist_push (cfulist_t * @var{list}, void * @var{data})
@end deftypefun
@deftypefun {void *} cfulist_pop (cfulist_t * @var{list});
@end deftypefun
@deftypefun {int} cfulist_unshift (cfulist_t * @var{list}, void * @var{data});
@end deftypefun
@deftypefun {void *} cfulist_shift (cfulist_t * @var{list});
@end deftypefun
@deftypefun {int} cfulist_enqueue (cfulist_t * @var{ist}, void * @var{data});
@end deftypefun
@deftypefun {void *} cfulist_dequeue (cfulist_t * @var{list});
@end deftypefun
Strings -- assume data is a null-terminated string -- size is calculated by strlen(data) + 1
@deftypefun {int} cfulist_push_string (cfulist_t * @var{list}, char * @var{data})
@end deftypefun
@deftypefun {char *} cfulist_pop_string (cfulist_t * @var{list});
@end deftypefun
@deftypefun {int} cfulist_unshift_string (cfulist_t * @var{list}, char * @var{data});
@end deftypefun
@deftypefun {char *} cfulist_shift_string (cfulist_t * @var{list});
@end deftypefun
@deftypefun {int} cfulist_enqueue_string (cfulist_t * @var{list}, char * @var{data});
@end deftypefun
@deftypefun {char *} cfulist_dequeue_string (cfulist_t * @var{list});
@end deftypefun
@deftypefun {char *} cfulist_join (cfulist_t * @var{list}, const char * @var{delimiter})
@end deftypefun
@node Strings, , Linked list, Data structures
@section Strings
@cindex strings
@cindex self-extending strings
@deftypefun {cfustring_t *} cfustring_new (size_t @var{initial_size})
Returns a new String.
@end deftypefun
@deftypefun {cfustring_t *} cfustring_new_from_string (const char * @var{string})
Returns a new String initalized with the given string.
@end deftypefun
@deftypefun {int} cfustring_dup (cfustring_t * @var{cfu_str}, const char * @var{string})
Overwrite anything currently in cfu_str with string.
@end deftypefun
@deftypefun {int} cfustring_clear (cfustring_t * @var{cfu_str})
Truncate the string.
@end deftypefun
@deftypefun {int} cfustring_append (cfustring_t * @var{cfu_str}, const char * @var{str})
Append str to the end of the buffer in cfu_str.
@end deftypefun
@deftypefun {char *} cfustring_get_buffer (cfustring_t * @var{cfu_str})
Get the buffer used to hold the string. Do not free() it, as it is
used directly by cfustring and will be destroyed when
cfustring_destroy() is called.
@end deftypefun
@deftypefun {char *} cfustring_get_buffer_copy (cfustring_t * @var{cfu_str})
Same as cfustring_get_buffer(), except return a copy of the string.
Caller is responsible for deallocating the buffer with free().
@end deftypefun
@deftypefun {cfustring_t **} cfustring_split (cfustring_t * @var{cfu_str}, size_t * @var{num_strings}, size_t @var{limit}, @var{...})
Split cfu_str on one or more delimiting strings, e.g.,
cfustring_split(cfu_str, 2, 0, "\r\n", "\n"). Use a limit > 0 if
you want to only get back a certain number of strings and ignore
any extra delimiters.
@end deftypefun
@deftypefun {char **} cfustring_split_to_c_str (cfustring_t * @var{cfu_str}, size_t * @var{num_strings}, size_t @var{limit}, @var{...})
Same as cfustring_split(), except return an array of C-strings.
Caller is responsible for deallocating the buffers.
@end deftypefun
@deftypefun {int} cfustring_destroy (cfustring_t * @var{cfu_str})
Free all resources allocated by cfu_str.
@end deftypefun
@deftypefun {char *} cfustring_dup_c_str (const char * @var{str})
Duplicate the C string str. Caller must free with free().
@end deftypefun
@deftypefun {char *} cfustring_dup_c_str_n (const char * @var{str}, size_t @var{n})
Same as cfustring_dup_c_str(), but only copy at most n chars
@end deftypefun
@deftypefun size_t cfustring_sprintf (cfustring_t * @var{cfu_str}, const char * @var{fmt}, @var{...});
Like sprintf(), but writes to a self-extending string.
@end deftypefun
@deftypefun size_t cfustring_vsprintf (cfustring_t * @var{cfu_str}, const char * @var{fmt}, va_list @var{ap});
Like vsprintf(), but writes to a self-extending string.
@end deftypefun
@deftypefun {char *} cfustring_sprintf_c_str (const char * @var{fmt}, @var{...})
Similar to sprintf(), but allocates a C string of the
appropriate size for you and returns it.
@end deftypefun
@deftypefun {char **} cfustring_c_str_split (const char * @var{c_str}, size_t * @var{num_strings}, size_t @var{limit}, @var{...})
Like cfustring_split_to_c_str(), but split a char * instead of a cfustring_t *.
@end deftypefun
@node Conf, Options, Top, Top
@chapter Conf
@cindex configuration file
@cindex apache configuration file
This needs to be better documented.
Apache-style conf files contain directives and containers.
Directives are simple one line specifications with or without
arguments, e.g.,
Doit
Expires On
LoadModule my_mod modules/my_mod.so
Containers have a type and a name associated with them and they
in turn contain directives and/or containers, e.g.,
<MyContainer test1>
Expires Off
<DB devdb>
DBHost db.example.com
DBUser test_user
</DB>
</MyContainer>
Values may be quoted, e.g.
DBUser "test user"
But must be specified on a single line. To escape quotes
within a quoted string, use the '\' character.
@deftypefun {int} cfuconf_parse_file (char * @var{file_path}, cfuconf_t ** @var{conf}, char ** @var{error})
Parse the apache-like conf file specified by file_path,
returning a pointer to a cfuconf_t structure in conf. Returns
zero on success, less than zero on error. If an error occurs
and error is not NULL, it will be set to an error message
(which must be free()'d by the caller).
@end deftypefun
@deftypefun {int} cfuconf_parse_buffer (char * @var{buffer}, cfuconf_t ** @var{conf}, char ** @var{error})
Same as cfuconf_parse_file(), except assume the contents of the
file are already in buffer.
@end deftypefun
@deftypefun {void} cfuconf_destroy (cfuconf_t * @var{conf})
Free all resources used by the cfuconf_t structure
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuconf_get_containers (cfuconf_t * @var{conf})
Get a hash of containers at the top level of conf
@end deftypefun
@deftypefun {cfuhash_table_t *} cfuconf_get_directives (cfuconf_t * @var{conf})
Get a hash of directives at the to level
@end deftypefun
@deftypefun {int} cfuconf_get_directive_one_arg (cfuconf_t * @var{conf}, char * @var{directive}, char ** @var{rvalue})
Get the value of the given directive, assuming there is only one argument
@end deftypefun
@deftypefun {int} cfuconf_get_directive_two_args (cfuconf_t * @var{conf}, char * @var{directive}, char ** @var{rvalue}, char ** @var{rvalue2})
Get the value of the given directive, assuming there are two arguments
@end deftypefun
@deftypefun {int} cfuconf_get_directive_n_args (cfuconf_t * @var{conf}, char * @var{directive}, size_t @var{n}, @var{...})
Get the value of the given directives, with n arguments
@end deftypefun
@node Options, Thread queue, Conf, Top
@chapter Options
@cindex options
@cindex command-line arguments
@cindex arguments
Command-line arguments can be parsed with the following:
@verbatim
cfuopt_t *opt = cfuopt_new();
cfuopt_add_entry(opt, "verbose|v!", &verbose, "Verbosity", "");
cfuopt_add_entry(opt, "file|f:s", &file, "File to load", "FILE");
cfuopt_add_entry(opt, "count|c|n=i", &count, "Count to run", "COUNT");
cfuopt_add_entry(opt, "scale|s:f", &scale, "Scaling factor", "SCALE");
cfuopt_parse(opt, &argc, &argv, &error);
/* do stuff here with the options */
cfuopt_destroy(opt);
free(file);
@end verbatim
@deftypefun {cfuopt_t *}cfuopt_new ()
Returns a new options context.
@end deftypefun
@deftypefun void cfuopt_add_entry (cfuopt_t *@var{context}, const char *@var{opt_str}, void *@var{arg_data}, const char *@var{description}, const char *@var{arg_description})
Adds to the list of known options.
@end deftypefun
@deftypefun void cfuopt_parse (cfuopt_t *@var{context}, int *@var{argc}, char ***@var{argv}, char **@var{error})
Parses the command line and modifies argc and argv to account for left over arguments.
@end deftypefun
@deftypefun {char *}cfuopt_get_help_str (cfuopt_t *@var{context})
Returns a help string built from the entries added with cfuopt_add_entry().
@end deftypefun
@deftypefun void cfuopt_destroy (cfuopt_t *@var{context})
Frees up resources used by the option parser.
@end deftypefun
@node Thread queue, Timer, Options, Top
@chapter Thread queue
@cindex threading
@cindex thread queue
cfuthread_queue provides a way to serialize requests for a resource
where you want the resource to be accessed from a single thread only.
For instance, for a database connection where making calls in separate
threads does not work properly, you can use cfuthread_queue.
cfuthread_queue_new() creates a new thread that waits for something to
be added to the queue. Once something is added, the thread will
process the data by calling the function you pass as an argument to
the cfuthread_queue_new() function.
@deftypefun {cfuthread_queue_t *} cfuthread_queue_new (cfuthread_queue_fn_t @var{fn})
Creates a new thread queue structure that will run the given
function when a request is received.
@end deftypefun
@deftypefun {cfuthread_queue_t *} cfuthread_queue_new_with_cleanup (cfuthread_queue_fn_t @var{fn}, cfuthread_queue_init_t @var{init_fn}, void * @var{init_arg}, cfuthread_queue_cleanup_t @var{cleanup_fn}, void * @var{cleanup_arg})
Same as cfuthread_queue_new(), but with an initialization
function that gets called with the argument init_arg when the
thread is created, and a cleanup function that gets called with
the argument cleanup_arg when the thread exits, e.g., when
cfuthread_queue_destroy() is called.
@end deftypefun
@deftypefun {void *} cfuthread_queue_make_request (cfuthread_queue_t * @var{tq}, void * @var{data})
Add a request to the queue. data will get passed to the
function fn given to cfuthread_queue_new when it reaches the
front of the queue.
@end deftypefun
@deftypefun {void} cfuthread_queue_destroy (cfuthread_queue_t * @var{tq})
Free up resources used by the queue, in addition to canceling
the thread.
@end deftypefun
@node Timer, License, Thread queue, Top
@chapter Timer
@cindex timer
@deftypefun {cfutime_t} *cfutime_new ();
Return a new cfutime structure.
@end deftypefun
@deftypefun void cfutime_begin (cfutime_t *@var{time})
Start the timer.
@end deftypefun
@deftypefun {void} cfutime_end (cfutime_t * @var{time})
Stop the timer.
@end deftypefun
@deftypefun {double} cfutime_elapsed (cfutime_t * @var{time})
Return the number of seconds elapsed as a double.
@end deftypefun
@deftypefun {void} cfutime_free (cfutime_t * @var{time})
Deallocate resources allocated for time.
@end deftypefun
@node License, , Timer, Top
@unnumbered License
@cindex license
Copyright @copyright{} 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
@node Concept index, Function index, Top, Top
@unnumbered Concept index
@printindex cp
@node Function index, , Concept index, Top
@unnumbered Function index
@printindex fn
@contents
@bye

133
doc/mdate-sh Executable file
View File

@ -0,0 +1,133 @@
#!/bin/sh
# Get modification time of a file or directory and pretty-print it.
# Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Prevent date giving response in another language.
LANG=C
export LANG
LC_ALL=C
export LC_ALL
LC_TIME=C
export LC_TIME
save_arg1="$1"
# Find out how to get the extended ls output of a file or directory.
if ls -L /dev/null 1>/dev/null 2>&1; then
ls_command='ls -L -l -d'
else
ls_command='ls -l -d'
fi
# A `ls -l' line looks as follows on OS/2.
# drwxrwx--- 0 Aug 11 2001 foo
# This differs from Unix, which adds ownership information.
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
#
# To find the date, we split the line on spaces and iterate on words
# until we find a month. This cannot work with files whose owner is a
# user named `Jan', or `Feb', etc. However, it's unlikely that `/'
# will be owned by a user whose name is a month. So we first look at
# the extended ls output of the root directory to decide how many
# words should be skipped to get the date.
# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
set - x`$ls_command /`
# Find which argument is the month.
month=
command=
until test $month
do
shift
# Add another shift to the command.
command="$command shift;"
case $1 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
done
# Get the extended ls output of the file or directory.
set - x`eval "$ls_command \"\$save_arg1\""`
# Remove all preceding arguments
eval $command
# Get the month. Next argument is day, followed by the year or time.
case $1 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
day=$2
# Here we have to deal with the problem that the ls output gives either
# the time of day or the year.
case $3 in
*:*) set `date`; eval year=\$$#
case $2 in
Jan) nummonthtod=1;;
Feb) nummonthtod=2;;
Mar) nummonthtod=3;;
Apr) nummonthtod=4;;
May) nummonthtod=5;;
Jun) nummonthtod=6;;
Jul) nummonthtod=7;;
Aug) nummonthtod=8;;
Sep) nummonthtod=9;;
Oct) nummonthtod=10;;
Nov) nummonthtod=11;;
Dec) nummonthtod=12;;
esac
# For the first six month of the year the time notation can also
# be used for files modified in the last year.
if (expr $nummonth \> $nummonthtod) > /dev/null;
then
year=`expr $year - 1`
fi;;
*) year=$3;;
esac
# The result.
echo $day $month $year

4
doc/stamp-vti Normal file
View File

@ -0,0 +1,4 @@
@set UPDATED 4 September 2005
@set UPDATED-MONTH September 2005
@set EDITION 0.03
@set VERSION 0.03

6735
doc/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

4
doc/version.texi Normal file
View File

@ -0,0 +1,4 @@
@set UPDATED 4 September 2005
@set UPDATED-MONTH September 2005
@set EDITION 0.03
@set VERSION 0.03

11
examples/Makefile.am Normal file
View File

@ -0,0 +1,11 @@
noinst_PROGRAMS = hash_usage large_hash strings conf_example conf_example2 opt_example
LDADD = -L$(top_srcdir)/src -lcfu
if DEBUG
AM_CFLAGS = -Wall -W -Werror -I$(top_srcdir)/include -DCFU_DEBUG=1
else
AM_CFLAGS = -Wall -W -Werror -I$(top_srcdir)/include
endif
AM_LDFLAGS = -Xlinker -rpath -Xlinker $(top_src_dir)/src

418
examples/Makefile.in Normal file
View File

@ -0,0 +1,418 @@
# Makefile.in generated by automake 1.9.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SOURCES = conf_example.c conf_example2.c hash_usage.c large_hash.c opt_example.c strings.c
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
noinst_PROGRAMS = hash_usage$(EXEEXT) large_hash$(EXEEXT) \
strings$(EXEEXT) conf_example$(EXEEXT) conf_example2$(EXEEXT) \
opt_example$(EXEEXT)
subdir = examples
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(noinst_PROGRAMS)
conf_example_SOURCES = conf_example.c
conf_example_OBJECTS = conf_example.$(OBJEXT)
conf_example_LDADD = $(LDADD)
conf_example_DEPENDENCIES =
conf_example2_SOURCES = conf_example2.c
conf_example2_OBJECTS = conf_example2.$(OBJEXT)
conf_example2_LDADD = $(LDADD)
conf_example2_DEPENDENCIES =
hash_usage_SOURCES = hash_usage.c
hash_usage_OBJECTS = hash_usage.$(OBJEXT)
hash_usage_LDADD = $(LDADD)
hash_usage_DEPENDENCIES =
large_hash_SOURCES = large_hash.c
large_hash_OBJECTS = large_hash.$(OBJEXT)
large_hash_LDADD = $(LDADD)
large_hash_DEPENDENCIES =
opt_example_SOURCES = opt_example.c
opt_example_OBJECTS = opt_example.$(OBJEXT)
opt_example_LDADD = $(LDADD)
opt_example_DEPENDENCIES =
strings_SOURCES = strings.c
strings_OBJECTS = strings.$(OBJEXT)
strings_LDADD = $(LDADD)
strings_DEPENDENCIES =
DEFAULT_INCLUDES = -I. -I$(srcdir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = conf_example.c conf_example2.c hash_usage.c large_hash.c \
opt_example.c strings.c
DIST_SOURCES = conf_example.c conf_example2.c hash_usage.c \
large_hash.c opt_example.c strings.c
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUG_FALSE = @DEBUG_FALSE@
DEBUG_TRUE = @DEBUG_TRUE@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBCFU_TYPE_u_int = @LIBCFU_TYPE_u_int@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
LDADD = -L$(top_srcdir)/src -lcfu
@DEBUG_FALSE@AM_CFLAGS = -Wall -W -Werror -I$(top_srcdir)/include
@DEBUG_TRUE@AM_CFLAGS = -Wall -W -Werror -I$(top_srcdir)/include -DCFU_DEBUG=1
AM_LDFLAGS = -Xlinker -rpath -Xlinker $(top_src_dir)/src
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu examples/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
conf_example$(EXEEXT): $(conf_example_OBJECTS) $(conf_example_DEPENDENCIES)
@rm -f conf_example$(EXEEXT)
$(LINK) $(conf_example_LDFLAGS) $(conf_example_OBJECTS) $(conf_example_LDADD) $(LIBS)
conf_example2$(EXEEXT): $(conf_example2_OBJECTS) $(conf_example2_DEPENDENCIES)
@rm -f conf_example2$(EXEEXT)
$(LINK) $(conf_example2_LDFLAGS) $(conf_example2_OBJECTS) $(conf_example2_LDADD) $(LIBS)
hash_usage$(EXEEXT): $(hash_usage_OBJECTS) $(hash_usage_DEPENDENCIES)
@rm -f hash_usage$(EXEEXT)
$(LINK) $(hash_usage_LDFLAGS) $(hash_usage_OBJECTS) $(hash_usage_LDADD) $(LIBS)
large_hash$(EXEEXT): $(large_hash_OBJECTS) $(large_hash_DEPENDENCIES)
@rm -f large_hash$(EXEEXT)
$(LINK) $(large_hash_LDFLAGS) $(large_hash_OBJECTS) $(large_hash_LDADD) $(LIBS)
opt_example$(EXEEXT): $(opt_example_OBJECTS) $(opt_example_DEPENDENCIES)
@rm -f opt_example$(EXEEXT)
$(LINK) $(opt_example_LDFLAGS) $(opt_example_OBJECTS) $(opt_example_LDADD) $(LIBS)
strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES)
@rm -f strings$(EXEEXT)
$(LINK) $(strings_LDFLAGS) $(strings_OBJECTS) $(strings_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_example.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_example2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_usage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large_hash.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_example.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strings.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstPROGRAMS ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

42
examples/conf_example.c Normal file
View File

@ -0,0 +1,42 @@
/* Creation date: 2005-07-08 23:43:37
* Authors: Don
* Change log:
*/
#include "cfuconf.h"
#include <stdlib.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
int main(int argc, char **argv) {
char *file_path = "/tmp/test.conf";
cfuconf_t *conf = NULL;
char *error = NULL;
argc = argc;
argv = argv;
if (cfuconf_parse_file(file_path, &conf, &error) < 0) {
fprintf(stderr, "Error loading conf file: %s\n", error);
free(error);
exit(-1);
}
fprintf(stderr, "\n\nvals:\n\n");
cfuconf_pretty_print_conf(conf, stderr, 0);
cfuconf_destroy(conf);
return 0;
}

48
examples/conf_example2.c Normal file
View File

@ -0,0 +1,48 @@
/* Creation date: 2005-07-25 22:00:49
* Authors: Don
* Change log:
*/
#include "cfuconf.h"
#include <stdlib.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
int main(int argc, char **argv) {
cfuconf_t *conf = NULL;
char *error = NULL;
char *buffer = "SetVar Test1 Val1\n"
"SetVar Test2 Val2\n"
"<test_container c1>\n"
" SetVar Test3 Val3\n"
" SetVar Test4 Val4\n"
"</test_container>\n";
argc = argc;
argv = argv;
if (cfuconf_parse_buffer(buffer, &conf, &error) < 0) {
fprintf(stderr, "Error loading conf buffer: %s\n", error);
free(error);
exit(-1);
}
fprintf(stderr, "\n\nvals:\n\n");
cfuconf_pretty_print_conf(conf, stderr, 0);
cfuconf_destroy(conf);
return 0;
}

133
examples/hash_usage.c Normal file
View File

@ -0,0 +1,133 @@
/* Creation date: 2005-06-25 10:33:53
* Authors: Don
* Change log:
*/
#include "cfuhash.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int
remove_func(void *key, size_t key_size, void *data, size_t data_size, void *arg) {
data_size = data_size;
data = data;
arg = arg;
if (key_size > 7) {
if (!strncasecmp(key, "content", 7)) {
return 1;
}
}
return 0;
}
int main(int argc, char **argv) {
cfuhash_table_t *hash = cfuhash_new_with_initial_size(30);
cfuhash_table_t *hash2 = cfuhash_new_with_initial_size(4);
char *val = NULL;
char list[32][2][32];
size_t i;
argc = argc;
argv = argv;
cfuhash_set_flag(hash, CFUHASH_FROZEN_UNTIL_GROWS);
for (i = 0; i < 32; i++) {
sprintf(list[i][0], "test_var%d", i);
sprintf(list[i][1], "value%d", i);
}
cfuhash_put(hash, "var1", "value1");
cfuhash_put(hash, "var2", "value2");
cfuhash_put(hash, "var3", "value3");
cfuhash_put(hash, "var4", "value4");
cfuhash_pretty_print(hash, stdout);
printf("\n\n");
val = (char *)cfuhash_delete(hash, "var3");
printf("delete: got back '%s'\n\n", val);
cfuhash_pretty_print(hash, stdout);
printf("\n\n");
val = cfuhash_get(hash, "var2");
printf("got var2='%s'\n", val);
printf("var4 %s\n", cfuhash_exists(hash, "var4") ? "exists" : "does NOT exist!!!");
printf("%d entries, %d buckets used out of %d\n", cfuhash_num_entries(hash), cfuhash_num_buckets_used(hash), cfuhash_num_buckets(hash));
cfuhash_pretty_print(hash, stdout);
cfuhash_clear(hash);
for (i = 0; i < 32; i++) {
size_t used = cfuhash_num_buckets_used(hash);
size_t num_buckets = cfuhash_num_buckets(hash);
size_t num_entries = cfuhash_num_entries(hash);
cfuhash_put(hash, list[i][0], list[i][1]);
printf("%d entries, %d buckets used out of %d (%.2f)\n", num_entries, used, num_buckets, (float)num_entries/(float)num_buckets);
}
cfuhash_pretty_print(hash, stdout);
{
char **keys = NULL;
size_t *key_sizes = NULL;
size_t key_count = 0;
keys = (char **)cfuhash_keys_data(hash, &key_count, &key_sizes, 0);
printf("\n\nkeys (%u):\n", key_count);
for (i = 0; i < key_count; i++) {
printf("\t%s\n", keys[i]);
free(keys[i]);
}
free(keys);
free(key_sizes);
}
cfuhash_clear(hash);
printf("%d entries, %d buckets used out of %d\n", cfuhash_num_entries(hash), cfuhash_num_buckets_used(hash), cfuhash_num_buckets(hash));
cfuhash_destroy(hash);
printf("\n\n====> case-insensitive hash:\n\n");
hash = cfuhash_new_with_initial_size(30);
cfuhash_set_flag(hash, CFUHASH_IGNORE_CASE);
cfuhash_put(hash, "Content-Type", "value1");
cfuhash_put(hash, "Content-Length", "value2");
cfuhash_put(hash2, "var3", "value3");
cfuhash_put(hash2, "var4", "value4");
cfuhash_pretty_print(hash, stdout);
cfuhash_copy(hash2, hash);
cfuhash_pretty_print(hash, stdout);
{
char keys[4][32] = { "content-type", "content-length", "Var3", "VaR4" };
size_t i = 0;
for (i = 0; i < 4; i++) {
printf("%s => %s\n", keys[i], (char *)cfuhash_get(hash, keys[i]));
}
cfuhash_foreach_remove(hash, remove_func, NULL, NULL);
printf("\n\nafter removing content*:\n");
for (i = 0; i < 4; i++) {
printf("%s => %s\n", keys[i], (char *)cfuhash_get(hash, keys[i]));
}
}
cfuhash_destroy(hash);
cfuhash_destroy(hash2);
return 0;
}

162
examples/large_hash.c Normal file
View File

@ -0,0 +1,162 @@
/* Creation date: 2005-06-26 00:41:47
* Authors: Don
* Change log:
*/
#include "cfuhash.h"
#include "cfutime.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static
void free_data(void *data) {
free(data);
}
static char *
dup_str(const char *str) {
size_t len = strlen(str);
char *ns = (char *)calloc(len + 1, 1);
memcpy(ns, str, len);
return ns;
}
static u_int32_t
hash_func1(const void *key, size_t length) {
size_t i = length;
u_int hash = 0;
char *s = (char *)key;
while (i--) hash = hash * 33 + *s++;
return hash;
}
/* From libtc */
#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<<8); \
c -= a; c -= b; c ^= (b>>13); \
a -= b; a -= c; a ^= (c>>12); \
b -= c; b -= a; b ^= (a<<16); \
c -= a; c -= b; c ^= (b>>5); \
a -= b; a -= c; a ^= (c>>3); \
b -= c; b -= a; b ^= (a<<10); \
c -= a; c -= b; c ^= (b>>15); \
}
typedef u_int32_t ub4;
static u_int
hash_func_tc(const void *key, size_t length)
{
register ub4 a,b,c,len;
const char *k = key;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = 0; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while(len >= 12){
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch(len){ /* all the case statements fall through */
case 11: c+=((ub4)k[10]<<24);
case 10: c+=((ub4)k[9]<<16);
case 9 : c+=((ub4)k[8]<<8);
/* the first byte of c is reserved for the length */
case 8 : b+=((ub4)k[7]<<24);
case 7 : b+=((ub4)k[6]<<16);
case 6 : b+=((ub4)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((ub4)k[3]<<24);
case 3 : a+=((ub4)k[2]<<16);
case 2 : a+=((ub4)k[1]<<8);
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix(a,b,c);
/*-------------------------------------------- report the result */
return c;
}
/* End of code from Jenkins */
static int
time_it(cfuhash_function_t hf, double *elapsed_time, u_int32_t num_tests) {
cfuhash_table_t *hash = cfuhash_new_with_initial_size(30);
u_int32_t flags = 0;
char key[32];
char value[32];
size_t i;
size_t used;
size_t num_buckets;
size_t num_entries;
cfutime_t *time = cfutime_new();
/* freeze the hash so that it won't shrink while we put in all the data */
flags = cfuhash_set_flag(hash, CFUHASH_FROZEN_UNTIL_GROWS);
cfuhash_set_hash_function(hash, hf);
cfutime_begin(time);
for (i = 0; i < num_tests; i++) {
sprintf(key, "%u", 15000000 - i);
sprintf(value, "value%d", i);
cfuhash_put(hash, key, dup_str(value));
}
cfutime_end(time);
*elapsed_time = cfutime_elapsed(time);
used = cfuhash_num_buckets_used(hash);
num_buckets = cfuhash_num_buckets(hash);
num_entries = cfuhash_num_entries(hash);
printf("%d entries, %d/%d buckets (%.2f%%), %.2f%% threshold check\n", num_entries, used, num_buckets, 100.0 * (float)used/(float)num_buckets, 100.0 * (float)num_entries/(float)num_buckets);
cfuhash_destroy_with_free_fn(hash, free_data);
return 0;
}
int main(int argc, char **argv) {
double elapsed_time = 0;
u_int32_t num_tests = 3000000;
argc = argc;
argv = argv;
printf("mutex is %d bytes\n", sizeof(pthread_mutex_t));
printf("default:\n");
time_it(NULL, &elapsed_time, num_tests);
printf("%.3f seconds\n", elapsed_time);
printf("\n");
fflush(stdout);
printf("hash_func1:\n");
time_it(hash_func1, &elapsed_time, num_tests);
printf("%.3f seconds\n", elapsed_time);
printf("\n");
fflush(stdout);
printf("hash_func_tc:\n");
time_it(hash_func_tc, &elapsed_time, num_tests);
printf("%.3f seconds\n", elapsed_time);
printf("\n");
fflush(stdout);
return 1;
}

56
examples/opt_example.c Normal file
View File

@ -0,0 +1,56 @@
/* Creation date: 2005-09-04 14:46:45
* Authors: Don
* Change log:
*/
#include "cfuopt.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
cfuopt_t *opt = cfuopt_new();
int verbose = 0;
char *file = NULL;
long count = 0;
char *error = NULL;
double scale = 0.0;
char *help = NULL;
int i = 0;
argc = argc;
argv = argv;
cfuopt_add_entry(opt, "verbose|v!", &verbose, "Verbosity", "");
cfuopt_add_entry(opt, "file|f:s", &file, "File to load", "FILE");
cfuopt_add_entry(opt, "count|c|n=i", &count, "Count to run", "COUNT");
cfuopt_add_entry(opt, "scale|s:f", &scale, "Scaling factor", "SCALE");
printf("\nStarting args:\n");
for (i = 0; i < argc; i++) {
printf("\t%s\n", argv[i]);
}
cfuopt_parse(opt, &argc, &argv, &error);
printf("\n\n");
printf("verbose=%d\n", verbose);
printf("file=%s\n", file);
printf("count=%ld\n", count);
printf("scale=%f\n", scale);
help = cfuopt_get_help_str(opt);
printf("\n\nhelp:\n%s\n", help);
free(help);
printf("\nLeft over args:\n");
for (i = 0; i < argc; i++) {
printf("\t%s\n", argv[i]);
}
cfuopt_destroy(opt);
free(file);
return 0;
}

99
examples/strings.c Normal file
View File

@ -0,0 +1,99 @@
/* Creation date: 2005-06-27 22:19:17
* Authors: Don
* Change log:
*/
#include "cfustring.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
int main(int argc, char **argv) {
cfustring_t *buf = cfustring_new_with_initial_size(32);
char **strings = NULL;
size_t num_strings = 0;
size_t num_headers = 0;
size_t i = 0;
char *ref_addr = NULL;
char *s = NULL;
cfustring_t *header_block = cfustring_new_from_string(
"User-Agent: curl/7.10.6 (i386-redhat-linux-gnu) libcurl/7.10.6 OpenSSL/0.9.7a ipv6 zlib/1.2.0.7\r\n"
"Host: localhost:9095\r\n"
"Pragma: no-cache\r\n"
"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n");
cfustring_t **header_lines = NULL;
argc = argc; argv = argv; /* avoid compiler warnings */
cfustring_append(buf, "test^*string%2^*3");
strings = cfustring_split_to_c_str(buf, &num_strings, 0, "%", "^*", NULL);
printf("got back %u strings\n", num_strings);
printf("\n");
for (i = 0; i < num_strings; i++) {
printf("'%s'\n", strings[i]);
}
for (i = 0; i < num_strings; i++) {
free(strings[i]);
}
free(strings);
header_lines = cfustring_split(header_block, &num_headers, 0, "\r\n", "\n", NULL);
printf("got back %u headers\n", num_strings);
for (i = 0; i < num_headers; i++) {
strings = cfustring_split_to_c_str(header_lines[i], &num_strings, 2, ":", NULL);
if (num_strings != 2) {
/* bad header */
size_t j = 0;
for (j = 0; j < num_strings; j++) free(strings[j]);
free(strings);
fprintf(stderr, "bad header: %u strings from split -- '%s'\n", num_strings, cfustring_get_buffer(header_lines[i]));
continue;
}
printf("Got header '%s' => '%s'\n", strings[0], strings[1]);
free(strings[0]); free(strings[1]);
free(strings);
}
for (i = 0; i < num_headers; i++) {
assert(cfu_is_string(header_lines[i]));
cfustring_destroy(header_lines[i]);
}
free(header_lines);
cfustring_sprintf(buf, "this %% is a string - '%.2f'", 509.0);
printf("cfustring_sprintf(): '%s'\n", cfustring_get_buffer(buf));
cfustring_destroy(buf);
s = cfustring_sprintf_c_str("this is a test with a num: '%u'\n", 5);
printf("got: %s\n", s);
free(s);
ref_addr = cfustring_sprintf_c_str("%p", (void *)header_block);
cfustring_destroy(header_block);
printf("\n\nheader_block as ref_addr='%s'\n\n", ref_addr);
free(ref_addr);
return 0;
}

82
include/cfu.h Normal file
View File

@ -0,0 +1,82 @@
/* Creation date: 2005-07-06 07:34:51
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LIBCFU_H_
#define _LIBCFU_H_
#include <stdio.h>
#include <cfutypes.h>
#ifdef __cplusplus
#define CFU_BEGIN_DECLS extern "C" {
#define CFU_END_DECLS }
#else
#define CFU_BEGIN_DECLS
#define CFU_END_DECLS
#endif
CFU_BEGIN_DECLS
/* define this to get thread-safe versions of functions */
#ifndef _REENTRANT
#define _REENTRANT 1
#endif
#ifndef _THREAD_SAFE
#define _THREAD_SAFE 1
#endif
#define LIBCFU_VERSION "0.03"
typedef enum { libcfu_t_none = 0, libcfu_t_hash_table, libcfu_t_list, libcfu_t_string,
libcfu_t_time, libcfu_t_conf } libcfu_type;
struct libcfu_item;
typedef struct libcfu_item libcfu_item_t;
extern libcfu_type cfu_get_type(void *item);
extern int cfu_is_hash(void *item);
extern int cfu_is_list(void *item);
extern int cfu_is_string(void *item);
extern int cfu_is_time(void *item);
extern int cfu_is_conf(void *item);
CFU_END_DECLS
#endif

82
include/cfu.h.in Normal file
View File

@ -0,0 +1,82 @@
/* Creation date: 2005-07-06 07:34:51
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LIBCFU_H_
#define _LIBCFU_H_
#include <stdio.h>
#include <cfutypes.h>
#ifdef __cplusplus
#define CFU_BEGIN_DECLS extern "C" {
#define CFU_END_DECLS }
#else
#define CFU_BEGIN_DECLS
#define CFU_END_DECLS
#endif
CFU_BEGIN_DECLS
/* define this to get thread-safe versions of functions */
#ifndef _REENTRANT
#define _REENTRANT 1
#endif
#ifndef _THREAD_SAFE
#define _THREAD_SAFE 1
#endif
#define LIBCFU_VERSION "@VERSION@"
typedef enum { libcfu_t_none = 0, libcfu_t_hash_table, libcfu_t_list, libcfu_t_string,
libcfu_t_time, libcfu_t_conf } libcfu_type;
struct libcfu_item;
typedef struct libcfu_item libcfu_item_t;
extern libcfu_type cfu_get_type(void *item);
extern int cfu_is_hash(void *item);
extern int cfu_is_list(void *item);
extern int cfu_is_string(void *item);
extern int cfu_is_time(void *item);
extern int cfu_is_conf(void *item);
CFU_END_DECLS
#endif

126
include/cfuconf.h Normal file
View File

@ -0,0 +1,126 @@
/* Creation date: 2005-07-08 22:24:03
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFU_CONF_H_
#define _CFU_CONF_H_
#include <cfu.h>
#include <cfuhash.h>
#include <cfulist.h>
#include <cfustring.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct cfuconf;
typedef struct cfuconf cfuconf_t;
/* Apache-style conf files contain directives and containers.
Directives are simple one line specifications with or without
arguments, e.g.,
Doit
Expires On
LoadModule my_mod modules/my_mod.so
Containers have a type and a name associated with them and they
in turn contain directives and/or containers, e.g.,
<MyContainer test1>
Expires Off
<DB devdb>
DBHost db.example.com
DBUser test_user
</DB>
</MyContainer>
Values may be quoted, e.g.
DBUser "test user"
But must be specified on a single line. To escape quotes
within a quoted string, use the '\' character.
*/
/* Parse the apache-like conf file specified by file_path,
* returning a pointer to a cfuconf_t structure in conf. Returns
* zero on success, less than zero on error. If an error occurs
* and error is not NULL, it will be set to an error message
* (which must be free()'d by the caller).
*/
extern int cfuconf_parse_file(char *file_path, cfuconf_t **conf, char **error);
/* Same as cfuconf_parse_file(), except assume the contents of the
* file are already in buffer.
*/
extern int cfuconf_parse_buffer(char *buffer, cfuconf_t **conf, char **error);
/* Free all resources used by the cfuconf_t structure */
extern void cfuconf_destroy(cfuconf_t *conf);
/* Get a hash of containers at the top level of conf */
extern cfuhash_table_t * cfuconf_get_containers(cfuconf_t *conf);
/* Get a hash of directives at the to level */
extern cfuhash_table_t * cfuconf_get_directives(cfuconf_t *conf);
/* Get the value of the given directive, assuming there is only one argument */
extern int cfuconf_get_directive_one_arg(cfuconf_t *conf, char *directive, char **rvalue);
/* Get the value of the given directive, assuming there are two arguments */
extern int cfuconf_get_directive_two_args(cfuconf_t *conf, char *directive, char **rvalue,
char **rvalue2);
/* Get the value of the given directives, with n arguments */
extern int cfuconf_get_directive_n_args(cfuconf_t *conf, char *directive, size_t n, ...);
/* Print out a representation of the parsed configuration */
extern void cfuconf_pretty_print_conf(cfuconf_t *conf, FILE *fp, size_t indent_level);
#ifdef __cplusplus
}
#endif
#endif

277
include/cfuhash.h Normal file
View File

@ -0,0 +1,277 @@
/* Creation date: 2005-06-24 21:22:09
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFU_HASH_H_
#define _CFU_HASH_H_
#include <cfu.h>
#include <sys/types.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* The hash table itself. */
struct cfuhash_table;
typedef struct cfuhash_table cfuhash_table_t;
/* Prototype for a pointer to a hashing function. */
typedef u_int32_t (*cfuhash_function_t)(const void *key, size_t length);
/* Prototype for a pointer to a free function. */
typedef void (*cfuhash_free_fn_t)(void *data);
/* Prototype for a pointer to a function that determines whether
* or not to remove an entry from the hash.
*/
typedef int (*cfuhash_remove_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
void *arg);
/* Prototype for a pointer to a function to be called foreach
* key/value pair in the hash by cfuhash_foreach(). Iteration
* stops if a non-zero value is returned.
*/
typedef int (*cfuhash_foreach_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
void *arg);
/* Creates a new hash table. */
extern cfuhash_table_t * cfuhash_new();
/* Creates a new hash table with the specified size (number of
* buckets).
*/
extern cfuhash_table_t * cfuhash_new_with_initial_size(size_t size);
/* Creates a new hash table with the specified flags. Pass zero
* for flags if you want the defaults.
*/
extern cfuhash_table_t * cfuhash_new_with_flags(u_int32_t flags);
/* Same as cfuhash_new() except automatically calls cfuhash_set_free_fn(). */
extern cfuhash_table_t * cfuhash_new_with_free_fn(cfuhash_free_fn_t ff);
/* Copies entries in src to dst */
extern int cfuhash_copy(cfuhash_table_t *src, cfuhash_table_t *dst);
/* Returns a new hash containing entries from both hash tables.
* For any entries with the same key, the one from ht2 wins.
*/
extern cfuhash_table_t * cfuhash_merge(cfuhash_table_t *ht1, cfuhash_table_t *ht2,
u_int32_t flags);
/* Sets the hashing function to use when computing which bucket to add
* entries to. It should return a 32-bit unsigned integer. By
* default, Perl's hashing algorithm is used.
*/
extern int cfuhash_set_hash_function(cfuhash_table_t *ht, cfuhash_function_t hf);
/* Sets the thresholds for when to rehash. The ratio
* num_entries/buckets is compared against low and high. If it is
* below 'low' or above 'high', the hash will shrink or grow,
* respectively, unless the flags say to do otherwise.
*/
extern int cfuhash_set_thresholds(cfuhash_table_t *ht, float low, float high);
/* Sets the function to use when removing an entry from the hash,
* i.e., when replacing an existing entry, deleting an entry, or
* clearing the hash. It is passed the value of the entry as a
* void *.
*/
extern int cfuhash_set_free_function(cfuhash_table_t * ht, cfuhash_free_fn_t ff);
/* Returns the hash's flags. See below for flag definitions. */
extern u_int32_t cfuhash_get_flags(cfuhash_table_t *ht);
/* Sets a flag. */
extern u_int32_t cfuhash_set_flag(cfuhash_table_t *ht, u_int32_t flag);
/* Clears a flag. */
extern u_int32_t cfuhash_clear_flag(cfuhash_table_t *ht, u_int32_t new_flag);
/* Returns the value for the entry with given key. If key_size is -1,
* key is assumed to be a null-terminated string. If data_size is not
* NULL, the size of the value is placed into data_size.
*/
extern int cfuhash_get_data(cfuhash_table_t *ht, const void *key, size_t key_size,
void **data, size_t *data_size);
/* Returns 1 if an entry with the given key exists in the hash, 0 otherwise. */
extern int cfuhash_exists_data(cfuhash_table_t *ht, const void *key, size_t key_size);
/* Inserts the given data value into the hash and associates it with
* key. If key_size is -1, key is assumed to be a null-terminated
* string. If data_size is -1, it is assumed to be a null-terminated
* string (it's length will be calculated using strlen). If
* data_size is zero, it will be returned as zero when the value is
* requested.
*/
extern int cfuhash_put_data(cfuhash_table_t *ht, const void *key, size_t key_size, void *data,
size_t data_size, void **r);
/* Clears the hash table (deletes all entries). */
extern void cfuhash_clear(cfuhash_table_t *ht);
/* Deletes the entry in the hash associated with key. If the entry
* existed, it's value will be returned.
*/
extern void * cfuhash_delete_data(cfuhash_table_t *ht, const void *key, size_t key_size);
/* Returns all the keys from the hash. The number of keys is placed
* into the value pointed to by num_keys. If key_sizes is not NULL,
* it will be set to an array of key sizes. If fast is zero, copies
* of the keys are returned. Otherwise, pointers to the real keys
* will be returned.
*/
extern void **cfuhash_keys_data(cfuhash_table_t *ht, size_t *num_keys, size_t **key_sizes,
int fast);
/* Initializes a loop over all the key/value pairs in the hash. It
* returns the first key/value pair (see cfuhash_next_data()). 1 is
* returned if there are any entries in the hash. 0 is returned
* otherwise.
*/
extern int cfuhash_each_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
size_t *data_size);
/* Gets the next key/value pair from the hash. You must initialize
* the loop using cfuhash_each_data() before calling this function.
* If a entry is left to return, 1 is returned from the function. 0
* is returned if there are no more entries in the hash.
*/
extern int cfuhash_next_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
size_t *data_size);
/* Iterates over the key/value pairs in the hash, passing each one
* to r_fn, and removes all entries for which r_fn returns true.
* If ff is not NULL, it is the passed the data to be freed. arg
* is passed to r_fn.
*/
extern size_t cfuhash_foreach_remove(cfuhash_table_t *ht, cfuhash_remove_fn_t r_fn,
cfuhash_free_fn_t ff, void *arg);
/* Iterates over the key/value pairs in the hash, passing each one
* to fe_fn, along with arg. This locks the hash, so do not call
* any operations on the hash from within fe_fn unless you really
* know what you're doing. A non-zero return value from fe_fn()
* stops the iteration.
*/
extern size_t cfuhash_foreach(cfuhash_table_t *ht, cfuhash_foreach_fn_t fe_fn, void *arg);
/* Frees all resources allocated by the hash. If ff is not NULL, it
* is called for each hash entry with the value of the entry passed as
* its only argument. If ff is not NULL, it overrides any function
* set previously with cfuhash_set_free_function().
*/
extern int cfuhash_destroy(cfuhash_table_t *ht);
extern int cfuhash_destroy_with_free_fn(cfuhash_table_t *ht, cfuhash_free_fn_t ff);
/* Rebuild the hash to better accomodate the number of entries. See
* cfuhash_set_thresholds().
*/
extern int cfuhash_rehash(cfuhash_table_t *ht);
/* Returns the number entries in the hash. */
extern size_t cfuhash_num_entries(cfuhash_table_t *ht);
/* Returns the number of buckets allocated for the hash. */
extern size_t cfuhash_num_buckets(cfuhash_table_t *ht);
/* Returns the number of buckets actually used out of the total number
* allocated for the hash.
*/
extern size_t cfuhash_num_buckets_used(cfuhash_table_t *ht);
/* Assumes all the keys and values are null-terminated strings and
* returns a bencoded string representing the hash (see
* http://www.bittorrent.com/protocol.html)
*/
extern char * cfuhash_bencode_strings(cfuhash_table_t *ht);
/* Locks the hash. Use this with the each and next functions for
* concurrency control. Note that the hash is locked automatically
* when doing inserts and deletes, so if you lock the hash and then
* try to insert something into it, you may get into a deadlock,
* depending on your system defaults for how mutexes work.
*/
extern int cfuhash_lock(cfuhash_table_t *ht);
/* Unlocks the hash. Use this with the each an next functions for
* concurrency control. The caveat for cfuhash_lcok() also applies to
* this function.
*/
extern int cfuhash_unlock(cfuhash_table_t *ht);
/* Pretty print the hash's key/value pairs to the stream fp. It is
* assumed that all the keys and values are null-terminated strings.
*/
extern int cfuhash_pretty_print(cfuhash_table_t *ht, FILE *fp);
/* These are like the _data versions of these functions, with the
* following exceptions:
* 1) They assume that the key provided is a null-terminated string.
* 2) They don't worry about the size of the data.
* 3) Returned keys or values are the return value of the function.
*/
extern void * cfuhash_get(cfuhash_table_t *ht, const char *key);
extern int cfuhash_exists(cfuhash_table_t *ht, const char *key);
extern void * cfuhash_put(cfuhash_table_t *ht, const char *key, void *data);
extern void * cfuhash_delete(cfuhash_table_t *ht, const char *key);
extern int cfuhash_each(cfuhash_table_t *ht, char **key, void **data);
extern int cfuhash_next(cfuhash_table_t *ht, char **key, void **data);
extern void **cfuhash_keys(cfuhash_table_t *ht, size_t *num_keys, int fast);
/* hash table flags */
#define CFUHASH_NOCOPY_KEYS 1 /* do not copy the key when inserting a hash entry */
#define CFUHASH_NO_LOCKING (1 << 1) /* do not make the hash thread-safe */
#define CFUHASH_FROZEN (1 << 2) /* do not rehash when the size thresholds are reached */
#define CFUHASH_FROZEN_UNTIL_GROWS (1 << 3) /* do not shrink the hash until it has grown */
#define CFUHASH_FREE_DATA (1 << 4) /* call free() on each value when the hash is destroyed */
#define CFUHASH_IGNORE_CASE (1 << 5) /* treat keys case-insensitively */
#ifdef __cplusplus
}
#endif
#endif

167
include/cfulist.h Normal file
View File

@ -0,0 +1,167 @@
/* Creation date: 2005-07-02 22:25:10
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFU_LIST_
#define _CFU_LIST_
#include <cfu.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
/* The list itself. */
struct cfulist;
typedef struct cfulist cfulist_t;
/* Function called for each element in the list when passed to
* cfulist_foreach(). A non-zero return value means to stop
* iteration.
*/
typedef int (*cfulist_foreach_fn_t)(void *data, size_t data_size, void *arg);
/* Function called for each element in the list when passed to
* cfulist_map(). The return value is used to build a new
* list.
*/
typedef void * (*cfulist_map_fn_t)(void *data, size_t data_size, void *arg,
size_t *new_data_size);
/* Function called to free the data in an element. */
typedef void (*cfulist_free_fn_t)(void *data);
/* Returns a new list. */
extern cfulist_t * cfulist_new();
/* Same as cfulist_new(), but set a function to be called on each
* element when the list is destroyed.
*/
extern cfulist_t * cfulist_new_with_free_fn(cfulist_free_fn_t free_fn);
/* Returns the number of entries in the list. */
extern size_t cfulist_num_entries(cfulist_t *list);
/* Manipulating list entries */
/* Push a value onto the end of the list. */
extern int cfulist_push_data(cfulist_t *list, void *data, size_t data_size);
/* Pop a value from the end of the list. */
extern int cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size);
/* Add a value at the beginning of the list. */
extern int cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size);
/* Shift a value off the beginning of the list. */
extern int cfulist_shift_data(cfulist_t *list, void **data, size_t *data_size);
/* Add a value at the end of the queue (equivalent to push) */
extern int cfulist_enqueue_data(cfulist_t *list, void *data, size_t data_size);
/* Remove the value at the beginning of the list (equivalent to shift). */
extern int cfulist_dequeue_data(cfulist_t *list, void **data, size_t *data_size);
/* Return the last entry from the list (without removing it from
* the list).
*/
extern int cfulist_first_data(cfulist_t *list, void **data, size_t *data_size);
/* Return the last entry from the list (without removing it from
* the list).
*/
extern int cfulist_last_data(cfulist_t *list, void **data, size_t *data_size);
/* Return the nth entry from the list (without removing it from
* the list). n starts at zero.
*/
extern int cfulist_nth_data(cfulist_t *list, void **data, size_t *data_size, size_t n);
extern void cfulist_reset_each(cfulist_t *list);
extern int cfulist_each_data(cfulist_t *list, void **data, size_t *data_size);
extern int cfulist_next_data(cfulist_t *list, void **data, size_t *data_size);
/* Calls fe_fn() for each element in the list. Also passes arg on
* each call. If fe_fn() returns a non-zero value, the iteration
* over the elements stops.
*/
extern size_t cfulist_foreach(cfulist_t *list, cfulist_foreach_fn_t fe_fn, void *arg);
/* Creates a new list from the list passed in. Calls map_fn() on
* each element in the list. The return value is placed in the
* corresponding position in the new list.
*/
extern cfulist_t *cfulist_map(cfulist_t *list, cfulist_map_fn_t map_fn, void *arg);
/* Free all resources used by the list. */
extern void cfulist_destroy(cfulist_t *list);
extern void cfulist_destroy_with_free_fn(cfulist_t *list, cfulist_free_fn_t free_fn);
/* When you don't care about the size of the data */
extern int cfulist_push(cfulist_t *list, void *data);
extern void * cfulist_pop(cfulist_t *list);
extern int cfulist_unshift(cfulist_t *list, void *data);
extern void * cfulist_shift(cfulist_t *list);
extern int cfulist_enqueue(cfulist_t *list, void *data);
extern void *cfulist_dequeue(cfulist_t *list);
/* Strings -- assume data is a null-terminated string -- size is
* calculated by strlen(data) + 1
*/
extern int cfulist_push_string(cfulist_t *list, char *data);
extern char * cfulist_pop_string(cfulist_t *list);
extern int cfulist_unshift_string(cfulist_t *list, char *data);
extern char * cfulist_shift_string(cfulist_t *list);
extern int cfulist_enqueue_string(cfulist_t *list, char *data);
extern char *cfulist_dequeue_string(cfulist_t *list);
extern char *cfulist_join(cfulist_t *list, const char *delimiter);
#ifdef __cplusplus
}
#endif
#endif

38
include/cfuopt.h Normal file
View File

@ -0,0 +1,38 @@
/* Creation date: 2005-09-04 12:54:41
* Authors: Don
* Change log:
*/
#include "cfu.h"
#ifndef _CFU_OPT_H_
#define _CFU_OPT_H_
CFU_BEGIN_DECLS
struct cfuopt_struct;
typedef struct cfuopt_struct cfuopt_t;
/* Returns a new options context */
extern cfuopt_t *cfuopt_new();
/* Adds to the list of known options. */
extern void cfuopt_add_entry(cfuopt_t *context, const char *opt_str, void *arg_data,
const char *description, const char *arg_description);
/* Parses the command line and modifies argc and argv to account for
* left over arguments.
*/
extern void cfuopt_parse(cfuopt_t *context, int *argc, char ***argv, char **error);
/* Returns a help string built from the entries added with
* cfuopt_add_entry().
*/
extern char * cfuopt_get_help_str(cfuopt_t *context);
/* Frees up resources used by the option parser. */
extern void cfuopt_destroy(cfuopt_t *context);
CFU_END_DECLS
#endif

126
include/cfustring.h Normal file
View File

@ -0,0 +1,126 @@
/* Creation date: 2005-06-26 19:56:34
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFU_STRING_H_
#define _CFU_STRING_H_
#include <cfu.h>
#include <string.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
struct cfustring;
typedef struct cfustring cfustring_t;
/* Returns a new String. */
extern cfustring_t * cfustring_new();
/* Returns a new String, but preallocates a buffer of the given size. */
extern cfustring_t * cfustring_new_with_initial_size(size_t initial_size);
/* Returns a new String initalized with the given string. */
extern cfustring_t * cfustring_new_from_string(const char *string);
/* Overwrite anything currently in cfu_str with string. */
extern int cfustring_dup(cfustring_t *cfu_str, const char *string);
/* Truncate the string. */
extern int cfustring_clear(cfustring_t *cfu_str);
/* Append str to the end of the buffer in cfu_str. */
extern int cfustring_append(cfustring_t *cfu_str, const char *str);
/* Get the buffer used to hold the string. Do not free() it, as it is
* used directly by cfustring and will be destroyed when
* cfustring_destroy() is called.
*/
extern char * cfustring_get_buffer(cfustring_t *cfu_str);
/* Same as cfustring_get_buffer(), except return a copy of the string.
* Caller is responsible for deallocating the buffer with free().
*/
extern char * cfustring_get_buffer_copy(cfustring_t *cfu_str);
/* Split cfu_str on one or more delimiting strings, e.g.,
* cfustring_split(cfu_str, 2, 0, "\r\n", "\n"). Use a limit > 0 if
* you want to only get back a certain number of strings and ignore
* any extra delimiters.
*/
extern cfustring_t ** cfustring_split(cfustring_t *cfu_str, size_t *num_strings,
size_t limit, ...);
/* Same as cfustring_split(), except return an array of C-strings.
* Caller is responsible for deallocating the buffers.
*/
extern char ** cfustring_split_to_c_str(cfustring_t *cfu_str, size_t *num_strings,
size_t limit, ...);
/* Free all resources allocated by cfu_str. */
extern int cfustring_destroy(cfustring_t *cfu_str);
/* Duplicate the C string str. Caller must free with free(). */
extern char * cfustring_dup_c_str(const char *str);
/* Same as cfustring_dup_c_str(), but only copy at most n chars */
extern char * cfustring_dup_c_str_n(const char *str, size_t n);
/* Like sprintf(), but writes to a self-extending string. */
extern size_t cfustring_sprintf(cfustring_t *cfu_str, const char *fmt, ...);
/* Like vsprintf(), but writes to a self-extending string. */
extern size_t cfustring_vsprintf(cfustring_t *cfu_str, const char *fmt, va_list ap);
/* Similar to sprintf(), but allocates a C string of the
* appropriate size for you and returns it.
*/
extern char * cfustring_sprintf_c_str(const char *fmt, ...);
/* Like cfustring_split_to_c_str(), but split a char * instead of a cfustring_t *. */
extern char ** cfustring_c_str_split(const char *c_str, size_t *num_strings, size_t limit, ...);
#ifdef __cplusplus
}
#endif
#endif

100
include/cfuthread_queue.h Normal file
View File

@ -0,0 +1,100 @@
/* Creation date: 2005-07-26 08:19:33
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFUTHREAD_QUEUE_H
#define _CFUTHREAD_QUEUE_H
#include <cfu.h>
#ifdef __cplusplus
extern "C" {
#endif
/* cfuthread_queue provides a way to serialize requests for a
* resource where you want the resource to be accessed from a
* single thread only. For instance, for a database connection
* where making calls in separate threads does not work properly,
* you can use cfuthread_queue. cfuthread_queue_new() creates a
* new thread that waits for something to be added to the queue.
* Once something is added, the thread will process the data by
* calling the function you pass as an argument to the
* cfuthread_queue_new() function.
*/
struct cfuthread_queue;
typedef struct cfuthread_queue cfuthread_queue_t;
typedef void * (*cfuthread_queue_fn_t)(void *arg);
typedef void (*cfuthread_queue_init_t)(void *arg);
typedef void (*cfuthread_queue_cleanup_t)(void *arg);
/* Creates a new thread queue structure that will run the given
* function when a request is received.
*/
extern cfuthread_queue_t * cfuthread_queue_new(cfuthread_queue_fn_t fn);
/* Same as cfuthread_queue_new(), but with an initialization
* function that gets called with the argument init_arg when the
* thread is created, and a cleanup function that gets called with
* the argument cleanup_arg when the thread exits, e.g., when
* cfuthread_queue_destroy() is called.
*/
extern cfuthread_queue_t * cfuthread_queue_new_with_cleanup(cfuthread_queue_fn_t fn,
cfuthread_queue_init_t init_fn, void *init_arg, cfuthread_queue_cleanup_t cleanup_fn,
void *cleanup_arg);
/* Add a request to the queue. data will get passed to the
* function fn given to cfuthread_queue_new when it reaches the
* front of the queue.
*/
extern void * cfuthread_queue_make_request(cfuthread_queue_t * tq, void *data);
/* Free up resources used by the queue, in addition to canceling
* the thread.
*/
extern void cfuthread_queue_destroy(cfuthread_queue_t *);
#ifdef __cplusplus
}
#endif
#endif

74
include/cfutime.h Normal file
View File

@ -0,0 +1,74 @@
/* Creation date: 2005-06-26 18:09:46
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CFU_TIME_H_
#define _CFU_TIME_H_
#include <cfu.h>
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
#endif
struct cfutime;
typedef struct cfutime cfutime_t;
/* Return a new cfutime structure. */
extern cfutime_t *cfutime_new();
/* Start the timer. */
extern void cfutime_begin(cfutime_t *time);
/* Stop the timer. */
extern void cfutime_end(cfutime_t *time);
/* Return the number of seconds elapsed as a double. */
extern double cfutime_elapsed(cfutime_t *time);
/* Deallocate resources allocated for time. */
extern void cfutime_free(cfutime_t *time);
#ifdef __cplusplus
}
#endif
#endif

13
include/cfutypes.h Normal file
View File

@ -0,0 +1,13 @@
/* Creation date: 2005-07-30 16:44:11
* Authors: Don
* Change log:
*/
#ifndef _CFU_TYPES_H_
#define _CFU_TYPES_H_
#include <sys/types.h>
/* u_int is defined */
#endif

13
include/cfutypes.h.in Normal file
View File

@ -0,0 +1,13 @@
/* Creation date: 2005-07-30 16:44:11
* Authors: Don
* Change log:
*/
#ifndef _CFU_TYPES_H_
#define _CFU_TYPES_H_
#include <sys/types.h>
@LIBCFU_TYPE_u_int@
#endif

294
install-sh Executable file
View File

@ -0,0 +1,294 @@
#!/bin/sh
#
# install - install a program, script, or datafile
#
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "$0: no input file specified" >&2
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d "$dst" ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "$0: no destination specified" >&2
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d "$dst" ]
then
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp=$pathcomp$1
shift
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "$pathcomp"
else
:
fi
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename "$dst"`
else
:
fi
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up temp files at exit.
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# Now remove or move aside any old file at destination location. We try this
# two ways since rm can't unlink itself on some systems and the destination
# file might be busy for other reasons. In this case, the final cleanup
# might fail but the new file should still install successfully.
{
if [ -f "$dstdir/$dstfile" ]
then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
{
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}

336
missing Executable file
View File

@ -0,0 +1,336 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - GNU automake"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
fi
if [ -f "$file" ]; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit 1
fi
;;
makeinfo)
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
# We have makeinfo, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
tar)
shift
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
fi
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

111
mkinstalldirs Executable file
View File

@ -0,0 +1,111 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# End:
# mkinstalldirs ends here

28
src/Makefile.am Normal file
View File

@ -0,0 +1,28 @@
lib_LIBRARIES = libcfu.a
libcfu_a_SOURCES = cfuhash.c cfutime.c cfustring.c cfulist.c cfuconf.c cfuthread_queue.c cfu.c cfuopt.c
bin_PROGRAMS = libcfu-config
CFU_CONFIG_DEFINES = -DCFU_LIBDIR="\"@libdir@\"" -DCFU_LIBS="\"@LIBS@\"" -DCFU_INCLUDEDIR="\"@includedir@\"" -DCFU_PREFIX="\"@prefix@\"" -DCFU_EXEC_PREFIX="\"@exec_prefix@\""
if DEBUG
AM_CFLAGS = -Wall -W -DCFU_DEBUG=1 $(CFU_CONFIG_DEFINES)
else
AM_CFLAGS = -Wall -W $(CFU_CONFIG_DEFINES)
endif
include_HEADERS = $(top_srcdir)/include/cfu.h $(top_srcdir)/include/cfuhash.h \
$(top_srcdir)/include/cfutime.h $(top_srcdir)/include/cfustring.h \
$(top_srcdir)/include/cfulist.h $(top_srcdir)/include/cfuconf.h \
$(top_srcdir)/include/cfuthread_queue.h $(top_srcdir)/include/cfutypes.h \
$(top_srcdir)/include/cfuopt.h
# libcfu_a_LDFLAGS = -lpthread
INCLUDES = -I$(top_srcdir)/include
default: libcfu.a libcfu-config
libcfu-config.o: libcfu-config.c
libcfu-config: libcfu.a libcfu-config.o
$(CC) $(CFLAGS) -o libcfu-config libcfu-config.o libcfu.a -pthread

497
src/Makefile.in Normal file
View File

@ -0,0 +1,497 @@
# Makefile.in generated by automake 1.9.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SOURCES = $(libcfu_a_SOURCES) libcfu-config.c
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
bin_PROGRAMS = libcfu-config$(EXEEXT)
subdir = src
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in TODO
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(includedir)"
libLIBRARIES_INSTALL = $(INSTALL_DATA)
LIBRARIES = $(lib_LIBRARIES)
AR = ar
ARFLAGS = cru
libcfu_a_AR = $(AR) $(ARFLAGS)
libcfu_a_LIBADD =
am_libcfu_a_OBJECTS = cfuhash.$(OBJEXT) cfutime.$(OBJEXT) \
cfustring.$(OBJEXT) cfulist.$(OBJEXT) cfuconf.$(OBJEXT) \
cfuthread_queue.$(OBJEXT) cfu.$(OBJEXT) cfuopt.$(OBJEXT)
libcfu_a_OBJECTS = $(am_libcfu_a_OBJECTS)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
libcfu_config_SOURCES = libcfu-config.c
libcfu_config_OBJECTS = libcfu-config.$(OBJEXT)
libcfu_config_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(srcdir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libcfu_a_SOURCES) libcfu-config.c
DIST_SOURCES = $(libcfu_a_SOURCES) libcfu-config.c
includeHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUG_FALSE = @DEBUG_FALSE@
DEBUG_TRUE = @DEBUG_TRUE@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBCFU_TYPE_u_int = @LIBCFU_TYPE_u_int@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
lib_LIBRARIES = libcfu.a
libcfu_a_SOURCES = cfuhash.c cfutime.c cfustring.c cfulist.c cfuconf.c cfuthread_queue.c cfu.c cfuopt.c
CFU_CONFIG_DEFINES = -DCFU_LIBDIR="\"@libdir@\"" -DCFU_LIBS="\"@LIBS@\"" -DCFU_INCLUDEDIR="\"@includedir@\"" -DCFU_PREFIX="\"@prefix@\"" -DCFU_EXEC_PREFIX="\"@exec_prefix@\""
@DEBUG_FALSE@AM_CFLAGS = -Wall -W $(CFU_CONFIG_DEFINES)
@DEBUG_TRUE@AM_CFLAGS = -Wall -W -DCFU_DEBUG=1 $(CFU_CONFIG_DEFINES)
include_HEADERS = $(top_srcdir)/include/cfu.h $(top_srcdir)/include/cfuhash.h \
$(top_srcdir)/include/cfutime.h $(top_srcdir)/include/cfustring.h \
$(top_srcdir)/include/cfulist.h $(top_srcdir)/include/cfuconf.h \
$(top_srcdir)/include/cfuthread_queue.h $(top_srcdir)/include/cfutypes.h \
$(top_srcdir)/include/cfuopt.h
# libcfu_a_LDFLAGS = -lpthread
INCLUDES = -I$(top_srcdir)/include
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-libLIBRARIES: $(lib_LIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f=$(am__strip_dir) \
echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
$(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
@$(POST_INSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
p=$(am__strip_dir) \
echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
$(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
else :; fi; \
done
uninstall-libLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
p=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLIBRARIES:
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
libcfu.a: $(libcfu_a_OBJECTS) $(libcfu_a_DEPENDENCIES)
-rm -f libcfu.a
$(libcfu_a_AR) libcfu.a $(libcfu_a_OBJECTS) $(libcfu_a_LIBADD)
$(RANLIB) libcfu.a
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfuconf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfuhash.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfulist.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfuopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfustring.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfuthread_queue.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfutime.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfu-config.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
uninstall-info-am:
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
rm -f "$(DESTDIR)$(includedir)/$$f"; \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
$(mkdir_p) $(distdir)/../include
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-libLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-includeHEADERS
install-exec-am: install-binPROGRAMS install-libLIBRARIES
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \
uninstall-info-am uninstall-libLIBRARIES
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic clean-libLIBRARIES ctags distclean \
distclean-compile distclean-generic distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-binPROGRAMS install-data install-data-am install-exec \
install-exec-am install-includeHEADERS install-info \
install-info-am install-libLIBRARIES install-man install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-includeHEADERS \
uninstall-info-am uninstall-libLIBRARIES
default: libcfu.a libcfu-config
libcfu-config.o: libcfu-config.c
libcfu-config: libcfu.a libcfu-config.o
$(CC) $(CFLAGS) -o libcfu-config libcfu-config.o libcfu.a -pthread
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

4
src/TODO Normal file
View File

@ -0,0 +1,4 @@
* command line option parsing

81
src/cfu.c Normal file
View File

@ -0,0 +1,81 @@
/* Creation date: 2005-07-09 21:44:59
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
struct libcfu_item {
libcfu_type type;
};
extern libcfu_type
cfu_get_type(void *item) {
if (!item) return libcfu_t_none;
return ((libcfu_item_t *)item)->type;
}
extern int
cfu_is_hash(void *item) {
if (cfu_get_type(item) == libcfu_t_hash_table) return 1;
return 0;
}
extern int
cfu_is_list(void *item) {
if (cfu_get_type(item) == libcfu_t_list) return 1;
return 0;
}
extern int
cfu_is_string(void *item) {
if (cfu_get_type(item) == libcfu_t_string) return 1;
return 0;
}
extern int
cfu_is_time(void *item) {
if (cfu_get_type(item) == libcfu_t_time) return 1;
return 0;
}
extern int
cfu_is_conf(void *item) {
if (cfu_get_type(item) == libcfu_t_conf) return 1;
return 0;
}

811
src/cfuconf.c Normal file
View File

@ -0,0 +1,811 @@
/* Creation date: 2005-07-08 22:23:31
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
#include "cfuconf.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
struct cfuconf {
libcfu_type type;
cfuhash_table_t *containers;
cfuhash_table_t *directives;
char *container_type;
char *container_name;
};
typedef struct cfuconf_stack_entry {
cfuhash_table_t *ht;
char *container_type;
char *container_name;
} cfuconf_stack_entry_t;
static cfuconf_t *
cfuconf_new() {
cfuconf_t *conf = (cfuconf_t *)calloc(1, sizeof(cfuconf_t));
conf->type = libcfu_t_conf;
conf->containers = cfuhash_new_with_flags(CFUHASH_IGNORE_CASE);
conf->directives = cfuhash_new_with_flags(CFUHASH_IGNORE_CASE);
return conf;
}
static void
_free_val_fn(void *data) {
free(data);
}
static void
_container_free_fn(void *data) {
assert(cfu_is_conf(data));
cfuconf_destroy((cfuconf_t *)data);
}
static void
_container_free_hashes_fn(void *data) {
assert(cfu_is_hash(data));
cfuhash_destroy_with_free_fn((cfuhash_table_t *)data, _container_free_fn);
}
/*
static void
_container_free_foreach_fn(void *key, size_t key_size, void *data, size_t data_size, void *arg) {
key = key;
key_size = key_size;
arg = arg;
data_size = data_size;
assert(cfu_is_hash(data));
cfuhash_destroy_with_free_fn((cfuhash_table_t *)data, _container_free_fn);
}
*/
static void
_directive_free_val_list_fn(void *data) {
cfulist_t *val_list = (cfulist_t *)data;
assert(cfu_is_list(val_list));
cfulist_destroy_with_free_fn(val_list, _free_val_fn);
}
static void
_directive_free_fn(void *data) {
cfulist_t *list = (cfulist_t *)data;
assert(cfu_is_list(list));
cfulist_destroy_with_free_fn(list, _directive_free_val_list_fn);
}
extern void
cfuconf_destroy(cfuconf_t *conf) {
if (conf->containers) {
/* cfuhash_foreach(conf->containers, _container_free_foreach_fn, NULL); */
cfuhash_destroy_with_free_fn(conf->containers, _container_free_hashes_fn);
}
if (conf->directives) {
cfuhash_destroy_with_free_fn(conf->directives, _directive_free_fn);
}
if (conf->container_type) free(conf->container_type);
if (conf->container_name) free(conf->container_name);
free(conf);
}
extern cfuhash_table_t *
cfuconf_get_containers(cfuconf_t *conf) {
if (!conf) return NULL;
return conf->containers;
}
extern cfuhash_table_t *
cfuconf_get_directives(cfuconf_t *conf) {
if (!conf) return NULL;
return conf->directives;
}
static int
_get_directive_last_val_list(cfuconf_t *conf, char *directive, cfulist_t **val_list) {
cfuhash_table_t *directives = NULL;
void *data = NULL;
size_t data_size = 0;
cfulist_t *list = NULL;
if (!conf) {
return -1;
}
directives = cfuconf_get_directives(conf);
if (!directives) {
return -1;
}
if (cfuhash_get_data(directives, (void *)directive, -1, &data, &data_size)) {
void *val = NULL;
size_t size = 0;
list = (cfulist_t *)data;
if (cfulist_last_data(list, &val, &size)) {
*val_list = (cfulist_t *)val;
return 0;
}
}
return -1;
}
extern int
cfuconf_get_directive_one_arg(cfuconf_t *conf, char *directive, char **rvalue) {
cfulist_t *val_list = NULL;
void *val = NULL;
size_t size = 0;
if (_get_directive_last_val_list(conf, directive, &val_list) >= 0) {
if (cfulist_first_data(val_list, &val, &size)) {
*rvalue = (char *)val;
return 0;
}
} else {
return -1;
}
return -1;
}
extern int
cfuconf_get_directive_two_args(cfuconf_t *conf, char *directive, char **rvalue, char **rvalue2) {
return cfuconf_get_directive_n_args(conf, directive, 2, rvalue, rvalue2);
}
extern int
cfuconf_get_directive_n_args(cfuconf_t *conf, char *directive, size_t n, ...) {
va_list ap;
size_t i = 0;
char **ptr = NULL;
int rv = -1;
cfulist_t *val_list = NULL;
void *val = NULL;
size_t size = 0;
if (_get_directive_last_val_list(conf, directive, &val_list) >= 0) {
va_start(ap, n);
for (i = 0; i < n; i++) {
ptr = va_arg(ap, char **);
if (cfulist_nth_data(val_list, &val, &size, 1)) {
*ptr = (char *)val;
} else {
i--;
break;
}
}
va_end(ap);
if (i == n) rv = 0;
}
return rv;
}
/*
static cfuconf_stack_entry_t *
new_stack_entry(cfuhash_table_t *ht, char *container_type, char *container_name) {
cfuconf_stack_entry_t *entry =
(cfuconf_stack_entry_t *)calloc(1, sizeof(cfuconf_stack_entry_t));
entry->ht = ht;
entry->container_type = container_type;
entry->container_name = container_name;
return entry;
}
*/
static char *
cfuconf_get_line(FILE *fp) {
char buf[1024];
cfustring_t *str = cfustring_new_with_initial_size(16);
char *rv = NULL;
if (fgets(buf, 1024, fp)) {
cfustring_append(str, buf);
while (strlen(buf) == 1024 - 1 && buf[1024 - 2] != '\n') {
if (!fgets(buf, 1024, fp)) break;
cfustring_append(str, buf);
}
rv = cfustring_get_buffer_copy(str);
}
cfustring_destroy(str);
return rv;
}
static cfulist_t *
_slurp_file_from_fp(FILE *fp) {
cfulist_t *lines = cfulist_new();
char *buf = NULL;
while ( (buf = cfuconf_get_line(fp)) ) {
cfulist_push(lines, buf);
}
return lines;
}
static inline int
_is_whitespace(char c) {
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
return 1;
}
return 0;
}
static inline char *
_eat_whitespace(char *buf) {
char *ptr = buf;
while (_is_whitespace(*ptr)) {
ptr++;
}
return ptr;
}
static char *
_get_name(char **buf) {
char *ptr = *buf;
char *name = *buf;
name = _eat_whitespace(*buf);
ptr = name;
if (!*ptr || *ptr == '>') {
*buf = ptr;
return NULL;
}
while (*ptr && *ptr != '>' && !_is_whitespace(*ptr)) ptr++;
name = cfustring_dup_c_str_n(name, ptr - name);
*buf = ptr;
return name;
}
static char *
_get_value(char **buf) {
char *ptr = *buf;
char *value = *buf;
value = _eat_whitespace(*buf);
ptr = value;
if (!*ptr || *ptr == '>') {
*buf = ptr;
return NULL;
}
while (*ptr && *ptr != '>' && !_is_whitespace(*ptr)) ptr++;
value = cfustring_dup_c_str_n(value, ptr - value);
*buf = ptr;
return value;
}
static char *
_dup_c_str_n_drop_escape(const char *str, size_t n, char escape) {
size_t len = n;
char *ns = NULL;
char *ptr = NULL;
char *ns_ptr = NULL;
char last_char = '\000';
char *end = (char *)str + n;
if (n == 0) return NULL;
ptr = (char *)str;
ns_ptr = ns = (char *)calloc(len + 1, 1);
last_char = *ptr;
for (ptr = (char *)str; ptr < end; ptr++) {
if (*ptr == escape && (last_char != escape || ptr == (char *)str)) {
if (ptr == (char *)str) {
if (*(ptr + 1) == escape) {
last_char = *ptr;
*ns_ptr = *ptr;
ns_ptr++;
}
}
last_char = *ptr;
} else {
last_char = *ptr;
*ns_ptr = *ptr;
ns_ptr++;
}
}
*ns_ptr = '\000';
return ns;
}
static char *
_get_quoted_value(char **buf, char quote) {
char *ptr = NULL;
char *value = NULL;
char last_char = '\000';
int done = 0;
int found_escape = 0;
if (!buf) return NULL;
if (!*buf) return NULL;
ptr = value = *buf;
last_char = *ptr;
while (!done) {
while (*ptr && *ptr != quote) {
if (*ptr == '\\') found_escape = 1;
last_char = *ptr;
ptr++;
}
if (last_char != '\\' || !*ptr) done = 1;
else {
if (last_char == '\\') {
ptr++;
found_escape = 1;
}
}
}
if (!*ptr) return NULL;
*buf = ptr;
if (found_escape) {
value = _dup_c_str_n_drop_escape(value, ptr - value, '\\');
} else {
value = cfustring_dup_c_str_n(value, ptr - value);
}
return value;
}
static char *
_get_next_value(char **buf) {
char *ptr = *buf;
char *value = *buf;
value = _eat_whitespace(*buf);
ptr = value;
if (!*ptr || *ptr == '>') {
*buf = ptr;
return NULL;
}
if (*ptr == '"' || *ptr == '\'') {
char quote = *ptr;
ptr++;
value = _get_quoted_value(&ptr, quote);
} else {
while (*ptr && *ptr != '>' && !_is_whitespace(*ptr)) ptr++;
value = cfustring_dup_c_str_n(value, ptr - value);
}
*buf = ptr;
return value;
}
#if 0
static char *
_get_long_value(char **buf) {
char *ptr = *buf;
char *value = *buf;
size_t len = strlen(*buf);
value = _eat_whitespace(*buf);
ptr = *buf + len;
while (ptr > value && _is_whitespace(*ptr)) {
ptr--;
}
if (ptr == value) return NULL;
value = cfustring_dup_c_str_n(value, ptr - value - 1);
*buf = ptr;
return value;
}
#endif
/* FIXME: implement these */
/* get directives */
/* get_containers */
/* get_containers_of_type */
/* xpath type access */
static cfuconf_t *
_cfuconf_parse_list(cfulist_t *lines, char **error) {
char *line = NULL;
char *ptr = NULL;
cfulist_t *stack = cfulist_new();
size_t cur_line = 0;
cfuconf_t *conf = cfuconf_new();
cfuconf_t *cur_conf = NULL;
cur_conf = conf;
while ( (line = (char *)cfulist_shift(lines)) ) {
cur_line++;
ptr = _eat_whitespace(line);
if (!*ptr || *ptr == '#') {
/* blank line or comment */
free(line);
continue;
}
if (*ptr == '<') { /* opening or closing container tag */
ptr++;
if (*ptr == '/') {
/* closing tag */
char *name = NULL;
ptr++;
name = _get_name(&ptr);
if (!name) {
if (error) {
*error = cfustring_sprintf_c_str("cfuconf: syntax error at line %u\n",
cur_line);
}
free(line);
free(name);
return NULL;
}
if (strcasecmp(name, cur_conf->container_type)) {
if (error) {
*error = cfustring_sprintf_c_str("Error: syntax error at line %u: "
"unmatched container should be %s\n", cur_line,
cur_conf->container_type);
}
/* FIXME: clean up memory here */
free(line);
free(name);
return NULL;
}
free(name); name = NULL;
cur_conf = cfulist_pop(stack);
if (!cur_conf) {
free(line);
return NULL;
}
/* fprintf(stderr, "====> got closing tag '%s'\n", name); */
} else {
/* opening tag */
char *name = NULL;
char *value = NULL;
cfuhash_table_t *this_hash = NULL;
cfuconf_t *new_conf = NULL;
name = _get_name(&ptr);
if (!name) {
if (error) {
*error = cfustring_sprintf_c_str("cfuconf: syntax error at line %u\n",
cur_line);
}
free(line);
/* FIXME: clean up memory here */
return NULL;
}
ptr = _eat_whitespace(ptr);
value = _get_value(&ptr);
assert(cur_conf);
if ( !(this_hash = cfuhash_get(cur_conf->containers, name)) ) {
this_hash = cfuhash_new_with_flags(CFUHASH_IGNORE_CASE);
cfuhash_put(cur_conf->containers, name, (void *)this_hash);
}
if ( !(new_conf = cfuhash_get(this_hash, value)) ) {
new_conf = cfuconf_new();
new_conf->container_type = name;
new_conf->container_name = value;
cfuhash_put(this_hash, value, (void *)new_conf);
} else {
free(name); name = NULL;
free(value); value = NULL;
}
cfulist_push(stack, (void *)cur_conf);
cur_conf = new_conf;
/*
fprintf(stderr, "====> got opening tag '%s' with param '%s'\n", name, value);
*/
}
} else {
char *name = NULL;
char *value = NULL;
cfulist_t *list = NULL;
cfulist_t *val_list = NULL;
name = _get_name(&ptr);
ptr = _eat_whitespace(ptr);
if ( !(list = cfuhash_get(cur_conf->directives, name)) ) {
list = cfulist_new();
cfuhash_put(cur_conf->directives, name, (void *)list);
}
free(name); name = NULL;
val_list = cfulist_new();
cfulist_enqueue(list, (void *)val_list);
/* fprintf(stderr, "====> got '%s' =>", name); */
while ( (value = _get_next_value(&ptr) ) ) {
/* fprintf(stderr, " '%s'", value); */
cfulist_enqueue(val_list, (void *)value);
if (*ptr) {
ptr++;
ptr = _eat_whitespace(ptr);
}
}
/* fprintf(stderr, "\n"); */
}
free(line);
}
cfulist_destroy(stack);
return conf;
}
extern int
cfuconf_parse_file(char *file_path, cfuconf_t **ret_conf, char **error) {
FILE *fp = NULL;
cfulist_t *lines = NULL;
cfuconf_t *conf = NULL;
if (! (fp = fopen(file_path, "r")) ) {
*ret_conf = NULL;
if (error) {
*error = cfustring_sprintf_c_str("Couldn't open file");
}
return -1;
}
lines = _slurp_file_from_fp(fp);
fclose(fp); fp = NULL;
if (!lines) return -1;
conf = _cfuconf_parse_list(lines, error);
cfulist_destroy(lines);
*ret_conf = conf;
if (conf) return 0;
return -1;
}
extern int
cfuconf_parse_buffer(char *buffer, cfuconf_t **ret_conf, char **error) {
cfulist_t *lines = cfulist_new();
char **strings = NULL;
size_t num_strings = 0;
cfuconf_t *conf = NULL;
size_t i = 0;
if (!buffer) return -1;
strings = cfustring_c_str_split(buffer, &num_strings, 0, "\r\n", "\n", NULL);
if (!strings) return -1;
for (i = 0; i < num_strings; i++) {
cfulist_push_string(lines, strings[i]);
}
conf = _cfuconf_parse_list(lines, error);
cfulist_destroy(lines);
*ret_conf = conf;
free(strings);
if (conf) return 0;
return -1;
}
static void
print_indent(size_t depth, FILE *fp) {
size_t i = 0;
if (depth <= 0) return;
for (i = 0; i < depth; i++) {
fprintf(fp, "\t");
}
}
static void
print_container(cfuhash_table_t *conf_hash, size_t depth) {
char **keys = NULL;
size_t num_keys = 0;
void *val = NULL;
cfulist_t *ol = NULL;
cfulist_t *il = NULL;
size_t i = 0;
size_t data_size = 0;
void *entry = NULL;
cfuhash_table_t *ht = NULL;
keys = (char **)cfuhash_keys(conf_hash, &num_keys, 0);
for (i = 0; i < num_keys; i++) {
entry = cfuhash_get(conf_hash, keys[i]);
if (cfu_is_list(entry)) {
ol = (cfulist_t *)entry;
cfulist_reset_each(ol);
while (cfulist_next_data(ol, (void *)&il, &data_size)) {
print_indent(depth, stderr);
fprintf(stderr, "%s =>", keys[i]);
cfulist_reset_each(il);
while (cfulist_next_data(il, &val, &data_size)) {
fprintf(stderr, " '%s'", (char *)val);
}
fprintf(stderr, "\n");
}
} else if (cfu_is_hash(entry)) {
/* container */
char **container_names = NULL;
size_t num_containers = 0;
char *container_type = keys[i];
char *container_name = NULL;
cfuhash_table_t *container = NULL;
size_t j = 0;
ht = (cfuhash_table_t *)entry;
container_names = (char **)cfuhash_keys(ht, &num_containers, 0);
for (j = 0; j < num_containers; j++) {
container_name = container_names[j];
print_indent(depth, stderr);
fprintf(stderr, "%s: '%s'\n", container_type, container_name);
container = cfuhash_get(ht, container_name);
print_container(container, depth + 1);
}
free(container_names);
}
free(keys[i]);
}
free(keys);
}
typedef struct directive_foreach_ds {
size_t depth;
FILE *fp;
char *name;
} directive_foreach_ds;
static void print_conf(cfuconf_t *conf, size_t depth, FILE *fp);
static int
print_sub_container_foreach_fn(void *name, size_t key_size, void *data, size_t data_size,
void *arg) {
directive_foreach_ds *ds = (directive_foreach_ds *)arg;
name = name;
key_size = key_size;
data_size = data_size;
print_indent(ds->depth, ds->fp);
fprintf(ds->fp, "container %s '%s'\n", ds->name, (char *)name);
print_conf((cfuconf_t *)data, ds->depth + 1, ds->fp);
return 0;
}
static int
print_container_foreach_fn(void *name, size_t key_size, void *data, size_t data_size, void *arg) {
directive_foreach_ds *ds = (directive_foreach_ds *)arg;
directive_foreach_ds *new_ds = (directive_foreach_ds *)calloc(1, sizeof(directive_foreach_ds));
memcpy(new_ds, ds, sizeof(directive_foreach_ds));
new_ds->name = (char *)name;
key_size = key_size;
data_size = data_size;
cfuhash_foreach((cfuhash_table_t *)data, print_sub_container_foreach_fn, new_ds);
free(new_ds);
return 0;
}
static int
print_directive_list_foreach_fn(void *data, size_t data_size, void *arg) {
cfulist_t *val_list = (cfulist_t *)data;
directive_foreach_ds *ds = (directive_foreach_ds *)arg;
char *str = NULL;
data_size = data_size;
if (!val_list) return 0;
assert(cfu_is_list(val_list));
str = cfulist_join(val_list, ", ");
print_indent(ds->depth, ds->fp);
fprintf(ds->fp, "directive '%s' => %s\n", ds->name, str);
free(str);
return 0;
}
static int
print_conf_foreach_directive(void *name, size_t key_size, void *data, size_t data_size, void *arg) {
directive_foreach_ds *ds = (directive_foreach_ds *)arg;
cfulist_t *this_directive_list = (cfulist_t *)data;
directive_foreach_ds *new_ds = (directive_foreach_ds *)calloc(1, sizeof(directive_foreach_ds));
key_size = key_size;
data_size = data_size;
new_ds->fp = ds->fp;
new_ds->depth = ds->depth;
new_ds->name = name;
assert(cfu_is_list(this_directive_list));
cfulist_foreach(this_directive_list, print_directive_list_foreach_fn, new_ds);
free(new_ds);
return 0;
}
static void
print_conf(cfuconf_t *conf, size_t depth, FILE *fp) {
directive_foreach_ds *ds = (directive_foreach_ds *)calloc(1, sizeof(directive_foreach_ds));
ds->depth = depth;
ds->fp = fp;
cfuhash_foreach(cfuconf_get_directives(conf), print_conf_foreach_directive, ds);
cfuhash_foreach(cfuconf_get_containers(conf), print_container_foreach_fn, ds);
free(ds);
}
extern void
cfuconf_pretty_print_conf(cfuconf_t *conf, FILE *fp, size_t indent_level) {
print_conf(conf, indent_level, fp);
}

897
src/cfuhash.c Normal file
View File

@ -0,0 +1,897 @@
/* Creation date: 2005-06-24 21:22:40
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "cfuhash.h"
#include "cfustring.h"
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
typedef struct cfuhash_event_flags {
int resized:1;
int pad:31;
} cfuhash_event_flags;
typedef struct cfuhash_entry {
void *key;
size_t key_size;
void *data;
size_t data_size;
struct cfuhash_entry *next;
} cfuhash_entry;
struct cfuhash_table {
libcfu_type type;
size_t num_buckets;
size_t entries; /* Total number of entries in the table. */
cfuhash_entry **buckets;
pthread_mutex_t mutex;
u_int32_t flags;
cfuhash_function_t hash_func;
size_t each_bucket_index;
cfuhash_entry *each_chain_entry;
float high;
float low;
cfuhash_free_fn_t free_fn;
unsigned int resized_count;
cfuhash_event_flags event_flags;
};
/* Perl's hash function */
static u_int32_t
hash_func(const void *key, size_t length) {
register size_t i = length;
register u_int hv = 0; /* could put a seed here instead of zero */
register const unsigned char *s = (char *)key;
while (i--) {
hv += *s++;
hv += (hv << 10);
hv ^= (hv >> 6);
}
hv += (hv << 3);
hv ^= (hv >> 11);
hv += (hv << 15);
return hv;
}
/* makes sure the real size of the buckets array is a power of 2 */
static u_int
hash_size(u_int s) {
u_int i = 1;
while (i < s) i <<= 1;
return i;
}
static inline void *
hash_key_dup(const void *key, size_t key_size) {
void *new_key = malloc(key_size);
memcpy(new_key, key, key_size);
return new_key;
}
static inline void *
hash_key_dup_lower_case(const void *key, size_t key_size) {
char *new_key = (char *)hash_key_dup(key, key_size);
size_t i = 0;
for (i = 0; i < key_size; i++) new_key[i] = tolower(new_key[i]);
return (void *)new_key;
}
/* returns the index into the buckets array */
static inline u_int
hash_value(cfuhash_table_t *ht, const void *key, size_t key_size, size_t num_buckets) {
u_int hv = 0;
if (key) {
if (ht->flags & CFUHASH_IGNORE_CASE) {
char *lc_key = (char *)hash_key_dup_lower_case(key, key_size);
hv = ht->hash_func(lc_key, key_size);
free(lc_key);
} else {
hv = ht->hash_func(key, key_size);
}
}
/* The idea is the following: if, e.g., num_buckets is 32
(000001), num_buckets - 1 will be 31 (111110). The & will make
sure we only get the first 5 bits which will guarantee the
index is less than 32.
*/
return hv & (num_buckets - 1);
}
static cfuhash_table_t *
_cfuhash_new(size_t size, u_int32_t flags) {
cfuhash_table_t *ht;
size = hash_size(size);
ht = (cfuhash_table_t *)malloc(sizeof(cfuhash_table_t));
memset(ht, '\000', sizeof(cfuhash_table_t));
ht->type = libcfu_t_hash_table;
ht->num_buckets = size;
ht->entries = 0;
ht->flags = flags;
ht->buckets = (cfuhash_entry **)calloc(size, sizeof(cfuhash_entry *));
pthread_mutex_init(&ht->mutex, NULL);
ht->hash_func = hash_func;
ht->high = 0.75;
ht->low = 0.25;
return ht;
}
extern cfuhash_table_t *
cfuhash_new() {
return _cfuhash_new(8, CFUHASH_FROZEN_UNTIL_GROWS);
}
extern cfuhash_table_t *
cfuhash_new_with_initial_size(size_t size) {
if (size == 0) size = 8;
return _cfuhash_new(size, CFUHASH_FROZEN_UNTIL_GROWS);
}
extern cfuhash_table_t *
cfuhash_new_with_flags(u_int32_t flags) {
return _cfuhash_new(8, CFUHASH_FROZEN_UNTIL_GROWS|flags);
}
extern cfuhash_table_t * cfuhash_new_with_free_fn(cfuhash_free_fn_t ff) {
cfuhash_table_t *ht = _cfuhash_new(8, CFUHASH_FROZEN_UNTIL_GROWS);
cfuhash_set_free_function(ht, ff);
return ht;
}
extern int
cfuhash_copy(cfuhash_table_t *src, cfuhash_table_t *dst) {
size_t num_keys = 0;
void **keys = NULL;
size_t *key_sizes;
size_t i = 0;
void *val = NULL;
size_t data_size = 0;
keys = cfuhash_keys_data(src, &num_keys, &key_sizes, 0);
for (i = 0; i < num_keys; i++) {
if (cfuhash_get_data(src, (void *)keys[i], key_sizes[i], &val, &data_size)) {
cfuhash_put_data(dst, (void *)keys[i], key_sizes[i], val, data_size, NULL);
}
free(keys[i]);
}
free(keys);
free(key_sizes);
return 1;
}
extern cfuhash_table_t *
cfuhash_merge(cfuhash_table_t *ht1, cfuhash_table_t *ht2, u_int32_t flags) {
cfuhash_table_t *new_ht = NULL;
flags |= CFUHASH_FROZEN_UNTIL_GROWS;
new_ht = _cfuhash_new(cfuhash_num_entries(ht1) + cfuhash_num_entries(ht2), flags);
if (ht1) cfuhash_copy(ht1, new_ht);
if (ht2) cfuhash_copy(ht2, new_ht);
return new_ht;
}
/* returns the flags */
extern u_int32_t
cfuhash_get_flags(cfuhash_table_t *ht) {
return ht->flags;
}
/* sets the given flag and returns the old flags value */
extern u_int32_t
cfuhash_set_flag(cfuhash_table_t *ht, u_int32_t new_flag) {
u_int32_t flags = ht->flags;
ht->flags = flags | new_flag;
return flags;
}
extern u_int32_t
cfuhash_clear_flag(cfuhash_table_t *ht, u_int32_t new_flag) {
u_int32_t flags = ht->flags;
ht->flags = flags & ~new_flag;
return flags;
}
extern int
cfuhash_set_thresholds(cfuhash_table_t *ht, float low, float high) {
float h = high < 0 ? ht->high : high;
float l = low < 0 ? ht->low : low;
if (h < l) return -1;
ht->high = h;
ht->low = l;
return 0;
}
/* Sets the hash function for the hash table ht. Pass NULL for hf to reset to the default */
extern int
cfuhash_set_hash_function(cfuhash_table_t *ht, cfuhash_function_t hf) {
/* can't allow changing the hash function if the hash already contains entries */
if (ht->entries) return -1;
ht->hash_func = hf ? hf : hash_func;
return 0;
}
extern int
cfuhash_set_free_function(cfuhash_table_t * ht, cfuhash_free_fn_t ff) {
if (ff) ht->free_fn = ff;
return 0;
}
static inline void
lock_hash(cfuhash_table_t *ht) {
if (!ht) return;
if (ht->flags & CFUHASH_NO_LOCKING) return;
pthread_mutex_lock(&ht->mutex);
}
static inline void
unlock_hash(cfuhash_table_t *ht) {
if (!ht) return;
if (ht->flags & CFUHASH_NO_LOCKING) return;
pthread_mutex_unlock(&ht->mutex);
}
extern int
cfuhash_lock(cfuhash_table_t *ht) {
pthread_mutex_lock(&ht->mutex);
return 1;
}
extern int
cfuhash_unlock(cfuhash_table_t *ht) {
pthread_mutex_unlock(&ht->mutex);
return 1;
}
/* see if this key matches the one in the hash entry */
/* uses the convention that zero means a match, like memcmp */
static inline int
hash_cmp(const void *key, size_t key_size, cfuhash_entry *he, u_int case_insensitive) {
if (key_size != he->key_size) return 1;
if (key == he->key) return 0;
if (case_insensitive) {
return strncasecmp(key, he->key, key_size);
}
return memcmp(key, he->key, key_size);
}
static inline cfuhash_entry *
hash_add_entry(cfuhash_table_t *ht, u_int hv, const void *key, size_t key_size,
void *data, size_t data_size) {
cfuhash_entry *he = (cfuhash_entry *)calloc(1, sizeof(cfuhash_entry));
assert(hv < ht->num_buckets);
if (ht->flags & CFUHASH_NOCOPY_KEYS)
he->key = (void *)key;
else
he->key = hash_key_dup(key, key_size);
he->key_size = key_size;
he->data = data;
he->data_size = data_size;
he->next = ht->buckets[hv];
ht->buckets[hv] = he;
ht->entries++;
return he;
}
/*
Returns one if the entry was found, zero otherwise. If found, r is
changed to point to the data in the entry.
*/
extern int
cfuhash_get_data(cfuhash_table_t *ht, const void *key, size_t key_size, void **r,
size_t *data_size) {
u_int hv = 0;
cfuhash_entry *hr = NULL;
if (!ht) return 0;
if (key_size == (size_t)(-1)) {
if (key) key_size = strlen(key) + 1;
else key_size = 0;
}
lock_hash(ht);
hv = hash_value(ht, key, key_size, ht->num_buckets);
assert(hv < ht->num_buckets);
for (hr = ht->buckets[hv]; hr; hr = hr->next) {
if (!hash_cmp(key, key_size, hr, ht->flags & CFUHASH_IGNORE_CASE)) break;
}
if (hr && r) {
*r = hr->data;
if (data_size) *data_size = hr->data_size;
}
unlock_hash(ht);
return (hr ? 1 : 0);
}
/*
Assumes the key is a null-terminated string, returns the data, or NULL if not found. Note that it is possible for the data itself to be NULL
*/
extern void *
cfuhash_get(cfuhash_table_t *ht, const char *key) {
void *r = NULL;
int rv = 0;
rv = cfuhash_get_data(ht, (const void *)key, -1, &r, NULL);
if (rv) return r; /* found */
return NULL;
}
/* Returns 1 if an entry exists in the table for the given key, 0 otherwise */
extern int
cfuhash_exists_data(cfuhash_table_t *ht, const void *key, size_t key_size) {
void *r = NULL;
int rv = cfuhash_get_data(ht, key, key_size, &r, NULL);
if (rv) return 1; /* found */
return 0;
}
/* Same as cfuhash_exists_data(), except assumes key is a null-terminated string */
extern int
cfuhash_exists(cfuhash_table_t *ht, const char *key) {
return cfuhash_exists_data(ht, (const void *)key, -1);
}
/*
Add the entry to the hash. If there is already an entry for the
given key, the old data value will be returned in r, and the return
value is zero. If a new entry is created for the key, the function
returns 1.
*/
extern int
cfuhash_put_data(cfuhash_table_t *ht, const void *key, size_t key_size, void *data,
size_t data_size, void **r) {
u_int hv = 0;
cfuhash_entry *he = NULL;
int added_an_entry = 0;
if (key_size == (size_t)(-1)) {
if (key) key_size = strlen(key) + 1;
else key_size = 0;
}
if (data_size == (size_t)(-1)) {
if (data) data_size = strlen(data) + 1;
else data_size = 0;
}
lock_hash(ht);
hv = hash_value(ht, key, key_size, ht->num_buckets);
assert(hv < ht->num_buckets);
for (he = ht->buckets[hv]; he; he = he->next) {
if (!hash_cmp(key, key_size, he, ht->flags & CFUHASH_IGNORE_CASE)) break;
}
if (he) {
if (r) *r = he->data;
if (ht->free_fn) {
ht->free_fn(he->data);
if (r) *r = NULL; /* don't return a pointer to a free()'d location */
}
he->data = data;
he->data_size = data_size;
} else {
hash_add_entry(ht, hv, key, key_size, data, data_size);
added_an_entry = 1;
}
unlock_hash(ht);
if (added_an_entry && !(ht->flags & CFUHASH_FROZEN)) {
if ( (float)ht->entries/(float)ht->num_buckets > ht->high ) cfuhash_rehash(ht);
}
return added_an_entry;
}
/*
Same as cfuhash_put_data(), except the key is assumed to be a
null-terminated string, and the old value is returned if it existed,
otherwise NULL is returned.
*/
extern void *
cfuhash_put(cfuhash_table_t *ht, const char *key, void *data) {
void *r = NULL;
if (!cfuhash_put_data(ht, (const void *)key, -1, data, 0, &r)) {
return r;
}
return NULL;
}
extern void
cfuhash_clear(cfuhash_table_t *ht) {
cfuhash_entry *he = NULL;
cfuhash_entry *hep = NULL;
size_t i = 0;
lock_hash(ht);
for (i = 0; i < ht->num_buckets; i++) {
if ( (he = ht->buckets[i]) ) {
while (he) {
hep = he;
he = he->next;
if (! (ht->flags & CFUHASH_NOCOPY_KEYS) ) free(hep->key);
if (ht->free_fn) ht->free_fn(hep->data);
free(hep);
}
ht->buckets[i] = NULL;
}
}
ht->entries = 0;
unlock_hash(ht);
if ( !(ht->flags & CFUHASH_FROZEN) &&
!( (ht->flags & CFUHASH_FROZEN_UNTIL_GROWS) && !ht->resized_count) ) {
if ( (float)ht->entries/(float)ht->num_buckets < ht->low ) cfuhash_rehash(ht);
}
}
extern void *
cfuhash_delete_data(cfuhash_table_t *ht, const void *key, size_t key_size) {
u_int hv = 0;
cfuhash_entry *he = NULL;
cfuhash_entry *hep = NULL;
void *r = NULL;
if (key_size == (size_t)(-1)) key_size = strlen(key) + 1;
lock_hash(ht);
hv = hash_value(ht, key, key_size, ht->num_buckets);
for (he = ht->buckets[hv]; he; he = he->next) {
if (!hash_cmp(key, key_size, he, ht->flags & CFUHASH_IGNORE_CASE)) break;
hep = he;
}
if (he) {
r = he->data;
if (hep) hep->next = he->next;
else ht->buckets[hv] = he->next;
ht->entries--;
if (! (ht->flags & CFUHASH_NOCOPY_KEYS) ) free(he->key);
if (ht->free_fn) {
ht->free_fn(he->data);
r = NULL; /* don't return a pointer to a free()'d location */
}
free(he);
}
unlock_hash(ht);
if (he && !(ht->flags & CFUHASH_FROZEN) &&
!( (ht->flags & CFUHASH_FROZEN_UNTIL_GROWS) && !ht->resized_count) ) {
if ( (float)ht->entries/(float)ht->num_buckets < ht->low ) cfuhash_rehash(ht);
}
return r;
}
extern void *
cfuhash_delete(cfuhash_table_t *ht, const char *key) {
return cfuhash_delete_data(ht, key, -1);
}
extern void **
cfuhash_keys_data(cfuhash_table_t *ht, size_t *num_keys, size_t **key_sizes, int fast) {
size_t *key_lengths = NULL;
void **keys = NULL;
cfuhash_entry *he = NULL;
size_t bucket = 0;
size_t entry_index = 0;
size_t key_count = 0;
if (!ht) {
*key_sizes = NULL;
*num_keys = 0;
return NULL;
}
if (! (ht->flags & CFUHASH_NO_LOCKING) ) lock_hash(ht);
if (key_sizes) key_lengths = (size_t *)calloc(ht->entries, sizeof(size_t));
keys = (void **)calloc(ht->entries, sizeof(void *));
for (bucket = 0; bucket < ht->num_buckets; bucket++) {
if ( (he = ht->buckets[bucket]) ) {
for (; he; he = he->next, entry_index++) {
if (entry_index >= ht->entries) break; /* this should never happen */
if (fast) {
keys[entry_index] = he->key;
} else {
keys[entry_index] = (void *)calloc(he->key_size, 1);
memcpy(keys[entry_index], he->key, he->key_size);
}
key_count++;
if (key_lengths) key_lengths[entry_index] = he->key_size;
}
}
}
if (! (ht->flags & CFUHASH_NO_LOCKING) ) unlock_hash(ht);
if (key_sizes) *key_sizes = key_lengths;
*num_keys = key_count;
return keys;
}
extern void **
cfuhash_keys(cfuhash_table_t *ht, size_t *num_keys, int fast) {
return cfuhash_keys_data(ht, num_keys, NULL, fast);
}
extern int
cfuhash_each_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
size_t *data_size) {
ht->each_bucket_index = -1;
ht->each_chain_entry = NULL;
return cfuhash_next_data(ht, key, key_size, data, data_size);
}
extern int
cfuhash_next_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
size_t *data_size) {
if (ht->each_chain_entry && ht->each_chain_entry->next) {
ht->each_chain_entry = ht->each_chain_entry->next;
} else {
ht->each_chain_entry = NULL;
ht->each_bucket_index++;
for (; ht->each_bucket_index < ht->num_buckets; ht->each_bucket_index++) {
if (ht->buckets[ht->each_bucket_index]) {
ht->each_chain_entry = ht->buckets[ht->each_bucket_index];
break;
}
}
}
if (ht->each_chain_entry) {
*key = ht->each_chain_entry->key;
*key_size = ht->each_chain_entry->key_size;
*data = ht->each_chain_entry->data;
if (data_size) *data_size = ht->each_chain_entry->data_size;
return 1;
}
return 0;
}
static void
_cfuhash_destroy_entry(cfuhash_table_t *ht, cfuhash_entry *he, cfuhash_free_fn_t ff) {
if (ff) {
ff(he->data);
} else {
if (ht->free_fn) ht->free_fn(he->data);
else {
if (ht->flags & CFUHASH_FREE_DATA) free(he->data);
}
}
if ( !(ht->flags & CFUHASH_NOCOPY_KEYS) ) free(he->key);
free(he);
}
extern size_t
cfuhash_foreach_remove(cfuhash_table_t *ht, cfuhash_remove_fn_t r_fn, cfuhash_free_fn_t ff,
void *arg) {
cfuhash_entry *entry = NULL;
cfuhash_entry *prev = NULL;
size_t hv = 0;
size_t num_removed = 0;
cfuhash_entry **buckets = NULL;
size_t num_buckets = 0;
if (!ht) return 0;
lock_hash(ht);
buckets = ht->buckets;
num_buckets = ht->num_buckets;
for (hv = 0; hv < num_buckets; hv++) {
entry = buckets[hv];
if (!entry) continue;
prev = NULL;
while (entry) {
if (r_fn(entry->key, entry->key_size, entry->data, entry->data_size, arg)) {
num_removed++;
if (prev) {
prev->next = entry->next;
_cfuhash_destroy_entry(ht, entry, ff);
entry = prev->next;
} else {
buckets[hv] = entry->next;
_cfuhash_destroy_entry(ht, entry, NULL);
entry = buckets[hv];
}
} else {
prev = entry;
entry = entry->next;
}
}
}
unlock_hash(ht);
return num_removed;
}
extern size_t
cfuhash_foreach(cfuhash_table_t *ht, cfuhash_foreach_fn_t fe_fn, void *arg) {
cfuhash_entry *entry = NULL;
size_t hv = 0;
size_t num_accessed = 0;
cfuhash_entry **buckets = NULL;
size_t num_buckets = 0;
int rv = 0;
if (!ht) return 0;
lock_hash(ht);
buckets = ht->buckets;
num_buckets = ht->num_buckets;
for (hv = 0; hv < num_buckets && !rv; hv++) {
entry = buckets[hv];
for (; entry && !rv; entry = entry->next) {
num_accessed++;
rv = fe_fn(entry->key, entry->key_size, entry->data, entry->data_size, arg);
}
}
unlock_hash(ht);
return num_accessed;
}
extern int
cfuhash_each(cfuhash_table_t *ht, char **key, void **data) {
size_t key_size = 0;
return cfuhash_each_data(ht, (void **)key, &key_size, data, NULL);
}
extern int
cfuhash_next(cfuhash_table_t *ht, char **key, void **data) {
size_t key_size = 0;
return cfuhash_next_data(ht, (void **)key, &key_size, data, NULL);
}
extern int
cfuhash_destroy_with_free_fn(cfuhash_table_t *ht, cfuhash_free_fn_t ff) {
size_t i;
if (!ht) return 0;
lock_hash(ht);
for (i = 0; i < ht->num_buckets; i++) {
if (ht->buckets[i]) {
cfuhash_entry *he = ht->buckets[i];
while (he) {
cfuhash_entry *hn = he->next;
_cfuhash_destroy_entry(ht, he, ff);
he = hn;
}
}
}
free(ht->buckets);
unlock_hash(ht);
pthread_mutex_destroy(&ht->mutex);
free(ht);
return 1;
}
extern int
cfuhash_destroy(cfuhash_table_t *ht) {
return cfuhash_destroy_with_free_fn(ht, NULL);
}
typedef struct _pretty_print_arg {
size_t count;
FILE *fp;
} _pretty_print_arg;
static int
_pretty_print_foreach(void *key, size_t key_size, void *data, size_t data_size, void *arg) {
_pretty_print_arg *parg = (_pretty_print_arg *)arg;
key_size = key_size;
data_size = data_size;
parg->count += fprintf(parg->fp, "\t\"%s\" => \"%s\",\n", (char *)key, (char *)data);
return 0;
}
extern int
cfuhash_pretty_print(cfuhash_table_t *ht, FILE *fp) {
int rv = 0;
_pretty_print_arg parg;
parg.fp = fp;
parg.count = 0;
rv += fprintf(fp, "{\n");
cfuhash_foreach(ht, _pretty_print_foreach, (void *)&parg);
rv += parg.count;
rv += fprintf(fp, "}\n");
return rv;
}
extern int
cfuhash_rehash(cfuhash_table_t *ht) {
size_t new_size, i;
cfuhash_entry **new_buckets = NULL;
lock_hash(ht);
new_size = hash_size(ht->entries * 2 / (ht->high + ht->low));
if (new_size == ht->num_buckets) {
unlock_hash(ht);
return 0;
}
new_buckets = (cfuhash_entry **)calloc(new_size, sizeof(cfuhash_entry *));
for (i = 0; i < ht->num_buckets; i++) {
cfuhash_entry *he = ht->buckets[i];
while (he) {
cfuhash_entry *nhe = he->next;
u_int hv = hash_value(ht, he->key, he->key_size, new_size);
he->next = new_buckets[hv];
new_buckets[hv] = he;
he = nhe;
}
}
ht->num_buckets = new_size;
free(ht->buckets);
ht->buckets = new_buckets;
ht->resized_count++;
unlock_hash(ht);
return 1;
}
extern size_t
cfuhash_num_entries(cfuhash_table_t *ht) {
if (!ht) return 0;
return ht->entries;
}
extern size_t
cfuhash_num_buckets(cfuhash_table_t *ht) {
if (!ht) return 0;
return ht->num_buckets;
}
extern size_t
cfuhash_num_buckets_used(cfuhash_table_t *ht) {
size_t i = 0;
size_t count = 0;
if (!ht) return 0;
lock_hash(ht);
for (i = 0; i < ht->num_buckets; i++) {
if (ht->buckets[i]) count++;
}
unlock_hash(ht);
return count;
}
extern char *
cfuhash_bencode_strings(cfuhash_table_t *ht) {
cfustring_t *bencoded = cfustring_new_with_initial_size(16);
char **keys = NULL;
size_t num_keys = 0;
size_t i = 0;
char len_str[32];
char *rv = NULL;
cfustring_append(bencoded, "d");
keys = (char **)cfuhash_keys(ht, &num_keys, 0);
for (i = 0; i < num_keys; i++) {
char *val = NULL;
snprintf(len_str, 32, "%d:", (keys[i] ? strlen(keys[i]) : 0));
cfustring_append(bencoded, len_str);
cfustring_append(bencoded, keys[i]);
val = (char *)cfuhash_get(ht, keys[i]);
snprintf(len_str, 32, "%d:", (val ? strlen(val) : 0));
cfustring_append(bencoded, len_str);
cfustring_append(bencoded, val);
free(keys[i]);
}
free(keys);
cfustring_append(bencoded, "e");
rv = cfustring_get_buffer_copy(bencoded);
cfustring_destroy(bencoded);
return rv;
}

552
src/cfulist.c Normal file
View File

@ -0,0 +1,552 @@
/* Creation date: 2005-07-02 22:25:39
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
#include <stdlib.h>
#include "cfulist.h"
#include "cfustring.h"
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
typedef struct cfulist_entry {
void *data;
size_t data_size;
struct cfulist_entry *next;
struct cfulist_entry *prev;
} cfulist_entry;
struct cfulist {
libcfu_type type;
cfulist_entry *entries;
cfulist_entry *tail;
size_t num_entries;
pthread_mutex_t mutex;
cfulist_entry *each_ptr;
cfulist_free_fn_t free_fn;
};
extern cfulist_t *
cfulist_new() {
cfulist_t *list = (cfulist_t *)calloc(1, sizeof(cfulist_t));
pthread_mutex_init(&list->mutex, NULL);
list->type = libcfu_t_list;
return list;
}
extern cfulist_t *
cfulist_new_with_free_fn(cfulist_free_fn_t free_fn) {
cfulist_t *list = cfulist_new();
list->free_fn = free_fn;
return list;
}
extern size_t
cfulist_num_entries(cfulist_t *list) {
return list->num_entries;
}
static inline void
lock_list(cfulist_t *list) {
pthread_mutex_lock(&list->mutex);
}
static inline void
unlock_list(cfulist_t *list) {
pthread_mutex_unlock(&list->mutex);
}
static inline cfulist_entry *
new_list_entry() {
return (cfulist_entry *)calloc(1, sizeof(cfulist_entry));
}
extern int
cfulist_push_data(cfulist_t *list, void *data, size_t data_size) {
cfulist_entry *entry = new_list_entry();
if (!entry) return 0;
if (data_size == (size_t)-1) data_size = strlen((char *)data) + 1;
entry->data = data;
entry->data_size = data_size;
lock_list(list);
if (list->tail) {
entry->prev = list->tail;
list->tail->next = entry;
list->tail = entry;
} else {
list->tail = list->entries = entry;
}
list->num_entries++;
unlock_list(list);
return 1;
}
extern int
cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size) {
if (!list) {
*data = NULL;
*data_size = 0;
return 0;
}
lock_list(list);
if (list->tail) {
if (list->tail->prev) {
cfulist_entry *new_tail = list->tail->prev;
assert(list->num_entries > 1);
new_tail->next = NULL;
*data = list->tail->data;
if (data_size) *data_size = list->tail->data_size;
free(list->tail);
list->tail = new_tail;
} else {
/* there is only one entry in the list */
assert(list->num_entries == 1);
*data = list->tail->data;
if (data_size) *data_size = list->tail->data_size;
free(list->tail);
list->tail = NULL;
list->entries = NULL;
}
list->num_entries--;
unlock_list(list);
return 1;
}
unlock_list(list);
if (data_size) *data_size = 0;
return 0;
}
extern int
cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size) {
cfulist_entry *entry = new_list_entry();
if (!entry) return 0;
if (data_size == (size_t)-1) data_size = strlen((char *)data) + 1;
entry->data = data;
entry->data_size = data_size;
lock_list(list);
if (list->entries) {
entry->next = list->entries;
list->entries->prev = entry;
list->entries = entry;
} else {
list->tail = list->entries = entry;
}
list->num_entries++;
unlock_list(list);
return 1;
}
extern int
cfulist_shift_data(cfulist_t *list, void **data, size_t *data_size) {
int rv = 0;
if (!list) {
if (data_size) *data_size = 0;
*data = NULL;
return rv;
}
lock_list(list);
if (list->entries) {
cfulist_entry *entry = list->entries;
assert(list->num_entries >= 1);
rv = 1;
*data = entry->data;
if (data_size) *data_size = entry->data_size;
if (entry->next) {
assert(list->num_entries > 1);
list->entries = entry->next;
list->entries->prev = NULL;
} else {
assert(list->num_entries == 1);
list->tail = NULL;
list->entries = NULL;
}
free(entry);
list->num_entries--;
} else {
assert(list->num_entries == 0);
rv = 0;
if (data_size) *data_size = 0;
*data = NULL;
}
unlock_list(list);
return rv;
}
extern int
cfulist_enqueue_data(cfulist_t *list, void *data, size_t data_size) {
return cfulist_push_data(list, data, data_size);
}
extern int
cfulist_dequeue_data(cfulist_t *list, void **data, size_t *data_size) {
return cfulist_shift_data(list, data, data_size);
}
extern int
cfulist_first_data(cfulist_t *list, void **data, size_t *data_size) {
int rv = 0;
if (!list) {
return 0;
}
lock_list(list);
if (list->entries) {
rv = 1;
*data = list->entries->data;
if (data_size) *data_size = list->entries->data_size;
} else {
rv = 0;
*data = NULL;
*data_size = 0;
}
unlock_list(list);
return rv;
}
extern int
cfulist_last_data(cfulist_t *list, void **data, size_t *data_size) {
int rv = 0;
if (!list) {
return 0;
}
lock_list(list);
if (list->tail) {
rv = 1;
*data = list->tail->data;
if (data_size) *data_size = list->tail->data_size;
} else {
rv = 0;
*data = NULL;
*data_size = 0;
}
unlock_list(list);
return rv;
}
extern int
cfulist_nth_data(cfulist_t *list, void **data, size_t *data_size, size_t n) {
int rv = 0;
size_t i = 0;
cfulist_entry *ptr = NULL;
if (!list) {
return 0;
}
lock_list(list);
if (list->entries) {
for (i = 0, ptr = list->entries; ptr && i < n; i++, ptr = ptr->next);
if (ptr && i == n) {
rv = 1;
*data = ptr->data;
if (data_size) *data_size = list->entries->data_size;
}
} else {
rv = 0;
*data = NULL;
*data_size = 0;
}
unlock_list(list);
return rv;
}
extern void
cfulist_reset_each(cfulist_t *list) {
if (!list) return;
list->each_ptr = list->entries;
}
extern int
cfulist_each_data(cfulist_t *list, void **data, size_t *data_size) {
if (!list) return 0;
cfulist_reset_each(list);
return cfulist_next_data(list, data, data_size);
}
extern int
cfulist_next_data(cfulist_t *list, void **data, size_t *data_size) {
if (!list) return 0;
*data = NULL;
if (list->each_ptr) {
*data = list->each_ptr->data;
*data_size = list->each_ptr->data_size;
list->each_ptr = list->each_ptr->next;
return 1;
}
return 0;
}
extern size_t
cfulist_foreach(cfulist_t *list, cfulist_foreach_fn_t fe_fn, void *arg) {
cfulist_entry *entry = NULL;
size_t num_processed = 0;
int rv = 0;
if (!list) return 0;
lock_list(list);
for (entry = list->entries; entry && !rv; entry = entry->next) {
rv = fe_fn(entry->data, entry->data_size, arg);
num_processed++;
}
unlock_list(list);
return num_processed;
}
typedef struct _cfulist_map_struct {
cfulist_t *list;
void *arg;
cfulist_map_fn_t map_fn;
} _cfulist_map_ds;
static int
_cfulist_map_foreach(void *data, size_t data_size, void *arg) {
_cfulist_map_ds *ds = (_cfulist_map_ds *)arg;
size_t new_data_size = 0;
void *rv = ds->map_fn(data, data_size, ds->arg, &new_data_size);
cfulist_push_data(ds->list, rv, new_data_size);
return 0;
}
extern cfulist_t *
cfulist_map(cfulist_t *list, cfulist_map_fn_t map_fn, void *arg) {
cfulist_t *new_list = cfulist_new();
_cfulist_map_ds ds;
ds.list = new_list;
ds.arg = arg;
ds.map_fn = map_fn;
cfulist_foreach(list, _cfulist_map_foreach, (void *)&ds);
return new_list;
}
/* For when you don't care about the data size */
extern int
cfulist_push(cfulist_t *list, void *data) {
return cfulist_push_data(list, data, 0);
}
extern void *
cfulist_pop(cfulist_t *list) {
void *data = NULL;
if (cfulist_pop_data(list, &data, NULL)) {
return data;
}
return NULL;
}
extern int
cfulist_unshift(cfulist_t *list, void *data) {
return cfulist_unshift_data(list, data, 0);
}
extern void *
cfulist_shift(cfulist_t *list) {
void *data = NULL;
if (cfulist_shift_data(list, &data, NULL)) {
return data;
}
return NULL;
}
extern int
cfulist_enqueue(cfulist_t *list, void *data) {
return cfulist_push(list, data);
}
extern void *
cfulist_dequeue(cfulist_t *list) {
return cfulist_shift(list);
}
/* Dealing with strings */
extern int
cfulist_push_string(cfulist_t *list, char *data) {
return cfulist_push_data(list, (void *)data, -1);
}
extern char *
cfulist_pop_string(cfulist_t *list) {
void *data = NULL;
if (cfulist_pop_data(list, &data, NULL)) {
return (char *)data;
}
return NULL;
}
extern int
cfulist_unshift_string(cfulist_t *list, char *data) {
return cfulist_unshift_data(list, (void *)data, -1);
}
extern char *
cfulist_shift_string(cfulist_t *list) {
void *data = NULL;
if (cfulist_shift_data(list, &data, NULL)) {
return (char *)data;
}
return NULL;
}
extern int
cfulist_enqueue_string(cfulist_t *list, char *data) {
return cfulist_push_string(list, data);
}
extern char *
cfulist_dequeue_string(cfulist_t *list) {
return cfulist_shift_string(list);
}
typedef struct _join_foreach_struct {
size_t count;
const char *delimiter;
cfustring_t *string;
} _join_foreach_struct;
static int
_join_foreach_fn(void *data, size_t data_size, void *arg) {
_join_foreach_struct *stuff = (_join_foreach_struct *)arg;
data_size = data_size;
if (stuff->count) cfustring_append(stuff->string, stuff->delimiter);
stuff->count++;
cfustring_append(stuff->string, (char *)data);
return 0;
}
extern char *
cfulist_join(cfulist_t *list, const char *delimiter) {
_join_foreach_struct *arg = (_join_foreach_struct *)calloc(1, sizeof(_join_foreach_struct));
char *str = NULL;
arg->delimiter = delimiter;
arg->string = cfustring_new();
cfulist_foreach(list, _join_foreach_fn, (void *)arg);
str = cfustring_get_buffer_copy(arg->string);
cfustring_destroy(arg->string);
free(arg);
return str;
}
extern void
cfulist_destroy(cfulist_t *list) {
if (!list) return;
if (list->free_fn) {
cfulist_destroy_with_free_fn(list, list->free_fn);
return;
}
lock_list(list);
if (list->entries) {
cfulist_entry *entry = NULL;
cfulist_entry *tmp = NULL;
entry = list->entries;
while (entry) {
tmp = entry->next;
free(entry);
entry = tmp;
}
}
unlock_list(list);
pthread_mutex_destroy(&list->mutex);
free(list);
}
extern void
cfulist_destroy_with_free_fn(cfulist_t *list, cfulist_free_fn_t free_fn) {
if (!list) return;
lock_list(list);
if (list->entries) {
cfulist_entry *entry = NULL;
cfulist_entry *tmp = NULL;
entry = list->entries;
while (entry) {
tmp = entry->next;
if (free_fn) free_fn(entry->data);
free(entry);
entry = tmp;
}
}
unlock_list(list);
pthread_mutex_destroy(&list->mutex);
free(list);
}

604
src/cfuopt.c Normal file
View File

@ -0,0 +1,604 @@
/* Creation date: 2005-09-04 12:57:25
* Authors: Don
* Change log:
*/
#include "cfu.h"
#include "cfuopt.h"
#include "cfuhash.h"
#include "cfulist.h"
#include "cfustring.h"
#include <stdlib.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
struct cfuopt_struct {
libcfu_type type;
cfulist_t *option_list;
cfuhash_table_t *option_map;
cfulist_t *extra;
char *progname;
};
typedef enum {
cfuopt_arg_invalid = 0,
cfuopt_arg_bool,
cfuopt_arg_string,
cfuopt_arg_int,
cfuopt_arg_float,
cfuopt_arg_string_array
} cfuopt_arg_t;
typedef struct cfuopt_list_entry {
const char *arg_data;
const char *description;
const char *arg_description;
cfuopt_arg_t arg_type;
int required;
cfulist_t *param_names;
} cfuopt_list_entry_t;
#define CFU_OPT_ALLOC(type, count) (type *)calloc(count, sizeof(type));
extern cfuopt_t *
cfuopt_new() {
cfuopt_t *context = (cfuopt_t *)calloc(1, sizeof(cfuopt_t));
context->option_list = cfulist_new();
context->option_map = cfuhash_new();
context->extra = cfulist_new();
return context;
}
#define CFUOPT_SET_TYPE(spec, type_var) \
switch (spec) { \
case 's': \
type_var = cfuopt_arg_string; \
break; \
case 'i': \
type_var = cfuopt_arg_int; \
break; \
case 'f': \
type_var = cfuopt_arg_float; \
break; \
case '!': \
type_var = cfuopt_arg_bool; \
default: \
break; \
}
/*
Parse a string like Perl's Getopt::Long takes, e.g.
"verbose|v!",
"file|f=s",
"scale:f",
"count:i"
! means boolean flag
= means required
: means optional
s means arbitrary string (C string)
f means float (double)
i means integer (long)
*/
static void
parse_opt_str(const char *opt_str, cfulist_t **param_list, cfuopt_arg_t *type, int *is_required) {
cfulist_t *params = cfulist_new();
size_t num_names = 0;
char **opt_names = cfustring_c_str_split(opt_str, &num_names, 0, "|", NULL);
char *last_opt = NULL;
char *pos = NULL;
size_t opt_len = 0;
cfuopt_arg_t arg_type = cfuopt_arg_invalid;
int required = 0;
size_t i = 0;
if (num_names == 0) {
cfulist_destroy(params);
free(opt_names);
return;
}
last_opt = opt_names[num_names - 1];
opt_len = strlen(last_opt);
if ( (pos = memchr((void *)last_opt, '=', opt_len)) ) {
char *tmp = pos;
required = 1;
tmp++;
if (*tmp) {
CFUOPT_SET_TYPE(*tmp, arg_type);
*pos = '\000';
}
else {
arg_type = cfuopt_arg_invalid;
}
}
else if ( (pos = memchr((void *)last_opt, ':', opt_len)) ) {
char *tmp = pos;
required = 0;
tmp++;
if (*tmp) {
CFUOPT_SET_TYPE(*tmp, arg_type);
*pos = '\000';
}
else {
arg_type = cfuopt_arg_invalid;
}
}
else if ( (pos = memchr((void *)last_opt, '!', opt_len)) ) {
required = 0;
arg_type = cfuopt_arg_bool;
*pos = '\000';
}
for (i = 0; i < num_names; i++) {
cfulist_push(params, opt_names[i]);
}
free(opt_names);
*type = arg_type;
*param_list = params;
*is_required = required;
}
static void
_simple_list_free_fn(void *data) {
free(data);
}
struct _add_entry_struct {
cfuopt_t *context;
cfuopt_list_entry_t *entry;
};
static int
_add_to_option_map(void *data, size_t data_size, void *arg) {
struct _add_entry_struct *es = (struct _add_entry_struct *)arg;
data_size = data_size;
cfuhash_put(es->context->option_map, (char *)data, (void *)es->entry);
return 0;
}
extern void
cfuopt_add_entry(cfuopt_t *context, const char *opt_str, void *arg_data,
const char *description, const char *arg_description) {
cfuopt_list_entry_t *entry = CFU_OPT_ALLOC(cfuopt_list_entry_t, 1);
cfulist_t *param_list = NULL;
cfuopt_arg_t arg_type = cfuopt_arg_invalid;
struct _add_entry_struct entry_struct;
int required = 0;
parse_opt_str(opt_str, &param_list, &arg_type, &required);
entry->arg_data = arg_data;
entry->description = description;
entry->arg_description = arg_description;
entry->arg_type = arg_type;
entry->required = required;
entry->param_names = param_list;
cfulist_push(context->option_list, (void *)entry);
entry_struct.entry = entry;
entry_struct.context = context;
cfulist_foreach(param_list, _add_to_option_map, &entry_struct);
}
static void
check_arg(const char *arg, int *is_long, int *is_short, int *is_data, int *is_end_of_options,
char **parsed_arg, const char **value) {
const char *ptr = NULL;
ptr = arg;
*is_long = 0;
*is_short = 0;
*is_data = 0;
*is_end_of_options = 0;
*parsed_arg = NULL;
*value = NULL;
if (!ptr || !*ptr) return;
if (*ptr != '-') {
*is_data = 1;
*parsed_arg = cfustring_dup_c_str(ptr);
return;
}
ptr++;
if (!*ptr) {
*is_data = 1;
*parsed_arg = cfustring_dup_c_str(ptr - 1);
return;
}
if (*ptr == '-') {
const char *val_ptr = NULL;
ptr++;
if (!*ptr) {
*is_end_of_options = 1;
return;
}
*is_long = 1;
*parsed_arg = cfustring_dup_c_str(ptr);
val_ptr = ptr;
for (val_ptr = ptr; *val_ptr && *val_ptr != '='; val_ptr++);
if (*val_ptr == '=') {
(*parsed_arg)[val_ptr - ptr] = '\000';
val_ptr++;
*value = val_ptr;
}
return;
} else {
*is_short = 1;
*parsed_arg = cfustring_dup_c_str(ptr);
return;
}
}
static void
_set_entry_val(cfuopt_list_entry_t *entry, const char *value) {
switch (entry->arg_type) {
case cfuopt_arg_bool:
if (entry->arg_data) *((int *)entry->arg_data) = 1;
break;
case cfuopt_arg_int:
if (entry->arg_data) *((int *)entry->arg_data) = atol((char *)value);
break;
case cfuopt_arg_float:
if (entry->arg_data) *((double *)entry->arg_data) = atof((char *)value);
break;
case cfuopt_arg_string:
if (entry->arg_data) *((char **)entry->arg_data) = cfustring_dup_c_str((char *)value);
break;
default:
break;
}
}
typedef struct {
int count;
char **argv;
} _update_extra_ds;
static int
_update_extra(void *data, size_t data_size, void *arg) {
_update_extra_ds *ds = (_update_extra_ds *)arg;
data_size = data_size;
ds->argv[ds->count] = (char *)data;
ds->count++;
return 0;
}
extern void
cfuopt_parse(cfuopt_t *context, int *argc, char ***argv, char **error) {
int i = 0;
char **args = *argv;
int is_long_opt = 0;
int is_short_opt = 0;
int is_data = 0;
int is_end_of_opt = 0;
char *parsed_arg = NULL;
const char *value = NULL;
cfuopt_list_entry_t *entry = NULL;
size_t extra_count = 0;
error = error;
if (!context) return;
if (*argc < 1) return;
context->progname = cfustring_dup_c_str(args[0]);
if (*argc < 2) return;
for (i = 1; i < *argc; i++) {
char *cur_arg = args[i];
entry = NULL;
value = NULL;
if (parsed_arg) free(parsed_arg);
parsed_arg = NULL;
check_arg(cur_arg, &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt, &parsed_arg,
&value);
if (is_long_opt || is_short_opt) {
entry = (cfuopt_list_entry_t *)cfuhash_get(context->option_map, parsed_arg);
if (parsed_arg) free(parsed_arg);
parsed_arg = NULL;
}
else if (is_end_of_opt) {
if (parsed_arg) free(parsed_arg);
parsed_arg = NULL;
i++;
for (; i < *argc; i++) {
cfulist_push(context->extra, args[i]);
}
break;
}
else if (is_data) {
if (parsed_arg) free(parsed_arg);
parsed_arg = NULL;
cfulist_push(context->extra, args[i]);
continue;
}
if (!entry) {
/* FIXME: return error here if need be */
continue;
}
switch (entry->arg_type) {
case cfuopt_arg_bool:
_set_entry_val(entry, "1");
break;
case cfuopt_arg_string:
case cfuopt_arg_int:
case cfuopt_arg_float:
if (value) {
if (entry->arg_data) {
_set_entry_val(entry, value);
}
} else {
i++;
if (i >= *argc) break; /* FIXME: set up error msg here */
check_arg(args[i], &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt,
&parsed_arg, &value);
if (!is_data) {
i--;
break; /* FIXME: set up error msg here */
}
_set_entry_val(entry, parsed_arg);
free(parsed_arg);
parsed_arg = NULL;
}
break;
case cfuopt_arg_string_array:
break;
case cfuopt_arg_invalid:
/* FIXME: really should produce an error msg here */
break;
default:
break;
}
}
extra_count = cfulist_num_entries(context->extra);
*argc = extra_count + 1;
{
_update_extra_ds ds;
size_t update_count = 0;
ds.count = 1;
ds.argv = args;
update_count = cfulist_foreach(context->extra, _update_extra, (void *)&ds);
assert(update_count + 1 == (unsigned)*argc);
}
}
static void
_opt_list_free_fn(void *data) {
cfuopt_list_entry_t *entry = (cfuopt_list_entry_t *)data;
cfulist_destroy_with_free_fn(entry->param_names, _simple_list_free_fn);
free(data);
}
extern void
cfuopt_destroy(cfuopt_t *context) {
if (!context) return;
cfulist_destroy_with_free_fn(context->option_list, _opt_list_free_fn);
cfuhash_destroy(context->option_map);
cfulist_destroy(context->extra);
free(context->progname);
free(context);
}
#define ARG_TYPE_TO_STR(type, str) \
switch(type) { \
case cfuopt_arg_invalid: \
str = "INVALID"; \
break; \
case cfuopt_arg_bool: \
str = "BOOL"; \
break; \
case cfuopt_arg_string: \
str = "STRING"; \
break; \
case cfuopt_arg_int: \
str = "INT"; \
break; \
case cfuopt_arg_float: \
str = "FLOAT"; \
break; \
case cfuopt_arg_string_array: \
str = "STRING ARRAY"; \
break; \
default: \
str = "INVALID"; \
break; \
}
static int
_cfuopt_pretty_print_foreach(void *key, size_t key_size, void *data, size_t data_size, void *arg) {
char *name = (char *)key;
cfuopt_list_entry_t *list_entry = data;
char *str = NULL;
key_size = key_size;
data_size = data_size;
arg = arg;
ARG_TYPE_TO_STR(list_entry->arg_type, str);
printf("%s=%p (%s - %s) => %s, \"%s\"\n", name, (void *)list_entry, (list_entry->required ? "required" : "optional"), str, list_entry->description, list_entry->arg_description);
return 0;
}
extern void
cfuopt_pretty_print(cfuopt_t *context) {
cfuhash_foreach(context->option_map, _cfuopt_pretty_print_foreach, NULL);
}
static void
_list_simple_free_fn(void *data) {
free(data);
}
extern void *
_param_map_fn(void *data, size_t data_size, void *arg, size_t *new_data_size) {
char *name = (char *)data;
size_t len = 0;
cfuopt_list_entry_t *opt = (cfuopt_list_entry_t *)arg;
data_size = data_size;
if (!name) return NULL;
len = strlen(name);
*new_data_size = -1;
if (len == 0) return cfustring_dup_c_str("");
if (opt->arg_description && strlen(opt->arg_description) > 0) {
if (len == 1) {
return cfustring_sprintf_c_str("-%s %s", name, opt->arg_description);
}
else {
return cfustring_sprintf_c_str("--%s=%s", name, opt->arg_description);
}
}
else {
if (len == 1) {
return cfustring_sprintf_c_str("-%s", name);
}
else {
return cfustring_sprintf_c_str("--%s", name);
}
}
return NULL;
}
typedef struct _find_foreach_struct {
cfulist_t *desc_list;
size_t max_size;
} _find_foreach_ds;
typedef struct _cfuopt_desc_struct {
char *desc;
cfuopt_list_entry_t *entry;
} _cfuopt_desc;
static int
_find_foreach_fn(void *data, size_t data_size, void *arg) {
cfuopt_list_entry_t *opt = (cfuopt_list_entry_t *)data;
_find_foreach_ds *ds = (_find_foreach_ds *)arg;
size_t this_size = 0;
cfulist_t *param_full_list = NULL;
char *desc = NULL;
_cfuopt_desc *desc_ds = CFU_OPT_ALLOC(_cfuopt_desc, 1);
if (!data) return 0;
param_full_list = cfulist_map(opt->param_names, _param_map_fn, opt);
desc = cfulist_join(param_full_list, ", ");
data_size = data_size;
cfulist_destroy_with_free_fn(param_full_list, _simple_list_free_fn);
desc_ds->desc = desc;
desc_ds->entry = opt;
cfulist_push(ds->desc_list, desc_ds);
this_size = strlen(desc);
if (this_size > ds->max_size) ds->max_size = this_size;
return 0;
}
static size_t
_find_longest_help_desc(cfuopt_t *context, cfulist_t **desc_list) {
_find_foreach_ds ds;
ds.max_size = 0;
ds.desc_list = cfulist_new();
cfulist_foreach(context->option_list, _find_foreach_fn, (void *)&ds);
*desc_list = ds.desc_list;
return ds.max_size;
}
typedef struct {
char *fmt;
cfulist_t *list;
cfulist_t *desc_list;
} _help_lines_ds;
static int
_get_help_lines(void *data, size_t data_size, void *arg) {
_cfuopt_desc *desc_ds = (_cfuopt_desc *)data;
_help_lines_ds *ds = (_help_lines_ds *)arg;
char *left_col = NULL;
const char *desc = NULL;
char *line = NULL;
data_size = data_size;
left_col = desc_ds->desc;
if (!left_col) return 0;
desc = desc_ds->entry->description;
if (!desc) desc = "test desc";
line = cfustring_sprintf_c_str(ds->fmt, left_col, desc);
cfulist_push(ds->list, (void *)line);
return 0;
}
static void
_desc_list_free(void *data) {
_cfuopt_desc *desc_ds = (_cfuopt_desc *)data;
free(desc_ds->desc);
free(data);
}
extern char *
cfuopt_get_help_str(cfuopt_t *context) {
cfulist_t *desc_list = NULL;
size_t max_width = 0;
char *fmt = NULL;
_help_lines_ds ds;
char *help_str = NULL;
max_width = _find_longest_help_desc(context, &desc_list);
fmt = cfustring_sprintf_c_str(" %%-%us %%s\n", max_width);
ds.fmt = fmt;
ds.list = cfulist_new();
ds.desc_list = desc_list;
cfulist_foreach(desc_list, _get_help_lines, (void *)&ds);
help_str = cfulist_join(ds.list, "\n");
cfulist_destroy_with_free_fn(ds.list, _list_simple_free_fn);
cfulist_destroy_with_free_fn(desc_list, _desc_list_free);
free(fmt);
return help_str;
}

631
src/cfustring.c Normal file
View File

@ -0,0 +1,631 @@
/* Creation date: 2005-06-26 19:59:10
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
#include "cfustring.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
struct cfustring {
libcfu_type type;
size_t max_size;
size_t used_size;
char *str;
};
extern cfustring_t *
cfustring_new() {
return cfustring_new_with_initial_size(0);
}
extern cfustring_t *
cfustring_new_with_initial_size(size_t initial_size) {
cfustring_t *cfu_str = (cfustring_t *)calloc(1, sizeof(cfustring_t));
cfu_str->type = libcfu_t_string;
if (initial_size > 0) {
cfu_str->str = (char *)calloc(initial_size, 1);
cfu_str->max_size = initial_size;
cfu_str->used_size = 1;
}
return cfu_str;
}
extern cfustring_t *
cfustring_new_from_string(const char *string) {
cfustring_t *cfu_str = cfustring_new();
cfustring_append(cfu_str, string);
return cfu_str;
}
extern int
cfustring_dup(cfustring_t *cfu_str, const char *string) {
if (!string) {
cfu_str->max_size = 0;
cfu_str->used_size = 0;
free(cfu_str->str);
cfu_str->str = NULL;
return 1;
}
cfustring_clear(cfu_str);
cfustring_append(cfu_str, string);
return 1;
}
extern int
cfustring_clear(cfustring_t *cfu_str) {
if (cfu_str->str) {
cfu_str->str[0] = '\000';
cfu_str->used_size = 1;
}
return 1;
}
extern int
cfustring_append_n(cfustring_t *cfu_str, const char *string, size_t n) {
size_t str_len = 0;
if (!string) return 1;
if (n) {
size_t i = 0;
const char *ptr = string;
for (i = 0; i < n; i++) {
if (*ptr) {
str_len++;
} else {
break;
}
}
} else {
str_len = strlen(string);
}
if (!cfu_str->str) {
cfu_str->str = (char *)malloc(str_len + 1);
cfu_str->max_size = str_len + 1;
cfu_str->used_size = 1;
cfu_str->str[0] = '\000';
}
if (cfu_str->used_size + str_len + 1 > cfu_str->max_size) {
/* allocate more memory and copy over */
char *tmp = NULL;
if (cfu_str->max_size * 2 >= cfu_str->used_size + str_len + 1) {
cfu_str->max_size *= 2;
} else {
cfu_str->max_size = cfu_str->used_size + str_len + 1;
}
tmp = (char *)malloc(cfu_str->max_size);
memcpy(tmp, cfu_str->str, cfu_str->used_size);
free(cfu_str->str);
cfu_str->str = tmp;
}
memcpy(&cfu_str->str[cfu_str->used_size - 1], string, str_len);
/* strcat(cfu_str->str, string); */
cfu_str->used_size += str_len;
cfu_str->str[cfu_str->used_size - 1] = '\000';
return 1;
}
extern int
cfustring_append(cfustring_t *cfu_str, const char *string) {
return cfustring_append_n(cfu_str, string, 0);
}
extern char *
cfustring_get_buffer(cfustring_t *cfu_str) {
return cfu_str->str;
}
extern char *
cfustring_get_buffer_copy(cfustring_t *cfu_str) {
char *buffer = NULL;
if (!cfu_str->str) return NULL;
buffer = (char *)calloc(cfu_str->used_size, 1);
memcpy(buffer, cfu_str->str, cfu_str->used_size);
return buffer;
}
static char *
_dup_str(const char *str) {
size_t len = strlen(str) + 1;
char *ns = (char *)calloc(len, 1);
memcpy(ns, str, len);
return ns;
}
static char *
_dup_str_n(const char *str, size_t n) {
size_t len = n;
char *ns;
if (n == 0) return NULL;
ns = (char *)calloc(len + 1, 1);
memcpy(ns, str, len);
ns[len] = '\000';
return ns;
}
extern char *
cfustring_dup_c_str(const char *str) {
return _dup_str(str);
}
extern char *
cfustring_dup_c_str_n(const char *str, size_t n) {
return _dup_str_n(str, n);
}
static char *
_check_sep(char **start, char **seps, size_t num_seps, char **sep_chk_ptrs, int last) {
size_t i;
char *end = *start;
for (i = 0; i < num_seps; i++) sep_chk_ptrs[i] = seps[i];
if (!*start || !*(*start)) return NULL;
if (last) {
for(; *end; end++);
if (end != *start) {
char *rv = _dup_str_n(*start, end - *start);
*start = end;
return rv;
}
return NULL;
}
for (end = *start; *end; end++) {
for (i = 0; i < num_seps; i++) {
if (*sep_chk_ptrs[i] == *end) {
sep_chk_ptrs[i]++;
if (!*sep_chk_ptrs[i]) {
/* got a match */
size_t size = end - *start + 1 - (sep_chk_ptrs[i] - seps[i]);
char *rv = _dup_str_n(*start, size);
*start = end + 1;
return rv;
}
} else {
sep_chk_ptrs[i] = seps[i];
}
}
}
if (end != *start) {
char *rv = _dup_str_n(*start, end - *start);
*start = end;
return rv;
}
return NULL;
}
static char **
__cfustring_split_to_raw(cfustring_t *cfu_str, size_t *num_strings, size_t num_seps, size_t limit,
va_list ap) {
char *sep = NULL;
size_t i = 0;
char **sep_array = (char **)calloc(num_seps, sizeof(char *));
char **sep_chk_ptrs = (char **)calloc(num_seps, sizeof(char *));
char **ret_strings = (char **)calloc(2, sizeof(char *));
u_int max_ret_strings = 2;
u_int used_ret_strings = 0;
char *start = NULL;
char *end = NULL;
char *next_str = NULL;
int last = 0;
*num_strings = 0;
if (limit == 1) {
ret_strings[0] = cfustring_get_buffer_copy(cfu_str);
*num_strings = 1;
return ret_strings;
}
for (i = 0; i < num_seps; i++) {
sep = va_arg(ap, char *);
sep_array[i] = _dup_str(sep);
}
start = end = cfustring_get_buffer(cfu_str);
if (!end) {
*num_strings = 0;
free(ret_strings);
for (i = 0; i < num_seps; i++) {
free(sep_array[i]);
}
free(sep_array);
return NULL;
}
while ( (next_str = _check_sep(&end, sep_array, num_seps, sep_chk_ptrs, last)) ) {
if (used_ret_strings == max_ret_strings) {
/* allocate more space */
size_t new_size = max_ret_strings << 1;
char **tmp = (char **)calloc(new_size, sizeof(char *));
for (i = 0; i < used_ret_strings; i++) tmp[i] = ret_strings[i];
free(ret_strings);
ret_strings = tmp;
max_ret_strings = new_size;
}
ret_strings[used_ret_strings] = next_str;
used_ret_strings++;
if (limit > 0 && used_ret_strings == limit - 1) {
last = 1;
}
}
for (i = 0; i < num_seps; i++) {
free(sep_array[i]);
}
free(sep_array);
free(sep_chk_ptrs);
*num_strings = used_ret_strings;
return ret_strings;
}
extern cfustring_t **
cfustring_split(cfustring_t *cfu_str, size_t *num_strings, size_t limit, ...) {
va_list ap;
char **strings = NULL;
char *sep = NULL;
cfustring_t **rv = NULL;
size_t i = 0;
size_t num_seps = 0;
va_start(ap, limit);
sep = va_arg(ap, char *);
while (sep) {
num_seps++;
sep = va_arg(ap, char *);
}
va_end(ap);
va_start(ap, limit);
strings = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
va_end(ap);
if (!*num_strings) return NULL;
rv = (cfustring_t **)malloc(*num_strings * sizeof(cfustring_t *));
for (i = 0; i < *num_strings; i++) {
rv[i] = cfustring_new_from_string(strings[i]);
free(strings[i]);
}
free(strings);
return rv;
}
extern char **
cfustring_split_to_c_str(cfustring_t *cfu_str, size_t *num_strings, size_t limit, ...) {
char **rv = NULL;
va_list ap;
size_t num_seps = 0;
char *sep = NULL;
va_start(ap, limit);
sep = va_arg(ap, char *);
while (sep) {
num_seps++;
sep = va_arg(ap, char *);
}
va_end(ap);
va_start(ap, limit);
rv = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
va_end(ap);
return rv;
}
extern char *
cfustring_sprintf_c_str(const char *fmt, ...) {
va_list ap;
char *str = NULL;
cfustring_t *cfu_str = cfustring_new();
va_start(ap, fmt);
cfustring_vsprintf(cfu_str, fmt, ap);
va_end(ap);
str = cfustring_get_buffer_copy(cfu_str);
cfustring_destroy(cfu_str);
return str;
}
extern size_t
cfustring_sprintf(cfustring_t *cfu_str, const char *fmt, ...) {
va_list ap;
size_t rv = 0;
va_start(ap, fmt);
rv = cfustring_vsprintf(cfu_str, fmt, ap);
va_end(ap);
return rv;
}
static int
_safe_sprintf(char **buf, size_t *buf_size, const char *fmt, ...) {
va_list ap;
int rv = 0;
int done = 0;
if (!(*buf) || *buf_size == 0) {
*buf_size = 128;
if (*buf) free(*buf);
*buf = (char *)malloc(*buf_size);
}
while (!done) {
va_start(ap, fmt);
rv = vsnprintf(*buf, *buf_size, fmt, ap);
va_end(ap);
if (rv >= (int)(*buf_size) - 1) {
*buf_size *= 2;
free(*buf);
*buf = (char *)malloc(*buf_size);
}
else {
done = 1;
}
}
return rv;
}
static char *
_safe_strncpy(char **buf, size_t *buf_size, const char *src, size_t size) {
char *rv = NULL;
if (!(*buf) || *buf_size == 0) {
*buf_size = size + 1;
if (*buf) free(*buf);
*buf = (char *)malloc(*buf_size);
(*buf)[0] = '\000';
}
if (size > *buf_size - 1) {
*buf_size = size + 1;
if (*buf) free(*buf);
*buf = (char *)malloc(*buf_size);
(*buf)[0] = '\000';
}
rv = strncpy(*buf, src, size);
return rv;
}
extern size_t
cfustring_vsprintf(cfustring_t *cfu_str, const char *fmt_in, va_list ap) {
const char *ptr = NULL;
const char *start = NULL;
const char *end = NULL;
size_t byte_count = 0;
size_t buf_size = 128;
size_t buf2_size = 128;
char *buf = NULL;
char *buf2 = NULL;
const char *fmt = NULL;
buf = (char *)malloc(buf_size);
buf2 = (char *)malloc(buf2_size);
cfustring_clear(cfu_str);
ptr = start = end = fmt = fmt_in;
while (*fmt) {
if (*fmt == '%') {
ptr = fmt;
fmt++;
if (*fmt == '%') {
end++;
cfustring_append_n(cfu_str, start, ptr - start + 1);
byte_count += ptr - start + 1;
fmt++;
start = end = fmt;
continue;
}
while (*fmt && *fmt != 'u' && *fmt != 's' && *fmt != 'd' && *fmt != 'f' && *fmt != 'F'
&& *fmt != 'x' && *fmt != 'X' && *fmt != 'p'
&& *fmt != ' ' && *fmt != '\t') fmt++;
if (*fmt == 'u' || *fmt == 'd' || *fmt == 'f' || *fmt == 'F'
|| *fmt == 'x' || *fmt == 'X' || *fmt == 'p') {
unsigned num = 0;
double f = 0;
int d = 0;
void *p = NULL;
size_t size = fmt - ptr + 1;
_safe_strncpy(&buf2, &buf2_size, ptr, size);
buf2[size] = '\000';
switch (*fmt) {
case 'u':
case 'x':
case 'X':
case 'o':
num = va_arg(ap, unsigned);
_safe_sprintf(&buf, &buf_size, buf2, num);
break;
case 'd':
case 'c':
d = va_arg(ap, int);
_safe_sprintf(&buf, &buf_size, buf2, d);
break;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
case 'a':
case 'A':
f = va_arg(ap, double);
_safe_sprintf(&buf, &buf_size, buf2, f);
break;
case 'p':
p = va_arg(ap, void *);
_safe_sprintf(&buf, &buf_size, buf2, p);
break;
default:
break;
}
cfustring_append_n(cfu_str, start, end - start + 1);
byte_count += end - start + 1;
cfustring_append(cfu_str, buf);
byte_count += strlen(buf);
fmt++;
start = end = fmt;
continue;
} else if (*fmt == 's') {
char *s = NULL;
size_t size = fmt - ptr + 1;
s = va_arg(ap, char *);
buf[0] = '\000';
_safe_strncpy(&buf2, &buf2_size, ptr, size);
buf2[size] = '\000';
_safe_sprintf(&buf, &buf_size, buf2, s);
if (ptr != start) {
cfustring_append_n(cfu_str, start, end - start + 1);
byte_count += end - start + 1;
}
if (s) {
cfustring_append(cfu_str, buf);
byte_count += strlen(buf);
} else {
s = "(null)";
cfustring_append(cfu_str, s);
byte_count += strlen(s);
}
fmt++;
start = end = fmt;
continue;
} else if (*fmt == ' ' || *fmt == '\t') {
cfustring_append_n(cfu_str, start, end - start + 1);
byte_count += end - start + 1;
fmt++;
start = end = fmt;
continue;
}
} else {
byte_count++;
end = fmt;
}
fmt++;
}
if (end != start) {
cfustring_append_n(cfu_str, start, end - start + 1);
byte_count += end - start + 1;
}
free(buf);
free(buf2);
return byte_count;
}
extern int
cfustring_destroy(cfustring_t *cfu_str) {
free(cfu_str->str);
free(cfu_str);
return 1;
}
extern char **
cfustring_c_str_split(const char *c_str, size_t *num_strings, size_t limit, ...) {
cfustring_t *cfu_str = cfustring_new_from_string(c_str);
char **rv = NULL;
va_list ap;
size_t num_seps = 0;
char *sep = NULL;
va_start(ap, limit);
sep = va_arg(ap, char *);
while (sep) {
num_seps++;
sep = va_arg(ap, char *);
}
va_end(ap);
va_start(ap, limit);
rv = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
va_end(ap);
cfustring_destroy(cfu_str);
return rv;
}

152
src/cfuthread_queue.c Normal file
View File

@ -0,0 +1,152 @@
/* Creation date: 2005-07-26 08:20:59
* Authors: Don
* Change log:
*/
#include "cfuthread_queue.h"
#include "cfulist.h"
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
struct cfuthread_queue {
pthread_mutex_t mutex;
pthread_cond_t cv;
cfulist_t *request_queue;
cfuthread_queue_fn_t fn;
pthread_t thread;
cfuthread_queue_init_t init_fn;
void *init_arg;
cfuthread_queue_cleanup_t cleanup_fn;
void *cleanup_arg;
};
typedef struct cfuthread_queue_entry {
pthread_mutex_t mutex;
pthread_cond_t cv;
void *data_in;
void *data_out;
} cfuthread_queue_entry;
static cfuthread_queue_entry *
_new_cfuthread_entry(void *data) {
cfuthread_queue_entry *entry =
(cfuthread_queue_entry *)calloc(1, sizeof(cfuthread_queue_entry));
pthread_mutex_init(&entry->mutex, NULL);
pthread_cond_init(&entry->cv, NULL);
entry->data_in = data;
return entry;
}
static void
_destroy_cfuthread_entry(cfuthread_queue_entry *entry) {
pthread_mutex_destroy(&entry->mutex);
pthread_cond_destroy(&entry->cv);
free(entry);
}
static void *
_run_queue(void *arg) {
cfuthread_queue_t *tq = (cfuthread_queue_t *)arg;
cfuthread_queue_entry *request = NULL;
if (tq->init_fn) {
tq->init_fn(tq->init_arg);
}
pthread_cleanup_push((void *)tq->cleanup_fn, tq->cleanup_arg);
while (1) {
pthread_mutex_lock(&tq->mutex);
while (cfulist_num_entries(tq->request_queue) == 0) {
pthread_cond_wait(&tq->cv, &tq->mutex);
}
request = (cfuthread_queue_entry *)cfulist_dequeue(tq->request_queue);
pthread_mutex_unlock(&tq->mutex);
if (!request) continue;
pthread_mutex_lock(&request->mutex);
request->data_out = tq->fn(request->data_in);
pthread_cond_signal(&request->cv);
pthread_mutex_unlock(&request->mutex);
}
pthread_exit((void *)0);
pthread_cleanup_pop(0);
}
extern cfuthread_queue_t *
cfuthread_queue_new_with_cleanup(cfuthread_queue_fn_t fn, cfuthread_queue_init_t init_fn,
void *init_arg, cfuthread_queue_cleanup_t cleanup_fn,
void *cleanup_arg) {
cfuthread_queue_t *tq = (cfuthread_queue_t *)calloc(1, sizeof(cfuthread_queue_t));
pthread_mutex_init(&tq->mutex, NULL);
pthread_cond_init(&tq->cv, NULL);
tq->fn = fn;
tq->request_queue = cfulist_new();
tq->init_fn = init_fn;
tq->init_arg = init_arg;
tq->cleanup_fn = cleanup_fn;
tq->cleanup_arg = cleanup_arg;
/* FIXME: do pthread_create() here to run a function that waits on
an entry to be put into the queue, then call fn().
*/
if ( (0 != pthread_create(&tq->thread, NULL, _run_queue, (void *)tq)) ) {
return NULL;
}
return tq;
}
extern cfuthread_queue_t *
cfuthread_queue_new(cfuthread_queue_fn_t fn) {
return cfuthread_queue_new_with_cleanup(fn, NULL, NULL, NULL, NULL);
}
extern void *
cfuthread_queue_make_request(cfuthread_queue_t * tq, void *data) {
cfuthread_queue_entry *request = _new_cfuthread_entry(data);
pthread_mutex_lock(&tq->mutex);
pthread_mutex_lock(&request->mutex);
cfulist_enqueue(tq->request_queue, (void *)request);
pthread_cond_signal(&tq->cv);
pthread_mutex_unlock(&tq->mutex);
pthread_cond_wait(&request->cv, &request->mutex);
pthread_mutex_unlock(&request->mutex);
data = request->data_out;
_destroy_cfuthread_entry(request);
return data;
}
extern void
cfuthread_queue_destroy(cfuthread_queue_t *tq) {
void *rv = NULL;
pthread_cancel(tq->thread);
pthread_join(tq->thread, &rv);
pthread_mutex_destroy(&tq->mutex);
pthread_cond_destroy(&tq->cv);
cfulist_destroy(tq->request_queue);
free(tq);
}

91
src/cfutime.c Normal file
View File

@ -0,0 +1,91 @@
/* Creation date: 2005-06-26 18:11:40
* Authors: Don
* Change log:
*/
/* Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cfu.h"
#include "cfutime.h"
#include <string.h>
#include <stdlib.h>
#ifdef CFU_DEBUG
#ifdef NDEBUG
#undef NDEBUG
#endif
#else
#ifndef NDEBUG
#define NDEBUG 1
#endif
#endif
#include <assert.h>
typedef struct cfutime {
libcfu_type type;
struct timeval begin_tv;
struct timezone begin_tz;
struct timeval end_tv;
struct timezone end_tz;
} cfutime;
extern cfutime_t *
cfutime_new() {
cfutime_t *time = (cfutime_t *)calloc(1, sizeof(cfutime));
time->type = libcfu_t_time;
return time;
}
extern void
cfutime_begin(cfutime_t *time) {
gettimeofday(&(time->begin_tv), &(time->begin_tz));
}
extern void
cfutime_end(cfutime_t *time) {
gettimeofday(&(time->end_tv), &(time->end_tz));
}
extern double
cfutime_elapsed(cfutime_t *time) {
return (double)time->end_tv.tv_sec + ((double)time->end_tv.tv_usec)/1000000 -
((double)time->begin_tv.tv_sec + ((double)time->begin_tv.tv_usec)/1000000);
}
extern void
cfutime_free(cfutime_t *time) {
free(time);
}

74
src/libcfu-config.c Normal file
View File

@ -0,0 +1,74 @@
/* Creation date: 2005-08-07 13:34:49
* Authors: Don
* Change log:
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "cfu.h"
#include "cfuopt.h"
#define GET_PREFIX CFU_PREFIX
#define GET_EXEC_PREFIX CFU_EXEC_PREFIX
#define GET_VERSION LIBCFU_VERSION
#define GET_LIBS "-L" CFU_LIBDIR " -lcfu " CFU_LIBS
#define GET_CFLAGS "-I" CFU_INCLUDEDIR
static void
print_usage() {
fprintf(stderr, "Usage: libcfu-config [OPTIONS]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " --prefix [%s]\n", GET_PREFIX);
fprintf(stderr, " --exec-prefix [%s]\n", GET_EXEC_PREFIX);
fprintf(stderr, " --version [%s]\n", GET_VERSION);
fprintf(stderr, " --libs [%s]\n", GET_LIBS);
fprintf(stderr, " --cflags [%s]\n", GET_CFLAGS);
}
int main(int argc, char **argv) {
char *arg = NULL;
int do_prefix = 0;
int do_exec_prefix = 0;
int do_version = 0;
int do_libs = 0;
int do_cflags = 0;
cfuopt_t *options = cfuopt_new();
char *error = NULL;
cfuopt_add_entry(options, "prefix!", &do_prefix, "Display install prefix", NULL);
cfuopt_add_entry(options, "exec-prefix!", &do_exec_prefix, "Display install prefix for executables", NULL);
cfuopt_add_entry(options, "version!", &do_version, "Display library version", NULL);
cfuopt_add_entry(options, "libs!", &do_libs, "Display libraries required for linking with this library", NULL);
cfuopt_add_entry(options, "cflags", &do_cflags, "Display CFLAGS required for compilation", NULL);
if (argc < 2) {
print_usage();
exit(1);
}
cfuopt_parse(options, &argc, &argv, &error);
arg = argv[1];
if (do_prefix) {
fprintf(stdout, "%s\n", GET_PREFIX);
} else if (do_exec_prefix) {
fprintf(stdout, "%s\n", GET_EXEC_PREFIX);
} else if (do_version) {
fprintf(stdout, "%s\n", GET_VERSION);
} else if (do_libs) {
fprintf(stdout, "%s\n", GET_LIBS);
} else if (do_cflags) {
fprintf(stdout, "%s\n", GET_CFLAGS);
} else {
print_usage();
cfuopt_destroy(options);
exit(1);
}
cfuopt_destroy(options);
return 0;
}