From f86bd5cf58604958002942d9fd5adfe0fa90aa14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonathan=20Sch=C3=B6bel?= <jonathan@xn--schbel-yxa.info>
Date: Mon, 17 Oct 2022 15:00:09 +0200
Subject: [PATCH] setup library (make & API)

The make process was restructured to create a library. For this libtool
is used to provide both static and dynamic linking. Also header
inclusion guards were introduced, to prevent clients of the library to
include some single file without including others. The types were
exported with forward declarations for better abstraction. When
compiling the library, the macro LIB_SEFHT_COMPILATION is defined and
symbol declarations are exported fully. For compiling the tests this
macro is also defined, as the tests not only tests the API, but also the
internal state, because a lot of errors couldn't be detected otherwise.
---
 configure.ac                        |   4 +
 sefht.geany                         |  55 ++++++-------
 src/Makefile.am                     |  21 ++---
 src/lib/Makefile.am                 |  32 ++++++++
 src/{ => lib/sefht}/cms.c           |   0
 src/{ => lib/sefht}/cms.h           |  29 +++++--
 src/{ => lib/sefht}/data.c          |   0
 src/{ => lib/sefht}/data.h          |  29 +++++--
 src/{ => lib/sefht}/error.h         |  10 ++-
 src/{ => lib/sefht}/fragment.c      |   0
 src/{ => lib/sefht}/fragment.h      |  43 ++++++----
 src/{ => lib/sefht}/log.h           |  10 ++-
 src/{ => lib/sefht}/macro.h         |  10 ++-
 src/{ => lib/sefht}/node_fragment.c |   0
 src/lib/sefht/node_fragment.h       | 117 ++++++++++++++++++++++++++++
 src/{ => lib/sefht}/sefht.h         |  21 ++++-
 src/{ => lib/sefht}/text.c          |   0
 src/{ => lib/sefht}/text.h          |  17 +++-
 src/{ => lib/sefht}/validator.c     |   0
 src/{ => lib/sefht}/validator.h     |  41 +++++++---
 src/main.c                          |  19 ++---
 src/node_fragment.h                 | 103 ------------------------
 tests/Makefile.am                   |  25 +++---
 23 files changed, 363 insertions(+), 223 deletions(-)
 create mode 100644 src/lib/Makefile.am
 rename src/{ => lib/sefht}/cms.c (100%)
 rename src/{ => lib/sefht}/cms.h (63%)
 rename src/{ => lib/sefht}/data.c (100%)
 rename src/{ => lib/sefht}/data.h (69%)
 rename src/{ => lib/sefht}/error.h (82%)
 rename src/{ => lib/sefht}/fragment.c (100%)
 rename src/{ => lib/sefht}/fragment.h (73%)
 rename src/{ => lib/sefht}/log.h (84%)
 rename src/{ => lib/sefht}/macro.h (81%)
 rename src/{ => lib/sefht}/node_fragment.c (100%)
 create mode 100644 src/lib/sefht/node_fragment.h
 rename src/{ => lib/sefht}/sefht.h (72%)
 rename src/{ => lib/sefht}/text.c (100%)
 rename src/{ => lib/sefht}/text.h (90%)
 rename src/{ => lib/sefht}/validator.c (100%)
 rename src/{ => lib/sefht}/validator.h (59%)
 delete mode 100644 src/node_fragment.h

diff --git a/configure.ac b/configure.ac
index a9bd36d..e430e8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,10 +12,13 @@ AM_INIT_AUTOMAKE([foreign -Wall -Werror subdir-objects])
 
 # Checks for programs.
 AC_PROG_CC
+AM_PROG_AR
+AC_PROG_LIBTOOL
 
 PKG_CHECK_MODULES([CHECK], [check >= 0.9.4])
 
 # Checks for libraries.
+LT_INIT()
 
 # Checks for header files.
 AC_CHECK_HEADER([errno.h])
@@ -33,6 +36,7 @@ AC_CHECK_HEADER([string.h])
 # Makefiles
 AC_CONFIG_FILES([Makefile
 		 src/Makefile
+		 src/lib/Makefile
 		 tests/Makefile])
 
 AC_OUTPUT
