diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2008-09-01 18:44:56 +0000 |
---|---|---|
committer | <> | 2013-07-02 12:44:56 +0000 |
commit | bd4e1730fe4d7878c4e5e2c13ea489f59e7e0f27 (patch) | |
tree | 5e605cc37a7e484e7008c7934f61e2cd25a0d57b /librarian | |
download | rarian-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.am | 33 | ||||
-rw-r--r-- | librarian/Makefile.in | 641 | ||||
-rw-r--r-- | librarian/rarian-info.c | 699 | ||||
-rw-r--r-- | librarian/rarian-info.h | 74 | ||||
-rw-r--r-- | librarian/rarian-language.c | 267 | ||||
-rw-r--r-- | librarian/rarian-language.h | 44 | ||||
-rw-r--r-- | librarian/rarian-main.c | 630 | ||||
-rw-r--r-- | librarian/rarian-main.h | 60 | ||||
-rw-r--r-- | librarian/rarian-man.c | 617 | ||||
-rw-r--r-- | librarian/rarian-man.h | 59 | ||||
-rw-r--r-- | librarian/rarian-omf.cpp | 673 | ||||
-rw-r--r-- | librarian/rarian-omf.h | 42 | ||||
-rw-r--r-- | librarian/rarian-reg-full.c | 760 | ||||
-rw-r--r-- | librarian/rarian-reg-full.h | 86 | ||||
-rw-r--r-- | librarian/rarian-reg-utils.c | 835 | ||||
-rw-r--r-- | librarian/rarian-reg-utils.h | 86 | ||||
-rw-r--r-- | librarian/rarian-utils.c | 75 | ||||
-rw-r--r-- | librarian/rarian-utils.h | 56 | ||||
-rw-r--r-- | librarian/rarian.h | 45 |
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 = §->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 = §->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 */ |