summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.in311
-rw-r--r--config.project50
-rw-r--r--config.usage79
-rwxr-xr-xconfigure467
-rw-r--r--include/slibtool/slibtool.h88
-rw-r--r--include/slibtool/slibtool_api.h35
-rw-r--r--project/arch.mk0
-rw-r--r--project/common.mk8
-rw-r--r--project/defs.mk44
-rw-r--r--project/depends.mk0
-rw-r--r--project/extras.mk3
-rw-r--r--project/headers.mk9
-rw-r--r--project/overrides.mk0
-rw-r--r--project/tree.mk8
-rw-r--r--src/driver/slbt_driver_ctx.c181
-rw-r--r--src/driver/slbt_unit_ctx.c62
-rw-r--r--src/internal/argv/argv.h1053
-rw-r--r--src/internal/slibtool_driver_impl.h31
-rw-r--r--src/logic/slbt_map_input.c51
-rw-r--r--src/skin/slbt_skin_default.c12
-rw-r--r--src/slibtool.c67
-rw-r--r--sysinfo/compiler/any-compiler.mk29
-rw-r--r--sysinfo/compiler/clang.mk31
-rw-r--r--sysinfo/compiler/cparser.mk31
-rw-r--r--sysinfo/compiler/gcc.mk24
-rw-r--r--sysinfo/host/any-host.mk7
-rwxr-xr-xsysinfo/host/host.sh82
-rw-r--r--sysinfo/host/i686-nt32-midipix.mk5
-rw-r--r--sysinfo/host/i686-unknown-linux.mk5
-rw-r--r--sysinfo/host/i686-w64-mingw32.mk5
-rw-r--r--sysinfo/host/native.mk45
-rw-r--r--sysinfo/host/x86_64-nt64-midipix.mk5
-rw-r--r--sysinfo/host/x86_64-unknown-linux.mk5
-rw-r--r--sysinfo/host/x86_64-w64-mingw32.mk5
-rw-r--r--sysinfo/os/any-os.mk10
-rw-r--r--sysinfo/os/bsd.mk10
-rw-r--r--sysinfo/os/darwin.mk12
-rw-r--r--sysinfo/os/linux.mk10
-rw-r--r--sysinfo/os/midipix.mk14
-rw-r--r--sysinfo/os/mingw.mk15
-rw-r--r--sysinfo/toolchain/binutils.mk17
-rw-r--r--sysinfo/toolchain/llvm.mk17
-rwxr-xr-xsysinfo/version.sh61
43 files changed, 3004 insertions, 0 deletions
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..bd47dfe
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,311 @@
+PACKAGE = @package@
+PROJECT_DIR = @project_dir@
+
+BUILD = @build@
+HOST = @host@
+TARGET = @target@
+ARCH = @arch@
+COMPILER = @compiler@
+TOOLCHAIN = @toolchain@
+SYSROOT = @sysroot@
+CROSS_COMPILE = @cross_compile@
+SHELL = @shell@
+
+CFLAGS_DEBUG = @cflags_debug@
+CFLAGS_COMMON = @cflags_common@
+CFLAGS_CMDLINE = @cflags_cmdline@
+CFLAGS_CONFIG = @cflags_config@
+CFLAGS_SYSROOT = @cflags_sysroot@
+CFLAGS_OS = @cflags_os@
+CFLAGS_SITE = @cflags_site@
+CFLAGS_PATH = @cflags_path@
+
+LDFLAGS_DEBUG = @ldflags_debug@
+LDFLAGS_COMMON = @ldflags_common@
+LDFLAGS_CMDLINE = @ldflags_cmdline@
+LDFLAGS_CONFIG = @ldflags_config@
+LDFLAGS_SYSROOT = @ldflags_sysroot@
+LDFLAGS_PATH = @ldflags_path@
+
+PE_SUBSYSTEM = @pe_subsystem@
+PE_IMAGE_BASE = @pe_image_base@
+PE_CONFIG_DEFS = @pe_config_defs@
+
+ELF_EH_FRAME = @elf_eh_frame@
+ELF_HASH_STYLE = @elf_hash_style@
+ELF_CONFIG_DEFS = @elf_config_defs@
+
+PREFIX = @prefix@
+BINDIR = @bindir@
+LIBDIR = @libdir@
+INCLUDEDIR = @includedir@
+SYSLIBDIR = @syslibdir@
+MANDIR = @mandir@
+DOCDIR = @docdir@
+LIBEXECDIR = @libexecdir@
+
+NATIVE_CC = @native_cc@
+NATIVE_OS = @native_os@
+NATIVE_OS_BITS = @native_os_bits@
+NATIVE_OS_UNDERSCORE = @native_os_underscore@
+
+USER_CC = @user_cc@
+USER_CPP = @user_cpp@
+USER_CXX = @user_cxx@
+
+
+all:
+install:
+shared:
+static:
+
+
+
+include $(PROJECT_DIR)/sysinfo/host/$(HOST).mk
+include $(PROJECT_DIR)/sysinfo/compiler/$(COMPILER).mk
+include $(PROJECT_DIR)/sysinfo/toolchain/$(TOOLCHAIN).mk
+
+include $(PROJECT_DIR)/project/defs.mk
+include $(PROJECT_DIR)/project/tree.mk
+include $(PROJECT_DIR)/project/depends.mk
+include $(PROJECT_DIR)/project/headers.mk
+include $(PROJECT_DIR)/project/common.mk
+include $(PROJECT_DIR)/project/arch.mk
+include $(PROJECT_DIR)/project/extras.mk
+include $(PROJECT_DIR)/project/overrides.mk
+
+
+
+$(APP_SRCS:%.c=%.o): version.tag
+$(APP_SRCS:%.c=%.o): CFLAGS_STATIC = $(CFLAGS_APP)
+
+src/%.lo: $(PROJECT_DIR)/src/%.c $(ALL_HEADERS) host.tag tree.tag
+ $(CC) -c -o $@ $< $(CFLAGS_SHARED)
+
+src/%.o: $(PROJECT_DIR)/src/%.c $(ALL_HEADERS) host.tag tree.tag
+ $(CC) -c -o $@ $< $(CFLAGS_STATIC)
+
+$(LIBDIR)/%$(OS_LIB_SUFFIX):
+ $(CC) -shared -o $@ $^ $(LDFLAGS_SHARED)
+
+$(LIBDIR)/%$(OS_ARCHIVE_EXT):
+ rm -f $@
+ $(AR) rcs $@ $^
+
+
+
+all: shared static app
+
+install: install-libs install-headers install-app
+
+app: default-app
+
+
+install-libs: install-shared install-static install-implib
+
+install-headers:shared static
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(INCLUDEDIR)/$(PACKAGE)
+ cp $(API_HEADERS) $(DESTDIR)///./$(PREFIX)/./$(INCLUDEDIR)/$(PACKAGE)
+
+install-shared: shared install-implib
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+ cp $(SHARED_LIB) $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+
+install-static: static
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+ cp $(STATIC_LIB) $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+
+install-app: app
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(BINDIR)
+ cp $(APP) $(DESTDIR)///./$(PREFIX)/./$(BINDIR)
+
+
+
+shared: shared-lib shared-implib
+
+static: static-lib
+
+shared-lib: shared-objs $(SHARED_LIB)
+
+static-lib: static-objs $(STATIC_LIB)
+
+shared-implib: shared-lib
+
+
+
+default-app: version.tag static $(DEFAULT_APP) $(APP)
+
+shared-app: version.tag shared $(SHARED_APP)
+
+static-app: version.tag static $(STATIC_APP)
+
+
+
+shared-objs: dirs $(SHARED_OBJS)
+
+static-objs: dirs $(STATIC_OBJS)
+
+app-objs: dirs $(APP_OBJS)
+
+
+
+$(SHARED_LIB): $(SHARED_OBJS)
+
+$(STATIC_LIB): $(STATIC_OBJS)
+
+$(APP): $(DEFAULT_APP)
+ cp $^ $@
+
+$(DEFAULT_APP): $(STATIC_OBJS) $(APP_OBJS)
+ $(CC) -o $@ $^ $(LDFLAGS_APP)
+
+$(SHARED_APP): $(SHARED_LIB) $(APP_OBJS)
+ $(CC) -o $@ $(APP_OBJS) -l$(PACKAGE) $(LDFLAGS_SHARED)
+
+$(STATIC_APP): $(STATIC_OBJS) $(APP_OBJS)
+ $(CC) -static -o $@ $^ -l$(PACKAGE) $(LDFLAGS_STATIC)
+
+
+dirs: dirs.tag tree.tag
+
+dirs.tag:
+ mkdir -p $(BINDIR)
+ mkdir -p $(LIBDIR)
+ touch dirs.tag
+
+host.tag: Makefile
+ $(PROJECT_DIR)/sysinfo/host/host.sh --compiler="$(CC)" --cflags="$(CFLAGS)"
+ touch host.tag
+
+version.tag:
+ $(PROJECT_DIR)/sysinfo/version.sh \
+ -s $(PROJECT_DIR) \
+ -o build/$(PACKAGE)_version.h \
+ -p $(PACKAGE)
+ touch version.tag
+
+distclean: clean
+ rm -f Makefile
+
+clean:
+ rm -f tree.tag
+ rm -f dirs.tag
+ rm -f host.tag
+ rm -f version.tag
+ rm -f $(SHARED_OBJS)
+ rm -f $(STATIC_OBJS)
+ rm -f $(APP_OBJS)
+ rm -f $(SHARED_LIB)
+ rm -f $(STATIC_LIB)
+ rm -f $(SHARED_IMPLIB)
+ rm -f $(APP)
+ rm -f $(DEFAULT_APP)
+ rm -f $(SHARED_APP)
+ rm -f $(STATIC_APP)
+
+
+.display: .display-project .display-env .display-tools .display-flags \
+ .display-pe .display-elf .display-dirs .display-build
+
+.display-project:
+ @echo PROJECT_DIR:' '$(PROJECT_DIR)
+ @echo BUILD_DIR:' '$(CURDIR)
+ @echo
+
+.display-env:
+ @echo BUILD:' '$(BUILD)
+ @echo HOST:' '$(HOST)
+ @echo TARGET:' '$(TARGET)
+ @echo ARCH:' '$(ARCH)
+ @echo COMPILER:' '$(COMPILER)
+ @echo TOOLCHAIN:' '$(TOOLCHAIN)
+ @echo SYSROOT:' '$(SYSROOT)
+ @echo CROSS_COMPILE:' '$(CROSS_COMPILE)
+ @echo SHELL:' '$(SHELL)
+ @echo
+
+.display-tools:
+ @echo CC:' '$(CC)
+ @echo CPP:' '$(CPP)
+ @echo CXX:' '$(CXX)
+ @echo
+ @echo AS:' '$(AS)
+ @echo AR:' '$(AR)
+ @echo LD:' '$(LD)
+ @echo NM:' '$(NM)
+ @echo OBJDUMP:' '$(OBJDUMP)
+ @echo RANLIB:' '$(RANLIB)
+ @echo SIZE:' '$(SIZE)
+ @echo STRIP:' '$(STRIP)
+ @echo STRINGS:' '$(STRINGS)
+ @echo
+ @echo ADDR2LINE:' '$(ADDR2LINE)
+ @echo COV:' '$(COV)
+ @echo CXXFILT' '$(CXXFILT)
+ @echo ELFEDIT:' '$(ELFEDIT)
+ @echo OBJCOPY:' '$(OBJCOPY)
+ @echo READELF:' '$(READELF)
+ @echo
+
+.display-flags:
+ @echo CFLAGS_DEBUG:' '$(CFLAGS_DEBUG)
+ @echo CFLAGS_COMMON:' '$(CFLAGS_COMMON)
+ @echo CFLAGS_CMDLINE:' '$(CFLAGS_CMDLINE)
+ @echo CFLAGS_CONFIG:' '$(CFLAGS_CONFIG)
+ @echo CFLAGS_SYSROOT:' '$(CFLAGS_SYSROOT)
+ @echo CFLAGS_OS:' '$(CFLAGS_OS)
+ @echo CFLAGS_SITE:' '$(CFLAGS_SITE)
+ @echo CFLAGS_PATH:' '$(CFLAGS_PATH)
+ @echo
+ @echo LDFLAGS_DEBUG:' '$(LDFLAGS_DEBUG)
+ @echo LDFLAGS_COMMON:' '$(LDFLAGS_COMMON)
+ @echo LDFLAGS_CMDLINE:' '$(LDFLAGS_CMDLINE)
+ @echo LDFLAGS_CONFIG:' '$(LDFLAGS_CONFIG)
+ @echo LDFLAGS_SYSROOT:' '$(LDFLAGS_SYSROOT)
+ @echo LDFLAGS_PATH:' '$(LDFLAGS_PATH)
+ @echo
+
+.display-pe:
+ @echo PE_SUBSYSTEM:' '$(PE_SUBSYSTEM)
+ @echo PE_IMAGE_BASE:' '$(PE_IMAGE_BASE)
+ @echo PE_CONFIG_DEFS:' '$(PE_CONFIG_DEFS)
+ @echo
+
+.display-elf:
+ @echo ELF_EH_FRAME:' '$(ELF_EH_FRAME)
+ @echo ELF_HASH_STYLE:' '$(ELF_HASH_STYLE)
+ @echo ELF_CONFIG_DEFS:' '$(ELF_CONFIG_DEFS)
+ @echo
+
+.display-dirs:
+ @echo PREFIX:' '$(PREFIX)
+ @echo BINDIR:' '$(BINDIR)
+ @echo LIBDIR:' '$(LIBDIR)
+ @echo INCLUDEDIR:' '$(INCLUDEDIR)
+ @echo SYSLIBDIR:' '$(SYSLIBDIR)
+ @echo MANDIR:' '$(MANDIR)
+ @echo DOCDIR:' '$(DOCDIR)
+ @echo LIBEXECDIR:' '$(LIBEXECDIR)
+ @echo
+
+.display-build:
+ @echo NATIVE_CC:' '$(NATIVE_CC)
+ @echo NATIVE_OS:' '$(NATIVE_OS)
+ @echo NATIVE_OS_BITS:' '$(NATIVE_OS_BITS)
+ @echo NATIVE_OS_UNDERSCORE:' '$(NATIVE_OS_UNDERSCORE)
+ @echo
+ @echo USER_CC:' '$(USER_CC)
+ @echo USER_CPP:' '$(USER_CPP)
+ @echo USER_CXX:' '$(USER_CXX)
+ @echo
+
+
+.PHONY: all install shared static app .display \
+ shared-objs shared-lib shared-implib \
+ static-objs static-lib \
+ default-app shared-app static-app \
+ install-shared install-static install-implib \
+ install-headers install-app \
+ clean distclean version \
+ .display-project .display-env .display-tools .display-flags \
+ .display-pe .display-elf .display-dirs .display-build
diff --git a/config.project b/config.project
new file mode 100644
index 0000000..bb734a7
--- /dev/null
+++ b/config.project
@@ -0,0 +1,50 @@
+# project
+mb_package=slibtool
+mb_require_out_of_tree=no
+
+
+# dirs
+mb_default_prefix=
+mb_default_bindir=bin
+mb_default_libdir=lib
+mb_default_includedir=include
+mb_default_syslibdir=lib
+mb_default_mandir=man
+mb_default_docdir=doc
+mb_default_libexecdir=libexec
+
+
+# build
+mb_default_build=
+mb_default_host=
+mb_default_target=
+mb_default_arch=
+mb_default_compiler=
+mb_default_toolchain=
+mb_default_sysroot=
+mb_default_cross_compile=
+mb_default_shell=sh
+
+
+# switches
+mb_default_cflags_debug=
+mb_default_cflags_common="-std=c99 -D_XOPEN_SOURCE=700 -I\$(PROJECT_DIR)/src/internal -I\$(PROJECT_DIR)/include -Ibuild"
+mb_default_cflags_cmdline=
+mb_default_cflags_config=
+mb_default_cflags_sysroot=
+mb_default_cflags_path=
+
+mb_default_ldflags_debug=
+mb_default_ldflags_common="-Llib"
+mb_default_ldflags_cmdline=
+mb_default_ldflags_config=
+mb_default_ldflags_sysroot=
+mb_default_ldflags_path=
+
+mb_default_pe_subsystem=windows
+mb_default_pe_image_base=
+mb_default_pe_config_defs=
+
+mb_default_elf_eh_frame=
+mb_default_elf_hash_style=
+mb_default_elf_config_defs=
diff --git a/config.usage b/config.usage
new file mode 100644
index 0000000..fda5882
--- /dev/null
+++ b/config.usage
@@ -0,0 +1,79 @@
+configure: a skinny configuration script.
+
+supported switches:
+-------------------
+ --help
+
+ --prefix
+ --bindir
+ --libdir
+ --includedir
+ --syslibdir
+ --mandir
+ --libexecdir
+
+ --build
+ --host
+ --target
+ --arch
+ --compiler
+ --toolchain
+ --sysroot
+ --cross-compile
+ --shell
+ --debug
+
+
+supported variables:
+--------------------
+ PREFIX
+ BINDIR
+ LIBDIR
+ INCLUDEDIR
+ LIBDIR
+ MANDIR
+ DOCDIR
+ LIBEXECDIR
+
+ CC
+ CPP
+ CXX
+
+ BUILD
+ HOST
+ TARGET
+ ARCH
+ COMPILER
+ TOOLCHAIN
+ SYSROOT
+ CROSS_COMPILE
+ SHELL
+
+ CFLAGS
+ CFLAGS_DEBUG
+ CFLAGS_COMMON
+ CFLAGS_CMDLINE
+ CFLAGS_CONFIG
+ CFLAGS_SYSROOT
+ CFLAGS_PATH
+
+ LDFLAGS
+ LDFLAGS_DEBUG
+ LDFLAGS_COMMON
+ LDFLAGS_CMDLINE
+ LDFLAGS_CONFIG
+ LDFLAGS_SYSROOT
+ LDFLAGS_PATH
+
+ PE_SUBSYSTEM
+ PE_IMAGE_BASE
+ PE_CONFIG_DEFS
+
+ ELF_EH_FRAME
+ ELF_HASH_STYLE
+ ELF_CONFIG_DEFS
+
+ NATIVE_CC
+ NATIVE_OS
+ NATIVE_OS_BITS
+ NATIVE_OS_UNDERSCORE
diff --git a/configure b/configure
new file mode 100755
index 0000000..fc22842
--- /dev/null
+++ b/configure
@@ -0,0 +1,467 @@
+#!/bin/sh
+# we are no longer lazy.
+
+# this script respects both CFLAGS and CFLAGS_CMDLINE,
+# as well as both LDFLAGS and LDFLAGS_CMDLINE, however
+# the latter variable of each pair should be preferred.
+
+usage()
+{
+ cat "$mb_project_dir"/config.usage
+ exit $?
+}
+
+error_msg()
+{
+ echo $@ >&2
+}
+
+
+init_vars()
+{
+ mb_project_dir=$(cd `dirname $0` ; pwd)
+ mb_pwd=`pwd`
+
+ if [ -z "$mb_config" ]; then
+ . $mb_project_dir/config.project || exit 2
+ else
+ . "$mb_config" || exit 2
+ fi
+
+ # dirs
+ mb_prefix=$PREFIX
+ mb_bindir=$BINDIR
+ mb_libdir=$LIBDIR
+ mb_includedir=$INCLUDEDIR
+ mb_syslibdir=$LIBDIR
+ mb_mandir=$MANDIR
+ mb_docdir=$DOCDIR
+ mb_libexecdir=$LIBEXECDIR
+
+
+ # build
+ mb_build=$BUILD
+ mb_host=$HOST
+ mb_target=$TARGET
+ mb_arch=$ARCH
+ mb_compiler=$COMPILER
+ mb_toolchain=$TOOLCHAIN
+ mb_sysroot=$SYSROOT
+ mb_cross_compile=$CROSS_COMPILE
+ mb_shell=$SHELL
+
+ # switches
+ mb_cflags=$CFLAGS
+ mb_cflags_debug=$CFLAGS_DEBUG
+ mb_cflags_common=$CFLAGS_COMMON
+ mb_cflags_cmdline=$CFLAGS_CMDLINE
+ mb_cflags_config=$CFLAGS_CONFIG
+ mb_cflags_sysroot=$CFLAGS_SYSROOT
+ mb_cflags_os=$CFLAGS_OS
+ mb_cflags_site=$CFLAGS_SITE
+ mb_cflags_path=$CFLAGS_PATH
+
+ mb_ldflags=$LDFLAGS
+ mb_ldflags_debug=$LDFLAGS_DEBUG
+ mb_ldflags_common=$LDFLAGS_COMMON
+ mb_ldflags_cmdline=$LDFLAGS_CMDLINE
+ mb_ldflags_config=$LDFLAGS_CONFIG
+ mb_ldflags_sysroot=$LDFLAGS_SYSROOT
+ mb_ldflags_path=$LDFLAGS_PATH
+
+ mb_pe_subsystem=$PE_SUBSYSTEM
+ mb_pe_image_base=$PE_IMAGE_BASE
+ mb_pe_config_defs=$PE_CONFIG_DEFS
+
+ mb_elf_eh_frame=$ELF_EH_FRAME
+ mb_elf_hash_style=$ELF_HASH_STYLE
+ mb_elf_config_defs=$ELF_CONFIG_DEFS
+
+ # overrides
+ mb_native_cc=$NATIVE_CC
+ mb_native_os=$NATIVE_OS
+ mb_native_os_bits=$NATIVE_OS_BITS
+ mb_native_os_underscore=$NATIVE_OS_UNDERSCORE
+
+ mb_user_cc=$CC
+ mb_user_cpp=$CPP
+ mb_user_cxx=$CXX
+}
+
+
+verify_build_directory()
+{
+ if [ "$mb_project_dir" = "$mb_pwd" ]; then
+ if [ "$mb_require_out_of_tree" = yes ]; then
+ error_msg "$mb_package: out-of-tree builds are required."
+ error_msg "please invoke configure again from a clean build directory."
+ exit 2
+ else
+ mb_project_dir='.'
+ fi
+ fi
+}
+
+
+common_defaults()
+{
+ # dirs
+ [ -z "$mb_prefix" ] && mb_prefix=$mb_default_prefix
+ [ -z "$mb_bindir" ] && mb_bindir=$mb_default_bindir
+ [ -z "$mb_libdir" ] && mb_libdir=$mb_default_libdir
+ [ -z "$mb_includedir" ] && mb_includedir=$mb_default_includedir
+ [ -z "$mb_syslibdir" ] && mb_syslibdir=$mb_default_syslibdir
+ [ -z "$mb_mandir" ] && mb_mandir=$mb_default_mandir
+ [ -z "$mb_docdir" ] && mb_docdir=$mb_default_docdir
+ [ -z "$mb_libexecdir" ] && mb_libexecdir=$mb_default_libexecdir
+
+ # build
+ [ -z "$mb_build" ] && mb_build=$mb_default_build
+ [ -z "$mb_host" ] && mb_host=$mb_default_host
+ [ -z "$mb_target" ] && mb_target=$mb_default_target
+ [ -z "$mb_arch" ] && mb_arch=$mb_default_arch
+ [ -z "$mb_compiler" ] && mb_compiler=$mb_default_compiler
+ [ -z "$mb_toolchain" ] && mb_toolchain=$mb_default_toolchain
+ [ -z "$mb_sysroot" ] && mb_sysroot=$mb_default_sysroot
+ [ -z "$mb_cross_compile" ] && mb_cross_compile=$mb_default_cross_compile
+ [ -z "$mb_shell" ] && mb_shell=$mb_default_shell
+
+ # switches
+ [ -z "$mb_cflags_debug" ] && mb_cflags_debug=$mb_default_cflags_debug
+ [ -z "$mb_cflags_common" ] && mb_cflags_common=$mb_default_cflags_common
+ [ -z "$mb_cflags_cmdline" ] && mb_cflags_cmdline=$mb_default_cflags_cmdline
+ [ -z "$mb_cflags_config" ] && mb_cflags_config=$mb_default_cflags_config
+ [ -z "$mb_cflags_sysroot" ] && mb_cflags_sysroot=$mb_default_cflags_sysroot
+ [ -z "$mb_cflags_os" ] && mb_cflags_os=$mb_default_cflags_os
+ [ -z "$mb_cflags_site" ] && mb_cflags_site=$mb_default_cflags_site
+ [ -z "$mb_cflags_path" ] && mb_cflags_path=$mb_default_cflags_path
+
+ [ -z "$mb_ldflags_debug" ] && mb_ldflags_debug=$mb_default_ldflags_debug
+ [ -z "$mb_ldflags_common" ] && mb_ldflags_common=$mb_default_ldflags_common
+ [ -z "$mb_ldflags_cmdline" ] && mb_ldflags_cmdline=$mb_default_ldflags_cmdline
+ [ -z "$mb_ldflags_config" ] && mb_ldflags_config=$mb_default_ldflags_config
+ [ -z "$mb_ldflags_sysroot" ] && mb_ldflags_sysroot=$mb_default_ldflags_sysroot
+ [ -z "$mb_ldflags_path" ] && mb_ldflags_path=$mb_default_ldflags_path
+
+ [ -z "$mb_pe_subsystem" ] && mb_pe_subsystem=$mb_default_pe_subsystem
+ [ -z "$mb_pe_image_base" ] && mb_pe_image_base=$mb_default_pe_image_base
+ [ -z "$mb_pe_config_defs" ] && mb_pe_config_defs=$mb_default_pe_config_defs
+
+ [ -z "$mb_elf_eh_frame" ] && mb_elf_eh_frame=$mb_default_elf_eh_frame
+ [ -z "$mb_elf_hash_style" ] && mb_elf_hash_style=$mb_default_elf_hash_style
+ [ -z "$mb_elf_config_defs" ] && mb_elf_config_defs=$mb_default_elf_config_defs
+
+ # host/target
+ [ -z "$mb_host" ] && mb_host=$mb_target
+ [ -z "$mb_target" ] && mb_target=$mb_host
+
+ # sysroot
+ if [ -n "$mb_sysroot" ]; then
+ if [ -z "$mb_cflags_sysroot" ]; then
+ mb_cflags_sysroot="--sysroot=$mb_sysroot"
+ fi
+
+ if [ -z "$mb_ldflags_sysroot" ]; then
+ mb_ldflags_sysroot="-Wl,--sysroot,$mb_sysroot"
+ fi
+ fi
+
+ # debug
+ if [ "$mb_debug" = yes ]; then
+ if [ -z "$mb_cflags_debug" ]; then
+ mb_cflags_debug='-g3 -O0'
+ fi
+ fi
+
+ # compiler
+ if [ -n "$mb_compiler" ]; then
+ if [ -z "$mb_native_cc" ]; then
+ mb_native_cc=$mb_compiler
+ fi
+ fi
+
+ # toolchain
+ if [ -z "$mb_toolchain" ]; then
+ mb_toolchain='binutils'
+ fi
+
+ # fallback host recipe
+ if [ -n "$mb_host" ]; then
+ if ! [ -f $mb_project_dir/sysinfo/host/$mb_host.mk ]; then
+ if [ -z "$mb_cross_compile" ]; then
+ mb_cross_compile=$mb_host-
+ fi
+
+ mb_host='any-host';
+ fi
+ fi
+
+ # fallback compiler recipe
+ if [ -n "$mb_compiler" ]; then
+ if ! [ -f $mb_project_dir/sysinfo/compiler/$mb_compiler.mk ]; then
+ mb_compiler='any-compiler'
+ fi
+ fi
+}
+
+
+native_defaults()
+{
+ # CC (when set, must be valid)
+ if [ -n "$CC" ]; then
+ $CC -dM -E - < /dev/null > /dev/null || exit 2
+ fi
+
+ # compiler
+ [ -z "$mb_native_cc" ] && mb_native_cc=$CC
+ [ -z "$mb_native_cc" ] && mb_native_cc='cc'
+ $mb_native_cc -dM -E - < /dev/null > /dev/null 2>/dev/null || mb_native_cc=
+
+ [ -z "$mb_native_cc" ] && mb_native_cc='gcc'
+ $mb_native_cc -dM -E - < /dev/null > /dev/null 2>/dev/null || mb_native_cc=
+
+ [ -z "$mb_native_cc" ] && mb_native_cc='clang'
+ $mb_native_cc -dM -E - < /dev/null > /dev/null 2>/dev/null || mb_native_cc=
+
+ [ -z "$mb_native_cc" ] && mb_native_cc='cparser'
+ $mb_native_cc -dM -E - < /dev/null > /dev/null 2>/dev/null || mb_native_cc=
+
+ if [ -z "$mb_native_cc" ]; then
+ echo "configure: info: could not find a working native compiler."
+ mb_native_cc='false'
+ fi
+
+ if [ -z "$mb_compiler" ]; then
+ $mb_native_cc -dM -E - < /dev/null | grep '__clang__' > /dev/null && mb_compiler='clang'
+ fi
+
+ if [ -z "$mb_compiler" ]; then
+ $mb_native_cc -dM -E - < /dev/null | grep '__GCC' > /dev/null && mb_compiler='gcc'
+ fi
+
+ if [ -z "$mb_compiler" ]; then
+ $mb_native_cc -dM -E - < /dev/null | grep '__CPARSER__' > /dev/null && mb_compiler='cparser'
+ fi
+
+ if [ -z "$mb_compiler" ]; then
+ echo "configure: info: could not identify the native compiler."
+ mb_compiler='any-compiler'
+ fi
+
+
+ # host
+ if [ -z "$mb_host" ]; then
+ mb_host='native'
+ fi
+
+
+ # target
+ if [ -z "$mb_target" ]; then
+ mb_target='native'
+ fi
+
+
+ # os
+ mb_native_os=`uname | tr '[:upper:]' '[:lower:]'`
+
+ mb_native_os_sizeof_pointer=`$mb_native_cc -dM -E - < /dev/null \
+ | grep __SIZEOF_POINTER__ \
+ | cut -d ' ' -f3`
+
+ mb_native_os_bits=`expr '8' '*' '0'"$mb_native_os_sizeof_pointer"`
+
+ if [ $mb_native_os_bits = 32 ]; then
+ mb_native_os_underscore='_'
+ else
+ mb_native_os_underscore=''
+ fi
+
+ if [ -z "$mb_native_os_sizeof_pointer" ]; then
+ error_msg "config error: could not determine size of pointer on native system."
+ exit 2
+ fi
+
+ [ -z "$mb_native_os" ] && mb_native_os=$mb_native_os
+ [ -z "$mb_native_os_bits" ] && mb_native_os_bits=$mb_native_os_bits
+ [ -z "$mb_native_os_underscore" ] && mb_native_os_underscore=$mb_native_os_underscore
+}
+
+
+cross_defaults()
+{
+ if [ -z "$mb_cross_compile" ] && [ "$mb_host" != native ]; then
+ mb_cross_compile=$mb_host'-'
+ fi
+}
+
+
+config_copy()
+{
+ sed -e 's^@package@^'"$mb_package"'^g' \
+ -e 's^@project_dir@^'"$mb_project_dir"'^g' \
+ \
+ -e 's^@build@^'"$mb_build"'^g' \
+ -e 's^@host@^'"$mb_host"'^g' \
+ -e 's^@target@^'"$mb_target"'^g' \
+ -e 's^@arch@^'"$mb_arch"'^g' \
+ -e 's^@compiler@^'"$mb_compiler"'^g' \
+ -e 's^@toolchain@^'"$mb_toolchain"'^g' \
+ -e 's^@sysroot@^'"$mb_sysroot"'^g' \
+ -e 's^@cross_compile@^'"$mb_cross_compile"'^g' \
+ -e 's^@shell@^'"$mb_shell"'^g' \
+ \
+ -e 's^@cflags@^'"$mb_cflags"'^g' \
+ -e 's^@cflags_debug@^'"$mb_cflags_debug"'^g' \
+ -e 's^@cflags_common@^'"$mb_cflags_common"'^g' \
+ -e 's^@cflags_cmdline@^'"$mb_cflags $mb_cflags_cmdline"'^g' \
+ -e 's^@cflags_config@^'"$mb_cflags_config"'^g' \
+ -e 's^@cflags_sysroot@^'"$mb_cflags_sysroot"'^g' \
+ -e 's^@cflags_os@^'"$mb_cflags_os"'^g' \
+ -e 's^@cflags_site@^'"$mb_cflags_site"'^g' \
+ -e 's^@cflags_path@^'"$mb_cflags_path"'^g' \
+ \
+ -e 's^@ldflags@^'"$mb_ldflags"'^g' \
+ -e 's^@ldflags_debug@^'"$mb_ldflags_debug"'^g' \
+ -e 's^@ldflags_common@^'"$mb_ldflags_common"'^g' \
+ -e 's^@ldflags_cmdline@^'"$mb_ldflags $mb_ldflags_cmdline"'^g' \
+ -e 's^@ldflags_config@^'"$mb_ldflags_config"'^g' \
+ -e 's^@ldflags_sysroot@^'"$mb_ldflags_sysroot"'^g' \
+ -e 's^@ldflags_path@^'"$mb_ldflags_path"'^g' \
+ \
+ -e 's^@pe_subsystem@^'"$mb_pe_subsystem"'^g' \
+ -e 's^@pe_image\_base@^'"$mb_pe_image_base"'^g' \
+ -e 's^@pe_config\_defs@^'"$mb_pe_config_defs"'^g' \
+ \
+ -e 's^@elf_eh\_frame@^'"$mb_elf_eh_frame"'^g' \
+ -e 's^@elf_hash\_style@^'"$mb_elf_hash_style"'^g' \
+ -e 's^@elf_config\_defs@^'"$mb_elf_config_defs"'^g' \
+ \
+ -e 's^@prefix@^'"$mb_prefix"'^g' \
+ -e 's^@bindir@^'"$mb_bindir"'^g' \
+ -e 's^@libdir@^'"$mb_libdir"'^g' \
+ -e 's^@includedir@^'"$mb_includedir"'^g' \
+ -e 's^@syslibdir@^'"$mb_syslibdir"'^g' \
+ -e 's^@mandir@^'"$mb_mandir"'^g' \
+ -e 's^@docdir@^'"$mb_docdir"'^g' \
+ -e 's^@libexecdir@^'"$mb_libexecdir"'^g' \
+ \
+ -e 's^@native_cc@^'"$mb_native_cc"'^g' \
+ -e 's^@native_os@^'"$mb_native_os"'^g' \
+ -e 's^@native_os_bits@^'"$mb_native_os_bits"'^g' \
+ -e 's^@native_os_underscore@^'"$mb_native_os_underscore"'^g' \
+ \
+ -e 's^@user_cc@^'"$mb_user_cc"'^g' \
+ -e 's^@user_cpp@^'"$mb_user_cpp"'^g' \
+ -e 's^@user_cxx@^'"$mb_user_cxx"'^g' \
+ $mb_project_dir/Makefile.in > $mb_pwd/Makefile
+}
+
+
+config_host()
+{
+ make -s host.tag && return 0
+
+ error_msg "configure was able to generate a Makefile for the selected host,"
+ error_msg "however the host-targeting compiler was found to be missing"
+ error_msg "at least one of the required headers or features."
+ exit 2
+}
+
+
+config_status()
+{
+ printf "\n\n"
+ make .display
+ printf "\nconfiguration completed successfully.\n\n"
+}
+
+# one: init
+init_vars
+verify_build_directory
+
+
+# two: args
+for arg ; do
+ case "$arg" in
+ --help) usage
+ ;;
+
+ # dirs
+ --prefix=*)
+ mb_prefix=${arg#*=}
+ ;;
+ --bindir=*)
+ mb_bindir=${arg#*=}
+ ;;
+ --libdir=*)
+ mb_libdir=${arg#*=}
+ ;;
+ --includedir=*)
+ mb_includedir=${arg#*=}
+ ;;
+ --syslibdir=*)
+ mb_syslibdir=${arg#*=}
+ ;;
+ --mandir=*)
+ mb_mandir=${arg#*=}
+ ;;
+ --libexecdir=*)
+ mb_libexecdir=${arg#*=}
+ ;;
+
+
+ # build
+ --build=*)
+ mb_build=${arg#*=}
+ ;;
+ --host=*)
+ mb_host=${arg#*=}
+ ;;
+ --target=*)
+ mb_target=${arg#*=}
+ ;;
+ --arch=*)
+ mb_arch=${arg#*=}
+ ;;
+ --compiler=*)
+ mb_compiler=${arg#*=}
+ ;;
+ --toolchain=*)
+ mb_toolchain=${arg#*=}
+ ;;
+ --sysroot=*)
+ mb_sysroot=${arg#*=}
+ ;;
+ --cross-compile=*)
+ mb_cross_compile=${arg#*=}
+ ;;
+ --shell=*)
+ mb_shell=${arg#*=}
+ ;;
+ --debug)
+ mb_debug='yes'
+ ;;
+ *)
+ error_msg ${arg#}: "unsupported config argument."
+ exit 2
+ ;;
+ esac
+done
+
+
+
+# three: defaults
+common_defaults
+native_defaults
+cross_defaults
+
+
+
+# four: config
+config_copy
+config_host
+config_status
+
+
+# all done
+exit 0
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h
new file mode 100644
index 0000000..4aec0cc
--- /dev/null
+++ b/include/slibtool/slibtool.h
@@ -0,0 +1,88 @@
+#ifndef SOFORT_H
+#define SOFORT_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "slibtool_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* pre-alpha */
+#ifndef SLBT_APP
+#ifndef SLBT_PRE_ALPHA
+#error libslibtool: pre-alpha: ABI is not final!
+#error to use the library, please pass -DSLBT_PRE_ALPHA to the compiler.
+#endif
+#endif
+
+/* status codes */
+#define SLBT_OK 0x00
+#define SLBT_USAGE 0x01
+#define SLBT_BAD_OPT 0x02
+#define SLBT_BAD_OPT_VAL 0x03
+#define SLBT_IO_ERROR 0xA0
+#define SLBT_MAP_ERROR 0xA1
+
+/* driver flags */
+#define SLBT_DRIVER_VERBOSITY_NONE 0x0000
+#define SLBT_DRIVER_VERBOSITY_ERRORS 0x0001
+#define SLBT_DRIVER_VERBOSITY_STATUS 0x0002
+#define SLBT_DRIVER_VERBOSITY_USAGE 0x0004
+#define SLBT_DRIVER_CLONE_VECTOR 0x0008
+
+#define SLBT_DRIVER_VERSION 0x0010
+#define SLBT_DRIVER_DRY_RUN 0x0020
+
+/* unit action flags */
+
+struct slbt_input {
+ void * addr;
+ size_t size;
+};
+
+struct slbt_common_ctx {
+ uint64_t drvflags;
+ uint64_t actflags;
+ uint64_t fmtflags;
+};
+
+struct slbt_driver_ctx {
+ const char ** units;
+ const char * program;
+ const char * module;
+ const struct slbt_common_ctx * cctx;
+ void * any;
+ int status;
+ int nerrors;
+};
+
+struct slbt_unit_ctx {
+ const char * const * path;
+ const struct slbt_input * map;
+ const struct slbt_common_ctx * cctx;
+ void * any;
+ int status;
+ int nerrors;
+};
+
+/* driver api */
+slbt_api int slbt_get_driver_ctx (char ** argv, char ** envp, uint32_t flags, struct slbt_driver_ctx **);
+slbt_api int slbt_create_driver_ctx (const struct slbt_common_ctx *, struct slbt_driver_ctx **);
+slbt_api void slbt_free_driver_ctx (struct slbt_driver_ctx *);
+
+slbt_api int slbt_get_unit_ctx (const struct slbt_driver_ctx *, const char * path, struct slbt_unit_ctx **);
+slbt_api void slbt_free_unit_ctx (struct slbt_unit_ctx *);
+
+slbt_api int slbt_map_input (int fd, const char * path, int prot, struct slbt_input *);
+slbt_api int slbt_unmap_input (struct slbt_input *);
+
+/* utility api */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/slibtool/slibtool_api.h b/include/slibtool/slibtool_api.h
new file mode 100644
index 0000000..2be0a47
--- /dev/null
+++ b/include/slibtool/slibtool_api.h
@@ -0,0 +1,35 @@
+#ifndef SOFORT_API_H
+#define SOFORT_API_H
+
+#include <limits.h>
+
+/* slbt_export */
+#if defined(__dllexport)
+#define slbt_export __dllexport
+#else
+#define slbt_export
+#endif
+
+/* slbt_import */
+#if defined(__dllimport)
+#define slbt_import __dllimport
+#else
+#define slbt_import
+#endif
+
+/* slbt_api */
+#ifndef SLBT_APP
+#if defined (SLBT_BUILD)
+#define slbt_api slbt_export
+#elif defined (SLBT_SHARED)
+#define slbt_api slbt_import
+#elif defined (SLBT_STATIC)
+#define slbt_api
+#else
+#define slbt_api
+#endif
+#else
+#define slbt_api
+#endif
+
+#endif
diff --git a/project/arch.mk b/project/arch.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/project/arch.mk
diff --git a/project/common.mk b/project/common.mk
new file mode 100644
index 0000000..45a3d8f
--- /dev/null
+++ b/project/common.mk
@@ -0,0 +1,8 @@
+COMMON_SRCS = \
+ src/driver/slbt_driver_ctx.c \
+ src/driver/slbt_unit_ctx.c \
+ src/logic/slbt_map_input.c \
+ src/skin/slbt_skin_default.c \
+
+APP_SRCS = \
+ src/slibtool.c
diff --git a/project/defs.mk b/project/defs.mk
new file mode 100644
index 0000000..9c36756
--- /dev/null
+++ b/project/defs.mk
@@ -0,0 +1,44 @@
+SHARED_LIB_DEPS =
+SHARED_APP_DEPS =
+STATIC_APP_DEPS =
+
+COMMON_LOBJS = $(COMMON_SRCS:.c=.lo)
+COMMON_OBJS = $(COMMON_SRCS:.c=.o)
+
+ARCH_LOBJS = $(ARCH_SRCS:.c=.lo)
+ARCH_OBJS = $(ARCH_SRCS:.c=.o)
+
+APP_LOBJS = $(APP_SRCS:.c=.lo)
+APP_OBJS = $(APP_SRCS:.c=.o)
+
+SHARED_OBJS = $(COMMON_LOBJS) $(ARCH_LOBJS)
+STATIC_OBJS = $(COMMON_OBJS) $(ARCH_OBJS)
+
+SHARED_LIB = $(LIBDIR)/$(OS_LIB_PREFIX)$(PACKAGE)$(OS_LIB_SUFFIX)
+STATIC_LIB = $(LIBDIR)/$(OS_LIB_PREFIX)$(PACKAGE)$(OS_ARCHIVE_EXT)
+SHARED_IMPLIB = $(LIBDIR)/$(OS_LIB_PREFIX)$(PACKAGE)$(OS_IMPLIB_EXT)
+
+APP = $(BINDIR)/$(OS_APP_PREFIX)$(PACKAGE)$(OS_APP_SUFFIX)
+DEFAULT_APP = $(BINDIR)/$(OS_APP_PREFIX)$(PACKAGE)-default$(OS_APP_SUFFIX)
+SHARED_APP = $(BINDIR)/$(OS_APP_PREFIX)$(PACKAGE)-shared$(OS_APP_SUFFIX)
+STATIC_APP = $(BINDIR)/$(OS_APP_PREFIX)$(PACKAGE)-static$(OS_APP_SUFFIX)
+
+CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_CONFIG) $(CFLAGS_SYSROOT) \
+ $(CFLAGS_COMMON) $(CFLAGS_CMDLINE) $(CFLAGS_HOST) \
+ $(CFLAGS_PATH) $(CFLAGS_OS) $(CFLAGS_SITE)
+
+CFLAGS_SHARED = $(CFLAGS) $(CFLAGS_PIC) $(CFLAGS_SHARED_ATTR)
+CFLAGS_STATIC = $(CFLAGS) $(CFLAGS_OBJ) $(CFLAGS_STATIC_ATTR)
+CFLAGS_APP = $(CFLAGS) $(CFLAGS_OBJ) $(CFLAGS_APP_ATTR)
+
+LDFLAGS_SHARED = $(LDFLAGS_DEBUG) $(LDFLAGS_CONFIG) $(LDFLAGS_SYSROOT) \
+ $(LDFLAGS_COMMON) $(LDFLAGS_CMDLINE) $(LDFLAGS_HOST) \
+ $(LDFLAGS_PATH) $(SHARED_LIB_DEPS) $(LDFLAGS_LAST)
+
+LDFLAGS_APP = $(LDFLAGS_DEBUG) $(LDFLAGS_CONFIG) $(LDFLAGS_SYSROOT) \
+ $(LDFLAGS_COMMON) $(LDFLAGS_CMDLINE) $(LDFLAGS_HOST) \
+ $(LDFLAGS_PATH) $(SHARED_APP_DEPS) $(LDFLAGS_LAST)
+
+LDFLAGS_STATIC = $(LDFLAGS_DEBUG) $(LDFLAGS_CONFIG) $(LDFLAGS_SYSROOT) \
+ $(LDFLAGS_COMMON) $(LDFLAGS_CMDLINE) $(LDFLAGS_HOST) \
+ $(LDFLAGS_PATH) $(STATIC_APP_DEPS) $(LDFLAGS_LAST)
diff --git a/project/depends.mk b/project/depends.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/project/depends.mk
diff --git a/project/extras.mk b/project/extras.mk
new file mode 100644
index 0000000..8e2cb61
--- /dev/null
+++ b/project/extras.mk
@@ -0,0 +1,3 @@
+CFLAGS_SHARED_ATTR += -DSLBT_PRE_ALPHA -DSLBT_BUILD
+CFLAGS_STATIC_ATTR += -DSLBT_PRE_ALPHA -DSLBT_STATIC
+CFLAGS_APP_ATTR += -DSLBT_APP
diff --git a/project/headers.mk b/project/headers.mk
new file mode 100644
index 0000000..1a210ff
--- /dev/null
+++ b/project/headers.mk
@@ -0,0 +1,9 @@
+API_HEADERS = \
+ $(PROJECT_DIR)/include/$(PACKAGE)/slibtool.h \
+ $(PROJECT_DIR)/include/$(PACKAGE)/slibtool_api.h \
+
+INTERNAL_HEADERS = \
+ $(PROJECT_DIR)/src/internal/argv/argv.h \
+ $(PROJECT_DIR)/src/internal/$(PACKAGE)_driver_impl.h \
+
+ALL_HEADERS = $(API_HEADERS) $(INTERNAL_HEADERS)
diff --git a/project/overrides.mk b/project/overrides.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/project/overrides.mk
diff --git a/project/tree.mk b/project/tree.mk
new file mode 100644
index 0000000..d91f6a2
--- /dev/null
+++ b/project/tree.mk
@@ -0,0 +1,8 @@
+tree.tag:
+ mkdir -p src
+ mkdir -p src/driver
+ mkdir -p src/internal
+ mkdir -p src/logic
+ mkdir -p src/output
+ mkdir -p src/skin
+ touch tree.tag
diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c
new file mode 100644
index 0000000..9888e46
--- /dev/null
+++ b/src/driver/slbt_driver_ctx.c
@@ -0,0 +1,181 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define ARGV_DRIVER
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+#include "argv/argv.h"
+
+struct slbt_driver_ctx_alloc {
+ struct argv_meta * meta;
+ struct slbt_driver_ctx_impl ctx;
+ uint64_t guard;
+ const char * units[];
+};
+
+static uint32_t slbt_argv_flags(uint32_t flags)
+{
+ uint32_t ret = 0;
+
+ if (flags & SLBT_DRIVER_VERBOSITY_NONE)
+ ret |= ARGV_VERBOSITY_NONE;
+
+ if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
+ ret |= ARGV_VERBOSITY_ERRORS;
+
+ if (flags & SLBT_DRIVER_VERBOSITY_STATUS)
+ ret |= ARGV_VERBOSITY_STATUS;
+
+ return ret;
+}
+
+static int slbt_driver_usage(
+ const char * program,
+ const char * arg,
+ const struct argv_option * options,
+ struct argv_meta * meta)
+{
+ char header[512];
+
+ snprintf(header,sizeof(header),
+ "Usage: %s [options] <file>...\n" "Options:\n",
+ program);
+
+ argv_usage(stdout,header,options,arg);
+ argv_free(meta);
+
+ return SLBT_USAGE;
+}
+
+static struct slbt_driver_ctx_impl * slbt_driver_ctx_alloc(
+ struct argv_meta * meta,
+ const struct slbt_common_ctx * cctx,
+ size_t nunits)
+{
+ struct slbt_driver_ctx_alloc * ictx;
+ size_t size;
+ struct argv_entry * entry;
+ const char ** units;
+
+ size = sizeof(struct slbt_driver_ctx_alloc);
+ size += (nunits+1)*sizeof(const char *);
+
+ if (!(ictx = calloc(1,size)))
+ return 0;
+
+ if (cctx)
+ memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
+
+ for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++)
+ if (!entry->fopt)
+ *units++ = entry->arg;
+
+ ictx->meta = meta;
+ ictx->ctx.ctx.units = ictx->units;
+ return &ictx->ctx;
+}
+
+static int slbt_get_driver_ctx_fail(struct argv_meta * meta)
+{
+ argv_free(meta);
+ return -1;
+}
+
+int slbt_get_driver_ctx(
+ char ** argv,
+ char ** envp,
+ uint32_t flags,
+ struct slbt_driver_ctx ** pctx)
+{
+ struct slbt_driver_ctx_impl * ctx;
+ struct slbt_common_ctx cctx;
+ const struct argv_option * options;
+ struct argv_meta * meta;
+ struct argv_entry * entry;
+ size_t nunits;
+ const char * program;
+
+ options = slbt_default_options;
+
+ if (!(meta = argv_get(argv,options,slbt_argv_flags(flags))))
+ return -1;
+
+ nunits = 0;
+ program = argv_program_name(argv[0]);
+ memset(&cctx,0,sizeof(cctx));
+
+ if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
+ return slbt_driver_usage(program,0,options,meta);
+
+ /* get options, count units */
+ for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
+ if (entry->fopt) {
+ switch (entry->tag) {
+ case TAG_HELP:
+ if (flags & SLBT_DRIVER_VERBOSITY_USAGE)
+ return slbt_driver_usage(program,entry->arg,options,meta);
+
+ case TAG_VERSION:
+ cctx.drvflags |= SLBT_DRIVER_VERSION;
+ break;
+ }
+ } else
+ nunits++;
+ }
+
+ if (!(ctx = slbt_driver_ctx_alloc(meta,&cctx,nunits)))
+ return slbt_get_driver_ctx_fail(meta);
+
+ ctx->ctx.program = program;
+ ctx->ctx.cctx = &ctx->cctx;
+
+ *pctx = &ctx->ctx;
+ return SLBT_OK;
+}
+
+int slbt_create_driver_ctx(
+ const struct slbt_common_ctx * cctx,
+ struct slbt_driver_ctx ** pctx)
+{
+ struct argv_meta * meta;
+ struct slbt_driver_ctx_impl * ctx;
+ char * argv[] = {"slibtool_driver",0};
+
+ if (!(meta = argv_get(argv,slbt_default_options,0)))
+ return -1;
+
+ if (!(ctx = slbt_driver_ctx_alloc(meta,cctx,0)))
+ return slbt_get_driver_ctx_fail(0);
+
+ ctx->ctx.cctx = &ctx->cctx;
+ memcpy(&ctx->cctx,cctx,sizeof(*cctx));
+ *pctx = &ctx->ctx;
+ return SLBT_OK;
+}
+
+static void slbt_free_driver_ctx_impl(struct slbt_driver_ctx_alloc * ictx)
+{
+ argv_free(ictx->meta);
+ free(ictx);
+}
+
+void slbt_free_driver_ctx(struct slbt_driver_ctx * ctx)
+{
+ struct slbt_driver_ctx_alloc * ictx;
+ uintptr_t addr;
+
+ if (ctx) {
+ addr = (uintptr_t)ctx - offsetof(struct slbt_driver_ctx_alloc,ctx);
+ addr = addr - offsetof(struct slbt_driver_ctx_impl,ctx);
+ ictx = (struct slbt_driver_ctx_alloc *)addr;
+ slbt_free_driver_ctx_impl(ictx);
+ }
+}
diff --git a/src/driver/slbt_unit_ctx.c b/src/driver/slbt_unit_ctx.c
new file mode 100644
index 0000000..3fab392
--- /dev/null
+++ b/src/driver/slbt_unit_ctx.c
@@ -0,0 +1,62 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+
+static int slbt_free_unit_ctx_impl(struct slbt_unit_ctx_impl * ctx, int status)
+{
+ if (ctx) {
+ slbt_unmap_input(&ctx->map);
+ free(ctx);
+ }
+
+ return status;
+}
+
+int slbt_get_unit_ctx(
+ const struct slbt_driver_ctx * dctx,
+ const char * path,
+ struct slbt_unit_ctx ** pctx)
+{
+ struct slbt_unit_ctx_impl * ctx;
+
+ if (!dctx || !(ctx = calloc(1,sizeof(*ctx))))
+ return -1;
+
+ if (slbt_map_input(-1,path,PROT_READ,&ctx->map))
+ return slbt_free_unit_ctx_impl(ctx,-1);
+
+ memcpy(&ctx->cctx,dctx->cctx,
+ sizeof(ctx->cctx));
+
+ ctx->path = path;
+
+ ctx->uctx.path = &ctx->path;
+ ctx->uctx.map = &ctx->map;
+ ctx->uctx.cctx = &ctx->cctx;
+
+ *pctx = &ctx->uctx;
+ return 0;
+}
+
+void slbt_free_unit_ctx(struct slbt_unit_ctx * ctx)
+{
+ struct slbt_unit_ctx_impl * ictx;
+ uintptr_t addr;
+
+ if (ctx) {
+ addr = (uintptr_t)ctx - offsetof(struct slbt_unit_ctx_impl,uctx);
+ ictx = (struct slbt_unit_ctx_impl *)addr;
+ slbt_free_unit_ctx_impl(ictx,0);
+ }
+}
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h
new file mode 100644
index 0000000..4f037fb
--- /dev/null
+++ b/src/internal/argv/argv.h
@@ -0,0 +1,1053 @@
+/****************************************************************************/
+/* argv.h: a thread-safe argument vector parser and usage screen generator */
+/* Copyright (C) 2015--2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SOFORT. */
+/* This file is (also) part of sofort: portable software project template. */
+/****************************************************************************/
+
+#ifndef ARGV_H
+#define ARGV_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ARGV_VERBOSITY_NONE 0x00
+#define ARGV_VERBOSITY_ERRORS 0x01
+#define ARGV_VERBOSITY_STATUS 0x02
+#define ARGV_CLONE_VECTOR 0x80
+
+#ifndef ARGV_TAB_WIDTH
+#define ARGV_TAB_WIDTH 8
+#endif
+
+/*******************************************/
+/* */
+/* support of hybrid options */
+/* ------------------------- */
+/* hybrid options are very similar to */
+/* long options, yet are prefixed by */
+/* a single dash rather than two */
+/* (i.e. -std, -isystem). */
+/* hybrid options are supported by this */
+/* driver for compatibility with legacy */
+/* tools; note, however, that the use */
+/* of hybrid options should be strongly */
+/* discouraged due to the limitations */
+/* they impose on short options (for */
+/* example, a driver implementing -std */
+/* may not provide -s as a short option */
+/* that takes an arbitrary value). */
+/* */
+/* SPACE: -hybrid VALUE (i.e. -MF file) */
+/* EQUAL: -hybrid=VALUE (i.e. -std=c99) */
+/* COMMA: -hybrid,VALUE (i.e. -Wl,<arg>) */
+/* ONLY: -opt accepted, --opt rejected */
+/* JOINED: -optVALUE */
+/* */
+/*******************************************/
+
+
+#define ARGV_OPTION_HYBRID_NONE 0x00
+#define ARGV_OPTION_HYBRID_ONLY 0x01
+#define ARGV_OPTION_HYBRID_SPACE 0x02
+#define ARGV_OPTION_HYBRID_EQUAL 0x04
+#define ARGV_OPTION_HYBRID_COMMA 0x08
+#define ARGV_OPTION_HYBRID_JOINED 0x10
+#define ARGV_OPTION_HYBRID_CIRCUS (ARGV_OPTION_HYBRID_SPACE \
+ | ARGV_OPTION_HYBRID_JOINED)
+#define ARGV_OPTION_HYBRID_DUAL (ARGV_OPTION_HYBRID_SPACE \
+ | ARGV_OPTION_HYBRID_EQUAL)
+#define ARGV_OPTION_HYBRID_SWITCH (ARGV_OPTION_HYBRID_SPACE \
+ | ARGV_OPTION_HYBRID_EQUAL \
+ | ARGV_OPTION_HYBRID_COMMA \
+ | ARGV_OPTION_HYBRID_JOINED)
+
+enum argv_optarg {
+ ARGV_OPTARG_NONE,
+ ARGV_OPTARG_REQUIRED,
+ ARGV_OPTARG_OPTIONAL,
+};
+
+enum argv_mode {
+ ARGV_MODE_SCAN,
+ ARGV_MODE_COPY,
+};
+
+enum argv_error {
+ ARGV_ERROR_OK,
+ ARGV_ERROR_INTERNAL,
+ ARGV_ERROR_SHORT_OPTION,
+ ARGV_ERROR_LONG_OPTION,
+ ARGV_ERROR_OPTARG_NONE,
+ ARGV_ERROR_OPTARG_REQUIRED,
+ ARGV_ERROR_OPTARG_PARADIGM,
+ ARGV_ERROR_HYBRID_NONE,
+ ARGV_ERROR_HYBRID_ONLY,
+ ARGV_ERROR_HYBRID_SPACE,
+ ARGV_ERROR_HYBRID_EQUAL,
+ ARGV_ERROR_HYBRID_COMMA,
+};
+
+struct argv_option {
+ const char * long_name;
+ const char short_name;
+ int tag;
+ enum argv_optarg optarg;
+ int flags;
+ const char * paradigm;
+ const char * argname;
+ const char * description;
+};
+
+struct argv_entry {
+ const char * arg;
+ int tag;
+ bool fopt;
+ bool fval;
+ bool fnoscan;
+ enum argv_error errcode;
+};
+
+struct argv_meta {
+ char ** argv;
+ struct argv_entry * entries;
+};
+
+struct argv_meta_impl {
+ char ** argv;
+ char * strbuf;
+ struct argv_meta meta;
+};
+
+struct argv_ctx {
+ int flags;
+ int mode;
+ int nentries;
+ int unitidx;
+ int erridx;
+ enum argv_error errcode;
+ const char * errch;
+ const struct argv_option * erropt;
+ const char * program;
+};
+
+#ifdef ARGV_DRIVER
+
+static const char * argv_program_name(const char *);
+
+static void argv_usage(
+ FILE *,
+ const char * header,
+ const struct argv_option[],
+ const char * mode);
+
+static struct argv_meta * argv_get(
+ char **,
+ const struct argv_option[],
+ int flags);
+
+static void argv_free(struct argv_meta *);
+
+
+
+
+/*------------------------------------*/
+/* implementation of static functions */
+/*------------------------------------*/
+
+static const struct argv_option * argv_short_option(
+ const char * ch,
+ const struct argv_option options[],
+ struct argv_entry * entry)
+{
+ const struct argv_option * option;
+
+ for (option=options; option->long_name || option->short_name; option++) {
+ if (option->short_name == *ch) {
+ entry->tag = option->tag;
+ entry->fopt = true;
+ return option;
+ }
+ }
+
+ return 0;
+}
+
+static const struct argv_option * argv_long_option(
+ const char * ch,
+ const struct argv_option options[],
+ struct argv_entry * entry)
+{
+ const struct argv_option * option;
+ const char * arg;
+ size_t len;
+
+ for (option=options; option->long_name || option->short_name; option++) {
+ len = option->long_name ? strlen(option->long_name) : 0;
+
+ if (len && !(strncmp(option->long_name,ch,len))) {
+ arg = ch + len;
+
+ if (!*arg
+ || (*arg == '=')
+ || (option->flags & ARGV_OPTION_HYBRID_JOINED)
+ || ((option->flags & ARGV_OPTION_HYBRID_COMMA)
+ && (*arg == ','))) {
+ entry->tag = option->tag;
+ entry->fopt = true;
+ return option;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static inline bool is_short_option(const char * arg)
+{
+ return (arg[0]=='-') && arg[1] && (arg[1]!='-');
+}
+
+static inline bool is_long_option(const char * arg)
+{
+ return (arg[0]=='-') && (arg[1]=='-') && arg[2];
+}
+
+static inline bool is_last_option(const char * arg)
+{
+ return (arg[0]=='-') && (arg[1]=='-') && !arg[2];
+}
+
+static inline bool is_hybrid_option(
+ const char * arg,
+ const struct argv_option options[])
+{
+ const struct argv_option * option;
+ struct argv_entry entry;
+
+ if (!is_short_option(arg))
+ return false;
+
+ if (!(option = argv_long_option(++arg,options,&entry)))
+ return false;
+
+ if (!(option->flags & ARGV_OPTION_HYBRID_SWITCH))
+ if (argv_short_option(arg,options,&entry))
+ return false;
+
+ return true;
+}
+
+static inline bool is_arg_in_paradigm(const char * arg, const char * paradigm)
+{
+ size_t len;
+ const char * ch;
+
+ for (ch=paradigm,len=strlen(arg); ch; ) {
+ if (!strncmp(arg,ch,len)) {
+ if (!*(ch += len))
+ return true;
+ else if (*ch == '|')
+ return true;
+ }
+
+ if ((ch = strchr(ch,'|')))
+ ch++;
+ }
+
+ return false;
+}
+
+static inline const struct argv_option * option_from_tag(
+ const struct argv_option options[],
+ int tag)
+{
+ const struct argv_option * option;
+
+ for (option=options; option->short_name || option->long_name; option++)
+ if (option->tag == tag)
+ return option;
+ return 0;
+}
+
+static void argv_scan(
+ char ** argv,
+ const struct argv_option options[],
+ struct argv_ctx * ctx,
+ struct argv_meta * meta)
+{
+ char ** parg;
+ const char * ch;
+ const char * val;
+ const struct argv_option * option;
+ struct argv_entry entry;
+ struct argv_entry * mentry;
+ enum argv_error ferr;
+ bool fval;
+ bool fnext;
+ bool fshort;
+ bool fhybrid;
+ bool fnoscan;
+
+ parg = &argv[1];
+ ch = *parg;
+ ferr = ARGV_ERROR_OK;
+ fshort = false;
+ fnoscan = false;
+ fval = false;
+ mentry = meta ? meta->entries : 0;
+
+ ctx->unitidx = 0;
+ ctx->erridx = 0;
+
+ while (ch && (ferr == ARGV_ERROR_OK)) {
+ option = 0;
+ fhybrid = false;
+
+ if (fnoscan)
+ fval = true;
+
+ else if (is_last_option(ch))
+ fnoscan = true;
+
+ else if (!fshort && is_hybrid_option(ch,options))
+ fhybrid = true;
+
+ if (!fnoscan && !fhybrid && (fshort || is_short_option(ch))) {
+ if (!fshort)
+ ch++;
+
+ if ((option = argv_short_option(ch,options,&entry))) {
+ if (ch[1]) {
+ ch++;
+ fnext = false;
+ fshort = (option->optarg == ARGV_OPTARG_NONE);
+ } else {
+ parg++;
+ ch = *parg;
+ fnext = true;
+ fshort = false;
+ }
+
+ if (option->optarg == ARGV_OPTARG_NONE) {
+ if (!fnext && ch && (*ch == '-'))
+ ferr = ARGV_ERROR_OPTARG_NONE;
+ else
+ fval = false;
+ } else if (!fnext)
+ fval = true;
+ else if (option->optarg == ARGV_OPTARG_REQUIRED) {
+ if (ch && is_short_option(ch))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (ch && is_long_option(ch))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (ch && is_last_option(ch))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (ch)
+ fval = true;
+ else
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ } else {
+ /* ARGV_OPTARG_OPTIONAL */
+ if (ch && is_short_option(ch))
+ fval = false;
+ else if (ch && is_long_option(ch))
+ fval = false;
+ else if (ch && is_last_option(ch))
+ fval = false;
+ else
+ fval = ch;
+ }
+ } else
+ ferr = ARGV_ERROR_SHORT_OPTION;
+
+ } else if (!fnoscan && (fhybrid || is_long_option(ch))) {
+ ch += (fhybrid ? 1 : 2);
+
+ if ((option = argv_long_option(ch,options,&entry))) {
+ val = ch + strlen(option->long_name);
+
+ /* val[0] is either '=' (or ',') or '\0' */
+ if (!val[0]) {
+ parg++;
+ ch = *parg;
+ }
+
+ if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH))
+ ferr = ARGV_ERROR_HYBRID_NONE;
+ else if (option->optarg == ARGV_OPTARG_NONE) {
+ if (val[0]) {
+ ferr = ARGV_ERROR_OPTARG_NONE;
+ ctx->errch = val + 1;
+ } else
+ fval = false;
+ } else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY))
+ ferr = ARGV_ERROR_HYBRID_ONLY;
+ else if (val[0] && (option->flags & ARGV_OPTION_HYBRID_JOINED)) {
+ fval = true;
+ ch = val;
+ } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE))
+ ferr = ARGV_ERROR_HYBRID_SPACE;
+ else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL))
+ ferr = ARGV_ERROR_HYBRID_EQUAL;
+ else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA))
+ ferr = ARGV_ERROR_HYBRID_COMMA;
+ else if (!fhybrid && (val[0]==','))
+ ferr = ARGV_ERROR_HYBRID_COMMA;
+ else if (val[0] && !val[1])
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (val[0] && val[1]) {
+ fval = true;
+ ch = ++val;
+ } else if (option->optarg == ARGV_OPTARG_REQUIRED) {
+ if (!val[0] && !*parg)
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (*parg && is_short_option(*parg))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (*parg && is_long_option(*parg))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else if (*parg && is_last_option(*parg))
+ ferr = ARGV_ERROR_OPTARG_REQUIRED;
+ else
+ fval = true;
+ } else {
+ /* ARGV_OPTARG_OPTIONAL */
+ fval = val[0];
+ }
+ } else
+ ferr = ARGV_ERROR_LONG_OPTION;
+ }
+
+ if (ferr == ARGV_ERROR_OK)
+ if (option && fval && option->paradigm)
+ if (!is_arg_in_paradigm(ch,option->paradigm))
+ ferr = ARGV_ERROR_OPTARG_PARADIGM;
+
+ if (ferr == ARGV_ERROR_OK)
+ if (!option && !ctx->unitidx)
+ ctx->unitidx = parg - argv;
+
+ if (ferr != ARGV_ERROR_OK) {
+ ctx->errcode = ferr;
+ ctx->errch = ctx->errch ? ctx->errch : ch;
+ ctx->erropt = option;
+ ctx->erridx = parg - argv;
+ return;
+ } else if (ctx->mode == ARGV_MODE_SCAN) {
+ if (!fnoscan)
+ ctx->nentries++;
+ else if (fval)
+ ctx->nentries++;
+
+ if (fval || !option) {
+ parg++;
+ ch = *parg;
+ }
+ } else if (ctx->mode == ARGV_MODE_COPY) {
+ if (fnoscan) {
+ if (fval) {
+ mentry->arg = ch;
+ mentry->fnoscan = true;
+ mentry++;
+ }
+
+ parg++;
+ ch = *parg;
+ } else if (option) {
+ mentry->arg = fval ? ch : 0;
+ mentry->tag = option->tag;
+ mentry->fopt = true;
+ mentry->fval = fval;
+ mentry++;
+
+ if (fval) {
+ parg++;
+ ch = *parg;
+ }
+ } else {
+ mentry->arg = ch;
+ mentry++;
+ parg++;
+ ch = *parg;
+ }
+ }
+ }
+}
+
+static const char * argv_program_name(const char * program_path)
+{
+ const char * ch;
+
+ if (program_path) {
+ if ((ch = strrchr(program_path,'/')))
+ return *(++ch) ? ch : 0;
+
+ if ((ch = strrchr(program_path,'\\')))
+ return *(++ch) ? ch : 0;
+ }
+
+ return program_path;
+}
+
+static void argv_show_error(struct argv_ctx * ctx)
+{
+ fprintf(stderr,"%s: error: ",ctx->program);
+
+ switch (ctx->errcode) {
+ case ARGV_ERROR_SHORT_OPTION:
+ fprintf(stderr,"'-%c' is not a valid short option\n",*ctx->errch);
+ break;
+
+ case ARGV_ERROR_LONG_OPTION:
+ fprintf(stderr,"'--%s' is not a valid long option\n",ctx->errch);
+ break;
+
+ case ARGV_ERROR_OPTARG_NONE:
+ fprintf(stderr,"'%s' is not a valid option value for [%s%c%s%s%s] "
+ "(option values may not be specified)\n",
+ ctx->errch,
+ ctx->erropt->short_name ? "-" : "",
+ ctx->erropt->short_name,
+ ctx->erropt->short_name ? "," : "",
+ ctx->erropt->long_name ? "--" : "",
+ ctx->erropt->long_name);
+ break;
+
+ case ARGV_ERROR_OPTARG_REQUIRED:
+ fprintf(stderr,"option [%s%c%s%s%s] requires %s %s%s%s\n",
+ ctx->erropt->short_name ? "-" : "",
+ ctx->erropt->short_name,
+ ctx->erropt->short_name ? "," : "",
+ ctx->erropt->long_name ? "--" : "",
+ ctx->erropt->long_name,
+ ctx->erropt->paradigm ? "one of the following values:" : "a value",
+ ctx->erropt->paradigm ? "{" : "",
+ ctx->erropt->paradigm ? ctx->erropt->paradigm : "",
+ ctx->erropt->paradigm ? "}" : "");
+ break;
+
+ case ARGV_ERROR_OPTARG_PARADIGM:
+ fprintf(stderr,"'%s' is not a valid option value for [%s%c%s%s%s]={%s}\n",
+ ctx->errch,
+ ctx->erropt->short_name ? "-" : "",
+ ctx->erropt->short_name,
+ ctx->erropt->short_name ? "," : "",
+ ctx->erropt->long_name ? "--" : "",
+ ctx->erropt->long_name,
+ ctx->erropt->paradigm);
+ break;
+
+ case ARGV_ERROR_HYBRID_NONE:
+ fprintf(stderr,"-%s is not a synonym for --%s\n",
+ ctx->erropt->long_name,
+ ctx->erropt->long_name);
+ break;
+
+ case ARGV_ERROR_HYBRID_ONLY:
+ fprintf(stderr,"--%s is not a synonym for -%s\n",
+ ctx->erropt->long_name,
+ ctx->erropt->long_name);
+ break;
+
+ case ARGV_ERROR_HYBRID_SPACE:
+ case ARGV_ERROR_HYBRID_EQUAL:
+ case ARGV_ERROR_HYBRID_COMMA:
+ fprintf(stderr,"-%s: illegal value assignment; valid syntax is "
+ "-%s%sVAL\n",
+ ctx->erropt->long_name,
+ ctx->erropt->long_name,
+ (ctx->erropt->flags & ARGV_OPTION_HYBRID_SPACE)
+ ? " " : (ctx->erropt->flags & ARGV_OPTION_HYBRID_EQUAL)
+ ? "=" : (ctx->erropt->flags & ARGV_OPTION_HYBRID_COMMA)
+ ? "," : "");
+
+ break;
+
+ case ARGV_ERROR_INTERNAL:
+ fputs("internal error",stderr);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void argv_show_status(
+ const struct argv_option options[],
+ struct argv_ctx * ctx,
+ struct argv_meta * meta)
+{
+ int argc;
+ char ** argv;
+ struct argv_entry * entry;
+ const struct argv_option * option;
+ char short_name[2] = {0};
+ const char * space = "";
+
+ fputs("\n\nconcatenated command line:\n",stderr);
+ for (argv=meta->argv; *argv; argv++) {
+ fprintf(stderr,"%s%s",space,*argv);
+ space = " ";
+ }
+
+ fputs("\n\nargument vector:\n",stderr);
+ for (argc=0,argv=meta->argv; *argv; argc++,argv++)
+ fprintf(stderr,"argv[%d]: %s\n",argc,*argv);
+
+ fputs("\n\nparsed entries:\n",stderr);
+ for (entry=meta->entries; entry->arg || entry->fopt; entry++)
+ if (entry->fopt) {
+ option = option_from_tag(options,entry->tag);
+ short_name[0] = option->short_name;
+
+ if (entry->fval)
+ fprintf(stderr,"[-%s,--%s] := %s\n",
+ short_name,option->long_name,entry->arg);
+ else
+ fprintf(stderr,"[-%s,--%s]\n",
+ short_name,option->long_name);
+ } else
+ fprintf(stderr,"<program arg> := %s\n",entry->arg);
+
+ fputs("\n\n",stderr);
+}
+
+static struct argv_meta * argv_free_impl(struct argv_meta_impl * imeta)
+{
+ if (imeta->argv)
+ free(imeta->argv);
+
+ if (imeta->strbuf)
+ free(imeta->strbuf);
+
+ if (imeta->meta.entries)
+ free(imeta->meta.entries);
+
+ free(imeta);
+ return 0;
+}
+
+static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx)
+{
+ struct argv_meta_impl * imeta;
+ char ** vector;
+ char * dst;
+ size_t size;
+ int argc;
+ int i;
+
+ if (!(imeta = calloc(1,sizeof(*imeta))))
+ return 0;
+
+ if (ctx->flags & ARGV_CLONE_VECTOR) {
+ for (vector=argv,argc=0,size=0; *vector; vector++) {
+ size += strlen(*vector) + 1;
+ argc++;
+ }
+
+ if (!(imeta->argv = calloc(argc+1,sizeof(char *))))
+ return argv_free_impl(imeta);
+ else if (!(imeta->strbuf = calloc(1,size+1)))
+ return argv_free_impl(imeta);
+
+ for (i=0,dst=imeta->strbuf; i<argc; i++) {
+ strcpy(dst,argv[i]);
+ imeta->argv[i] = dst;
+ dst += strlen(dst)+1;
+ }
+
+ imeta->meta.argv = imeta->argv;
+ } else
+ imeta->meta.argv = argv;
+
+ if (!(imeta->meta.entries = calloc(
+ ctx->nentries+1,
+ sizeof(struct argv_entry))))
+ return argv_free_impl(imeta);
+ else
+ return &imeta->meta;
+}
+
+static struct argv_meta * argv_get(
+ char * argv[],
+ const struct argv_option options[],
+ int flags)
+{
+ struct argv_meta * meta;
+ struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0};
+
+ argv_scan(argv,options,&ctx,0);
+
+ if (ctx.errcode != ARGV_ERROR_OK) {
+ if (!ctx.program)
+ ctx.program = argv_program_name(argv[0]);
+
+ if (ctx.flags & ARGV_VERBOSITY_ERRORS)
+ argv_show_error(&ctx);
+
+ return 0;
+ }
+
+ if (!(meta = argv_alloc(argv,&ctx)))
+ return 0;
+
+ ctx.mode = ARGV_MODE_COPY;
+ argv_scan(meta->argv,options,&ctx,meta);
+
+ if (ctx.errcode != ARGV_ERROR_OK) {
+ if (!ctx.program)
+ ctx.program = argv[0];
+
+ ctx.errcode = ARGV_ERROR_INTERNAL;
+ argv_show_error(&ctx);
+ argv_free(meta);
+
+ return 0;
+ }
+
+ if (ctx.flags & ARGV_VERBOSITY_STATUS)
+ argv_show_status(options,&ctx,meta);
+
+ return meta;
+}
+
+static void argv_free(struct argv_meta * xmeta)
+{
+ struct argv_meta_impl * imeta;
+ uintptr_t addr;
+
+ if (xmeta) {
+ addr = (uintptr_t)xmeta - offsetof(struct argv_meta_impl,meta);
+ imeta = (struct argv_meta_impl *)addr;
+ argv_free_impl(imeta);
+ }
+}
+
+static void argv_usage(
+ FILE * file,
+ const char * header,
+ const struct argv_option options[],
+ const char * mode)
+{
+ const struct argv_option * option;
+ bool fshort,flong;
+ bool fnewline;
+ size_t len,optlen;
+ size_t paralen,rparalen,mparalen;
+ size_t desclen,rdesclen;
+
+ char * para;
+ char * next_para;
+ char * desc;
+ char * next_desc;
+ char * paradigm;
+ char * buf;
+ size_t buflen;
+ const char * sdescription;
+ const char * sargname;
+
+ const char indent[] = " ";
+ const int rblen = sizeof("}") - sizeof(char);
+ const int rbblen = sizeof("{]") - sizeof(char);
+ const int brcklen= sizeof("[]") - sizeof(char);
+ const int solen = sizeof("-") - sizeof(char);
+ const int lolen = sizeof("--") - sizeof(char);
+ const int slolen = sizeof("-X,--") - sizeof(char);
+
+ fshort = mode ? !strcmp(mode,"short") : 0;
+ flong = fshort ? 0 : mode && !strcmp(mode,"long");
+
+ if (header)
+ fprintf(stdout,"%s",header);
+
+ optlen = 0;
+ paralen = 0;
+
+ for (option=options; option->short_name || option->long_name; option++) {
+ if (fshort)
+ len = option->short_name ? sizeof(char) + solen : 0;
+ else if (flong)
+ len = option->long_name ? strlen(option->long_name) + lolen : 0;
+ else
+ len = option->long_name ? strlen(option->long_name) + slolen : 0;
+
+ if (len) {
+ if (len > optlen)
+ optlen = len;
+
+ if (option->argname)
+ len = strlen(option->argname);
+ else if (option->paradigm)
+ len = strlen(option->paradigm) + strlen("{}");
+ else if (option->optarg != ARGV_OPTARG_NONE)
+ len = strlen("<val>");
+
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ len += strlen("[]");
+
+ if (len > paralen)
+ paralen = len;
+ }
+ }
+
+ optlen += ARGV_TAB_WIDTH;
+ optlen &= (~(ARGV_TAB_WIDTH-1));
+
+ paradigm = next_para = buf = 0;
+ fnewline = false;
+ rparalen = 0;
+ mparalen = 0;
+
+ if (paralen) {
+ paralen += (ARGV_TAB_WIDTH);
+ paralen &= (~(ARGV_TAB_WIDTH-1));
+ mparalen = paralen + 2*rbblen;
+
+ if (optlen + paralen > 64)
+ paralen = 32;
+ }
+
+ /* account for ' ','\t', try to fit in 80 or 96 columns */
+ if (optlen+paralen+2+ARGV_TAB_WIDTH < 80-32)
+ desclen = 80 - (optlen+paralen+2+ARGV_TAB_WIDTH);
+ else if (optlen+paralen+2+ARGV_TAB_WIDTH < 96-32)
+ desclen = 96 - (optlen+paralen+2+ARGV_TAB_WIDTH);
+ else
+ desclen = 32;
+
+ buflen = 0;
+ rdesclen = 1;
+
+ for (option=options; option->short_name || option->long_name; option++) {
+ if (fshort && !option->short_name)
+ continue;
+ else if (flong && !option->long_name)
+ continue;
+
+ if (option->paradigm) {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ rparalen = strlen(option->paradigm) - 2*rbblen;
+ else
+ rparalen = strlen(option->paradigm) - 2*rblen;
+ }
+
+ sdescription = option->description ? option->description : "";
+ sargname = option->argname ? option->argname : "";
+
+ if (option->paradigm)
+ rdesclen = snprintf(buf,buflen,sdescription,option->paradigm);
+ else
+ rdesclen = snprintf(buf,buflen,sdescription,sargname);
+
+ if (fnewline)
+ (void)0;
+
+ if ((rparalen > paralen) || (rdesclen > desclen)) {
+ if (!fnewline) {
+ (void)0;
+ fnewline = true;
+ }
+ } else
+ fnewline = false;
+
+ if (fshort)
+ fprintf(file,"%s-%-*c",indent,(int)(optlen-solen),option->short_name);
+ else if (flong)
+ fprintf(file,
+ (option->flags & ARGV_OPTION_HYBRID_ONLY)
+ ? "%s -%-*s"
+ : "%s--%-*s",
+ indent,(int)(optlen-lolen),option->long_name);
+ else {
+ if (option->short_name && option->long_name)
+ fprintf(file,
+ (option->flags & ARGV_OPTION_HYBRID_ONLY)
+ ? "%s-%c, -%-*s"
+ : "%s-%c,--%-*s",
+ indent,option->short_name,
+ (int)(optlen-slolen),option->long_name);
+ else if (option->short_name)
+ fprintf(file,"%s-%-*c",
+ indent,(int)(optlen-solen),option->short_name);
+ else
+ fprintf(file,
+ (option->flags & ARGV_OPTION_HYBRID_ONLY)
+ ? "%s%3s -%-*s"
+ : "%s%3s--%-*s",
+ indent,"",
+ (int)(optlen-slolen),option->long_name);
+ }
+
+ if (rdesclen > buflen) {
+ if (buf) {
+ free(buf);
+ buf = 0;
+ }
+
+ len = rdesclen + 512;
+ len &= (~511);
+
+ if ((buf = calloc(1,len))) {
+ buflen = len;
+
+ if (option->paradigm)
+ rdesclen = snprintf(buf,buflen,
+ option->description,
+ option->paradigm);
+ else
+ rdesclen = snprintf(buf,buflen,
+ option->description,
+ option->argname);
+ } else {
+ buflen = 0;
+ continue;
+ }
+ }
+
+ if (option->argname) {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ fprintf(file,"[%s]%-*c",
+ option->argname,
+ (int)(paralen-strlen(option->argname)-brcklen),' ');
+ else
+ fprintf(file,"%s%-*c",
+ option->argname,
+ (int)(paralen-strlen(option->argname)),' ');
+ para = (char *)0;
+ } else if (option->paradigm && (rparalen <= paralen)) {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ fprintf(file,"[{%s}]%-*c",
+ option->paradigm,
+ (int)(paralen-strlen(option->paradigm)-2*rbblen),' ');
+ else
+ fprintf(file,"{%s}%-*c",
+ option->paradigm,
+ (int)(paralen-strlen(option->paradigm)-rbblen),' ');
+ para = (char *)0;
+ } else if (option->paradigm) {
+ if (!paradigm && !(paradigm = calloc(1,mparalen))) {
+ fputc('\n',file);
+ continue;
+ } else
+ para = strcpy(paradigm,option->paradigm);
+
+ if (option->optarg == ARGV_OPTARG_OPTIONAL) {
+ fputs("[{",file);
+ rparalen = paralen - rbblen;
+ } else {
+ fputc('{',file);
+ rparalen = paralen - rblen;
+ }
+ } else {
+ fprintf(file,"%-*c",(int)paralen,' ');
+ para = (char *)0;
+ }
+
+
+ if (!para && option->description && rdesclen <= desclen) {
+ fputc('\t',file);
+ fputs(buf,file);
+ desc = (char *)0;
+ } else if (option->description)
+ desc = buf;
+ else
+ desc = (char *)0;
+
+ while (para || desc) {
+ if (para) {
+ next_para = para+rparalen-1;
+
+ for (; (next_para>para) && (*next_para!='|'); )
+ next_para--;
+
+ if (para > paradigm) {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ fputs(" ",file);
+ else
+ fputc(' ',file);
+ }
+
+ if (*next_para != '|') {
+ fprintf(file,"%s",para);
+ para = (char *)0;
+ } else if (next_para > para) {
+ *next_para = '\0';
+ fprintf(file,"%-*s",(int)rparalen,para);
+ *next_para = '|';
+ para = next_para;
+ rparalen = strlen(para);
+
+ /* 2*rbblen,2*rblen, etc.: account for indentation */
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ rparalen = (rparalen+2*rbblen > paralen)
+ ? paralen-rbblen
+ : rparalen;
+ else
+ rparalen = (rparalen+2*rblen > paralen)
+ ? paralen-rblen
+ : rparalen;
+ } else {
+ if (option->optarg == ARGV_OPTARG_OPTIONAL)
+ fprintf(file,"%s}]%-*c",para,
+ (int)(paralen-strlen(para)-rbblen),' ');
+ else
+ fprintf(file,"%s}%-*c",para,
+ (int)(paralen-strlen(para)-rblen),' ');
+ para = (char *)0;
+ }
+ } else if (desc > buf)
+ fprintf(file,"%-*c",(int)paralen,' ');
+
+ if (desc) {
+ if (desc > buf)
+ fputs("\t ",file);
+ else
+ fputc('\t',file);
+
+ if ((rdesclen = strlen(desc)+(desc>buf)) <= desclen) {
+ fputs(desc,file);
+ desc = (char *)0;
+ } else {
+ next_desc = desc + desclen - 1;
+
+ for (; (next_desc > desc)
+ && (*next_desc != ' ')
+ && (*next_desc != '\n'); )
+ next_desc--;
+
+ if ((*next_desc != ' ') && (*next_desc!='\n')) {
+ fputs(desc,file);
+ desc = (char *)0;
+ } else if (next_desc > desc) {
+ *next_desc = '\0';
+ fputs(desc,file);
+ desc = ++next_desc;
+ } else {
+ fputs(desc,file);
+ desc = (char *)0;
+ }
+ }
+ }
+
+ if (para || desc)
+ fprintf(file,"\n%s%-*c",indent,(int)optlen,' ');
+ }
+
+ fputc('\n',file);
+ }
+
+ if (paradigm)
+ free(paradigm);
+
+ if (buf)
+ free(buf);
+}
+
+#endif
+
+#endif
diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h
new file mode 100644
index 0000000..d8e3111
--- /dev/null
+++ b/src/internal/slibtool_driver_impl.h
@@ -0,0 +1,31 @@
+#ifndef SOFORT_DRIVER_IMPL_H
+#define SOFORT_DRIVER_IMPL_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <slibtool/slibtool.h>
+#include "argv/argv.h"
+
+extern int slibtool_main(int, char **, char **);
+extern const struct argv_option slbt_default_options[];
+
+enum app_tags {
+ TAG_HELP,
+ TAG_VERSION,
+};
+
+struct slbt_driver_ctx_impl {
+ struct slbt_common_ctx cctx;
+ struct slbt_driver_ctx ctx;
+};
+
+struct slbt_unit_ctx_impl {
+ const char * path;
+ struct slbt_input map;
+ struct slbt_common_ctx cctx;
+ struct slbt_unit_ctx uctx;
+};
+
+#endif
diff --git a/src/logic/slbt_map_input.c b/src/logic/slbt_map_input.c
new file mode 100644
index 0000000..2da2429
--- /dev/null
+++ b/src/logic/slbt_map_input.c
@@ -0,0 +1,51 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <slibtool/slibtool.h>
+
+int slbt_map_input(
+ int fd,
+ const char * path,
+ int prot,
+ struct slbt_input * map)
+{
+ struct stat st;
+ bool fnew;
+ int ret;
+
+ if ((fnew = (fd < 0)))
+ fd = open(path,O_RDONLY | O_CLOEXEC);
+
+ if (fd < 0)
+ return -1;
+
+ if ((ret = fstat(fd,&st) < 0) && fnew)
+ close(fd);
+
+ if (ret < 0)
+ return -1;
+
+ map->size = st.st_size;
+ map->addr = mmap(0,map->size,prot,MAP_PRIVATE,fd,0);
+
+ if (fnew)
+ close(fd);
+
+ return (map->addr == MAP_FAILED) ? -1 : 0;
+}
+
+int slbt_unmap_input(struct slbt_input * map)
+{
+ return munmap(map->addr,map->size);
+}
diff --git a/src/skin/slbt_skin_default.c b/src/skin/slbt_skin_default.c
new file mode 100644
index 0000000..644b6b9
--- /dev/null
+++ b/src/skin/slbt_skin_default.c
@@ -0,0 +1,12 @@
+#include "slibtool_driver_impl.h"
+#include "argv/argv.h"
+
+const struct argv_option slbt_default_options[] = {
+ {"version", 'v',TAG_VERSION,ARGV_OPTARG_NONE,0,0,0,
+ "show version information"},
+
+ {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0,
+ "show usage information [listing %s options only]"},
+
+ {0,0,0,0,0,0,0,0}
+};
diff --git a/src/slibtool.c b/src/slibtool.c
new file mode 100644
index 0000000..6fb3422
--- /dev/null
+++ b/src/slibtool.c
@@ -0,0 +1,67 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016 Z. Gilboa */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <slibtool/slibtool.h>
+#include "slibtool_version.h"
+#include "slibtool_driver_impl.h"
+
+#ifndef SLBT_DRIVER_FLAGS
+#define SLBT_DRIVER_FLAGS SLBT_DRIVER_VERBOSITY_ERRORS \
+ | SLBT_DRIVER_VERBOSITY_USAGE
+#endif
+
+static const char vermsg[] = "%s (git://midipix.org/slibtool): commit %s.\n";
+
+static ssize_t slibtool_version(struct slbt_driver_ctx * dctx)
+{
+ return fprintf(stdout,vermsg,dctx->program,SLIBTOOL_GIT_VERSION);
+}
+
+static void slibtool_perform_unit_actions(struct slbt_unit_ctx * uctx)
+{
+}
+
+static int slibtool_exit(struct slbt_driver_ctx * dctx, int nerrors)
+{
+ slbt_free_driver_ctx(dctx);
+ return nerrors ? 2 : 0;
+}
+
+int slibtool_main(int argc, char ** argv, char ** envp)
+{
+ int ret;
+ struct slbt_driver_ctx * dctx;
+ struct slbt_unit_ctx * uctx;
+ const char ** unit;
+
+ if ((ret = slbt_get_driver_ctx(argv,envp,SLBT_DRIVER_FLAGS,&dctx)))
+ return (ret == SLBT_USAGE) ? !--argc : 2;
+
+ if (dctx->cctx->drvflags & SLBT_DRIVER_VERSION)
+ if ((slibtool_version(dctx)) < 0)
+ return slibtool_exit(dctx,2);
+
+ for (unit=dctx->units; *unit; unit++) {
+ if (!(slbt_get_unit_ctx(dctx,*unit,&uctx))) {
+ slibtool_perform_unit_actions(uctx);
+ ret += uctx->nerrors;
+ slbt_free_unit_ctx(uctx);
+ }
+ }
+
+ return slibtool_exit(dctx,ret);
+}
+
+#ifndef SLIBTOOL_IN_A_BOX
+
+int main(int argc, char ** argv, char ** envp)
+{
+ return slibtool_main(argc,argv,envp);
+}
+
+#endif
diff --git a/sysinfo/compiler/any-compiler.mk b/sysinfo/compiler/any-compiler.mk
new file mode 100644
index 0000000..4c98621
--- /dev/null
+++ b/sysinfo/compiler/any-compiler.mk
@@ -0,0 +1,29 @@
+ifeq ($(CROSS_COMPILE)x,x)
+ CROSS_HOST =
+ CROSS_HOST_SPEC =
+else
+ CROSS_HOST =
+ CROSS_HOST_SPEC =
+endif
+
+
+ifeq ($(USER_CC)x,x)
+ CC = $(NATIVE_CC) $(CROSS_HOST_SPEC)
+else
+ CC = $(USER_CC) $(CROSS_HOST_SPEC)
+endif
+
+ifeq ($(USER_CPP)x,x)
+ CPP = $(NATIVE_CC) $(CROSS_HOST_SPEC) -E
+else
+ CPP = $(USER_CPP) $(CROSS_HOST_SPEC) -E
+endif
+
+ifeq ($(USER_CXX)x,x)
+ CXX = $(NATIVE_CC) $(CROSS_HOST_SPEC) -std=c++
+else
+ CXX = $(USER_CXX) $(CROSS_HOST_SPEC) -std=c++
+endif
+
+
+CFLAGS_PIC = -fPIC
diff --git a/sysinfo/compiler/clang.mk b/sysinfo/compiler/clang.mk
new file mode 100644
index 0000000..77b4b86
--- /dev/null
+++ b/sysinfo/compiler/clang.mk
@@ -0,0 +1,31 @@
+ifeq ($(CROSS_COMPILE)x,x)
+ CROSS_HOST =
+ CROSS_HOST_SPEC =
+else ifeq ($(CROSS_HOST)x,x)
+ CROSS_HOST = $(HOST)
+ CROSS_HOST_SPEC = --target=$(HOST)
+else
+ CROSS_HOST_SPEC = --target=$(CROSS_HOST)
+endif
+
+
+ifeq ($(USER_CC)x,x)
+ CC = $(NATIVE_CC) $(CROSS_HOST_SPEC)
+else
+ CC = $(USER_CC) $(CROSS_HOST_SPEC)
+endif
+
+ifeq ($(USER_CPP)x,x)
+ CPP = $(NATIVE_CC) $(CROSS_HOST_SPEC) -E
+else
+ CPP = $(USER_CPP) $(CROSS_HOST_SPEC) -E
+endif
+
+ifeq ($(USER_CXX)x,x)
+ CXX = $(NATIVE_CC)++ $(CROSS_HOST_SPEC)
+else
+ CXX = $(USER_CXX) $(CROSS_HOST_SPEC)
+endif
+
+
+CFLAGS_PIC = -fPIC
diff --git a/sysinfo/compiler/cparser.mk b/sysinfo/compiler/cparser.mk
new file mode 100644
index 0000000..6c4dc8e
--- /dev/null
+++ b/sysinfo/compiler/cparser.mk
@@ -0,0 +1,31 @@
+ifeq ($(CROSS_COMPILE)x,x)
+ CROSS_HOST =
+ CROSS_HOST_SPEC =
+else ifeq ($(CROSS_HOST)x,x)
+ CROSS_HOST = $(HOST)
+ CROSS_HOST_SPEC = --target=$(HOST)
+else
+ CROSS_HOST_SPEC = --target=$(CROSS_HOST)
+endif
+
+
+ifeq ($(USER_CC)x,x)
+ CC = $(NATIVE_CC) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp
+else
+ CC = $(USER_CC) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp
+endif
+
+ifeq ($(USER_CPP)x,x)
+ CPP = $(NATIVE_CC) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp -E
+else
+ CPP = $(USER_CPP) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp -E
+endif
+
+ifeq ($(USER_CXX)x,x)
+ CXX = $(NATIVE_CC) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp -std=c++
+else
+ CXX = $(USER_CXX) $(CROSS_HOST_SPEC) -Wno-experimental -integrated-cpp -std=c++
+endif
+
+
+CFLAGS_PIC = -fPIC
diff --git a/sysinfo/compiler/gcc.mk b/sysinfo/compiler/gcc.mk
new file mode 100644
index 0000000..d14d8dc
--- /dev/null
+++ b/sysinfo/compiler/gcc.mk
@@ -0,0 +1,24 @@
+ifeq ($(USER_CC)x,x)
+ ifeq ($(CROSS_COMPILE)x,x)
+ CC = $(CROSS_COMPILE)$(NATIVE_CC)
+ else
+ CC = $(CROSS_COMPILE)gcc
+ endif
+else
+ CC = $(USER_CC)
+endif
+
+ifeq ($(USER_CPP)x,x)
+ CPP = $(CROSS_COMPILE)cpp
+else
+ CPP = $(USER_CPP)
+endif
+
+ifeq ($(USER_CXX)x,x)
+ CXX = $(CROSS_COMPILE)c++
+else
+ CXX = $(USER_CXX)
+endif
+
+
+CFLAGS_PIC = -fPIC
diff --git a/sysinfo/host/any-host.mk b/sysinfo/host/any-host.mk
new file mode 100644
index 0000000..acb606a
--- /dev/null
+++ b/sysinfo/host/any-host.mk
@@ -0,0 +1,7 @@
+include $(PROJECT_DIR)/sysinfo/os/any-os.mk
+
+ARCH =
+HOST_BITS =
+HOST_UNDERSCORE =
+
+CROSS_HOST = $(TARGET)
diff --git a/sysinfo/host/host.sh b/sysinfo/host/host.sh
new file mode 100755
index 0000000..e4079ee
--- /dev/null
+++ b/sysinfo/host/host.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+error_msg()
+{
+ echo $@ >&2
+}
+
+host_test()
+{
+ mb_hdrdir=$(pwd)/build
+ mkdir -p $mb_hdrdir || exit 2
+
+ if [ -z "$mb_compiler" ]; then
+ echo "config error: compiler not set."
+ exit 2
+ fi
+
+ $mb_compiler -dM -E - < /dev/null > /dev/null && return 0
+
+ error_msg "config error: invalid compiler."
+ exit 2
+}
+
+host_endian_h()
+{
+ mb_header='endian.h'
+ rm -f "$mb_hdrdir"/$mb_header
+
+ # portable
+ printf "#include <$mb_header>" | $mb_compiler $mb_cflags \
+ -E - > /dev/null 2>/dev/null \
+ && return 0
+
+ # non-portable
+ mb_hosthdr=
+
+ [ -z $mb_hosthdr ] && printf "#include <sys/$mb_header>" | $mb_compiler $mb_cflags \
+ -E - > /dev/null 2>/dev/null \
+ && mb_hosthdr='sys/'$mb_header
+
+ [ -z $mb_hosthdr ] && printf "#include <machine/$mb_header>" | $mb_compiler $mb_cflags \
+ -E - > /dev/null 2>/dev/null \
+ && mb_hosthdr='machine/'$mb_header
+
+ if [ -z "$mb_hosthdr" ]; then
+ error_msg "config error: could not find an alternate <$mb_header>."
+ exit 2
+ fi
+
+ printf "#include <%s>\\n" $mb_hosthdr > "$mb_hdrdir"/$mb_header || exit 2
+}
+
+
+# one: args
+for arg ; do
+ case "$arg" in
+ --help) usage
+ ;;
+ --compiler=*)
+ mb_compiler=${arg#*=}
+ ;;
+ --cflags=*)
+ mb_cflags=${arg#*=}
+ ;;
+ *)
+ error_msg ${arg#}: "unsupported config argument."
+ exit 2
+ ;;
+ esac
+done
+
+
+# two: test
+host_test
+
+
+# three: headers
+host_endian_h
+
+
+# all done
+exit 0
diff --git a/sysinfo/host/i686-nt32-midipix.mk b/sysinfo/host/i686-nt32-midipix.mk
new file mode 100644
index 0000000..fd4b8f8
--- /dev/null
+++ b/sysinfo/host/i686-nt32-midipix.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/midipix.mk
+
+ARCH = nt32
+HOST_BITS = 32
+HOST_UNDERSCORE = '_'
diff --git a/sysinfo/host/i686-unknown-linux.mk b/sysinfo/host/i686-unknown-linux.mk
new file mode 100644
index 0000000..bec437c
--- /dev/null
+++ b/sysinfo/host/i686-unknown-linux.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/linux.mk
+
+ARCH = i386
+HOST_BITS = 32
+HOST_UNDERSCORE = '_'
diff --git a/sysinfo/host/i686-w64-mingw32.mk b/sysinfo/host/i686-w64-mingw32.mk
new file mode 100644
index 0000000..b18e2e3
--- /dev/null
+++ b/sysinfo/host/i686-w64-mingw32.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/mingw.mk
+
+ARCH = w32
+HOST_BITS = 32
+HOST_UNDERSCORE = '_'
diff --git a/sysinfo/host/native.mk b/sysinfo/host/native.mk
new file mode 100644
index 0000000..f0cf720
--- /dev/null
+++ b/sysinfo/host/native.mk
@@ -0,0 +1,45 @@
+include $(PROJECT_DIR)/sysinfo/os/$(NATIVE_OS).mk
+
+OS = $(NATIVE_OS)
+HOST_BITS = $(NATIVE_OS_BITS)
+HOST_UNDERSCORE = $(NATIVE_OS_UNDERSCORE)
+
+ifeq ($(OS),linux)
+ ifeq ($(HOST_BITS),32)
+ ARCH = i386
+ else ifeq ($(HOST_BITS),64)
+ ARCH = x86_64
+ endif
+endif
+
+ifeq ($(OS),midipix)
+ ifeq ($(HOST_BITS),32)
+ ARCH = nt32
+ else ifeq ($(HOST_BITS),64)
+ ARCH = nt64
+ endif
+endif
+
+ifeq ($(OS),mingw)
+ ifeq ($(HOST_BITS),32)
+ ARCH = w32
+ else ifeq ($(HOST_BITS),64)
+ ARCH = w64
+ endif
+endif
+
+ifeq ($(OS),bsd)
+ ifeq ($(HOST_BITS),32)
+ ARCH = bsd32
+ else ifeq ($(HOST_BITS),64)
+ ARCH = bsd64
+ endif
+endif
+
+ifeq ($(OS),darwin)
+ ifeq ($(HOST_BITS),32)
+ ARCH = dw32
+ else ifeq ($(HOST_BITS),64)
+ ARCH = dw64
+ endif
+endif
diff --git a/sysinfo/host/x86_64-nt64-midipix.mk b/sysinfo/host/x86_64-nt64-midipix.mk
new file mode 100644
index 0000000..d0e1d52
--- /dev/null
+++ b/sysinfo/host/x86_64-nt64-midipix.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/midipix.mk
+
+ARCH = nt64
+HOST_BITS = 64
+HOST_UNDERSCORE = ''
diff --git a/sysinfo/host/x86_64-unknown-linux.mk b/sysinfo/host/x86_64-unknown-linux.mk
new file mode 100644
index 0000000..4bd1bff
--- /dev/null
+++ b/sysinfo/host/x86_64-unknown-linux.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/linux.mk
+
+ARCH = x86_64
+HOST_BITS = 64
+HOST_UNDERSCORE = ''
diff --git a/sysinfo/host/x86_64-w64-mingw32.mk b/sysinfo/host/x86_64-w64-mingw32.mk
new file mode 100644
index 0000000..a86f9b0
--- /dev/null
+++ b/sysinfo/host/x86_64-w64-mingw32.mk
@@ -0,0 +1,5 @@
+include $(PROJECT_DIR)/sysinfo/os/mingw.mk
+
+ARCH = w64
+HOST_BITS = 64
+HOST_UNDERSCORE = ''
diff --git a/sysinfo/os/any-os.mk b/sysinfo/os/any-os.mk
new file mode 100644
index 0000000..0aa0a75
--- /dev/null
+++ b/sysinfo/os/any-os.mk
@@ -0,0 +1,10 @@
+OS = any-os
+OS_APP_PREFIX =
+OS_APP_SUFFIX =
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .so
+OS_IMPLIB_EXT = .invalid
+OS_LIBDEF_EXT = .invalid
+OS_ARCHIVE_EXT = .a
+
+.PHONY: $(SHARED_IMPLIB)
diff --git a/sysinfo/os/bsd.mk b/sysinfo/os/bsd.mk
new file mode 100644
index 0000000..1b29c90
--- /dev/null
+++ b/sysinfo/os/bsd.mk
@@ -0,0 +1,10 @@
+OS = bsd
+OS_APP_PREFIX =
+OS_APP_SUFFIX =
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .so
+OS_IMPLIB_EXT = .invalid
+OS_LIBDEF_EXT = .invalid
+OS_ARCHIVE_EXT = .a
+
+.PHONY: $(SHARED_IMPLIB)
diff --git a/sysinfo/os/darwin.mk b/sysinfo/os/darwin.mk
new file mode 100644
index 0000000..f16b1f1
--- /dev/null
+++ b/sysinfo/os/darwin.mk
@@ -0,0 +1,12 @@
+OS = darwin
+OS_APP_PREFIX =
+OS_APP_SUFFIX =
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .dylib
+OS_IMPLIB_EXT = .invalid
+OS_LIBDEF_EXT = .invalid
+OS_ARCHIVE_EXT = .a
+
+CFLAGS_OS += -D_DARWIN_C_SOURCE
+
+.PHONY: $(SHARED_IMPLIB)
diff --git a/sysinfo/os/linux.mk b/sysinfo/os/linux.mk
new file mode 100644
index 0000000..2bd6329
--- /dev/null
+++ b/sysinfo/os/linux.mk
@@ -0,0 +1,10 @@
+OS = linux
+OS_APP_PREFIX =
+OS_APP_SUFFIX =
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .so
+OS_IMPLIB_EXT = .invalid
+OS_LIBDEF_EXT = .invalid
+OS_ARCHIVE_EXT = .a
+
+.PHONY: $(SHARED_IMPLIB)
diff --git a/sysinfo/os/midipix.mk b/sysinfo/os/midipix.mk
new file mode 100644
index 0000000..715dbcd
--- /dev/null
+++ b/sysinfo/os/midipix.mk
@@ -0,0 +1,14 @@
+OS = midipix
+OS_APP_PREFIX =
+OS_APP_SUFFIX =
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .so
+OS_IMPLIB_EXT = .lib.a
+OS_LIBDEF_EXT = .so.def
+OS_ARCHIVE_EXT = .a
+
+LDFLAGS_CONFIG += -mout-implib
+
+install-implib: shared-implib
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+ cp $(SHARED_IMPLIB) $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
diff --git a/sysinfo/os/mingw.mk b/sysinfo/os/mingw.mk
new file mode 100644
index 0000000..6fbc76d
--- /dev/null
+++ b/sysinfo/os/mingw.mk
@@ -0,0 +1,15 @@
+OS = mingw
+OS_APP_PREFIX =
+OS_APP_SUFFIX = .exe
+OS_LIB_PREFIX = lib
+OS_LIB_SUFFIX = .dll
+OS_IMPLIB_EXT = .dll.a
+OS_LIBDEF_EXT = .def
+OS_ARCHIVE_EXT = .a
+
+CFLAGS_PIC =
+LDFLAGS_CONFIG += -Wl,--out-implib,$(SHARED_IMPLIB)
+
+install-implib: shared-implib
+ mkdir -p $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
+ cp $(SHARED_IMPLIB) $(DESTDIR)///./$(PREFIX)/./$(LIBDIR)
diff --git a/sysinfo/toolchain/binutils.mk b/sysinfo/toolchain/binutils.mk
new file mode 100644
index 0000000..a29ac0c
--- /dev/null
+++ b/sysinfo/toolchain/binutils.mk
@@ -0,0 +1,17 @@
+AS = $(CROSS_COMPILE)as
+AR = $(CROSS_COMPILE)ar
+LD = $(CROSS_COMPILE)ld
+NM = $(CROSS_COMPILE)nm
+OBJDUMP = $(CROSS_COMPILE)objdump
+RANLIB = $(CROSS_COMPILE)ranlib
+SIZE = $(CROSS_COMPILE)size
+STRIP = $(CROSS_COMPILE)strip
+STRINGS = $(CROSS_COMPILE)strings
+
+
+ADDR2LINE = $(CROSS_COMPILE)addr2line
+COV = $(CROSS_COMPILE)gcov
+CXXFILT = $(CROSS_COMPILE)c++filt
+ELFEDIT = $(CROSS_COMPILE)elfedit
+OBJCOPY = $(CROSS_COMPILE)objcopy
+READELF = $(CROSS_COMPILE)readelf
diff --git a/sysinfo/toolchain/llvm.mk b/sysinfo/toolchain/llvm.mk
new file mode 100644
index 0000000..3c805a8
--- /dev/null
+++ b/sysinfo/toolchain/llvm.mk
@@ -0,0 +1,17 @@
+AS = llvm-mc -filetype=obj
+AR = llvm-ar
+LD = lld
+NM = llvm-nm
+OBJDUMP = llvm-objdump
+RANLIB = llvm-ranlib
+SIZE = llvm-size
+STRIP = $(CROSS_COMPILE)strip
+STRINGS = $(CROSS_COMPILE)strings
+
+
+ADDR2LINE = $(CROSS_COMPILE)addr2line
+COV = $(CROSS_COMPILE)gcov
+CXXFILT = $(CROSS_COMPILE)c++filt
+ELFEDIT = $(CROSS_COMPILE)elfedit
+OBJCOPY = $(CROSS_COMPILE)objcopy
+READELF = $(CROSS_COMPILE)readelf
diff --git a/sysinfo/version.sh b/sysinfo/version.sh
new file mode 100755
index 0000000..8157765
--- /dev/null
+++ b/sysinfo/version.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+usage()
+{
+cat << EOF >&2
+
+Usage:
+ -h show this HELP message
+ -s SRCDIR set source directory
+ -o OUTPUT set output header
+ -p PREFIX set macro prefix
+
+EOF
+exit 1
+}
+
+
+# one
+workdir=$(pwd)
+srcdir=
+output=
+prefix=
+
+
+while getopts "hs:o:p:" opt; do
+ case $opt in
+ h)
+ usage
+ ;;
+ s)
+ srcdir="$OPTARG"
+ ;;
+ o)
+ output="$OPTARG"
+ ;;
+ p)
+ prefix="$OPTARG"
+ ;;
+ \?)
+ printf "Invalid option: -%s" "$OPTARG" >&2
+ usage
+ ;;
+ esac
+done
+
+
+# two
+if [ -z "$srcdir" ] || [ -z "$output" ] || [ -z "$prefix" ]; then
+ usage
+fi
+
+cd "$srcdir" || exit 2
+
+gitver=`git rev-parse --verify HEAD 2>/dev/null` || gitver="unknown"
+macro=`echo "$prefix"_GIT_VERSION | tr '[:lower:]' '[:upper:]'`
+
+cd "$workdir" || exit 2
+printf "#define $macro\t\"$gitver\"\n" > "$output"
+
+# all done
+exit 0