diff --git a/sefht.geany b/sefht.geany
index f9ef171..6f23630 100644
--- a/sefht.geany
+++ b/sefht.geany
@@ -28,33 +28,34 @@ long_line_behaviour=1
 long_line_column=72
 
 [files]
-current_page=2
-FILE_NAME_0=607;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8
-FILE_NAME_1=384;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8
-FILE_NAME_2=811;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8
-FILE_NAME_3=1280;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fcms.c;0;8
-FILE_NAME_4=1148;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fcms.h;0;8
-FILE_NAME_5=4036;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fdata.c;0;8
-FILE_NAME_6=1099;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fdata.h;0;8
-FILE_NAME_7=1500;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ffragment.c;0;8
-FILE_NAME_8=1058;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ffragment.h;0;8
-FILE_NAME_9=1420;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fnode_fragment.c;0;8
-FILE_NAME_10=1574;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fnode_fragment.h;0;8
-FILE_NAME_11=25433;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.c;0;8
-FILE_NAME_12=3011;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ftext.h;0;8
-FILE_NAME_13=1351;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fvalidator.c;0;8
-FILE_NAME_14=1130;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fvalidator.h;0;8
-FILE_NAME_15=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Ferror.h;0;4
-FILE_NAME_16=881;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flog.h;0;4
-FILE_NAME_17=938;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmacro.h;0;8
-FILE_NAME_18=847;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fsefht.h;0;8
-FILE_NAME_19=1089;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8
-FILE_NAME_20=1113;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8
-FILE_NAME_21=3059;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8
-FILE_NAME_22=8535;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8
-FILE_NAME_23=11889;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8
-FILE_NAME_24=960;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8
-FILE_NAME_25=55;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8
+current_page=20
+FILE_NAME_0=923;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8
+FILE_NAME_1=73;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8
+FILE_NAME_2=943;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8
+FILE_NAME_3=1138;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2FMakefile.am;0;8
+FILE_NAME_4=1280;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.c;0;8
+FILE_NAME_5=1021;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.h;0;8
+FILE_NAME_6=4036;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.c;0;8
+FILE_NAME_7=1645;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.h;0;8
+FILE_NAME_8=1500;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.c;0;8
+FILE_NAME_9=2729;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.h;0;8
+FILE_NAME_10=1420;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.c;0;8
+FILE_NAME_11=1461;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.h;0;8
+FILE_NAME_12=25433;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.c;0;8
+FILE_NAME_13=3332;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.h;0;8
+FILE_NAME_14=1351;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8
+FILE_NAME_15=1818;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8
+FILE_NAME_16=987;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ferror.h;0;8
+FILE_NAME_17=1259;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4
+FILE_NAME_18=1077;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8
+FILE_NAME_19=1063;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fsefht.h;0;8
+FILE_NAME_20=1329;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8
+FILE_NAME_21=1113;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8
+FILE_NAME_22=3059;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8
+FILE_NAME_23=13535;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8
+FILE_NAME_24=11889;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8
+FILE_NAME_25=960;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8
+FILE_NAME_26=55;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8
 
 [VTE]
 last_dir=/home/jonathan/Dokumente/projekte/prgm/internet/web/SeFHT/tests
diff --git a/src/Makefile.am b/src/Makefile.am
index f720509..211dd58 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,20 +1,13 @@
 ## Process this file with automake to produce Makefile.in
 
+SUBDIRS = lib
+
 AM_CFLAGS = -Wall -Wextra
 
-bin_PROGRAMS = sefht.fcgi
+bin_PROGRAMS = sefht_demo
 
