summaryrefslogtreecommitdiff
path: root/librarian
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2008-09-01 18:44:56 +0000
committer <>2013-07-02 12:44:56 +0000
commitbd4e1730fe4d7878c4e5e2c13ea489f59e7e0f27 (patch)
tree5e605cc37a7e484e7008c7934f61e2cd25a0d57b /librarian
downloadrarian-bd4e1730fe4d7878c4e5e2c13ea489f59e7e0f27.tar.gz
Imported from /home/lorry/working-area/delta_rarian/rarian-0.8.1.tar.bz2.HEADrarian-0.8.1master
Diffstat (limited to 'librarian')
-rw-r--r--librarian/Makefile.am33
-rw-r--r--librarian/Makefile.in641
-rw-r--r--librarian/rarian-info.c699
-rw-r--r--librarian/rarian-info.h74
-rw-r--r--librarian/rarian-language.c267
-rw-r--r--librarian/rarian-language.h44
-rw-r--r--librarian/rarian-main.c630
-rw-r--r--librarian/rarian-main.h60
-rw-r--r--librarian/rarian-man.c617
-rw-r--r--librarian/rarian-man.h59
-rw-r--r--librarian/rarian-omf.cpp673
-rw-r--r--librarian/rarian-omf.h42
-rw-r--r--librarian/rarian-reg-full.c760
-rw-r--r--librarian/rarian-reg-full.h86
-rw-r--r--librarian/rarian-reg-utils.c835
-rw-r--r--librarian/rarian-reg-utils.h86
-rw-r--r--librarian/rarian-utils.c75
-rw-r--r--librarian/rarian-utils.h56
-rw-r--r--librarian/rarian.h45
19 files changed, 5782 insertions, 0 deletions
diff --git a/librarian/Makefile.am b/librarian/Makefile.am
new file mode 100644
index 0000000..7bd69b0
--- /dev/null
+++ b/librarian/Makefile.am
@@ -0,0 +1,33 @@
+pkginclude_HEADERS = rarian.h rarian-main.h rarian-reg-utils.h \
+ rarian-info.h rarian-man.h
+lib_LTLIBRARIES = librarian.la
+
+librarian_la_SOURCES = \
+ rarian.h \
+ rarian-main.h \
+ rarian-main.c \
+ rarian-reg-utils.h \
+ rarian-reg-utils.c \
+ rarian-language.c \
+ rarian-language.h \
+ rarian-utils.h \
+ rarian-utils.c \
+ rarian-info.h \
+ rarian-info.c \
+ rarian-man.c \
+ rarian-man.h
+
+if ENABLE_OMF_READ
+librarian_la_SOURCES += \
+ rarian-omf.h \
+ rarian-omf.cpp \
+ $(top_srcdir)/util/tinyxml.cpp \
+ $(top_srcdir)/util/tinyxml.h \
+ $(top_srcdir)/util/tinyxmlparser.cpp \
+ $(top_srcdir)/util/tinystr.cpp \
+ $(top_srcdir)/util/tinystr.h \
+ $(top_srcdir)/util/tinyxmlerror.cpp
+endif
+
+librarian_la_CFLAGS = -DDATADIR=\""$(datadir)"\" -DSYSCONFDIR=\""$(sysconfdir)"\" -DI_KNOW_RARIAN_0_8_IS_UNSTABLE
+librarian_la_LDFLAGS = -export-symbols-regex "^rrn_.*" \ No newline at end of file
diff --git a/librarian/Makefile.in b/librarian/Makefile.in
new file mode 100644
index 0000000..d238869
--- /dev/null
+++ b/librarian/Makefile.in
@@ -0,0 +1,641 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 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@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@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@
+@ENABLE_OMF_READ_TRUE@am__append_1 = \
+@ENABLE_OMF_READ_TRUE@ rarian-omf.h \
+@ENABLE_OMF_READ_TRUE@ rarian-omf.cpp \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinyxml.cpp \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinyxml.h \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinyxmlparser.cpp \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinystr.cpp \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinystr.h \
+@ENABLE_OMF_READ_TRUE@ $(top_srcdir)/util/tinyxmlerror.cpp
+
+subdir = librarian
+DIST_COMMON = $(pkginclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(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 =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+librarian_la_LIBADD =
+am__librarian_la_SOURCES_DIST = rarian.h rarian-main.h rarian-main.c \
+ rarian-reg-utils.h rarian-reg-utils.c rarian-language.c \
+ rarian-language.h rarian-utils.h rarian-utils.c rarian-info.h \
+ rarian-info.c rarian-man.c rarian-man.h rarian-omf.h \
+ rarian-omf.cpp $(top_srcdir)/util/tinyxml.cpp \
+ $(top_srcdir)/util/tinyxml.h \
+ $(top_srcdir)/util/tinyxmlparser.cpp \
+ $(top_srcdir)/util/tinystr.cpp $(top_srcdir)/util/tinystr.h \
+ $(top_srcdir)/util/tinyxmlerror.cpp
+@ENABLE_OMF_READ_TRUE@am__objects_1 = rarian-omf.lo tinyxml.lo \
+@ENABLE_OMF_READ_TRUE@ tinyxmlparser.lo tinystr.lo \
+@ENABLE_OMF_READ_TRUE@ tinyxmlerror.lo
+am_librarian_la_OBJECTS = librarian_la-rarian-main.lo \
+ librarian_la-rarian-reg-utils.lo \
+ librarian_la-rarian-language.lo librarian_la-rarian-utils.lo \
+ librarian_la-rarian-info.lo librarian_la-rarian-man.lo \
+ $(am__objects_1)
+librarian_la_OBJECTS = $(am_librarian_la_OBJECTS)
+librarian_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(librarian_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(librarian_la_SOURCES)
+DIST_SOURCES = $(am__librarian_la_SOURCES_DIST)
+pkgincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(pkginclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASH = @BASH@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONVERT_DIR = @CONVERT_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_INSTALL = @ENABLE_INSTALL@
+ENABLE_OMF_READ = @ENABLE_OMF_READ@
+ENABLE_SKDB_UPDATE = @ENABLE_SKDB_UPDATE@
+ENABLE_SK_COMPAT = @ENABLE_SK_COMPAT@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+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_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+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@
+have_bash = @have_bash@
+have_xslt = @have_xslt@
+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@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkginclude_HEADERS = rarian.h rarian-main.h rarian-reg-utils.h \
+ rarian-info.h rarian-man.h
+
+lib_LTLIBRARIES = librarian.la
+librarian_la_SOURCES = rarian.h rarian-main.h rarian-main.c \
+ rarian-reg-utils.h rarian-reg-utils.c rarian-language.c \
+ rarian-language.h rarian-utils.h rarian-utils.c rarian-info.h \
+ rarian-info.c rarian-man.c rarian-man.h $(am__append_1)
+librarian_la_CFLAGS = -DDATADIR=\""$(datadir)"\" -DSYSCONFDIR=\""$(sysconfdir)"\" -DI_KNOW_RARIAN_0_8_IS_UNSTABLE
+librarian_la_LDFLAGS = -export-symbols-regex "^rrn_.*"
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu librarian/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu librarian/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+librarian.la: $(librarian_la_OBJECTS) $(librarian_la_DEPENDENCIES)
+ $(librarian_la_LINK) -rpath $(libdir) $(librarian_la_OBJECTS) $(librarian_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-language.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-main.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-man.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-reg-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librarian_la-rarian-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rarian-omf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinystr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxml.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlerror.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlparser.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+librarian_la-rarian-main.lo: rarian-main.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-main.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-main.Tpo -c -o librarian_la-rarian-main.lo `test -f 'rarian-main.c' || echo '$(srcdir)/'`rarian-main.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-main.Tpo $(DEPDIR)/librarian_la-rarian-main.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-main.c' object='librarian_la-rarian-main.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-main.lo `test -f 'rarian-main.c' || echo '$(srcdir)/'`rarian-main.c
+
+librarian_la-rarian-reg-utils.lo: rarian-reg-utils.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-reg-utils.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-reg-utils.Tpo -c -o librarian_la-rarian-reg-utils.lo `test -f 'rarian-reg-utils.c' || echo '$(srcdir)/'`rarian-reg-utils.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-reg-utils.Tpo $(DEPDIR)/librarian_la-rarian-reg-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-reg-utils.c' object='librarian_la-rarian-reg-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-reg-utils.lo `test -f 'rarian-reg-utils.c' || echo '$(srcdir)/'`rarian-reg-utils.c
+
+librarian_la-rarian-language.lo: rarian-language.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-language.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-language.Tpo -c -o librarian_la-rarian-language.lo `test -f 'rarian-language.c' || echo '$(srcdir)/'`rarian-language.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-language.Tpo $(DEPDIR)/librarian_la-rarian-language.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-language.c' object='librarian_la-rarian-language.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-language.lo `test -f 'rarian-language.c' || echo '$(srcdir)/'`rarian-language.c
+
+librarian_la-rarian-utils.lo: rarian-utils.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-utils.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-utils.Tpo -c -o librarian_la-rarian-utils.lo `test -f 'rarian-utils.c' || echo '$(srcdir)/'`rarian-utils.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-utils.Tpo $(DEPDIR)/librarian_la-rarian-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-utils.c' object='librarian_la-rarian-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-utils.lo `test -f 'rarian-utils.c' || echo '$(srcdir)/'`rarian-utils.c
+
+librarian_la-rarian-info.lo: rarian-info.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-info.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-info.Tpo -c -o librarian_la-rarian-info.lo `test -f 'rarian-info.c' || echo '$(srcdir)/'`rarian-info.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-info.Tpo $(DEPDIR)/librarian_la-rarian-info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-info.c' object='librarian_la-rarian-info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-info.lo `test -f 'rarian-info.c' || echo '$(srcdir)/'`rarian-info.c
+
+librarian_la-rarian-man.lo: rarian-man.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -MT librarian_la-rarian-man.lo -MD -MP -MF $(DEPDIR)/librarian_la-rarian-man.Tpo -c -o librarian_la-rarian-man.lo `test -f 'rarian-man.c' || echo '$(srcdir)/'`rarian-man.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/librarian_la-rarian-man.Tpo $(DEPDIR)/librarian_la-rarian-man.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rarian-man.c' object='librarian_la-rarian-man.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librarian_la_CFLAGS) $(CFLAGS) -c -o librarian_la-rarian-man.lo `test -f 'rarian-man.c' || echo '$(srcdir)/'`rarian-man.c
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+tinyxml.lo: $(top_srcdir)/util/tinyxml.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxml.lo -MD -MP -MF $(DEPDIR)/tinyxml.Tpo -c -o tinyxml.lo `test -f '$(top_srcdir)/util/tinyxml.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxml.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tinyxml.Tpo $(DEPDIR)/tinyxml.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(top_srcdir)/util/tinyxml.cpp' object='tinyxml.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxml.lo `test -f '$(top_srcdir)/util/tinyxml.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxml.cpp
+
+tinyxmlparser.lo: $(top_srcdir)/util/tinyxmlparser.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlparser.lo -MD -MP -MF $(DEPDIR)/tinyxmlparser.Tpo -c -o tinyxmlparser.lo `test -f '$(top_srcdir)/util/tinyxmlparser.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxmlparser.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tinyxmlparser.Tpo $(DEPDIR)/tinyxmlparser.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(top_srcdir)/util/tinyxmlparser.cpp' object='tinyxmlparser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlparser.lo `test -f '$(top_srcdir)/util/tinyxmlparser.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxmlparser.cpp
+
+tinystr.lo: $(top_srcdir)/util/tinystr.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinystr.lo -MD -MP -MF $(DEPDIR)/tinystr.Tpo -c -o tinystr.lo `test -f '$(top_srcdir)/util/tinystr.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinystr.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tinystr.Tpo $(DEPDIR)/tinystr.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(top_srcdir)/util/tinystr.cpp' object='tinystr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinystr.lo `test -f '$(top_srcdir)/util/tinystr.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinystr.cpp
+
+tinyxmlerror.lo: $(top_srcdir)/util/tinyxmlerror.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlerror.lo -MD -MP -MF $(DEPDIR)/tinyxmlerror.Tpo -c -o tinyxmlerror.lo `test -f '$(top_srcdir)/util/tinyxmlerror.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxmlerror.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tinyxmlerror.Tpo $(DEPDIR)/tinyxmlerror.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(top_srcdir)/util/tinyxmlerror.cpp' object='tinyxmlerror.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlerror.lo `test -f '$(top_srcdir)/util/tinyxmlerror.cpp' || echo '$(srcdir)/'`$(top_srcdir)/util/tinyxmlerror.cpp
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)"
+ @list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+ $(pkgincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgincludedir)/$$f"; \
+ done
+
+uninstall-pkgincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkginclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ 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 $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-pkgincludeHEADERS install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS
+
+# 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/librarian/rarian-info.c b/librarian/rarian-info.c
new file mode 100644
index 0000000..aa247bf
--- /dev/null
+++ b/librarian/rarian-info.c
@@ -0,0 +1,699 @@
+/*
+ * rarian-info.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2007 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif /*HAVE_MALLOC_H*/
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "rarian-info.h"
+#include "rarian-utils.h"
+
+typedef struct _InfoLink InfoLink;
+
+
+struct _InfoLink
+{
+ RrnInfoEntry *reg;
+ InfoLink *next;
+ InfoLink *prev;
+};
+
+static InfoLink * info_head = NULL;
+static InfoLink * info_tail = NULL;
+static char **categories = NULL;
+static char *current_category = NULL;
+static char *current_path = NULL;
+RrnInfoEntry *current_entry = NULL;
+
+static void
+set_category (const char *new_cat)
+{
+ char *stripped = strdup (new_cat);
+ char **cats = categories;
+ int ncats = 1;
+ char **tmp_copy = NULL;
+ char **tmp_copy_iter = NULL;
+ if (current_category)
+ free (current_category);
+
+ stripped = rrn_strip (stripped);
+ while (cats && *cats) {
+ if (!strcmp (stripped, *cats)) {
+ current_category = strdup (*cats);
+ free (stripped);
+ return;
+ }
+ ncats++;
+ cats++;
+ }
+ /* If we get here, we got a new category and have to do some work */
+ cats = categories;
+ tmp_copy = malloc (sizeof(char *) * (ncats+1));
+ memset (tmp_copy, 0, sizeof(char *) * (ncats+1));
+ tmp_copy_iter = tmp_copy;
+
+ cats = categories;
+ while (cats && *cats) {
+ char *tmp = *cats;
+ *tmp_copy_iter = strdup (tmp);
+ cats++;
+ tmp_copy_iter++;
+ free (tmp);
+ }
+ *tmp_copy_iter = strdup (stripped);
+ current_category = strdup (stripped);
+ free (categories);
+ categories = tmp_copy;
+ free (stripped);
+ return;
+}
+
+static void
+process_initial_entry (const char *line)
+{
+ char *tmp = (char *) line;
+ char *end_name = NULL;
+ char *begin_fname = NULL;
+ char *end_fname = NULL;
+ char *begin_section = NULL;
+ char *end_section = NULL;
+ char *comment = NULL;
+
+ if (!tmp) {
+ fprintf (stderr, "Error: Malformed line! Ignoring\n");
+ return;
+ }
+
+ if (!current_category) {
+ /* The docs are appearing before the first category. Ignore
+ them. */
+ fprintf (stderr, "Error: Documents outwith categories. Ignoring\n");
+ return;
+ }
+
+ tmp++;
+ end_name = strchr(tmp, ':');
+ if (!end_name) {
+ fprintf (stderr, "Error: Malformed line (no ':'). Ignoring entry\n");
+ return;
+ }
+ begin_fname = strchr(end_name, '(');
+ if (!begin_fname) {
+ fprintf (stderr, "Error: Malformed line (no filename). Ignoring entry\n");
+ return;
+ }
+ end_fname = strchr(begin_fname, ')');
+ if (!end_fname) {
+ fprintf (stderr, "Error: Malformed line (no filename close). Ignoring entry\n");
+ return;
+ }
+ end_section = strchr(end_fname, '.');
+
+ if (!end_section) {
+ fprintf (stderr, "Error: Malformed line (no section). Ignoring entry\n");
+ return;
+ }
+
+ current_entry->category = strdup(current_category);
+ current_entry->base_path = strdup(current_path);
+ current_entry->base_filename = NULL;
+ current_entry->doc_name = rrn_strip(rrn_strndup(tmp, (end_name - tmp)));
+ current_entry->name = rrn_strip(rrn_strndup(begin_fname+1,
+ (end_fname-begin_fname-1)));
+ if (end_section == end_fname+1)
+ current_entry->section = NULL;
+ else {
+ current_entry->section = rrn_strip(rrn_strndup(end_fname+1,
+ (end_section - end_fname -1)));
+ }
+ comment = rrn_strip(strdup (end_section+1));
+ if (strlen (comment) > 0) {
+ current_entry->comment = comment;
+ } else {
+ free(comment);
+ current_entry->comment = NULL;
+ }
+}
+
+static void
+process_add_desc (const char *line)
+{
+ char *current;
+ char *cpy = NULL;
+ cpy = rrn_strip(strdup(line));
+ if (!cpy)
+ return;
+
+ if (current_entry->comment) {
+ current = malloc (sizeof(char) * (strlen(current_entry->comment) +
+ strlen(cpy) + 2));
+ sprintf (current, "%s %s", current_entry->comment, cpy);
+ free (current_entry->comment);
+ } else {
+ current = strdup(cpy);
+ }
+ current_entry->comment = current;
+ free (cpy);
+}
+
+static int
+process_check_file()
+{
+ char *filename = NULL;
+ char *tmp = NULL;
+ InfoLink *iter;
+ struct stat fileinfo;
+
+ if (!current_entry->name) {
+ return FALSE;
+ }
+
+ /* First, look for an additional part on the filename */
+ tmp = strchr(current_entry->name, '/');
+ if (tmp) {
+ char *new_base = NULL;
+ char *addition;
+ char *name;
+ addition = rrn_strndup (current_entry->name, tmp - current_entry->name);
+ name = strdup(tmp+1);
+ new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ strlen(addition)+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path, addition);
+ free(current_entry->base_path);
+ free(current_entry->name);
+ free(addition);
+ current_entry->base_path = new_base;
+ current_entry->name = name;
+ }
+
+ /* Search for duplicate files. If we find one, we
+ * use the older one and forget this one
+ */
+ iter = info_head;
+
+ while (iter) {
+ if (!strcmp (iter->reg->doc_name, current_entry->doc_name)) {
+ return FALSE;
+ }
+ iter = iter->next;
+
+ }
+
+
+ /* Search for all the types we know of in all the
+ * locations we know of to find the file, starting with
+ * the most popular and working down.
+ * If and when we find it, we set the encoding
+ * (loose) and return */
+ /* Use the largest possible storage for filename */
+ filename = malloc(sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name)*2) + 15));
+
+
+ sprintf (filename, "%s/%s.info.gz", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_GZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.gz", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_GZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.info.bz2", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_BZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.bz2", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_BZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.info.lzma", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_LZMA;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.lzma", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_LZMA;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s.info", current_entry->base_path,
+ current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ current_entry->compression = INFO_ENCODING_NONE;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s/%s.info.gz", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_GZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s/%s.gz", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_GZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s/%s.info.bz2", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_BZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s/%s.bz2", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_BZIP;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ sprintf (filename, "%s/%s/%s.info.lzma", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_LZMA;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+
+ sprintf (filename, "%s/%s/%s.lzma", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_LZMA;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+
+ sprintf (filename, "%s/%s/%s.info", current_entry->base_path,
+ current_entry->name, current_entry->name);
+ if (!stat(filename, &fileinfo)) {
+ /* Add to base path */
+ char *new_base = malloc (sizeof(char) * (strlen(current_entry->base_path) +
+ (strlen(current_entry->name) *2) +
+ 2));
+ sprintf (new_base, "%s/%s", current_entry->base_path,
+ current_entry->name);
+ free(current_entry->base_path);
+ current_entry->base_path = new_base;
+
+ current_entry->compression = INFO_ENCODING_NONE;
+ current_entry->base_filename = filename;
+ return TRUE;
+ }
+ free(filename);
+ return FALSE;
+
+
+}
+
+static void
+free_entry (RrnInfoEntry *entry)
+{
+ if (entry->name)
+ free(entry->name);
+ if (entry->base_path)
+ free(entry->base_path);
+ if (entry->base_filename)
+ free (entry->base_filename);
+ if (entry->category)
+ free (entry->category);
+ if (entry->section)
+ free(entry->section);
+ if (entry->doc_name)
+ free(entry->doc_name);
+ if (entry->comment)
+ free(entry->comment);
+ free(entry);
+
+}
+
+static void
+process_add_entry (void)
+{
+ InfoLink *link = NULL;
+
+ link = malloc (sizeof(InfoLink));
+ link->reg = current_entry;
+ link->next = NULL;
+ link->prev = NULL;
+ if (info_tail && info_head) {
+ info_tail->next = link;
+ link->prev = info_tail;
+ info_tail = link;
+ } else {
+ /* Initial link */
+ info_head = info_tail = link;
+ }
+}
+
+static void
+process_info_dir (const char *dir)
+{
+
+ char *filename;
+ FILE *fp = NULL;
+ char *line = NULL;
+ int started = FALSE;
+ int ret = FALSE;
+
+ filename = (char *) malloc(sizeof(char) * strlen(dir)+5);
+
+ sprintf(filename, "%s/dir", dir);
+ fp = fopen(filename, "r");
+ if (!fp) {
+ free (filename);
+ return;
+ }
+ if (current_path)
+ free (current_path);
+ current_path = strdup (dir);
+ line = (char *) malloc(sizeof(char) * 1024);
+ while (fgets (line, 1023, fp)) {
+ if (!started) {
+ if (!strncmp (line, "* Menu", 6) ||
+ !strncmp (line, "* menu", 6)) {
+ started = TRUE;
+ }
+ continue;
+ }
+ if ((*line != '*') && !isspace(*line)) {
+ /* New category */
+ set_category (line);
+ } else if ((*line == '*')) {
+ /* New entry */
+ if (current_entry) {
+ if (process_check_file()) {
+ process_add_entry ();
+ } else {
+ free_entry (current_entry);
+ }
+ current_entry = NULL;
+ }
+ current_entry = malloc (sizeof(RrnInfoEntry));
+ current_entry->name = NULL;
+ current_entry->base_path = NULL;
+ current_entry->base_filename = NULL;
+ current_entry->category = NULL;
+ current_entry->section = NULL;
+ current_entry->doc_name = NULL;
+ current_entry->comment = NULL;
+
+
+ process_initial_entry (line);
+
+
+ } else if (strlen(line) > 1) {
+ /* Continuation of description */
+ process_add_desc (line);
+ } else {
+ /* Blank line, ignore */
+ }
+ }
+ if (process_check_file()) {
+ process_add_entry ();
+ } else {
+ free_entry (current_entry);
+ }
+ current_entry = NULL;
+ free (line);
+ fclose(fp);
+ free (filename);
+}
+
+static void
+sanity_check_categories ()
+{
+ char **cats = categories;
+ char **iter = cats;
+ char **new_cats = NULL;
+ InfoLink *l;
+ int ncats = 1;
+
+ while (iter && *iter) {
+ l = info_head;
+ while (l) {
+ if (!strcmp(l->reg->category, *iter)) {
+ char **tmp = NULL;
+ char **cats_iter = new_cats;
+ char **tmp_iter = NULL;
+ ncats++;
+ tmp = (char **) malloc(sizeof(char *) * (ncats+1));
+ memset(tmp, 0, sizeof(char *) * (ncats+1));
+ tmp_iter = tmp;
+ while (cats_iter && *cats_iter) {
+ *tmp_iter = *cats_iter;
+ tmp_iter++;
+ cats_iter++;
+ }
+ *tmp_iter = *iter;
+ tmp_iter = tmp;
+ if (new_cats)
+ free(new_cats);
+ new_cats = tmp;
+
+ break;
+ }
+ l = l->next;
+ }
+ /* If we got here, we have an empty category and should remove
+ * it
+ */
+ iter++;
+ }
+ free(categories);
+ categories = new_cats;
+}
+
+static void
+rrn_info_init (void)
+{
+ char *default_dirs = "/usr/info:/usr/share/info:/usr/local/info:/usr/local/share/info";
+ char *info_dirs = NULL;
+ char *split = NULL;
+ int free_info_dirs = FALSE;
+
+ info_dirs = (char *) getenv ("INFOPATH");
+
+
+ if (!info_dirs || !strcmp (info_dirs, "")) {
+ free_info_dirs = TRUE;
+ info_dirs = strdup (default_dirs);
+ }
+
+ split = info_dirs;
+ do {
+ char *next = strchr(split, ':');
+ char *dirname = NULL;
+
+ if (next)
+ dirname = rrn_strndup(split, (next-split));
+ else
+ dirname = strdup (split);
+ process_info_dir (dirname);
+ free (dirname);
+
+ split = strchr(split, ':');
+ if (split)
+ split++;
+ } while (split);
+
+ if (free_info_dirs)
+ free (info_dirs);
+
+ /* Sanity check our categories. Yes, I put this
+ * comment in then came up with the function name */
+ sanity_check_categories ();
+
+}
+
+
+char **
+rrn_info_get_categories (void)
+{
+ if (!categories)
+ rrn_info_init();
+ return categories;
+
+}
+
+void rrn_info_for_each (RrnInfoForeachFunc funct, void * user_data)
+{
+ InfoLink *l;
+ if (!categories)
+ rrn_info_init();
+ l = info_head;
+ while (l) {
+ int res;
+ res = funct (l->reg, user_data);
+ if (res == FALSE)
+ break;
+ l = l->next;
+ }
+ return;
+}
+
+
+void
+rrn_info_for_each_in_category (char *category,
+ RrnInfoForeachFunc funct,
+ void * user_data)
+{
+ InfoLink *l;
+ if (!categories)
+ rrn_info_init();
+ l = info_head;
+ while (l) {
+ int res;
+ if (!strcmp (l->reg->category, category)) {
+ res = funct (l->reg, user_data);
+ if (res == FALSE)
+ break;
+ }
+ l = l->next;
+ }
+ return;
+
+}
+
+RrnInfoEntry *
+rrn_info_find_from_uri (char *uri, char *section)
+{
+ InfoLink *l;
+ InfoLink *best_result = NULL;
+ if (!categories)
+ rrn_info_init();
+
+ l = info_head;
+
+ while (l) {
+ if ((l->reg->doc_name && !strcmp (uri, l->reg->doc_name)) ||
+ (!strcmp (uri, l->reg->name))) {
+ if (!section || (*section && l->reg->section && !strcmp (l->reg->section, section))) {
+ return l->reg;
+ } else {
+ best_result = l;
+ }
+ }
+ l = l->next;
+ }
+
+ if (best_result)
+ return best_result->reg;
+
+ return NULL;
+}
+
+void
+rrn_info_shutdown ()
+{
+ InfoLink *l = info_head;
+
+ while (l) {
+ InfoLink *next = l->next;
+ free_entry (l->reg);
+ free (l);
+ l = next;
+ }
+ info_head = info_tail = NULL;
+
+ free(categories);
+ categories = NULL;
+}
diff --git a/librarian/rarian-info.h b/librarian/rarian-info.h
new file mode 100644
index 0000000..eb3e3b1
--- /dev/null
+++ b/librarian/rarian-info.h
@@ -0,0 +1,74 @@
+/*
+ * rarian-info.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2007 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RARIAN_INFO_H__
+#define RARIAN_INFO_H__
+
+#ifndef I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#error Rarian is unstable. To use it, you must acknowledge that
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+ /* Note: This encoding isn't exact. It will be easily
+ * tricked if (e.g.) someone sets an info file to point
+ * at info.gz and is really uncompressed etc.
+ */
+ typedef enum _RrnInfoCompression {
+ INFO_ENCODING_NONE = 0,
+ INFO_ENCODING_GZIP,
+ INFO_ENCODING_BZIP,
+ INFO_ENCODING_LZMA,
+ INFO_ENCODING_UNKNOWN,
+ } RrnInfoCompression;
+
+ typedef struct _RrnInfoEntry {
+ char *name;
+ char *shortcut_name;
+ char *base_filename;
+ char *base_path;
+ char *section;
+ char *doc_name;
+ char *comment;
+ RrnInfoCompression compression;
+ char *category;
+ } RrnInfoEntry;
+
+ typedef int (* RrnInfoForeachFunc) (void * reg, void *data);
+
+ char **rrn_info_get_categories (void);
+ void rrn_info_for_each (RrnInfoForeachFunc funct, void * user_data);
+ void rrn_info_for_each_in_category (char *category, RrnInfoForeachFunc funct, void * user_data);
+ RrnInfoEntry *rrn_info_find_from_uri (char *uri, char *section);
+ void rrn_info_shutdown ();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RARIAN_INFO_H__ */
diff --git a/librarian/rarian-language.c b/librarian/rarian-language.c
new file mode 100644
index 0000000..30a74a9
--- /dev/null
+++ b/librarian/rarian-language.c
@@ -0,0 +1,267 @@
+/*
+ * rarian-language.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rarian-language.h>
+#include "rarian-utils.h"
+
+typedef struct _Lang Lang;
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+struct _Lang
+{
+ char *base;
+ Lang *next;
+ Lang *prev;
+};
+
+static Lang *lang_list;
+static int nlangs = 0 ;
+
+static int
+check_lang (char *lang)
+{
+ Lang *iter = lang_list;
+
+ while (iter) {
+ if (!strcmp (iter->base, lang))
+ return TRUE;
+ iter = iter->next;
+ }
+ return FALSE;
+}
+
+static void
+add_lang (char *language)
+{
+ Lang *lang = NULL;
+
+ lang = malloc (sizeof (Lang));
+ lang->base = language;
+ lang->prev = NULL;
+ if (lang_list) {
+ lang->next = lang_list;
+ lang_list->prev = lang;
+ } else {
+ lang->next = NULL;
+ }
+ lang_list = lang;
+
+}
+
+void
+rrn_language_init (char *lang)
+{
+ char *loc = NULL;
+ char *current = NULL;
+ char *tmp = NULL;
+ Lang *iter = lang_list;
+
+ if (lang == NULL) {
+ loc = getenv ("LANGUAGE");
+ if (!loc || !strcmp (loc, "")) {
+ loc = getenv ("LC_ALL");
+ }
+ if (!loc || !strcmp (loc, "")) {
+ loc = getenv ("LANG");
+ }
+
+ } else {
+ loc = strdup (lang);
+ }
+ nlangs = 0;
+
+ if (!loc || !strcmp (loc, "")) {
+ loc = strdup("C");
+ }
+
+ current = loc;
+ do {
+ Lang *lang;
+ char *at_mod;
+ char *dot_mod;
+ char *ter_mod;
+ char *full_lang = NULL;
+ char *exploded = NULL;
+
+ tmp = strchr (current, ':');
+
+ if (tmp)
+ full_lang = rrn_strndup (current, tmp-current);
+ else
+ full_lang = strdup (current);
+
+ at_mod = strrchr (full_lang, '@');
+ dot_mod = strrchr (full_lang, '.');
+ ter_mod = strrchr (full_lang, '_');
+
+ /* Full lang first */
+ if (!check_lang (full_lang)) {
+ add_lang (full_lang);
+ }
+
+ /* Lang sans modifier */
+ if (at_mod) {
+ exploded = rrn_strndup (full_lang, at_mod - full_lang);
+ if (!check_lang (exploded)) {
+ add_lang (exploded);
+ }
+ }
+
+ /* Lang sans modifier and codeset */
+ if (dot_mod) {
+ exploded = rrn_strndup (full_lang, dot_mod - full_lang);
+ if (!check_lang (exploded)) {
+ add_lang (exploded);
+ }
+ }
+
+ /* Lang sans modifier, codeset and territory */
+ if (ter_mod) {
+ exploded = rrn_strndup (full_lang, ter_mod - full_lang);
+ if (!check_lang (exploded)) {
+ add_lang (exploded);
+ }
+ }
+
+ if (tmp)
+ current = tmp+1;
+ else
+ current = NULL;
+ } while (current);
+
+ tmp = strdup ("C");
+ if (!check_lang (tmp)) {
+ add_lang (tmp);
+ }
+
+ iter = lang_list;
+ while (iter) {
+ Lang *tmp = iter->next;
+ nlangs += 1;
+
+ iter->next = iter->prev;
+ iter->prev = tmp;
+ if (iter->prev == NULL) {
+ lang_list = iter;
+ }
+ iter = iter->prev;
+ }
+ iter = lang_list;
+
+}
+
+int
+rrn_language_use (char *current_language, char *proposed)
+{
+ Lang *iter = lang_list;
+
+ if (!lang_list)
+ rrn_language_init(NULL);
+
+ iter = lang_list;
+
+ while (iter) {
+ if (current_language && !strcmp (current_language, iter->base)) {
+ return 0;
+ }
+ if (!strcmp (proposed, iter->base)) {
+ return 1;
+ }
+ iter = iter->next;
+ }
+ return 0;
+}
+
+char **
+rrn_language_get_langs (void)
+{
+ char **ret = NULL;
+ Lang *iter;
+ int i = 0;
+
+ if (!lang_list)
+ rrn_language_init(NULL);
+
+ iter = lang_list;
+ ret = malloc (sizeof (char*) * (nlangs+1));
+
+ while (iter) {
+ ret[i] = iter->base;
+ i++;
+ iter = iter->next;
+ }
+ ret[i] = NULL;
+ return ret;
+
+
+}
+
+char **
+rrn_language_get_dirs (char *base)
+{
+ char **ret = NULL;
+ Lang *iter;
+ int i = 0;
+
+ if (!lang_list)
+ rrn_language_init(NULL);
+
+ iter = lang_list;
+
+ ret = malloc (sizeof (char*) * (nlangs+1));
+
+ while (iter) {
+ char *new_path = NULL;
+
+ new_path = malloc (sizeof (char) *(strlen(base)+9+strlen (iter->base)));
+ sprintf (new_path, "%s/LOCALE/%s", base, iter->base);
+ ret[i] = new_path;
+ i++;
+ iter = iter->next;
+ }
+ ret[i] = NULL;
+ return ret;
+}
+
+
+void
+rrn_language_shutdown (void)
+{
+ Lang *iter = lang_list;
+
+ while (iter) {
+ Lang *next = iter->next;
+ free (iter->base);
+ free (iter);
+ iter = next;
+
+ }
+ lang_list = NULL;
+}
diff --git a/librarian/rarian-language.h b/librarian/rarian-language.h
new file mode 100644
index 0000000..293eef0
--- /dev/null
+++ b/librarian/rarian-language.h
@@ -0,0 +1,44 @@
+/*
+ * rarian-language.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef __RARIAN_LANGUAGE_H
+#define __RARIAN_LANGUAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void rrn_language_init (char *lang);
+
+int rrn_language_use (char *current_language, char *proposed);
+
+char ** rrn_language_get_dirs (char *base);
+
+ char ** rrn_language_get_langs (void);
+
+void rrn_language_shutdown (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__RARIAN_LANGUAGE_H */
diff --git a/librarian/rarian-main.c b/librarian/rarian-main.c
new file mode 100644
index 0000000..f550be0
--- /dev/null
+++ b/librarian/rarian-main.c
@@ -0,0 +1,630 @@
+/*
+ * rarian-main.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include "config.h"
+
+#include "rarian.h"
+#include "rarian-reg-utils.h"
+#include "rarian-language.h"
+#include "rarian-utils.h"
+#if ENABLE_OMF_READ
+#include "rarian-omf.h"
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+/* Internal structures and lists */
+
+typedef struct _Link Link;
+
+
+struct _Link
+{
+ union {
+ RrnReg *reg;
+ RrnSect *sect;
+ } reg;
+ Link *next;
+ Link *prev;
+};
+
+static Link * head = NULL;
+static Link * tail = NULL;
+
+static Link *orphans_head = NULL;
+static Link *orphans_tail = NULL;
+
+/* Function Prototypes */
+
+static void rrn_init (void);
+static void scan_directories (void);
+static void scan_directory (char *dir);
+static void process_file (char *filename);
+static void process_section (char *filename);
+static void insert_orphans (void);
+static void reverse_children (void);
+static void process_locale_dirs (char * dir);
+#if ENABLE_OMF_READ
+static void process_omf_dir (char *dir);
+#endif
+
+void
+rrn_set_language (char *lang_code)
+{
+ if (head) {
+ rrn_shutdown ();
+ }
+ rrn_language_init (lang_code);
+ rrn_init ();
+}
+
+static void
+rrn_init (void)
+{
+ scan_directories ();
+
+ return;
+}
+
+void
+rrn_for_each (RrnForeachFunc funct, void * user_data)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+
+ iter = head;
+
+ while (iter) {
+ int res;
+ res = funct (iter->reg.reg, user_data);
+ if (res == FALSE)
+ break;
+ iter = iter->next;
+ }
+
+ return;
+}
+
+void rrn_for_each_in_category (RrnForeachFunc funct, char * category,
+ void *user_data)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+ int res;
+ char **cats;
+
+ cats = iter->reg.reg->categories;
+ while (cats && *cats) {
+ if (!strcmp(*cats, category)) {
+ res = funct (iter->reg.reg, user_data);
+ if (res == FALSE)
+ break;
+ }
+ cats++;
+ }
+ iter = iter->next;
+ }
+
+ return;
+
+}
+
+RrnReg *
+rrn_find_entry_from_uri (char *uri)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+
+ if (!strcmp(iter->reg.reg->uri, uri))
+ return iter->reg.reg;
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+static void
+scan_directories (void)
+{
+ char *cur_path = NULL;
+
+#if ENABLE_INSTALL
+ char *path = NULL;
+ char *first_colon = NULL;
+ char *next_colon = NULL;
+ char *home_dir = NULL;
+ char *home_data_dir = NULL;
+ char *home_env = NULL;
+
+ home_env = getenv ("XDG_DATA_HOME");
+ if (home_env)
+ home_data_dir = strdup(home_env);
+
+ if (!home_data_dir || !strcmp (home_data_dir, "")) {
+ home_dir = getenv ("HOME");
+ if (!home_dir || !strcmp (home_dir, "")) {
+ fprintf (stderr, "Warning: HOME dir is not defined."
+ " Skipping check of XDG_DATA_HOME");
+ goto past;
+ }
+ home_data_dir = malloc (sizeof(char) * (strlen(home_dir)+14));
+ sprintf (home_data_dir, "%s/.local/share", home_dir);
+ }
+
+ /* Reuse home_dir. Bad.*/
+ home_dir = malloc (sizeof (char) * (strlen(home_data_dir)+6));
+
+ sprintf (home_dir, "%s/help", home_data_dir);
+
+#if ENABLE_OMF_READ
+ process_omf_dir (home_data_dir);
+#endif
+
+ free (home_data_dir);
+
+ process_locale_dirs (home_dir);
+ scan_directory (home_dir);
+
+ free (home_dir);
+
+past:
+ path = getenv ("XDG_DATA_DIRS");
+
+ if (!path || !strcmp (path, "")) {
+ path = "/usr/local/share/:/usr/share/";
+ }
+ cur_path = path;
+
+ do {
+ char *int_path = NULL;
+ char *check_path = NULL;
+ first_colon = strchr (cur_path, ':');
+ if (first_colon)
+ int_path = rrn_strndup (cur_path, (first_colon-cur_path));
+ else
+ int_path = strdup (cur_path);
+ check_path = malloc (sizeof(char)*(strlen(int_path)+6));
+ sprintf (check_path, "%s/help", int_path);
+#if ENABLE_OMF_READ
+ process_omf_dir (int_path);
+#endif
+ process_locale_dirs (check_path);
+
+ scan_directory (check_path);
+ if (int_path && *int_path) {
+ free (int_path);
+ }
+ if (check_path) {
+ free (check_path);
+ }
+ cur_path = first_colon+1;
+ } while (first_colon);
+#else
+ cur_path = "data/sk-import";
+ process_locale_dirs (cur_path);
+ scan_directory (cur_path);
+#endif
+ reverse_children ();
+}
+
+static void
+process_locale_dirs (char * dir)
+{
+ DIR *dirp = NULL;
+ char **paths_to_check = NULL;
+ char **iter = NULL;
+
+ paths_to_check = rrn_language_get_dirs (dir);
+ iter = paths_to_check;
+
+ while (*iter) {
+ scan_directory (*iter);
+ free (*iter);
+ iter++;
+ }
+ free (paths_to_check);
+
+}
+
+static void
+scan_directory (char *dir)
+{
+ DIR * dirp = NULL;
+ struct dirent * dp = NULL;
+ struct stat buf;
+ char *path = NULL;
+ dirp = opendir (dir);
+
+ if (access (dir, R_OK)) {
+ return;
+ }
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ char *full_name = NULL;
+ full_name = malloc (sizeof(char)*(strlen (dp->d_name) + strlen(dir) + 2));
+
+ sprintf (full_name, "%s/%s", dir, dp->d_name);
+ stat(full_name,&buf);
+
+ if (S_ISREG(buf.st_mode)) {
+ char *suffix = NULL;
+
+ suffix = strrchr (full_name, '.');
+ if (!strcmp (suffix, ".document")) {
+ process_file (full_name);
+ } else if (!strcmp (suffix, ".section")) {
+ process_section (full_name);
+ }
+ } else if (S_ISDIR(buf.st_mode) && strcmp (dp->d_name, ".") &&
+ strcmp (dp->d_name, "..") &&
+ strcmp (dp->d_name, "LOCALE")) {
+
+ scan_directory (full_name);
+ }
+ free (full_name);
+ } else {
+ goto done;
+ }
+ }
+
+done:
+ insert_orphans ();
+ closedir (dirp);
+ free (path);
+}
+
+static int
+handle_duplicate (RrnReg *reg)
+{
+ Link *iter;
+
+ iter = head;
+
+ while (iter) {
+ if ((iter->reg.reg->heritage && reg->heritage &&
+ !strcmp (iter->reg.reg->heritage, reg->heritage)) ||
+ !strcmp (iter->reg.reg->identifier, reg->identifier)) {
+ if (iter->reg.reg->lang && reg->lang &&
+ rrn_language_use (iter->reg.reg->lang, reg->lang)) {
+ rrn_reg_free (iter->reg.reg);
+ iter->reg.reg = reg;
+ }
+ return TRUE;
+ }
+ iter = iter->next;
+ }
+
+ return FALSE;
+
+}
+
+#if ENABLE_OMF_READ
+static void
+process_omf_dir (char *dir)
+{
+ char *path;
+ DIR * dirp = NULL;
+ char **langs = NULL;
+ char **langs_iter = NULL;
+ int lang_found = FALSE;
+ int lang_count = 0;
+ char *tmp = NULL;
+
+ struct dirent * dp = NULL;
+ struct stat buf;
+
+ langs = rrn_language_get_langs ();
+ path = malloc (sizeof(char) * (strlen (dir)+6));
+
+ sprintf (path, "%s/omf", dir);
+
+ if (access (path, R_OK)) {
+ return;
+ }
+
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ lang_count++;
+ if (!strcmp (*langs_iter, "C")) {
+ lang_found = TRUE;
+ }
+ langs_iter++;
+ }
+ if (!lang_found) {
+ char **tmp;
+ int i = 0;
+ tmp = malloc (sizeof (char *) * (lang_count+2));
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ tmp[i] = strdup (*langs_iter);
+ i++;
+ langs_iter++;
+ }
+ tmp[i] = strdup ("C");
+ i++;
+ tmp[i] = NULL;
+ langs = tmp;
+ }
+
+
+ dirp = opendir (path);
+
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ char *full_name;
+ full_name = malloc (sizeof(char) * (strlen(path) + strlen(dp->d_name) + 5));
+ sprintf (full_name, "%s/%s", path, dp->d_name);
+ stat(full_name,&buf);
+ free (full_name);
+ if (S_ISDIR(buf.st_mode) && strcmp (dp->d_name, ".") &&
+ strcmp (dp->d_name, "..")) {
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ char *lang = (*langs_iter);
+ /* Add extra 2 for separator and NULL. Otherwise, it falls over */
+ tmp = malloc (sizeof (char) * (strlen(dir)+(strlen(dp->d_name)*2) +
+ strlen(lang) + 20));
+ sprintf (tmp, "%s/%s/%s-%s.omf", path, dp->d_name, dp->d_name,(*langs_iter));
+
+ if (!access (tmp, R_OK)) {
+ RrnReg *reg = NULL;
+ reg = rrn_omf_parse_file (tmp);
+ if (reg) {
+ reg->omf_location = strdup (tmp);
+ reg->ghelp_name = strdup (dp->d_name);
+ }
+ if (reg && !handle_duplicate (reg)) {
+ Link *link;
+
+ link = malloc (sizeof (Link));
+ link->reg.reg = reg;
+ link->next = NULL;
+
+ if (!tail) {
+ if (head) {
+ fprintf (stderr, "ERROR: Tail not pointing anywhere. "
+ "Aborting");
+ exit (3);
+ }
+ head = link;
+ tail = link;
+ } else {
+ tail->next = link;
+ tail = link;
+
+ }
+ }
+ }
+ free (tmp);
+ tmp = NULL;
+ langs_iter++;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+done:
+ insert_orphans ();
+ closedir (dirp);
+}
+#endif
+
+static void
+process_section (char *filename)
+{
+ RrnSect *sect = NULL;
+ Link *link;
+
+ sect = rrn_sect_parse_file (filename);
+ if (!sect)
+ return;
+
+ link = malloc (sizeof (Link));
+ link->reg.sect = sect;
+ link->next = NULL;
+ link->prev = NULL;
+
+ if (!orphans_head) {
+ orphans_head = link;
+ orphans_tail = link;
+ } else {
+ orphans_tail->next = link;
+ link->prev = orphans_tail;
+ orphans_tail = link;
+ }
+}
+
+static void
+process_file (char *filename)
+{
+ RrnReg *reg;
+ Link *link;
+
+ reg = rrn_reg_parse_file (filename);
+ if (!reg)
+ return;
+
+ if (handle_duplicate (reg)) {
+ return;
+ }
+
+ link = malloc (sizeof (Link));
+ link->reg.reg = reg;
+ link->next = NULL;
+
+ if (!tail) {
+ if (head) {
+ fprintf (stderr, "ERROR: Tail not pointing anywhere. Aborting");
+ exit (3);
+ }
+ head = link;
+ tail = link;
+ } else {
+ tail->next = link;
+ tail = link;
+
+ }
+}
+
+static void
+insert_orphans ()
+{
+ Link *sect = orphans_head;
+
+ while (sect) {
+ Link *iter = head;
+
+ while (iter) {
+ if (!strncmp (iter->reg.reg->identifier, sect->reg.sect->owner,
+ strlen(iter->reg.reg->identifier))) {
+ break;
+ }
+ iter = iter->next;
+ }
+ if (iter) {
+ sect->reg.sect = rrn_reg_add_sections (iter->reg.reg,
+ sect->reg.sect);
+ if (sect->reg.sect == NULL) {
+ Link *tmp = sect->next;
+ if (sect->prev)
+ sect->prev->next = sect->next;
+ if (sect->next)
+ sect->next->prev = sect->prev;
+ if (sect == orphans_head)
+ orphans_head = NULL;
+ free (sect);
+ sect = tmp;
+ }
+ } else {
+ sect->reg.sect->priority++;
+ sect = sect->next;
+ }
+ }
+}
+
+static RrnSect *
+reverse_child (RrnSect *child)
+{
+ RrnSect *local_tail = NULL;
+ RrnSect *iter = child;
+ RrnSect *tmp = NULL;
+
+ while (iter) {
+ if (iter->children)
+ iter->children = reverse_child (iter->children);
+ tmp = iter->next;
+ iter->next = iter->prev;
+ iter->prev = tmp;
+ if (iter->prev == NULL) {
+ return iter;
+ }
+ iter = iter->prev;
+ }
+}
+
+static void
+reverse_children ()
+{
+ Link *iter = head;
+
+ while (iter) {
+ if (iter->reg.reg->children) {
+ iter->reg.reg->children = reverse_child (iter->reg.reg->children);
+ }
+
+ iter = iter->next;
+ }
+}
+
+RrnReg *
+rrn_find_from_name (char *name)
+{
+ if (!head)
+ rrn_init ();
+
+ return NULL;
+
+
+}
+
+RrnReg *
+rrn_find_from_ghelp (char *ghelp)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+ if (iter->reg.reg->ghelp_name && !strcmp(iter->reg.reg->ghelp_name, ghelp))
+ return iter->reg.reg;
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+
+void
+rrn_shutdown ()
+{
+ Link *next;
+
+ while (head) {
+ next = head->next;
+
+ rrn_reg_free (head->reg.reg);
+ free (head);
+ head = next;
+ }
+ rrn_language_shutdown ();
+ head = tail = NULL;
+ return;
+}
diff --git a/librarian/rarian-main.h b/librarian/rarian-main.h
new file mode 100644
index 0000000..126b7b1
--- /dev/null
+++ b/librarian/rarian-main.h
@@ -0,0 +1,60 @@
+/*
+ * rarian-main.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __RARIAN_MAIN_H
+#define __RARIAN_MAIN_H
+
+#ifndef I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#error Rarian is unstable. To use it, you must acknowledge that
+#endif
+
+#include <rarian-reg-utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+ typedef int (* RrnForeachFunc) (void * reg, void *data);
+
+ void rrn_set_language (char *lang_code);
+
+ void rrn_for_each (RrnForeachFunc funct, void * user_data);
+
+ void rrn_for_each_in_category (RrnForeachFunc funct, char * category,
+ void *user_data);
+ RrnReg * rrn_find_entry_from_uri (char *uri);
+
+ RrnReg * rrn_find_from_name (char *name);
+
+ RrnReg * rrn_find_from_ghelp (char *ghelp);
+
+ void rrn_shutdown ();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__RARIAN_MAIN_H */
diff --git a/librarian/rarian-man.c b/librarian/rarian-man.c
new file mode 100644
index 0000000..9ad9c1b
--- /dev/null
+++ b/librarian/rarian-man.c
@@ -0,0 +1,617 @@
+/*
+ * rarian-man.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2007 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "rarian-man.h"
+#include "rarian-language.h"
+#include "rarian-utils.h"
+
+/*#ifdef HAVE_LIBGDBM
+#include <gdbm.h>
+static GDBM_FILE *gdbm_handle;
+#endif
+
+#ifdef HAVE_LIBNDBM
+#include <ndbm.h>
+static DBM *ndbm_handle;
+#endif*/
+
+typedef struct _ManLink ManLink;
+
+struct _ManLink
+{
+ RrnManEntry *reg;
+ ManLink *next;
+ ManLink *prev;
+};
+
+static char *keys[43] = {"1", "1p", "1g", "1t", "1x", "1ssl", "1m",
+ "2",
+ "3", "3o", "3t", "3p", "3blt", "3nas", "3form", "3menu", "3tiff", "3ssl", "3readline",
+ "3ncurses", "3curses", "3f", "3pm", "3perl", "3qt", "3x", "3X11",
+ "4", "4x",
+ "5", "5snmp", "5x", "5ssl",
+ "6", "6x",
+ "7", "7gcc", "7x", "7ssl",
+ "8", "8l", "9", "0p"
+};
+
+static ManLink *manhead[44];
+static ManLink *mantail[44];
+
+static char *avail_dirs[] = {
+ "man0p", "man1", "man1p", "man2", "man3",
+ "man3p", "man4", "man5", "man6", "man7",
+ "man8", "man9", "mann",
+ NULL
+ };
+
+static char **man_paths = NULL;
+
+int initialised = FALSE;
+int mode = -1;
+/* Modes: 0 = default
+ * 1 = gdbm
+ * 2 = ndbm
+ */
+
+static void
+setup_man_path ()
+{
+ int outfd[2];
+ int infd[2];
+
+ int oldstdin, oldstdout;
+ fflush(stdin);
+ fflush(stdout);
+ fflush(stderr);
+
+ pipe(outfd); // Where the parent is going to write to
+ pipe(infd); // From where parent is going to read
+
+ oldstdin = dup(0); // Save current stdin
+ oldstdout = dup(1); // Save stdout
+
+ close(0);
+ close(1);
+
+ dup2(outfd[0], 0); // Make the read end of outfd pipe as stdin
+ dup2(infd[1],1); // Make the write end of infd as stdout
+
+ if(!fork()) {
+ /* Child process */
+ char *argv[]={"manpath"};
+ close(outfd[0]); // Not required for the child
+ close(outfd[1]);
+ close(infd[0]);
+ close(infd[1]);
+ execlp("manpath", "manpath", (char *) 0);
+ exit (0);
+ } else {
+ /* Parent process */
+ char *input = NULL;
+ char *colon = NULL;
+ char *next = NULL;
+ int i, count = 0;
+ input = malloc(sizeof(char) * 256);
+ close(0); // Restore the original std fds of parent
+ close(1);
+ dup2(oldstdin, 0);
+ dup2(oldstdout, 1);
+
+ close(outfd[0]); // These are being used by the child
+ close(infd[1]);
+ memset(input, 0, sizeof(char)*255);
+
+ input[read(infd[0],input,255)] = 0; // Read from child's stdout
+ if (*input != '\0') {
+ int i;
+ i = strlen(input);
+ input[i-1]='\0';
+ }
+ if (!input || *input == '\0') {
+ char *env = NULL;
+ env = getenv("MANPATH");
+ if (env)
+ input = strdup(env);
+ }
+ if (!input || *input == '\0') {
+ if (input)
+ free(input);
+ /* Hard coded default. Don't argue. */
+ input = strdup ("/usr/share/man:/usr/man:/usr/local/share/man:/usr/local/man");
+ }
+ colon = input;
+
+ while (*colon) {
+ if (*colon == ':')
+ count++;
+ colon++;
+ }
+ man_paths = malloc (sizeof(char *) * (count+2)); /* 2 is for final string
+ * + NULL entry */
+ colon = input;
+ for (i=0; i< count; i++) {
+ next = strchr (colon, ':');
+ man_paths[i] = rrn_strndup(colon, next-colon);
+ colon = next;
+ colon++;
+ }
+ /* Final 2 entries - straight strdup of final entry and NULL */
+ man_paths[i] = strdup(colon);
+ i++;
+ man_paths[i] = NULL;
+ free (input);
+ }
+
+}
+#if 0
+#ifdef HAVE_LIBGDBM
+static void
+setup_gdbm (char *name)
+{
+ gdbm_handle = gdbm_open(name, 0, GDBM_READER, 0666, 0);
+ if (!gdbm_handle) {
+ sprintf(stderr, "ERROR: GDBM index %s could not be opened. Falling back\n", name);
+ setup_default();
+ } else {
+ initialised = TRUE;
+ mode = 1;
+ }
+}
+#endif
+
+#ifdef HAVE_LIBNDBM
+static void
+setup_ndbm (char *name)
+{
+ char *trunc;
+
+ trunc = malloc (sizeof(char) * (strlen(name)-3));
+ trunc = rrn_strndup (name, strlen(name) - 4);
+ ndbm_handle = dbm_open(trunc, O_RDONLY, 0666);
+ if (!ndbm_handle) {
+ sprintf(stderr, "ERROR: NDBM index %s could not be opened. Falling back\n", trunc);
+ setup_default();
+ } else {
+ initialise = TRUE;
+ mode = 2;
+ }
+ free (trunc);
+}
+#endif
+#endif
+
+static char *strrstr (char *s, char *wanted)
+{
+ char *scan;
+ char *first;
+ int len;
+
+ first = wanted;
+ len = strlen(wanted);
+ for (scan = s + strlen(s) - len ; scan >= s ; scan--)
+ {
+ if (*scan == *first)
+ {
+ if (!strncmp (scan, wanted, len))
+ {
+ return (scan);
+ }
+ }
+ }
+ return(NULL);
+}
+
+
+
+static char *
+get_name_for_file (char *filename, char **subsect)
+{
+ char *suffix;
+ char *cut;
+ char *sect;
+ char *final;
+
+ /* We assume, like reasonable people, that man pages
+ * have one of the forms:
+ * manname.sect.{gz,bz,bz2,lzma}
+ * manname.sect
+ * If it doesn't, things will probably break but we return
+ * our "best guess" (i.e. everything up to the suffix)
+ */
+ suffix = strrstr(filename, ".gz");
+ if (!suffix) {
+ suffix = strrstr(filename, ".bz2");
+ if (!suffix) {
+ suffix = strrstr(filename, ".bz");
+ }
+ if (!suffix) {
+ suffix = strrstr(filename, ".lzma");
+ }
+ }
+ if (suffix)
+ cut = rrn_strndup (filename, suffix-filename);
+ else
+ cut = strdup (filename);
+ sect = strrchr (cut, '.');
+ if (!sect)
+ return cut;
+
+ final = rrn_strndup (cut, sect-cut);
+ sect++;
+ *subsect = strdup (sect);
+ free (cut);
+ return final;
+
+}
+
+static int
+check_for_dup (RrnManEntry *reg, int entry)
+{
+ ManLink *iter = manhead[entry];
+
+ while (iter) {
+ if (!strcmp(reg->name, iter->reg->name))
+ return TRUE;
+ iter = iter->next;
+
+ }
+ return FALSE;
+}
+
+static int
+find_key (char *sect)
+{
+ int i;
+ for (i=0; i<43; i++){
+ if (!strcmp (sect, keys[i]))
+ return i;
+ }
+ return i;
+}
+
+static void
+process_dir(char *dir)
+{
+ char **dir_iter;
+ char *path = NULL;
+
+ DIR * dirp = NULL;
+ struct dirent * dp = NULL;
+ struct stat buf;
+ int current;
+
+ current = -1;
+ path = malloc(sizeof(char) * (strlen(dir) + 8));
+
+ dir_iter = avail_dirs;
+ while (dir_iter && *dir_iter) {
+ current++;
+ sprintf(path, "%s/%s", dir, *dir_iter);
+ if (access (path, R_OK)) {
+ dir_iter++;
+ continue;
+ }
+
+ dirp = opendir (path);
+
+ if (!dirp) {
+ dir_iter++;
+ continue;
+ }
+
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ char *full_name;
+
+ full_name = malloc (sizeof(char) * (strlen(dp->d_name) + strlen (path) + 3));
+ sprintf (full_name, "%s/%s", path, dp->d_name);
+
+ stat(full_name,&buf);
+ if (S_ISREG(buf.st_mode) || buf.st_mode & S_IFLNK) {
+ char *tmp = NULL;
+ char *suffix = NULL;
+ RrnManEntry *entry;
+ ManLink *link;
+ char *subsect = NULL;
+
+ entry = malloc (sizeof(RrnManEntry));
+ entry->name = get_name_for_file (dp->d_name, &subsect);
+ entry->path = full_name;
+ if (subsect) {
+ entry->section = subsect;
+ entry->comment = NULL;
+ current = find_key(subsect);
+ if (!check_for_dup (entry, current)) {
+ link = malloc (sizeof(ManLink));
+ link->reg = entry;
+
+ if (mantail[current]) {
+ mantail[current]->next = link;
+ link->next = NULL;
+ link->prev = mantail[current];
+ mantail[current] = link;
+ } else {
+ manhead[current] = mantail[current] = link;
+ link->prev = link->next = NULL;
+ }
+ } else {
+ free (entry->name);
+ free (entry->path);
+ free (entry->section);
+ if (entry->comment)
+ free (entry->comment);
+ free (entry);
+ }
+ }
+ }
+ } else {
+ closedir (dirp);
+ break;
+ }
+ }
+ dir_iter++;
+ }
+ free (path);
+}
+
+static void
+setup_default()
+{
+ char **path_iter;
+ char **langs;
+ char **lang_iter;
+
+ path_iter = man_paths;
+ langs = rrn_language_get_langs();
+
+ while (path_iter && *path_iter) {
+ if (access (*path_iter, R_OK)) {
+ path_iter++;
+ continue;
+ }
+
+ lang_iter = langs;
+ while (lang_iter && *lang_iter) {
+ char *path;
+ path = malloc (sizeof(char) * (strlen(*path_iter) +
+ strlen(*lang_iter)+2));
+ sprintf (path, "%s/%s", *path_iter, *lang_iter);
+ if (!access (path, R_OK)) {
+ process_dir(path);
+ }
+ free (path);
+ lang_iter++;
+ }
+
+
+ process_dir(*path_iter);
+ path_iter++;
+ }
+
+ /*lang_iter = langs;
+ while (lang_iter && *lang_iter) {
+ char **next = lang_iter;
+ next++;
+ free (lang_iter);
+ lang_iter = next;
+ }*/
+ free (langs);
+}
+
+static void
+rrn_man_init (void)
+{
+ char *default_dirs = "/var/cache/man:/usr/man";
+ char *split = NULL;
+#if 0
+ char *gdbm_index = "index.db";
+ char *ndbm_index = "index.dir";
+#endif
+ int i;
+ int npaths = 0;
+ char *ddirs;
+
+ for (i=0; i<44; i++) {
+ manhead[i] = mantail[i] = NULL;
+ }
+
+ setup_man_path ();
+
+ split = default_dirs;
+
+#if 0
+ while (split) {
+ char *next = strchr(split, ':');
+ char *dirname = NULL;
+ char *index = NULL;
+ FILE *access = NULL;
+
+ if (next)
+ dirname = rrn_strndup(split, (next-split));
+ else
+ dirname = strdup (split);
+#ifdef HAVE_LIBGDBM
+ index = malloc (sizeof(char) * (strlen(dirname) + 10 /*Len of gdbm_index + additional chars*/));
+ sprintf (index, "%s/%s", dirname, gdbm_index);
+ access = fopen(index, "r");
+ free(dirname);
+ if (access) {
+ fclose(access);
+ setup_gdbm(index);
+ free(index);
+ return;
+ }
+#endif
+#ifdef HAVE_NDBM
+ index = malloc (sizeof(char) * (strlen(dirname) + 11 /*Len of ndbm_index + additional chars*/));
+ sprintf (index, "%s/%s", dirname, gdbm_index);
+ access = fopen(index, "r");
+ free(dirname);
+ if (access) {
+ fclose(access);
+ setup_ndbm(index);
+ free(index);
+ return;
+ }
+#endif
+ split = strchr(split, ':');
+ if (split)
+ split++;
+ }
+#endif /* 0 */
+ /* If we get here, we have to do our own thang */
+ setup_default();
+ initialised = TRUE;
+
+}
+
+void
+rrn_man_for_each (RrnManForeachFunc funct, void * user_data)
+{
+ ManLink *iter;
+ int i;
+
+ if (!initialised)
+ rrn_man_init();
+
+ for (i=0; i<44; i++) {
+ iter = manhead[i];
+
+ while (iter) {
+ int res;
+ res = funct (iter->reg, user_data);
+ if (res == FALSE)
+ break;
+ iter = iter->next;
+ }
+ }
+ return;
+}
+
+
+void
+rrn_man_for_each_in_category (char *category,
+ RrnManForeachFunc funct,
+ void * user_data)
+{
+ ManLink *iter;
+ int cat;
+
+ if (!initialised)
+ rrn_man_init();
+
+ cat = find_key(category);
+ iter = manhead[cat];
+
+ while (iter) {
+ int res;
+ if (!strcmp (iter->reg->section, category)) {
+ res = funct (iter->reg, user_data);
+ if (res == FALSE)
+ break;
+ }
+ iter = iter->next;
+ }
+ return;
+}
+
+RrnManEntry *
+rrn_man_find_from_name (char *name, char *sect)
+{
+ ManLink *iter;
+ int cat;
+ RrnManEntry *res;
+
+ if (!initialised)
+ rrn_man_init ();
+
+ if (sect) {
+ cat = find_key(sect);
+ } else {
+ int i=0;
+ for (i=0; i<43; i++) {
+ iter = manhead[i];
+
+ while (iter) {
+ if (!strcmp (iter->reg->name, name)) {
+ return iter->reg;
+ }
+ iter = iter->next;
+ }
+ }
+ return NULL;
+ }
+ iter = manhead[cat];
+
+ while (iter) {
+ if (!strcmp (iter->reg->name, name)) {
+ return iter->reg;
+ }
+ iter = iter->next;
+ }
+
+
+ return NULL;
+}
+
+char **
+rrn_man_get_categories (void)
+{
+ if (!initialised)
+ rrn_man_init();
+
+ return keys;
+}
+
+
+void
+rrn_man_shutdown ()
+{
+ ManLink *iter;
+ int i;
+ initialised = FALSE;
+
+ for (i=0; i< 44; i++) {
+ iter = manhead[i];
+ while (iter) {
+ ManLink *tmp = iter->next;
+ free (iter->reg->name);
+ free (iter->reg->path);
+ free (iter->reg->section);
+ if (iter->reg->comment)
+ free (iter->reg->comment);
+ free (iter->reg);
+ free (iter);
+ iter = tmp;
+ }
+ manhead[i] = mantail[i] = NULL;
+ }
+ rrn_language_shutdown ();
+ return;
+}
diff --git a/librarian/rarian-man.h b/librarian/rarian-man.h
new file mode 100644
index 0000000..308c1fb
--- /dev/null
+++ b/librarian/rarian-man.h
@@ -0,0 +1,59 @@
+/*
+ * rarian-man.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2007 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RARIAN_MAN_H__
+#define RARIAN_MAN_H__
+
+#ifndef I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#error Rarian is unstable. To use it, you must acknowledge that
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+ typedef struct _RrnManEntry {
+ char *name;
+ char *path;
+ char *section;
+ char *comment;
+ } RrnManEntry;
+
+ typedef int (* RrnManForeachFunc) (void * reg, void *data);
+
+ void rrn_man_for_each (RrnManForeachFunc funct, void * user_data);
+ void rrn_man_for_each_in_category (char *category,
+ RrnManForeachFunc funct,
+ void * user_data);
+ char **rrn_man_get_categories (void);
+ RrnManEntry *rrn_man_find_from_name (char *name, char *sect);
+ void rrn_man_shutdown ();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RARIAN_INFO_H__ */
diff --git a/librarian/rarian-omf.cpp b/librarian/rarian-omf.cpp
new file mode 100644
index 0000000..17c08da
--- /dev/null
+++ b/librarian/rarian-omf.cpp
@@ -0,0 +1,673 @@
+/*
+ * rarian-omf.cpp
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <../util/tinyxml.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+
+/* TODO: Figure out why this is required here */
+#define I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#include "rarian-omf.h"
+
+static char *lang;
+static char *sk_series;
+static char *new_series;
+static char *type;
+
+static bool am_parsing = false;
+
+enum ElemType {
+ REG_NAME,
+ REG_URI,
+ REG_DESC,
+ REG_LANG,
+ REG_SERIES,
+ REG_TYPE,
+ REG_CATEGORIES
+};
+
+static char * omf_process_category (char *omf_cat);
+
+static void
+get_attribute (TiXmlElement *elem, ElemType e, RrnReg *reg)
+{
+ TiXmlAttribute* pAttrib=elem->FirstAttribute();
+
+ while (pAttrib != NULL) {
+ if (e == REG_URI && !strcmp (pAttrib->Name(), "url")) {
+ reg->uri = strdup (pAttrib->Value());
+ } else if (e == REG_LANG && !strcmp(pAttrib->Name(), "code")) {
+ reg->lang = strdup (pAttrib->Value());
+ } else if (e == REG_SERIES && !strcmp(pAttrib->Name(), "seriesid")) {
+ reg->identifier = (char *) malloc (sizeof(char) * (strlen(pAttrib->Value()) + 18));
+ sprintf (reg->identifier, "org.scrollkeeper.%s", pAttrib->Value());
+ } else if (e == REG_TYPE && !strcmp (pAttrib->Name(), "mime")) {
+ reg->type = strdup (pAttrib->Value());
+ } else if (e == REG_CATEGORIES && !strcmp (pAttrib->Name(), "category")) {
+
+ /* OMF files can only have 1 category. */
+ reg->categories = (char **) malloc (sizeof(char *) * 2);
+ reg->categories[0] = omf_process_category ((char *) pAttrib->Value());
+ reg->categories[1] = NULL;
+ } else {
+ /* Ignore unknown elements */
+ }
+
+ pAttrib = pAttrib->Next();
+ }
+}
+
+static void
+get_text (TiXmlNode* pElement, ElemType e, RrnReg *reg)
+{
+
+ if (!pElement) {
+ if (e == REG_NAME) {
+ reg->name = strdup (" ");
+ } else {
+ reg->comment = strdup (" ");
+ }
+ return;
+ }
+ if (e == REG_NAME) {
+ reg->name = strdup (pElement->Value());
+ } else if (e == REG_DESC ) {
+ reg->comment = strdup (pElement->Value());
+ }
+
+}
+
+static int
+process_node (TiXmlNode *pParent, RrnReg *reg)
+{
+ TiXmlNode* pChild;
+ TiXmlText* pText;
+ int t = pParent->Type();
+ int num;
+ ElemType e;
+
+
+ switch ( t )
+ {
+ case TiXmlNode::DOCUMENT:
+ break;
+
+ case TiXmlNode::ELEMENT:
+ if (!strcmp (pParent->Value(), "omf")) {
+ am_parsing = true;
+ } else if (!am_parsing) {
+ return 1;
+ }
+ if (!strcmp (pParent->Value(), "title")) {
+ e = REG_NAME;
+ get_text (pParent->FirstChild(), e, reg);
+ } else if (!strcmp (pParent->Value(), "description")) {
+ e = REG_DESC;
+ get_text (pParent->FirstChild(), e, reg);
+ } else if (!strcmp (pParent->Value(), "identifier")) {
+ e = REG_URI;
+ get_attribute (pParent->ToElement(), e, reg);
+ } else if (!strcmp (pParent->Value(), "language")) {
+ e = REG_LANG;
+ get_attribute (pParent->ToElement(), e, reg);
+ } else if (!strcmp (pParent->Value(), "relation")) {
+ e = REG_SERIES;
+ get_attribute (pParent->ToElement(), e, reg);
+ } else if (!strcmp (pParent->Value(), "format")) {
+ e = REG_TYPE;
+ get_attribute (pParent->ToElement(), e, reg);
+ } else if (!strcmp (pParent->Value(), "subject")) {
+ e = REG_CATEGORIES;
+ get_attribute (pParent->ToElement(), e, reg);
+ }
+ break;
+ default:
+ break;
+ }
+
+ for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
+ {
+ int ret;
+ ret = process_node ( pChild, reg);
+ if (ret != 0)
+ return ret;
+ }
+ return 0;
+}
+
+RrnReg *
+rrn_omf_parse_file (char *path)
+{
+ bool loadok;
+ RrnReg *reg;
+ TiXmlDocument doc (path);
+
+ reg = rrn_reg_new ();
+
+ loadok = doc.LoadFile(TIXML_ENCODING_UTF8);
+
+ if (!loadok) {
+ fprintf (stderr, "ERROR: Cannot parse %s. Is it valid?\n", path);
+ rrn_reg_free (reg);
+ return NULL;
+ }
+
+ TiXmlNode *pParent = doc.FirstChildElement();
+
+ if (process_node (pParent, reg) != 0) {
+ rrn_reg_free (reg);
+ return NULL;
+ }
+
+ if (!reg->identifier) {
+ reg->identifier = (char *) malloc (sizeof(char) * 35);
+ sprintf (reg->identifier, "org.scrollkeeper.unknown%d", rand());
+ }
+
+ return reg;
+}
+
+static char *
+omf_process_category (char *omf_cat)
+{
+ /* Converts omf categories into fd.o style categories
+ * using my own special and rather obscure methodology
+ * - Full omf categories and their current equivalents
+ * can be found in the docs directory of the source in the
+ * file "omf_equivalence.txt"
+ * I'm sorry.
+ */
+ char *result = NULL;
+ char *next = NULL;
+
+ if (!strncmp (omf_cat, "Applications", 12)) {
+ next = &(omf_cat[12]);
+ while (*next == '|') next++;
+ if (!next || *next == 0) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Amusement", 9)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Education", 9)) {
+ next = &(next[9]);
+ while (*next == '|') next++;
+ if (!next || *next == 0) {
+ result = strdup ("Education");
+ } else if (!strncmp (next, "Arts", 4)) {
+ result = strdup ("Art");
+ } else if (!strncmp (next, "Computer Science", 16) ||
+ !strncmp (next, "Technology", 10)) {
+ result = strdup ("ComputerScience");
+ } else if (!strncmp (next, "English", 7) ||
+ !strncmp (next, "Language", 8)) {
+ result = strdup ("Languages");
+ } else if (!strncmp (next, "Maths", 5)) {
+ result = strdup ("Math");
+ } else if (!strncmp (next, "Science", 7)) {
+ result = strdup ("Science");
+ } else if (!strncmp (next, "Other", 5)) {
+ result = strdup ("Education");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Games", 5)) {
+ next = &(next[5]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strncmp (next, "Other", 5)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Arcade", 6) ||
+ !strncmp (next, "Fighting", 8)) {
+ result = strdup ("ArcadeGame");
+ } else if (!strncmp (next, "Board", 5)) {
+ result = strdup ("BoardGame");
+ } else if (!strncmp (next, "First Person Shooters", 21) ||
+ !strncmp (next, "Role-Playing", 12)) {
+ result = strdup ("RolePlay");
+ } else if (!strncmp (next, "Puzzles", 7)) {
+ result = strdup ("LogicGame");
+ } else if (!strncmp (next, "Simulation", 10)) {
+ result = strdup ("Simulation");
+ } else if (!strncmp (next, "Strategy", 8)) {
+ result = strdup ("StrategyGame");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Internet", 8)) {
+ next = &(next[8]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 ||
+ !strncmp (next, "Fax", 3) ||
+ !strncmp (next, "Other", 5)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Chat", 4)) {
+ result = strdup ("Chat");
+ } else if (!strncmp (next, "Email", 5)) {
+ result = strdup ("Email");
+ } else if (!strncmp (next, "File Sharing", 12) ||
+ !strncmp (next, "FTP", 3)) {
+ result = strdup ("FileTransfer");
+ } else if (!strncmp (next, "Internet Phone", 14)) {
+ result = strdup ("Telephony");
+ } else if (!strncmp (next, "Messaging", 9)) {
+ result = strdup ("InstantMessaging");
+ } else if (!strncmp (next, "News", 4)) {
+ result = strdup ("News");
+ } else if (!strncmp (next, "Video Conferencing", 18)) {
+ result = strdup ("VideoConference");
+ } else if (!strncmp (next, "Web", 3)) {
+ result = strdup ("WebBrowser");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Multimedia", 10)) {
+ next = &(next[10]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 ||
+ !strncmp (next, "Other", 5)) {
+ result = strdup ("AudioVideo");
+ } else if (!strcmp (next, "Graphics|Conversion") ||
+ !strcmp (next, "Sound|Analysis") ||
+ !strcmp (next, "Sound|Conversion") ||
+ !strcmp (next, "Sound|Editing") ||
+ !strcmp (next, "Video|Conversion") ||
+ !strcmp (next, "Video|Editing")) {
+ result = strdup ("AudioVideoEditing");
+ } else if (!strncmp (next, "Graphics", 8)) {
+ next = &(next[8]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 ||
+ !strncmp (next, "Other", 5)) {
+ result = strdup ("Video");
+ } else if (!strncmp (next, "3D Modelling", 12) ||
+ !strncmp (next, "3D Rendering", 12)) {
+ result = strdup ("3DGraphics");
+ } else if (!strncmp (next, "CAD", 3)) {
+ result = strdup ("Engineering");
+ } else if (!strncmp (next, "Capture", 7)) {
+ result = strdup ("Recording");
+ } else if (!strncmp (next, "Drawing", 7) ||
+ !strncmp (next, "Editing", 7)) {
+ result = strdup ("2DGraphics");
+ } else if (!strncmp (next, "Viewing", 7)) {
+ result = strdup ("Viewer");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Sound", 5)) {
+ next = &(next[5]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 ||
+ !strncmp (next, "Other", 5)) {
+ result = strdup ("Audio");
+ } else if (!strncmp (next, "CD Mastering", 12)) {
+ result = strdup ("DiscBurning");
+ } else if (!strncmp (next, "MIDI", 4)) {
+ result = strdup ("Midi");
+ } else if (!strncmp (next, "Mixers", 6)) {
+ result = strdup ("Mixer");
+ } else if (!strncmp (next, "Players", 7)) {
+ result = strdup ("Player");
+ } else if (!strncmp (next, "Recording", 9)) {
+ result = strdup ("Recorder");
+ } else if (!strncmp (next, "Speech", 6)) {
+ result = strdup ("Audio");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Video", 5)) {
+ next = &(next[5]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 ||
+ !strncmp (next, "Other", 5)) {
+ result = strdup ("Video");
+ } else if (!strncmp (next, "Capture", 7)) {
+ result = strdup ("Recorder");
+ } else if (!strncmp (next, "Display", 7)) {
+ result = strdup ("Player");
+ } else {
+ goto failed;
+ }
+
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Office", 6)) {
+ next = &(next[6]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Office");
+ } else if (!strncmp (next, "Calendar", 8)) {
+ result = strdup ("Calendar");
+ } else if (!strncmp (next, "Data Processing", 15)) {
+ result = strdup ("Office");
+ } else if (!strncmp (next, "Database", 8)) {
+ result = strdup ("Database");
+ } else if (!strncmp (next, "Email", 5)) {
+ result = strdup ("Email");
+ } else if (!strncmp (next, "Financial", 9)) {
+ result = strdup ("Finance");
+ } else if (!strncmp (next, "PIM", 3)) {
+ result = strdup ("ContactManagement");
+ } else if (!strncmp (next, "Plotting", 8)) {
+ result = strdup ("Office");
+ } else if (!strncmp (next, "Presentation", 12)) {
+ result = strdup ("Presentation");
+ } else if (!strncmp (next, "Publishing", 10)) {
+ result = strdup ("Publishing");
+ } else if (!strncmp (next, "Web Publishing", 14)) {
+ result = strdup ("Publishing");
+ } else if (!strncmp (next, "Word Processing", 15)) {
+ result = strdup ("WordProcessor");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Scientific", 10)) {
+ next = &(next[10]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Science");
+ } else if (!strncmp (next, "Astronomy", 9)) {
+ result = strdup ("Astronomy");
+ } else if (!strncmp (next, "Astrophysics", 12)) {
+ result = strdup ("Astronomy");
+ } else if (!strncmp (next, "Biology", 7)) {
+ result = strdup ("Biology");
+ } else if (!strncmp (next, "Chemistry", 9)) {
+ result = strdup ("Chemistry");
+ } else if (!strncmp (next, "EDA", 3)) {
+ result = strdup ("Engineering");
+ } else if (!strncmp (next, "Genetics", 8)) {
+ result = strdup ("Biology");
+ } else if (!strncmp (next, "Math", 4)) {
+ result = strdup ("Math");
+ } else if (!strncmp (next, "Physics", 7)) {
+ result = strdup ("Physics");
+ } else if (!strncmp (next, "Visualisation", 13)) {
+ result = strdup ("DataVisualisation");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Security", 8)) {
+ /* First, "don't care" type one, where all
+ * categories go to the same category */
+ result = strdup ("Security");
+ } else if (!strncmp (next, "Text Editors", 12)) {
+ /* Another don't care */
+ result = strdup ("TextEditor");
+ } else if (!strncmp (next, "Utilities", 9)) {
+ next = &(next[9]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Archiving", 9)) {
+ result = strdup ("Archiving");
+ } else if (!strncmp (next, "Calculating", 11)) {
+ result = strdup ("Calculator");
+ } else if (!strncmp (next, "Clocks", 6)) {
+ result = strdup ("Clock");
+ } else if (!strncmp (next, "Compression", 11)) {
+ result = strdup ("Compression");
+ } else if (!strncmp (next, "File Utilities", 14)) {
+ result = strdup ("FileTools");
+ } else if (!strncmp (next, "Monitors", 8)) {
+ result = strdup ("Monitor");
+ } else if (!strncmp (next, "Printing", 8)) {
+ result = strdup ("Printing");
+ } else if (!strncmp (next, "Terminals", 9)) {
+ result = strdup ("TerminalEmulator");
+ } else if (!strncmp (next, "Text Utilities", 13)) {
+ result = strdup ("ConsoleOnly");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "X", 1)) {
+ next = &(next[1]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Configuration", 13) ||
+ !strncmp (next, "Fonts", 5) ||
+ !strncmp (next, "Login Managers", 14) ||
+ !strncmp (next, "Window Managers", 15)) {
+ result = strdup ("DesktopSettings");
+ } else if (!strncmp (next, "Screensavers", 12)) {
+ result = strdup ("Screensaver");
+ } else {
+ goto failed;
+ }
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (omf_cat, "CDE", 3)) {
+ result = strdup ("DesktopSettings");
+ } else if (!strncmp (omf_cat, "Development", 11)) {
+ next = &(omf_cat[11]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Development");
+ } else if (!strncmp (next, "Databases", 9)) {
+ result = strdup ("Database");
+ } else if (!strncmp (next, "Development Tools", 17)) {
+ next = &(next[17]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other") ||
+ !strcmp (next, "Code Generators") ||
+ !strcmp (next, "Configuration") ||
+ !strcmp (next, "Packaging") ||
+ !strcmp (next, "RAD")) {
+ result = strdup ("Development");
+ } else if (!strncmp (next, "Build Tools", 11)) {
+ result = strdup ("Building");
+ } else if (!strncmp (next, "Debuggers", 9)) {
+ result = strdup ("Debugger");
+ } else if (!strncmp (next, "IDEs", 4)) {
+ result = strdup ("IDE");
+ } else if (!strncmp (next, "Profiling", 9)) {
+ result = strdup ("Profiling");
+ } else if (!strncmp (next, "Version Control", 15)) {
+ result = strdup ("RevisionControl");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Environments", 12) ||
+ !strncmp (next, "Kernels", 7) ||
+ !strncmp (next, "Libraries", 9) ||
+ !strncmp (next, "System Calls", 12)) {
+ /* Another don't care. All go into dev. */
+ result = strdup ("Development");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (omf_cat, "General", 7)) {
+ next = &(omf_cat[7]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Documentation");
+ } else if (!strncmp (next, "Licenses", 8)) {
+ result = strdup ("Documentation");
+ } else if (!strncmp (next, "Linux", 5)) {
+ /* Another don't care. All go in core */
+ result = strdup ("Core");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (omf_cat, "GNOME", 5)) {
+ next = &(omf_cat[6]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other") ||
+ !strncmp (next, "Desktop", 7)) {
+ result = strdup ("Core");
+ } else if (!strncmp (next, "Accessibility", 13)) {
+ result = strdup ("Accessibility");
+ } else if (!strncmp (next, "Applications", 12)) {
+ /* Grr. Fake categories galore */
+ next = &(next[12]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other") ||
+ !strncmp (next, "Accessories", 11)) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Amusement", 9) ||
+ !strncmp (next, "Games", 5)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Clock", 5)) {
+ result = strdup ("Clock");
+ } else if (!strncmp (next, "Monitors", 8)) {
+ result = strdup ("Monitor");
+ } else if (!strncmp (next, "Multimedia", 10)) {
+ result = strdup ("AudioVideo");
+ } else if (!strncmp (next, "Network", 7) ||
+ !strncmp (next, "Internet", 8)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Utility", 7)) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Accessories", 11)) {
+ /* Grr. people ignoring categorisation */
+ result = strdup ("Applet");
+ }
+ } else if (!strncmp (next, "Applets", 7)) {
+ next = &(next[7]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("Applet");
+ } else if (!strncmp (next, "Amusement", 9)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Clock", 5)) {
+ result = strdup ("Clock");
+ } else if (!strncmp (next, "Monitors", 8)) {
+ result = strdup ("Monitor");
+ } else if (!strncmp (next, "Multimedia", 10)) {
+ result = strdup ("AudioVideo");
+ } else if (!strncmp (next, "Network", 7) ||
+ !strncmp (next, "Internet", 8)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Utility", 7)) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Accessories", 11)) {
+ /* Grr. people ignoring categorisation */
+ result = strdup ("Applet");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (next, "Utilities", 9)) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Development", 11)) {
+ /* Don't care */
+ result = strdup ("Development");
+ } else if (!strncmp (next, "Games", 5)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Graphics", 8)) {
+ result = strdup ("Graphics");
+ } else if (!strncmp (next, "Internet", 8)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Multimedia", 10)) {
+ result = strdup ("AudioVideo");
+ } else if (!strncmp (next, "Settings", 8)) {
+ result = strdup ("Settings");
+ } else if (!strncmp (next, "System", 6)) {
+ result = strdup ("System");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (omf_cat, "KDE", 3)) {
+ next = &(omf_cat[3]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other") ||
+ !strcmp (next, "Programs") ||
+ !strcmp (next, "Applications")) {
+ result = strdup ("KDE");
+ } else if (!strncmp (next, "Utilities", 9)) {
+ result = strdup ("Utility");
+ } else if (!strncmp (next, "Games", 5)) {
+ result = strdup ("Game");
+ } else if (!strncmp (next, "Graphics", 8)) {
+ result = strdup ("Graphics");
+ } else if (!strncmp (next, "Internet", 8)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Multimedia", 10)) {
+ result = strdup ("AudioVideo");
+ } else if (!strncmp (next, "Settings", 8)) {
+ result = strdup ("Settings");
+ } else if (!strncmp (next, "System", 6)) {
+ result = strdup ("System");
+ } else if (!strncmp (next, "Development", 11)) {
+ result = strdup ("Development");
+ } else {
+ goto failed;
+ }
+ } else if (!strncmp (omf_cat, "System", 6)) {
+ next = &(omf_cat[6]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other")) {
+ result = strdup ("System");
+ } else if (!strncmp (next, "Administration", 14)) {
+ next = &(next[14]);
+ while (*next == '|') next++;
+ if (!next || *next == 0 || !strcmp (next, "Other") ||
+ !strcmp (next, "Users")) {
+ result = strdup ("Settings");
+ } else if (!strncmp (next, "Backups", 7)) {
+ result = strdup ("Archiving");
+ } else if (!strncmp (next, "Filesystems", 11)) {
+ result = strdup ("Filesystem");
+ } else if (!strncmp (next, "Networking", 10)) {
+ result = strdup ("Network");
+ } else if (!strncmp (next, "Configuration", 13)) {
+ /* Yet another don't care */
+ result = strdup ("Settings");
+ } else if (!strncmp (next, "Hardware", 8)) {
+ /* Another don't care */
+ result = strdup ("HardwareSettings");
+ } else if (!strncmp (next, "Package Management", 18)) {
+ result = strdup ("PackageManager");
+ } else if (!strncmp (next, "Security", 8)) {
+ result = strdup ("Security");
+ } else if (!strncmp (next, "Services", 8)) {
+ next = &(next[8]);
+ while (*next == '|') next++;
+ if (!next || *next == 0) {
+ result = strdup ("System");
+ } else if (!strncmp (next, "Printing", 8)) {
+ result = strdup ("Printing");
+ } else {
+ result = strdup ("System");
+ }
+ } else {
+ goto failed;
+ }
+ } else {
+ goto failed;
+ }
+ } else {
+ failed:
+ fprintf (stderr, "OMF category \'%s\' not recognised, ignoring.\n",
+ omf_cat);
+ }
+
+ return result;
+}
diff --git a/librarian/rarian-omf.h b/librarian/rarian-omf.h
new file mode 100644
index 0000000..711e4a9
--- /dev/null
+++ b/librarian/rarian-omf.h
@@ -0,0 +1,42 @@
+/*
+ * rarian-omf.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RARIAN_OMF_H__
+#define RARIAN_OMF_H__
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#include <rarian-reg-utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+RrnReg *rrn_omf_parse_file (char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RARIAN_OMF_H__ */
diff --git a/librarian/rarian-reg-full.c b/librarian/rarian-reg-full.c
new file mode 100644
index 0000000..f3abe9a
--- /dev/null
+++ b/librarian/rarian-reg-full.c
@@ -0,0 +1,760 @@
+/*
+ * rarian-reg-full.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/* TODO: Figure out why this is required here */
+#define I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#include "rarian-reg-full.h"
+#include "rarian-reg-utils.h"
+#include "rarian-utils.h"
+
+
+static void process_line_full (char *line, RrnRegFull *reg);
+static void process_pair_full (RrnRegFull *reg, char *key, char *value);
+
+static void process_sect_line_full (char *line, RrnSectFull *sect);
+static void process_sect_pair_full (RrnSectFull *sect, char *key,
+ char *value);
+static int rrn_reg_add_sect_full (RrnRegFull *reg, RrnSectFull *sect);
+static RrnSectFull * rrn_sect_new_full ();
+static void rrn_sect_free_full (RrnSectFull *sect);
+static void process_path_full (RrnRegFull *reg);
+static void process_section_path_full (RrnListEntry *owner_paths, RrnSectFull *section);
+
+RrnRegFull *
+rrn_reg_new_full ()
+{
+ RrnRegFull *reg;
+
+ reg = malloc (sizeof (RrnRegFull));
+ reg->name = NULL;
+ reg->uri = NULL;
+ reg->comment = NULL;
+ reg->identifier = NULL;
+ reg->type = NULL;
+ reg->icon = NULL;
+ reg->categories = NULL;
+ reg->weight = 0;
+ reg->heritage = NULL;
+ reg->lang = NULL;
+ reg->children = NULL;
+
+ return reg;
+}
+
+RrnRegFull *
+rrn_reg_parse_file_full (char *filename)
+{
+ RrnRegFull *reg = NULL;
+ RrnSectFull *sect = NULL;
+ RrnSectFull *orphaned_sections = NULL;
+ int mode = 0;
+ FILE *file;
+ char *buf;
+
+ if (access(filename, R_OK)) {
+ fprintf (stderr, "WARNING: cannot access file %s\n", filename);
+ return NULL;
+ }
+ reg = rrn_reg_new_full ();
+
+ file = fopen (filename, "r");
+
+ buf = malloc (sizeof (char) * 1024);
+ while (fgets (buf, 1023, file)) {
+ char *real = NULL;
+ while (buf[strlen(buf)-1] != '\n') {
+ char *tmp;
+ char *result = NULL;
+ tmp = strdup (buf);
+ buf = fgets (buf, 1023, file);
+ result = malloc (sizeof (char) * (strlen(tmp)+strlen(buf)+2));
+ strcpy (result, tmp);
+ strcat (result, buf);
+ free (tmp);
+ free (buf);
+ buf = result;
+ }
+ real = buf;
+ while (*real && isspace(*real) && *real != '\n') {
+ real++;
+ }
+ if (!real || real[0] == '\n' || real[0] == '#') {
+ /* Black Line or comment. Ignore. */
+ } else if (real[0] == '[') {
+ if (!strncmp (real, "[Document]", 10)) {
+ mode = 0;
+
+ if (sect) {
+ if (rrn_reg_add_sect_full (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ sect = NULL;
+ }
+ } else if (!strncmp (real, "[Section]", 9)) {
+ mode = 1;
+ if (sect) {
+ if (rrn_reg_add_sect_full (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ sect = NULL;
+ }
+ sect = rrn_sect_new_full ();
+ } else {
+ fprintf (stderr, "Unknown section header: %s. Ignoring\n", real);
+ }
+ } else if (strchr ( real, '=')) {
+ if (mode == 0) {
+ process_line_full (buf, reg);
+ } else {
+ process_sect_line_full (buf, sect);
+ }
+ } else {
+ fprintf (stdout, "WARNING: Don't know how to handle line: %s\n", buf);
+ }
+ }
+ fclose (file);
+ free (buf);
+ if (sect) {
+ if (rrn_reg_add_sect_full (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ if (!reg->name || !reg->uri || !reg->type || !reg->categories ) {
+ rrn_reg_free_full (reg);
+ reg = NULL;
+ }
+ sect = orphaned_sections;
+ while (sect) {
+ if (rrn_reg_add_sect_full (reg, sect) == 1) {
+ fprintf (stderr, "Error: Orphaned section %s not added.\n",
+ sect->name);
+ }
+ sect = sect->next;
+ }
+
+ if (reg && !reg->identifier) {
+ char *last;
+ char *sep;
+ char *basename;
+
+ sep = strrchr (filename, '/');
+ last = strrchr (filename, '.');
+ if (!last || !sep || last < sep) {
+ fprintf (stderr, "Error: Can't cut put basename properly\n");
+ rrn_reg_free_full (reg);
+ return NULL;
+ }
+ basename = rrn_strndup (sep + 1, last - (sep + 1));
+ reg->identifier = malloc (sizeof (char)*(strlen(basename)+11));
+ sprintf (reg->identifier, "org.other.%s", basename);
+ free (basename);
+
+ }
+ if (reg)
+ process_path_full (reg);
+
+
+ return reg;
+}
+
+static void
+process_line_full (char *line, RrnRegFull *reg)
+{
+ char *ret = NULL;
+ char *key;
+ char *value;
+ char *tmp;
+
+ tmp = strchr (line, '=');
+ if (!tmp) {
+ fprintf (stderr, "WARNING: Malformed line: \n%s\n", line);
+ return;
+ }
+
+ if (line[strlen(line)-1] == '\n') {
+ line[strlen(line)-1] = '\0';
+ }
+
+ key = rrn_strndup (line, tmp - line);
+ tmp++;
+ value = strdup (tmp);
+ process_pair_full (reg, key, value);
+ free (key);
+ free (value);
+
+ return;
+}
+
+static char *
+find_language (char *key)
+{
+ char *lbrace = NULL, *rbrace = NULL;
+ char *result;
+
+ result = strdup ("C");
+ lbrace = strchr (key, '[');
+ if (!lbrace)
+ return result;
+ lbrace++;
+ rbrace = strchr (key, ']');
+ if (!rbrace)
+ return result;
+ free (result);
+ result = rrn_strndup (lbrace, rbrace-lbrace);
+ return result;
+}
+
+RrnListEntry *
+rrn_full_add_field (RrnListEntry *current, char *text, char *lang)
+{
+ RrnListEntry *entry = NULL;
+ RrnListEntry *iter = NULL;
+ iter = current;
+ while (iter) {
+ if (!strcmp(iter->lang, lang))
+ return current;
+ iter = iter->next;
+ }
+ entry = malloc (sizeof (RrnListEntry));
+ if (text) {
+ entry->text = strdup (text);
+ } else {
+ entry->text = strdup ("");
+ }
+ entry->lang = strdup (lang);
+ entry->next = current;
+
+ return entry;
+
+}
+
+static char **
+process_categories_full (char *cat_string)
+{
+ char **result = NULL;
+ char **tmp = NULL;
+ int ncats = 0;
+ char *current_break = cat_string;
+ char *semi;
+ int i;
+ do {
+ semi = strchr (current_break, ';');
+ if (result) {
+ tmp = malloc (sizeof (char *)*ncats);
+ for (i=0; i< ncats; i++) {
+ tmp[i] = strdup (result[i]);
+ free (result[i]);
+ }
+ free (result);
+ }
+ ncats += 1;
+ result = malloc (sizeof (char *)*(ncats+1));
+ if (tmp) {
+ for (i=0; i<ncats-1; i++) {
+ result[i] = strdup (tmp[i]);
+ free (tmp[i]);
+ }
+ free (tmp);
+ }
+ result[ncats-1] = rrn_strndup (current_break, semi - current_break);
+ result[ncats] = NULL;
+ current_break = semi+1;
+ } while (semi);
+
+ return result;
+}
+
+static void
+process_pair_full (RrnRegFull *reg, char *key, char *value)
+{
+ char *lang = NULL;
+
+ lang = find_language (key);
+
+ if (!strncmp (key, "Name", 4)) {
+ reg->name = rrn_full_add_field (reg->name, value, lang);
+ } else if (!strncmp (key, "Comment", 7)) {
+ reg->comment = rrn_full_add_field (reg->comment, value, lang);
+ } else if (!strncmp (key, "DocPath", 7)) {
+ reg->uri = rrn_full_add_field (reg->uri, value, lang);
+ } else if (!strcmp (key, "DocIdentifier")) {
+ reg->identifier = strdup (value);
+ } else if (!strcmp (key, "DocType")) {
+ reg->type = strdup (value);
+ } else if (!strcmp (key, "Categories")) {
+ reg->categories = process_categories_full (value);
+ } else if (!strcmp (key, "DocWeight")) {
+ reg->weight = atoi (value);
+ } else if (!strcmp (key, "DocHeritage")) {
+ reg->heritage = strdup (value);
+ } else if (!strcmp (key, "NoDisplay")) {
+ reg->hidden = TRUE;
+ } else if (!strcmp (key, "DocDefaultSection")) {
+ reg->default_section = strdup (value);
+ } else if (!strcmp (key, "DocLang")) {
+ if (!reg->lang) {
+ reg->lang = strdup (value);
+ }
+ } else if (!strcmp (key, "Icon")){
+ reg->icon = strdup (value);
+ } else {
+ fprintf (stderr, "WARNING: Unknown element %s: %s\n", key, value);
+ }
+ return;
+}
+
+void
+rrn_reg_free_full (RrnRegFull *reg)
+{
+ RrnSectFull *sect = reg->children;
+ char **tmp = reg->categories;
+ free (reg->name);
+ free (reg->comment);
+ free (reg->uri);
+ free (reg->type);
+ free (reg->identifier);
+ free (reg->heritage);
+ free (reg->lang);
+ if (tmp) {
+ while (*tmp) {
+ free (*tmp);
+ tmp++;
+ }
+ }
+ free (reg->categories);
+ while (sect) {
+ RrnSectFull *s1 = sect->next;
+ rrn_sect_free_full (sect);
+ sect = s1;
+ }
+ free (reg);
+ return;
+}
+
+/* Section stuff */
+RrnSectFull *
+rrn_sect_new_full ()
+{
+ RrnSectFull * sect;
+ sect = malloc (sizeof (RrnSectFull));
+
+ sect->name = NULL;
+ sect->identifier = NULL;
+ sect->uri = NULL;
+ sect->next = NULL;
+ sect->prev = NULL;
+ sect->children = NULL;
+ sect->owner = NULL;
+
+ return sect;
+}
+
+static RrnSectFull *
+find_sect_full (RrnSectFull *start, char *id)
+{
+ RrnSectFull *ret = start;
+
+ while (ret) {
+ if (!strcmp (ret->identifier, id)) {
+ return ret;
+ }
+ ret = ret->next;
+ }
+ return NULL;
+}
+
+static void
+rrn_reg_add_sections_full (RrnRegFull *reg, RrnSectFull *sects)
+{
+ RrnSectFull *real_orphans = NULL;
+ RrnSectFull *next = NULL;
+ int depth = 0;
+ do {
+ depth ++;
+ if (depth > 4) {
+ /* The pathological case where someone's done something really,
+ * stupid and defined a subsection with the section without
+ * definind the section.
+ * We break after 4 iterations.
+ */
+ return;
+ }
+ next = sects;
+ while (sects) {
+ next = sects->next;
+ if (rrn_reg_add_sect_full (reg, sects) == 1) {
+ sects->prev = NULL;
+ sects->next = real_orphans;
+ if (real_orphans)
+ real_orphans->prev = sects;
+ real_orphans = sects;
+ };
+ sects = next;
+ }
+ sects = real_orphans;
+ } while (sects);
+ return;
+}
+
+static int
+rrn_sects_add_sect_full (RrnSectFull *current, RrnSectFull *sect)
+{
+ char *cur_sect = NULL;
+ RrnSectFull *append_sect;
+ char *tmp = NULL;
+ char *dot = NULL;
+
+ cur_sect = sect->owner;
+
+ append_sect = current;
+ do {
+ dot = strchr (cur_sect, '.');
+ tmp = rrn_strndup (cur_sect, dot-cur_sect);
+ append_sect = find_sect_full (append_sect, tmp);
+ cur_sect = dot;
+ free (tmp);
+ } while (cur_sect && append_sect);
+ if (append_sect) {
+ sect->prev = NULL;
+ sect->next = append_sect->children;
+ if (append_sect->children)
+ append_sect->children->prev = sect;
+ append_sect->children = sect;
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+rrn_reg_add_sect_full (RrnRegFull *reg, RrnSectFull *sect)
+{
+ if (!sect->owner || !strcmp (reg->identifier, sect->owner)) {
+ sect->prev = NULL;
+ sect->next = reg->children;
+ if (reg->children)
+ reg->children->prev = sect;
+ reg->children = sect;
+ } else {
+ char *cur_sect = NULL;
+ RrnSectFull *append_sect;
+ char *tmp = NULL;
+ char *dot = NULL;
+
+ if (!strncmp (sect->owner, reg->identifier, strlen (reg->identifier))) {
+ cur_sect = &sect->owner[strlen(reg->identifier)+1];
+ } else {
+ cur_sect = sect->owner;
+ }
+ append_sect = reg->children;
+ do {
+ dot = strchr (cur_sect, '.');
+ tmp = rrn_strndup (cur_sect, dot-cur_sect);
+ append_sect = find_sect_full (append_sect, tmp);
+ cur_sect = dot;
+ free (tmp);
+ } while (cur_sect && append_sect);
+ if (append_sect) {
+ sect->prev = NULL;
+ sect->next = append_sect->children;
+ if (append_sect->children)
+ append_sect->children->prev = sect;
+ append_sect->children = sect;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+RrnSectFull *
+rrn_sect_parse_file_full (char *filename)
+{
+ RrnSectFull *sect = NULL;
+ RrnSectFull *orphaned_sections = NULL;
+ FILE *file;
+ char *buf;
+ char *real_owner = NULL;
+
+ if (access(filename, R_OK)) {
+ fprintf (stderr, "WARNING: cannot access file %s\n", filename);
+ return NULL;
+ }
+
+ file = fopen (filename, "r");
+
+ buf = malloc (sizeof (char) * 1024);
+ while (fgets (buf, 1023, file)) {
+ char *real = NULL;
+ while (buf[strlen(buf)-1] != '\n') {
+ char *tmp;
+ char *result = NULL;
+ tmp = strdup (buf);
+ buf = fgets (buf, 1023, file);
+ result = malloc (sizeof (char) * (strlen(tmp)+strlen(buf)+2));
+ strcpy (result, tmp);
+ strcat (result, buf);
+ free (tmp);
+ free (buf);
+ buf = result;
+ }
+ real = buf;
+ while (*real && isspace(*real) && *real != '\n') {
+ real++;
+ }
+ if (!real || real[0] == '\n' || real[0] == '#') {
+ /* Black Line or comment. Ignore. */
+ } else if (real[0] == '[') {
+ if (!strncmp (real, "[Section]", 9)) {
+ if (sect) {
+ if (rrn_sects_add_sect_full (orphaned_sections, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ sect = rrn_sect_new_full ();
+ } else {
+ fprintf (stderr, "Unknown section header: !%s!. Ignoring\n", real);
+ }
+ } else if (strchr ( real, '=')) {
+ process_sect_line_full (buf, sect);
+ } else {
+ fprintf (stderr, "WARNING: Don't know how to handle line: %s\n", buf);
+ }
+ }
+ fclose (file);
+ free (buf);
+
+ if (sect) {
+ if (rrn_sects_add_sect_full (orphaned_sections, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ return orphaned_sections;
+}
+
+static void
+process_sect_line_full (char *line, RrnSectFull *sect)
+{
+ char *ret = NULL;
+ char *key;
+ char *value;
+ char *tmp;
+
+ tmp = strchr (line, '=');
+ if (!tmp) {
+ fprintf (stderr, "WARNING: Malformed line: \n%s\n", line);
+ return;
+ }
+
+ if (line[strlen(line)-1] == '\n') {
+ line[strlen(line)-1] = '\0';
+ }
+
+ key = rrn_strndup (line, tmp - line);
+ tmp++;
+ value = strdup (tmp);
+ process_sect_pair_full (sect, key, value);
+ free (key);
+ free (value);
+
+ return;
+
+}
+
+static void
+process_sect_pair_full (RrnSectFull *sect, char *key, char *value)
+{
+ char *lang = NULL;
+
+ lang = find_language (key);
+
+ if (!strncmp (key, "SectionName", 11) || !strncmp (key, "sectionname", 11)) {
+ sect->name = rrn_full_add_field (sect->name, value, lang);
+ } else if (!strcmp (key, "SectionIdentifier") || !strcmp (key, "sectionidentifier")) {
+ sect->identifier = strdup (value);
+ } else if (!strncmp (key, "SectionPath", 11) || !strncmp (key, "sectionpath", 11)) {
+ sect->uri = rrn_full_add_field (sect->uri, value, lang);
+ } else if (!strcmp (key, "SectionDocument") || !strcmp (key, "sectiondocument")) {
+ sect->owner = strdup (value);
+ } else {
+ fprintf (stderr, "WARNING: Unknown element for section %s: %s\n", key, value);
+ }
+ return;
+}
+
+static void
+process_path_full (RrnRegFull *reg)
+{
+ char *prefix = NULL;
+ RrnSectFull *child = reg->children;
+ RrnListEntry *entry = reg->uri;
+ while (entry) {
+ if (!strncmp ("file:", entry->text, 5)) {
+ /* No processing needs done. The URI is already in the file: scheme */
+ return;
+ }
+ if ((prefix = strchr (entry->text, ':')) && (prefix-(entry->text) < 7)) {
+ /* Probably has another (non-file:) URI scheme. If so, we're going to
+ * return as is
+ */
+ return;
+ }
+ /* Otherwise, promote to file: URI scheme, reusing the prefix vble */
+ prefix = malloc (sizeof (char) * (strlen(entry->text)+6));
+ sprintf (prefix, "file:%s", entry->text);
+ free (entry->text);
+ entry->text = prefix;
+ entry = entry->next;
+ }
+ while (child) {
+ process_section_path_full (reg->uri, child);
+ child = child->next;
+ }
+}
+
+static void
+process_section_path_full (RrnListEntry *owner_paths, RrnSectFull *section)
+{
+ char *tmp = NULL;
+ char *new_uri = NULL;
+ char *prefix = NULL;
+ char *filename = NULL;
+ char *owner_path = NULL;
+
+ RrnSectFull *child = section->children;
+
+ RrnListEntry *entry = section->uri;
+
+ while (entry) {
+ RrnListEntry *parent_entry = owner_paths;
+
+ while (parent_entry && strcmp (parent_entry->lang, entry->lang)) {
+ parent_entry = parent_entry->next;
+ }
+ if (!parent_entry) {
+ parent_entry = owner_paths;
+ while (strcmp (parent_entry->lang, "C")) {
+ parent_entry = parent_entry->next;
+ }
+ if (!parent_entry) {
+ fprintf (stderr, "Error: Cannot find a suitable parent for child %s\n"
+ "This usually results from bad script files. Please correct and\n"
+ "try again. Ignoring this child (and it's children) completely.\n",
+ entry->text);
+ return;
+ }
+ }
+ owner_path = parent_entry->text;
+
+ if (!strncmp ("file:", entry->text, 5))
+ goto done;
+ if ((prefix = strchr (entry->text, ':')) && (prefix-(entry->text) < 7)) {
+ /* Probably has another (non-file:) URI scheme. If so, we're going to
+ * return as is
+ */
+ goto done;
+ }
+ if (entry->text[0] == '/') {
+ /* Absolute path */
+ new_uri = malloc (sizeof (char) * strlen(entry->text)+6);
+ sprintf (new_uri, "file:/%s", entry->text);
+ free (entry->text);
+ entry->text = new_uri;
+ goto done;
+ }
+
+ /* If we get through to here, the path is relative to the parents
+ * own path. We need to disect and repair
+ */
+
+ /* First, cut out the owner's file */
+ tmp = strrchr (owner_path, '/');
+ prefix = rrn_strndup (owner_path, tmp-owner_path);
+ if (!tmp) {
+ fprintf (stderr, "Warning: cannot cut up path for the %s section\n"
+ "This generally indicates a problem with the scroll\n"
+ " file for this section, or its parent document.\n"
+ "The path will not be fixed.\n", entry->text);
+ return;
+ }
+ new_uri = malloc (sizeof (char) * (strlen(prefix)+strlen(entry->text)+2));
+ sprintf (new_uri, "%s/%s", prefix, entry->text);
+ free (entry->text);
+ entry->text = new_uri;
+done:
+ entry = entry->next;
+ }
+
+ /* In all cases, we want to iterate through the children of the children
+ * just to make sure they're all right
+ */
+ while (child) {
+ process_section_path_full (section->uri, child);
+ child = child->next;
+ }
+}
+
+
+
+void
+rrn_sect_free_full (RrnSectFull *sect)
+{
+ RrnSectFull *child = sect->children;
+ free (sect->name);
+ free (sect->identifier);
+ free (sect->uri);
+ free (sect->owner);
+ while (child) {
+ RrnSectFull *c1 = child->next;
+ rrn_sect_free_full (child);
+ child = c1;
+ }
+ free (sect);
+}
diff --git a/librarian/rarian-reg-full.h b/librarian/rarian-reg-full.h
new file mode 100644
index 0000000..59f339c
--- /dev/null
+++ b/librarian/rarian-reg-full.h
@@ -0,0 +1,86 @@
+/*
+ * rarian-reg-full.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __RARIAN_REG_FULL_H
+#define __RARIAN_REG_FULL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A special type of RrnReg that contains all the translations
+ * of all the fields, instead of the interesting ones
+ */
+typedef struct _RrnRegFull RrnRegFull;
+typedef struct _RrnListEntry RrnListEntry;
+
+typedef struct _RrnSectFull RrnSectFull;
+
+struct _RrnListEntry
+{
+ RrnListEntry * next;
+ char *text;
+ char *lang;
+};
+
+struct _RrnRegFull
+{
+ RrnListEntry *name;
+ RrnListEntry *uri;
+ RrnListEntry *comment;
+ char *icon;
+ char *identifier;
+ char *type;
+ char **categories;
+ int weight;
+ char *heritage;
+ char *lang;
+ char *default_section;
+ int hidden;
+ RrnSectFull *children;
+};
+
+struct _RrnSectFull
+{
+ RrnListEntry *name;
+ char *identifier;
+ RrnListEntry *uri;
+ char *owner;
+ RrnSectFull *next;
+ RrnSectFull *prev;
+ RrnSectFull *children;
+};
+
+RrnRegFull * rrn_reg_new_full ();
+
+RrnRegFull * rrn_reg_parse_file_full (char *filename);
+
+RrnRegFull *rrn_find_series_full (char * series_id);
+
+RrnListEntry *rrn_full_add_field (RrnListEntry *current, char *text, char *lang);
+
+void rrn_reg_free_full (RrnRegFull *reg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__RARIAN_REG_FULL_H */
diff --git a/librarian/rarian-reg-utils.c b/librarian/rarian-reg-utils.c
new file mode 100644
index 0000000..aec298f
--- /dev/null
+++ b/librarian/rarian-reg-utils.c
@@ -0,0 +1,835 @@
+/*
+ * rarian-reg-utils.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "rarian-reg-utils.h"
+#include "rarian-language.h"
+#include "rarian-utils.h"
+
+
+static void process_line (char *line, RrnReg *reg);
+static void process_pair (RrnReg *reg, char *key, char *value);
+static void process_sect_line (char *line, RrnSect *sect);
+static void process_sect_pair (RrnSect *sect, char *key, char *value);
+static int rrn_reg_add_sect (RrnReg *reg, RrnSect *sect);
+static void process_path (RrnReg *reg);
+static void process_section_path (char *owner_path, RrnSect *section);
+
+
+RrnReg *
+rrn_reg_new ()
+{
+ RrnReg *reg;
+
+ reg = malloc (sizeof (RrnReg));
+ reg->name = NULL;
+ reg->uri = NULL;
+ reg->comment = NULL;
+ reg->identifier = NULL;
+ reg->type = NULL;
+ reg->icon = NULL;
+ reg->categories = NULL;
+ reg->weight = 0;
+ reg->heritage = NULL;
+ reg->omf_location = NULL;
+ reg->lang = NULL;
+ reg->ghelp_name = NULL;
+ reg->default_section = NULL;
+ reg->hidden = FALSE;
+ reg->children = NULL;
+
+ return reg;
+}
+
+RrnReg *
+rrn_reg_parse_file (char *filename)
+{
+ RrnReg *reg = NULL;
+ RrnSect *sect = NULL;
+ RrnSect *orphaned_sections = NULL;
+ int mode = 0;
+ FILE *file;
+ char *buf;
+
+ if (access(filename, R_OK)) {
+ fprintf (stderr, "WARNING: cannot access file %s\n", filename);
+ return NULL;
+ }
+ reg = rrn_reg_new ();
+
+ /* First, figure out it's ghelp name */
+ {
+ char *dot = strrchr (filename, '.');
+ char *sep = strrchr (filename, '/');
+ if (!dot || !sep) {
+ fprintf (stderr, "Error parsing file %s for ghelp name. Ignoring\n", filename);
+ } else {
+ sep++;
+ reg->ghelp_name = rrn_strndup (sep, dot-sep);
+ }
+ }
+
+ file = fopen (filename, "r");
+
+ buf = malloc (sizeof (char) * 1024);
+ while (fgets (buf, 1023, file)) {
+ char *real = NULL;
+ while (buf[strlen(buf)-1] != '\n') {
+ char *tmp;
+ char *result = NULL;
+ tmp = strdup (buf);
+ if (fgets (buf, 1023, file)) {
+ result = malloc (sizeof (char) * (strlen(tmp)+strlen(buf)+2));
+ strcpy (result, tmp);
+ strcat (result, buf);
+ free (tmp);
+ free (buf);
+ buf = result;
+ } else {
+ free (buf);
+ buf = tmp;
+ break;
+ }
+ }
+ real = buf;
+ while (*real && isspace(*real) && *real != '\n') {
+ real++;
+ }
+ if (!real || real[0] == '\n' || real[0] == '#') {
+ /* Black Line or comment. Ignore. */
+ } else if (real[0] == '[') {
+ if (!strncmp (real, "[Document]", 10)) {
+ mode = 0;
+
+ if (sect) {
+ if (rrn_reg_add_sect (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ sect = NULL;
+ }
+ } else if (!strncmp (real, "[Section]", 9)) {
+ mode = 1;
+ if (sect) {
+ if (rrn_reg_add_sect (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ sect = NULL;
+ }
+ sect = rrn_sect_new ();
+ } else {
+ fprintf (stderr, "Unknown section header: %s. Ignoring\n", real);
+ }
+ } else if (strchr ( real, '=')) {
+ if (mode == 0) {
+ process_line (buf, reg);
+ } else {
+ process_sect_line (buf, sect);
+ }
+ } else {
+ fprintf (stdout, "WARNING: Don't know how to handle line: %s\n", buf);
+ }
+ }
+ fclose (file);
+ free (buf);
+ if (sect) {
+ if (rrn_reg_add_sect (reg, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ if (!reg->name || !reg->uri || !reg->type || !reg->categories ) {
+ rrn_reg_free (reg);
+ reg = NULL;
+ }
+ sect = orphaned_sections;
+ while (sect) {
+ if (rrn_reg_add_sect (reg, sect) == 1) {
+ fprintf (stderr, "Error: Orphaned section %s not added.\n",
+ sect->name);
+ }
+ sect = sect->next;
+ }
+
+ if (reg && !reg->identifier) {
+ char *last;
+ char *sep;
+ char *basename;
+
+ sep = strrchr (filename, '/');
+ last = strrchr (filename, '.');
+ if (!last || !sep || last < sep) {
+ fprintf (stderr, "Error: Can't cut put basename properly\n");
+ rrn_reg_free (reg);
+ return NULL;
+ }
+ basename = rrn_strndup (sep + 1, last - (sep + 1));
+ reg->identifier = malloc (sizeof (char)*(strlen(basename)+11));
+ sprintf (reg->identifier, "org.other.%s", basename);
+ free (basename);
+ printf ("identifier is %s\n", reg->identifier);
+
+ }
+ if (reg)
+ process_path (reg);
+
+ if (reg && reg->omf_location) {
+ /* Replace -* with something more sensible */
+ char *star_loc;
+ char *tmp;
+ char *tmp2;
+
+ star_loc = strrchr (reg->omf_location, '*');
+
+ /*tmp = malloc (sizeof(char) * (strlen(reg->omf_location) -
+ strlen(star_loc)));*/
+ tmp = rrn_strndup (reg->omf_location, (star_loc - reg->omf_location));
+ star_loc++;
+ if (reg->lang) {
+ tmp2 = malloc (sizeof(char) * (strlen(tmp) +
+ strlen(star_loc) +
+ strlen (reg->lang))+1);
+ sprintf (tmp2, "%s%s%s", tmp, reg->lang, star_loc);
+ } else {
+ tmp2 = malloc (sizeof(char) * (strlen(tmp) +
+ strlen(star_loc)));
+ sprintf (tmp2, "%sC%s", tmp, star_loc);
+ }
+ free (reg->omf_location);
+ reg->omf_location = strdup (tmp2);
+ free (tmp);
+ free (tmp2);
+ }
+ return reg;
+}
+
+static void
+process_line (char *line, RrnReg *reg)
+{
+ char *ret = NULL;
+ char *key;
+ char *value;
+ char *tmp;
+
+ tmp = strchr (line, '=');
+ if (!tmp) {
+ fprintf (stderr, "WARNING: Malformed line: \n%s\n", line);
+ return;
+ }
+
+ if (line[strlen(line)-1] == '\n') {
+ line[strlen(line)-1] = '\0';
+ }
+
+ key = rrn_strndup (line, tmp - line);
+ tmp++;
+ value = strdup (tmp);
+
+ rrn_strip(key);
+ rrn_strip(value);
+
+ process_pair (reg, key, value);
+ free (key);
+ free (value);
+
+ return;
+}
+
+static void
+process_field (char **current, char **lang, char *key, char *value)
+{
+ char *lbrace = NULL, *rbrace = NULL, *l = NULL;
+ lbrace = strchr (key, '[');
+ lbrace++;
+ rbrace = strchr (key, ']');
+ if ((!lbrace || !rbrace)) {
+ if (!*current) {
+ *current = strdup (value);
+ if (lang) {
+ if (*lang)
+ free (*lang);
+ *lang = strdup ("C");
+ }
+ }
+ return;
+ }
+ l = rrn_strndup (lbrace, rbrace - lbrace);
+ if (rrn_language_use ( (lang ? *lang : NULL), l) == 1) {
+ if (*current) {
+ free (*current);
+ }
+ if (lang && *lang) {
+ free (*lang);
+ }
+
+ *current = strdup (value);
+ if (lang) {
+ *lang = strdup (l);
+ }
+
+ }
+ free (l);
+}
+
+static char **
+process_categories (char *cat_string)
+{
+ char **result = NULL;
+ char **tmp = NULL;
+ int ncats = 0;
+ char *current_break = cat_string;
+ char *semi;
+ int i;
+ do {
+ semi = strchr (current_break, ';');
+ if (result) {
+ tmp = malloc (sizeof (char *)*ncats);
+ for (i=0; i< ncats; i++) {
+ tmp[i] = strdup (result[i]);
+ free (result[i]);
+ }
+ free (result);
+ }
+ ncats += 1;
+ result = malloc (sizeof (char *)*(ncats+1));
+ if (tmp) {
+ for (i=0; i<ncats-1; i++) {
+ result[i] = strdup (tmp[i]);
+ free (tmp[i]);
+ }
+ free (tmp);
+ }
+ if (semi)
+ result[ncats-1] = rrn_strndup (current_break, semi - current_break);
+ else
+ result[ncats-1] = strdup (current_break);
+ result[ncats] = NULL;
+ current_break = semi+1;
+ } while (semi);
+
+ return result;
+}
+
+static void
+process_pair (RrnReg *reg, char *key, char *value)
+{
+ if (!strncmp (key, "Name", 4)) {
+ process_field (&(reg->name), &(reg->lang), key, value);
+ } else if (!strncmp (key, "Comment", 7)) {
+ process_field (&(reg->comment), &(reg->lang), key, value);
+ } else if (!strncmp (key, "DocPath", 7)) {
+ process_field (&(reg->uri), &(reg->lang), key, value);
+ } else if (!strcmp (key, "DocIdentifier")) {
+ reg->identifier = strdup (value);
+ } else if (!strcmp (key, "DocType")) {
+ reg->type = strdup (value);
+ } else if (!strcmp (key, "Categories")) {
+ reg->categories = process_categories (value);
+ } else if (!strcmp (key, "DocWeight")) {
+ reg->weight = atoi (value);
+ } else if (!strcmp (key, "x-DocHeritage")) {
+ reg->heritage = strdup (value);
+ } else if (!strcmp (key, "x-Scrollkeeper-omf-loc")) {
+ reg->omf_location = strdup(value);
+ } else if (!strcmp (key, "DocLang")) {
+ if (!reg->lang) {
+ reg->lang = strdup (value);
+ }
+ } else if (!strcmp (key, "NoDisplay")) {
+ if (!strcmp (key, "true"))
+ reg->hidden = TRUE;
+ } else if (!strcmp (key, "DocDefaultSection")) {
+ reg->default_section = strdup (value);
+ } else if (!strcmp (key, "Icon")) {
+ reg->icon = strdup (value);
+ } else {
+ fprintf (stderr, "WARNING: Unknown element %s: %s\n", key, value);
+ }
+ return;
+}
+
+void
+rrn_reg_free (RrnReg *reg)
+{
+ RrnSect *sect = reg->children;
+ char **tmp = reg->categories;
+ free (reg->name);
+ free (reg->comment);
+ free (reg->uri);
+ free (reg->type);
+ free (reg->identifier);
+ free (reg->heritage);
+ free (reg->omf_location);
+ free (reg->lang);
+ if (reg->default_section)
+ free (reg->default_section);
+ if (reg->ghelp_name)
+ free (reg->ghelp_name);
+ if (tmp) {
+ while (*tmp) {
+ free (*tmp);
+ tmp++;
+ }
+ }
+ free (reg->categories);
+ while (sect) {
+ RrnSect *s1 = sect->next;
+ rrn_sect_free (sect);
+ sect = s1;
+ }
+ free (reg);
+ return;
+}
+
+/* Section stuff */
+RrnSect *
+rrn_sect_new ()
+{
+ RrnSect * sect;
+ sect = malloc (sizeof (RrnSect));
+
+ sect->name = NULL;
+ sect->identifier = NULL;
+ sect->uri = NULL;
+ sect->next = NULL;
+ sect->prev = NULL;
+ sect->children = NULL;
+ sect->owner = NULL;
+ sect->priority = 0;
+}
+
+RrnSect *
+find_sect (RrnSect *start, char *id)
+{
+ RrnSect *ret = start;
+
+ while (ret) {
+ if (!strcmp (ret->identifier, id)) {
+ return ret;
+ }
+ ret = ret->next;
+ }
+ return NULL;
+}
+
+RrnSect *
+rrn_reg_add_sections (RrnReg *reg, RrnSect *sects)
+{
+ RrnSect *real_orphans = NULL;
+ RrnSect *next = NULL;
+ int depth = 0;
+ do {
+ depth ++;
+ if (depth > 4) {
+ /* The pathological case where someone's done something really,
+ * stupid and defined a subsection with the section without
+ * definind the section.
+ * We break after 4 iterations.
+ */
+ return sects;
+ }
+ next = sects;
+ while (sects) {
+ next = sects->next;
+ if (rrn_reg_add_sect (reg, sects) == 1) {
+ sects->prev = NULL;
+ sects->next = real_orphans;
+ if (real_orphans)
+ real_orphans->prev = sects;
+ real_orphans = sects;
+ };
+ sects = next;
+ }
+ sects = real_orphans;
+ } while (sects);
+ return sects;
+}
+
+int
+rrn_sects_add_sect (RrnSect *current, RrnSect *sect)
+{
+ char *cur_sect = NULL;
+ RrnSect *append_sect;
+ char *tmp = NULL;
+ char *dot = NULL;
+
+ cur_sect = sect->owner;
+
+ append_sect = current;
+ do {
+ dot = strchr (cur_sect, '.');
+ tmp = rrn_strndup (cur_sect, dot-cur_sect);
+ append_sect = find_sect (append_sect, tmp);
+ cur_sect = dot;
+ free (tmp);
+ } while (cur_sect && append_sect);
+ if (append_sect) {
+ RrnSect *iter = append_sect->children;
+ while (iter) {
+ if (!strcmp (iter->identifier, sect->identifier)) {
+ sect->prev = iter->prev;
+ sect->next = iter->next;
+ if (iter->prev) {
+ iter->prev->next = sect;
+ }
+ if (iter->next) {
+ iter->next->prev = sect;
+ }
+ return 0;
+ }
+ iter = iter->next;
+ }
+ sect->prev = NULL;
+ sect->next = append_sect->children;
+ if (append_sect->children)
+ append_sect->children->prev = sect;
+ append_sect->children = sect;
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+int
+rrn_reg_add_sect (RrnReg *reg, RrnSect *sect)
+{
+ if (!sect->owner || !strcmp (reg->identifier, sect->owner)) {
+ RrnSect *iter = reg->children;
+ while (iter) {
+ if (!strcmp (iter->identifier, sect->identifier)) {
+ if (iter->priority < sect->priority) {
+ process_section_path (reg->uri, sect);
+ sect->prev = iter->prev;
+ sect->next = iter->next;
+ if (iter->prev) {
+ iter->prev->next = sect;
+ }
+ if (iter->next && iter->next->prev == iter) {
+ iter->next->prev = sect;
+ }
+ if (reg->children == iter) {
+ reg->children = sect;
+ }
+ }
+ return 0;
+ }
+ iter = iter->next;
+ }
+ process_section_path (reg->uri, sect);
+ sect->prev = NULL;
+ sect->next = reg->children;
+ if (reg->children)
+ reg->children->prev = sect;
+ reg->children = sect;
+ } else {
+ char *cur_sect = NULL;
+ RrnSect *append_sect;
+ char *tmp = NULL;
+ char *dot = NULL;
+
+ if (!strncmp (sect->owner, reg->identifier, strlen (reg->identifier))) {
+ cur_sect = &sect->owner[strlen(reg->identifier)+1];
+ } else {
+ cur_sect = sect->owner;
+ }
+ append_sect = reg->children;
+ do {
+ dot = strchr (cur_sect, '.');
+ tmp = rrn_strndup (cur_sect, dot-cur_sect);
+ append_sect = find_sect (append_sect, tmp);
+ cur_sect = dot;
+ free (tmp);
+ } while (cur_sect && append_sect);
+ if (append_sect) {
+ RrnSect *iter = append_sect->children;
+ while (iter) {
+ if (!strcmp (iter->identifier, sect->identifier)) {
+ rrn_sect_free (sect);
+ return 2;
+ }
+ iter = iter->next;
+ }
+ process_section_path (append_sect->uri, sect);
+ sect->prev = NULL;
+ sect->next = append_sect->children;
+ if (append_sect->children)
+ append_sect->children->prev = sect;
+ append_sect->children = sect;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+RrnSect *
+rrn_sect_parse_file (char *filename)
+{
+ RrnSect *sect = NULL;
+ RrnSect *orphaned_sections = NULL;
+ FILE *file;
+ char *buf;
+ char *real_owner = NULL;
+
+ if (access(filename, R_OK)) {
+ fprintf (stderr, "WARNING: cannot access file %s\n", filename);
+ return NULL;
+ }
+
+ file = fopen (filename, "r");
+
+ buf = malloc (sizeof (char) * 1024);
+ while (fgets (buf, 1023, file)) {
+ char *real = NULL;
+ while (buf[strlen(buf)-1] != '\n') {
+ char *tmp;
+ char *result = NULL;
+ tmp = strdup (buf);
+ buf = fgets (buf, 1023, file);
+ result = malloc (sizeof (char) * (strlen(tmp)+strlen(buf)+2));
+ strcpy (result, tmp);
+ strcat (result, buf);
+ free (tmp);
+ free (buf);
+ buf = result;
+ }
+ real = buf;
+ while (*real && isspace(*real) && *real != '\n') {
+ real++;
+ }
+ if (!real || real[0] == '\n' || real[0] == '#') {
+ /* Black Line or comment. Ignore. */
+ } else if (real[0] == '[') {
+ if (!strncmp (real, "[Section]", 9)) {
+ if (sect) {
+ if (rrn_sects_add_sect (orphaned_sections, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ sect = rrn_sect_new ();
+ sect->priority = 1;
+ } else {
+ fprintf (stderr, "Unknown section header: !%s!. Ignoring\n", real);
+ }
+ } else if (strchr ( real, '=')) {
+ process_sect_line (buf, sect);
+ } else {
+ fprintf (stderr, "WARNING: Don't know how to handle line: %s\n", buf);
+ }
+ }
+ fclose (file);
+ free (buf);
+
+ if (sect) {
+ if (rrn_sects_add_sect (orphaned_sections, sect) == 1) {
+ sect->prev = NULL;
+ sect->next = orphaned_sections;
+ if (orphaned_sections)
+ orphaned_sections->prev = sect;
+ orphaned_sections = sect;
+ }
+ }
+
+ return orphaned_sections;
+}
+
+static void
+process_sect_line (char *line, RrnSect *sect)
+{
+ char *ret = NULL;
+ char *key;
+ char *value;
+ char *tmp;
+
+ tmp = strchr (line, '=');
+ if (!tmp) {
+ fprintf (stderr, "WARNING: Malformed line: \n%s\n", line);
+ return;
+ }
+
+ if (line[strlen(line)-1] == '\n') {
+ line[strlen(line)-1] = '\0';
+ }
+
+ key = rrn_strndup (line, tmp - line);
+ tmp++;
+ value = strdup (tmp);
+ process_sect_pair (sect, key, value);
+ free (key);
+ free (value);
+
+ return;
+
+}
+
+static void
+process_sect_pair (RrnSect *sect, char *key, char *value)
+{
+ if (!strncmp (key, "SectionName", 11) || !strncmp (key, "sectionname", 11)) {
+ process_field (&(sect->name), NULL, key, value);
+ } else if (!strcmp (key, "SectionIdentifier") || !strcmp (key, "sectionidentifier")) {
+ sect->identifier = strdup (value);
+ } else if (!strncmp (key, "SectionPath", 11) || !strncmp (key, "sectionpath", 11)) {
+ process_field (&(sect->uri), NULL, key, value);
+ } else if (!strcmp (key, "SectionDocument") || !strcmp (key, "sectiondocument")) {
+ sect->owner = strdup (value);
+ } else {
+ fprintf (stderr, "WARNING: Unknown element for section %s: %s\n", key, value);
+ }
+ return;
+}
+
+static void
+process_path (RrnReg *reg)
+{
+ char *prefix = NULL;
+ RrnSect *child = reg->children;
+ if (!strncmp ("file://", reg->uri, 7)) {
+ /* No processing needs done. The URI is already in the file: scheme */
+ return;
+ }
+ if (!strncmp ("file:", reg->uri, 5)) {
+ /* We got the wrong number of slashes. Fix here. */
+ char *new_prefix = &(reg->uri[5]);
+ char *result;
+ while (*new_prefix && *new_prefix == '/') {
+ new_prefix++;
+ }
+ new_prefix--;
+ result = malloc (sizeof(char) * (strlen(reg->uri)+7));
+ sprintf(result, "file://%s", new_prefix);
+ free (reg->uri);
+ reg->uri = result;
+ return;
+ }
+
+ if ((prefix = strchr (reg->uri, ':')) &&
+ (prefix - reg->uri) < 7) {
+ /* Probably has another (non-file:) URI scheme. If so, we're going to
+ * return as is
+ */
+ return;
+ }
+ /* Otherwise, promote to file: URI scheme, reusing the prefix vble */
+ prefix = malloc (sizeof (char) * (strlen(reg->uri)+8));
+ sprintf (prefix, "file://%s", reg->uri);
+ free (reg->uri);
+ reg->uri = prefix;
+ while (child) {
+ process_section_path (reg->uri, child);
+ child = child->next;
+ }
+
+}
+
+static void
+process_section_path (char *owner_path, RrnSect *section)
+{
+ char *tmp = NULL;
+ char *new_uri = NULL;
+ char *prefix = NULL;
+ char *filename = NULL;
+
+ RrnSect *child = section->children;
+
+ if (!strncmp ("file:", section->uri, 5))
+ goto done;
+ if ((prefix = strchr (section->uri, ':')) &&
+ prefix-(section->uri) < 7) {
+ /* Probably has another (non-file:) URI scheme. If so, we're going to
+ * return as is
+ */
+ goto done;
+ }
+ if (section->uri[0] == '/') {
+ /* Absolute path */
+ new_uri = malloc (sizeof (char) * strlen(section->uri)+6);
+ sprintf (new_uri, "file:/%s", section->uri);
+ free (section->uri);
+ section->uri = new_uri;
+ goto done;
+ }
+
+ /* If we get through to here, the path is relative to the parents
+ * own path. We need to disect and repair
+ */
+
+ /* First, cut out the owner's file */
+ tmp = strrchr (owner_path, '/');
+ prefix = rrn_strndup (owner_path, tmp-owner_path);
+ if (!tmp) {
+ fprintf (stderr, "Warning: cannot cut up path for the %s section\n"
+ "This generally indicates a problem with the scroll\n"
+ " file for this section, or its parent document.\n"
+ "The path will not be fixed.\n", section->uri);
+ return;
+ }
+ new_uri = malloc (sizeof (char) * (strlen(prefix)+strlen(section->uri)+2));
+ sprintf (new_uri, "%s/%s", prefix, section->uri);
+ free (section->uri);
+ section->uri = new_uri;
+
+done:
+ /* In all cases, we want to iterate through the children of the children
+ * just to make sure they're all right
+ */
+ while (child) {
+ process_section_path (section->uri, child);
+ child = child->next;
+ }
+}
+
+void
+rrn_sect_free (RrnSect *sect)
+{
+ RrnSect *child = sect->children;
+ free (sect->name);
+ free (sect->identifier);
+ free (sect->uri);
+ free (sect->owner);
+ while (child) {
+ RrnSect *c1 = child->next;
+ rrn_sect_free (child);
+ child = c1;
+ }
+ free (sect);
+}
diff --git a/librarian/rarian-reg-utils.h b/librarian/rarian-reg-utils.h
new file mode 100644
index 0000000..ffc3caa
--- /dev/null
+++ b/librarian/rarian-reg-utils.h
@@ -0,0 +1,86 @@
+/*
+ * rarian-reg-utils.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __RARIAN_REG_UTILS_H
+#define __RARIAN_REG_UTILS_H
+
+#ifndef I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#error Rarian is unstable. To use it, you must acknowledge that
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _RrnReg RrnReg;
+typedef struct _RrnSect RrnSect;
+
+struct _RrnReg
+{
+ char *name;
+ char *uri;
+ char *comment;
+ char *identifier;
+ char *type;
+ char *icon;
+ char **categories;
+ int weight;
+ char *heritage;
+ char *omf_location;
+ char *ghelp_name;
+ char *lang;
+ char *default_section;
+ int hidden;
+ RrnSect *children;
+};
+
+struct _RrnSect
+{
+ char *name;
+ char *identifier;
+ char *uri;
+ char *owner;
+ RrnSect *next;
+ RrnSect *prev;
+ RrnSect *children;
+
+ /* Used internally to determine whether to overwrite
+ * the section
+ */
+ int priority;
+};
+
+RrnReg * rrn_reg_new ();
+RrnSect * rrn_sect_new ();
+
+RrnReg * rrn_reg_parse_file (char *filename);
+RrnSect * rrn_sect_parse_file (char *filename);
+
+RrnSect * rrn_reg_add_sections (RrnReg *reg, RrnSect *sects);
+
+void rrn_reg_free (RrnReg *reg);
+void rrn_sect_free (RrnSect *sect);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__RARIAN_REG_UTILS_H */
diff --git a/librarian/rarian-utils.c b/librarian/rarian-utils.c
new file mode 100644
index 0000000..b17abd7
--- /dev/null
+++ b/librarian/rarian-utils.c
@@ -0,0 +1,75 @@
+/*
+ * rarian-utils.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif /* HAS_MALLOC_H */
+#include "rarian-utils.h"
+
+char*
+rrn_chug (char *string)
+{
+ char *start;
+
+ for (start = (char*) string; *start && isspace (*start); start++)
+ ;
+
+ memmove (string, start, strlen ((char *) start) + 1);
+
+ return string;
+}
+
+char*
+rrn_chomp (char *string)
+{
+ int len;
+
+ len = strlen (string);
+
+ while (len--) {
+ if (isspace ((char) string[len]))
+ string[len] = '\0';
+ else
+ break;
+ }
+
+ return string;
+}
+
+char *
+rrn_strndup (char *string, int len)
+{
+ char *new_str = NULL;
+
+ if (string) {
+ new_str = (char *) calloc (sizeof(char), len + 1);
+ strncpy (new_str, string, len);
+ new_str[len] = '\0';
+ } else
+ new_str = NULL;
+
+ return new_str;
+}
diff --git a/librarian/rarian-utils.h b/librarian/rarian-utils.h
new file mode 100644
index 0000000..738f2ef
--- /dev/null
+++ b/librarian/rarian-utils.h
@@ -0,0 +1,56 @@
+/*
+ * rarian-utils.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __RARIAN_UTILS_H
+#define __RARIAN_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+ /* A collection of useful functions that have no real place
+ * anywhere else
+ */
+
+ /* The string functions are shamelessly cribbed from glib,
+ * changing their names to fit into rarian */
+
+/* removes leading spaces */
+char* rrn_chug (char *string);
+/* removes trailing spaces */
+char* rrn_chomp (char *string);
+
+ char * rrn_strndup (char *string, int len);
+
+
+#define rrn_strip( string ) rrn_chomp (rrn_chug (string))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__RRN_UTILS_H */
diff --git a/librarian/rarian.h b/librarian/rarian.h
new file mode 100644
index 0000000..de42c8f
--- /dev/null
+++ b/librarian/rarian.h
@@ -0,0 +1,45 @@
+/*
+ * rarian.h
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This file is the main header for the rarian library.
+ * If you include this file, you should get everything you
+ * need to work with rarian.
+ */
+
+#ifndef __RARIAN_H
+#define __RARIAN_H
+
+#ifndef I_KNOW_RARIAN_0_8_IS_UNSTABLE
+#error Rarian is unstable. To use it, you must acknowledge that
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#include <rarian-reg-utils.h>
+#include <rarian-main.h>
+#include <rarian-man.h>
+#include <rarian-info.h>
+
+
+#endif /*__RARIAN_H */