summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/.gitignore2
-rw-r--r--doc/Makefile.am16
-rw-r--r--doc/Makefile.in505
-rw-r--r--doc/api.txt355
-rw-r--r--doc/assorted.txt68
-rw-r--r--doc/changelog.txt535
-rw-r--r--doc/const_cast.c12
-rw-r--r--doc/dirstamp.txt4
-rwxr-xr-xdoc/generate6
-rw-r--r--doc/generator.cpp43
-rw-r--r--doc/libHX_Documentation.lyx24728
-rw-r--r--doc/libHX_Documentation.pdfbin0 -> 523100 bytes
-rw-r--r--doc/slurp.c38
-rw-r--r--doc/ux-file.txt30
-rw-r--r--doc/ux-mmap.txt26
15 files changed, 26368 insertions, 0 deletions
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..2789f42
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,2 @@
+*.lyx~
+*.pdf
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..14eba9f
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,16 @@
+# -*- Makefile -*-
+
+if BUILD_DOCS
+dist_doc_DATA = libHX_Documentation.pdf
+endif
+
+libHX_Documentation.pdf: libHX_Documentation.lyx
+ srcdir="${srcdir}" ${srcdir}/generate;
+
+EXTRA_DIST = libHX_Documentation.lyx api.txt changelog.txt
+
+install-data-local:
+ if test -e libHX_Documentation.pdf; then \
+ ${MKDIR_P} "${DESTDIR}${docdir}" || exit 1; \
+ ${INSTALL_DATA} libHX_Documentation.pdf "${DESTDIR}${docdir}" || exit $$?; \
+ fi
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..50f826f
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,505 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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@
+
+# -*- Makefile -*-
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+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 = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = doc
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(am__dist_doc_DATA_DIST)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gcc4_visibility.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__dist_doc_DATA_DIST = libHX_Documentation.pdf
+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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(docdir)"
+DATA = $(dist_doc_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LYX = @LYX@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+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 = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libdl_LIBS = @libdl_LIBS@
+libexecdir = @libexecdir@
+libpthread_LIBS = @libpthread_LIBS@
+librt_LIBS = @librt_LIBS@
+libsocket_LIBS = @libsocket_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+regular_CFLAGS = @regular_CFLAGS@
+regular_CPPFLAGS = @regular_CPPFLAGS@
+regular_CXXFLAGS = @regular_CXXFLAGS@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@BUILD_DOCS_TRUE@dist_doc_DATA = libHX_Documentation.pdf
+EXTRA_DIST = libHX_Documentation.lyx api.txt changelog.txt
+all: all-am
+
+.SUFFIXES:
+$(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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign 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
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-dist_docDATA: $(dist_doc_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-dist_docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(docdir)"; 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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-dist_docDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_docDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dist_docDATA install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am uninstall-dist_docDATA
+
+
+libHX_Documentation.pdf: libHX_Documentation.lyx
+ srcdir="${srcdir}" ${srcdir}/generate;
+
+install-data-local:
+ if test -e libHX_Documentation.pdf; then \
+ ${MKDIR_P} "${DESTDIR}${docdir}" || exit 1; \
+ ${INSTALL_DATA} libHX_Documentation.pdf "${DESTDIR}${docdir}" || exit $$?; \
+ fi
+
+# 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:
diff --git a/doc/api.txt b/doc/api.txt
new file mode 100644
index 0000000..eb3b06b
--- /dev/null
+++ b/doc/api.txt
@@ -0,0 +1,355 @@
+
+Table of contents
+=================
+1. Symbol reference
+2. Header reference
+
+
+Function reference
+==================
+
+R column: Recommend version number to use in PKG_CONFIG_CHECK in
+projects using libHX. Includes important bugfixes.
+M column: Lowest possible version with the same function signature.
+F column: Function first seen in version, possibly with different API.
+
+RMV MinVer FirstA Name
+----------------------------------------------------------------------
+3.22 3.22 3.22 HXQUOTE_SQLBQUOTE
+3.21 3.21 3.21 xml_getnsprop
+3.19 3.19 3.19 HXQUOTE_SQLSQUOTE
+3.18 3.18 3.18 HX_stpltrim
+3.17 3.17 3.17 HX_LONGLONG_FMT
+3.17 3.17 3.17 HX_SIZET_FMT
+3.16 3.16 3.16 container_of
+3.16 3.16 3.16 wxCDF
+3.16 3.16 3.16 wxDSPAN
+3.15 3.15 3.15 FIELD_SIZEOF
+3.15 3.15 3.15 HXQUOTE_URIENC
+3.15 3.15 3.15 HX_strchr2
+3.13 3.13 3.13 DEMOTE_TO_PTR
+3.13 3.13 3.13 HXTYPE_SIZE_T
+3.13 3.13 3.13 HX_TIMESPEC_EXP
+3.13 3.13 3.13 HX_TIMESPEC_FMT
+3.13 3.13 3.13 HX_TIMEVAL_EXP
+3.13 3.13 3.13 HX_TIMEVAL_FMT
+3.13 3.13 3.13 HX_timespec_add
+3.13 3.13 3.13 HX_timespec_isneg
+3.13 3.13 3.13 HX_timespec_mul
+3.13 3.13 3.13 HX_timespec_mulf
+3.13 3.13 3.13 HX_timespec_neg
+3.13 3.13 3.13 HX_timespec_sub
+3.13 3.13 3.13 HX_timeval_sub
+3.12 3.12 1.10.0 HX_mkdir
+3.12 3.12 3.12 HX_strndup
+3.12 3.12 3.12 HX_strnlen
+3.12 3.0 3.0 HXMAP_CDATA
+3.12 3.0 3.0 HXMAP_CKEY
+3.12 3.0 3.0 HXMAP_SCDATA
+3.12 3.0 3.0 HXMAP_SCKEY
+3.12 3.0 3.0 HXMAP_SDATA
+3.12 3.0 3.0 HXMAP_SINGULAR
+3.12 3.0 3.0 HXMAP_SKEY
+3.12 3.12 3.12 HXOPT_ERR_SUCCESS
+3.12 3.12 3.12 HXOPT_ERR_SYS
+3.12 3.12 3.12 HXOPTCB_BY_LONG
+3.12 3.12 3.12 HXOPTCB_BY_SHORT
+3.12 3.0 1.10.0 HXformat_aprintf
+3.12 3.0 1.10.0 HXformat_fprintf
+3.12 3.0 1.10.0 HXformat_sprintf
+3.11 3.11 3.11 HXQUOTE_BASE64
+3.10 3.10 3.10 BUILD_BUG_ON_EXPR
+3.10 3.10 3.10 HX_readlink
+3.10 3.10 3.10 HX_realpath
+3.9.1 3.9 3.9 HXio_fullread
+3.9.1 3.9 3.9 HXio_fullwrite
+3.9 3.9 3.9 HXMAP_NONE
+3.7 3.7 3.7 HXlist_for_each_rev
+3.7 3.7 3.7 HXlist_for_each_rev_safe
+3.7 3.7 1.22 xml_newnode
+3.7 1.15 1.15 HXclist_pop
+3.7 1.15 1.15 HXclist_shift
+3.7 1.10.0 1.10.0 HX_ffs
+3.7 1.10.0 1.10.0 HX_zveclen
+3.7 1.10.0 1.10.0 HXdir_close
+3.7 1.10.0 1.10.0 HXdir_open
+3.7 1.10.0 1.10.0 HXdir_read
+3.6 3.6 3.1 HXbitmap_clear
+3.6 3.6 3.1 HXbitmap_set
+3.6 3.6 3.1 HXbitmap_test
+3.6 1.10.0 1.10.0 HX_split
+3.5 3.5 3.5 HXMAP_NOFLAGS
+3.5 3.5 3.5 HXQUOTE_LDAPFLT
+3.5 3.5 3.5 HXQUOTE_LDAPRDN
+3.5 3.5 3.5 HXSIZEOF_Z16
+3.5 2.2 2.2 HXproc_run_async
+3.5 2.2 2.2 HXproc_run_sync
+3.4 3.4 3.4 HX_exit
+3.4 3.4 3.4 HX_init
+3.4 3.4 3.4 HX_memmem
+3.4 3.4 3.4 HXlist_empty
+3.3 3.3 3.3 HX_drand
+3.3 3.3 3.3 HX_shconfig_map
+3.3 3.3 3.3 HXdeque_genocide2
+3.3 3.3 3.3 HXmc_zvecfree
+3.3 1.10.0 1.10.0 HX_shconfig
+3.3 1.10.0 1.10.0 HX_shconfig_pv
+3.2 3.2 3.2 HXQUOTE_DQUOTE
+3.2 3.2 3.2 HXQUOTE_HTML
+3.2 3.2 3.2 HXQUOTE_SQUOTE
+3.2 3.2 3.2 HXTYPE_MCSTR
+3.2 3.2 3.2 HX_strquote
+3.1 3.1 3.1 HXbitmap_size
+3.1 1.25 1.25 HXmc_strcpy
+3.0.1 3.0 3.0 HXmap_add
+3.0.1 3.0 3.0 HXmap_del
+3.0.1 3.0 3.0 HXmap_del<>
+3.0.1 3.0 3.0 HXmap_find
+3.0.1 3.0 3.0 HXmap_get
+3.0.1 3.0 3.0 HXmap_get<>
+3.0.1 3.0 3.0 HXmap_qfe
+3.0.1 3.0 3.0 HXmap_traverse
+3.0.1 3.0 3.0 HXmap_travinit
+3.0 3.0 3.0 HXMAPT_DEFAULT
+3.0 3.0 3.0 HXMAPT_HASH
+3.0 3.0 3.0 HXMAPT_ORDERED
+3.0 3.0 3.0 HXMAPT_RBTREE
+3.0 3.0 3.0 HXMAP_DTRAV
+3.0 3.0 3.0 HXMAP_NOREPLACE
+3.0 3.0 3.0 HX_diff_timespec
+3.0 3.0 3.0 HX_diff_timeval
+3.0 3.0 3.0 HXhash_djb2
+3.0 3.0 3.0 HXhash_jlookup3
+3.0 3.0 3.0 HXhash_jlookup3s
+3.0 3.0 3.0 HXmap_free
+3.0 3.0 3.0 HXmap_init
+3.0 3.0 3.0 HXmap_init5
+3.0 3.0 3.0 HXmap_keysvalues
+3.0 3.0 3.0 HXmap_travfree
+3.0 3.0 3.0 HXsizeof_member
+3.0 3.0 3.0 HXtypeof_member
+3.0 3.0 1.10.0 HXformat_add
+3.0 3.0 1.10.0 HXformat_free
+3.0 3.0 1.10.0 HXformat_init
+2.9 2.9 2.9 HX_basename_exact
+2.9 2.2 2.2 HX_split4
+2.9 1.10.0 1.10.0 HX_basename
+2.8 2.8 2.8 HXPROC_NULL_STDERR
+2.8 2.8 2.8 HXPROC_NULL_STDIN
+2.8 2.8 2.8 HXPROC_NULL_STDOUT
+2.6 2.6 2.6 HX_fls
+2.6 2.6 2.6 wxACV
+2.6 2.6 2.6 wxDPOS
+2.6 2.6 2.6 wxDSIZE
+2.6 2.6 2.6 wxfu8
+2.6 2.6 2.6 wxfv8
+2.6 2.6 2.6 wxtu8
+2.6 2.6 2.6 xml_strcasecmp
+2.3 2.0 2.0 offsetof
+2.3 1.25 1.25 HXmc_length
+2.2 2.2 2.2 HXPROC_A0
+2.2 2.2 2.2 HXPROC_EXECV
+2.2 2.2 2.2 HXPROC_STDERR
+2.2 2.2 2.2 HXPROC_STDIN
+2.2 2.2 2.2 HXPROC_STDOUT
+2.2 2.2 2.2 HXPROC_VERBOSE
+2.2 2.2 2.2 HXSIZEOF_Z32
+2.2 2.2 2.2 HXSIZEOF_Z64
+2.2 2.2 2.2 HX_STRINGIFY
+2.2 2.2 2.2 HXproc_wait
+2.2 2.0 2.0 const_cast1
+2.2 2.0 2.0 const_cast2
+2.2 2.0 2.0 const_cast3
+2.1 2.0 2.0 static_cast
+2.0 2.0 2.0 HX_isalnum
+2.0 2.0 2.0 HX_isalpha
+2.0 2.0 2.0 HX_isdigit
+2.0 2.0 2.0 HX_islower
+2.0 2.0 2.0 HX_isprint
+2.0 2.0 2.0 HX_isspace
+2.0 2.0 2.0 HX_isupper
+2.0 2.0 2.0 HX_isxdigit
+2.0 2.0 2.0 HX_tolower
+2.0 2.0 2.0 HX_toupper
+2.0 2.0 2.0 HXmc_setlen
+2.0 2.0 2.0 const_cast
+2.0 2.0 2.0 containerof
+2.0 2.0 2.0 reinterpret_cast
+2.0 2.0 2.0 signed_cast<>
+2.0 1.23 1.23 signed_cast
+2.0 1.10.0 1.10.0 HX_strmid
+1.28 1.28 1.28 HXTYPE_INT16
+1.28 1.28 1.28 HXTYPE_INT32
+1.28 1.28 1.28 HXTYPE_INT64
+1.28 1.28 1.28 HXTYPE_INT8
+1.28 1.28 1.28 HXTYPE_UINT16
+1.28 1.28 1.28 HXTYPE_UINT32
+1.28 1.28 1.28 HXTYPE_UINT64
+1.28 1.28 1.28 HXTYPE_UINT8
+1.26 1.26 1.26 HX_hexdump
+1.26 1.26 1.26 HX_time_compare
+1.25 1.25 1.25 HX_getl
+1.25 1.25 1.25 HXmc_free
+1.25 1.25 1.25 HXmc_memcat
+1.25 1.25 1.25 HXmc_memcpy
+1.25 1.25 1.25 HXmc_memdel
+1.25 1.25 1.25 HXmc_meminit
+1.25 1.25 1.25 HXmc_memins
+1.25 1.25 1.25 HXmc_mempcat
+1.25 1.25 1.25 HXmc_strcat
+1.25 1.25 1.25 HXmc_strinit
+1.25 1.25 1.25 HXmc_strins
+1.25 1.25 1.25 HXmc_strpcat
+1.25 1.25 1.25 HXmc_trunc
+1.23 1.23 1.23 ARRAY_SIZE
+1.23 1.23 1.23 BUILD_BUG_ON
+1.23 1.23 1.23 O_BINARY
+1.23 1.23 1.23 S_IRUGO
+1.23 1.23 1.23 S_IRWXUGO
+1.23 1.23 1.23 S_IWUGO
+1.23 1.23 1.23 S_IXUGO
+1.22 1.22 1.22 xml_getprop
+1.22 1.22 1.22 xml_newprop
+1.22 1.22 1.22 xml_strcmp
+1.18 1.18 1.18 HXlist_for_each_entry_rev
+1.17 1.17 1.17 HXclist_del
+1.17 1.17 1.17 HXlist_entry
+1.17 1.17 1.17 HXlist_for_each_entry_safe
+1.17 1.17 1.17 HXlist_for_each_safe
+1.17 1.17 1.15 HXclist_init
+1.17 1.17 1.15 HXlist_init
+1.15 1.15 1.15 HXCLIST_HEAD
+1.15 1.15 1.15 HXCLIST_HEAD_INIT
+1.15 1.15 1.15 HXLIST_HEAD
+1.15 1.15 1.15 HXLIST_HEAD_INIT
+1.15 1.15 1.15 HXclist_push
+1.15 1.15 1.15 HXclist_unshift
+1.15 1.15 1.15 HXlist_add
+1.15 1.15 1.15 HXlist_add_tail
+1.15 1.15 1.15 HXlist_del
+1.15 1.15 1.15 HXlist_for_each
+1.15 1.15 1.15 HXlist_for_each_entry
+1.10.0 1.10.0 1.10.0 HXFORMAT_IMMED
+1.10.0 1.10.0 1.10.0 HXF_GID
+1.10.0 1.10.0 1.10.0 HXF_KEEP
+1.10.0 1.10.0 1.10.0 HXF_UID
+1.10.0 1.10.0 1.10.0 HXOPT_AND
+1.10.0 1.10.0 1.10.0 HXOPT_AUTOHELP
+1.10.0 1.10.0 1.10.0 HXOPT_DEC
+1.10.0 1.10.0 1.10.0 HXOPT_DESTROY_OLD
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_MIS
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_UNKN
+1.10.0 1.10.0 1.10.0 HXOPT_ERR_VOID
+1.10.0 1.10.0 1.10.0 HXOPT_HELPONERR
+1.10.0 1.10.0 1.10.0 HXOPT_INC
+1.10.0 1.10.0 1.10.0 HXOPT_NOT
+1.10.0 1.10.0 1.10.0 HXOPT_OPTIONAL
+1.10.0 1.10.0 1.10.0 HXOPT_OR
+1.10.0 1.10.0 1.10.0 HXOPT_PTHRU
+1.10.0 1.10.0 1.10.0 HXOPT_QUIET
+1.10.0 1.10.0 1.10.0 HXOPT_TABLEEND
+1.10.0 1.10.0 1.10.0 HXOPT_USAGEONERR
+1.10.0 1.10.0 1.10.0 HXOPT_XOR
+1.10.0 1.10.0 1.10.0 HXTYPE_BOOL
+1.10.0 1.10.0 1.10.0 HXTYPE_CHAR
+1.10.0 1.10.0 1.10.0 HXTYPE_DOUBLE
+1.10.0 1.10.0 1.10.0 HXTYPE_FLOAT
+1.10.0 1.10.0 1.10.0 HXTYPE_INT
+1.10.0 1.10.0 1.10.0 HXTYPE_LLONG
+1.10.0 1.10.0 1.10.0 HXTYPE_LONG
+1.10.0 1.10.0 1.10.0 HXTYPE_NONE
+1.10.0 1.10.0 1.10.0 HXTYPE_SHORT
+1.10.0 1.10.0 1.10.0 HXTYPE_STRDQ
+1.10.0 1.10.0 1.10.0 HXTYPE_STRING
+1.10.0 1.10.0 1.10.0 HXTYPE_STRP
+1.10.0 1.10.0 1.10.0 HXTYPE_SVAL
+1.10.0 1.10.0 1.10.0 HXTYPE_UCHAR
+1.10.0 1.10.0 1.10.0 HXTYPE_UINT
+1.10.0 1.10.0 1.10.0 HXTYPE_ULLONG
+1.10.0 1.10.0 1.10.0 HXTYPE_ULONG
+1.10.0 1.10.0 1.10.0 HXTYPE_USHORT
+1.10.0 1.10.0 1.10.0 HXTYPE_VAL
+1.10.0 1.10.0 1.10.0 HX_chomp
+1.10.0 1.10.0 1.10.0 HX_copy_dir
+1.10.0 1.10.0 1.10.0 HX_copy_file
+1.10.0 1.10.0 1.10.0 HX_dirname
+1.10.0 1.10.0 1.10.0 HX_dlclose
+1.10.0 1.10.0 1.10.0 HX_dlerror
+1.10.0 1.10.0 1.10.0 HX_dlopen
+1.10.0 1.10.0 1.10.0 HX_dlsym
+1.10.0 1.10.0 1.10.0 HX_dlsym<>
+1.10.0 1.10.0 1.10.0 HX_getopt
+1.10.0 1.10.0 1.10.0 HX_getopt_help
+1.10.0 1.10.0 1.10.0 HX_getopt_usage
+1.10.0 1.10.0 1.10.0 HX_irand
+1.10.0 1.10.0 1.10.0 HX_memdup
+1.10.0 1.10.0 1.10.0 HX_memdup<>
+1.10.0 1.10.0 1.10.0 HX_rand
+1.10.0 1.10.0 1.10.0 HX_rrmdir
+1.10.0 1.10.0 1.10.0 HX_shconfig_free
+1.10.0 1.10.0 1.10.0 HX_split5
+1.10.0 1.10.0 1.10.0 HX_strbchr
+1.10.0 1.10.0 1.10.0 HX_strclone
+1.10.0 1.10.0 1.10.0 HX_strdup
+1.10.0 1.10.0 1.10.0 HX_strlcat
+1.10.0 1.10.0 1.10.0 HX_strlcpy
+1.10.0 1.10.0 1.10.0 HX_strlncat
+1.10.0 1.10.0 1.10.0 HX_strlower
+1.10.0 1.10.0 1.10.0 HX_strltrim
+1.10.0 1.10.0 1.10.0 HX_strrcspn
+1.10.0 1.10.0 1.10.0 HX_strrev
+1.10.0 1.10.0 1.10.0 HX_strrtrim
+1.10.0 1.10.0 1.10.0 HX_strsep
+1.10.0 1.10.0 1.10.0 HX_strsep2
+1.10.0 1.10.0 1.10.0 HX_strupper
+1.10.0 1.10.0 1.10.0 HX_zvecfree
+1.10.0 1.10.0 1.10.0 HXdeque_del
+1.10.0 1.10.0 1.10.0 HXdeque_find
+1.10.0 1.10.0 1.10.0 HXdeque_free
+1.10.0 1.10.0 1.10.0 HXdeque_get
+1.10.0 1.10.0 1.10.0 HXdeque_init
+1.10.0 1.10.0 1.10.0 HXdeque_move
+1.10.0 1.10.0 1.10.0 HXdeque_pop
+1.10.0 1.10.0 1.10.0 HXdeque_push
+1.10.0 1.10.0 1.10.0 HXdeque_shift
+1.10.0 1.10.0 1.10.0 HXdeque_to_vec
+1.10.0 1.10.0 1.10.0 HXdeque_to_vec<>
+1.10.0 1.10.0 1.10.0 HXdeque_unshift
+1.10.0 1.10.0 1.10.0 SHCONF_ONE
+
+
+Struct reference
+================
+MinVer FirstA
+2.0 2.0 struct HXdeque_node.sptr
+1.10.0 1.10.0 struct HXdeque_node
+1.10.0 1.10.0 struct HXdeque
+1.15 1.15 struct HXclist_head
+1.15 1.15 struct HXlist_head
+3.0 3.0 struct HXmap
+3.0 3.0 struct HXmap_ops
+3.0 3.0 struct HXmap_node
+3.12 1.10.0 struct HXoptcb
+3.12 1.10.0 struct HXoption
+2.2 2.2 struct HXproc_ops
+2.2 2.2 struct HXproc
+
+
+Header reference
+================
+
+MinVer Name
+-------------------------------------------
+3.9 libHX/io.h
+3.4 libHX/init.h
+3.0 libHX/map.h
+2.6 libHX/wx_helper.hpp
+2.2 libHX/proc.h
+2.0 libHX/ctype_helper.h
+1.23 libHX/misc.h
+1.23 libHX/defs.h
+1.22 libHX/xml_helper.h
+1.15 libHX/string.h
+1.15 libHX/option.h
+1.15 libHX/list.h
+1.15 libHX/deque.h
diff --git a/doc/assorted.txt b/doc/assorted.txt
new file mode 100644
index 0000000..b2739e1
--- /dev/null
+++ b/doc/assorted.txt
@@ -0,0 +1,68 @@
+===============================================================================
+assorted - Assorted functions 2006-02-25
+
+
+DESCRIPTION
+
+ Some functions have been taken out of libHX because they are largely unused
+ in code I write. Since there are currently not too many users of libHX that
+ seem to need these functions, they currently remain out.
+
+
+SYNOPSIS
+
+ size_t HX_pack(char *fmt, size_t len, ...);
+ int HX_tofrac(size_t *num, size_t *denom, double arg);
+
+
+HX_pack()
+
+ Mimics perl's pack function. FMT can contain:
+
+ A Pascal-style string: a uint8_t length specifier and a string
+ with up to 255 chars
+ a (same)
+ C encode as uint8_t
+ c encode as int8_t
+ H encode as uint16_t
+ h encode as int16_t
+ L encode as uint32_t
+ l encode as int32_t
+ S Like A, but with a uint16_t length specifier and a string
+ with up to 64K chars
+ s (same)
+ V fixed-size string; first argument is string, second is length
+
+ Example:
+
+ HX_pack(dest, sizeof(dest), "LLSV", 1337, 2006, "64k test string",
+ "fixed test", 5);
+
+ will produce this byte sequence on x86:
+
+ 39 05 00 00 1337
+ D6 07 00 00 2006
+ 0E 00 15
+ 36 34 6B 20 74 65 "64k test string" (length=15)
+ 73 74 20 73 74 72
+ 69 6E 67
+ 66 69 78 65 64 "fixed"
+
+
+HX_tofrac()
+
+ Calculates a readable fraction (i.e. 1/3) from arg and puts the
+ *numerator into num, the denominator into *denom. Since the fraction
+ is found out by an iterative loop, you can specify the minimum value
+ of the denominator in *num and the maximum value of the denominator
+ into *denom before calling the function.
+
+ If a suitable fraction has been found (within the range of the
+ minimum / maximum denominator, *num and *denom will be overwritten
+ with the results and 1 is returned; 0 for no success.
+
+ You need to re-put your min/max denom values into *num and *denom
+ then.
+
+
+
diff --git a/doc/changelog.txt b/doc/changelog.txt
new file mode 100644
index 0000000..2b68284
--- /dev/null
+++ b/doc/changelog.txt
@@ -0,0 +1,535 @@
+
+
+HEAD
+====
+
+
+v3.22 (2014-08-25)
+==================
+Enhancements:
+- string: add the HXQUOTE_SQLBQUOTE quoting variant
+
+
+v3.21 (2014-06-02)
+==================
+Enhancements:
+- HXformat_add() now supports HXTYPE_MCSTR objects (with and without
+ HXTYPE_IMMED)
+- libxml_helper: New xml_getnsprop() function that gets the value of a
+ property (element attribute) by namespace prefix
+
+
+v3.20 (2014-04-18)
+==================
+Enhancements:
+- resolve some link errors when built with Solaris ld
+
+
+v3.19 (2014-02-21)
+==================
+Enhancements:
+- string: add the HXQUOTE_SQLSQUOTE quoting variant
+Internal changes:
+- format: rework function calling code to support extending with functions
+
+
+v3.18 (2014-03-01)
+==================
+Enhancements:
+- string: add the HX_stpltrim function
+Fixes:
+- Make HX_strltrim move the correct number of bytes
+Changes:
+- remove wxCFF from wx_helper.hpp
+
+
+v3.17 (2013-11-16)
+==================
+Enhancements:
+- defs: add HX_SIZET_FMT and HX_LONGLONG_FMT
+- support for Win64
+Fixes:
+- compile warnings on mingw were addressed
+
+
+v3.16 (2013-09-29)
+==================
+Enhancements:
+- format: remove 256-char format key length limit
+Fixes:
+- compile errors on mingw were addressed
+
+
+v3.15 (2013-03-07)
+==================
+Enhancements:
+- string: add HX_strchr2
+- string: add HXQUOTE_URIENC mechanism for HX_strquote
+Changes:
+- defs: HXsizeof_member becomes FIELD_SIZEOF
+ (to match the Linux kernel's macro name)
+
+
+v3.14.1 (2012-12-31)
+====================
+Fixes:
+- Restore forward-sorting order of ordered maps
+ (revert "map: always have needle as second argument")
+
+
+v3.14 (2012-11-14)
+==================
+Fixes:
+- io: use pathconf(3) to determine dirent size for dir traversal
+- rand: avoid division by zero when calling HX_irand with lo==hi
+- time: use C++ static_cast syntax for C++ mode
+- headers: improve operability with C89 compile mode
+
+
+v3.13 (2012-07-28)
+==================
+Enhancements:
+- defs: add DEMOTE_TO_PTR
+- option: new HXOPT_RQ_ORDER flag, allows unconditional POSIX-style parsing
+ (parsing terminates at first non-option encountered)
+- option: add HXTYPE_SIZE_T
+- time: add functions and macros for arithmetic and handling of timespec
+ with support for negative time values
+ * time: add HX_TIMESPEC_{EXP,FMT}
+ * time: add HX_TIMEVAL_{EXP,FMT}
+ * time: add the HX_timespec_isneg function
+ * time: add the HX_timespec_neg function
+ * time: add the HX_timespec_add function
+ * time: add the HX_timespec_mul function
+ * time: add the HX_timespec_mulf function
+Changes:
+- io: remove HX_REALPATH_SYMLINK
+- time: rename HX_diff_timespec to HX_timespec_sub (old ABI kept)
+- time: rename HX_diff_timeval to HX_timeval_sub (old ABI kept)
+- string: make HX_memmem consider the special case of search_length=0
+- string: optimize search_length=1 case in HX_memmem
+- string: speed up HX_memmem searches for search_length >=2
+
+
+v3.12.1 (2011-12-15)
+====================
+Fixes:
+- build: make build error-free when using -Wl,--no-undefined
+- string: make HX_strdup(NULL) valid again
+
+
+v3.12 (2010-12-03)
+==================
+Fixes:
+- defs: resolve warning for users of const_cast*() when using -Wextra
+- format: error handling for HXformat2_aprintf
+- option: do not omit dashes when passthru'ing unknown two-part long opts
+- option: do not omit arg following unknown unknown two-part long opts in pthru
+- option: do run callback on HXTYPE_BOOL
+- option: correct passthrough of squashed unknown short options
+- option: do not stop early when printing help/usage
+- option: avoid crash when passing an empty argv
+- option: avoid crash when passing NULL for struct HXoptcb.arg0
+Enhancements:
+- build: deactivate type-checking of the *_cast() macros for clang due to a
+ compiler bug involving nested structs-in-typeofs
+- option: allow argc=NULL on HX_getopt
+- option: error handling for HX_getopt
+- option: support POSIXLY_CORRECT environment variable
+- string: add a HX_strndup function
+- string: add a HX_strnlen function
+- mc: use an implicit minimum allocated length
+Changes:
+- format: renamed HXformat2_[afs]printf back to HXformat_[afs]printf
+- io: add mode argument to HX_mkdir
+- map: avoid 1<<31 in constants
+- option: remove struct HXoptcb.arg0
+- option: remove struct HXoptcb.match_{ln,sh} by .flags
+- option: let HX_getopt return code indicate system failure states
+- option: remove struct HXoption.sval (replaced by .uptr)
+- string: unline HX_strdup, HX_strlcat, HX_strlcpy, HX_strnlcat
+
+
+v3.11 (2011-07-25)
+==================
+Enhancements:
+- A LD_PRELOAD-able library libHX_rtcheck.so that adds global state correctness
+ checks, was added.
+- add a HXQUOTE_BASE64 to HX_strquote
+Changes:
+- HX_strquote will return NULL for unknown types now instead of just
+ returning the input pointer
+
+
+v3.10.1 (2011-04-06)
+====================
+Fixes:
+- defs: BUILD_BUG_ON_EXPR had erroneously returned 1
+
+
+v3.10 (2011-04-05)
+==================
+Fixes:
+- build: resolve autoconf-2.68 warnings
+- format: do not split arguments in %(lower) and %(upper)
+Changes:
+- defs: add array type checking in ARRAY_SIZE
+- opt: use non-zero sentinel marker
+- string: make HX_getl more resilient against errors
+Enhancements:
+- defs: add BUILD_BUG_ON_EXPR
+- format: provide a %(substr) function
+- io: add HX_readlink (zero-terminating mc-output readlink)
+- io: add HX_realpath (supports relative-path output)
+
+
+v3.9.1 (2011-01-17)
+===================
+Fixes:
+- libHX/io.h was not copied on `make install`, which has been fixed
+
+
+v3.9 (2011-01-15)
+=================
+Fixes:
+- Added missing __cplusplus guards to libHX/io.h
+- Added missing includes to libHX/string.h
+- Use __typeof__ in includes
+Changes:
+- For filesystem/filehandle-related functions, io.h should now be included
+ in userspace programs instead of misc.h
+- libHX.so is now built with a symvers map file
+Enhancements:
+- hxdirstamp: new development helper program for library users
+ (Note to distros: should be in libHX-devel; it is only used during builds)
+- io: new functions HXio_full{read,write}
+
+
+v3.8 (2010-12-01)
+=================
+This was supposed to go into 3.7 but I forgot to merge in time..
+Changes:
+- hexdump: colorize characters 0x00 thru 0x1F in tty mode
+
+
+v3.7 (2010-12-01)
+=================
+Changes:
+- libxml_helper: redo xml_newnode to take a parent and value string
+- list: unify naming of reverse-direction functions
+- misc: HX_zveclen now returns unsigned from (previous: int)
+- dir: HXdir functions now work with struct HXdir * instead of void *
+Fixes:
+- list: avoid potential shadow warning when using HXclist_{shift,pop}
+Enhancements:
+- doc: add doc/api.txt that lists the minimum required versions for symbols
+
+
+v3.6 (2010-08-16)
+=================
+Fixed:
+- bitmap: set/clear/test had no effect due to wrong type selection
+- bitmap: avoid left-shift larger than type on 64-bit
+- string: fixed buffer overflow in HX_split when too few fields were present
+ in the input
+
+
+v3.5 (2010-08-01)
+=================
+Fixed:
+- format2: failure to skip escaped char in "%(echo foo\ bar)" was corrected
+- proc: properly check for HXPROC_STDx--HXPROC_STDx_NULL overlap
+- strquote: do not cause allocation with invalid format numbers
+Enhancements:
+- format2: add the %(exec) function
+- format2: add the %(shell) function
+- format2: security feature for %(exec) and %(shell)
+- format2: add the %(snl) function
+- string: HX_strquote gained HXQUOTE_LDAPFLT (LDAP search filter) support
+- string: HX_strquote gained HXQUOTE_LDAPRDN (LDAP relative DN) support
+Changes:
+- format1: removed older formatter in favor of format2
+- format2: add check for empty key
+- format2: function-specific delimiters
+- format2: do nest-counting even with normal parentheses
+- format2: check for zero-argument function calls
+- hashmap: do not needlessy change TID when no reshape was done
+- string: HX_basename (the fast variant) now recognizes the root directory
+- string: HX_basename now returns the trailing component with slashes
+ instead of everything after the last slash (which may have been nothing)
+
+
+v3.4 (2010-04-03)
+=================
+Changes:
+- add explicit initialize/deinitialize functions HX_init, HX_exit
+Enhancements:
+- add the HX_memmem function
+- add the HXlist_empty function
+- documentation updates: HXlist traversal
+
+
+v3.3 (2010-01-20)
+=================
+Bug fixes:
+- format: fix incorrect copying of non-expanded % strings
+- proc: avoid calling close(-1) to not trip up valgrind
+- shconfig: fix incorrect parsing of "\'"
+- shconfig: fix incorrect processing of "\"\\\0BCD"
+- shconfig: be more strict with syntax
+Enhancements:
+- deque: add HXdeque_genocide2
+- format2: new format string (make-style) support
+- mc: add HXmc_zvecfree
+- shconfig: add HX_shconfig_map to return all entries of a shconfig file
+- rand: add HX_drand ('double'-type bounds and return value)
+- rand: avoid some function call overhead in HX_irand
+
+
+v3.2 (2009-10-11)
+=================
+Enhancements:
+- opt: add HXTYPE_MCSTR for storing into hxmc_t *s
+- string: add HX_strquote
+
+
+v3.1 (2009-09-13)
+=================
+Enhancements:
+- added HXbitmap_* functions
+Fixes:
+- mc: HXmc_strcpy produced a zero-length string when NULL was copied
+
+
+v3.0.1 (2009-08-31)
+===================
+Fixes:
+- map: avoid underflow in value-based tree comparison
+
+
+v3.0 (2009-08-27)
+=================
+Changes:
+- automatically skip building testcases if C++ compiler not available
+ (reminder: libHX itself does not require a C++ compiler)
+- arbtree: HXbtree was removed in favor of the new HXmap
+- clist: clist.h moved into list.h
+- format: HXformat_* now uses struct HXformat_map,
+ so that it does not tie itself to HXbtree
+- mc: fix an alignment-induced overallocation
+- rand: use faster modulo-based variant for numbers within RAND_MAX range
+- rand: use libc rand() almost exclusively, only use /dev/urandom for seed
+Enhancements:
+- defs: add HXsizeof_member and HXtypeof_member
+- map: new map API, with hash-based maps and classic rbtree-based maps
+- time: add time delta functions (HX_diff_timeval/HX_diff_timespec)
+Fixes:
+- format: memory leaks fixes in HXformat
+
+
+v2.9 (2009-07-11)
+=================
+Fixes:
+- string: fixed number of fields and trailing NULL in HX_split4
+Enhancements:
+- string: add HX_basename_exact
+
+
+v2.8 (2009-07-01)
+=================
+Enhancements:
+- HXproc now knows about HXPROC_NULL_*, which can be used to discard I/O
+- HXproc: expressly prohibit HXPROC_STD* for HXproc_run_sync
+
+
+v2.7 (2009-04-08)
+=================
+Fixes:
+- install missing wx_helper.hpp
+
+
+v2.6 (2009-03-28)
+=================
+Documentation:
+- install documentation
+- update project URLs
+- add section about Miscellaneous functions
+Changes:
+- arbtree: add "flat view" operation
+- misc: added HX_fls
+- misc: make HX_time_compare otime-capable
+- add wx_helper.hpp
+
+
+v2.5 (2009-02-11)
+=================
+Fixes:
+- proc: fix fd setup when the standard channels are already closed
+
+
+v2.4 (2009-02-05)
+=================
+Documentation updates. A few internal cleanups, nothing user-visible.
+
+
+v2.3 (2009-01-13)
+=================
+Fixes:
+- defs: only use __builtin_offsetof with GCC >= 4
+- misc: fix time_compare on FreeBSD to actually use mtimespec
+- mc: handle HXmc_length(NULL)
+- dir: do not cause directory traversal to restart after 2^32 entries
+
+
+v2.2 (2009-01-01)
+=================
+Fixes:
+- defs/cast: avoid warning between conversion from type[] to type *
+- defs/cast: add fallback defs for const_castN()
+- arbtree: correctly set errno (to ENOENT) in HXbtree_find and _get
+- string: document behavior details of HX_basename
+
+Changes:
+- removed old HX_vfsystem
+
+Enhancements:
+- defs: add HXSIZEOF_Z*
+- defs: add HX_STRINGIFY
+- proc: initial code
+- string: add HX_split4 function
+
+
+v2.1 (2008-12-23)
+=================
+- defs: fix bogus offsetof macro for non-GCC
+- defs: add a pair of guarding parentheses in static_cast()
+- doc: generate PDF file from LyX document
+
+
+v2.0 (2008-12-23)
+=================
+Fixes:
+- arbtree: reject illegal flag combinations
+- arbtree: correctly set errno in HXbtree_find and HXbtree_get
+- arbtree: do not return dangling pointer in HXbtree_del
+- defs: add a working offsetof() and containerof() for C++ mode
+- defs: use GCC's __builtin_offsetof
+- defs: resolve warnings with signed_cast() for char* -> const char* conversions
+- dir: HX_rrmdir: do not stop on error
+- opt: fix interpretation of strings during conversion to bool
+ (all strings that were not empty and not 0 were interpreted as "true",
+ and this included the strings "no", "off" and "false", which should
+ actually have mapped to, well, "false".)
+- rand: use autoconf to detect presence of unix functions
+- string: replace HX_strrev implementation by one that does not allocate
+
+
+New feature: Type-checking casts.
+- defs: enable type-checking signed_cast()
+- defs: add signed_cast<> for C++ mode
+- defs: rewrite static_cast() to not cause -Wshadow warnings when nested
+- defs: rewrite const_cast() to do type checking
+ (actually, const_cast1(), cosnt_cast2() and const_cast3() were introduced.
+ const_cast() is kept to not break program compilation.)
+
+
+New misc code:
+- ctype_helper: initial version
+- deque: add struct HXdeque_node->char *sptr as a typed variant for ptr
+- mc: add HXmc_setlen()
+- opt: HXTYPE_BOOL and HXTYPE_NONE now take int * (instead of unsigned int *)
+
+
+New arbtree code:
+- arbtree: add struct HXbtree_node->char *skey and char *sdata
+- arbtree: support arbitrary key/data duplication
+- arbtree: add HXbtree_init2
+
+
+Removals:
+- mc: remove HXmc_dup
+ [you can use HXmc_meminit(old, HXmc_length(old))]
+- string: HX_strmid behavior changed for length=0
+ [no more "remaining string", now returns a zero-length string]
+
+
+v1.28 (2008-11-18)
+==================
+- add HXTYPE_{U,}INT{8,16,32,64}
+- add includedir to cflags (libHX.pc)
+
+
+v1.27 (2008-12-23)
+==================
+No functional changes for Linux platforms.
+
+- build: fixed compile errors with i586-mingw32msvc cross compile
+- regenerated the Makefile.in files in the tarball with an updated
+ version of automake-tranquility so that they are now
+ POSIX-compliant and work with BSD make
+
+
+v1.26 (2008-10-12)
+==================
+- add HX_hexdump() for debugging within programs
+- fix double free in the error path of HX_getopt() when a long option preceded
+ a short option of which the latter had problems (i.e. missing argument)
+- add actual typechecking to signed_cast()
+- add typechecking to static_cast(),
+ (but this is normally disabled to avoid compile interruption)
+
+
+v1.25 (2008-09-07)
+==================
+- install missing misc.h
+- HXmc: pointer was not automatically updated after hmc_trunc()
+- HXmc: rename functions and put them into the HX* namespace (API change)
+- HXmc: make code resistant to memory allocation failure
+
+
+v1.23 (2008-09-02)
+==================
+- code cleanup: misc.h has been split off libHX.h
+- add defs.h
+
+
+v1.22 (2008-07-16)
+==================
+- need to use lstat() on directory operations such as mkdir and rrmdir
+- use RTLD_LAZY when opening dynamic libraries
+- add libxml_helper
+
+
+v1.18 (2008-06-10)
+==================
+- implement reverse iterating through HXlist
+- remove deprecated HXlist_init_head() and HXclist_init_head()
+ [replaced by HXlist_init() and HXclist_init()]
+- added HX_ffs()
+
+
+v1.17 (2008-05-08)
+==================
+- HXlist: added HXlist_for_each_safe, HXlist_for_each_entry_safe
+- HXclist: added HXclist_del
+
+
+v1.15 (2008-04-04)
+==================
+- HXformat: add %(ifempty) and %(ifnempty) tags
+- libHX.h: split into {arbtree,deque,option,string}.h (and libHX.h)
+- Add inline-doubly-linked-list data structures
+
+
+v1.10.2 (2007-12-06)
+====================
+- [r105]: pass up NULL from memory allocation error
+- [r108]: only return success on EEXIST when HXF_KEEP was given
+- [r112]: HX_dirname() incorrectly computed the path
+
+
+v1.10.1 (2007-09-17)
+====================
+- [r96]: Fix output of line-wrapped help text
+- tarball: in libHX 1.10.0 I forgot to provide the configure - sorry
+ (but you could regenerate it using ./autogen.sh if you have autotools)
diff --git a/doc/const_cast.c b/doc/const_cast.c
new file mode 100644
index 0000000..0a7c070
--- /dev/null
+++ b/doc/const_cast.c
@@ -0,0 +1,12 @@
+/*
+ Fails to compile with gcc-4.7, 4.8 with the error message
+ "const_cast.c:5:13: error: dereferencing pointer to incomplete type".
+ But __typeof__(*f) is just a fancy way of writing "struct undisclosed"
+ and should be permitted. (Request for enhancement)
+*/
+struct undisclosed;
+int main(void) {
+ const struct undisclosed *f = 0;
+ __typeof__(*f) *g = 0;
+ return 0;
+}
diff --git a/doc/dirstamp.txt b/doc/dirstamp.txt
new file mode 100644
index 0000000..92c1696
--- /dev/null
+++ b/doc/dirstamp.txt
@@ -0,0 +1,4 @@
+Improved dirstamp:
+
+dirstamp.lst:
+ [ ! -e $@ -o -n "$(find dir/ -newer $@ -print -quit)" ] && touch $@ || :;
diff --git a/doc/generate b/doc/generate
new file mode 100755
index 0000000..ed3b8aa
--- /dev/null
+++ b/doc/generate
@@ -0,0 +1,6 @@
+#!/bin/sh -ex
+
+if [ -z "$srcdir" ]; then
+ srcdir=".";
+fi;
+exec lyx -e pdf2 "$srcdir/libHX_Documentation.lyx";
diff --git a/doc/generator.cpp b/doc/generator.cpp
new file mode 100644
index 0000000..6c64f80
--- /dev/null
+++ b/doc/generator.cpp
@@ -0,0 +1,43 @@
+/*
+ * sample.
+ *
+ * Something more or less like Python generators.
+ */
+#include <cstdlib>
+#include <cstdio>
+template<class base> class fi /* filler_iterator */ {
+ private:
+ base &parent;
+ public:
+ fi(base &p) : parent(p) {};
+ bool operator!=(const fi &) { return parent.has_more(); };
+ const fi &operator++(void) { return *this; };
+ int operator*(void) { return parent.yield(); };
+};
+
+class rdgen {
+ private:
+ unsigned int remaining;
+
+ public:
+ rdgen(unsigned int x) {
+ remaining = x;
+ };
+ bool has_more(void) {
+ return remaining > 0;
+ };
+ int yield(void) {
+ --remaining;
+ return rand();
+ };
+
+ fi<rdgen> begin(void) { return fi<rdgen>(*this); };
+ fi<rdgen> end(void) { return fi<rdgen>(*this); };
+};
+
+int main(int argc, const char **argv)
+{
+ for (auto x : rdgen(argc))
+ printf("%d\n", x);
+ return 0;
+}
diff --git a/doc/libHX_Documentation.lyx b/doc/libHX_Documentation.lyx
new file mode 100644
index 0000000..69ad84c
--- /dev/null
+++ b/doc/libHX_Documentation.lyx
@@ -0,0 +1,24728 @@
+#LyX 2.0 created this file. For more info see http://www.lyx.org/
+\lyxformat 413
+\begin_document
+\begin_header
+\textclass article
+\use_default_options true
+\maintain_unincluded_children false
+\language english
+\language_package default
+\inputencoding utf8
+\fontencoding global
+\font_roman lmodern
+\font_sans lmss
+\font_typewriter lmtt
+\font_default_family default
+\use_non_tex_fonts false
+\font_sc false
+\font_osf false
+\font_sf_scale 100
+\font_tt_scale 100
+
+\graphics default
+\default_output_format default
+\output_sync 0
+\bibtex_command default
+\index_command default
+\paperfontsize 12
+\spacing single
+\use_hyperref true
+\pdf_bookmarks false
+\pdf_bookmarksnumbered false
+\pdf_bookmarksopen false
+\pdf_bookmarksopenlevel 1
+\pdf_breaklinks false
+\pdf_pdfborder true
+\pdf_colorlinks false
+\pdf_backref page
+\pdf_pdfusetitle true
+\papersize a4paper
+\use_geometry true
+\use_amsmath 1
+\use_esint 1
+\use_mhchem 1
+\use_mathdots 1
+\cite_engine natbib_numerical
+\use_bibtopic false
+\use_indices false
+\paperorientation portrait
+\suppress_date false
+\use_refstyle 0
+\index Index
+\shortcut idx
+\color #008000
+\end_index
+\leftmargin 2cm
+\topmargin 2cm
+\rightmargin 2cm
+\bottommargin 2cm
+\secnumdepth 3
+\tocdepth 1
+\paragraph_separation indent
+\paragraph_indentation default
+\quotes_language english
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+\tracking_changes false
+\output_changes false
+\html_math_output 0
+\html_css_as_file 0
+\html_be_strict false
+\end_header
+
+\begin_body
+
+\begin_layout Title
+libHX 3.22
+\begin_inset Newline newline
+\end_inset
+
+Documentation
+\end_layout
+
+\begin_layout Standard
+\begin_inset VSpace defskip
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset CommandInset toc
+LatexCommand tableofcontents
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Introduction
+\end_layout
+
+\begin_layout Standard
+libHX collects many useful day-to-day functions, intended to reduce the
+ amount of otherwise repeatedly open-coded instructions.
+\end_layout
+
+\begin_layout Section
+Overview
+\end_layout
+
+\begin_layout Itemize
+Maps (key-value pairs) (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:maps"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Originally created to provide a data structure like Perl's associative arrays.
+ Different map types and characteristics are available, such as hash-based
+ or the traditional rbtree.
+\end_layout
+
+\begin_layout Itemize
+Deques (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:deque"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Double-ended queues, implemented as a doubly-linked list with sentinels,
+ are suitable for both providing stack and queue functionality.
+\end_layout
+
+\begin_layout Itemize
+Inline doubly-linked list, uncounted and counted (sections
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:list"
+
+\end_inset
+
+ and
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:clist"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Light-weight linked lists as used in the Linux kernel.
+\end_layout
+
+\begin_layout Itemize
+Common string operations (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:strings"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+basename, chomp, dirname, getl(ine), split, strlcat/strlcpy, strlower/-upper,
+ str*trim, strsep, etc.
+\end_layout
+
+\begin_layout Itemize
+Memory containers, auto-sizing string operations (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:mc"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Scripting-like invocation for string handling
+\begin_inset space ~
+\end_inset
+
+--- automatically doing (re)allocations as needed.
+\end_layout
+
+\begin_layout Itemize
+String formatter (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:format"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+HXfmt is a small template system for by-name variable expansion.
+ It can be used to substitute placeholders in format strings supplied by
+ the user by appropriate expanded values defined by the program.
+\end_layout
+
+\begin_layout Itemize
+Directory creation, traversal, removal, and file copying (sections
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:dir-ops1"
+
+\end_inset
+
+,
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:dir-ops2"
+
+\end_inset
+
+ and
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:file-ops"
+
+\end_inset
+
+)
+\end_layout
+
+\begin_layout Itemize
+Option parsing (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:option"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Table-/callback-based option parser that works similar to Perl's
+\family typewriter
+Getopt::Long
+\family default
+
+\begin_inset space ~
+\end_inset
+
+--- no open-coding but a single
+\begin_inset Quotes eld
+\end_inset
+
+atomic
+\begin_inset Quotes erd
+\end_inset
+
+ invocation.
+\end_layout
+
+\begin_layout Itemize
+Shell-style config parser (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:shconf"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Configuration file reader for Shell-style
+\begin_inset Quotes eld
+\end_inset
+
+configuration
+\begin_inset Quotes erd
+\end_inset
+
+ files with key-value pairs, as usually foudn in
+\family typewriter
+/etc\SpecialChar \slash{}
+sysconfig
+\family default
+.
+\end_layout
+
+\begin_layout Itemize
+Random number gathering (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:random"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Convenient wrapper that uses kernel-provided RNG devices when available.
+\end_layout
+
+\begin_layout Itemize
+External process invocation (section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:proc"
+
+\end_inset
+
+)
+\begin_inset Newline newline
+\end_inset
+
+Setting up pipes for the standard file descriptors for sending/capturing
+ data to/from a program.
+\end_layout
+
+\begin_layout Itemize
+
+\shape italic
+a bit more beyond that ...
+ Miscellaneous
+\end_layout
+
+\begin_layout Section
+Resources
+\end_layout
+
+\begin_layout Standard
+As of this writing, the repository is located at
+\end_layout
+
+\begin_layout Itemize
+\begin_inset Flex URL
+status open
+
+\begin_layout Plain Layout
+
+git://libhx.git.sf.net/gitroot/libhx/libhx
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+--- clone URL
+\end_layout
+
+\begin_layout Itemize
+\begin_inset Flex URL
+status open
+
+\begin_layout Plain Layout
+
+http://libhx.git.sf.net/
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+--- gitweb interface
+\end_layout
+
+\begin_layout Itemize
+\begin_inset Flex URL
+status open
+
+\begin_layout Plain Layout
+
+http://libhx.sf.net/
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+--- home page (and link to tarballs)
+\end_layout
+
+\begin_layout Itemize
+\begin_inset Flex URL
+status open
+
+\begin_layout Plain Layout
+
+http://freecode.com/projects/libhx/
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+--- Freecode page (useful for automatic notification of new releases)
+\end_layout
+
+\begin_layout Section
+Installation
+\end_layout
+
+\begin_layout Standard
+libHX uses GNU autotools as a build environment, which means that all you
+ have to run as a end-user is the
+\family typewriter
+configure
+\family default
+ with any options that you need, plus the usual
+\family typewriter
+make
+\family default
+ and
+\family typewriter
+make install
+\family default
+ as desired.
+\end_layout
+
+\begin_layout Standard
+Pay attention to multi-lib Linux distributions where you most likely need
+ to specify a different libdir instead of using the default
+\begin_inset Quotes eld
+\end_inset
+
+lib
+\begin_inset Quotes erd
+\end_inset
+
+.
+ In case of the Debian-style multi-arch/multi-lib proposal (
+\begin_inset Flex URL
+status collapsed
+
+\begin_layout Plain Layout
+
+http://wiki.debian.org/Multiarch
+\end_layout
+
+\end_inset
+
+):
+\end_layout
+
+\begin_layout LyX-Code
+$
+\series bold
+./configure --libdir='${prefix}/lib/x86_64-linux-gnu'
+\end_layout
+
+\begin_layout Standard
+and the classic-style 32-64 2-lib distributions:
+\end_layout
+
+\begin_layout LyX-Code
+$
+\series bold
+./configure --libdir='${prefix}/lib64'
+\end_layout
+
+\begin_layout Subsection
+Requirements
+\end_layout
+
+\begin_layout Itemize
+GNU C Compiler 3.3.5 or newer.
+ Other compilers (non-GCC) have not been tested in months
+\begin_inset space ~
+\end_inset
+
+--- use at your own risk.
+\end_layout
+
+\begin_layout Itemize
+approximately 80--160
+\begin_inset space ~
+\end_inset
+
+KB of disk space on Linux for the shared library (depends on platform) and
+ header files.
+\end_layout
+
+\begin_layout Standard
+A C++ compiler is only needed if you want to build the C++ test programs
+ that come with libHX.
+ By default, if there is no C++ compiler present, these will not be built.
+\end_layout
+
+\begin_layout Itemize
+No external libraries are needed for compilation of libHX.
+ Helper files, like
+\family typewriter
+libxml_\SpecialChar \-
+helper.h
+\family default
+, may reference their include files, but they are not used during compilation.
+\end_layout
+
+\begin_layout Section
+Portability notice
+\end_layout
+
+\begin_layout Standard
+libHX runs on contemporary versions of Linux, Solaris and the three BSD
+ distributions.
+ It might even work on Microsoft Windows, but this is not tested very often,
+ if at all.
+ Overly old systems, especially Unices, are not within focus.
+ While AIX
+\begin_inset space ~
+\end_inset
+
+5.3 might still classify as contemporary, strangelets like
+\begin_inset Quotes eld
+\end_inset
+
+Ultrix
+\begin_inset Quotes erd
+\end_inset
+
+ or
+\begin_inset Quotes eld
+\end_inset
+
+Dynix
+\begin_inset Quotes erd
+\end_inset
+
+ you can find in the autotools-related file
+\family typewriter
+config.guess
+\family default
+ are some that are definitely not.
+\end_layout
+
+\begin_layout Standard
+Furthermore, a compiler that understands the C99 or GNU89 standard is required.
+ The integer type
+\begin_inset Quotes eld
+\end_inset
+
+int
+\begin_inset Quotes erd
+\end_inset
+
+ should at best have 32 bits at least.
+ There is no ultra-portable version as of this writing, but feel free to
+ start one akin to the
+\begin_inset Quotes eld
+\end_inset
+
+p
+\begin_inset Quotes erd
+\end_inset
+
+ variants of OpenBSD software such as OpenSSH.
+\end_layout
+
+\begin_layout Section
+History
+\end_layout
+
+\begin_layout Standard
+The origins of libHX trace back, even crossing a language boundary, to when
+ the author started on using Perl in 1999.
+ Some tasks were just too damn useful to be open-coded every time.
+ Two such examples are what is these days known as
+\family typewriter
+HX_basename
+\family default
+ and
+\family typewriter
+HX_mkdir
+\family default
+.
+ The name does not relate to anyone's initials; it is a result of a truncation
+ of the author's nick used years ago.
+\end_layout
+
+\begin_layout Standard
+Around the beginning of 2003, the author also started on the C programming
+ language and soon the small library was converted from Perl to C.
+ The libHX library as of today is the result of working with C ever since,
+ and naturally grew from there to support whatever the author was in need
+ of.
+\end_layout
+
+\begin_layout Standard
+The
+\begin_inset Quotes eld
+\end_inset
+
+correct
+\begin_inset Quotes erd
+\end_inset
+
+ name for libHX is with an uppercase
+\begin_inset Quotes eld
+\end_inset
+
+H
+\begin_inset Quotes erd
+\end_inset
+
+ and uppercase
+\begin_inset Quotes eld
+\end_inset
+
+X
+\begin_inset Quotes erd
+\end_inset
+
+, and the same is used for filenames, such as
+\begin_inset Quotes eld
+\end_inset
+
+libHX.so
+\begin_inset Quotes erd
+\end_inset
+
+
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+Software projects may choose to entirely lowercase the project name for
+ use in filenames, such as the Linux kernel which is released as
+\family typewriter
+linux-${
+\family default
+\shape italic
+version
+\family typewriter
+\shape default
+}.tar.bz2
+\family default
+, or the project may choose to keep the name for filenames, like Mesa and
+ SDL do.
+ libHX is of the latter.
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+General
+\end_layout
+
+\begin_layout Standard
+Many functions are prefixed with
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+HX_
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ or
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+HXsubsys_
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, as are structures (sometimes without underscores, be sure to check the
+ syntax and names), to avoid name clashes with possibly existing files.
+ Functions that are not tied to a specific data structure such as most of
+ the string functions (see chapter
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:strings"
+
+\end_inset
+
+) use the subsystem-less prefix,
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+HX_
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Functions from a clearly-defined subsystem, such as map or deque, augment
+ the base prefix by a suffix, forming e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+HXmap_
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Section
+Initialization
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/init.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_init(
+\series bold
+void
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HX_exit(
+\series bold
+void
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX_exit
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Before using the library's functions,
+\family typewriter
+HX_init
+\family default
+ must be called.
+ This function will initialize any needed state libHX needs for itself,
+ if any.
+ It is designed to be invoked multiple times, such as for example, from
+ different libraries linking to libHX itself, and will refcount.
+ On success, >0 is returned.
+ If there was an error, it will return a negative error code or zero.
+
+\family typewriter
+HX_exit
+\family default
+ is the logical counterpart of notifying that the library is no longer used.
+\end_layout
+
+\begin_layout Section
+Type-checking casts
+\end_layout
+
+\begin_layout Standard
+The C++ language provides so-called
+\begin_inset Quotes eld
+\end_inset
+
+new-style casts
+\begin_inset Quotes erd
+\end_inset
+
+, referring to the four template-looking invocations
+\family typewriter
+static_cast<>
+\family default
+,
+\family typewriter
+const_cast<>
+\family default
+,
+\family typewriter
+reinterpret_cast<>
+\family default
+ and
+\family typewriter
+dynamic_cast<>
+\family default
+.
+ No such blessing was given to the C language, but still, even using macros
+ that expand to the olde cast make it much easier to find casts in source
+ code and annotate why something was casted, which is already an improvement.
+\begin_inset space ~
+\end_inset
+
+--- Actually, it
+\shape italic
+is
+\shape default
+ possible to do a some type checking, using some GCC extensions, which augments
+ these macros from their documentary nature to an actual safety measure.
+\end_layout
+
+\begin_layout Subsection
+
+\family typewriter
+reinterpret_cast
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+reinterpret_cast
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+reinterpret_cast()
+\family default
+ maps directly to the old-style typecast,
+\family typewriter
+(type)(expr)
+\family default
+, and causes the bit pattern for the expr rvalue to be
+\begin_inset Quotes eld
+\end_inset
+
+reinterpreted
+\begin_inset Quotes erd
+\end_inset
+
+ as a new type.
+ You will notice that
+\begin_inset Quotes eld
+\end_inset
+
+reinterpret
+\begin_inset Quotes erd
+\end_inset
+
+ is the longest of all the
+\family typewriter
+*_cast
+\family default
+ names, and can easily cause your line to grow to 80 columns (the good maximum
+ in many style guides).
+ As a side effect, it is a good indicator that something potentially dangerous
+ might be going on, for example converting intergers from/to pointer.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/defs.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/defs.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+int
+\series default
+ i;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Tree with numeric keys
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+tree = HXhashmap_init(0);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+for
+\series default
+ (i = 0; i < 6; ++i)
+\begin_inset Newline newline
+\end_inset
+
+ HXmap_add(tree,
+\series bold
+reinterpret_cast
+\series default
+(
+\series bold
+void *
+\series default
+,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static_cast
+\series default
+(
+\series bold
+long
+\series default
+, i)), my_data);
+\end_layout
+
+\begin_layout Subsection
+
+\family typewriter
+signed_cast
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+signed_cast
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+This tag is for annotating that the cast was solely done to change the signednes
+s of pointers to char
+\begin_inset space ~
+\end_inset
+
+--- and only those.
+ No integers etc.
+ The intention is to facilitate working with libraries that use
+\family typewriter
+unsigned char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ pointers, such as libcrypto and libssl (from the OpenSSL project) or libxml2,
+ for example.
+ See table
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "tab:defs-signed_cast"
+
+\end_inset
+
+ for the allowed conversions.
+ C++ does
+\shape italic
+not
+\shape default
+ actually have a
+\family typewriter
+signed_cast<>
+\family default
+, and one would have to use
+\family typewriter
+reinterpret_cast<>
+\family default
+ to do the conversion, because
+\family typewriter
+static_cast<>
+\family default
+ does not allow conversion from
+\family typewriter
+const char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ to
+\family typewriter
+const unsigned char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+, for example.
+ (libHX's
+\family typewriter
+static_cast()
+\family default
+ would also throw at least a compiler warning about the different signedness.)
+ libHX does provide a
+\family typewriter
+signed_cast<>
+\family default
+ for C++ though.
+ This is where
+\family typewriter
+signed_cast
+\family default
+ comes in.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float table
+wide false
+sideways false
+status open
+
+\begin_layout Plain Layout
+\align center
+\begin_inset Tabular
+<lyxtabular version="3" rows="7" columns="7">
+<features tabularvalignment="middle">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+From
+\backslash
+ To
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+c*
+\series default
+section
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+sc*
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+uc*
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+Cc*
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+Csc*
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+Cuc*
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+signed char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+unsigned char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+const char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+const signed char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+const unsigned char *
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+--
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\checkmark$
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+\begin_inset CommandInset label
+LatexCommand label
+name "tab:defs-signed_cast"
+
+\end_inset
+
+Accepted conversions for
+\family typewriter
+signed_cast()
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsection
+
+\family typewriter
+static_cast
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:defs-static_cast"
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+static_cast
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Just like C++'s
+\family typewriter
+static_cast<>
+\family default
+, libHX's
+\family typewriter
+static_cast()
+\family default
+ verifies that
+\family typewriter
+expr
+\family default
+ can be implicitly converted to the new type (by a simple
+\family typewriter
+b
+\begin_inset space ~
+\end_inset
+
+=
+\begin_inset space ~
+\end_inset
+
+a
+\family default
+).
+ Such is mainly useful for forcing a specific type, as is needed in varargs
+ functions such as
+\family typewriter
+printf
+\family default
+, and where the conversion actually incurs other side effects, such as truncatio
+n or promotion:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Convert to a type printf knows about
+\family default
+\series bold
+\shape default
+ */
+\begin_inset Newline newline
+\end_inset
+
+uint64_t
+\series default
+ x = something;
+\begin_inset Newline newline
+\end_inset
+
+printf("%llu
+\backslash
+n",
+\series bold
+static_cast
+\series default
+(
+\series bold
+unsigned long long
+\series default
+, x));
+\end_layout
+
+\begin_layout Standard
+Because there is no format specifier for
+\family typewriter
+uint64_t
+\family default
+ for
+\family typewriter
+printf
+\family default
+, a conversion to an accepted type is necessary to not cause undefined behavior.
+ The author has seen code that did, for example,
+\family typewriter
+printf("%u")
+\family default
+ on a
+\begin_inset Quotes eld
+\end_inset
+
+long
+\begin_inset Quotes erd
+\end_inset
+
+, which only works on architectures where
+\family typewriter
+sizeof(unsigned int)
+\family default
+ happens to equal
+\family typewriter
+sizeof(unsigned long)
+\family default
+, such as x86_32.
+ On x86_64, an
+\family typewriter
+unsigned long
+\family default
+ is usually twice as big as an
+\family typewriter
+unsigned int
+\family default
+, so that 8 bytes are pushed onto the stack, but
+\family typewriter
+printf
+\family default
+ only unshifts 4 bytes because the developer used
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%u
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, leading to misreading the next variable on the stack.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Force promotion
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+double
+\series default
+ a_quarter =
+\series bold
+static_cast
+\series default
+(
+\series bold
+double
+\series default
+, 1) / 4;
+\end_layout
+
+\begin_layout Standard
+Were
+\begin_inset Quotes eld
+\end_inset
+
+1
+\begin_inset Quotes erd
+\end_inset
+
+ not promoted to double, the result in
+\family typewriter
+q
+\family default
+ would be zero because 1/4 is just an integer division, yielding zero.
+ By making one of the operands a floating-point quantity, the compiler will
+ instruct the FPU to compute the result.
+ Of course, one could have also written
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+1.0
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ instead of
+\family typewriter
+static_cast(double, 1)
+\family default
+, but this is left for the programmer to decide which style s/he prefers.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Force truncation before invoking second sqrt
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+double
+\series default
+ f = sqrt(
+\series bold
+static_cast
+\series default
+(
+\series bold
+int
+\series default
+, 10 * sqrt(3.0 / 4)));
+\end_layout
+
+\begin_layout Standard
+And here, the conversion from
+\family typewriter
+double
+\family default
+ to
+\family typewriter
+int
+\family default
+ incurs a (wanted) truncation of the decimal fraction, that is, rounding
+ down for positive numbers, and rounding up for negative numbers.
+\end_layout
+
+\begin_layout Subsubsection
+Allowed conversions
+\end_layout
+
+\begin_layout Itemize
+
+\series bold
+Numbers
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+Conversion between numeric types, such as
+\family typewriter
+char
+\family default
+,
+\family typewriter
+short
+\family default
+,
+\family typewriter
+int
+\family default
+,
+\family typewriter
+long
+\family default
+,
+\family typewriter
+long long
+\family default
+,
+\family typewriter
+int
+\shape italic
+N
+\shape default
+_t
+\family default
+, both their signed and unsigned variants,
+\family typewriter
+float
+\family default
+ and
+\family typewriter
+double
+\family default
+.
+\end_layout
+
+\begin_layout Itemize
+
+\series bold
+Generic Pointer
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+Conversion from
+\family typewriter
+type
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ to and from
+\family typewriter
+void
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+.
+ (Where
+\family typewriter
+type
+\family default
+ may very well be a type with further indirection.)
+\end_layout
+
+\begin_layout Itemize
+
+\series bold
+Generic Pointer (const)
+\begin_inset Newline newline
+\end_inset
+
+
+\series default
+Conversion from
+\family typewriter
+const type
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ to and from
+\family typewriter
+const void
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+
+\family typewriter
+const_cast
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+const_cast
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+const_cast
+\family default
+ allows to add or remove
+\begin_inset Quotes eld
+\end_inset
+
+const
+\begin_inset Quotes erd
+\end_inset
+
+ qualifiers from the type a pointer is pointing to.
+ Due to technical limitations, it could not be implemented to support arbitrary
+ indirection.
+ Instead,
+\family typewriter
+const_cast
+\family default
+ comes in three variants, to be used for indirection levels of 1 to 3:
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+\series bold
+const_cast
+\series default
+1(
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+*
+\series default
+, expr)
+\family default
+ with
+\family typewriter
+\series bold
+typeof
+\series default
+(expr)
+\begin_inset space ~
+\end_inset
+
+=
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+\series default
+.
+ (Similarly for any combinations of const.)
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+\series bold
+const_cast
+\series default
+2(
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+**
+\series default
+, expr) with
+\series bold
+typeof
+\series default
+(expr)
+\begin_inset space ~
+\end_inset
+
+=
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+**
+\family default
+\series default
+ (and all combinations of const in all possible locations).
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+\series bold
+const_cast
+\series default
+3(
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+***
+\series default
+, expr) with
+\series bold
+typeof
+\series default
+(expr)
+\begin_inset space ~
+\end_inset
+
+=
+\series bold
+type
+\begin_inset space ~
+\end_inset
+
+***
+\family default
+\series default
+ (and all combinations...).
+\end_layout
+
+\begin_layout Standard
+As indirection levels above 3 are really unlikely
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+See
+\begin_inset Quotes eld
+\end_inset
+
+Three Star Programmer
+\begin_inset Quotes erd
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+, having only these three type-checking cast macros was deemed sufficient.
+ The only place where libHX even uses a level\SpecialChar \nobreakdash-
+3 indirection is in the option
+ parser.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float table
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout Plain Layout
+\align center
+\begin_inset Tabular
+<lyxtabular version="3" rows="2" columns="2">
+<features tabularvalignment="middle">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int **
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int *const *
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+const int **
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+const int *const *
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Accepted expr/target types for
+\family typewriter
+const_cast2
+\family default
+; example for the
+\begin_inset Quotes eld
+\end_inset
+
+int
+\begin_inset Quotes erd
+\end_inset
+
+ type
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Plain Layout
+\align center
+Conversion is permitted when expression and target type are from the table.
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+It is currently not possible to use
+\family typewriter
+const_cast
+\family default
+1/2/3 on pointers to structures whose member structure is unknown.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Macros
+\end_layout
+
+\begin_layout Standard
+All macros in this section are available through
+\family typewriter
+#include <libHX/defs.h>
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/defs.h
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Subsection
+Preprocessor
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#define
+\series default
+ HX_STRINGIFY(s)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_STRINGIFY
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Transforms the expansion of the argument
+\family typewriter
+s
+\family default
+ into a C string.
+\end_layout
+
+\begin_layout Subsection
+Sizes
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#define
+\series default
+ HXSIZEOF_Z16
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXSIZEOF_Z16
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ HXSIZEOF_Z32
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXSIZEOF_Z32
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ HXSIZEOF_Z64
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXSIZEOF_Z64
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Expands to the size needed for a buffer (including '
+\family typewriter
+
+\backslash
+0
+\family default
+') to hold the base-10 string representation of a 16\SpecialChar \nobreakdash-
+, 32\SpecialChar \nobreakdash-
+ or 64\SpecialChar \nobreakdash-
+bit integer.
+\end_layout
+
+\begin_layout Subsection
+Locators
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+long
+\series default
+ offsetof(type, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+offsetof
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+output_type
+\series bold
+*
+\series default
+containerof(
+\series bold
+input_type *
+\series default
+ptr, output_type, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+containerof
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ FIELD_SIZEOF(struct_type, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+FIELD_SIZEOF
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+output_type HXtypeof_member(struct_type, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXtypeof_member
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+In case
+\family typewriter
+offsetof
+\family default
+ and
+\family typewriter
+containerof
+\family default
+ have not already defined by inclusion of another header file, libHX's defs.h
+ will define these accessors.
+
+\family typewriter
+offsetof
+\family default
+ is defined in
+\family typewriter
+stddef.h
+\family default
+ (for C) or
+\family typewriter
+cstddef
+\family default
+ (C++), but inclusion of these is not necessary if you have included
+\family typewriter
+defs.h
+\family default
+.
+
+\family typewriter
+defs.h
+\family default
+ will use GCC's
+\family typewriter
+__builtin_\SpecialChar \-
+offsetof
+\family default
+ if available, which does some extra sanity checks in C++ mode.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+offsetof
+\family default
+ calculates the offset of the specified member in the type, which needs
+ to be a struct or union.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+containerof
+\family default
+ will return a pointer to the struct in which
+\family typewriter
+ptr
+\family default
+ is contained as the given member.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ foo {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ bar;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ baz;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static void
+\series default
+ test(
+\series bold
+int *
+\series default
+ptr)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ foo
+\series bold
+*
+\series default
+self = containerof(baz,
+\series bold
+struct
+\series default
+ foo, baz);
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+FIELD_SIZEOF
+\family default
+ (formerly
+\family typewriter
+HXsizeof_member
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXsizeof_member
+\end_layout
+
+\end_inset
+
+) and
+\family typewriter
+HXtypeof_member
+\family default
+ are convenient shortcuts to get the size or type of a named member in a
+ given struct:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char
+\series default
+ padding[FIELD_SIZEOF(
+\series bold
+struct
+\series default
+ foo, baz)];
+\end_layout
+
+\begin_layout Subsection
+Array size
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+size_t
+\series default
+ ARRAY_SIZE(
+\series bold
+type
+\series default
+ array
+\series bold
+[]
+\series default
+);
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+implemented as a macro
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+ARRAY_SIZE
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Returns the number of elements in
+\family typewriter
+array
+\family default
+.
+ This only works with true arrays (
+\family typewriter
+type[]
+\family default
+), and will not output a meaningful value when used with a pointer-to-element
+ (
+\family typewriter
+type
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+), which is often used for array access too.
+\end_layout
+
+\begin_layout Subsection
+Compile-time build checks
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ BUILD_BUG_ON_EXPR(
+\series bold
+bool
+\series default
+ condition);
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+implemented as a macro
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+BUILD_BUG_ON_EXPR
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ BUILD_BUG_ON(
+\series bold
+bool
+\series default
+ condition);
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+implemented as a macro
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+BUILD_BUG_ON
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Causes the compiler to fail when
+\family typewriter
+condition
+\family default
+ evaluates to true.
+ If not implemented for a compiler, it will be a no-op.
+
+\family typewriter
+BUILD_BUG_ON
+\family default
+ is meant to be used as a standalone statement, while
+\family typewriter
+BUILD_\SpecialChar \-
+BUG_\SpecialChar \-
+ON_\SpecialChar \-
+EXPR
+\family default
+ is for when a check is to occur within an expression, that latter of which
+ is useful for within macros when one cannot, or does not want to use multiple
+ statements.
+\end_layout
+
+\begin_layout LyX-Code
+type DEMOTE_TO_PTR(type expr);
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+macro
+\family default
+\series bold
+\shape default
+ */
+\end_layout
+
+\begin_layout Standard
+Changes the type of expr to pointer type: If
+\family typewriter
+expr
+\family default
+ of array type class, changes it to a pointer to the first element.
+ If
+\family typewriter
+expr
+\family default
+ of function type class, changes it to a pointer to the function.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ main(
+\series bold
+void
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int (*
+\series default
+fp
+\series bold
+)
+\series default
+(
+\series bold
+void
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ a
+\series bold
+[
+\series default
+123
+\series bold
+]
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+DEMOTE_TO_PTR(main);
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+yields
+\series bold
+int (*)
+\series default
+(
+\series bold
+void
+\series default
+);
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+DEMOTE_TO_PTR(fp);
+\series bold
+/*
+\series default
+also yields
+\family roman
+\series bold
+\shape italic
+int (*)
+\series default
+(
+\series bold
+void
+\series default
+);
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+DEMOTE_TO_PTR(a);
+\series bold
+/*
+\series default
+yields
+\family roman
+\series bold
+\shape italic
+char *
+\family default
+\shape default
+ */
+\end_layout
+
+\begin_layout Subsection
+UNIX file modes
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#define
+\series default
+ S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+S_IRUGO
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+S_IWUGO
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+S_IXUGO
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ S_IRWXUGO (S_IRUGO | S_IWUGO | S_IXUGO)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+S_IRWXUGO
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The defines make it vastly easier to specify permissions for large group
+ of users.
+ For example, if one wanted to create a file with the permissions
+\family typewriter
+rw-r--r--
+\family default
+ (ignoring the umask in this description),
+\family typewriter
+S_IRUSR
+\begin_inset space ~
+\end_inset
+
+| S_IWUSR
+\family default
+ can now be used instead of the longer
+\family typewriter
+S_IRUSR
+\begin_inset space ~
+\end_inset
+
+| S_IWUSR
+\begin_inset space ~
+\end_inset
+
+| S_IRGRP
+\begin_inset space ~
+\end_inset
+
+| S_IROTH
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+VC runtime format specifiers
+\end_layout
+
+\begin_layout Standard
+The Microsoft Visual C runtime (a weak libc) uses non-standard format specifiers
+ for certain types.
+ Whereas C99 specifies
+\begin_inset Quotes eld
+\end_inset
+
+z
+\begin_inset Quotes erd
+\end_inset
+
+ for
+\family typewriter
+size_t
+\family default
+ and
+\begin_inset Quotes eld
+\end_inset
+
+ll
+\begin_inset Quotes erd
+\end_inset
+
+ for long long, MSVCRT users must use
+\begin_inset Quotes eld
+\end_inset
+
+I
+\begin_inset Quotes erd
+\end_inset
+
+ and
+\begin_inset Quotes eld
+\end_inset
+
+I64
+\begin_inset Quotes erd
+\end_inset
+
+ (forming
+\family typewriter
+%Id
+\family default
+ instead of
+\family typewriter
+%zd
+\family default
+ for
+\family typewriter
+ssize_t
+\family default
+, for example).
+ libHX provides two convenience macros for this:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#define
+\series default
+ HX_SIZET_FMT "z"
+\family roman
+\shape italic
+ or
+\family default
+\shape default
+"I"
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_SIZET_FMT
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#define
+\series default
+ HX_LONGLONG_FMT "ll"
+\family roman
+\shape italic
+ or
+\family default
+\shape default
+"I64"
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_LONGLONG_FMT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+These may be used together with printf or scanf:
+\end_layout
+
+\begin_layout LyX-Code
+printf("struct timespec is of size %" HX_SIZET_FMT "u
+\backslash
+n",
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+sizeof
+\series default
+(struct timespec));
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Miscellaneous functions
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/misc.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/misc.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_ffs(
+\series bold
+unsigned long
+\series default
+ z);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_ffs
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_fls(
+\series bold
+unsigned long
+\series default
+ z);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_fls
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HX_hexdump(
+\series bold
+FILE *
+\series default
+fp,
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+unsigned int
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_hexdump
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HX_zvecfree(
+\series bold
+char **
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_zvecfree
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ HX_zveclen(
+\series bold
+const char *const *
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_zveclen
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_ffs
+\family default
+ Finds the first (lowest-significant) bit in a value and returns its position,
+ or -1 to indicate failure.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_fls
+\family default
+ Finds the last (most-significant) bit in a value and returns its position,
+ or -1 to indicate failure.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_hexdump
+\family default
+ Outputs a nice pretty-printed hex and ASCII dump to the filedescriptor
+
+\family typewriter
+fp
+\family default
+.
+
+\family typewriter
+ptr
+\family default
+ is the memory area, of which
+\family typewriter
+len
+\family default
+ bytes will be dumped.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_zvecfree
+\family default
+ Frees the supplied Z-vector array.
+ (Frees all array elements from the first element to (excluding) the first
+
+\family typewriter
+NULL
+\family default
+ element.)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_zveclen
+\family default
+ Counts the number of array elements until the first
+\family typewriter
+NULL
+\family default
+ array element is seen, and returns this number.
+\end_layout
+
+\begin_layout Section
+Time functions
+\end_layout
+
+\begin_layout Standard
+Time in POSIX systems is represented in
+\family typewriter
+struct timespec
+\family default
+.
+ This structure is composed of two members: one integer for the number of
+ full seconds in the time value, and one integer for the number of nanoseconds
+ that remain when subtracting the full seconds from the time value.
+ POSIX leaves it unspecified how negative time is to be represented with
+ this structure, so I have devised an algebra for use with the same struct
+ that gives negative time support.
+\end_layout
+
+\begin_layout Standard
+Since integers often cannot store negative zero (due to e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+use of 2s complements in the language implementation), we will store the
+ minus sign in the nanosecond member if the integral second part is zero.
+ This gives us the property that we can test for negative time by looking
+ for whether at least one member of the structure is negative.
+ Also, we want to avoid storing the minus in both members to somewhat aid
+ the pretty-printing construct often seen,
+\end_layout
+
+\begin_layout LyX-Code
+printf("%ld.%09ld
+\backslash
+n", (long)ts.tv_sec, ts.tv_nsec);
+\end_layout
+
+\begin_layout Standard
+The number of combinations of a (non-zero) negative number, zero and a (non-zero
+) positive number is small, so we can actually just exhaustively list them
+ all.
+\end_layout
+
+\begin_layout Standard
+\noindent
+\align center
+\begin_inset Tabular
+<lyxtabular version="3" rows="4" columns="6">
+<features tabularvalignment="middle">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+Representation
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+Time value
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+R
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+T
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+R
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+T
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ -1,-1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+illegal
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 0,-1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+-0.1
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 1,-1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+illegal
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ -1,0\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+-1.0
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 0,0\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+0.0
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 1,0\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+1.0
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ -1,1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+-1.1
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 0,1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+0.1
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+\begin_inset Formula $\left\{ 1,1\right\} $
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+1.1
+\begin_inset space \thinspace{}
+\end_inset
+
+s
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The set of so-extended valid timespecs is therefore:
+\end_layout
+
+\begin_layout Standard
+\begin_inset Formula
+\[
+K=\left\{ \left(i,f\right):i,f\in\mathbb{Z}\wedge i\neq0\wedge0\leq f<10^{9}\right\} \cup\left\{ \left(i,f\right):i=0\wedge f\in\mathbb{Z}\wedge-10^{9}<f<10^{9}\right\}
+\]
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsection
+Function list
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/misc.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_timespec_isneg(
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_timespec_isneg
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+HX_timespec_neg(
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+result,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_timespec_neg
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+HX_timespec_add(
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+result,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p,
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+q);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_timespec_add
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+HX_timespec_sub(
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+delta,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p,
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+q);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_timespec_sub
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+HX_timespec_mul(
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+delta,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p,
+\series bold
+int
+\series default
+ f);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_timespec_mul
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+HX_timespec_mulf(
+\series bold
+struct
+\series default
+ timespec
+\series bold
+*
+\series default
+delta,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timespec
+\series bold
+*
+\series default
+p,
+\series bold
+double
+\series default
+ f);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_timespec_mulf
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ timeval
+\series bold
+*
+\series default
+HX_timeval_sub(
+\series bold
+struct
+\series default
+ timeval
+\series bold
+*
+\series default
+delta,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ timeval
+\series bold
+*
+\series default
+p,
+\series bold
+const struct
+\series default
+ timeval
+\series bold
+*
+\series default
+q);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_timeval_sub
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_time_compare(
+\series bold
+const struct
+\series default
+ stat
+\series bold
+*
+\series default
+a,
+\series bold
+const struct
+\series default
+ stat
+\series bold
+*
+\series default
+b,
+\series bold
+int
+\series default
+ mode);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_time_compare
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_isneg
+\family default
+ Determines whether a timespec structure represents (non-zero) negative
+ time.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_neg
+\family default
+ Computes the negation of the time specified by
+\family typewriter
+p
+\family default
+.
+
+\family typewriter
+result
+\family default
+ and
+\family typewriter
+p
+\family default
+ may point to the same structure.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_add
+\family default
+ Calculates the sum of the two times specified by
+\family typewriter
+p
+\family default
+ and
+\family typewriter
+q
+\family default
+, which are of type
+\family typewriter
+struct timespec
+\family default
+.
+ Any of
+\family typewriter
+result
+\family default
+,
+\family typewriter
+p
+\family default
+ and
+\family typewriter
+q
+\family default
+ may point to the same structure.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_sub
+\family default
+ Calculates the difference between the two timepoints p and q, which are
+ of type
+\family typewriter
+struct timespec
+\family default
+ (nanosecond granularity).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_mul
+\family default
+ Multiplies the time quantum in
+\family typewriter
+p
+\family default
+ by
+\family typewriter
+f
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timespec_mulf
+\family default
+ Multiplies the time quantum in
+\family typewriter
+p
+\family default
+ by
+\family typewriter
+f
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_timeval_sub
+\family default
+ Calculates the difference between the two timepoints p and q, which are
+ of type
+\family typewriter
+struct timeval
+\family default
+ (microsecnod granularity).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_time_compare
+\family default
+ Compares the timestamps from two
+\family typewriter
+struct stat
+\family default
+s.
+
+\family typewriter
+mode
+\family default
+ indicates which field is compared, which can either be
+\family typewriter
+'a'
+\family default
+ for the access time,
+\family typewriter
+'c'
+\family default
+ for the inode change time,
+\family typewriter
+'m'
+\family default
+ for the modification time, or
+\family typewriter
+'o'
+\family default
+ for the creation time (where available).
+ Returns a negative number if the time in
+\family typewriter
+a
+\family default
+ is less than
+\family typewriter
+b
+\family default
+, zero when they are equal, or a positive number greater than zero if
+\family typewriter
+a
+\family default
+ is greater than
+\family typewriter
+b
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+The macros
+\family typewriter
+HX_TIMESPEC_FMT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_TIMESPEC_FMT
+\end_layout
+
+\end_inset
+
+ and
+\family typewriter
+HX_TIMESPEC_EXP
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_TIMESPEC_EXP
+\end_layout
+
+\end_inset
+
+ can be used for passing and printing a
+\family typewriter
+struct timespec
+\family default
+ using the *
+\family typewriter
+printf
+\family default
+ function family:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ timespec p;
+\begin_inset Newline newline
+\end_inset
+
+clock_gettime(CLOCK_MONOTONIC, &p);
+\begin_inset Newline newline
+\end_inset
+
+printf("Now: " HX_TIMESPEC_FMT, HX_TIMESPEC_EXP(&p));
+\end_layout
+
+\begin_layout Standard
+Similarly,
+\family typewriter
+HX_TIMEVAL_FMT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_TIMEVAL_FMT
+\end_layout
+
+\end_inset
+
+ and
+\family typewriter
+HX_TIMEVAL_EXP
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_TIMEVAL_EXP
+\end_layout
+
+\end_inset
+
+ exist for the older
+\family typewriter
+struct timeval
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Bitmaps
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/misc.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ HXbitmap_size(
+\series bold
+type
+\series default
+ array,
+\series bold
+unsigned int
+\series default
+ bits);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXbitmap_size
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXbitmap_set(
+\series bold
+type *
+\series default
+bmap,
+\series bold
+unsigned int
+\series default
+ bit);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXbitmap_set
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXbitmap_clear(
+\series bold
+type *
+\series default
+bmap,
+\series bold
+unsigned int
+\series default
+ bit);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXbitmap_clear
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HXbitmap_test(
+\series bold
+type *
+\series default
+bmap,
+\series bold
+unsigned int
+\series default
+ bit);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXbitmap_test
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+All of these four are implemented as macros, so they can be used with any
+ integer type that is desired to be used.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXbitmap_size
+\family default
+ Returns the amount of
+\begin_inset Quotes eld
+\end_inset
+
+type
+\begin_inset Quotes erd
+\end_inset
+
+-based integers that would be needed to hold an array of the requested amount
+ of bits.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXbitmap_set
+\family default
+ Set the specific bit in the bitmap.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXbitmap_clear
+\family default
+ Clear the specific bit in this bitmap.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXbitmap_test
+\family default
+ Test for the specific bit and returns
+\family typewriter
+true
+\family default
+ if it is set, otherwise
+\family typewriter
+false
+\family default
+.
+\end_layout
+
+\begin_layout Subsubsection
+Example
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <stdlib.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/misc.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ main(
+\series bold
+void
+\series default
+)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned long
+\series default
+ bitmap
+\series bold
+[
+\series default
+HXbitmap_size(
+\series bold
+unsigned long
+\series default
+, 128)
+\series bold
+]
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ memset(bitmap, 0, sizeof(bitmap));
+\begin_inset Newline newline
+\end_inset
+
+ HXbitmap_set(bitmap, 49);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ HXbitmap_get(bitmap, HX_irand(0, 128)) ?
+\begin_inset Newline newline
+\end_inset
+
+ EXIT_SUCCESS : EXIT_FAILURE;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+Data structures
+\end_layout
+
+\begin_layout Section
+Maps
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:maps"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+A map is a collection of key-value pairs.
+ (Some languages, such as Perl, also call them
+\begin_inset Quotes eld
+\end_inset
+
+associative array
+\begin_inset Quotes erd
+\end_inset
+
+ or just
+\begin_inset Quotes eld
+\end_inset
+
+hash
+\begin_inset Quotes erd
+\end_inset
+
+, however, the underlying storage mechanism may not be an array or a hash,
+ however.) Each key is unique and has an associated value.
+ Keys can be any data desired; HXmap allows to specify your own key and
+ data handling functions so they can be strings, raw pointers, or complex
+ structures.
+\end_layout
+
+\begin_layout Standard
+To access any map-related functions,
+\family typewriter
+#include <libHX\SpecialChar \slash{}
+map.h>
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Structural definition
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:maps-def"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+HXmap
+\family default
+ structure is a near-opaque type.
+ Unlike the predecessor map implementation
+\family typewriter
+struct HXbtree
+\family default
+ from libHX 2.x, the 3.x API exposes much less fields.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXmap {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXmap
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ items, flags;
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+items
+\family default
+ The number of items in the tree.
+ This field tracks the number of items in the map and is used to report
+ the number of elements to the user, and is updated whenever an element
+ is inserted or removed from the map.
+ The field must not be changed by user.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+flags
+\family default
+ The current behavior flags for the map.
+ While implementation-private bits are exposed, only
+\family typewriter
+HXMAP_NOREPLACE
+\family default
+ is currently allowed to be (un)set by the developer while a map exists.
+\end_layout
+
+\begin_layout Standard
+For retrieving elements from a tree, some functions work with
+\family typewriter
+struct HXmap_node
+\family default
+, which is defined as follows:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXmap_node {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXmap_node
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+union
+\series default
+ {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+key;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *const
+\series default
+ skey;
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+union
+\series default
+ {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+data;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+sdata;
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+key
+\family default
+ The so-called primary key, which uniquely identifies an element (a key-value
+ pair) in the map.
+ The memory portions that make up the key must not be modified.
+ (If the key changes, so does its hash value and/or position index, and
+ without taking that into account, writing to the key directly is going
+ to end up with an inconsistent state.
+ To change the key, you will need to delete the element and reinsert it
+ with its new key.)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+skey
+\family default
+ A convenience type field for when the map's keys are C strings.
+ It is useful for use with e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+printf
+\family default
+ or other varargs function, which would otherwise require casting of the
+
+\family typewriter
+void
+\begin_inset space ~
+\end_inset
+
+*key
+\family default
+ member to
+\family typewriter
+const char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ first.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+data
+\family default
+ The data associated with the key.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+sdata
+\family default
+ Convenience type field.
+\end_layout
+
+\begin_layout Subsection
+Map initialization
+\end_layout
+
+\begin_layout Standard
+During initialization, you specify the underlying storage type by selecting
+ a given constructor function.
+ All further operations are done through the unified HXmap API which uses
+ a form of virtual calls internally.
+\end_layout
+
+\begin_layout Standard
+Currently, there are two distinct map types in libHX.
+ There are a handful of selectable symbols, though.
+ Abstract types are:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAPT_DEFAULT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAPT_DEFAULT
+\end_layout
+
+\end_inset
+
+ No further preferences or guarantees; selects any map type that the libHX
+ maintainer deemed fast.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAPT_ORDERED
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAPT_ORDERED
+\end_layout
+
+\end_inset
+
+ The map shall use a data structure that provides ordered traversal.
+\end_layout
+
+\begin_layout Standard
+Specific types include:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAPT_HASH
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_MAPT_HASH
+\end_layout
+
+\end_inset
+
+ Hash-based map
+\begin_inset space ~
+\end_inset
+
+-- Amortized
+\begin_inset Formula $\mathcal{O}\left(1\right)$
+\end_inset
+
+ insertion, lookup and deletion; unordered.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAPT_RBTREE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_MAPT_RBTREE
+\end_layout
+
+\end_inset
+
+ Red-black binary tree
+\begin_inset space ~
+\end_inset
+
+--
+\begin_inset Formula $\mathcal{O}\left(\log\left(n\right)\right)$
+\end_inset
+
+ insertion, lookup and deletion; ordered.
+\end_layout
+
+\begin_layout Standard
+These can then be used with the initialization functions:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+HXmap_init(
+\series bold
+unsigned int
+\series default
+ type,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+HXmap_init5(
+\series bold
+unsigned int
+\series default
+ type,
+\series bold
+unsigned int
+\series default
+ flags,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ HXmap_ops
+\series bold
+*
+\series default
+ops,
+\series bold
+size_t
+\series default
+ key_size,
+\series bold
+size_t
+\series default
+ data_size);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_init5
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Both the
+\family typewriter
+*_init
+\family default
+ and
+\family typewriter
+*_init5
+\family default
+ variant creates a new map; the latter function allows to specify the operations
+ in detail as well as key and data size, which may become necessary when
+ using data sets which have their own way of being managed.
+ The
+\family typewriter
+flags
+\family default
+ parameter can contain any of the following:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_NONE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_NONE
+\end_layout
+
+\end_inset
+
+ This is just a mnemonic for the value 0, indicating no flags.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_NOREPLACE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_NOREPLACE
+\end_layout
+
+\end_inset
+
+ If a key already exists and another add operation is attempted, the key's
+ associated value will be replaced by the new value.
+ If this flag is absent,
+\family typewriter
+-EEXIST
+\family default
+ is returned.
+ This flag is allowed to be subsequently changed by the developer if so
+ desired, using bit logic such as
+\family typewriter
+map->flags &= ~HXMAP_NOREPLACE;
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_SKEY
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SKEY
+\end_layout
+
+\end_inset
+
+ Notifies the constructor that keys will be C-style strings.
+ The flag presets the
+\family typewriter
+k_compare
+\family default
+ operation to use
+\family typewriter
+strcmp
+\family default
+.
+ In the flag's absence, direct value comparison will be used if the key
+ size is specified as zero (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+with the
+\family typewriter
+HXhashmap_\SpecialChar \-
+init4
+\family default
+ function call), or
+\family typewriter
+memcmp
+\family default
+ if the key size is non-zero.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_CKEY
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_CKEY
+\end_layout
+
+\end_inset
+
+ Instructs the map to make copies of keys when they are added to the map.
+ This is required when the buffer holding the key changes or goes out of
+ scope.
+ The flag presets the
+\family typewriter
+k_clone
+\family default
+ and
+\family typewriter
+k_free
+\family default
+ operations to
+\family typewriter
+HX_memdup
+\family default
+ and
+\family typewriter
+free
+\family default
+, and as such, the
+\family typewriter
+key_size
+\family default
+ parameter must not be zero.
+ If however,
+\family typewriter
+HXMAP_SKEY
+\family default
+ is also specified,
+\family typewriter
+HX_strdup
+\family default
+ and
+\family typewriter
+free
+\family default
+ will be used and
+\family typewriter
+key_size
+\family default
+ must be zero.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_SDATA
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SDATA
+\end_layout
+
+\end_inset
+
+ Notifies the constructor that data will be C-style strings.
+ This sets up the
+\family typewriter
+d_clone
+\family default
+ and
+\family typewriter
+d_free
+\family default
+ operations.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_CDATA
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_CDATA
+\end_layout
+
+\end_inset
+
+ Instructs the map to make copies of the data when new entries are added
+ to the map.
+ This is required when the buffer holding the data either goes out of scope,
+ or you want to keep the original contents instead of just a pointer.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_SCKEY
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SCKEY
+\end_layout
+
+\end_inset
+
+ Mnemonic for the combination of
+\family typewriter
+HXMAP_\SpecialChar \-
+SKEY
+\family default
+ OR'ed with
+\family typewriter
+HXMAP_\SpecialChar \-
+CKEY
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_SCDATA
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SCDATA
+\end_layout
+
+\end_inset
+
+ Mnemonic for the combination of
+\family typewriter
+HXMAP_\SpecialChar \-
+SDATA
+\family default
+ OR'ed with
+\family typewriter
+HXMAP_\SpecialChar \-
+SDATA
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_SINGULAR
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SINGULAR
+\end_layout
+
+\end_inset
+
+ Specifies that the
+\begin_inset Quotes eld
+\end_inset
+
+map
+\begin_inset Quotes erd
+\end_inset
+
+ is only used as a set, i.
+\begin_inset space \thinspace{}
+\end_inset
+
+e.
+\begin_inset space \space{}
+\end_inset
+
+it does not store any values, only keys.
+ Henceforth, the
+\family typewriter
+value
+\family default
+ argument to
+\family typewriter
+HXmap_add
+\family default
+ must always be
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Flag combinations
+\end_layout
+
+\begin_layout Standard
+This subsection highlights the way
+\family typewriter
+HXMAP_SKEY
+\family default
+ interacts with
+\family typewriter
+HXMAP_CKEY
+\family default
+ and the key size.
+ The copy semantics are the same for
+\family typewriter
+HXMAP_SDATA
+\family default
+ and
+\family typewriter
+HXMAP_CDATA
+\family default
+.
+\end_layout
+
+\begin_layout Subsubsection*
+
+\family typewriter
+HXMAP_SKEY
+\family default
+ is unset,
+\family typewriter
+HXMAP_CKEY
+\family default
+ is unset
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+key_size
+\family default
+ parameter at the time of map construction is ignored.
+ The pointer value of the
+\family typewriter
+key
+\family default
+ parameter for the
+\family typewriter
+HXmap_add
+\family default
+ call is directly stored in the tree, and this is the key that uniquely
+ identifies the map entry and which is used for comparisons.
+ This may be used if you intend to directly map pointer values.
+\end_layout
+
+\begin_layout LyX-Code
+static struct something *x = ..., *y = ...;
+\begin_inset Newline newline
+\end_inset
+
+HXmap_add(map, &x[0], "foo");
+\begin_inset Newline newline
+\end_inset
+
+HXmap_add(map, &x[1], "bar");
+\end_layout
+
+\begin_layout Subsubsection*
+
+\family typewriter
+HXMAP_SKEY
+\family default
+ is set,
+\family typewriter
+HXMAP_CKEY
+\family default
+ is unset
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+key_size
+\family default
+ parameter at the time of map construction is ignored.
+ The pointer value of the
+\family typewriter
+key
+\family default
+ parameter for the
+\family typewriter
+HXmap_add
+\family default
+ call is directly stored in the tree, but it is the C string
+\shape italic
+pointed to
+\shape default
+ by the
+\family typewriter
+key
+\family default
+ parameter that serves as the key.
+\end_layout
+
+\begin_layout Subsubsection*
+
+\family typewriter
+HXMAP_SKEY
+\family default
+ is set,
+\family typewriter
+HXMAP_CKEY
+\family default
+ is set
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+key_size
+\family default
+ parameter at the time of map construction is ignored.
+ The string pointed to by the key parameter will be duplicated, and the
+ resulting pointer will be stored in the tree.
+ Again, it is the pointed-to string that is the key.
+\end_layout
+
+\begin_layout Subsubsection*
+
+\family typewriter
+HXMAP_SKEY
+\family default
+ is unset,
+\family typewriter
+HXMAP_CKEY
+\family default
+ is set
+\end_layout
+
+\begin_layout Standard
+The memory block pointed to by the key parameter will be duplicated.
+ The
+\family typewriter
+key_size
+\family default
+ parameter must be non-zero for this to successfully work.
+\end_layout
+
+\begin_layout Subsubsection*
+With separate ops
+\end_layout
+
+\begin_layout Standard
+However, when a custom
+\family typewriter
+struct HXmap_ops
+\family default
+ is provided in the call to
+\family typewriter
+HXmap_init5
+\family default
+, any of these semantics can be overridden.
+ Particularly, since your own ops can practically ignore
+\family typewriter
+key_size
+\family default
+, it could be set to any value.
+\end_layout
+
+\begin_layout Subsection
+Key-data operations
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+HXMAP_SKEY
+\family default
+\SpecialChar \slash{}
+
+\family typewriter
+CKEY
+\family default
+\SpecialChar \slash{}
+
+\family typewriter
+SDATA
+\family default
+\SpecialChar \slash{}
+
+\family typewriter
+CDATA
+\family default
+ flags are generally sufficient to set up common maps where keys and/or
+ data are C strings or simple binary data where
+\family typewriter
+memdup
+\family default
+/
+\family typewriter
+memcmp
+\family default
+ is enough.
+ Where the provided mechanisms are not cutting it, an extra
+\family typewriter
+HXmap_ops
+\family default
+ structure with functions specialized in handling the keys and/or data has
+ to be used as an argument to the initialization function call.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXmap_ops {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXmap_ops
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int (*
+\series default
+k_compare
+\series bold
+)
+\series default
+(
+\series bold
+const void *
+\series default
+,
+\series bold
+const void *
+\series default
+,
+\series bold
+size_t
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *(*
+\series default
+k_clone
+\series bold
+)
+\series default
+(
+\series bold
+const void *
+\series default
+,
+\series bold
+size_t
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+k_free
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *(*
+\series default
+d_clone
+\series bold
+)
+\series default
+(
+\series bold
+const void *
+\series default
+,
+\series bold
+size_t
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+d_free
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned long (*
+\series default
+k_hash
+\series bold
+)
+\series default
+(
+\series bold
+const void *
+\series default
+,
+\series bold
+size_t
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+k_compare
+\family default
+ Function to compare two keys.
+ The return value is the same as that of
+\family typewriter
+memcmp
+\family default
+ or
+\family typewriter
+strcmp
+\family default
+: negative values indicate that the first key is
+\begin_inset Quotes eld
+\end_inset
+
+less than
+\begin_inset Quotes erd
+\end_inset
+
+ the second, zero indicates that both keys are equal, and positive values
+ indicate that the first key is
+\begin_inset Quotes eld
+\end_inset
+
+greater than
+\begin_inset Quotes erd
+\end_inset
+
+ the second.
+ The size argument in third position is provided so that
+\family typewriter
+memcmp
+\family default
+, which wants a size parameter, can directly be used without having to write
+ an own function.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+k_clone
+\family default
+ Function that will clone (duplicate) a key.
+ This is used for keys that will be added to the tree, and potentially also
+ for state-keeping during traversal of the map.
+ It is valid that this clone function simply returns the value of the pointer
+ it was actually passed; this is used by default for maps without
+\family typewriter
+HXMAP_CKEY
+\family default
+ for example.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+k_free
+\family default
+ Function to free a key.
+ In most cases it defaults to
+\family typewriter
+free
+\family default
+(3), but in case you are using complex structs, more cleanup may be needed.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+d_clone
+\family default
+ Same as
+\family typewriter
+k_clone
+\family default
+, but for data.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+d_free
+\family default
+ Same as
+\family typewriter
+k_free
+\family default
+, but for data.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+k_hash
+\family default
+ Specifies an alternate hash function.
+ Only to be used with hash-based maps.
+ Hashmaps default to using the DJB2 string hash function when
+\family typewriter
+HXMAP_SKEY
+\family default
+ is given, or otherwise the Jenkins' lookup3 hash function.
+\end_layout
+
+\begin_layout Standard
+libHX exports two hash functions that you can select for
+\family typewriter
+struct HXmap_ops
+\family default
+'s
+\family typewriter
+k_hash
+\family default
+ if the default for a given flag combination is not to your liking.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXhash_jlookup3
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXhash_jlookup3
+\end_layout
+
+\end_inset
+
+ Bob Jenkins's lookup3 hash.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXhash_djb2
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXhash_djb2
+\end_layout
+
+\end_inset
+
+ DJB2 string hash.
+\end_layout
+
+\begin_layout Subsection
+Map operations
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ HXmap_add(
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+,
+\series bold
+const void *
+\series default
+key,
+\series bold
+const void *
+\series default
+value);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_add
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ HXmap_node
+\series bold
+*
+\series default
+HXmap_find(
+\series bold
+const struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+,
+\series bold
+const void *
+\series default
+key);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_find
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXmap_get(
+\series bold
+const struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+,
+\series bold
+const void *
+\series default
+key);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_get
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXmap_del(
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+,
+\series bold
+const void *
+\series default
+key);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_del
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXmap_free(
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_free
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXmap_node
+\series bold
+*
+\series default
+HXmap_keysvalues(
+\series bold
+const struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_keysvalues
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_add
+\family default
+
+\family typewriter
+A
+\family default
+dds a new node to the tree using the given key and data.
+ When an element is in the map, the key may not be modified, as doing so
+ could possibly invalidate the internal location of the element, or its
+ ordering with respect to other elements.
+ If you need to change the key, you will have to delete the element from
+ the tree and re-insert it.
+ On error,
+\family typewriter
+-errno
+\family default
+ will be returned.
+\begin_inset Newline newline
+\end_inset
+
+When
+\family typewriter
+HXMAP_SINGULAR
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_SINGULAR
+\end_layout
+
+\end_inset
+
+ is in effect,
+\family typewriter
+value
+\family default
+ must be
+\family typewriter
+NULL
+\family default
+, or
+\family typewriter
+-EINVAL
+\family default
+ is returned.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_find
+\family default
+ Finds the node for the given key.
+ The key can be read from the node using
+\family typewriter
+node->key
+\family default
+ or
+\family typewriter
+node->skey
+\family default
+ (convenience alias for
+\family typewriter
+key
+\family default
+, but with a type of
+\family typewriter
+const char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+), and the data by using
+\family typewriter
+node->data
+\family default
+ or
+\family typewriter
+node->sdata
+\family default
+.
+ (see section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:maps-def"
+
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_get
+\family default
+ Get is a find operation directly returning
+\family typewriter
+node->data
+\family default
+ instead of the node itself.
+ Since
+\family typewriter
+HXmap_get
+\family default
+ may legitimately return
+\family typewriter
+NULL
+\family default
+ if
+\family typewriter
+NULL
+\family default
+ was stored in the tree as the data for a given key, only
+\family typewriter
+errno
+\family default
+ will really tell whether the node was found or not; in the latter case,
+
+\family typewriter
+errno
+\family default
+ is set to
+\family typewriter
+ENOENT
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_del
+\family default
+ Removes an element from the map and returns the data value that was associated
+ with it.
+ When an error occurred, or the element was not found,
+\family typewriter
+NULL
+\family default
+ is returned.
+ Because
+\family typewriter
+NULL
+\family default
+ can be a valid data value,
+\family typewriter
+errno
+\family default
+ can be checked for non-zero.
+
+\family typewriter
+errno
+\family default
+ will be
+\family typewriter
+-ENOENT
+\family default
+ if the element was not found, or zero when everything was ok.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_free
+\family default
+ The function will delete all elements in the map and free memory it holds.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_keysvalues
+\family default
+ Returns all key-value-pairs in an array of the size as many items were
+ in the map (
+\family typewriter
+map->items
+\family default
+) at the time it was called.
+ The memory must be freed using
+\family typewriter
+free
+\family default
+(3) when it is no longer needed.
+ The order elements in the array follows the traverser notes (see below),
+ unless otherwise specified.
+\end_layout
+
+\begin_layout Subsection
+Map traversal
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXmap_trav
+\series bold
+*
+\series default
+HXmap_travinit(
+\series bold
+const struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ HXmap_node
+\series bold
+*
+\series default
+HXmap_traverse(
+\series bold
+struct
+\series default
+ HXmap_trav
+\series bold
+*
+\series default
+iterator);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXmap_travfree(
+\series bold
+struct
+\series default
+ HXmap_trav
+\series bold
+*
+\series default
+iterator);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXmap_qfe(
+\series bold
+const struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+,
+\series bold
+bool (*
+\series default
+fn
+\series bold
+)
+\series default
+(
+\series bold
+const struct
+\series default
+ HXmap_node
+\series bold
+*
+\series default
+,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+arg),
+\series bold
+void *
+\series default
+arg);
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_travinit
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_travinit
+\end_layout
+
+\end_inset
+
+ Initializes a traverser (a.
+\begin_inset space \thinspace{}
+\end_inset
+
+k.
+\begin_inset space \thinspace{}
+\end_inset
+
+a.
+\begin_inset space \space{}
+\end_inset
+
+iterator) for the map, and returns a pointer to it.
+
+\family typewriter
+NULL
+\family default
+ will be returned in case of an error, such as memory allocation failure.
+ Traversers are returned even if the map has zero elements.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_traverse
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_traverse
+\end_layout
+
+\end_inset
+
+ Returns a pointer to a
+\family typewriter
+struct HXmap_node
+\family default
+ for the next element
+\begin_inset space ~
+\end_inset
+
+\SpecialChar \slash{}
+ key-value pair from the map, or
+\family typewriter
+NULL
+\family default
+ if there are no more entries.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_travfree
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_travfree
+\end_layout
+
+\end_inset
+
+ Release the memory associated with a traverser.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmap_qfe
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmap_qfe
+\end_layout
+
+\end_inset
+
+ The
+\begin_inset Quotes eld
+\end_inset
+
+quick foreach
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Iterates over all map elements in the fastest possible manner, but has
+ the restriction that no modifications to the map are allowed.
+ Furthermore, a separate function to handle each visited node, is required.
+ (Hence this is also called
+\begin_inset Quotes eld
+\end_inset
+
+closed traversal
+\begin_inset Quotes erd
+\end_inset
+
+, because one cannot access the stack frame of the original function which
+ called
+\family typewriter
+HXmap_qfe
+\family default
+.) The user-defined function returns a bool which indicates whether traversal
+ shall continue or not.
+\end_layout
+
+\begin_layout Standard
+Flags for
+\family typewriter
+HXmap_travinit
+\family default
+:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_NOFLAGS
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_NOFLAGS
+\end_layout
+
+\end_inset
+
+ A mnemonic for no flags, and is defined to be
+\family typewriter
+0
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXMAP_DTRAV
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXMAP_DTRAV
+\end_layout
+
+\end_inset
+
+ Enable support for deletion during traversal.
+ As it can make traversal slower, it needs to be explicitly specified for
+ cases where it is needed, to not penalize cases where it is not.
+\end_layout
+
+\begin_layout Standard
+WARNING: Modifying the map while a traverser is active is implementation-specifi
+c behavior! libHX generally ensures that there will be no undefined behavior
+ (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+crashes), but there is no guarantee that elements will be returned exactly
+ once.
+ There are fundamental cases that one should be aware of:
+\end_layout
+
+\begin_layout Itemize
+An element is inserted before where the traverser is currently positioned
+ at.
+ The element may not be returned in subsequent calls to
+\family typewriter
+HXmap_traverse
+\family default
+ on an already-active traverser.
+\end_layout
+
+\begin_layout Itemize
+Insertion or deletion may cause internal data structure to re-layout.
+\end_layout
+
+\begin_deeper
+\begin_layout Itemize
+Traversers of ordered data structures may choose to rebuild their state.
+\end_layout
+
+\begin_layout Itemize
+Traversers of unordered data structures would run risk to return more than
+ once, or not at all.
+\end_layout
+
+\end_deeper
+\begin_layout Standard
+Descriptions for different map types follow.
+\end_layout
+
+\begin_layout Description
+Hashmaps On
+\family typewriter
+HXmap_add
+\family default
+, an element may be inserted in a position that is before where the traverser
+ is currently positioned.
+ Such elements will not be returned in the remaining calls to
+\family typewriter
+HXmap_traverse
+\family default
+.
+ The insertion or deletion of an element may cause the internal data structure
+ to re-layout itself.
+ When this happens, the traverser will stop, so as to not return entries
+ twice.
+\end_layout
+
+\begin_layout Description
+Binary
+\begin_inset space ~
+\end_inset
+
+trees Elements may be added before the traverser's position.
+ These elements will not be returned in subsequent traversion calls.
+ If the data structure changes as a result of an addition or deletion, the
+ traverser will rebuild its state and continue traversal transparently.
+ Because elements in a binary tree are ordered, that is, element positions
+ may not change with respect to another when the tree is rebalanced, there
+ is no risk of returning entries more than once.
+ Nor will elements that are sorted after the current traverser's position
+ not be returned (=
+\begin_inset space ~
+\end_inset
+
+they will be returned, because they cannot get reordered to before the traverser
+ like in a hash map).
+ The HX rbtree implementation also has proper handling for when the node
+ which is currently visiting is deleted.
+\end_layout
+
+\begin_layout Subsection
+RB-tree Limitations
+\end_layout
+
+\begin_layout Standard
+The implementation has a theoretical minimum on the maximum number of nodes,
+
+\begin_inset Formula $2^{24}=16{,}777{,}216$
+\end_inset
+
+.
+ A worst-case tree with this many elements already has a height of 48 (
+\family typewriter
+RBT_MAXDEP
+\family default
+), which is the maximum height currently supported.
+ The larger the height is that HXrbtree is supposed to handle, the more
+ memory (linear increase) it needs.
+ All functions that build or keep a path reserve memory for
+\family typewriter
+RBT_MAXDEP
+\family default
+ nodes; on x86_64 this is 9 bytes per
+\begin_inset Formula $\langle$
+\end_inset
+
+node, direction
+\begin_inset Formula $\rangle$
+\end_inset
+
+ pair, amounting to 432 bytes for path tracking alone.
+ It may not sound like a lot to many, but given that kernel people can limit
+ their stack usage to 4096 bytes is impressive alone
+\end_layout
+
+\begin_layout Standard
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+Not always of course.
+ Linux kernels are often configured to use an 8K stack because some components
+ still use a lot of stack space, but even 8K is still damn good.
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout Subsubsection
+Case-insensitive ordering
+\end_layout
+
+\begin_layout Standard
+The correct way:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static int
+\series default
+ my_strcasecmp(
+\series bold
+const void *
+\series default
+a,
+\series bold
+const void *
+\series default
+b,
+\series bold
+size_t
+\series default
+ z)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ strcasecmp(a, b);
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXmap_ops icase = {
+\begin_inset Newline newline
+\end_inset
+
+ .k_compare = my_strcasecmp,
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0,
+\shape italic
+dsize
+\shape default
+);
+\end_layout
+
+\begin_layout Standard
+A hackish way (which wholly depends on the C implementation and use of extra
+ safeguards is a must):
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static const struct
+\series default
+ HXmap_ops icase = {
+\begin_inset Newline newline
+\end_inset
+
+ .k_compare = (
+\series bold
+void *
+\series default
+)strcasecmp,
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+BUILD_BUG_ON(
+\series bold
+sizeof
+\series default
+(DEMOTE_TO_PTR(strcasecmp)) >
+\series bold
+sizeof
+\series default
+(void *));
+\begin_inset Newline newline
+\end_inset
+
+BUILD_BUG_ON(
+\series bold
+sizeof
+\series default
+(DEMOTE_TO_PTR(strcasecmp)) >
+\series bold
+sizeof
+\series default
+(icase.k_compare));
+\begin_inset Newline newline
+\end_inset
+
+HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &icase, 0,
+\shape italic
+dsize
+\shape default
+);
+\end_layout
+
+\begin_layout Subsubsection
+Reverse sorting order
+\end_layout
+
+\begin_layout Standard
+Any function that behaves like
+\family typewriter
+strcmp
+\family default
+ can be used.
+ It merely has to return negative when
+\begin_inset Formula $a<b$
+\end_inset
+
+, zero on
+\begin_inset Formula $a=b$
+\end_inset
+
+, and positive non-zero when
+\begin_inset Formula $a>b$
+\end_inset
+
+.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static int
+\series default
+ strcmp_rev(
+\series bold
+const void *
+\series default
+a,
+\series bold
+const void *
+\series default
+b,
+\series bold
+size_t
+\series default
+ z)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+z is provided for cases when things are raw memory blocks.
+
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ strcmp(b, a);
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXmap_ops rev = {
+\begin_inset Newline newline
+\end_inset
+
+ .k_compare = strcmp_rev,
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+HXmap_init5(HXMAPT_RBTREE, HXMAP_SKEY, &rev, 0,
+\shape italic
+dsize
+\shape default
+);
+\end_layout
+
+\begin_layout Subsubsection
+Keys with non-unique data
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:maps-examples-bigkey"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Keys can actually store non-unique data, as long as this extra fields does
+ not actually contribute to the logical key
+\begin_inset space ~
+\end_inset
+
+--- the parts that do uniquely identify it.
+ In the following example, the
+\family typewriter
+notes
+\family default
+ member may be part of struct package, which is the key as far as HXmap
+ is concerned, but still, only the name and versions are used to identify
+ it.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ package {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+name;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ major_version;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ minor_version;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ notes
+\series bold
+[
+\series default
+64
+\series bold
+]
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static int
+\series default
+ package_cmp(
+\series bold
+const void *
+\series default
+a,
+\series bold
+const void *
+\series default
+b)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ package
+\series bold
+*
+\series default
+p = a,
+\series bold
+*
+\series default
+q = b;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ ret;
+\begin_inset Newline newline
+\end_inset
+
+ ret = strcmp(p->name, q->name);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (ret != 0)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ ret;
+\begin_inset Newline newline
+\end_inset
+
+ ret = p->major_version - q->major_version;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (ret != 0)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ ret;
+\begin_inset Newline newline
+\end_inset
+
+ ret = p->minor_version - q->minor_version;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (ret != 0)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ ret;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXmap_ops package_ops = {
+\begin_inset Newline newline
+\end_inset
+
+ .k_compare = package_cmp,
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXmap_init5(HXMAPT_RBTREE,
+\shape italic
+flags
+\shape default
+, &package_ops,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+sizeof
+\series default
+(
+\series bold
+struct
+\series default
+ package),
+\shape italic
+dsize
+\shape default
+);
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Doubly-linked list
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:deque"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+HXdeque is a data structure for a doubly-linked non-circular
+\family typewriter
+NULL
+\family default
+-sentineled list.
+ Despite being named a deque, which is short for double-ended queue, and
+ which may be implemented using an array, HXdeque is in fact using a linked
+ list to provide its deque functionality.
+ Furthermore, a dedicated root structure and decidated node structures with
+ indirect data referencing are used.
+\end_layout
+
+\begin_layout Subsection
+Structural definition
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/deque.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/deque.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXdeque
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+first,
+\series bold
+*
+\series default
+last;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ items;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+ptr;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque_node {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXdeque_node
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+next,
+\series bold
+*
+\series default
+prev;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+parent;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+ptr;
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+ptr
+\family default
+ member in
+\family typewriter
+struct HXdeque
+\family default
+ provides room for an arbitrary custom user-supplied pointer.
+
+\family typewriter
+items
+\family default
+ will reflect the number of elements in the list, and must not be modified.
+
+\family typewriter
+first
+\family default
+ and
+\family typewriter
+last
+\family default
+ provide entrypoints to the list's ends.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+ptr
+\family default
+ within
+\family typewriter
+struct HXdeque_node
+\family default
+ is the pointer to the user's data.
+ It may be modified and used at will by the user.
+ See example section
+\begin_inset space ~
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Subsection
+Constructor, destructors
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+HXdeque_init(
+\series bold
+void
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXdeque_free(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_free
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXdeque_genocide(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_genocide
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXdeque_genocide2(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+void (*
+\series default
+xfree
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+));
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_genocide2
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void **
+\series default
+HXdeque_to_vec(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+unsigned int *
+\series default
+num);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_to_vec
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+To allocate a new empty list, use
+\family typewriter
+HXdeque_init
+\family default
+.
+
+\family typewriter
+HXdeque_free
+\family default
+ will free the list (including all nodes owned by the list), but not the
+ data pointers.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_genocide
+\family default
+ is a variant that will not only destroy the list, but also calls a freeing
+ function
+\family typewriter
+free()
+\family default
+ on all stored data pointers.
+ This puts a number of restrictions on the characteristics of the list:
+ all data pointers must have been obtained with
+\family typewriter
+malloc
+\family default
+,
+\family typewriter
+calloc
+\family default
+ or
+\family typewriter
+realloc
+\family default
+ before, and no data pointer must exist twice in the list.
+ The function is more efficient than an open-coded loop over all nodes calling
+
+\family typewriter
+HXdeque_del
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+A generic variant is available with
+\family typewriter
+HXdeque_genocide2
+\family default
+, which takes a pointer to an appropriate freeing function.
+
+\family typewriter
+HXdeque_genocide
+\family default
+ is thus equivalent to
+\family typewriter
+HXdeque_genocide2(dq, free)
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+To convert a linked list to a
+\family typewriter
+NULL
+\family default
+-terminated array,
+\family typewriter
+HXdeque_to_vec
+\family default
+ can be used.
+ If
+\family typewriter
+num
+\family default
+ is not
+\family typewriter
+NULL
+\family default
+, the number of elements excluding the
+\family typewriter
+NULL
+\family default
+ sentinel, is stored in
+\family typewriter
+*num
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Addition and removal
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+HXdeque_push(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+void *
+\series default
+ptr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_push
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+HXdeque_unshift(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+void *
+\series default
+ptr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_unshift
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXdeque_pop(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_pop
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXdeque_shift(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_shift
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+HXdeque_move(
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+target,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+node);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_move
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXdeque_del(
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+node);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_del
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_\SpecialChar \-
+push
+\family default
+ and
+\family typewriter
+HXdeque_\SpecialChar \-
+unshift
+\family default
+ add the data item in a new node at the end (
+\begin_inset Quotes eld
+\end_inset
+
+push
+\begin_inset Quotes erd
+\end_inset
+
+) or as the new first element (
+\begin_inset Quotes eld
+\end_inset
+
+unshift
+\begin_inset Quotes erd
+\end_inset
+
+ as Perl calls it), respectively.
+ The functions will return the new node on success, or
+\family typewriter
+NULL
+\family default
+ on failure and
+\family typewriter
+errno
+\family default
+ will be set.
+ The node is owned by the list.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_\SpecialChar \-
+pop
+\family default
+ and
+\family typewriter
+HXdeque_\SpecialChar \-
+shift
+\family default
+ remove the last (
+\begin_inset Quotes eld
+\end_inset
+
+pop
+\begin_inset Quotes erd
+\end_inset
+
+) or first (
+\begin_inset Quotes eld
+\end_inset
+
+shift
+\begin_inset Quotes erd
+\end_inset
+
+) node, respectively, and return the data pointer that was stored in the
+ data.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_\SpecialChar \-
+move
+\family default
+ will unlink a node from its list, and reinsert it after the given target
+ node, which may be in a different list.
+\end_layout
+
+\begin_layout Standard
+Deleting a node is accomplished by calling
+\family typewriter
+HXdeque_del
+\family default
+ on it.
+ The data pointer stored in the node is not freed, but returned.
+\end_layout
+
+\begin_layout Subsection
+Iteration
+\end_layout
+
+\begin_layout Standard
+Iterating over a HXdeque linked list is done manually and without additional
+ overhead of function calls:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+const struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+node;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+for
+\series default
+ (node = dq->first; node != NULL; node = node->next)
+\begin_inset Newline newline
+\end_inset
+
+ do_something(node->ptr);
+\end_layout
+
+\begin_layout Subsection
+Searching
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXdeque_node
+\series bold
+*
+\series default
+HXdeque_find(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+const void *
+\series default
+ptr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_find
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HXdeque_get(
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq,
+\series bold
+void *
+\series default
+ptr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXdeque_get
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_find
+\family default
+ searches for the node which contains
+\family typewriter
+ptr
+\family default
+, and does so by beginning at the start of the list.
+ If no node is found,
+\family typewriter
+NULL
+\family default
+ is returned.
+ If a pointer is more than once in the list, any node may be returned.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdeque_get
+\family default
+ will further return the data pointer stored in the node
+\begin_inset space ~
+\end_inset
+
+--- however, since that is just what the
+\family typewriter
+ptr
+\family default
+ argument is, the function practically only checks for existence of
+\family typewriter
+ptr
+\family default
+ in the list.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout Standard
+
+\series bold
+\begin_inset Float figure
+placement h
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <stdlib.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/defs.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/deque.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <pwd.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+int
+\series default
+ main(
+\series bold
+void
+\series default
+)
+\begin_inset Newline newline
+\end_inset
+
+{
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series default
+
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq = HXdeque_init();
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ passwd *pw;
+\begin_inset Newline newline
+\end_inset
+
+
+\family typewriter
+\series bold
+unsigned int
+\series default
+ elem;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char **
+\series default
+users;
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ setpwent();
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ ((pw = getpwent()) != NULL)
+\begin_inset Newline newline
+\end_inset
+
+ HXdeque_push(dq, HX_strdup(pw->pw_name));
+\begin_inset Newline newline
+\end_inset
+
+ endpwent();
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ users =
+\series bold
+reinterpret_cast
+\series default
+(
+\series bold
+char **
+\series default
+, HXdeque_to_vec(dq, &elem));
+\begin_inset Newline newline
+\end_inset
+
+ HXdeque_free(dq);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ qsort(users, elem,
+\series bold
+sizeof
+\series default
+(*users),
+\series bold
+static_cast
+\series default
+(
+\series bold
+void *
+\series default
+, strcmp));
+\begin_inset Newline newline
+\end_inset
+
+ return 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Example use of HXdeque to store and sort a list
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+In this example, all usernames are obtained from NSS, and put into a list.
+
+\family typewriter
+HX_strdup
+\family default
+ is used, because
+\family typewriter
+getpwent
+\family default
+ will overwrite the buffer it uses to store its results.
+ The list is then converted to an array, and the list is freed (because
+ it is not need it anymore).
+
+\family typewriter
+HXdeque_genocide
+\family default
+ must not be used here, because it would free all the data pointers (strings
+ here) that were just inserted into the list.
+ Finally, the list is sorted using the well-known
+\family typewriter
+qsort
+\family default
+ function.
+ Because
+\family typewriter
+strcmp
+\family default
+ takes two
+\family typewriter
+const char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ arguments, but
+\family typewriter
+qsort
+\family default
+ mandates a function taking two
+\family typewriter
+const void
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+, a cast can be used to silence the compiler.
+ This only works because we know that the array consists of a bunch of
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ pointers, so
+\family typewriter
+strcmp
+\family default
+ will work.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Inline doubly-linked list
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:list"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Classical linked-list implementations, such as HXdeque, either store the
+ actual data within a node, or indirectly through a pointer, but the
+\begin_inset Quotes eld
+\end_inset
+
+inline doubly-linked list
+\begin_inset Quotes erd
+\end_inset
+
+ instead does it reverse and has the list head within the data structure.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement h
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ package_desc {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+package_name;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ version;
+\end_layout
+
+\begin_layout LyX-Code
+};
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ classic_direct_node {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ classic_direct_node
+\series bold
+*
+\series default
+next,
+\series bold
+*
+\series default
+prev;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ package_desc direct_data;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ classic_indirect_node {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ classic_indirect_node
+\series bold
+*
+\series default
+next,
+\series bold
+*
+\series default
+prev;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+indirect_data;
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Classic linked-list implementations with direct/indirect data blocks.
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ package_desc {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXlist_head list;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+package_name;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ version;
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+List head (next,prev pointers) inlined into the data block
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+At first glance, an inline list does not look much different from
+\family typewriter
+struct classic_\SpecialChar \-
+direct_\SpecialChar \-
+data
+\family default
+, it is mostly a viewpoint decision which struct is in the foreground.
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/list.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/list.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXlist_head {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXlist_head
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+All fields considered private
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXLIST_HEAD_INIT(name);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXLIST_HEAD_INIT
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXLIST_HEAD(name);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXLIST_HEAD
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXlist_init(
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+list);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXlist_add(
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+list,
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+elem);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_add
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXlist_add_tail(
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+list,
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+elem);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_add_tail
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXlist_del(
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+element);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_del
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HXlist_empty(
+\series bold
+const struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+list);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_empty
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXLIST_HEAD_INIT
+\family default
+ This macro expands to the static initializer for a list head.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXLIST_HEAD
+\family default
+ This macro expands to the definition of a list head (i.
+\begin_inset space \thinspace{}
+\end_inset
+
+e.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+struct HXlist_head name = HXLIST_HEAD_INIT;
+\family default
+)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_init
+\family default
+ Initializes the list head.
+ This function is generally used when the list head is on the heap where
+ the static initializer cannot be used.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_add
+\family default
+ Adds
+\family typewriter
+elem
+\family default
+ to the front of the list.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_add_tail
+\family default
+ Adds
+\family typewriter
+elem
+\family default
+ to the end of the list.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_del
+\family default
+ Deletes the given element from the list.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_empty
+\family default
+ Tests whether the list is empty.
+ Note: For clists, you could also use
+\family typewriter
+clist->items == 0
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Traversal
+\end_layout
+
+\begin_layout Standard
+Traversal is implemented using macros that expand to for() statements which
+ can syntactically be used like them, i.
+\begin_inset space \thinspace{}
+\end_inset
+
+e.
+\begin_inset space \space{}
+\end_inset
+
+curly braces may be omitted if only a single statement is in the body of
+ the loop.
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+head
+\family default
+ parameter specifies the list head (
+\family typewriter
+struct HXlist_head
+\family default
+),
+\family typewriter
+pos
+\family default
+ specifies an iterator, also of type
+\family typewriter
+struct HXlist_head
+\family default
+.
+ Lists can either be traversed in forward direction, or, using the
+\family typewriter
+_rev
+\family default
+ variants, in reverse direction.
+ The
+\family typewriter
+_safe
+\family default
+ variants use a temporary
+\family typewriter
+n
+\family default
+ to hold the next object in the list, which is needed when pos itself is
+ going to be inaccessible at the end of the block, through, for example,
+ freeing its encompassing object.
+\end_layout
+
+\begin_layout LyX-Code
+HXlist_for_each(pos, head)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_rev(pos, head)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_rev
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_safe(pos, n, head)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_safe
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_rev_safe(pos, n, head)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_rev_safe
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each
+\family default
+ Forward iteration over the list heads.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_rev
+\family default
+ Reverse iteration over the list heads.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_safe
+\family default
+ Forward iteration over the list heads that is safe against freeing
+\family typewriter
+pos
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_rev_safe
+\family default
+ Reverse iteration over the list heads that is safe against freeing
+\family typewriter
+pos
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+_entry
+\family default
+ variants use an iterator
+\family typewriter
+pos
+\family default
+ of the type of the encompassing object (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+struct item
+\family default
+ in below's example), so that the manual
+\family typewriter
+HXlist_entry
+\family default
+ invocation is not needed.
+
+\family typewriter
+member
+\family default
+ is the name of the list structure embedded into the item.
+\end_layout
+
+\begin_layout LyX-Code
+HXlist_for_each_entry(pos, head, member)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_entry
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_entry_rev(pos, head, member)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_entry_rev
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_entry_safe(pos, n, head, member)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXlist_for_each_entry_safe
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_entry
+\family default
+ Forward iteration over the list elements.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_entry_rev
+\family default
+ Reverse iteration over the list elements.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXlist_for_each_entry_safe
+\family default
+ Forward iteration over the list elements that is safe against freeing
+\family typewriter
+pos
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ item {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXlist_head anchor;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ name
+\series bold
+[
+\series default
+32
+\series bold
+]
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+e;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ item
+\series bold
+*
+\series default
+i,
+\series bold
+*
+\series default
+j;
+\begin_inset Newline newline
+\end_inset
+
+HXLIST_HEAD(list);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+i = malloc(
+\series bold
+sizeof
+\series default
+(
+\series bold
+*
+\series default
+i));
+\begin_inset Newline newline
+\end_inset
+
+HXlist_init(&e->anchor);
+\begin_inset Newline newline
+\end_inset
+
+strcpy(i->name, "foo");
+\begin_inset Newline newline
+\end_inset
+
+HXlist_add_tail(&list, &i->anchor);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+i = malloc(
+\series bold
+sizeof
+\series default
+(
+\series bold
+*
+\series default
+i));
+\begin_inset Newline newline
+\end_inset
+
+HXlist_init(&e->anchor);
+\begin_inset Newline newline
+\end_inset
+
+strcpy(i->name, "bar");
+\begin_inset Newline newline
+\end_inset
+
+HXlist_add_tail(&list, &i->anchor);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each(e, &list) {
+\begin_inset Newline newline
+\end_inset
+
+ i = HXlist_entry(e,
+\series bold
+typeof
+\series default
+(
+\series bold
+*
+\series default
+i), anchor);
+\begin_inset Newline newline
+\end_inset
+
+ printf("e=%p i=%p name=%s
+\backslash
+n", e, i, i->name);
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_entry(i, &list, anchor)
+\begin_inset Newline newline
+\end_inset
+
+ printf("i=%p name=%s
+\backslash
+n", i, i->name);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_entry_rev(i, &list, anchor)
+\begin_inset Newline newline
+\end_inset
+
+ printf("i=%p name=%s
+\backslash
+n", i, i->name);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXlist_for_each_entry_safe(i, j, &list, anchor) {
+\begin_inset Newline newline
+\end_inset
+
+ printf("i=%p name=%s
+\backslash
+n", i, i->name);
+\begin_inset Newline newline
+\end_inset
+
+ free(i);
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Subsection
+When to use HXdeque/HXlist
+\end_layout
+
+\begin_layout Standard
+The choice whether to use HXdeque or HXlist/HXclist depends on whether one
+ wants the list head handling on the developer or on the library.
+ Especially for
+\begin_inset Quotes eld
+\end_inset
+
+atomic
+\begin_inset Quotes erd
+\end_inset
+
+ and
+\begin_inset Quotes eld
+\end_inset
+
+small
+\begin_inset Quotes erd
+\end_inset
+
+ data, it might be easier to just let HXdeque do the management.
+ Compare the following two code examples to store strings:
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ main(
+\family typewriter
+\series bold
+int
+\series default
+ argc,
+\series bold
+const char **
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq = HXdeque_init();
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (--argc)
+\begin_inset Newline newline
+\end_inset
+
+ HXdeque_push(dq, ++argv);
+\begin_inset Newline newline
+\end_inset
+
+
+\family default
+\series bold
+return
+\family typewriter
+\series default
+ 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Storing strings in a HXdeque
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ element {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXlist_head list;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\family typewriter
+\series default
+data;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ main(
+\series bold
+int
+\series default
+ main,
+\series bold
+const char **
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+ HXLIST_HEAD(lh);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (--argc) {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ element
+\series bold
+*
+\series default
+e = malloc(
+\family default
+\series bold
+sizeof
+\family typewriter
+\series default
+(*e));
+\begin_inset Newline newline
+\end_inset
+
+ e->data = *++argv;
+\begin_inset Newline newline
+\end_inset
+
+ HXlist_init(&e->list);
+\begin_inset Newline newline
+\end_inset
+
+ HXlist_add_tail(&e->list);
+\begin_inset Newline newline
+\end_inset
+
+ }
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Storing strings in a HXlist
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+These examples assume that
+\family typewriter
+argv
+\family default
+ is persistent, which, for the sample, is true.
+\end_layout
+
+\begin_layout Standard
+With HXlist, one needs to have a struct with a HXlist_head in it, and if
+ one does not already have such a struct
+\begin_inset space ~
+\end_inset
+
+---e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+by means of wanting to store more than just one value
+\begin_inset space ~
+\end_inset
+
+--- one will need to create it first, as shown, and this may lead to an
+ expansion of code.
+\end_layout
+
+\begin_layout Standard
+This however does not mean that HXlist is the better solution over HXdeque
+ for data already available in a struct.
+ As each struct has a list_head that is unique to the node, it is not possible
+ to share this data.
+ Trying to add a HXlist_head to another list is not going to end well, while
+ HXdeque has no problem with this as list heads are detached from the actual
+ data in HXdeque.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ point p = {15, 30};
+\begin_inset Newline newline
+\end_inset
+
+HXdeque_push(dq, &p);
+\begin_inset Newline newline
+\end_inset
+
+HXdeque_push(dq, &p);
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Data can be added multiple times in a HXdeque without ill effects
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+To support this, an extra allocation is needed on the other hand.
+ In a HXlist, to store
+\begin_inset Formula $n$
+\end_inset
+
+ elements of compound data (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+struct point
+\family default
+),
+\begin_inset Formula $n$
+\end_inset
+
+ allocations are needed, assuming the list head is a stack object, and the
+ points are not.
+ HXdeque will need at least
+\begin_inset Formula $2n+1$
+\end_inset
+
+ allocations,
+\begin_inset Formula $n$
+\end_inset
+
+ for the nodes,
+\begin_inset Formula $n$
+\end_inset
+
+ for the points and another for the head.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Counted inline doubly-linked list
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:clist"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+clist is the inline doubly-linked list from chapter
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sec:list"
+
+\end_inset
+
+, extended by a counter to retrieve the number of elements in the list in
+
+\begin_inset Formula $\mathcal{O}\left(1\right)$
+\end_inset
+
+ time.
+ This is also why all operations always require the list head.
+ For traversal of clists, use the corresponding HXlist macros.
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/list.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/list.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXclist_head {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXclist_head
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+public readonly:
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ items;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Undocumented fields are considered
+\begin_inset Quotes eld
+\end_inset
+
+private
+\begin_inset Quotes erd
+\end_inset
+
+
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXCLIST_HEAD_INIT(name);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXCLIST_HEAD_INIT
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+HXCLIST_HEAD(name);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXCLIST_HEAD
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXclist_init(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXclist_unshift(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head,
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+new_node);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_unshift
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXclist_push(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head,
+\series bold
+struct
+\series default
+ HXlist_head
+\series bold
+*
+\series default
+new_node);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_push
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+type
+\series default
+ HXclist_pop(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head,
+\series bold
+type
+\series default
+, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_pop
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+type
+\series default
+ HXclist_shift(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head,
+\series bold
+type
+\series default
+, member);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_shift
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXclist_del(
+\series bold
+struct
+\series default
+ HXclist_head
+\series bold
+*
+\series default
+head,
+\series bold
+struct
+\series default
+HXlist_chead
+\series bold
+*
+\series default
+node);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXclist_del
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXCLIST_HEAD_INIT
+\family default
+ Macro that expands to the static initializer for a clist.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXCLIST_HEAD
+\family default
+ Macro that expands to the definition of a clist head, with initialization.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_init
+\family default
+ Initializes a clist.
+ This function is generally used when the head has been allocated from the
+ heap.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_unshift
+\family default
+ Adds the node to the front of the list.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_push
+\family default
+ Adds the node to the end of the list.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_pop
+\family default
+ Removes the last node in the list and returns it.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_shift
+\family default
+ Removes the first node in the list and returns it.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXclist_del
+\family default
+ Deletes the node from the list.
+\end_layout
+
+\begin_layout Standard
+The list count in the clist head is updated whenever a modification is done
+ on the clist through these functions.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+Strings and memory
+\end_layout
+
+\begin_layout Section
+String operations
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:strings"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Some string functions are merely present in libHX because they are otherwise
+ unportable; some are only in the C libraries of the BSDs, some only in
+ GNU libc.
+\end_layout
+
+\begin_layout Subsection
+Locating chars
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HX_memmem(
+\series bold
+const void *
+\series default
+haystack,
+\series bold
+size_t
+\series default
+ hsize,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const void *
+\series default
+needle,
+\series bold
+size_t
+\series default
+ nsize);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_memmem
+\end_layout
+
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+char *
+\series default
+HX_strbchr(
+\series bold
+const char *
+\series default
+start,
+\series bold
+const char *
+\series default
+now,
+\series bold
+char
+\series default
+ delimiter);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_strbchr
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strchr2(
+\series bold
+const char *
+\series default
+s,
+\series bold
+const char *
+\series default
+accept);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_strchr2
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ HX_strrcspn(
+\series bold
+const char *
+\series default
+s,
+\series bold
+const char *
+\series default
+reject);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_strccspn
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_memmem
+\family default
+ Analogous to
+\family typewriter
+strstr
+\family default
+(3),
+\family typewriter
+memmem
+\family default
+ tries to locate the memory block pointed to by
+\family typewriter
+needle
+\family default
+ (which is of length
+\family typewriter
+nsize
+\family default
+) in the block pointed to by
+\family typewriter
+haystack
+\family default
+ (which is of size
+\family typewriter
+hsize
+\family default
+).
+ It returns a pointer to the first occurrence in
+\family typewriter
+haystack
+\family default
+, or
+\family typewriter
+NULL
+\family default
+ when it was not found.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strbchr
+\family default
+ Searches the character specified by
+\family typewriter
+delimiter
+\family default
+ in the range from
+\family typewriter
+now
+\family default
+ to
+\family typewriter
+start
+\family default
+.
+ It works like
+\family typewriter
+strrchr
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strrchr
+\end_layout
+
+\end_inset
+
+, but begins at
+\family typewriter
+now
+\family default
+ rather than the end of the string.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strchr2
+\family default
+ This function searches the string
+\family typewriter
+s
+\family default
+ for any set of bytes that are not specified in the second argument,
+\family typewriter
+n
+\family default
+.
+ In this regard, the function is the opposite to
+\family typewriter
+strpbrk
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strpbrk
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strrcspn
+\family default
+ Works like
+\family typewriter
+strcspn
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+strcspn
+\end_layout
+
+\end_inset
+
+, but processes the string from end to start.
+\end_layout
+
+\begin_layout Subsection
+Extraction
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_basename(
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_basename
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_basename_exact(
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_basename_exact
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_dirname(
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_dirname
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strmid(
+\series bold
+const char *
+\series default
+s,
+\series bold
+long
+\series default
+ offset,
+\series bold
+long
+\series default
+ length);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strmid
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_basename
+\family default
+ Returns a pointer to the basename portion of the supplied path
+\family typewriter
+s
+\family default
+.
+ The result of this function is never
+\family typewriter
+NULL
+\family default
+, and must never be freed either.
+ Trailing slashes are not stripped, to avoid having to do an allocation.
+ In other words,
+\family typewriter
+basename("/mnt/")
+\family default
+ will return
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+mnt/
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ If you need to have the slashes stripped, use
+\family typewriter
+HX_basename_exact
+\family default
+.
+ A possible use for this function is, for example, to derive a logging prefix
+ from
+\family typewriter
+argv[0]
+\family default
+.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ main(
+\series bold
+int
+\series default
+ argc,
+\series bold
+const char **
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (foo())
+\end_layout
+
+\begin_layout LyX-Code
+ fprintf(stderr, "%s: Special condition occurred.
+\backslash
+n",
+\begin_inset Newline newline
+\end_inset
+
+ HX_basename(argv[0]));
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_basename_exact
+\family default
+ The accurate and safe version of
+\family typewriter
+HX_basename
+\family default
+ that deals with trailing slashes correctly and produces the same result
+ as
+\family typewriter
+dirname
+\family default
+(3).
+ It returns a pointer to a newly-allocated string that must be freed when
+ done using.
+
+\family typewriter
+NULL
+\family default
+ may be returned in case of an allocation error.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_dirname
+\family default
+ Returns a pointer to a new string that contains the directory name portion
+ (everything except basename).
+ When done using the string, it must be freed to avoid memory leaks.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strmid
+\family default
+ Extract a substring of
+\family typewriter
+length
+\family default
+ characters from
+\family typewriter
+s
+\family default
+, beginning at
+\family typewriter
+offset
+\family default
+.
+ If
+\family typewriter
+offset
+\family default
+ is negative, counting beings from the end of the string;
+\begin_inset Formula $-1$
+\end_inset
+
+ is the last character (not the
+\family typewriter
+'
+\backslash
+0'
+\family default
+ byte).
+ If
+\family typewriter
+length
+\family default
+ is negative, it will leave out that many characters off the end.
+ The function returns a pointer to a new string, and the user has to free
+ it.
+\end_layout
+
+\begin_layout Subsection
+In-place transformations
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_chomp(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_chomp
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ HX_strltrim(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strltrim
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_stpltrim(
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_stpltrim
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strlower(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strlower
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strrev(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strrev
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ HX_strrtrim(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strrtrim
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strupper(
+\series bold
+char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strupper
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_chomp
+\family default
+ Removes the characters
+\family typewriter
+'
+\backslash
+r'
+\family default
+ and
+\family typewriter
+'
+\backslash
+n'
+\family default
+ from the right edge of the string.
+ Returns the original argument.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strltrim
+\family default
+ Trim all whitespace (characters on which
+\family typewriter
+isspace
+\family default
+(3) return true) on the left edge of the string.
+ Returns the number of characters that were stripped.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_stpltrim
+\family default
+ Returns a pointer to the first non-whitespace character in
+\family typewriter
+s
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strlower
+\family default
+ Transforms all characters in the string
+\family typewriter
+s
+\family default
+ into lowercase using
+\family typewriter
+tolower
+\family default
+(3).
+ Returns the original argument.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strrev
+\family default
+ Reverse the string in-place.
+ Returns the original argument.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strrtrim
+\family default
+ Trim all whitespace on the right edge of the string.
+ Returns the number of characters that were stripped.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strupper
+\family default
+ Transforms all characters in the string
+\family typewriter
+s
+\family default
+ into uppercase using
+\family typewriter
+toupper
+\family default
+(3).
+ Returns the original argument.
+\end_layout
+
+\begin_layout Subsection
+Out-of-place quoting transforms
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strquote(
+\series bold
+const char *
+\series default
+s,
+\series bold
+unsigned int
+\series default
+ type,
+\series bold
+char **
+\series default
+free_me);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_strquote
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_strquote
+\family default
+ will escape metacharacters in a string according to
+\family typewriter
+type
+\family default
+, and returns the escaped result.
+\end_layout
+
+\begin_layout Standard
+Possible values for
+\family typewriter
+type
+\family default
+:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_SQUOTE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_SQUOTE
+\end_layout
+
+\end_inset
+
+ Escape all single quotes and backslashes in a string with a backslash.
+ (
+\begin_inset Quotes eld
+\end_inset
+
+Ol'
+\backslash
+Backslash
+\begin_inset Quotes erd
+\end_inset
+
+
+\begin_inset Formula $\rightarrow$
+\end_inset
+
+
+\begin_inset Quotes eld
+\end_inset
+
+Ol
+\backslash
+'
+\backslash
+
+\backslash
+Backslash
+\begin_inset Quotes erd
+\end_inset
+
+)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_DQUOTE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_DQUOTE
+\end_layout
+
+\end_inset
+
+ Escape all double quotes and backslahes in a string with the backslash
+ method.
+ (
+\begin_inset Quotes eld
+\end_inset
+
+Ol
+\begin_inset Quotes erd
+\end_inset
+
+
+\backslash
+Backslash
+\begin_inset Quotes erd
+\end_inset
+
+
+\begin_inset Formula $\rightarrow$
+\end_inset
+
+
+\begin_inset Quotes eld
+\end_inset
+
+Ol
+\backslash
+
+\begin_inset Quotes erd
+\end_inset
+
+
+\backslash
+
+\backslash
+Backslash
+\begin_inset Quotes erd
+\end_inset
+
+)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_HTML
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_HTML
+\end_layout
+
+\end_inset
+
+ Escape '
+\family typewriter
+<
+\family default
+', '
+\family typewriter
+>
+\family default
+', '
+\family typewriter
+&
+\family default
+' and '
+\family typewriter
+"
+\family default
+' by their respective HTML entities
+\family typewriter
+&lt;
+\family default
+,
+\family typewriter
+&gt;
+\family default
+,
+\family typewriter
+&amp;
+\family default
+ and
+\family typewriter
+&quot;
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_LDAPFLT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_LDAPFLT
+\end_layout
+
+\end_inset
+
+ Escape the string using backslash-plus-hexcode notation as described in
+ RFC 4515
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+\begin_inset Flex URL
+status collapsed
+
+\begin_layout Plain Layout
+
+http://tools.ietf.org/html/rfc4515
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+, to make it suitable for use in an LDAP search filter.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_LDAPRDN
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_LDAPRDN
+\end_layout
+
+\end_inset
+
+ Escape the string using backslash-plus-hexcode notation as described in
+ RFC 4514
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+\begin_inset Flex URL
+status collapsed
+
+\begin_layout Plain Layout
+
+http://tools.ietf.org/html/rfc4514
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+, to make it suitable for use in an LDAP Relative Distinguished Name.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_BASE64
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_BASE64
+\end_layout
+
+\end_inset
+
+ Transform the string to BASE64, as described in RFC 4648
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+\begin_inset Flex URL
+status collapsed
+
+\begin_layout Plain Layout
+
+http://tools.ietf.org/html/rfc4648
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_URIENC
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_URIENC
+\end_layout
+
+\end_inset
+
+ Escape the string so that it becomes a valid part for an URI.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_SQLSQUOTE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_SQLSQUOTE
+\end_layout
+
+\end_inset
+
+ Escape all single quotes in the string by double single-quotes, as required
+ for using it in a single-quoted SQL string.
+ No surrounding quotes will be generated to facilitate concatenating of
+
+\family typewriter
+HX_strquote
+\family default
+ results.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXQUOTE_SQLBQUOTE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXQUOTE_SQLBQUOTE
+\end_layout
+
+\end_inset
+
+ Escape all backticks in the string by double backticks, as required for
+ using it in a backtick-quoted SQL string (used for table names and columns).
+ No surrounding ticks will be generated to facilitate concatenation.
+\end_layout
+
+\begin_layout Standard
+Specifying an unrecognized type will result in
+\family typewriter
+NULL
+\family default
+ being returned and
+\family typewriter
+errno
+\family default
+ be set to
+\family typewriter
+EINVAL
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+If
+\family typewriter
+free_me
+\family default
+ is
+\family typewriter
+NULL
+\family default
+, the function will always allocate memory, even if the string needs no
+ quoting.
+ The program then has to free the result:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char *
+\series default
+s = HX_strquote("<head>", HXQUOTE_HTML, NULL);
+\begin_inset Newline newline
+\end_inset
+
+printf("%s
+\backslash
+n", s);
+\begin_inset Newline newline
+\end_inset
+
+free(s);
+\end_layout
+
+\begin_layout Standard
+If
+\family typewriter
+free_me
+\family default
+ is not
+\family typewriter
+NULL
+\family default
+ however, the function will put the pointer to the memory area into
+\family typewriter
+*free_me
+\family default
+, if the string needed quoting.
+ The program then has to free that after it is done with the quoted result:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char *
+\series default
+tmp = NULL;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+s = HX_strquote("head", HXQUOTE_HTML, &tmp);
+\begin_inset Newline newline
+\end_inset
+
+printf("%s
+\backslash
+n", s);
+\begin_inset Newline newline
+\end_inset
+
+free(tmp);
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+tmp
+\family default
+ could be
+\family typewriter
+NULL
+\family default
+, and since
+\family typewriter
+free(NULL)
+\family default
+ is not an error, this is perfectly valid.
+ Furthermore, if
+\family typewriter
+*free_me
+\family default
+ is not
+\family typewriter
+NULL
+\family default
+ by the time
+\family typewriter
+HX_strquote
+\family default
+ is called, the function will free it.
+ This makes it possible to call
+\family typewriter
+HX_strquote
+\family default
+ in succession without
+\family typewriter
+free
+\family default
+s in between:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char *
+\series default
+tmp = NULL;
+\begin_inset Newline newline
+\end_inset
+
+printf("%s
+\backslash
+n", HX_strquote("<html>", HXQUOTE_HTML, &tmp));
+\begin_inset Newline newline
+\end_inset
+
+printf("%s
+\backslash
+n", HX_strquote("<head>", HXQUOTE_HTML, &tmp));
+\begin_inset Newline newline
+\end_inset
+
+free(tmp);
+\end_layout
+
+\begin_layout Subsection
+Tokenizing
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char **
+\series default
+HX_split(
+\series bold
+const char *
+\series default
+s,
+\series bold
+const char *
+\series default
+delimiters,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t *
+\series default
+fields,
+\series bold
+int
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_split
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char **
+\series default
+HX_split4(
+\series bold
+char *
+\series default
+s,
+\series bold
+const char *
+\series default
+delimiters,
+\series bold
+int *
+\series default
+fields,
+\series bold
+int
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_split4
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_split5(
+\series bold
+char *
+\series default
+s,
+\series bold
+const char *
+\series default
+delimiters,
+\series bold
+int
+\series default
+ max,
+\series bold
+char **
+\series default
+stack);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_split5
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strsep(
+\series bold
+char **
+\series default
+sp,
+\series bold
+const char *
+\series default
+delimiters);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strsep
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strsep2(
+\series bold
+char **
+\series default
+sp,
+\series bold
+const char *
+\series default
+dstr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strsep2
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_split
+\family default
+ Split the string
+\family typewriter
+s
+\family default
+ on any characters from the
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+delimiters
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ string.
+ Both the substrings and the array holding the pointers to these substrings
+ will be allocated as required; the original string is not modified.
+ If
+\family typewriter
+max
+\family default
+ is larger than zero, produces no more than
+\family typewriter
+max
+\family default
+ fields.
+ If
+\family typewriter
+fields
+\family default
+ is not
+\family typewriter
+NULL
+\family default
+, the number of elements produced will be stored in
+\family typewriter
+*fields
+\family default
+.
+ The result is a
+\family typewriter
+NULL
+\family default
+-terminated array of
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+, and the user needs to free it when done with it, using
+\family typewriter
+HX_zvecfree
+\family default
+ or equivalent.
+ An empty string (zero-length string) for
+\family typewriter
+s
+\family default
+ yields a single field.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_split4
+\family default
+ Split the string
+\family typewriter
+s
+\family default
+ in-place on any characters from the
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+delimiters
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ string.
+ The array that will be holding the pointers to the substrings will be allocated
+ and needs to be freed by the user, using
+\family typewriter
+free
+\family default
+(3).
+ The
+\family typewriter
+fields
+\family default
+ and
+\family typewriter
+max
+\family default
+ arguments work as with
+\family typewriter
+HX_split
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_split5
+\family default
+ Split the string
+\family typewriter
+s
+\family default
+ in-place on any characters from the
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+delimiters
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ string.
+ The array for the substring pointers must be provided by the user through
+ the
+\family typewriter
+stack
+\family default
+ argument.
+
+\family typewriter
+max
+\family default
+ must be the number of elements in the array or less.
+ The array will not be
+\family typewriter
+NULL
+\family default
+-terminated
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+An implementation may however decide to put NULL in the unassigned fields,
+ but this is implementation and situation-specific.
+ Do not rely on it.
+\end_layout
+
+\end_inset
+
+.
+ The number of fields produced is returned.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strsep
+\family default
+ Extract tokens from a string.
+\begin_inset Newline newline
+\end_inset
+
+This implementation of
+\family typewriter
+strsep
+\family default
+ has been added since the function is non-standard (according to the manpage,
+ conforms to BSD4.4 only) and may not be available on every operating system.
+\begin_inset Newline newline
+\end_inset
+
+This function extracts tokens, separated by one of the characters in
+\family typewriter
+delimiters
+\family default
+.
+ The string is modified in-place and thus must be writable.
+ The delimiters in the string are then overwritten with
+\family typewriter
+'
+\backslash
+0'
+\family default
+,
+\family typewriter
+*sp
+\family default
+ is advanced to the character after the delimiter, and the original pointer
+ is returned.
+ After the final token,
+\family typewriter
+strsep
+\family default
+ will return
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strsep2
+\family default
+ Like
+\family typewriter
+HX_strsep
+\family default
+, but
+\family typewriter
+dstr
+\family default
+ is not an array of delimiting characters, but an entire substring that
+ acts as a delimiter.
+\end_layout
+
+\begin_layout Subsection
+Size-bounded string ops
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strlcat(
+\series bold
+char *
+\series default
+dest,
+\series bold
+const char *
+\series default
+src,
+\series bold
+size_t
+\series default
+ length);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strlcat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strlcpy(
+\series bold
+char *
+\series default
+dest,
+\series bold
+const char *
+\series default
+src,
+\series bold
+size_t
+\series default
+ length);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strlcpy
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strlncat(
+\series bold
+char *
+\series default
+dest,
+\series bold
+const char *
+\series default
+src,
+\series bold
+size_t
+\series default
+ dlen,
+\series bold
+size_t
+\series default
+ slen);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strlncat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+size_t
+\series default
+ HX_strnlen(
+\series bold
+const char *
+\series default
+src,
+\series bold
+size_t
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_strnlen
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_strlcat
+\family default
+ and
+\family typewriter
+HX_strlcpy
+\family default
+ provide implementations of the BSD-originating
+\family typewriter
+strlcat
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strlcat
+\end_layout
+
+\end_inset
+
+ and
+\family typewriter
+strlcpy
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strlcpy
+\end_layout
+
+\end_inset
+
+.
+
+\family typewriter
+strlcat
+\family default
+ and
+\family typewriter
+strlcpy
+\family default
+ are less error-prone variants for
+\family typewriter
+strncat
+\family default
+ and
+\family typewriter
+strncpy
+\family default
+ as they always take the length of the entire buffer specified by
+\family typewriter
+dest
+\family default
+, instead of just the length that is to be written.
+ The functions guarantee that the buffer is
+\family typewriter
+'
+\backslash
+0'
+\family default
+-terminated.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_strnlen
+\family default
+ will return the length of the input string or the upper bound given by
+
+\family typewriter
+max
+\family default
+, whichever is less.
+ It will not attempt to access more than this many bytes in the input buffer.
+\end_layout
+
+\begin_layout Subsection
+Allocation-related
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+HX_memdup(
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ length);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_memdup
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strdup(
+\series bold
+const char *
+\series default
+str);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strdup
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+HX_strndup(
+\series bold
+const char *
+\series default
+str,
+\series bold
+size_t
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_strndup
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Note Greyedout
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+char *
+\series default
+HX_strclone(
+\series bold
+char **
+\series default
+pa,
+\series bold
+const char *
+\series default
+pb);
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_strclone
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+#ifdef
+\series default
+ __cplusplus
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+template<typename type> type
+\series default
+ HX_memdup(
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ length);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#endif
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_memdup
+\family default
+ Duplicates
+\family typewriter
+length
+\family default
+ bytes from the memory area pointed to by
+\family typewriter
+ptr
+\family default
+ and returns a pointer to the new memory block.
+
+\family typewriter
+ptr
+\family default
+ may not be
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strdup
+\family default
+ Duplicates the string.
+ The function is equivalent to
+\family typewriter
+strdup
+\family default
+, but the latter may not be available on all platforms.
+
+\family typewriter
+str
+\family default
+ may be
+\family typewriter
+NULL
+\family default
+, in which case
+\family typewriter
+NULL
+\family default
+ is also returned.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strndup
+\family default
+ Duplicates the input string, but copies at most
+\family typewriter
+max
+\family default
+ characters.
+ (The resulting string will be NUL-terminated of course.)
+\family typewriter
+str
+\family default
+ may not be
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_strclone
+\family default
+ Copies the string pointed to by
+\family typewriter
+pb
+\family default
+ into
+\family typewriter
+*pa
+\family default
+.
+ If
+\family typewriter
+*pa
+\family default
+ was not
+\family typewriter
+NULL
+\family default
+ by the time
+\family typewriter
+HX_strclone
+\family default
+ was called, the string is freed before a new one is allocated.
+ The function returns
+\family typewriter
+NULL
+\family default
+ and sets
+\family typewriter
+errno
+\family default
+ to
+\family typewriter
+EINVAL
+\family default
+ if
+\family typewriter
+pb
+\family default
+ is
+\family typewriter
+NULL
+\family default
+ (this way it can be freed), or, if
+\family typewriter
+malloc
+\family default
+ fails, returns
+\family typewriter
+NULL
+\family default
+ and leaves
+\family typewriter
+errno
+\family default
+ at what
+\family typewriter
+malloc
+\family default
+ set it to.
+\begin_inset Newline newline
+\end_inset
+
+The use of this function is deprecated, albeit no replacement is proposed.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout Subsubsection
+Using HX_split5
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:string-ex-HX_split5"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_split5
+\family default
+, where the
+\begin_inset Quotes eld
+\end_inset
+
+5
+\begin_inset Quotes erd
+\end_inset
+
+ should be interpreted (with a bit of imagination and the knowledge of leetspeak
+) as an
+\begin_inset Quotes eld
+\end_inset
+
+S
+\begin_inset Quotes erd
+\end_inset
+
+ for stack, as
+\family typewriter
+HX_split5
+\family default
+ is often used only with on-stack variables and where the field count of
+ interest is fixed, as the example for parsing
+\family typewriter
+/etc/passwd
+\family default
+ shows:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+field[8];
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+line = NULL;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (HX_getl(&line, fp) != NULL) {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (HX_split5(line, ":", ARRAY_SIZE(field), field) < 7) {
+\begin_inset Newline newline
+\end_inset
+
+ fprintf(stderr, "That does not look like a valid line.
+\backslash
+n");
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+continue
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+ }
+\begin_inset Newline newline
+\end_inset
+
+ printf("Username: %s
+\backslash
+n", field[0]);
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Subsubsection
+Using HX_split4
+\end_layout
+
+\begin_layout Standard
+Where the number of fields is not previously known and/or estimatable, but
+ the string can be modified in place, one uses
+\family typewriter
+HX_split4
+\family default
+ as follows:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <errno.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (HX_getl(&line, fp) != NULL) {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char **
+\series default
+field = HX_split4(line, ":", NULL, 0);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (field == NULL) {
+\begin_inset Newline newline
+\end_inset
+
+ fprintf(stderr, "Badness! %s
+\backslash
+n", strerror(errno));
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+break
+\series default
+;
+\begin_inset Newline newline
+\end_inset
+
+ }
+\begin_inset Newline newline
+\end_inset
+
+ printf("Username: %s
+\backslash
+n", field[0]);
+\begin_inset Newline newline
+\end_inset
+
+ free(field);
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Subsubsection
+Using HX_split
+\end_layout
+
+\begin_layout Standard
+Where the string is not modifiable in-place, one has to resort to using
+ the full-fledged
+\family typewriter
+HX_split
+\family default
+ that allocates space for each substring.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <errno.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (HX_getl(&line, fp) != NULL) {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char **
+\series default
+field = HX_split(line, ":", NULL, 0);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (field == NULL) {
+\begin_inset Newline newline
+\end_inset
+
+ fprintf(stderr, "Badness.
+ %s
+\backslash
+n", strerror(errno));
+\begin_inset Newline newline
+\end_inset
+
+ break;
+\begin_inset Newline newline
+\end_inset
+
+ }
+\begin_inset Newline newline
+\end_inset
+
+ printf("Username: %s
+\backslash
+n", field[0]);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Suppose
+\begin_inset Quotes eld
+\end_inset
+
+callme
+\begin_inset Quotes erd
+\end_inset
+
+ needs the original string
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+ callme(line);
+\begin_inset Newline newline
+\end_inset
+
+ HX_zvecfree(field);
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Subsubsection
+Using HX_strsep
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_strsep
+\family default
+ provides for thread- and reentrant-safe tokenizing a string where strtok
+ from the C standard would otherwise fail.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ line
+\series bold
+[]
+\series default
+ = "root:x:0:0:root:/root:/bin/bash";
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+wp,
+\series bold
+*
+\series default
+p;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+wp = line;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ ((p = HX_strsep(&wp, ":")) != NULL)
+\begin_inset Newline newline
+\end_inset
+
+ printf("%s
+\backslash
+n", p)
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Memory containers
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:mc"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The HXmc series of functions provide scripting-like semantics for strings,
+ especially automatically resizing the buffer on demand.
+ They can also be used to store a binary block of data together with its
+ length.
+ (Hence the name: mc = memory container.)
+\end_layout
+
+\begin_layout Standard
+The benefit of using the HXmc functions is that one does not have to meticulousl
+y watch buffer and string sizes anymore.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout Paragraph
+/* Step
+\begin_inset space ~
+\end_inset
+
+1 */
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char
+\series default
+ buf
+\series bold
+[
+\family roman
+\series default
+\shape italic
+whatever was believed to be long enough
+\family default
+\series bold
+\shape default
+]
+\series default
+ = "helloworld";
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+if
+\series default
+ (strlen(buf) + strlen(".txt") <
+\series bold
+sizeof
+\series default
+(buf))
+\begin_inset Newline newline
+\end_inset
+
+ strcat(s, ".txt");
+\end_layout
+
+\begin_layout Paragraph
+/* Step
+\begin_inset space ~
+\end_inset
+
+2 */
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+char
+\series default
+ buf
+\series bold
+[
+\family roman
+\series default
+\shape italic
+long_enough
+\family default
+\series bold
+\shape default
+]
+\series default
+ = "helloworld";
+\end_layout
+
+\begin_layout LyX-Code
+strlcat(s, ".txt",
+\series bold
+sizeof
+\series default
+(buf));
+\end_layout
+
+\begin_layout Paragraph
+/* Step
+\begin_inset space ~
+\end_inset
+
+3 */
+\end_layout
+
+\begin_layout LyX-Code
+hxmc_t
+\series bold
+*
+\series default
+buf = HXmc_strinit("helloworld");
+\begin_inset Newline newline
+\end_inset
+
+HXmc_strcat(&s, ".txt");
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Improvement of string safety over time
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+This makes it quite similar to the string operations (and append seems to
+ be the most commonly used one to me) supported in scripting languages that
+ also do without a size argument.
+ The essential part of such memory containers is that their internal (hidden)
+ metadata structure contains the length of the memory block in the container.
+ For binary data this may be the norm, but for C-style strings, the stored
+ and auto-updated length field serves as an accelerator cache.
+ For more details, see
+\family typewriter
+HXmc_length
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+Of course, the automatic management of memory comes with a bit of overhead
+ as the string expands beyond its preallocated region.
+ Such may be mitigated by doing explicit (re)sizing.
+\end_layout
+
+\begin_layout Subsection
+Structural overview
+\end_layout
+
+\begin_layout Standard
+HXmc functions do not actually return a pointer to the memory container
+ (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+struct
+\family default
+) itself, but a pointer to the data block.
+ Conversely, input parameters to HXmc functions will be the data block pointer.
+ It is of type
+\family typewriter
+hxmc_t
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+, which is typedef'ed to
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ and inherits all properties and privileges of
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+.
+ Pointer arithmetic is thus supported.
+ It also means you can just pass it to functions that take a
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ without having to do a member access like
+\family typewriter
+s.c_str
+\family default
+.
+ The drawback is that many functions operating on the memory container need
+ a
+\family typewriter
+hxmc_t
+\begin_inset space ~
+\end_inset
+
+**
+\family default
+ (a level-two indirection), because not only does the memory block move,
+ but also the memory container itself.
+ This is due to the implementation of the container metadata which immediately
+ and always precedes the writable memory block.
+\end_layout
+
+\begin_layout Standard
+HXmc ensures that the data block is terminated by a NUL (
+\family typewriter
+'
+\backslash
+0'
+\family default
+) byte (unless you trash it), so you do not have to, and of course, to be
+ on the safe side.
+ But, the automatic NUL byte is not part of the region allocated by the
+ user.
+ That is, when one uses the classic approach with
+\family typewriter
+malloc(4096)
+\family default
+, the user will have control of 4096 bytes and has to stuff the NUL byte
+ in there somehow on his own; for strings this means the maximum string
+ length is 4095.
+ Requesting space for a 4096-byte sized HXmc container gives you the possibility
+ to use all 4096 bytes for the string, because HXmc provides a NUL byte.
+\end_layout
+
+\begin_layout Standard
+By the way,
+\family typewriter
+hxmc_t
+\family default
+ is the
+\shape italic
+only
+\shape default
+ typedef in this entire library, to distinguish it from regular
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ that does not have a backing memory cointainer.
+\end_layout
+
+\begin_layout Subsection
+Constructors, destructors
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/string.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/string.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_strinit(
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmc_strinit
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_meminit(
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ size);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmc_meminit
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_strinit
+\family default
+ Creates a new hxmc_t object from the supplied string and returns it.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_meminit
+\family default
+ Creates a new hxmc_t object from the supplied memory buffer of the given
+ size and returns it.
+
+\family typewriter
+HXmc_meminit(NULL, len)
+\family default
+ may be used to obtain an empty container with a preallocated region of
+
+\family typewriter
+len
+\family default
+ bytes (zero is accepted for
+\family typewriter
+len
+\family default
+).
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+void
+\series default
+ HXmc_free(hxmc_t
+\series bold
+*
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmc_free
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXmc_zvecfree(hxmc_t
+\series bold
+**
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmc_zvecfree
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_free
+\family default
+ Frees the hxmc object.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_zvecfree
+\family default
+ Frees all hxmc objects in the NULL-terminated array, and finally frees
+ the array itself, similar to
+\family typewriter
+HX_zvecfree
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Data manipulation
+\end_layout
+
+\begin_layout Subsubsection
+Binary-based
+\end_layout
+
+\begin_layout LyX-Code
+hxmc_t
+\series bold
+*
+\series default
+HXmc_trunc(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_trunc
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_setlen(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_setlen
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_memcpy(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_memcpy
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_memcat(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_memcat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_mempcat(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_mempcat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_memins(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+size_t
+\series default
+ pos,
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_memins
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_memdel(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+size_t
+\series default
+ pos,
+\series bold
+size_t
+\series default
+ len);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_memdel
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+When
+\family typewriter
+ptr
+\family default
+ is
+\family typewriter
+NULL
+\family default
+, each call behaves as if
+\family typewriter
+len
+\family default
+ would be zero.
+ Specifically, no undefined behavior will result of the use of
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_trunc
+\family default
+ Truncates the container's data to
+\family typewriter
+len
+\family default
+ size.
+ If
+\family typewriter
+len
+\family default
+ is greater than the current data size of the container, the length is in
+ fact
+\shape italic
+not
+\shape default
+ updated, but a reallocation may be triggered, which can be used to do explicit
+ allocation.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_setlen
+\family default
+ Set the data length, doing a reallocation of the memory container if needed.
+ The newly available bytes are uninitialized.
+ Make use of this function when letting 3rd party functions write to the
+ buffer, but it should not be used with
+\family typewriter
+HXmc_str*
+\family default
+(),
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_memcpy
+\family default
+ Truncates the container's data and copies
+\family typewriter
+len
+\family default
+ bytes from the memory area pointed to by
+\family typewriter
+ptr
+\family default
+ to the container.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_memcat
+\family default
+ Concatenates (appends)
+\family typewriter
+len
+\family default
+ bytes from the memory area pointed to by
+\family typewriter
+ptr
+\family default
+ to the container's data.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_mempcat
+\family default
+ Prepends
+\family typewriter
+len
+\family default
+ bytes from the memory area pointed to by
+\family typewriter
+ptr
+\family default
+ to the container's data.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_memins
+\family default
+ Prepends
+\family typewriter
+len
+\family default
+ bytes from the memory area pointed to by
+\family typewriter
+ptr
+\family default
+ to the
+\family typewriter
+pos
+\family default
+'th byte of the container's data.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_memdel
+\family default
+ Deletes
+\family typewriter
+len
+\family default
+ bytes from the container beginning at position
+\family typewriter
+pos
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+In case of a memory allocation failure, the
+\family typewriter
+HXmc_*
+\family default
+ functions will return
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Subsubsection
+String-based
+\end_layout
+
+\begin_layout Standard
+The string-based functions correspond to their binary-based equivalents
+ with a
+\family typewriter
+len
+\family default
+ argument of
+\family typewriter
+strlen(s)
+\family default
+.
+\end_layout
+
+\begin_layout LyX-Code
+hxmc_t
+\series bold
+*
+\series default
+HXmc_strcpy(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_strcpy
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_strcat(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_strcat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_strpcat(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXmc_strpcat
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+hxmc_t
+\series bold
+*
+\series default
+HXmc_strins(hxmc_t
+\series bold
+**
+\series default
+mc,
+\series bold
+size_t
+\series default
+ pos,
+\series bold
+const char *
+\series default
+s);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXmc_strins
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_strcpy
+\family default
+ Copies the string pointed to by
+\family typewriter
+s
+\family default
+ into the memory container given by
+\family typewriter
+mc
+\family default
+.
+ If
+\family typewriter
+mc
+\family default
+ is
+\family typewriter
+NULL
+\family default
+, the memory container will be deallocated, that is,
+\family typewriter
+*mc
+\family default
+ becomes
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Subsubsection
+From auxiliary sources
+\end_layout
+
+\begin_layout LyX-Code
+hxmc_t
+\series bold
+*
+\series default
+HX_getl(hxmc_t
+\series bold
+**
+\series default
+mc, FILE
+\series bold
+*
+\series default
+fp);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_getl
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_getl
+\family default
+ Read the next line from
+\family typewriter
+fp
+\family default
+ and store the result in the container.
+ Returns
+\family typewriter
+NULL
+\family default
+ on error, or when end of file occurs while no characters have been read.
+\end_layout
+
+\begin_layout Subsection
+Container properties
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+size_t
+\series default
+ HXmc_length(
+\series bold
+const
+\series default
+ hxmc_t
+\series bold
+**
+\series default
+mc);
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXmc_length
+\family default
+ Returns the length of the memory container.
+ This is not always equal to the actual string length.
+ For example, if
+\family typewriter
+HX_chomp
+\family default
+ was used on an MC-backed string,
+\family typewriter
+strlen
+\family default
+ will return less than
+\family typewriter
+HXmc_length
+\family default
+ if newline control characters (
+\family typewriter
+'
+\backslash
+r'
+\family default
+ and
+\family typewriter
+'
+\backslash
+n'
+\family default
+) were removed.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Format templates
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:format"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+HXfmt is a small template system for by-name variable expansion.
+ It can be used to substitute placeholders in format strings supplied by
+ the user by appropriate expanded values defined by the program.
+ Such can be used to allow for flexible configuration files that define
+ key-value mappings such as
+\end_layout
+
+\begin_layout LyX-Code
+detect_peer = ping6 -c1 %(ADDR)
+\begin_inset Newline newline
+\end_inset
+
+#detect_peer = nmap -sP %(ADDR) | grep -Eq "appears to be up"
+\end_layout
+
+\begin_layout Standard
+Consider for example a monitoring daemon that allows the administrator to
+ specify a program of his choice with which to detect whether a peer is
+ alive or not.
+ The user can choose any program that is desired, but evidently needs to
+ pass the address to be tested to the program.
+ This is where the daemon will do a substitution of the string
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+ping -c1 %(ADDR)
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ it read from the config file, and put the actual address in it before finally
+ executing the command.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+printf("%s has %u files
+\backslash
+n", user, num);
+\begin_inset Newline newline
+\end_inset
+
+printf("%2$u files belong to %1$s
+\backslash
+n", num, user);
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%s
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ (or
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%1$s
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ here) specifies how large
+\begin_inset Quotes eld
+\end_inset
+
+user
+\begin_inset Quotes erd
+\end_inset
+
+ is
+\begin_inset space ~
+\end_inset
+
+---
+\family typewriter
+sizeof(const char *)
+\family default
+ in this case.
+ If that is missing, there is no way to know the offset of
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+num
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ relative to
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+user
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, making varargs retrieval impossible.
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+
+\family typewriter
+printf
+\family default
+ positional parameters
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+printf
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+printf
+\end_layout
+
+\end_inset
+
+, at least from GNU libc, has something vaguely similar: positional parameters
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+positional parameters
+\end_layout
+
+\end_inset
+
+.
+ They have inherent drawbacks, though.
+ One is of course the question of portability, but there is a bigger issue.
+ All parameters must be specified, otherwise there is no way to determine
+ the location of all following objects following the missing one on the
+ stack in a varargs-function like
+\family typewriter
+printf
+\family default
+., which makes it unsuitable to be used with templates where omitting some
+ placeholders is allowed.
+\end_layout
+
+\begin_layout Subsection
+Initialization, use and deallocation
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/option.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/option.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+HXformat_init(
+\series bold
+void
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXformat_init
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXformat_free(
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXformat_free
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HXformat_add(
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table,
+\series bold
+const char *
+\series default
+key,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const void *
+\series default
+ptr,
+\series bold
+unsigned int
+\series default
+ ptr_type);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXformat_add
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXformat_init
+\family default
+ will allocate and set up a simple string-to-string map that is used for
+ the underlying storage, and returns it.
+\end_layout
+
+\begin_layout Standard
+To release the substitution table and memory associated with it, call
+\family typewriter
+HXformat_free
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXformat_add
+\family default
+ is used to add substitution entries.
+ One can also specify other types such as numeral types.
+
+\family typewriter
+ptr_type
+\family default
+ describes the type behind
+\family typewriter
+ptr
+\family default
+ and are constants from
+\family typewriter
+option.h
+\family default
+ (cf.
+\begin_inset space \space{}
+\end_inset
+
+section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-types"
+
+\end_inset
+
+)
+\begin_inset space ~
+\end_inset
+
+--- not all constants can be used, though, and their meaning also differs
+ from what
+\family typewriter
+HX_getopt
+\family default
+ or
+\family typewriter
+HX_shconfig
+\family default
+ use them for
+\begin_inset space ~
+\end_inset
+
+--- the two could be seen as
+\begin_inset Quotes eld
+\end_inset
+
+read
+\begin_inset Quotes erd
+\end_inset
+
+ operations, while HXformat is a write operation.
+\end_layout
+
+\begin_layout Subsubsection
+Immediate types
+\end_layout
+
+\begin_layout Standard
+\begin_inset Quotes eld
+\end_inset
+
+Immediate types
+\begin_inset Quotes erd
+\end_inset
+
+ are resolved when
+\family typewriter
+HXformat_add
+\family default
+ is called, that is, they are copied and inserted into the tree, and are
+ subsequently independent from any changes to variables in the program.
+ Because the HXopt-originating type name, that is,
+\family typewriter
+HXTYPE_*
+\family default
+, is also used for deferred types, the constant
+\family typewriter
+HXFORMAT_IMMED
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXFORMAT_IMMED
+\end_layout
+
+\end_inset
+
+
+\family default
+ needs to be specified on some types to denote an immediate value.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_STRING
+\family default
+
+\begin_inset space ~
+\end_inset
+
+---
+\family typewriter
+ptr
+\family default
+ is a
+\family typewriter
+const char *
+\family default
+.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_
+\family default
+{
+\family typewriter
+U
+\family default
+,}{
+\family typewriter
+CHAR
+\family default
+,
+\family typewriter
+SHORT
+\family default
+,
+\family typewriter
+INT
+\family default
+,
+\family typewriter
+LONG
+\family default
+,
+\family typewriter
+LLONG
+\family default
+}
+\family typewriter
+ | HXFORMAT_IMMED
+\family default
+
+\begin_inset space ~
+\end_inset
+
+--- mapping to the standard types
+\end_layout
+
+\begin_layout Subsubsection
+Deferred types
+\end_layout
+
+\begin_layout Standard
+\begin_inset Quotes eld
+\end_inset
+
+Deferred types
+\begin_inset Quotes erd
+\end_inset
+
+ are resolved on every invocation of a formatter function (
+\family typewriter
+HXformat_*printf
+\family default
+).
+ The expansions may be changed by modifying the underlying variable pointed
+ to, but the pointer must remain valid and its pointee not go out of scope.
+ Figure
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "fig:hxformat-immediate-deferred"
+
+\end_inset
+
+ shows the difference in a code sample.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_STRP
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_STRP
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+---
+\family typewriter
+ptr
+\family default
+ is a
+\family typewriter
+const char *const *
+\family default
+; the pointer resolution is deferred until the formatter is called with
+ one of the
+\family typewriter
+HXformat_*printf
+\family default
+ functions.
+ Deferred in the sense it is always resolved anew.
+
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_BOOL
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_BOOL
+\end_layout
+
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+---
+\family typewriter
+ptr
+\family default
+ is a
+\family typewriter
+const int
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_
+\family default
+{
+\family typewriter
+U
+\family default
+,}{
+\family typewriter
+CHAR
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_CHAR
+\end_layout
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UCHAR
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+SHORT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_SHORT
+\end_layout
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_USHORT
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+INT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT
+\end_layout
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+LONG
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LONG
+\end_layout
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULONG
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+LLONG
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LLONG
+\end_layout
+
+\end_inset
+
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULLONG
+\end_layout
+
+\end_inset
+
+}
+\begin_inset space ~
+\end_inset
+
+--- mapping to the standard types with one indirection (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+int
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+)
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+HXTYPE_
+\family default
+{
+\family typewriter
+FLOAT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_FLOAT
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+DOUBLE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_DOUBLE
+\end_layout
+
+\end_inset
+
+}
+\begin_inset space ~
+\end_inset
+
+--- mapping to the two floating-point types with one indirection (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+double
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+)
+\end_layout
+
+\begin_layout Subsection
+Invoking the formatter
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ HXformat_aprintf(
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table, hxmc_t
+\series bold
+**
+\series default
+dest,
+\series bold
+const char *
+\series default
+template);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXformat_aprintf
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HXformat_sprintf(
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table,
+\series bold
+char *
+\series default
+dest,
+\series bold
+size_t
+\series default
+ size,
+\series bold
+const char *
+\series default
+template);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXformat_sprintf
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HXformat_fprintf(
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table, FILE
+\series bold
+*
+\series default
+filp,
+\series bold
+const char *
+\series default
+template);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXformat_fprintf
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXformat_aprintf
+\family default
+ Substitute placeholders in
+\family typewriter
+template
+\family default
+ using the given table.
+ This will produce a string in a HX memory container (
+\family typewriter
+hxmc_t
+\family default
+), and the pointer is put into
+\family typewriter
+*dest
+\family default
+.
+ The caller will be responsible for freeing it later when it is done using
+ the result.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXformat_sprintf
+\family default
+ Do substitution and store the expanded result in the buffer
+\family typewriter
+dest
+\family default
+ which is of size
+\family typewriter
+size
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXformat_fprintf
+\family default
+ Do substituion and directly output the expansion to the given stdio stream.
+\end_layout
+
+\begin_layout Standard
+On success, the length of the expanded string is returned, excluding the
+ trailing
+\family typewriter
+'
+\backslash
+0'
+\family default
+.
+ While
+\family typewriter
+HXformat_sprintf
+\family default
+ will not write more than
+\family typewriter
+size
+\family default
+ bytes (including the
+\family typewriter
+'
+\backslash
+0'
+\family default
+), the length it would have taken is returned, similar to what
+\family typewriter
+sprintf
+\family default
+ does.
+ On error, negative errno is returned.
+\end_layout
+
+\begin_layout Standard
+The HXformat function family recognizes make-style like functions and recursive
+ expansion, described below.
+\end_layout
+
+\begin_layout Subsection
+Functions
+\end_layout
+
+\begin_layout Standard
+To expand a variable, one uses a syntax like
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%(NAME)
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ in the format string.
+ Recursive expansion like
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%(%(USER))
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ is supported; assuming
+\family typewriter
+%(USER)
+\family default
+ would expand to
+\begin_inset Quotes eld
+\end_inset
+
+linux
+\begin_inset Quotes erd
+\end_inset
+
+, HXformat would try to resolve
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%(linux)
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ next.
+ Besides these variable substitutions, HXformat also provides function calls
+ whose syntax is
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+%(nameOfFunction parameters[...])
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Parameters can be any text, including variables.
+ Paramters are separated from another by a delimiter specific to each function.
+ See this list for details:
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(env
+\family default
+
+\shape italic
+variable
+\family typewriter
+\shape default
+)
+\begin_inset Newline newline
+\end_inset
+
+
+\family default
+The
+\family typewriter
+env
+\family default
+ function expands to the string that is stored in the environmental variable
+ by the given name.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(exec
+\family default
+\shape italic
+command
+\family typewriter
+\shape default
+
+\family default
+[
+\shape italic
+args
+\shape default
+...]
+\family typewriter
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+The
+\family typewriter
+exec
+\family default
+ function expands to the standard output of the command.
+ The command is directly run without shell invocation, so no special character
+ expansion (wildcards, etc.) takes place.
+ stdin is set to
+\family typewriter
+/dev\SpecialChar \slash{}
+null
+\family default
+.
+ The parameter delimiter is the space character.
+ To be able to use this function
+\begin_inset space ~
+\end_inset
+
+--- as it is relevant to security
+\begin_inset space ~
+\end_inset
+
+--- the fmt table needs to have a key called
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+/libhx/exec
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ See example
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "fig:hxformat-exec"
+
+\end_inset
+
+ for details.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(if
+\family default
+\shape italic
+condition
+\family typewriter
+\shape default
+,
+\family default
+[
+\shape italic
+then
+\shape default
+][
+\family typewriter
+,
+\family default
+[
+\shape italic
+else
+\shape default
+]]
+\family typewriter
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+If the condition parameter expands to a string of non-zero length, the function
+ expands to the
+\begin_inset Quotes eld
+\end_inset
+
+then
+\begin_inset Quotes erd
+\end_inset
+
+ block, otherwise the
+\begin_inset Quotes eld
+\end_inset
+
+else
+\begin_inset Quotes erd
+\end_inset
+
+ block.
+ The delimiter used is a comma.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(lower
+\family default
+\shape italic
+text
+\family typewriter
+\shape default
+)
+\family default
+,
+\family typewriter
+%(upper
+\family default
+\shape italic
+text
+\family typewriter
+\shape default
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+Lowercases or uppercases the supplied argument.
+ As these functions are meant to take only one argument, there is no delimiter
+ defined that would need escaping if multiple arguments were supposed to
+ be passed.
+
+\family typewriter
+%(lower a,b)
+\family default
+ is equivalent to
+\family typewriter
+%(lower "a,b")
+\family default
+.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(shell
+\family default
+\shape italic
+command
+\family typewriter
+\shape default
+
+\family default
+[
+\shape italic
+args
+\shape default
+...]
+\family typewriter
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+Similar to
+\family typewriter
+%(exec)
+\family default
+, but invokes the shell inbetween (i.
+\begin_inset space \thinspace{}
+\end_inset
+
+e.
+\begin_inset space \space{}
+\end_inset
+
+`
+\family typewriter
+sh -c '
+\family default
+\shape italic
+command
+\shape default
+...
+\family typewriter
+'
+\family default
+`) such that special characters, redirection, and so on can be used.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(substr
+\family default
+\shape italic
+text
+\family typewriter
+\shape default
+,
+\family default
+\shape italic
+offset
+\shape default
+[
+\family typewriter
+,
+\family default
+\shape italic
+length
+\shape default
+]
+\family typewriter
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+Extracts a substring out of the given text, starting at
+\shape italic
+offset
+\shape default
+ and running for the given length.
+ If no length is given, will extract until the end of the string.
+ If
+\shape italic
+offset
+\shape default
+ is negative, it specifies the offset from the end of the string.
+ If
+\shape italic
+length
+\shape default
+ is negative, that many characters are left off the end.
+\end_layout
+
+\begin_layout Itemize
+
+\family typewriter
+%(snl
+\family default
+\shape italic
+text
+\family typewriter
+\shape default
+)
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+Strips trailing newlines from text and replaces any other newline by a space.
+ What happens implicity in Makefiles'
+\family typewriter
+$(shell
+\family default
+...
+\family typewriter
+)
+\family default
+ statements usually is explicitly separate in libHX.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+const char *
+\series default
+b = "Hello World";
+\begin_inset Newline newline
+\end_inset
+
+
+\family typewriter
+\series bold
+char
+\series default
+ c
+\family default
+\series bold
+[]
+\family typewriter
+\series default
+ = "Hello World";
+\family default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\family typewriter
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table = HXformat_init();
+\begin_inset Newline newline
+\end_inset
+
+HXformat_add(table, "%(GREETING1)", b, HXTYPE_STRING);
+\begin_inset Newline newline
+\end_inset
+
+HXformat_add(table, "%(GREETING2)", &c, HXTYPE_STRP);
+\begin_inset Newline newline
+\end_inset
+
+b = NULL;
+\begin_inset Newline newline
+\end_inset
+
+snprintf(c,
+\family default
+\series bold
+sizeof
+\family typewriter
+\series default
+(c), "Hello Home");
+\begin_inset Newline newline
+\end_inset
+
+HXformat_aprintf(...);
+\end_layout
+
+\begin_layout Plain Layout
+Upon calling
+\family typewriter
+HXformat_*printf
+\family default
+,
+\family typewriter
+%(GREETING1)
+\family default
+ will expand to
+\begin_inset Quotes eld
+\end_inset
+
+Hello World
+\begin_inset Quotes erd
+\end_inset
+
+ whereas
+\family typewriter
+%(GREETING2)
+\family default
+ will expand to
+\begin_inset Quotes eld
+\end_inset
+
+Hello Home
+\begin_inset Quotes erd
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+\begin_inset CommandInset label
+LatexCommand label
+name "fig:hxformat-immediate-deferred"
+
+\end_inset
+
+Immediate and deferred resolution
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Float figure
+wide false
+sideways false
+status open
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXformat_map
+\series bold
+*
+\series default
+table = HXformat_init();
+\begin_inset Newline newline
+\end_inset
+
+HXformat_add(table, "/libhx/exec", NULL, HXTYPE_IMMED);
+\begin_inset Newline newline
+\end_inset
+
+HXformat_aprintf(table, &result, "%(exec uname -s)");
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+\begin_inset CommandInset label
+LatexCommand label
+name "fig:hxformat-exec"
+
+\end_inset
+
+Using the
+\family typewriter
+%(exec)
+\family default
+ function
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+Filesystem operations
+\end_layout
+
+\begin_layout Section
+Dentry operations
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include <libHX/io.h>
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_readlink(hxmc_t
+\series bold
+**
+\series default
+buf,
+\series bold
+const char *
+\series default
+path);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_readlink
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_realpath(hxmc_t
+\series bold
+**
+\series default
+buf,
+\series bold
+const char *
+\series default
+path,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_realpath
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_readlink
+\family default
+ calls through to
+\family typewriter
+readlink
+\family default
+ to read the target of a symbolic link, and stores the result in the memory
+ container referenced by
+\family typewriter
+*buf
+\family default
+ (similar to
+\family typewriter
+HX_getl
+\family default
+ semantics).
+ If
+\family typewriter
+*buf
+\family default
+ is
+\family typewriter
+NULL
+\family default
+, a new container will be allocated and a pointer to it stored in
+\family typewriter
+*buf
+\family default
+.
+ The container's content is naturally zero-terminated automatically.
+ The return value of the function will be the length of the link target,
+ or negative to indicate the system error value.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_realpath
+\family default
+ will normalize the given path by transforming various path components into
+ alternate descriptions.
+ The
+\family typewriter
+flags
+\family default
+ parameter controls its actions:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_REALPATH_DEFAULT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_REALPATH_DEFAULT
+\end_layout
+
+\end_inset
+
+ A mnemonic for a set of standard flags:
+\family typewriter
+HX_\SpecialChar \-
+REALPATH_\SpecialChar \-
+SELF
+\begin_inset space ~
+\end_inset
+
+| HX_\SpecialChar \-
+REALPATH_\SpecialChar \-
+PARENT
+\family default
+.
+ Note that
+\family typewriter
+HX_\SpecialChar \-
+REALPATH_\SpecialChar \-
+ABSOLUTE
+\family default
+, which would also be required to get libc's
+\family typewriter
+realpath
+\family default
+(3) behavior, is not included in the set.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_REALPATH_ABSOLUTE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_REALPATH_ABSOLUTE
+\end_layout
+
+\end_inset
+
+ Requests that the output path shall be absolute.
+ In the absence of this flag, an absolute output path will only be produced
+ if the input path is also absolute.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_REALPATH_SELF
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_REALPATH_SELF
+\end_layout
+
+\end_inset
+
+ Request resolution of
+\begin_inset Quotes eld
+\end_inset
+
+.
+\begin_inset Quotes erd
+\end_inset
+
+ path components.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_REALPATH_PARENT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_REALPATH_PARENT
+\end_layout
+
+\end_inset
+
+ Request resolution of
+\begin_inset Quotes eld
+\end_inset
+
+..
+\begin_inset Quotes erd
+\end_inset
+
+ path components.
+\end_layout
+
+\begin_layout Standard
+The result is stored in a memory container whose pointer is returned through
+
+\family typewriter
+*buf
+\family default
+.
+ The return value of the function will be negative to indicate a possible
+ system error, or be positive non-zero for success.
+\end_layout
+
+\begin_layout Section
+Directory traversal
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:dir-ops1"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+libHX provides a minimal readdir-style wrapper for cross-platform directory
+ traversal.
+ This is needed because platforms such as do not have readdir (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+Win32), or to work around peculiarities in the lower implementation.
+ Solaris's
+\family typewriter
+struct dirent
+\family default
+ for example is
+\begin_inset Quotes eld
+\end_inset
+
+too small
+\begin_inset Quotes erd
+\end_inset
+
+, that is,
+\family typewriter
+readdir
+\family default
+ will cause a buffer overrun when Linux code is directly ported to it without
+ anticipating for this scenario.
+ libHX's
+\family typewriter
+io.c
+\family default
+ mitigates this.
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/io.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/io.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdir
+\series bold
+*
+\series default
+HXdir_open(
+\series bold
+const char *
+\series default
+directory);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXdir_open
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+HXdir_read(
+\series bold
+struct
+\series default
+ HXdir
+\series bold
+*
+\series default
+handle);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXdir_read
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void
+\series default
+ HXdir_close(
+\series bold
+struct
+\series default
+ HXdir
+\series bold
+*
+\series default
+handle);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXdir_close
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXdir_open
+\family default
+ returns a pointer to its private data area, or
+\family typewriter
+NULL
+\family default
+ upon failure, in which case
+\family typewriter
+errno
+\family default
+ is preserved from the underlying system calls.
+
+\family typewriter
+HXdir_read
+\family default
+ causes the next entry from the directory to be fetched.
+ The pointer returned by
+\family typewriter
+HXdir_read
+\family default
+ must not be freed, and the data is overwritten in subsequent calls to the
+ same handle.
+ If you want to keep it around, you will have to duplicate it yourself.
+
+\family typewriter
+HXdir_close
+\family default
+ will close the directory and free the private data it held.
+\end_layout
+
+\begin_layout Subsection
+Example
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <errno.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/io.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXdir
+\series bold
+*
+\series default
+dh;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ ((dh = HXdir_open(".")) == NULL) {
+\begin_inset Newline newline
+\end_inset
+
+ fprintf(stderr, "Could not open directory: %s
+\backslash
+n", strerror(errno));
+\begin_inset Newline newline
+\end_inset
+
+ return;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ ((dentry = HXdir_read(dh)) != NULL)
+\begin_inset Newline newline
+\end_inset
+
+ printf("%s
+\backslash
+n", dentry);
+\begin_inset Newline newline
+\end_inset
+
+HXdir_close(dh);
+\end_layout
+
+\begin_layout Standard
+This sample will open the current directory, and print out all entries as
+ it iterates over them.
+\end_layout
+
+\begin_layout Section
+Directory operations
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:dir-ops2"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/io.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/io.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_mkdir(
+\series bold
+const char *
+\series default
+path,
+\series bold
+unsigned int
+\series default
+ mode);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+HX_mkdir
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_rrmdir(
+\series bold
+const char *
+\series default
+path);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_rrmdir
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_mkdir
+\family default
+ will create the directory given by
+\family typewriter
+path
+\family default
+ and all its parents that do not exist yet using the given
+\family typewriter
+mode
+\family default
+.
+ It is equivalent to the `
+\family typewriter
+mkdir -p
+\family default
+` shell command.
+ It will return >0 for success, or
+\family typewriter
+-errno
+\family default
+ on error.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_rrmdir
+\family default
+ also maps to an operation commonly done on the shell, `
+\family typewriter
+rm -Rf
+\family default
+`, deleting the directory given by
+\family typewriter
+path
+\family default
+, including all files within it and its subdirectories.
+ Errors during deletion are ignored, but if there was any, the errno value
+ of the first one is returned negated.
+\end_layout
+
+\begin_layout Section
+File operations
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:file-ops"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/io.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/io.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_copy_file(
+\series bold
+const char *
+\series default
+src,
+\series bold
+const char *
+\series default
+dest,
+\series bold
+unsigned int
+\series default
+ flags, ...);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_copy_file
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_copy_dir(
+\series bold
+const char *
+\series default
+src,
+\series bold
+const char *
+\series default
+dest,
+\series bold
+unsigned int
+\series default
+ flags, ...);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_copy_dir
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Possible flags that can be used with the functions:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXF_KEEP
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXF_KEEP
+\end_layout
+
+\end_inset
+
+ Do not overwrite existing files.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXF_UID
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXF_UID
+\end_layout
+
+\end_inset
+
+ Change the new file's owner to the UID given in the varargs section (
+\family typewriter
+...
+\family default
+).
+
+\family typewriter
+HXF_UID
+\family default
+ is processed before
+\family typewriter
+HXF_GID
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXF_GID
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXF_GID
+\end_layout
+
+\end_inset
+
+ Change the new file's group owner to the GID given in the varargs section.
+ This is processed after
+\family typewriter
+HXF_UID
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+Error checking is flakey.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_copy_file
+\family default
+ will return >0 on success, or
+\family typewriter
+-errno
+\family default
+ on failure.
+ Errors can arise from the use of the syscalls
+\family typewriter
+open
+\family default
+,
+\family typewriter
+read
+\family default
+ and
+\family typewriter
+write
+\family default
+.
+ The return value of
+\family typewriter
+fchmod
+\family default
+, which is used to set the UID and GID, is actually ignored, which means
+ verifying that the owner has been set cannot be detected with
+\family typewriter
+HX_copy_file
+\family default
+ alone (historic negligience?).
+\end_layout
+
+\begin_layout Subsection
+Filedescriptor I/O
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/io.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/io.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+ssize_t
+\series default
+ HXio_fullread(
+\series bold
+int
+\series default
+ fd,
+\series bold
+void *
+\series default
+buf,
+\series bold
+size_t
+\series default
+ size,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXio_fullread
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+ssize_t
+\series default
+ HXio_fullwrite(
+\series bold
+int
+\series default
+ fd,
+\series bold
+const void *
+\series default
+buf,
+\series bold
+size_t
+\series default
+ size,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXio_fullwrite
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Since plain
+\family typewriter
+read
+\family default
+(2) and
+\family typewriter
+write
+\family default
+(2) may process only part of the buffer
+\begin_inset space ~
+\end_inset
+
+--- even more likely so with sockets
+\begin_inset space ~
+\end_inset
+
+---, libHX provides two functions that calls these in a loop to retry said
+ operations until the full amount has been processed.
+ Since
+\family typewriter
+read
+\family default
+ and
+\family typewriter
+write
+\family default
+ can also be used with socket file descriptors, so can these.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+Options and Configuration Files
+\end_layout
+
+\begin_layout Section
+Option parsing
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:option"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+libHX uses a table-based approach like libpopt
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+The alternative would be an iterative, open-coded approach like
+\family typewriter
+getopt
+\family default
+(3) requires.
+\end_layout
+
+\end_inset
+
+.
+ It provides for both long and short options and the different styles associated
+ with them, such as absence or presence of an equals sign for long options
+ (
+\family typewriter
+--foo=bar
+\family default
+ and
+\family typewriter
+--foo bar
+\family default
+), bundling (writing
+\family typewriter
+-abc
+\family default
+ for non-argument taking options
+\family typewriter
+-a -b -c
+\family default
+), squashing (writing
+\family typewriter
+-fbar
+\family default
+ for an argument-requiring option
+\family typewriter
+-f
+\begin_inset space ~
+\end_inset
+
+bar
+\family default
+).
+ The
+\begin_inset Quotes eld
+\end_inset
+
+lone dash
+\begin_inset Quotes erd
+\end_inset
+
+ that is often used to indicate standard input or standard output, is correctly
+ handled
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+popt failed to do this for a long time.
+\end_layout
+
+\end_inset
+
+, as in
+\family typewriter
+-f
+\begin_inset space ~
+\end_inset
+
+-
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+A table-based approach allows for the parser to run as one atomic block
+ of code (callbacks are, by definition,
+\begin_inset Quotes eld
+\end_inset
+
+special
+\begin_inset Quotes erd
+\end_inset
+
+ exceptions), making it more opaque than an open-coded
+\family typewriter
+getopt
+\family default
+(3) loop.
+ You give it your argument vector and the table, snip the finger (call the
+ parser function once), and it is done.
+ In getopt on the other hand, the
+\family typewriter
+getopt
+\family default
+ function returns for every argument it parsed and needs to be called repeatedly.
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-synopsis"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/option.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/option.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption {
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+struct HXoption
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char
+\series default
+ *ln;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ sh;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ type;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+ptr,
+\series bold
+*
+\series default
+uptr;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+cb
+\series bold
+)
+\series default
+(
+\series bold
+const struct
+\series default
+ HXoptcb
+\series bold
+*
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ val;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+help,
+\series bold
+*
+\series default
+htyp;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_getopt(
+\series bold
+const struct
+\series default
+ HXoption
+\series bold
+*
+\series default
+options_table,
+\series bold
+int *
+\series default
+argc,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char ***
+\series default
+argv,
+\series bold
+unsigned int
+\series default
+ flags);
+\end_layout
+
+\begin_layout Standard
+The various fields of
+\family typewriter
+struct HXoption
+\family default
+ are:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+ln
+\family default
+ The long option name, if any.
+ May be
+\family typewriter
+NULL
+\family default
+ if none is to be assigned for this entry.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+sh
+\family default
+ The short option name/character, if any.
+ May be
+\family typewriter
+'
+\backslash
+0'
+\family default
+ if none is to be assigned for this entry.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+type
+\family default
+ The type of the entry, essentially denoting the type of the target variable.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+val
+\family default
+ An integer value to be stored into
+\family typewriter
+*(int
+\begin_inset space ~
+\end_inset
+
+*)ptr
+\family default
+ when
+\family typewriter
+HXTYPE_IVAL
+\family default
+ is used.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+ptr
+\family default
+ A pointer to the variable so that the option parser can store the requested
+ data in it.
+ The pointer may be
+\family typewriter
+NULL
+\family default
+ in which case no data is stored (but
+\family typewriter
+cb
+\family default
+ is still called if defined, with the data).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+uptr
+\family default
+ A user-supplied pointer.
+ Its value is passed verbatim to the callback, and may be used for any purpose
+ the user wishes.
+ If
+\family typewriter
+type
+\family default
+ is
+\family typewriter
+HXTYPE_SVAL
+\family default
+, it is the value in
+\family typewriter
+uptr
+\family default
+ that will be used to populate
+\family typewriter
+*(const char
+\begin_inset space ~
+\end_inset
+
+**)ptr
+\family default
+.
+ (The original
+\family typewriter
+.sval
+\family default
+ field has been removed in libHX 3.12.)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+cb
+\family default
+ If not
+\family typewriter
+NULL
+\family default
+, call out to the referenced function after the option has been parsed (and
+ the results possibly be stored in
+\family typewriter
+ptr
+\family default
+)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+help
+\family default
+ A help string that is shown for the option when the option table is dumped
+ by request (e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g.
+\begin_inset space \space{}
+\end_inset
+
+
+\family typewriter
+yourprgram --help
+\family default
+)
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+htyp
+\family default
+ String containing a keyword to aid the user in understanding the available
+ options during dump.
+ See examples.
+\end_layout
+
+\begin_layout Standard
+Due to the amount of fields, it is advised to use C99 named initializers
+ to populate a struct, as they allow to omit unspecified fields, and assume
+ no specific order of the members:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ HXoption e = {.sh = 'f', .help = "Force"};
+\end_layout
+
+\begin_layout Standard
+It is a sad fact that C++ has not gotten around to implement these yet.
+ It is advised to put the option parsing code into a separate
+\family typewriter
+.c
+\family default
+ file that can then be compiled in C99 rather than C++ mode.
+\end_layout
+
+\begin_layout Subsection
+Type map
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-types"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_NONE
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXTYPE_NONE
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ The option does not take any argument, but the presence of the option may
+ be record by setting the
+\family typewriter
+*(int
+\begin_inset space ~
+\end_inset
+
+*)ptr
+\family default
+ to 1.
+ Other rules apply when
+\family typewriter
+HXOPT_\SpecialChar \-
+INC
+\family default
+ or
+\family typewriter
+HXOPT_\SpecialChar \-
+DEC
+\family default
+ are specified as flags (see section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-flags"
+
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_VAL
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXTYPE_VAL
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Use the integer value specified by
+\family typewriter
+ival
+\family default
+ and store it in
+\family typewriter
+*(int
+\begin_inset space ~
+\end_inset
+
+*)ptr
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_SVAL
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXTYPE_SVAL
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Use the memory location specified by
+\family typewriter
+sval
+\family default
+ and store it in
+\family typewriter
+*(const char
+\begin_inset space ~
+\end_inset
+
+**)ptr
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_BOOL
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXTYPE_BOOL
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Interpret the supplied argument as a boolean descriptive (must be
+\begin_inset Quotes eld
+\end_inset
+
+yes
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+no
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+on
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+off
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+true
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+false
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+0
+\begin_inset Quotes erd
+\end_inset
+
+ or
+\begin_inset Quotes eld
+\end_inset
+
+1
+\begin_inset Quotes erd
+\end_inset
+
+) and store the result in
+\family typewriter
+*(int
+\begin_inset space ~
+\end_inset
+
+*)ptr
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_STRING
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_STRING
+\end_layout
+
+\end_inset
+
+
+\family default
+ The argument string is duplicated to a new memory region and the resulting
+ pointer stored into
+\family typewriter
+*(char
+\begin_inset space ~
+\end_inset
+
+**)ptr
+\family default
+.
+ This incurs an allocation so that subsequently modifying the original argument
+ string in any way will not falsely propagate.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXTYPE_STRDQ
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXTYPE_STRDQ
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ The argument string is duplicated to a new memory region and the resulting
+ pointer is added to the given HXdeque.
+ Note that you often need to use deferred initialization of the options
+ table to avoid putting
+\family typewriter
+NULL
+\family default
+ into the entry.
+ See section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-pitfalls-static"
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Standard
+The following table lists the types that map to the common integral and
+ floating-point types.
+ Signed and unsigned integeral types are processed using
+\family typewriter
+strtol
+\family default
+ and
+\family typewriter
+strtoul
+\family default
+, respectively.
+
+\family typewriter
+strtol
+\family default
+ and
+\family typewriter
+strtoul
+\family default
+ will be called with automatic base detection.
+ This usually means that a leading
+\begin_inset Quotes eld
+\end_inset
+
+0
+\begin_inset Quotes erd
+\end_inset
+
+ indicates the string is given in octal (8) base, a leading
+\begin_inset Quotes eld
+\end_inset
+
+0x
+\begin_inset Quotes erd
+\end_inset
+
+ indicates hexadecimal (16) base, and decimal (10) otherwise.
+
+\family typewriter
+HXTYPE_\SpecialChar \-
+LLONG
+\family default
+,
+\family typewriter
+ HXTYPE_\SpecialChar \-
+ULLONG
+\family default
+,
+\family typewriter
+ HXTYPE_\SpecialChar \-
+INT64
+\family default
+ and
+\family typewriter
+ HXTYPE_\SpecialChar \-
+UINT64
+\family default
+ use
+\family typewriter
+ strtoll
+\family default
+ and/or
+\family typewriter
+ strtoull
+\family default
+, which may not be available on all platforms.
+\end_layout
+
+\begin_layout Standard
+\align center
+\begin_inset Float table
+placement H
+wide false
+sideways false
+status open
+
+\begin_layout Plain Layout
+\align center
+\begin_inset Tabular
+<lyxtabular version="3" rows="12" columns="4">
+<features tabularvalignment="middle">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="bottom" width="0">
+<column alignment="center" valignment="top" width="0">
+<column alignment="center" valignment="top" width="0">
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series bold
+type
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+Type of pointee
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+type
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\series bold
+Type of pointee
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_CHAR
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_CHAR
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+char
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT8
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT8
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int8_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UCHAR
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UCHAR
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+unsigned char
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT8
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT8
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+uint8_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_SHORT
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_SHORT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+short
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT16
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT16
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int16_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_USHORT
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_USHORT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+unsigned short
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT16
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT16
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+uint16_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT32
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT32
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int32_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+unsigned int
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT32
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT32
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+uint32_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LONG
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LONG
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+long
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT64
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_INT64
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+int64_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULONG
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULONG
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+unsigned long
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT64
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_UINT64
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+uint64_t
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LLONG
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_LLONG
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+long long
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_FLOAT
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_FLOAT
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+float
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULLONG
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_ULLONG
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+unsigned long long
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_DOUBLE
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_DOUBLE
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+double
+\end_layout
+
+\end_inset
+</cell>
+</row>
+<row>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_SIZE_T
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXTYPE_SIZE_T
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\family typewriter
+size_t
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\end_layout
+
+\end_inset
+</cell>
+<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\begin_layout Plain Layout
+
+\end_layout
+
+\end_inset
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Plain Layout
+\begin_inset Caption
+
+\begin_layout Plain Layout
+Integral and floating-point types for the libHX option parser
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HXTYPE_\SpecialChar \-
+FLOAT
+\family default
+ and
+\family typewriter
+HXTYPE_\SpecialChar \-
+DOUBLE
+\family default
+ make use of
+\family typewriter
+strtod
+\family default
+ (
+\family typewriter
+strtof
+\family default
+ is not used).
+ A corresponding
+\family typewriter
+type
+\family default
+ for the
+\begin_inset Quotes eld
+\end_inset
+
+long double
+\begin_inset Quotes erd
+\end_inset
+
+ format is not specified, but may be implemented on behalf of the user via
+ a callback (see section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-example-cb"
+
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Subsection
+Flags
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-flags"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Flags can be combined into the
+\family typewriter
+type
+\family default
+ parameter by OR'ing them.
+ It is valid to not specify any flags at all, but most flags collide with
+ one another.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_INC
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_INC
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Perform an increment on the memory location specified by the
+\family typewriter
+*(int
+\begin_inset space ~
+\end_inset
+
+*)ptr
+\family default
+ pointer.
+ Make sure the referenced variable is initialized before!
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_DEC
+\family default
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_DEC
+\end_layout
+
+\end_inset
+
+
+\series default
+ Perform a decrement on the pointee.
+\end_layout
+
+\begin_layout Standard
+Only one of
+\family typewriter
+HXOPT_\SpecialChar \-
+INC
+\family default
+ and
+\family typewriter
+HXOPT_\SpecialChar \-
+DEC
+\family default
+ may be specified at a time, and they require that the base type is
+\family typewriter
+HXTYPE_\SpecialChar \-
+NONE
+\family default
+, or they will have no effect.
+ An example may be found in section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-example-incdec"
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_NOT
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_NOT
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Binary negation of the argument directly after reading it from the command
+ line into memory.
+ Any of the three following operations are executed with the already-negated
+ value.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_OR
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_OR
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Binary
+\begin_inset Quotes eld
+\end_inset
+
+OR
+\begin_inset Quotes erd
+\end_inset
+
+s the pointee with the specified\SpecialChar \slash{}
+transformed value.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_AND
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_AND
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Binary
+\begin_inset Quotes eld
+\end_inset
+
+AND
+\begin_inset Quotes erd
+\end_inset
+
+s the pointee with the specified\SpecialChar \slash{}
+transformed value.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_XOR
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_XOR
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Binary
+\begin_inset Quotes eld
+\end_inset
+
+XOR
+\begin_inset Quotes erd
+\end_inset
+
+s the pointee with the specified\SpecialChar \slash{}
+transformed value.
+\end_layout
+
+\begin_layout Standard
+Only one of (
+\family typewriter
+HXOPT_OR
+\family default
+,
+\family typewriter
+HXOPT_\SpecialChar \-
+AND
+\family default
+,
+\family typewriter
+HXOPT_\SpecialChar \-
+XOR
+\family default
+) may be specified at a time, but they can be used with any integral
+\family typewriter
+type
+\family default
+ (
+\family typewriter
+HXTYPE_\SpecialChar \-
+UINT
+\family default
+,
+\family typewriter
+HXTYPE_\SpecialChar \-
+ULONG
+\family default
+, etc.).
+ An example can be found in section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-example-mask"
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_OPTIONAL
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_OPTIONAL
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ This flag allows for an option to take zero or one argument.
+ Needless to say that this can be confusing to the user.
+
+\shape italic
+iptables
+\shape default
+'s
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-L
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ option for example is one of this kind (though it does not use the libHX
+ option parser).
+ When this flag is used,
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-f -b
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ is interpreted as
+\family typewriter
+-f
+\family default
+ without an argument, as is
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-f --bar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+
+\begin_inset space ~
+\end_inset
+
+--- things that look like an option take precedence over an option with
+ an optional argument.
+
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-f -
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ of course denotes an option with an argument, as
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ is used to indicate standard input/output.
+\end_layout
+
+\begin_layout Subsection
+Special entries
+\end_layout
+
+\begin_layout Standard
+HXopt provides two special entries via macros:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_AUTOHELP
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_AUTOHELP
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Adds entries to recognize
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-?
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ and
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+--help
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ that will display the (long-format) help screen, and
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+--usage
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ that will display the short option syntax overview.
+ All three options will exit the program afterwards.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_TABLEEND
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_TABLEEND
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ This sentinel marks the end of the table and is required on all tables.
+ (See examples for details.)
+\end_layout
+
+\begin_layout Subsection
+Invoking the parser
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+int
+\series default
+ HX_getopt(
+\series bold
+const struct
+\series default
+ HXoption
+\series bold
+*
+\series default
+options_table,
+\series bold
+int *
+\series default
+argc,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char ***
+\series default
+argv,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_getopt
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_getopt
+\family default
+ is the actual parsing function.
+ It takes the option table, and a pointer to your
+\family typewriter
+argc
+\family default
+ and
+\family typewriter
+argv
+\family default
+ variables that you get from the
+\family typewriter
+main
+\family default
+ function.
+ The parser will, unlike GNU getopt, literally
+\begin_inset Quotes eld
+\end_inset
+
+eat
+\begin_inset Quotes erd
+\end_inset
+
+ all options and their arguments, leaving only non-options in
+\family typewriter
+argv
+\family default
+, and
+\family typewriter
+argc
+\family default
+ updated, when finished.
+ This is similar to how Perl's
+\begin_inset Quotes eld
+\end_inset
+
+Getopt::Long
+\begin_inset Quotes erd
+\end_inset
+
+ module works.
+ Additional flags can control the exact behavior of
+\family typewriter
+HX_getopt
+\family default
+:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_PTHRU
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_PTHRU
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+
+\begin_inset Quotes eld
+\end_inset
+
+Passthrough mode
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Any unknown options are not
+\begin_inset Quotes eld
+\end_inset
+
+eaten
+\begin_inset Quotes erd
+\end_inset
+
+ and are instead passed back into the resulting
+\family typewriter
+argv
+\family default
+ array.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_QUIET
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_QUIET
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Do not print any diagnostics when encountering errors in the user's input.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_HELPONERR
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_HELPONERR
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Display the (long-format) help when an error, such as an unknown option
+ or a violation of syntax, is encountered.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_USAGEONERR
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_USAGEONERR
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Display the short-format usage syntax when an error is encountered.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_RQ_ORDER
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_RQ_ORDER
+\end_layout
+
+\end_inset
+
+ Specifying this option terminates option processing when the first non-option
+ argument in
+\family typewriter
+argv
+\family default
+ is encountered.
+ This behavior is also implicit when the environment variable
+\family typewriter
+POSIXLY_CORRECT
+\family default
+ is set.
+\end_layout
+
+\begin_layout Standard
+The return value can be one of the following:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_ERR_SUCCESS
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXOPT_ERR_SUCCESS
+\end_layout
+
+\end_inset
+
+ Parsing was successful.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_ERR_UNKN
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_ERR_UNKN
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ An unknown option was encountered.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_ERR_VOID
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_ERR_VOID
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ An argument was given for an option which does not allow one.
+ In practice this only happens with
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+--foo=bar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ when
+\family typewriter
+--foo
+\family default
+ is of type
+\family typewriter
+HXTYPE_\SpecialChar \-
+NONE
+\family default
+,
+\family typewriter
+HXTYPE_\SpecialChar \-
+VAL
+\family default
+ or
+\family typewriter
+HXTYPE_\SpecialChar \-
+SVAL
+\family default
+.
+ This does not affect
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+--foo bar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, because this can be unambiguously interpreted as
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+bar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ being a remaining argument to the program.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXOPT_ERR_MIS
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXOPT_ERR_MIS
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Missing argument for an option that requires one.
+\end_layout
+
+\begin_layout Description
+negative
+\begin_inset space ~
+\end_inset
+
+non-zero Failure on behalf of lower-level calls; errno.
+\end_layout
+
+\begin_layout Subsection
+Pitfalls
+\end_layout
+
+\begin_layout Subsubsection
+Staticness of tables
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-pitfalls-static"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The following is an example of a trap regarding
+\family typewriter
+HXTYPE_\SpecialChar \-
+STRDQ
+\family default
+:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static struct
+\series default
+ HXdeque
+\series bold
+*
+\series default
+dq;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static bool
+\series default
+ get_options(
+\series bold
+int *
+\series default
+argc,
+\series bold
+const char ***
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'N', .type = HXTYPE_STRDQ, .q_strdq = dq,
+\begin_inset Newline newline
+\end_inset
+
+ .help = "Add name"},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ HX_getopt(options_table, argc, argv, HXOPT_USAGEONERR) ==
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_ERR_SUCCESS;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ main(
+\series bold
+int
+\series default
+ argc,
+\series bold
+const char **
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+ dq = HXdeque_init();
+\begin_inset Newline newline
+\end_inset
+
+ get_options(&argc, &argv);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ 0;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Standard
+The problem here is that
+\family typewriter
+options_\SpecialChar \-
+table
+\family default
+ is, due to the
+\family typewriter
+static
+\family default
+ keyword, initialized at compile-time where
+\family typewriter
+dq
+\family default
+ is still
+\family typewriter
+NULL
+\family default
+.
+ To counter this problem and have it doing the right thing, you must remove
+ the
+\family typewriter
+static
+\family default
+ qualifier on the options table when used with
+\family typewriter
+HXTYPE_\SpecialChar \-
+STRDQ
+\family default
+, so that it will be evaluated when it is first executed.
+\end_layout
+
+\begin_layout Standard
+It was not deemed worthwhile to have
+\family typewriter
+HXTYPE_\SpecialChar \-
+STRDQ
+\family default
+ take an indirect HXdeque (
+\family typewriter
+struct HXdeque
+\begin_inset space ~
+\end_inset
+
+**
+\family default
+) instead just to bypass this issue.
+ (Live with it.)
+\end_layout
+
+\begin_layout Subsection
+Limitations
+\end_layout
+
+\begin_layout Standard
+The HX option parser has been influenced by both popt and Getopt::Long,
+ but eventually, there are differences:
+\end_layout
+
+\begin_layout Itemize
+Long options with a single dash (
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-foo bar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+).
+ This unsupported syntax clashes very easily with support for option bundling
+ or squashing.
+ In case of bundling,
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-foo
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ might actually be
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-f -o -o
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, or
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+-f oo
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ in case of squashing.
+ It also introduces redundant ways to specify options, which is not in the
+ spirit of the author.
+\end_layout
+
+\begin_layout Itemize
+Options using a
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
++
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ as a prefix, as in
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
++foo
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Xterm for example uses it as a way to negate an option.
+ In the author's opinion, using one character to specify options is enough
+\begin_inset space ~
+\end_inset
+
+--- by GNU standards, a negator is named
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+--no-foo
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Even Microsoft stuck to a single option introducing character (that would
+ be
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+/
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Itemize
+Table nesting like implemented in popt.
+ HXopt has no provision for nested tables, as the need has not come up yet.
+ It does however support chained processing (see section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-example-chained"
+
+\end_inset
+
+).
+ You cannot do nested tables even with callbacks, as the new
+\family typewriter
+argv
+\family default
+ array is only put in place shortly before
+\family typewriter
+HX_getopt
+\family default
+ returns.
+\end_layout
+
+\begin_layout Subsection
+Examples
+\end_layout
+
+\begin_layout Subsubsection
+Basic example
+\end_layout
+
+\begin_layout Standard
+The following code snippet should provide an equivalent of the GNU getopt
+ sample
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+\begin_inset Flex URL
+status open
+
+\begin_layout Plain Layout
+
+http://www.gnu.org/software/libtool/manual/libc/Example-of-Getopt.html
+\backslash
+#Example-of-Getopt
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <stdio.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <stdilb.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+#include
+\series default
+ <libHX/option.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ main(
+\series bold
+int
+\series default
+ argc,
+\series bold
+const char **
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ aflag = 0;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ bflag = 0;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+cflag = NULL;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'a', .type = HXTYPE_NONE, .ptr = &aflag},
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'b', .type = HXTYPE_NONE, .ptr = &bflag},
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'c', .type = HXTYPE_STRING, .ptr = &cflag},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_AUTOHELP,
+\end_layout
+
+\begin_layout LyX-Code
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (HX_getopt(options_table, &argc, &argv, HXOPT_USAGEONERR) !=
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_ERR_SUCCESS)
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+return
+\series default
+ EXIT_FAILURE;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ printf("aflag = %d, bflag = %d, cvalue = %s
+\backslash
+n",
+\begin_inset Newline newline
+\end_inset
+
+ aflag, bflag, cvalue);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+while
+\series default
+ (*++argv != NULL)
+\begin_inset Newline newline
+\end_inset
+
+ printf("Non-option argument %s
+\backslash
+n", *argv);
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ EXIT_SUCCESS;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Subsubsection
+Verbosity levels
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-example-incdec"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static int
+\series default
+ verbosity = 1;
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+somewhat silent by default
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .q_int = &verbosity,
+\begin_inset Newline newline
+\end_inset
+
+ .help = "Reduce verbosity"},
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .q_int = &verbosity,
+\begin_inset Newline newline
+\end_inset
+
+ .help = "Increase verbosity"},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Standard
+This sample option table makes it possible to turn the verbosity of the
+ program up or down, depending on whether the user specified
+\family typewriter
+-q
+\family default
+ or
+\family typewriter
+-v
+\family default
+.
+ By passing multiple
+\family typewriter
+-v
+\family default
+ flags, the verbosity can be turned up even more.
+ The range depends on the
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+int
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ data type for your particular platform and compiler; if you want to have
+ the verbosity capped at a specific level, you will need to use an extra
+ callback:
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static int
+\series default
+ verbosity = 1;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static void
+\series default
+ v_check(
+\series bold
+const struct
+\series default
+ HXoptcb
+\series bold
+*
+\series default
+cbi)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (verbosity < 0)
+\begin_inset Newline newline
+\end_inset
+
+ verbosity = 0;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+else if
+\series default
+ (verbosity > 4)
+\begin_inset Newline newline
+\end_inset
+
+ verbosity = 4;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static const struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'q', .type = HXTYPE_NONE | HXOPT_DEC, .q_int = &verbosity,
+\begin_inset Newline newline
+\end_inset
+
+ .cb = v_check, .help = "Lower verbosity"},
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'v', .type = HXTYPE_NONE | HXOPT_INC, .q_int = &verbosity,
+\begin_inset Newline newline
+\end_inset
+
+ .cb = v_check, .help = "Raise verbosity"},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Subsubsection
+Mask operations
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-example-mask"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+run on all CPU cores by default
+\family default
+\series bold
+\shape default
+ *
+\series default
+/
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static unsigned int
+\series default
+ cpu_mask = ~0U
+\series bold
+;
+\begin_inset Newline newline
+\end_inset
+
+/*
+\family roman
+\series default
+\shape italic
+use no network connections by default
+\family default
+\shape default
+
+\series bold
+*/
+\begin_inset Newline newline
+\end_inset
+
+static unsigned int
+\series default
+ net_mask = 0;
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+static struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'c', .type = HXTYPE_UINT | HXOPT_NOT | HXOPT_AND,
+\begin_inset Newline newline
+\end_inset
+
+ .q_uint = &cpu_mask,
+\begin_inset Newline newline
+\end_inset
+
+ .help = "Mask of cores to exclude", .htyp = "cpu_mask"},
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'n', .type = HXTYPE_UINT | HXOPT_OR, .q_uint = &net_mask,
+\end_layout
+
+\begin_layout LyX-Code
+ .help = "Mask of network channels to additionally use",
+\begin_inset Newline newline
+\end_inset
+
+ .htyp = "channel_mask"},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Standard
+What this options table does is
+\family typewriter
+cpu_mask &= ~x
+\family default
+ and
+\family typewriter
+net_mask |= y
+\family default
+, the classic operations of clearing and setting bits.
+\end_layout
+
+\begin_layout Subsubsection
+Support for non-standard actions
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-example-cb"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Supporting additional types or custom storage formats is easy, by simply
+ using
+\family typewriter
+HXTYPE_\SpecialChar \-
+STRING
+\family default
+,
+\family typewriter
+NULL
+\family default
+ as the data pointer (usually by not specifying it at all), the pointer
+ to your data in the user-specified pointer
+\family typewriter
+uptr
+\family default
+, and the callback function in
+\family typewriter
+cb
+\family default
+.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+struct
+\series default
+ fixed_point {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ integral;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ fraction;
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static struct
+\series default
+ fixed_point number;
+\end_layout
+
+\begin_layout LyX-Code
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static void
+\series default
+ fixed_point_parse
+\series bold
+(const struct
+\series default
+ HXoptcb
+\series bold
+
+\series default
+*cbi)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+end;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+ number.integral = strtol(cbi->data, &end, 0);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (*end == '
+\backslash
+0')
+\begin_inset Newline newline
+\end_inset
+
+ number.fraction = 0;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+else if
+\series default
+ (*end == '.')
+\begin_inset Newline newline
+\end_inset
+
+ number.fraction = strtoul(end + 1, NULL, 0);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+else
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+ fprintf(stderr, "Illegal input.
+\backslash
+n");
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+static const struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.sh = 'n', .type = HXTYPE_STRING, .cb = fixed_point_parse,
+\begin_inset Newline newline
+\end_inset
+
+ .uptr = &number, .help = "Do this or that",
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\end_layout
+
+\begin_layout LyX-Code
+};
+\end_layout
+
+\begin_layout Subsubsection
+Chained argument processing
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:option-example-chained"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+On the first run, only
+\family typewriter
+--cake
+\family default
+ and
+\family typewriter
+--fruit
+\family default
+ is considered, which is then used to select the next set of accepted options.
+ Note that
+\family typewriter
+HXOPT_\SpecialChar \-
+DESTROY_\SpecialChar \-
+OLD
+\family default
+ is used here, which causes the argv that is produced by the first invocation
+ of
+\family typewriter
+HX_getopt
+\family default
+ in the
+\family typewriter
+get_options
+\family default
+ function to be freed as it gets replaced by a new argv again by
+\family typewriter
+HX_getopt
+\family default
+ in
+\family typewriter
+get_cakes
+\family default
+\SpecialChar \slash{}
+
+\family typewriter
+get_fruit
+\family default
+.
+
+\family typewriter
+HXOPT_\SpecialChar \-
+DESTROY_\SpecialChar \-
+OLD
+\family default
+ is however
+\shape italic
+not
+\shape default
+ specified in the first invocation, because the initial argv resides on
+ the stack and cannot be freed.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+static bool
+\series default
+ get_cakes(
+\series bold
+int *
+\series default
+argc,
+\series bold
+const char ***
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption option_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ ...
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ HX_getopt(cake_table, argc, argv,
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static bool
+\series default
+ get_fruit(
+\series bold
+int *
+\series default
+argc,
+\series bold
+const char ***
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption fruit_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ ...
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ HX_getopt(fruit_table, argc, argv,
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_USAGEONERR | HXOPT_DESTROY_OLD) == HXOPT_ERR_SUCCESS;
+\begin_inset Newline newline
+\end_inset
+
+}
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+static bool
+\series default
+ get_options(
+\series bold
+int *
+\series default
+argc,
+\series bold
+const char ***
+\series default
+argv)
+\begin_inset Newline newline
+\end_inset
+
+{
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ cake = 0, fruit = 0;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption option_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.ln = "cake", .type = HXTYPE_NONE, .ptr = &cake},
+\begin_inset Newline newline
+\end_inset
+
+ {.ln = "fruit", .type = HXTYPE_NONE, .ptr = &fruit},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+ };
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (HX_getopt(option_table, argc, argv, HXOPT_PTHRU) !=
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_ERR_SUCCESS)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ false;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+if
+\series default
+ (cake)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ get_cakes(argc, argv);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+else if
+\series default
+ (fruit)
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ get_fruit(argc, argv);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+return
+\series default
+ false;
+\begin_inset Newline newline
+\end_inset
+
+}
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Shell-style configuration file parser
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:shconf"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+libHX provides functions to read shell-style configuration files.
+ Such files are common, for example, in
+\family typewriter
+/etc/sysconfig
+\family default
+ on Linux systems.
+ The format is pretty basic; it only knows about
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+key=value
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ pairs and does not even have sections like INI files.
+ Not relying on any features however makes them quite interchangable as
+ the syntax is accepted by Unix Shells.
+\end_layout
+
+\begin_layout Standard
+Lines beginning with a hash mark (
+\family typewriter
+#
+\family default
+) are ignored, as are empty lines and unrecognized keys.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+# Minimum / maximum values for automatic UID selection
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+UID_MIN=100
+\begin_inset Newline newline
+\end_inset
+
+UID_MAX=65000
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+# Home directory base
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+HOME="/home"
+\begin_inset Newline newline
+\end_inset
+
+#HOME="/export/home"
+\end_layout
+
+\begin_layout Standard
+Any form of variable or parameter substitution or expansion is highly implementa
+tion specific, and is not supported in libHX's reader.
+ Even Shell users should not rely on it as you never know in which context
+ the configuration files are evaluated.
+ Still, you will have to escape specific sequences like you would need to
+ in Shell.
+ The use of single quotes is acceptable.
+ That means:
+\end_layout
+
+\begin_layout LyX-Code
+AMOUNT="US
+\backslash
+$5"
+\begin_inset Newline newline
+\end_inset
+
+AMOUNT='US$5'
+\end_layout
+
+\begin_layout Subsection
+Synopsis
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/option.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/option.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_shconfig(
+\series bold
+const char *
+\series default
+file,
+\series bold
+const struct
+\series default
+ HXoption
+\series bold
+*
+\series default
+table);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_shconfig
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_shconfig_pv(
+\series bold
+const char **
+\series default
+path_vec,
+\series bold
+const char *
+\series default
+file,
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ HXoption
+\series bold
+*
+\series default
+table,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_shconfig_pv
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXmap
+\series bold
+*
+\series default
+HX_shconfig_map(
+\series bold
+const char *
+\series default
+file);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_shconfig_map
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The shconfig parser reuses
+\family typewriter
+struct HXoption
+\family default
+ that fits very well in specifying name-pointer associations.
+
+\family typewriter
+HX_shconfig
+\family default
+ will read the given file using the key-to-pointer mappings from the table
+ to store the variable contents.
+ Of
+\family typewriter
+struct HXoption
+\family default
+, described in section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-synopsis"
+
+\end_inset
+
+, only the
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+ln
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+,
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+type
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ and
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+ptr
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ fields are used.
+ The list of accepted types is described in section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:option-types"
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Standard
+To parse a file, call
+\family typewriter
+HX_shconfig
+\family default
+ function with the corresponding parameters.
+ If you want to read configuration files from different paths, i.
+\begin_inset space \thinspace{}
+\end_inset
+
+e.
+\begin_inset space \space{}
+\end_inset
+
+to build up on default values, you can use
+\family typewriter
+HX_shconfig_pv
+\family default
+
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+pv = path vector
+\end_layout
+
+\end_inset
+
+, which is a variant for reading a file from multiple locations.
+ Its purpose is to facilitate reading system-wide settings which are then
+ overriden by a file in the users home directory, for example (per-setting-overr
+ide).
+ It is also possible to do per-file-override, that is, a file in the home
+ directory has higher precedence than a system-wide one in such a way that
+ the system-wide configuration file is not even read.
+ This is accomplished by traversing the paths in the
+\begin_inset Quotes eld
+\end_inset
+
+other
+\begin_inset Quotes erd
+\end_inset
+
+ direction (actually you have to turn the array around) and stopping at
+ the first existing file by use of the
+\family typewriter
+SHCONF_\SpecialChar \-
+ONE
+\family default
+ flag.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+HX_shconfig_map
+\family default
+ will return all entries from the file in a HXmap, usable for parsing arbitrary
+ keys without having to specify any static key table.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+SHCONF_ONE
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+SHCONF_ONE
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Parsing files will stop after one file has been successfully parsed.
+ This allows for a
+\begin_inset Quotes eld
+\end_inset
+
+personal overrides system config
+\begin_inset Quotes erd
+\end_inset
+
+ style.
+\end_layout
+
+\begin_layout Standard
+The call to
+\family typewriter
+HX_shconfig
+\family default
+ will either return >0 for success, 0 for no success (actually, this is
+ never returned) and
+\family typewriter
+-errno
+\family default
+ for an error.
+\end_layout
+
+\begin_layout Subsection
+Example
+\end_layout
+
+\begin_layout Subsubsection
+Per-setting-override
+\end_layout
+
+\begin_layout Standard
+This example sources key-value pairs from a configuration file in a system
+ location (
+\family typewriter
+/etc
+\family default
+) first, before overriding specific keys with new values from the file in
+ the home directory.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+long
+\series default
+ uid_min, uid_max;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+passwd_file;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXoption options_table
+\series bold
+[]
+\series default
+ = {
+\begin_inset Newline newline
+\end_inset
+
+ {.ln = "UID_MIN", .type = HXTYPE_LONG, .ptr = &uid_min},
+\begin_inset Newline newline
+\end_inset
+
+ {.ln = "UID_MAX", .type = HXTYPE_LONG, .ptr = &uid_max},
+\begin_inset Newline newline
+\end_inset
+
+ {.ln = "PWD_FILE", .type = HXTYPE_STRING, .ptr = &passwd_file},
+\begin_inset Newline newline
+\end_inset
+
+ HXOPT_TABLEEND,
+\begin_inset Newline newline
+\end_inset
+
+};
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+home = getenv("HOME");
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+paths
+\series bold
+[]
+\series default
+ = {"/etc", home, NULL};
+\begin_inset Newline newline
+\end_inset
+
+HX_shconfig(paths, "test.cf", options_table, 0);
+\end_layout
+
+\begin_layout Subsubsection
+Per-file-override
+\end_layout
+
+\begin_layout Standard
+This particular example reads from the file in the home directory first
+ (if it exists), but stops after it has been successfull, so any subsequent
+ locations listed in the
+\family typewriter
+paths
+\family default
+ variable are not read.
+ This has the effect that the file from the home directory has the highest
+ priority too like in the previous example, but without any keys from the
+ system files.
+ Note the
+\family typewriter
+SHCONF_ONE
+\family default
+ flag.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+const char *
+\series default
+home = getenv("HOME");
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+paths
+\series bold
+[]
+\series default
+ = {home, "/usr/local/etc", "/etc", NULL};
+\begin_inset Newline newline
+\end_inset
+
+HX_shconfig_pv(paths, "test.cf", options_table, SHCONF_ONE);
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Part
+Systems-related components
+\end_layout
+
+\begin_layout Section
+Random numbers
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:random"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsection
+Function overview
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/misc.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/misc.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HX_rand(
+\series bold
+void
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_rand
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ HX_irand(
+\series bold
+unsigned int
+\series default
+ min,
+\series bold
+unsigned int
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_irand
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+double
+\series default
+ HX_drand(
+\series bold
+double
+\series default
+ min,
+\series bold
+double
+\series default
+ max);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_drand
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_rand
+\family default
+ Retrieve the next random number.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_irand
+\family default
+ Retrieve the next random number and fold it so that
+\begin_inset Formula $\textit{min}\le n<\textit{max}$
+\end_inset
+
+, where min and max are unsigned integers.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HX_drand
+\family default
+ Retrieve the next random number and fold it so that
+\begin_inset Formula $\textit{min}\le n<\textit{max}$
+\end_inset
+
+, where min and max are double-precision floating point numbers.
+\end_layout
+
+\begin_layout Subsection
+Implementation information
+\end_layout
+
+\begin_layout Standard
+On systems that provide operating system-level random number generators,
+ predominantly Linux and Unix-alikes such as BSD and Solaris, these will
+ be used when they are available and random numbers are requested through
+
+\family typewriter
+HX_rand
+\family default
+ or
+\family typewriter
+HX_irand
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+On Linux, Solaris and the BSDs, this is
+\family typewriter
+/dev/urandom
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+/dev/urandom
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Standard
+If no random number generating device is available (and libHX configured
+ to use it), it will fall back to using the libc's
+\family typewriter
+rand
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+rand
+\end_layout
+
+\end_inset
+
+ function.
+ If libc is selected for random number generation,
+\family typewriter
+srand
+\family default
+ will be called on library initialization with what is believed to be good
+ defaults
+\begin_inset space ~
+\end_inset
+
+--- usually this will be before a program's
+\family typewriter
+main
+\family default
+ function with normal linking, but may actually happen later when used with
+
+\family typewriter
+dlopen
+\family default
+.
+ The initial seed would be the current microtime when
+\family typewriter
+gettimeofday
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+gettimeofday
+\end_layout
+
+\end_inset
+
+
+\family default
+ is available, or just the seconds with
+\family typewriter
+time
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+time
+\end_layout
+
+\end_inset
+
+.
+ To counter the problem of different programs potentially using the same
+ seed within a time window of a second due to the limited granularity of
+ standard
+\family typewriter
+time
+\family default
+, the seed is augmented by process ID and parent process ID where available.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+/dev/random
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+/dev/random
+\end_layout
+
+\end_inset
+
+
+\family default
+ is not used on Linux because it may block during read, and
+\family typewriter
+/dev/urandom
+\family default
+ is just as good when there is entropy available.
+ If you need definitive PRNG
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+PRNG
+\end_layout
+
+\end_inset
+
+ security, perhaps use one from a crypto suite such as OpenSSL.
+\end_layout
+
+\begin_layout Standard
+\begin_inset Newpage clearpage
+\end_inset
+
+
+\end_layout
+
+\begin_layout Section
+Process management
+\begin_inset CommandInset label
+LatexCommand label
+name "sec:proc"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The process code is experimental at this stage (just moved from the pam_mount
+ codebase).
+ As it also relies on the POSIX functions
+\family typewriter
+fork
+\family default
+,
+\family typewriter
+execv
+\family default
+,
+\family typewriter
+execvp
+\family default
+ and
+\family typewriter
+pipe
+\family default
+(2), so it may not be available everywhere.
+ Where this is the case, the functions will return
+\family typewriter
+-ENOSYS
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+Process metadata structure
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/proc.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/proc.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXproc {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const struct
+\series default
+ HXproc_ops
+\series bold
+*
+\series default
+p_ops;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void *
+\series default
+p_data;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned int
+\series default
+ p_flags;
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+Following members should only be read
+\family default
+\series bold
+\shape default
+ */
+\series default
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ p_stdin, p_stdout, p_stderr;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ p_pid;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char
+\series default
+ p_status;
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ p_exited, p_terminated;
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Standard
+When creating a new process with the intent of running it asynchronously
+ (using
+\family typewriter
+HXproc_\SpecialChar \-
+run_\SpecialChar \-
+async
+\family default
+), the first three fields must be filled in by the user.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_ops
+\family default
+ A table of callbacks, generally used for setting and/or restoring signals
+ before/after execution.
+ This member may be
+\family typewriter
+NULL
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_data
+\family default
+ Free pointer for the user to supply.
+ Will be passed to the callback functions when they are invoked.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_flags
+\family default
+ Process creation flags, see below.
+\end_layout
+
+\begin_layout Standard
+After the subprocess has been started,
+\family typewriter
+HXproc_run_async
+\family default
+ will have filled in some fields:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_stdin
+\family default
+ If
+\family typewriter
+HXPROC_STDIN
+\family default
+ was specified in
+\family typewriter
+p_flags
+\family default
+,
+\family typewriter
+p_stdin
+\family default
+ will be assigned the write side file descriptor of the subprocess's to-be
+ stdin.
+ The subprocess will get the read side file descriptor in this member.
+ This is so that the correct fd is used in when
+\family typewriter
+p_ops->p_postfork
+\family default
+ is called.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_stdout
+\family default
+ If
+\family typewriter
+HXPROC_STDOUT
+\family default
+ is specified in
+\family typewriter
+p_flags
+\family default
+,
+\family typewriter
+p_stdout
+\family default
+ will be assigned the read side file descriptor of the subprocess's to-be
+ stdout.
+ The subprocess will get the write side file descriptor in this member.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_stderr
+\family default
+ If
+\family typewriter
+HXPROC_STDERR
+\family default
+ is specified in
+\family typewriter
+p_flags
+\family default
+,
+\family typewriter
+p_stderr
+\family default
+ will be assigned the read side file descriptor of the subprocess's to-be
+ stderr, and the subprocess will get the write side fd.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_pid
+\family default
+ The process ID of the spawned process.
+\end_layout
+
+\begin_layout Standard
+Upon calling
+\family typewriter
+HXproc_wait
+\family default
+, further fields will have been filled when the function returns:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_exited
+\family default
+ Whether the process exited normally (cf.
+\begin_inset space \space{}
+\end_inset
+
+signalled\SpecialChar \slash{}
+terminated).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_terminated
+\family default
+ Whether the process was terminated (signalled).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_status
+\family default
+ The exit status of the process or the termination signal.
+\end_layout
+
+\begin_layout Subsubsection
+Flags
+\begin_inset CommandInset label
+LatexCommand label
+name "sub:proc-pflags"
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+Possible values for the
+\family typewriter
+p_flags
+\family default
+ member are:
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_STDIN
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_STDIN
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ The subprocess's stdin file descriptor shall be connected to the master
+ program, that is, not inherit the stdin of the master.
+ Cannot be used for
+\family typewriter
+HXproc_\SpecialChar \-
+run_\SpecialChar \-
+sync
+\family default
+ (because there would be no one to provide data in a sync operation).
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_STDOUT
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXPROC_STDOUT
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Connect the stdout file descriptor of the subprocess with the master.
+ Cannot be used for
+\family typewriter
+HXproc_run_sync
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_STDERR
+\series medium
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\series medium
+HXPROC_STDERR
+\end_layout
+
+\end_inset
+
+
+\family default
+\series default
+ Connect the stderr file descriptor of the subprocess with the master.
+ Cannot be used for
+\family typewriter
+HXproc_run_sync
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_NULL_STDIN
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_NULL_STDIN
+\end_layout
+
+\end_inset
+
+ The subprocess's stdin file descriptor shall be connected to
+\family typewriter
+/dev\SpecialChar \slash{}
+null
+\family default
+.
+
+\family typewriter
+HXPROC_\SpecialChar \-
+STDIN
+\family default
+ and
+\family typewriter
+HXPROC_\SpecialChar \-
+NULL_\SpecialChar \-
+STDIN
+\family default
+ are mutually exclusive.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_NULL_STDOUT
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_NULL_STDOUT
+\end_layout
+
+\end_inset
+
+ Connect the stdout file descriptor of the subprocess to
+\family typewriter
+/dev\SpecialChar \slash{}
+null
+\family default
+, thereby essentially discarding its output.
+
+\family typewriter
+HXPROC_\SpecialChar \-
+STDOUT
+\family default
+ and
+\family typewriter
+HXPROC_\SpecialChar \-
+NULL_\SpecialChar \-
+STDOUT
+\family default
+ are mutuall exclusive.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_NULL_STDERR
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_NULL_STDERR
+\end_layout
+
+\end_inset
+
+ Connect the stderr file descriptor of the subprocess to
+\family typewriter
+/dev\SpecialChar \slash{}
+null
+\family default
+, thereby essentially discarding its output.
+
+\family typewriter
+HXPROC_\SpecialChar \-
+STDERR
+\family default
+ and
+\family typewriter
+HXPROC_\SpecialChar \-
+NULL_\SpecialChar \-
+STDERR
+\family default
+ are mutually exclusive.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_VERBOSE
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_VERBOSE
+\end_layout
+
+\end_inset
+
+ Have the subprocess print an error message to stderr if exec'ing returned
+ an error.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_A0
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_A0
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+argv[0]
+\family default
+ refers to program file, while
+\family typewriter
+argv[1]
+\family default
+ to the program invocation name, with
+\family typewriter
+argv[2]
+\family default
+ being the arguments.
+ Without this flag,
+\family typewriter
+argv[0]
+\family default
+ will be both the program file and program invocation name, and arguments
+ begin at
+\family typewriter
+argv[1]
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXPROC_EXECV
+\family default
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HXPROC_EXECV
+\end_layout
+
+\end_inset
+
+ Normally,
+\family typewriter
+execvp
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+execvp
+\end_layout
+
+\end_inset
+
+ will be used which scans
+\family typewriter
+$PATH
+\family default
+ for the program.
+ Use this flag to use
+\family typewriter
+execv
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+execv
+\end_layout
+
+\end_inset
+
+ instead, which will not do such thing.
+\end_layout
+
+\begin_layout Subsection
+Callbacks
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/proc.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+struct
+\series default
+ HXproc_ops {
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+p_prefork
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+p_postfork
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+void (*
+\series default
+p_complete
+\series bold
+)
+\series default
+(
+\series bold
+void *
+\series default
+);
+\begin_inset Newline newline
+\end_inset
+
+};
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+struct HXproc_ops
+\family default
+ provides a way to run user-specified functions just before the fork, after,
+ and when the process has been waited for.
+ They can be used to set and/or restore signals as needed, for example.
+ The function pointers can be
+\family typewriter
+NULL
+\family default
+.
+ The
+\family typewriter
+p_data
+\family default
+ member is passed as an argument.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_prefork
+\family default
+ Run immediately before calling
+\family typewriter
+fork
+\family default
+(2).
+ This is useful, for taking any action regarding signals, like setting
+\family typewriter
+SIGCHLD
+\family default
+ to
+\family typewriter
+SIG_DFL
+\family default
+, or
+\family typewriter
+SIGPIPE
+\family default
+ to
+\family typewriter
+SIG_IGN
+\family default
+, for example.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_postfork
+\family default
+ Run in the subprocess (and only there) after forking.
+ Useful to do a
+\family typewriter
+setuid
+\family default
+(2) or other change in privilege level.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+p_complete
+\family default
+ Run in
+\family typewriter
+HXproc_wait
+\family default
+ when the process has been waited for.
+ Useful to restore the signal handler(s).
+\end_layout
+
+\begin_layout Subsection
+Process control
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/proc.h>
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+
+\begin_inset Newline newline
+\end_inset
+
+int
+\series default
+ HXproc_run_async(
+\series bold
+const char *const *
+\series default
+argv,
+\series bold
+struct
+\series default
+ HXproc
+\series bold
+*
+\series default
+proc);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXproc_run_async
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HXproc_run_sync(
+\series bold
+const char *const *
+\series default
+argv,
+\series bold
+unsigned int
+\series default
+ flags);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXproc_run_sync
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ HXproc_wait(
+\series bold
+struct
+\series default
+ HXproc
+\series bold
+*
+\series default
+proc);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HXproc_wait
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXproc_run_async
+\family default
+ Start a subprocess according to the parameters in
+\family typewriter
+proc
+\family default
+.
+ Returns a negative errno code if something went wrong, or positive non-zero
+ on success.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXproc_run_sync
+\family default
+ Start a subprocess synchronously, similar to calling
+\family typewriter
+system
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+system
+\end_layout
+
+\end_inset
+
+, but with the luxury of being able to specify arguments as separate strings
+ (via argv) rather than one big command line that is run through the shell.
+
+\family typewriter
+flags
+\family default
+ is a value composed of the HXproc flags mentioned above in section
+\begin_inset space ~
+\end_inset
+
+
+\begin_inset CommandInset ref
+LatexCommand ref
+reference "sub:proc-pflags"
+
+\end_inset
+
+.
+
+\family typewriter
+HXPROC_STDIN
+\family default
+,
+\family typewriter
+HXPROC_STDOUT
+\family default
+ and
+\family typewriter
+HXPROC_STDERR
+\family default
+ are ignored because there would be no one in a synchronous execution that
+ could supply data to these file descriptors or read from them
+\begin_inset Foot
+status open
+
+\begin_layout Plain Layout
+Even for threads, please just use the async model.
+\end_layout
+
+\end_inset
+
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+HXproc_wait
+\family default
+ Wait for a subprocess to terminate, if it has not already.
+ It will also retrieve the exit status of the process and store it in the
+
+\family typewriter
+struct HXproc
+\family default
+.
+\end_layout
+
+\begin_layout Standard
+Return value will be positive non-zero on success, or negative on error.
+ Underlying system function's errors are returned, plus:
+\end_layout
+
+\begin_layout Description
+
+\family sans
+EINVAL
+\family default
+ Flags were not accepted.
+\end_layout
+
+\begin_layout Section
+Helper headers
+\end_layout
+
+\begin_layout Subsection
+ctype helpers
+\end_layout
+
+\begin_layout Standard
+Functions from the
+\family typewriter
+<ctype.h>
+\family default
+ header, including, but not limited to,
+\family typewriter
+isalpha
+\family default
+,
+\family typewriter
+tolower
+\family default
+, and so forth, are defined to take an
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+int
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ as first argument.
+ Strings used in C programs are usually
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+, without any
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+signed
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ or
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+unsigned
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ qualifier.
+ By a high-level view, which also matches daily common sense, characters
+ (a.
+\begin_inset space \thinspace{}
+\end_inset
+
+k.
+\begin_inset space \thinspace{}
+\end_inset
+
+a.
+\begin_inset space \space{}
+\end_inset
+
+letters) have no notion of signedness
+\begin_inset space ~
+\end_inset
+
+--- there is no
+\begin_inset Quotes eld
+\end_inset
+
+positive
+\begin_inset Quotes erd
+\end_inset
+
+ or
+\begin_inset Quotes eld
+\end_inset
+
+negative
+\begin_inset Quotes erd
+\end_inset
+
+
+\begin_inset Quotes eld
+\end_inset
+
+A
+\begin_inset Quotes erd
+\end_inset
+
+ in at least the Latin alphabet that is mapped into the ASCII set.
+ In fact,
+\family typewriter
+char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ could either be
+\family typewriter
+signed char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+ or
+\family typewriter
+unsigned char
+\begin_inset space ~
+\end_inset
+
+*
+\family default
+, depending on the compiler settings.
+ Only when you start interpreting and using characters as a number does
+ such become important.
+
+\end_layout
+
+\begin_layout Standard
+There come the problems.
+ Characters are in the same class as numbers in C, that is, can be implicitly
+ converted from or to a
+\begin_inset Quotes eld
+\end_inset
+
+number
+\begin_inset Quotes erd
+\end_inset
+
+ (in this case, their ASCII code point) without causing a compiler warning.
+ That may be practical in some cases, but is also a bit
+\begin_inset Quotes eld
+\end_inset
+
+unfortunate
+\begin_inset Quotes erd
+\end_inset
+
+.
+ Characters, when interpreted as the 8-bit signed numeric quantity they
+ are implicitly convertable to, run from 0 to 127 and \SpecialChar \nobreakdash-
+128 to \SpecialChar \nobreakdash-
+1.
+ Since the
+\family typewriter
+isalpha
+\family default
+ function and others from
+\family typewriter
+ctype.h
+\family default
+ take a (signed)
+\family typewriter
+int
+\family default
+ as argument means that values fed to
+\family typewriter
+isalpha
+\family default
+ are sign-extended, preserving negative values.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+/*
+\family roman
+\series default
+\shape italic
+
+\begin_inset Quotes eld
+\end_inset
+
+hyvää yötä
+\begin_inset Quotes erd
+\end_inset
+
+, UTF-8 encoded
+\family default
+\series bold
+\shape default
+ */
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+const char
+\series default
+h
+\series bold
+[]
+\series default
+ = {'h', 'y', 'v', 0xc3, 0xa4, 0xc3, 0xa4, ' ',
+\begin_inset Newline newline
+\end_inset
+
+ 'y', 0xc3, 0xb6, 't', 0xc3, 0xa4};
+\end_layout
+
+\begin_layout Standard
+When you now pass
+\family typewriter
+h[3]
+\family default
+ to
+\family typewriter
+isalpha
+\family default
+ for example (regardless of whether doing so actually produces a meaningful
+ result), the CPU is instructed to copy
+\begin_inset Quotes eld
+\end_inset
+
+0xc3
+\begin_inset Quotes erd
+\end_inset
+
+ into a register and sign-extend it (because
+\begin_inset Quotes eld
+\end_inset
+
+char
+\begin_inset Quotes erd
+\end_inset
+
+ is often
+\begin_inset Quotes eld
+\end_inset
+
+signed char
+\begin_inset Quotes erd
+\end_inset
+
+, see above), producing 0xffffffc3 (\SpecialChar \nobreakdash-
+61).
+ But passing \SpecialChar \nobreakdash-
+61 is not what was intended.
+\end_layout
+
+\begin_layout Standard
+libHX's
+\family typewriter
+ctype_helper.h
+\family default
+ therefore provides wrappers with a different function signature that uses
+ zero extension (not sign extension) by means of using an
+\family typewriter
+unsigned
+\family default
+ quantity.
+ Currently this is
+\family typewriter
+ unsigned char
+\family default
+, because
+\family typewriter
+isalpha
+\family default
+'s domain only goes from 0--255.
+ The implication is that you cannot pass
+\family typewriter
+EOF
+\family default
+ to
+\family typewriter
+HX_isalpha
+\family default
+.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/ctype_helper.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/ctype_helper.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isalnum(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_isalnum
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isalpha(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_isalpha
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isdigit(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_isdigit
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_islower(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_islower
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isprint(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_isprint
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isspace(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_isspace
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isupper(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+HX_isupper
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+bool
+\series default
+ HX_isxdigit(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_isxdigit
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned char
+\series default
+ HX_tolower(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_tolower
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+unsigned char
+\series default
+ HX_toupper(
+\series bold
+unsigned char
+\series default
+ c);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+HX_toupper
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The
+\family typewriter
+is*
+\family default
+ functions also differ from ctype's in that they return
+\family typewriter
+bool
+\family default
+ instead of
+\family typewriter
+int
+\family default
+.
+ Not all functions from
+\family typewriter
+ctype.h
+\family default
+ are present either;
+\family typewriter
+isascii
+\family default
+,
+\family typewriter
+isblank
+\family default
+,
+\family typewriter
+iscntrl
+\family default
+,
+\family typewriter
+isgraph
+\family default
+,
+\family typewriter
+ispunct
+\family default
+ and
+\family typewriter
+isxdigit
+\family default
+ have been omitted as the author has never needed them so far.
+\end_layout
+
+\begin_layout Subsection
+libxml2 helpers
+\end_layout
+
+\begin_layout Standard
+libxml2 uses an
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+xmlChar
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+ type as an underlying type for the strings that it reads and outputs.
+
+\family typewriter
+xmlChar
+\family default
+ is typedef'ed to
+\family typewriter
+unsigned char
+\family default
+ by libxml2, causing compiler warnings related to differing signedness whenever
+ interacting with strings from the outside world, which are usually just
+ a pointer to
+\family typewriter
+char
+\family default
+.
+ Because casting would be a real chore,
+\family typewriter
+libxml_helper.h
+\family default
+ will do it by providing some wrappers with better argument types.
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/libxml_helper.h>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/libxml_helper.h
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ xml_strcmp(
+\series bold
+const
+\series default
+ xmlChar
+\series bold
+*
+\series default
+a,
+\series bold
+const char *
+\series default
+b);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xml_strcmp
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+int
+\series default
+ xml_strcasecmp(
+\series bold
+const
+\series default
+ xmlChar
+\series bold
+*
+\series default
+a,
+\series bold
+const char *
+\series default
+b);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xml_strcasecmp
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+char *
+\series default
+xml_getprop(xmlNode
+\series bold
+*
+\series default
+node,
+\series bold
+const char *
+\series default
+attr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xml_getprop
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+char *xml_getnsprop(
+\series bold
+xmlNode *
+\series default
+node,
+\series bold
+const char *
+\series default
+nsprefix,
+\series bold
+const char *
+\series default
+attr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+xml_getnsprop
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+xmlAttr
+\series bold
+*
+\series default
+xml_newprop(xmlNode
+\series bold
+*
+\series default
+node,
+\series bold
+const char *
+\series default
+attr);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xml_newprop
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+xmlNode
+\series bold
+*
+\series default
+xml_newnode(xmlNode
+\series bold
+*
+\series default
+parent,
+\series bold
+const char *
+\series default
+name,
+\series bold
+const char *
+\series default
+value);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+xml_newnode
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+xmlAttr
+\series bold
+*
+\series default
+xml_setprop(xmlNode
+\series bold
+*
+\series default
+node,
+\series bold
+const char *
+\series default
+name,
+\series bold
+const char *
+\series default
+value);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+\size normal
+\color none
+xml_setprop
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Standard
+The functions map to
+\family typewriter
+strcmp
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strcmp
+\end_layout
+
+\end_inset
+
+,
+\family typewriter
+strcasecmp
+\family default
+(3)
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+strcasecmp
+\end_layout
+
+\end_inset
+
+,
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xmlGetProp
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+xmlGetProp
+\family default
+,
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xmlNewProp
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+xmlNewProp
+\family default
+,
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xmlNewTextNode
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+xml\SpecialChar \-
+New\SpecialChar \-
+Text\SpecialChar \-
+Node
+\family default
+ and
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+xmlSetProp
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+xml\SpecialChar \-
+Set\SpecialChar \-
+Prop
+\family default
+, respectively.
+\end_layout
+
+\begin_layout Standard
+
+\family typewriter
+xml_getnsprop
+\family default
+ works similar to
+\family typewriter
+xmlGetNsProp
+\family default
+, but instead of taking a namespace URI, it does a lookup by namespace prefix.
+ The argument order is also different compared to
+\family typewriter
+xmlGetNsProp
+\family default
+.
+\end_layout
+
+\begin_layout Subsection
+wxWidgets
+\end_layout
+
+\begin_layout LyX-Code
+
+\series bold
+#include
+\series default
+ <libHX/wx_helper.hpp>
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+libHX/wx_helper.hpp
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Subsubsection
+Shortcut macros
+\end_layout
+
+\begin_layout Description
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxACV
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxACV
+\family default
+ Expands to
+\family typewriter
+
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxALIGN_CENTER_VERTICAL
+\end_layout
+
+\end_inset
+
+wxALIGN_CENTER_VERTICAL
+\end_layout
+
+\begin_layout Description
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxCDF
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxCDF
+\family default
+ Expands to a set of common dialog flags for
+\family typewriter
+wxDialog
+\family default
+s, which includes
+\family typewriter
+wxDEFAULT_\SpecialChar \-
+FRAME_\SpecialChar \-
+STYLE
+\family default
+ and a flag such that the dialog does not create a new window in the task
+ bar (
+\family typewriter
+wxFRAME_\SpecialChar \-
+NO_\SpecialChar \-
+TASKBAR
+\family default
+).
+\end_layout
+
+\begin_layout Description
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDPOS
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDPOS
+\family default
+ Expands to
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDefaultPosition
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDefaultPosition
+\family default
+.
+\end_layout
+
+\begin_layout Description
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDSIZE
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDSIZE
+\family default
+ Expands to
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDefaultSize
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDefaultSize
+\family default
+.
+\end_layout
+
+\begin_layout Description
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDSPAN
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDSPAN
+\family default
+ Expands to
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxDefaultSpan
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxDefaultSpan
+\family default
+.
+\end_layout
+
+\begin_layout Subsubsection
+String conversion
+\end_layout
+
+\begin_layout LyX-Code
+wxString wxfu8(
+\series bold
+const char *
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxfu8
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+wxString wxfv8(
+\series bold
+const char *
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxfv8
+\end_layout
+
+\end_inset
+
+
+\begin_inset Newline newline
+\end_inset
+
+
+\series bold
+const char *
+\series default
+wxtu8(
+\series bold
+const
+\series default
+ wxString
+\series bold
+&
+\series default
+);
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxtu8
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+wxfu8
+\family default
+ Converts an UTF-8 string to a
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxString
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxString
+\family default
+ object.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+wxfv8
+\family default
+ Converts an UTF-8 string to an entity usable by
+\begin_inset Index idx
+status open
+
+\begin_layout Plain Layout
+
+\family typewriter
+wxPrintf
+\end_layout
+
+\end_inset
+
+
+\family typewriter
+wxPrintf
+\family default
+.
+\end_layout
+
+\begin_layout Description
+
+\family typewriter
+wxtu8
+\family default
+ Converts a wxString to a pointer to char usable by
+\family typewriter
+printf
+\family default
+.
+ Note that the validity of the pointer is very limited and usually does
+ not extend the statement in which it is used.
+ Hence storing the pointer in a variable (
+\begin_inset Quotes eld
+\end_inset
+
+
+\family typewriter
+const char *p = wxtu8(s);
+\family default
+
+\begin_inset Quotes erd
+\end_inset
+
+) will make
+\family typewriter
+p
+\family default
+ pointing to an invalid region as soon as the assignment is done.
+\end_layout
+
+\begin_layout Part
+\start_of_appendix
+Appendix
+\end_layout
+
+\begin_layout Standard
+\begin_inset CommandInset index_print
+LatexCommand printindex
+type "idx"
+
+\end_inset
+
+
+\end_layout
+
+\end_body
+\end_document
diff --git a/doc/libHX_Documentation.pdf b/doc/libHX_Documentation.pdf
new file mode 100644
index 0000000..0a1f6fb
--- /dev/null
+++ b/doc/libHX_Documentation.pdf
Binary files differ
diff --git a/doc/slurp.c b/doc/slurp.c
new file mode 100644
index 0000000..f0b047d
--- /dev/null
+++ b/doc/slurp.c
@@ -0,0 +1,38 @@
+static void *p_slurp(const char *file, size_t *outsize)
+{
+ struct stat sb;
+ int ret = 0, fd = open(file, O_RDONLY | O_BINARY);
+ void *buf = NULL;
+ ssize_t rdret;
+
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: Slurping %s failed: %s\n",
+ file, strerror(errno));
+ return NULL;
+ }
+ if (fstat(fd, &buf) < 0) {
+ ret = errno;
+ perror("fstat");
+ goto out;
+ }
+ *outsize = sb.st_size; /* truncate if need be */
+ buf = malloc(*outsize);
+ if (buf == NULL) {
+ ret = errno;
+ perror("malloc");
+ goto out;
+ }
+ rdret = read(fd, buf, *outsize);
+ if (rdret < 0) {
+ ret = errno;
+ perror("read");
+ free(buf);
+ } else {
+ *outsize = rdret;
+ }
+ out:
+ close(fd);
+ errno = ret;
+ return buf;
+}
+
diff --git a/doc/ux-file.txt b/doc/ux-file.txt
new file mode 100644
index 0000000..2f32247
--- /dev/null
+++ b/doc/ux-file.txt
@@ -0,0 +1,30 @@
+===============================================================================
+ux-file - Unix compatibility functions 2006-02-25
+
+
+DESCRIPTION
+
+ libHX provides some dummy Unix functions for platforms where they are not
+ available. They mostly return -ENOSYS.
+
+
+SYNOPSIS
+
+ #include <libHX.h>
+
+ int chown(const char *PATH, long UID, long GID);
+ int fchmod(int FD, long PERM);
+ int fchown(int FD, long UID, long GID);
+ int lchown(const char *PATH, long UID, long GID);
+ int lstat(const char *PATH, struct stat *SB);
+ int mkfifo(const char *PATH, long MODE);
+ int mknod(const char *PATH, long MODE, long DEV);
+ int readlink(const char *PATH, char *DEST, size_t LEN);
+ int symlink(const char *SRC, const char *DEST);
+
+
+lstat()
+
+ Maps to stat() under Win32.
+
+===============================================================================
diff --git a/doc/ux-mmap.txt b/doc/ux-mmap.txt
new file mode 100644
index 0000000..43f5ac9
--- /dev/null
+++ b/doc/ux-mmap.txt
@@ -0,0 +1,26 @@
+===============================================================================
+ux-mmap - Unix compatibility functions 2006-02-25
+
+
+DESCRIPTION
+
+ libHX provides a Linux-style mmap() function for Win32.
+
+
+SYNOPSIS
+
+ #include <libHX.h>
+
+ void *mmap(void *START, size_t LENGTH, int PROT, int FLAGS, int FD,
+ off_t OFFSET);
+
+
+mmap()
+
+ See the Linux manual page mmap(2) for details. Many flags described in
+ mmap(2) do not work. What does work: PROT_NONE, PROT_READ, PROT_WRITE,
+ PROT_EXEC (only WinPX SP2 or WinServer2003 SP1 or up), MAP_SHARED and
+ MAP_PRIVATE. MAP_SHARED is the default if no MAP_PRIVATE is given.
+
+
+===============================================================================