-sefht_fcgi_SOURCES =
-sefht_fcgi_SOURCES += main.c
-sefht_fcgi_SOURCES += macro.h
-sefht_fcgi_SOURCES += sefht.h
-sefht_fcgi_SOURCES += error.h
-sefht_fcgi_SOURCES += log.h
-sefht_fcgi_SOURCES += cms.c cms.h
-sefht_fcgi_SOURCES += data.c data.h
-sefht_fcgi_SOURCES += fragment.c fragment.h
-sefht_fcgi_SOURCES += node_fragment.c node_fragment.h
-sefht_fcgi_SOURCES += text.c text.h
-sefht_fcgi_SOURCES += validator.c validator.h
+sefht_demo_SOURCES =
+sefht_demo_SOURCES += main.c
 
-sefht_fcgi_LDADD = -lm
+sefht_demo_CPPFLAGS = -I$(srcdir)/lib
+sefht_demo_LDADD = -lm lib/libsefht.la
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644
index 0000000..84f2a2c
--- /dev/null
+++ b/src/lib/Makefile.am
@@ -0,0 +1,32 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CFLAGS = -Wall -Wextra
+
+lib_LTLIBRARIES = libsefht.la
+
+libsefht_la_SOURCES =
+libsefht_la_SOURCES += sefht/macro.h
+libsefht_la_SOURCES += sefht/sefht.h
+libsefht_la_SOURCES += sefht/error.h
+libsefht_la_SOURCES += sefht/log.h
+libsefht_la_SOURCES += sefht/cms.c sefht/cms.h
+libsefht_la_SOURCES += sefht/data.c sefht/data.h
+libsefht_la_SOURCES += sefht/fragment.c sefht/fragment.h
+libsefht_la_SOURCES += sefht/node_fragment.c sefht/node_fragment.h
+libsefht_la_SOURCES += sefht/text.c sefht/text.h
+libsefht_la_SOURCES += sefht/validator.c sefht/validator.h
+
+nobase_include_HEADERS =
+nobase_include_HEADERS += sefht/macro.h
+nobase_include_HEADERS += sefht/sefht.h
+nobase_include_HEADERS += sefht/error.h
+nobase_include_HEADERS += sefht/log.h
+nobase_include_HEADERS += sefht/cms.h
+nobase_include_HEADERS += sefht/data.h
+nobase_include_HEADERS += sefht/fragment.h
+nobase_include_HEADERS += sefht/node_fragment.h
+nobase_include_HEADERS += sefht/text.h
+nobase_include_HEADERS += sefht/validator.h
+
+libsefht_la_CPPFLAGS = -DLIB_SEFHT_COMPILATION
+libsefht_la_LDFLAGS = -version_info 0:0:0
diff --git a/src/cms.c b/src/lib/sefht/cms.c
similarity index 100%
rename from src/cms.c
rename to src/lib/sefht/cms.c
diff --git a/src/cms.h b/src/lib/sefht/cms.h
similarity index 63%
rename from src/cms.h
rename to src/lib/sefht/cms.h
index 683f0cb..d9fca6a 100644
--- a/src/cms.h
+++ b/src/lib/sefht/cms.h
@@ -22,23 +22,38 @@
  */
 
 
-#ifndef _CMS_H
-#define _CMS_H
+#ifndef __CMS_H__
+#define __CMS_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include "error.h"
 
 #include "data.h"
 
 
+#ifdef LIB_SEFHT_COMPILATION
+
 struct SH_Cms
 {
 	struct SH_Data * data;
 };
 
-struct SH_Cms * SH_Cms_new (struct SH_Error * error);
-void SH_Cms_free (struct SH_Cms * cms, struct SH_Error * error);
+#endif /* LIB_SEFHT_COMPILATION */
+
+typedef struct SH_Cms SH_Cms;
+
+
+SH_Cms *
+SH_Cms_new (struct SH_Error * error);
+
+void
+SH_Cms_free (SH_Cms * cms, struct SH_Error * error);
 
-page_t SH_Cms_register_page (struct SH_Cms * cms, const char * name,
-			     struct SH_Error * error);
+page_t
+SH_Cms_register_page (SH_Cms * cms, const char * name,
+                      struct SH_Error * error);
 
-#endif /* _CMS_H */
+#endif /* __CMS_H__ */
diff --git a/src/data.c b/src/lib/sefht/data.c
similarity index 100%
rename from src/data.c
rename to src/lib/sefht/data.c
diff --git a/src/data.h b/src/lib/sefht/data.h
similarity index 69%
rename from src/data.h
rename to src/lib/sefht/data.h
index 4b502d3..22e7553 100644
--- a/src/data.h
+++ b/src/lib/sefht/data.h
@@ -22,8 +22,12 @@
  */
 
 
-#ifndef _DATA_H
-#define _DATA_H
+#ifndef __DATA_H__
+#define __DATA_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include <limits.h>
 
@@ -36,6 +40,9 @@ typedef unsigned int page_t;
 #define PAGE_ERR 0
 #define PAGE_MIN 1
 #define PAGE_MAX UINT_MAX
+
+#ifdef LIB_SEFHT_COMPILATION
+
 #define NEXT_PAGE(page) page++
 
 struct SH_Page
@@ -52,11 +59,19 @@ struct SH_Data
 	page_t last_page;
 };
 
-struct SH_Data * SH_Data_new (struct SH_Error * error);
-void SH_Data_free (struct SH_Data * data, struct SH_Error * error);
+#endif /* LIB_SEFHT_COMPILATION */
+
+typedef struct SH_Data SH_Data;
+
+
+SH_Data *
+SH_Data_new (struct SH_Error * error);
 
+void
+SH_Data_free (SH_Data * data, struct SH_Error * error);
 
-page_t SH_Data_register_page (struct SH_Data * data, const char * name,
-			      struct SH_Error * error);
+page_t
+SH_Data_register_page (SH_Data * data, const char * name,
+                       struct SH_Error * error);
 
-#endif /* _DATA_H */
+#endif /* __DATA_H__ */
diff --git a/src/error.h b/src/lib/sefht/error.h
similarity index 82%
rename from src/error.h
rename to src/lib/sefht/error.h
index f8e2e5e..a8ded62 100644
--- a/src/error.h
+++ b/src/lib/sefht/error.h
@@ -22,8 +22,12 @@
  */
 
 
-#ifndef _ERROR_H
-#define _ERROR_H
+#ifndef __ERROR_H__
+#define __ERROR_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 
 enum SH_ErrorType
@@ -40,4 +44,4 @@ struct SH_Error
 	enum SH_ErrorType type;
 };
 
-#endif /* _ERROR_H */
+#endif /* __ERROR_H__ */
diff --git a/src/fragment.c b/src/lib/sefht/fragment.c
similarity index 100%
rename from src/fragment.c
rename to src/lib/sefht/fragment.c
diff --git a/src/fragment.h b/src/lib/sefht/fragment.h
similarity index 73%
rename from src/fragment.h
rename to src/lib/sefht/fragment.h
index c15ed29..30de47f 100644
--- a/src/fragment.h
+++ b/src/lib/sefht/fragment.h
@@ -22,8 +22,12 @@
  */
 
 
-#ifndef _FRAGMENT_H
-#define _FRAGMENT_H
+#ifndef __FRAGMENT_H__
+#define __FRAGMENT_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include "data.h"
 #include "text.h"
@@ -35,6 +39,8 @@ enum HTML_MODE
 	WRAP
 };
 
+#ifdef LIB_SEFHT_COMPILATION
+
 enum SH_FRAGMENT_TYPE
 {
 	NODE
@@ -108,21 +114,24 @@ get_type (struct SH_Fragment * fragment)
 	return fragment->type;
 }
 
+#endif /* LIB_SEFHT_COMPILATION */
+
+typedef struct SH_Fragment SH_Fragment;
 
-struct SH_Fragment *
-SH_Fragment_copy (struct SH_Fragment * fragment,
-		  struct SH_Error * error);
+SH_Fragment *
+SH_Fragment_copy (SH_Fragment * fragment,
+                  struct SH_Error * error);
 
 void
-SH_Fragment_free (struct SH_Fragment * fragment,
-		  struct SH_Error * error);
-
-struct SH_Text *
-SH_Fragment_to_html (struct SH_Fragment * fragment,
-		     enum HTML_MODE mode,
-		     unsigned int indent_base,
-		     unsigned int indent_step,
-		     char * indent_char,
-		     struct SH_Error * error);
-
-#endif /* _FRAGMENT_H */
+SH_Fragment_free (SH_Fragment * fragment,
+                  struct SH_Error * error);
+
+SH_Text *
+SH_Fragment_to_html (SH_Fragment * fragment,
+                     enum HTML_MODE mode,
+                     unsigned int indent_base,
+                     unsigned int indent_step,
+                     char * indent_char,
+                     struct SH_Error * error);
+
+#endif /* __FRAGMENT_H__ */
diff --git a/src/log.h b/src/lib/sefht/log.h
similarity index 84%
rename from src/log.h
rename to src/lib/sefht/log.h
index 8e5c3a7..684fc67 100644
--- a/src/log.h
+++ b/src/lib/sefht/log.h
@@ -22,8 +22,12 @@
  */
 
 
-#ifndef _LOG_H
-#define _LOG_H
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include <stdio.h>
 
@@ -33,4 +37,4 @@
 #define ERROR3(message, arg1, arg2) printf (message, arg1, arg2)
 #define ERROR4(message, arg1, arg2, arg3) printf (message, arg1, arg2, arg3)
 
-#endif /* _LOG_H */
+#endif /* __LOG_H__ */
diff --git a/src/macro.h b/src/lib/sefht/macro.h
similarity index 81%
rename from src/macro.h
rename to src/lib/sefht/macro.h
index 844daa8..23dd36a 100644
--- a/src/macro.h
+++ b/src/lib/sefht/macro.h
@@ -22,12 +22,16 @@
  */
 
 
-#ifndef _MACRO_H
-#define _MACRO_H
+#ifndef __MACRO_H__
+#define __MACRO_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include <stdbool.h>
 
 #define TRUE (bool) 1
 #define FALSE (bool) 0
 
-#endif /* _MACRO_H */
+#endif /* __MACRO_H__ */
diff --git a/src/node_fragment.c b/src/lib/sefht/node_fragment.c
similarity index 100%
rename from src/node_fragment.c
rename to src/lib/sefht/node_fragment.c
diff --git a/src/lib/sefht/node_fragment.h b/src/lib/sefht/node_fragment.h
new file mode 100644
index 0000000..7f29ed5
--- /dev/null
+++ b/src/lib/sefht/node_fragment.h
@@ -0,0 +1,117 @@
+/*
+ * node_fragment.h
+ *
+ * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+
+#ifndef __NODE_FRAGMENT_H__
+#define __NODE_FRAGMENT_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
+
+#include "data.h"
+#include "text.h"
+
+#include "fragment.h"
+
+
+#ifdef LIB_SEFHT_COMPILATION
+
+struct SH_NodeFragment;
+struct SH_NodeFragment
+{
+	struct SH_Fragment base;
+
+	char * tag;
+
+	size_t child_n;
+	struct SH_Fragment ** childs;
+};
+
+#define OPEN_TAG_BEGIN "<"
+#define OPEN_TAG_END ">"
+#define CLOSE_TAG_BEGIN "</"
+#define CLOSE_TAG_END ">"
+
+//~ #define INDENT_TEXT "\t"
+#define NEWLINE "\n"
+
+#endif /* LIB_SEFHT_COMPILATION */
+
+/* TODO: no-export */
+#define INDENT_TEXT "\t"
+
+typedef struct SH_NodeFragment SH_NodeFragment;
+
+
+SH_Fragment *
+SH_NodeFragment_new (const char * tag,
+                     SH_Data * data,
+                     struct SH_Error * error);
+
+void
+SH_NodeFragment_free (SH_NodeFragment * fragment,
+                      struct SH_Error * error);
+
+SH_Fragment *
+SH_NodeFragment_copy (SH_NodeFragment * fragment,
+                      struct SH_Error * error);
+
+SH_Fragment *
+SH_NodeFragment_deepcopy (SH_NodeFragment * fragment,
+                          struct SH_Error * error);
+
+bool
+SH_Fragment_is_NodeFragment (SH_Fragment * fragment);
+
+char *
+SH_NodeFragment_get_tag (SH_NodeFragment * fragment,
+                         struct SH_Error * error);
+
+SH_Fragment *
+SH_NodeFragment_get_child (SH_NodeFragment * fragment,
+                           size_t index,
+                           struct SH_Error * error);
+
+bool
+SH_NodeFragment_is_child (SH_NodeFragment * fragment,
+                          SH_Fragment * child);
+
+bool
+SH_NodeFragment_is_descendant (SH_NodeFragment * fragment,
+                               SH_Fragment * child);
+
+bool
+SH_NodeFragment_append_child (SH_NodeFragment * fragment,
+			      SH_Fragment * child,
+                              struct SH_Error * error);
+
+SH_Text *
+SH_NodeFragment_to_html (SH_NodeFragment * fragment,
+                         enum HTML_MODE mode,
+                         unsigned int indent_base,
+                         unsigned int indent_step,
+                         char * indent_char,
+                         struct SH_Error * error);
+
+#endif /* __NODE_FRAGMENT_H__ */
diff --git a/src/sefht.h b/src/lib/sefht/sefht.h
similarity index 72%
rename from src/sefht.h
rename to src/lib/sefht/sefht.h
index 74f46db..5787fe5 100644
--- a/src/sefht.h
+++ b/src/lib/sefht/sefht.h
@@ -22,7 +22,22 @@
  */
 
 
-#ifndef _SEFHT_H
-#define _SEFHT_H
+#ifndef __SEFHT_H__
+#define __SEFHT_H__
 
-#endif /* _SEFHT_H */
+#define __SEFHT_H_INSIDE__
+
+#include "error.h"
+#include "log.h"
+#include "macro.h"
+
+#include "cms.h"
+#include "data.h"
+#include "fragment.h"
+#include "node_fragment.h"
+#include "text.h"
+#include "validator.h"
+
+#undef __SEFHT_H_INSIDE__
+
+#endif /* __SEFHT_H__ */
diff --git a/src/text.c b/src/lib/sefht/text.c
similarity index 100%
rename from src/text.c
rename to src/lib/sefht/text.c
diff --git a/src/text.h b/src/lib/sefht/text.h
similarity index 90%
rename from src/text.h
rename to src/lib/sefht/text.h
index 2b5e74e..8dcd7bd 100644
--- a/src/text.h
+++ b/src/lib/sefht/text.h
@@ -22,14 +22,20 @@
  */
 
 
-#ifndef _TEXT_H
-#define _TEXT_H
+#ifndef __TEXT_H__
+#define __TEXT_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include <stdbool.h>
 
 #include "error.h"
 
 
+#ifdef LIB_SEFHT_COMPILATION
+
 #ifndef CHUNK_SIZE
 #define CHUNK_SIZE 64
 #endif /* CHUNK_SIZE */
@@ -54,6 +60,11 @@ struct SH_Text
 	/*@notnull@*/ struct text_segment * data;
 };
 
+#endif /* LIB_SEFHT_COMPILATION */
+
+typedef /*@abstract@*/ struct SH_Text SH_Text;
+
+
 /*@null@*/
 /*@only@*/
 struct SH_Text *
@@ -119,4 +130,4 @@ SH_Text_join (struct SH_Text * text,
 void
 SH_Text_print (const struct SH_Text * text);
 
-#endif /* _TEXT_H */
+#endif /* __TEXT_H__ */
diff --git a/src/validator.c b/src/lib/sefht/validator.c
similarity index 100%
rename from src/validator.c
rename to src/lib/sefht/validator.c
diff --git a/src/validator.h b/src/lib/sefht/validator.h
similarity index 59%
rename from src/validator.h
rename to src/lib/sefht/validator.h
index f0fd7be..902d1ac 100644
--- a/src/validator.h
+++ b/src/lib/sefht/validator.h
@@ -22,17 +22,26 @@
  */
 
 
-#ifndef _VALIDATOR_H
-#define _VALIDATOR_H
+#ifndef __VALIDATOR_H__
+#define __VALIDATOR_H__
+
+#if !defined (__SEFHT_H_INSIDE__) && !defined (LIB_SEFHT_COMPILATION)
+#error "Only <sefht/sefht.h> can be included directly."
+#endif
 
 #include <limits.h>
 #include <stdbool.h>
 
+#include "error.h"
+
 
 typedef unsigned int tag_t;
 #define TAG_ERR 0
 #define TAG_MIN 1
 #define TAG_MAX UINT_MAX
+
+#ifdef LIB_SEFHT_COMPILATION
+
 #define NEXT_TAG(tag) tag++
 
 struct SH_Tag
@@ -48,16 +57,26 @@ struct SH_Validator
 	tag_t last_tag;
 };
 
-struct SH_Validator * SH_Validator_new (struct SH_Error * error);
-void SH_Validator_free (struct SH_Validator * validator,
-			struct SH_Error * error);
+#endif /* LIB_SEFHT_COMPILATION */
+
+typedef struct SH_Validator SH_Validator;
+
+
+SH_Validator *
+SH_Validator_new (struct SH_Error * error);
+
+void
+SH_Validator_free (SH_Validator * validator,
+                   struct SH_Error * error);
 
-tag_t SH_Validator_register_tag (struct SH_Validator * validator,
-				 const char * tag,
-				 struct SH_Error * error);
+tag_t
+SH_Validator_register_tag (SH_Validator * validator,
+                           const char * tag,
+                           struct SH_Error * error);
 
 
-bool SH_Validator_check_tag (struct SH_Validator * validator,
-			     const char * tag);
+bool
+SH_Validator_check_tag (SH_Validator * validator,
+                        const char * tag);
 
-#endif /* _VALIDATOR_H */
+#endif /* __VALIDATOR_H__ */
diff --git a/src/main.c b/src/main.c
index 804fc9f..0fa442c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -24,18 +24,15 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "cms.h"
-#include "data.h"
-#include "fragment.h"
-#include "node_fragment.h"
-#include "text.h"
+
+#include <sefht/sefht.h>
 
 int main(int argc, char **argv)
 {
 	page_t page;
 
 	/* startup */
-	struct SH_Cms * cms = SH_Cms_new (NULL);
+	SH_Cms * cms = SH_Cms_new (NULL);
 	/* startup */
 
 	page = SH_Cms_register_page (cms, "Startpage", NULL);
@@ -45,11 +42,11 @@ int main(int argc, char **argv)
 	/* shutdown */
 
 
-	struct SH_Data * data;
-	struct SH_Fragment * root;
-	struct SH_Fragment * child1;
-	struct SH_Fragment * child2;
-	struct SH_Text * text;
+	SH_Data * data;
+	SH_Fragment * root;
+	SH_Fragment * child1;
+	SH_Fragment * child2;
+	SH_Text * text;
 
 	data = SH_Data_new (NULL);
 
diff --git a/src/node_fragment.h b/src/node_fragment.h
deleted file mode 100644
index fecfafe..0000000
--- a/src/node_fragment.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * node_fragment.h
- *
- * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- *
- */
-
-
-#ifndef _NODE_FRAGMENT_H
-#define _NODE_FRAGMENT_H
-
-#include "data.h"
-#include "text.h"
-
-#include "fragment.h"
-
-
-struct SH_NodeFragment;
-struct SH_NodeFragment
-{
-	struct SH_Fragment base;
-
-	char * tag;
-
-	size_t child_n;
-	struct SH_Fragment ** childs;
-};
-
-#define OPEN_TAG_BEGIN "<"
-#define OPEN_TAG_END ">"
-#define CLOSE_TAG_BEGIN "</"
-#define CLOSE_TAG_END ">"
-
-#define INDENT_TEXT "\t"
-#define NEWLINE "\n"
-
-struct SH_Fragment *
-SH_NodeFragment_new (const char * tag,
-		     struct SH_Data * data,
-		     struct SH_Error * error);
-
-void
-SH_NodeFragment_free (struct SH_NodeFragment * fragment,
-		      struct SH_Error * error);
-
-struct SH_Fragment *
-SH_NodeFragment_copy (struct SH_NodeFragment * fragment,
-		      struct SH_Error * error);
-
-struct SH_Fragment *
-SH_NodeFragment_deepcopy (struct SH_NodeFragment * fragment,
-			  struct SH_Error * error);
-
-bool
-SH_Fragment_is_NodeFragment (struct SH_Fragment * fragment);
-
-char *
-SH_NodeFragment_get_tag (struct SH_NodeFragment * fragment,
-			 struct SH_Error * error);
-
-struct SH_Fragment *
-SH_NodeFragment_get_child (struct SH_NodeFragment * fragment,
-			   size_t index,
-			   struct SH_Error * error);
-
-bool
-SH_NodeFragment_is_child (struct SH_NodeFragment * fragment,
-			  struct SH_Fragment * child);
-
-bool
-SH_NodeFragment_is_descendant (struct SH_NodeFragment * fragment,
-			       struct SH_Fragment * child);
-
-bool
-SH_NodeFragment_append_child (struct SH_NodeFragment * fragment,
-			      struct SH_Fragment * child,
-			      struct SH_Error * error);
-
-struct SH_Text *
-SH_NodeFragment_to_html (struct SH_NodeFragment * fragment,
-			 enum HTML_MODE mode,
-			 unsigned int indent_base,
-			 unsigned int indent_step,
-			 char * indent_char,
-			 struct SH_Error * error);
-
-#endif /* _NODE_FRAGMENT_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 20e43f9..d0a8894 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -12,30 +12,33 @@ TESTS += sefht_validator_test
 check_PROGRAMS = $(TESTS)
 
 AM_CPPFLAGS =
-AM_CPPFLAGS += -I$(top_srcdir)/src
+AM_CPPFLAGS += -DLIB_SEFHT_COMPILATION
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/sefht
 
 LDADD = $(CHECK_LIBS)
 
+OBJECT_PREFIX = $(top_builddir)/src/lib/sefht/libsefht_la-
+
 sefht_cms_test_SOURCES = test_cms.c
 sefht_cms_test_LDADD =
-sefht_cms_test_LDADD += $(top_builddir)/src/cms.o
-sefht_cms_test_LDADD += $(top_builddir)/src/data.o
-sefht_cms_test_LDADD += $(top_builddir)/src/validator.o
+sefht_cms_test_LDADD += $(OBJECT_PREFIX)cms.o
+sefht_cms_test_LDADD += $(OBJECT_PREFIX)data.o
+sefht_cms_test_LDADD += $(OBJECT_PREFIX)validator.o
 sefht_cms_test_LDADD += $(LDADD)
 
 sefht_data_test_SOURCES = test_data.c
 sefht_data_test_LDADD =
-sefht_data_test_LDADD += $(top_builddir)/src/data.o
-sefht_data_test_LDADD += $(top_builddir)/src/validator.o
+sefht_data_test_LDADD += $(OBJECT_PREFIX)data.o
+sefht_data_test_LDADD += $(OBJECT_PREFIX)validator.o
 sefht_data_test_LDADD += $(LDADD)
 
 sefht_node_fragment_test_SOURCES = test_node_fragment.c
 sefht_node_fragment_test_LDADD =
-sefht_node_fragment_test_LDADD += $(top_builddir)/src/node_fragment.o
-sefht_node_fragment_test_LDADD += $(top_builddir)/src/data.o
-sefht_node_fragment_test_LDADD += $(top_builddir)/src/fragment.o
-sefht_node_fragment_test_LDADD += $(top_builddir)/src/text.o
-sefht_node_fragment_test_LDADD += $(top_builddir)/src/validator.o
+sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)node_fragment.o
+sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)data.o
+sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)fragment.o
+sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)text.o
+sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)validator.o
 sefht_node_fragment_test_LDADD += $(LDADD)
 
 sefht_text_test_SOURCES = test_text.c
-- 
GitLab