summaryrefslogtreecommitdiffabout
path: root/include/sitecing
authorMichael Krelin <hacker@klever.net>2005-01-29 21:21:05 (UTC)
committer Michael Krelin <hacker@klever.net>2005-01-29 21:21:05 (UTC)
commitce1f37aae46ea95020d7b865f7a80e8abdfad0d8 (patch) (side-by-side diff)
tree4964383ab8cd7e6d8ea821f1a615d1bbcf98dad8 /include/sitecing
parent3c75c860fc1ad5b3f5185e23ec6f438dd2528958 (diff)
downloadsitecing-0.0.zip
sitecing-0.0.tar.gz
sitecing-0.0.tar.bz2
initial commit into repository0.0
Diffstat (limited to 'include/sitecing') (more/less context) (show whitespace changes)
-rw-r--r--include/sitecing/acomponent.h78
-rw-r--r--include/sitecing/cgi_component.h54
-rw-r--r--include/sitecing/component_factory.h84
-rw-r--r--include/sitecing/component_so.h159
-rw-r--r--include/sitecing/configuration.h459
-rw-r--r--include/sitecing/exception.h542
-rw-r--r--include/sitecing/file_factory.h64
-rw-r--r--include/sitecing/magic.h63
-rw-r--r--include/sitecing/process_manager.h89
-rw-r--r--include/sitecing/scoreboard.h102
-rw-r--r--include/sitecing/sitecing_enflesher.h65
-rw-r--r--include/sitecing/sitecing_exception.h103
-rw-r--r--include/sitecing/sitecing_interface.h40
-rw-r--r--include/sitecing/sitecing_interface_cgi.h62
-rw-r--r--include/sitecing/sitecing_parser.h326
-rw-r--r--include/sitecing/sitecing_util.h341
-rw-r--r--include/sitecing/sitespace.h76
-rw-r--r--include/sitecing/util.h148
18 files changed, 2855 insertions, 0 deletions
diff --git a/include/sitecing/acomponent.h b/include/sitecing/acomponent.h
new file mode 100644
index 0000000..160e854
--- a/dev/null
+++ b/include/sitecing/acomponent.h
@@ -0,0 +1,78 @@
+#ifndef __SITECING_ACOMPONENT_H
+#define __SITECING_ACOMPONENT_H
+
+#include "sitecing/sitecing_interface.h"
+
+/**
+ * @file
+ * @brief The acomponent class declaration.
+ */
+
+namespace sitecing {
+
+ /**
+ * An abstract base class for sitecing components.
+ */
+ class acomponent {
+ public:
+ /**
+ * Pointer to the interface object, used to communicate with the
+ * site-C-ing core.
+ */
+ sitecing_interface *__SCIF;
+
+ acomponent();
+ virtual ~acomponent();
+
+ /**
+ * Set the interface to core pointer.
+ * @param scif the pointer to the interface object.
+ */
+ virtual void __set_interface(sitecing_interface *scif=0);
+ /**
+ * Invoked if the interface to the core has changed.
+ * @param oscif pointer to the old interface object.
+ */
+ virtual void __on_change_interface(sitecing_interface *oscif);
+
+ /**
+ * do import components.
+ */
+ virtual void __do_imports();
+ /**
+ * invoked on components imports.
+ */
+ virtual void __on_imports();
+ /**
+ * fetch the pointer to the most derived component.
+ * @returns pointer to the most derived object.
+ */
+ virtual void *__the_most_derived_this() = 0;
+
+ /**
+ * Do the job.
+ * @param __magic the magic number used as a key to decipher the
+ * rest of parameters.
+ * @param __args the parameters.
+ */
+ virtual void main(int __magic,va_list __args) = 0;
+
+ /**
+ * Run the component. Convenience helper for calling main().
+ * @param __magic the magic number.
+ * @param ... the rest of parameters.
+ * @see main();
+ */
+ void run(int __magic,...);
+
+ /**
+ * Helper function (which doesn't necessarily belongs here!) for
+ * reading the file and passing it to the output stream.
+ * @param fn the file name.
+ */
+ void pass_file_through(const char *fn);
+ };
+
+}
+
+#endif /* __SITECING_ACOMPONENT_H */
diff --git a/include/sitecing/cgi_component.h b/include/sitecing/cgi_component.h
new file mode 100644
index 0000000..91df689
--- a/dev/null
+++ b/include/sitecing/cgi_component.h
@@ -0,0 +1,54 @@
+#ifndef __SITECING_CGI_COMPONENT_H
+#define __SITECING_CGI_COMPONENT_H
+
+#include <map>
+#include "kingate/cgi_gateway.h"
+#include "sitecing/acomponent.h"
+#include "sitecing/sitecing_interface_cgi.h"
+
+/**
+ * @file
+ * @brief The cgi_component class declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * The CGI-oriented component class.
+ */
+ class cgi_component : virtual public acomponent {
+ public:
+ /**
+ * The interface to site-C-ing core.
+ */
+ sitecing_interface_cgi* __SCIF;
+ /**
+ * The interface to the CGI gateway.
+ */
+ kingate::cgi_gateway* __CGI;
+
+ cgi_component();
+ virtual ~cgi_component();
+
+ /**
+ * @overload acomponent::__set_interface()
+ */
+ void __set_interface(sitecing_interface* scif);
+ /**
+ * @overload acomponent::__on_change_interface()
+ */
+ void __on_change_interface(sitecing_interface *o);
+ /**
+ * Invoked on the change of the interface to the CGI.
+ */
+ virtual void __on_change_CGI(kingate::cgi_gateway *o);
+ /**
+ * @overload acomponent::__on_imports()
+ */
+ virtual void __on_imports();
+ };
+
+}
+
+#endif /* __SITECING_CGI_COMPONENT_H */
diff --git a/include/sitecing/component_factory.h b/include/sitecing/component_factory.h
new file mode 100644
index 0000000..a208ed1
--- a/dev/null
+++ b/include/sitecing/component_factory.h
@@ -0,0 +1,84 @@
+#ifndef __SITECING_COMPONENT_FACTORY_H
+#define __SITECING_COMPONENT_FACTORY_H
+
+#include <string>
+#include <list>
+#include <stdexcept>
+#include "sitecing/file_factory.h"
+#include "sitecing/configuration.h"
+
+/**
+ * @file
+ * @brief The component_factory class declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * @brief The components builder.
+ */
+ class component_factory : public file_factory {
+ public:
+ /**
+ * Path to the source files root.
+ */
+ string root_source;
+ /**
+ * Path to the root of the intermediate files storage.
+ */
+ string root_intermediate;
+ /**
+ * Output path for .so components.
+ */
+ string root_so;
+ /**
+ * Reference to the configuration container.
+ */
+ configuration& config;
+
+ /**
+ * @param c reference to the configuration container.
+ */
+ component_factory(configuration& c);
+
+ /**
+ * @overload file_factory::get_dependencies()
+ */
+ virtual void get_dependencies(const string& dst,file_list_t& deps);
+ /**
+ * @overload file_factory::is_uptodate()
+ */
+ virtual bool is_uptodate(const string& dst,file_list_t *deps=NULL);
+ /**
+ * @overload file_factory::build()
+ */
+ virtual void build(const string& dst);
+
+ /**
+ * Helper function for executing external command.
+ * @param cmd the command to execute.
+ * @param args the command line arguments.
+ * @param stdo stdout for the child process.
+ * @param stde stderr for the child process.
+ * @return exit code.
+ */
+ int execute(const string& cmd,const list<string>& args,int stdo,int stde);
+ /**
+ * Fetch the class name of the component.
+ * @param component the component.
+ * @return the class name.
+ */
+ string get_classname(const string& component);
+ /**
+ * Get the components from which the target component has been
+ * derived.
+ * @param component the target component
+ * @param rv where to store the list of ancestors.
+ */
+ void get_ancestors(const string& component,file_list_t &rv);
+ };
+
+}
+
+#endif /* __SITECING_COMPONENT_FACTORY_H */
diff --git a/include/sitecing/component_so.h b/include/sitecing/component_so.h
new file mode 100644
index 0000000..3239d4a
--- a/dev/null
+++ b/include/sitecing/component_so.h
@@ -0,0 +1,159 @@
+#ifndef __SITECING_COMPONENT_SO_H
+#define __SITECING_COMPONENT_SO_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string>
+#include <map>
+#include <list>
+#include "sitecing/acomponent.h"
+
+/**
+ * @file
+ * @brief Classes related to the .so components handling.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * The 'class' component object.
+ */
+ class component_so {
+ public:
+ /**
+ * The type of the component instantiating function.
+ */
+ typedef acomponent *(*egg_t)();
+ /**
+ * Type for storing the list of instances and the reference counts.
+ */
+ typedef map<acomponent*,int> used_chickens_t;
+ /**
+ * The type for storing the list of unused instances.
+ */
+ typedef list<acomponent*> free_chickens_t;
+
+ /**
+ * The .so file name.
+ */
+ string sofile;
+ /**
+ * The stat structure for the .so loaded.
+ */
+ struct stat stso;
+ /**
+ * The dloaded .so handle.
+ */
+ void *dl;
+ /**
+ * Pointer to the instatiator function.
+ */
+ egg_t egg;
+ /**
+ * The list of instances in use.
+ */
+ used_chickens_t chickens_used;
+ /**
+ * The list of unused instances.
+ */
+ free_chickens_t chickens_free;
+
+ /**
+ * @param soname the .so file name
+ */
+ component_so(const string& soname);
+ ~component_so();
+ /**
+ * Check whether the loaded .so is in sync with the disk file.
+ */
+ bool is_uptodate() const;
+
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ acomponent* allocate_chicken();
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void allocate_chicken(acomponent *ac);
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void deallocate_chicken(acomponent *ac);
+ };
+
+ /**
+ * The component instance container.
+ */
+ class so_component {
+ public:
+ /**
+ * Pointer to the component 'class'.
+ */
+ component_so *hen;
+ /**
+ * The instance in question.
+ */
+ acomponent* ac;
+
+ so_component()
+ : hen(0), ac(0) { }
+ /**
+ * @param h the 'class' object.
+ * @param scif pointer to the interface to the site-C-ing core.
+ */
+ so_component(component_so *h,sitecing_interface *scif);
+ /**
+ * Copy constructor
+ * @param s source instance.
+ */
+ so_component(const so_component& s)
+ : hen(0), ac(0) { attach(s); }
+ ~so_component() { detach(); }
+
+ /**
+ * Assignment operator.
+ * @param s source instance.
+ */
+ so_component& operator=(const so_component& s) {
+ attach(s); return *this;
+ }
+
+ /**
+ * @todo TODO: wish I could remember the details -- document me.
+ * @param h the 'class' object.
+ * @param a the instance to be attached.
+ */
+ void attach(component_so *h,acomponent *a);
+ /**
+ * @todo TODO: wish I could remember the details -- document me.
+ * @param s the source instance.
+ */
+ void attach(const so_component& s) { attach(s.hen,s.ac); }
+ /**
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ void detach();
+ };
+
+ /**
+ * The typed component instance container template.
+ * @param CT the component class.
+ */
+ template<typename CT>
+ class so_component_t : public sitecing::so_component {
+ public:
+ /**
+ * @param s The untyped instance container.
+ */
+ so_component_t(const so_component& s)
+ : so_component(s) { }
+ CT* operator->() {
+ return static_cast<CT*>(ac->__the_most_derived_this());
+ }
+ };
+
+}
+
+#endif /* __SITECING_COMPONENT_SO_H */
diff --git a/include/sitecing/configuration.h b/include/sitecing/configuration.h
new file mode 100644
index 0000000..330a5a6
--- a/dev/null
+++ b/include/sitecing/configuration.h
@@ -0,0 +1,459 @@
+#ifndef __SITECING_CONFIGURATION_H
+#define __SITECING_CONFIGURATION_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string>
+#include <list>
+#include <map>
+#include <pcre++.h>
+
+/**
+ * @file
+ * @brief Classes related to configuration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ class configuration;
+
+ /**
+ * The config options container class.
+ */
+ class config_options {
+ public:
+ /**
+ * The flags enumeration.
+ */
+ enum _flags {
+ /**
+ * Skeleton has been specified in the context.
+ * @see skeleton
+ */
+ flag_skeleton = 0x0001,
+ /**
+ * CPPFLAGS have been specified in the context
+ * @see cpp_flags
+ */
+ flag_cpp_flags = 0x0002,
+ /**
+ * LDFLAGS have been specified in the context.
+ * @see ld_flags
+ */
+ flag_ld_flags = 0x0004,
+ /**
+ * Enforced intermediate dependencies have been specified in the
+ * context.
+ * @see internediate_deps
+ */
+ flag_intermediate_deps = 0x0008,
+ /**
+ * Enforced .so dependencies have been specified in the context.
+ * @see so_deps
+ */
+ flag_so_deps = 0x0010,
+ /**
+ * Whether components should be built specified in the context.
+ * @see build
+ */
+ flag_build = 0x0020,
+ /**
+ * Whether to track down cpp dependencies has been specified in
+ * the context.
+ * @see cpp_deps
+ */
+ flag_cpp_deps = 0x0040,
+ /**
+ * The exception handler has been specified in the context.
+ * @see exception_handler
+ */
+ flag_exception_handler = 0x0080,
+ /**
+ * Action handlers have been specified in the context.
+ * @see action_handlers
+ */
+ flag_action_handlers = 0x0100,
+ /**
+ * HTTP status handerls have been specified in the context.
+ * @see http_status_handlers
+ */
+ flag_http_status_handlers = 0x0200,
+ /**
+ * The files to be built are specified in the context.
+ * @see auto_build_files
+ */
+ flag_auto_build_files = 0x0400
+ };
+ /**
+ * The flags specifying what parts of configuration have been
+ * specified for the context.
+ */
+ int flags;
+
+ /**
+ * The skeleton for building components.
+ */
+ string skeleton;
+ /**
+ * The flags to pass to compiler.
+ */
+ list<string> cpp_flags;
+ /**
+ * The flags to pass to linker.
+ */
+ list<string> ld_flags;
+ /**
+ * Whether to build inexstent and outdated components.
+ */
+ bool build;
+ /**
+ * Whether to track cpp dependencies.
+ */
+ bool cpp_deps;
+ /**
+ * The component handling caught exceptions.
+ */
+ string exception_handler;
+ /**
+ * Enforced intermediate dependencies.
+ */
+ list<string> intermediate_deps;
+ /**
+ * Enforced depencies for .so objects.
+ */
+ list<string> so_deps;
+ /**
+ * The action handler type.
+ */
+ struct action_handler_t {
+ /**
+ * The regexp to check request against.
+ */
+ string s_regex;
+ /**
+ * Precompiled regex.
+ */
+ pcrepp::Pcre regex;
+ /**
+ * The action handler component.
+ */
+ string action;
+ /**
+ * Arguments for the action hander coponent.
+ */
+ list<string> args;
+
+ action_handler_t(const string& s,const string& a)
+ : s_regex(s), regex(s), action(a) { }
+ action_handler_t(const action_handler_t& s)
+ : s_regex(s.s_regex), regex(s.regex), action (s.action), args(s.args) { }
+ };
+ /**
+ * Type for the list of action handlers.
+ */
+ typedef list<action_handler_t> action_handlers_t;
+ /**
+ * The list of action handlers.
+ */
+ action_handlers_t action_handlers;
+ /**
+ * Type for the map of HTTP status handler components.
+ */
+ typedef map<string,string> http_status_handlers_t;
+ /**
+ * The map of HTTP status handler components.
+ */
+ http_status_handlers_t http_status_handlers;
+ /**
+ * Files to be built automatically.
+ */
+ list<string> auto_build_files;
+
+ config_options()
+ : flags(0) { }
+
+ /**
+ * Look up if there is an action handler for the target defined.
+ * @param target the target component.
+ * @return the pointer to handler or zero.
+ */
+ action_handler_t *lookup_action_handler(const string& target);
+ /**
+ * Look up if there is a handler defined for the HTTP status.
+ * @param status HTTP status
+ * @return the handler component.
+ */
+ string lookup_http_status_handler(const string& status);
+ /**
+ * Check whether the file should be build automatically.
+ * @param fn file name.
+ * @param rv reference to the boolean where the answer should go.
+ * @return true if we know the answer.
+ */
+ bool match_autobuild_files(const char *fn,bool &rv);
+ };
+
+ /**
+ * Configuration data container for the configuration loaded from disk file.
+ */
+ class loaded_options : public config_options {
+ public:
+ /**
+ * The file where configuration originates from.
+ */
+ string source_file;
+ /**
+ * The stat structure for the source file as it was when we have
+ * loaded it.
+ */
+ struct stat st;
+
+ /**
+ * See if the data is still valid.
+ * @return true if yes.
+ */
+ bool is_valid();
+
+ /**
+ * Load the configuration file.
+ * @param config the main configuration container.
+ * @param the configuration file.
+ */
+ void parse(configuration *config,const string& cfile);
+ };
+
+ /**
+ * The main configuration container.
+ */
+ class configuration {
+ public:
+ /**
+ * @todo TODO:: document me.
+ */
+ bool autobuild;
+ /**
+ * The flags enumeration.
+ */
+ enum _flags {
+ /**
+ * Was the source root specified?
+ * @see root_source
+ */
+ flag_root_source = 0x00000001,
+ /**
+ * Was the root for intermediate files specified?
+ * @see root_intermediate
+ */
+ flag_root_intermediate = 0x00000002,
+ /**
+ * Was the root for the resulting .so files specified?
+ * @see root_so
+ */
+ flag_root_so = 0x00000004,
+ /**
+ * Was the socket to listen to specified?
+ * @see listen_socket
+ */
+ flag_listen_socket = 0x00000008,
+ /**
+ * Was the per-dir config file name specified.
+ * @see rc_file_name
+ */
+ flag_rc_file_name = 0x00000010,
+ /**
+ * Was the minimum number of child processes specified?
+ * @see min_children
+ */
+ flag_min_children = 0x00000020,
+ /**
+ * Was the maximum number of child processes specified?
+ * @see max_children
+ */
+ flag_max_children = 0x00000040,
+ /**
+ * Was the minimum number of spare child processes specified?
+ * @see min_spare_children
+ */
+ flag_min_spare_children = 0x00000080,
+ /**
+ * Was he maximum number of spare child processes specified?
+ * @see max_spare_children
+ */
+ flag_max_spare_children = 0x00000100,
+ /**
+ * Was the number of requests to handle per child process
+ * specified?
+ * @see requests_per_child
+ */
+ flag_requests_per_child = 0x00000200,
+ /**
+ * Was the multiprocess node (or it's absences) specified?
+ * @see multi_process
+ */
+ flag_multi_process = 0x00000400,
+ /**
+ * Was the user specified?
+ * @see user
+ */
+ flag_user = 0x00000800,
+ /**
+ * @Was the group specified?
+ * @see group
+ */
+ flag_group = 0x00001000,
+ /**
+ * Was the root to change to specified?
+ * @see chroot
+ */
+ flag_chroot = 0x00002000,
+ /**
+ * Was the file for storing PID specified?
+ * @see pidfile
+ */
+ flag_pid_file = 0x00004000,
+ /**
+ * Was it specified wether we should daemonize the process?
+ * @see daemonize
+ */
+ flag_daemonize = 0x00008000
+ };
+ /**
+ * The flags specifying what parts of the configuration has been
+ * loaded into the object.
+ */
+ long flags;
+
+ /**
+ * The root for the components source code.
+ */
+ string root_source;
+ /**
+ * The root for intermediate files.
+ */
+ string root_intermediate;
+ /**
+ * The root for .so files.
+ */
+ string root_so;
+ /**
+ * Socket to bind to
+ */
+ string listen_socket;
+ /**
+ * per-dir config file name.
+ */
+ string rc_file_name;
+ /**
+ * The minimum number of child processes in multiprocess mode.
+ */
+ int min_children;
+ /**
+ * The maxium number of child processes in multiprocess mode.
+ */
+ int max_children;
+ /**
+ * The minimum number of spare chidren in multiprocess mode.
+ */
+ int min_spare_children;
+ /**
+ * The maximum number of spare children in multiprocess mode.
+ */
+ int max_spare_children;
+ /**
+ * The number of requests the child process should handle before
+ * exiting.
+ */
+ int requests_per_child;
+ /**
+ * Whether we should run in multiprocess mode or not.
+ */
+ bool multi_process;
+ /**
+ * User to change to.
+ */
+ string user;
+ /**
+ * Group to set to.
+ */
+ string group;
+ /**
+ * Directory to change root to.
+ */
+ string chroot;
+ /**
+ * The file to store PID into.
+ */
+ string pid_file;
+ /**
+ * Whether we should fork into background.
+ */
+ bool daemonize;
+
+ typedef map<string,config_options> specs_t;
+ /**
+ * The local config options map.
+ */
+ specs_t specs;
+ typedef map<string,loaded_options> loaded_specs_t;
+ /**
+ * The local config options as specified in per-dir config files
+ * map.
+ */
+ loaded_specs_t loaded_specs;
+
+ configuration();
+ /**
+ * @param cfile the configuration file.
+ * @param ab @todo TODO:: document me
+ */
+ configuration(const string& cfile,bool ab=false);
+
+ /**
+ * Parse the configuration file.
+ * @param cfile the configuration file.
+ */
+ void parse(const string& cfile);
+
+ /**
+ * Fetch the reference to options for the very root.
+ */
+ config_options& root_options() { return specs[""]; }
+ /**
+ * Lookup where the certain config option for the target lies in.
+ * @param target the target component.
+ * @param flag the flag specifying the option we're looking for.
+ * @return the destination options continer or zero.
+ */
+ config_options* lookup_config(const string& target,int flag);
+ /**
+ * Lookup the action handler for the target.
+ * @param target the target request.
+ * @return the action handler or zero.
+ */
+ config_options::action_handler_t *lookup_action_handler(const string& target);
+ /**
+ * Lookup the HTPP status handler for the target.
+ * @param target the target.
+ * @param status the HTTP status.
+ * @return the handler component.
+ */
+ string lookup_http_status_handler(const string& target,const string& status);
+ /**
+ * Lookup the options loaded from per-dir config for the target
+ * @param target the target.
+ * @return options container or zero.
+ */
+ loaded_options* lookup_loaded_options(const string& target);
+ /**
+ * Check whether the components for the target should be prebuilt.
+ * @param target the target.
+ * @param fn file name.
+ * @return true if yes.
+ */
+ bool match_autobuild_files(const string& target,const char *fn);
+ };
+
+}
+
+#endif /* __SITECING_CONFIGURATION_H */
diff --git a/include/sitecing/exception.h b/include/sitecing/exception.h
new file mode 100644
index 0000000..985fc6d
--- a/dev/null
+++ b/include/sitecing/exception.h
@@ -0,0 +1,542 @@
+#ifndef __SITECING_EXCEPTION_H
+#define __SITECING_EXCEPTION_H
+
+/**
+ * @file
+ * @brief The site-C-ing specific exceptions.
+ */
+
+/**
+ * @brief The main site-C-ing namespace.
+ */
+namespace sitecing {
+
+ // TODO: status specifics
+
+ /**
+ * The http status to return.
+ */
+ class http_status {
+ public:
+ /**
+ * The status string.
+ */
+ string status;
+ /**
+ * The message to follow the status string.
+ */
+ string message;
+
+ /**
+ * @param s HTTP status.
+ * @param m HTTP status message.
+ */
+ http_status(const string& s,const string& m)
+ : status(s), message(m) { }
+ virtual ~http_status() throw() { }
+ };
+
+ // per RFC 2616
+
+ /**
+ * Informational.
+ */
+ class http_status_1xx : public http_status {
+ public:
+ explicit http_status_1xx(const string &s,const string& m)
+ : http_status(s,m) { }
+ };
+ /**
+ * Continue.
+ */
+ class http_status_100 : public http_status_1xx {
+ public:
+ explicit http_status_100(const string& m)
+ : http_status_1xx("100",m) { }
+ explicit http_status_100()
+ : http_status_1xx("100","Continue") { }
+ };
+ /**
+ * Switching protocols.
+ */
+ class http_status_101 : public http_status_1xx {
+ public:
+ explicit http_status_101(const string& m)
+ : http_status_1xx("101",m) { }
+ explicit http_status_101()
+ : http_status_1xx("101","Switching protocols") { }
+ };
+
+ /**
+ * Successful.
+ */
+ class http_status_2xx : public http_status {
+ public:
+ explicit http_status_2xx(const string& s,const string& m)
+ : http_status(s,m) { }
+ };
+ /**
+ * OK.
+ */
+ class http_status_200 : public http_status_2xx {
+ public:
+ explicit http_status_200(const string& m)
+ : http_status_2xx("200",m) { }
+ explicit http_status_200()
+ : http_status_2xx("200","OK") { }
+ };
+ /**
+ * Created.
+ */
+ class http_status_201 : public http_status_2xx {
+ public:
+ explicit http_status_201(const string& m)
+ : http_status_2xx("201",m) { }
+ explicit http_status_201()
+ : http_status_2xx("201","Created") { }
+ };
+ /**
+ * Accepted.
+ */
+ class http_status_202 : public http_status_2xx {
+ public:
+ explicit http_status_202(const string& m)
+ : http_status_2xx("202",m) { }
+ explicit http_status_202()
+ : http_status_2xx("202","Accepted") { }
+ };
+ /**
+ * Non-authoritative infortmation.
+ */
+ class http_status_203 : public http_status_2xx {
+ public:
+ explicit http_status_203(const string& m)
+ : http_status_2xx("203",m) { }
+ explicit http_status_203()
+ : http_status_2xx("203","Non-authoritative information") { }
+ };
+ /**
+ * No content.
+ */
+ class http_status_204 : public http_status_2xx {
+ public:
+ explicit http_status_204(const string& m)
+ : http_status_2xx("204",m) { }
+ explicit http_status_204()
+ : http_status_2xx("204","No content") { }
+ };
+ /**
+ * Reset content.
+ */
+ class http_status_205 : public http_status_2xx {
+ public:
+ explicit http_status_205(const string& m)
+ : http_status_2xx("205",m) { }
+ explicit http_status_205()
+ : http_status_2xx("205","Reset content") { }
+ };
+ /**
+ * Partial content.
+ */
+ class http_status_206 : public http_status_2xx {
+ public:
+ explicit http_status_206(const string& m)
+ : http_status_2xx("206",m) { }
+ explicit http_status_206()
+ : http_status_2xx("206","Partial content") { }
+ };
+
+ /**
+ * Redirection.
+ */
+ class http_status_3xx : public http_status {
+ public:
+ explicit http_status_3xx(const string& s,const string& m)
+ : http_status(s,m) { }
+ };
+ /**
+ * Multiple choices.
+ */
+ class http_status_300 : public http_status_3xx {
+ public:
+ explicit http_status_300(const string& m)
+ : http_status_3xx("300",m) { }
+ explicit http_status_300()
+ : http_status_3xx("300","Multiple choices") { }
+ };
+ /**
+ * Moved permanently.
+ */
+ class http_status_301 : public http_status_3xx {
+ public:
+ explicit http_status_301(const string& m)
+ : http_status_3xx("301",m) { }
+ explicit http_status_301()
+ : http_status_3xx("301","Moved permanently") { }
+ };
+ /**
+ * Found.
+ */
+ class http_status_302 : public http_status_3xx {
+ public:
+ explicit http_status_302(const string& m)
+ : http_status_3xx("302",m) { }
+ explicit http_status_302()
+ : http_status_3xx("302","Found") { }
+ };
+ /**
+ * See other.
+ */
+ class http_status_303 : public http_status_3xx {
+ public:
+ explicit http_status_303(const string& m)
+ : http_status_3xx("303",m) { }
+ explicit http_status_303()
+ : http_status_3xx("303","See other") { }
+ };
+ /**
+ * Not modified.
+ */
+ class http_status_304 : public http_status_3xx {
+ public:
+ explicit http_status_304(const string& m)
+ : http_status_3xx("304",m) { }
+ explicit http_status_304()
+ : http_status_3xx("304","Not modified") { }
+ };
+ /**
+ * Use proxy.
+ */
+ class http_status_305 : public http_status_3xx {
+ public:
+ explicit http_status_305(const string& m)
+ : http_status_3xx("305",m) { }
+ explicit http_status_305()
+ : http_status_3xx("305","Use proxy") { }
+ };
+ // 306 is unused and reserved
+ /**
+ * Temporary redirect.
+ */
+ class http_status_307 : public http_status_3xx {
+ public:
+ explicit http_status_307(const string& m)
+ : http_status_3xx("307",m) { }
+ explicit http_status_307()
+ : http_status_3xx("307","Temporary redirect") { }
+ };
+
+ /**
+ * Error.
+ */
+ class http_status_4xx : public http_status {
+ public:
+ explicit http_status_4xx(const string& s,const string& m)
+ : http_status(s,m) { }
+ };
+ /**
+ * Bad request.
+ */
+ class http_status_400 : public http_status_4xx {
+ public:
+ explicit http_status_400(const string& m)
+ : http_status_4xx("400",m) { }
+ explicit http_status_400()
+ : http_status_4xx("400","Bad request") { }
+ };
+ /**
+ * Unauthorized.
+ */
+ class http_status_401 : public http_status_4xx {
+ public:
+ explicit http_status_401(const string& m)
+ : http_status_4xx("401",m) { }
+ explicit http_status_401()
+ : http_status_4xx("401","Unauthorized") { }
+ };
+ /**
+ * Payment required.
+ */
+ class http_status_402 : public http_status_4xx {
+ public:
+ explicit http_status_402(const string& m)
+ : http_status_4xx("402",m) { }
+ explicit http_status_402()
+ : http_status_4xx("402","Payment required") { }
+ };
+ /**
+ * Forbidden.
+ */
+ class http_status_403 : public http_status_4xx {
+ public:
+ explicit http_status_403(const string& m)
+ : http_status_4xx("403",m) { }
+ explicit http_status_403()
+ : http_status_4xx("403","Forbidden") { }
+ };
+ /**
+ * Not found.
+ */
+ class http_status_404 : public http_status_4xx {
+ public:
+ explicit http_status_404(const string& m)
+ : http_status_4xx("404",m) { }
+ explicit http_status_404()
+ : http_status_4xx("404","Not found") { }
+ };
+ /**
+ * Method not allowed.
+ */
+ class http_status_405 : public http_status_4xx {
+ public:
+ explicit http_status_405(const string& m)
+ : http_status_4xx("405",m) { }
+ explicit http_status_405()
+ : http_status_4xx("405","Method not allowed") { }
+ };
+ /**
+ * Not acceptable.
+ */
+ class http_status_406 : public http_status_4xx {
+ public:
+ explicit http_status_406(const string& m)
+ : http_status_4xx("406",m) { }
+ explicit http_status_406()
+ : http_status_4xx("406","Not acceptable") { }
+ };
+ /**
+ * Proxy authentication required.
+ */
+ class http_status_407 : public http_status_4xx {
+ public:
+ explicit http_status_407(const string& m)
+ : http_status_4xx("407",m) { }
+ explicit http_status_407()
+ : http_status_4xx("407","Proxy authentication required") { }
+ };
+ /**
+ * Request timeout.
+ */
+ class http_status_408 : public http_status_4xx {
+ public:
+ explicit http_status_408(const string& m)
+ : http_status_4xx("408",m) { }
+ explicit http_status_408()
+ : http_status_4xx("408","Request timeout") { }
+ };
+ /**
+ * Conflict.
+ */
+ class http_status_409 : public http_status_4xx {
+ public:
+ explicit http_status_409(const string& m)
+ : http_status_4xx("409",m) { }
+ explicit http_status_409()
+ : http_status_4xx("409","Conflict") { }
+ };
+ /**
+ * Gone.
+ */
+ class http_status_410 : public http_status_4xx {
+ public:
+ explicit http_status_410(const string& m)
+ : http_status_4xx("410",m) { }
+ explicit http_status_410()
+ : http_status_4xx("410","Gone") { }
+ };
+ /**
+ * Length required.
+ */
+ class http_status_411 : public http_status_4xx {
+ public:
+ explicit http_status_411(const string& m)
+ : http_status_4xx("411",m) { }
+ explicit http_status_411()
+ : http_status_4xx("411","Length required") { }
+ };
+ /**
+ * Precondition failed.
+ */
+ class http_status_412 : public http_status_4xx {
+ public:
+ explicit http_status_412(const string& m)
+ : http_status_4xx("412",m) { }
+ explicit http_status_412()
+ : http_status_4xx("412","Precondition failed") { }
+ };
+ /**
+ * Request entity too large.
+ */
+ class http_status_413 : public http_status_4xx {
+ public:
+ explicit http_status_413(const string& m)
+ : http_status_4xx("413",m) { }
+ explicit http_status_413()
+ : http_status_4xx("413","Request entity too large") { }
+ };
+ /**
+ * Request URI too long.
+ */
+ class http_status_414 : public http_status_4xx {
+ public:
+ explicit http_status_414(const string& m)
+ : http_status_4xx("414",m) { }
+ explicit http_status_414()
+ : http_status_4xx("414","Request URI too long") { }
+ };
+ /**
+ * Unsupported media type.
+ */
+ class http_status_415 : public http_status_4xx {
+ public:
+ explicit http_status_415(const string& m)
+ : http_status_4xx("415",m) { }
+ explicit http_status_415()
+ : http_status_4xx("415","Unsupported media type") { }
+ };
+ /**
+ * Requested range not satisfiable.
+ */
+ class http_status_416 : public http_status_4xx {
+ public:
+ explicit http_status_416(const string& m)
+ : http_status_4xx("416",m) { }
+ explicit http_status_416()
+ : http_status_4xx("416","Requested range not satisfiable") { }
+ };
+ /**
+ * Expectation failed.
+ */
+ class http_status_417 : public http_status_4xx {
+ public:
+ explicit http_status_417(const string& m)
+ : http_status_4xx("417",m) { }
+ explicit http_status_417()
+ : http_status_4xx("417","Expectation failed") { }
+ };
+
+ /**
+ * Server error.
+ */
+ class http_status_5xx : public http_status {
+ public:
+ explicit http_status_5xx(const string& s,const string& m)
+ : http_status(s,m) { }
+ };
+ /**
+ * Internal server error.
+ */
+ class http_status_500 : public http_status_5xx {
+ public:
+ explicit http_status_500(const string& m)
+ : http_status_5xx("500",m) { }
+ explicit http_status_500()
+ : http_status_5xx("500","Internal server error") { }
+ };
+ /**
+ * Not implemented.
+ */
+ class http_status_501 : public http_status_5xx {
+ public:
+ explicit http_status_501(const string& m)
+ : http_status_5xx("501",m) { }
+ explicit http_status_501()
+ : http_status_5xx("501","Not implemented") { }
+ };
+ /**
+ * Bad gateway.
+ */
+ class http_status_502 : public http_status_5xx {
+ public:
+ explicit http_status_502(const string& m)
+ : http_status_5xx("502",m) { }
+ explicit http_status_502()
+ : http_status_5xx("502","Bad gateway") { }
+ };
+ /**
+ * Service unavailable.
+ */
+ class http_status_503 : public http_status_5xx {
+ public:
+ explicit http_status_503(const string& m)
+ : http_status_5xx("503",m) { }
+ explicit http_status_503()
+ : http_status_5xx("503","Service unavailable") { }
+ };
+ /**
+ * Gateway timeout.
+ */
+ class http_status_504 : public http_status_5xx {
+ public:
+ explicit http_status_504(const string& m)
+ : http_status_5xx("504",m) { }
+ explicit http_status_504()
+ : http_status_5xx("504","Gateway timeout") { }
+ };
+ /**
+ * HTTP version not supported.
+ */
+ class http_status_505 : public http_status_5xx {
+ public:
+ explicit http_status_505(const string& m)
+ : http_status_5xx("505",m) { }
+ explicit http_status_505()
+ : http_status_5xx("505","HTTP version not supported") { }
+ };
+
+ // Aliases
+
+ typedef http_status_1xx http_status_informational;
+ typedef http_status_100 http_status_continue;
+ typedef http_status_101 http_status_switching_protocols;
+
+ typedef http_status_2xx http_status_sucessful;
+ typedef http_status_200 http_status_ok;
+ typedef http_status_201 http_status_created;
+ typedef http_status_202 http_status_accepted;
+ typedef http_status_203 http_status_non_authoritative_information;
+ typedef http_status_204 http_status_no_content;
+ typedef http_status_205 http_status_reset_content;
+ typedef http_status_206 http_status_partial_content;
+
+ typedef http_status_3xx http_status_redirection;
+ typedef http_status_300 http_status_multiple_choices;
+ typedef http_status_301 http_status_moved_permanently;
+ typedef http_status_302 http_status_found;
+ typedef http_status_303 http_status_see_other;
+ typedef http_status_304 http_status_not_modified;
+ typedef http_status_305 http_status_use_proxy;
+ // 306 is unused and reserved
+ typedef http_status_307 http_status_temporary_redirect;
+
+ typedef http_status_4xx http_status_client_error;
+ typedef http_status_400 http_status_bad_request;
+ typedef http_status_401 http_status_unauthorized;
+ typedef http_status_402 http_status_payment_required;
+ typedef http_status_403 http_status_forbidden;
+ typedef http_status_404 http_status_not_found;
+ typedef http_status_405 http_status_method_not_allowed;
+ typedef http_status_406 http_status_not_acceptable;
+ typedef http_status_407 http_status_proxy_authentication_required;
+ typedef http_status_408 http_status_request_timeout;
+ typedef http_status_409 http_status_conflict;
+ typedef http_status_410 http_status_gone;
+ typedef http_status_411 http_status_length_required;
+ typedef http_status_412 http_status_precondition_failed;
+ typedef http_status_413 http_status_request_entity_too_large;
+ typedef http_status_414 http_status_requrest_uri_too_long;
+ typedef http_status_415 http_status_unsupported_media_type;
+ typedef http_status_416 http_status_required_range_not_satisfiable;
+ typedef http_status_417 http_status_expectation_failed;
+
+ typedef http_status_5xx http_status_server_error;
+ typedef http_status_500 http_status_internal_server_error;
+ typedef http_status_501 http_status_not_implemented;
+ typedef http_status_502 http_status_bad_gateway;
+ typedef http_status_503 http_status_service_unavailable;
+ typedef http_status_504 http_status_gateway_timeout;
+ typedef http_status_505 http_status_http_version_not_supported;
+
+}
+
+#endif /* __SITECING_EXCEPTION_H */
diff --git a/include/sitecing/file_factory.h b/include/sitecing/file_factory.h
new file mode 100644
index 0000000..7ec82da
--- a/dev/null
+++ b/include/sitecing/file_factory.h
@@ -0,0 +1,64 @@
+#ifndef __SITECING_FILE_FACTORY_H
+#define __SITECING_FILE_FACTORY_H
+
+#include <string>
+#include <list>
+
+/**
+ * @file
+ * @brief the file_factory class declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * The factory class. Does the job similar to that which is done by make
+ * utility.
+ */
+ class file_factory {
+ public:
+ /**
+ * The recursion depth.
+ */
+ int depth;
+ /**
+ * The list of files type. The list of strings, in fact.
+ */
+ typedef list<string> file_list_t;
+
+ file_factory()
+ : depth(0) { }
+
+ /**
+ * Fetch depndencies for the given file.
+ * @param dst destination file.
+ * @param deps where to put dependencies to.
+ */
+ virtual void get_dependencies(const string& dst,file_list_t& deps) = 0;
+ /**
+ * Check if the destination is up to day.
+ * @param the destination file.
+ * @param deps if the deps pointer is non there, the dependencies
+ * retrieved will be stored there.
+ * @return true if yes.
+ * @see get_dependencies()
+ */
+ virtual bool is_uptodate(const string& dst,file_list_t* deps=0);
+ /**
+ * Build the file requested.
+ * @param dst the file requested.
+ */
+ virtual void build(const string& dst) = 0;
+ /**
+ * Make the file requested, which means: build it, unless it's
+ * uptodate.
+ * @see is_uptodate()
+ * @see build()
+ */
+ virtual void make(const string& dst);
+ };
+
+}
+
+#endif /* __SITECING_FILE_FACTORY_H */
diff --git a/include/sitecing/magic.h b/include/sitecing/magic.h
new file mode 100644
index 0000000..4802fcc
--- a/dev/null
+++ b/include/sitecing/magic.h
@@ -0,0 +1,63 @@
+#ifndef __SITECING_MAGIC_H
+#define __SITECING_MAGIC_H
+
+/**
+ * @file
+ * @brief The magic numbers globally defined.
+ */
+
+namespace sitecing {
+
+ /**
+ * The magic numbers enumeration.
+ */
+ enum {
+ /**
+ * There is no magic.
+ */
+ __magic_none = 0,
+ /**
+ * Here is where user-defined magic starts.
+ */
+ __user_magical_numbers_start = 1,
+ /**
+ * Here is where site-C-ing defined magic starts.
+ */
+ __sitecing_magical_numbers_start = 0x8000,
+ /**
+ * The compiler error occured. The parameters passed are:
+ *
+ * char *message, char *root_source, char *root_intermediate, char *root_so, char *component
+ */
+ __magic_compile_error,
+ /**
+ * The preprocessor error occured. The parameters passed are:
+ *
+ * char *message, char *root_source, char *root_intermediate, char *root_so, char *component,
+ * int line_number
+ */
+ __magic_preprocess_error,
+ /**
+ * Exception caught while executing the component. The parameters passed are:
+ *
+ * char *message, char *root_source, char *root_intermediate, char *root_so, char *component,
+ * const exception *exception_caught
+ */
+ __magic_generic_exception,
+ /**
+ * The component called as an action handler. The parameters passed are:
+ *
+ * char *root_source, char *root_intermediate, char *root_so, list<string>* args
+ */
+ __magic_action,
+ /**
+ * The component called as an HTTP status handler. The parameters passed are:
+ *
+ * char *root_source, char *root_intermediate, char *root_so, char *component,
+ * const http_status *http_status_caught
+ */
+ __magic_http_status
+ };
+}
+
+#endif /* __SITECING_MAGIC_H */
diff --git a/include/sitecing/process_manager.h b/include/sitecing/process_manager.h
new file mode 100644
index 0000000..73415d3
--- a/dev/null
+++ b/include/sitecing/process_manager.h
@@ -0,0 +1,89 @@
+#ifndef __SITECING_PROCESS_MANAGER_H
+#define __SITECING_PROCESS_MANAGER_H
+
+#include <sitecing/scoreboard.h>
+
+/**
+ * @file
+ * @brief the process manager.
+ */
+
+namespace sitecing {
+
+ /**
+ * The process manager.
+ */
+ class process_manager {
+ public:
+ /**
+ * Minimum number of child processes.
+ */
+ int min_children;
+ /**
+ * Maxinum number of child processes.
+ */
+ int max_children;
+ /**
+ * Minimum number of spare child processes.
+ */
+ int min_spare_children;
+ /**
+ * Maxiumum number of spare child processes.
+ */
+ int max_spare_children;
+ /**
+ * The scoreboard.
+ */
+ scoreboard sboard;
+ /**
+ * We're in the process of shutting down.
+ */
+ bool finishing;
+ /**
+ * @todo TODO: wish I could rememer -- document me.
+ */
+ bool die_humbly;
+
+ process_manager();
+ virtual ~process_manager();
+
+ /**
+ * The main loop.
+ */
+ void manage();
+
+ /**
+ * The worker function.
+ * @param the slot allocated for the process.
+ */
+ virtual void process(int slot) = 0;
+
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void manage_children();
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ bool spawn_children();
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ bool kill_children();
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void spawn_child();
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void wait_for_children(bool hang=false);
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void collect_dead_souls(bool actively=false);
+ };
+
+}
+
+#endif /* __SITECING_PROCESS_MANAGER_H */
diff --git a/include/sitecing/scoreboard.h b/include/sitecing/scoreboard.h
new file mode 100644
index 0000000..788f881
--- a/dev/null
+++ b/include/sitecing/scoreboard.h
@@ -0,0 +1,102 @@
+#ifndef __SITECING_SCOREBOARD_H
+#define __SITECING_SCOREBOARD_H
+
+#include <sys/types.h>
+
+/**
+ * @file
+ * @brief the scoreboard manager.
+ */
+
+/**
+ * @def MAX_SITECING_SCOREBOARD_SLOTS
+ * The maximum number of slots scoreboard can hold.
+ */
+#define MAX_SITECING_SCOREBOARD_SLOTS 512
+
+namespace sitecing {
+
+ /**
+ * The scoreboard slot.
+ */
+ struct scoreboard_slot {
+ /**
+ * The state enumeration.
+ */
+ enum _state {
+ /**
+ * The slot is free.
+ */
+ state_free = 0,
+ /**
+ * The slot is allocated.
+ */
+ state_allocated,
+ /**
+ * The process is idle.
+ */
+ state_idle,
+ /**
+ * The process is accepting connection.
+ */
+ state_accept,
+ /**
+ * The process is processing request.
+ */
+ state_processing
+ } state;
+ pid_t pid;
+ };
+
+ /**
+ * The scoreboard manager.
+ */
+ class scoreboard {
+ /**
+ * shared memory id.
+ */
+ int shmid;
+ public:
+ /**
+ * Pointer to the scoreboard slots.
+ */
+ scoreboard_slot *slots;
+
+ scoreboard();
+ ~scoreboard();
+
+ /**
+ * Allocate a scoreboard slot.
+ * @return the slot number.
+ */
+ int allocate_slot();
+ /**
+ * Free the slot allocated.
+ * @param slot the slot number.
+ */
+ void free_slot(int slot);
+
+ /**
+ * Get the pointer to the slot.
+ * @param slot the slot number.
+ * @return the pointer.
+ */
+ scoreboard_slot *get_slot(int slot);
+ /**
+ * Find the slot corresponding to the process ID.
+ * @param pid the process id.
+ * @return the slot number.
+ */
+ int get_slot_by_pid(pid_t pid);
+
+ /**
+ * Count the slots in the particular state.
+ * @param state the state.
+ * @return the number of slots found.
+ */
+ int count_slots(enum scoreboard_slot::_state state=scoreboard_slot::state_free);
+ };
+
+}
+
+#endif /* __SITECING_SCOREBOARD_H */
diff --git a/include/sitecing/sitecing_enflesher.h b/include/sitecing/sitecing_enflesher.h
new file mode 100644
index 0000000..ad57fb5
--- a/dev/null
+++ b/include/sitecing/sitecing_enflesher.h
@@ -0,0 +1,65 @@
+#ifndef __SITECING_SITECING_ENFLESHER_H
+#define __SITECING_SITECING_ENFLESHER_H
+
+#include <fstream>
+#include <string>
+using namespace std;
+
+/**
+ * @file
+ * @brief The preprocessed source builder.
+ */
+
+#ifndef sitecing_enflesher_flexlexer_once
+#define sitecing_enflesher_flexlexer_once
+#undef yyFlexLexer
+#define yyFlexLexer sitecing_enflesherFlexLexer
+#include <FlexLexer.h>
+#undef yyFlexLexerOnce
+#endif
+
+class sitecing_parser;
+/**
+ * The enfleshing of the skeleton file according to the in-memory parsed
+ * component source.
+ */
+class sitecing_enflesher : public sitecing_enflesherFlexLexer {
+ public:
+ /**
+ * It is time to anchor output with the #line directive.
+ */
+ bool anchor_time;
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ bool anchoraged;
+ /**
+ * The reference to the parser object containg the parsed source.
+ */
+ sitecing_parser& parser;
+ /**
+ * The output stream.
+ */
+ ofstream outs;
+
+ /**
+ * @param p The parser object containing preparsed data.
+ */
+ sitecing_enflesher(sitecing_parser& p)
+ : parser(p), anchor_time(true) { }
+
+ /**
+ * Do the job.
+ */
+ void enflesh();
+
+ virtual void LexerOutput(const char *buf,int size);
+ virtual int yylex();
+
+ /**
+ * Put a #line anchor into output.
+ */
+ void anchor();
+};
+
+#endif /* __SITECING_SITECING_ENFLESHER_H */
diff --git a/include/sitecing/sitecing_exception.h b/include/sitecing/sitecing_exception.h
new file mode 100644
index 0000000..bf475ac
--- a/dev/null
+++ b/include/sitecing/sitecing_exception.h
@@ -0,0 +1,103 @@
+#ifndef __SITECING_SITECING_EXCEPTION_H
+#define __SITECING_SITECING_EXCEPTION_H
+
+#include <konforka/exception.h>
+
+/**
+ * @file
+ * @brief The site-C-ing specific exception.
+ */
+
+namespace sitecing {
+
+ /**
+ * The component failed to compile.
+ */
+ class compile_error : public konforka::exception {
+ public:
+ /**
+ * The component path
+ */
+ string component_path;
+
+ /**
+ * @param w the message.
+ * @param cp component path.
+ */
+ compile_error(const string& w,const string& cp)
+ : konforka::exception(NOCODEPOINT,w), component_path(cp) { }
+ /**
+ * @param whe point in code.
+ * @param wha the message.
+ * @param cp component path.
+ */
+ compile_error(const string &whe,const string& wha,const string& cp)
+ : konforka::exception(whe,wha), component_path(cp) { }
+ /**
+ * @param fi the file name where the exception is thrown from.
+ * @param fu the function name where the exception originates from.
+ * @param l the line number where the exception originates from.
+ * @param cp component path.
+ */
+ compile_error(const string &fi,const string& fu,int l,const string& w,const string& cp)
+ : konforka::exception(fi,fu,l,w), component_path(cp) { }
+ ~compile_error() throw() { }
+ };
+
+ /**
+ * Failed to preprocess component source.
+ */
+ class preprocessor_error : public konforka::exception {
+ public:
+ /**
+ * Component name.
+ */
+ string component_name;
+ /**
+ * The line number of the source code where the error occured.
+ */
+ int line_number;
+
+ /**
+ * @param fi file name where the exception originates from.
+ * @param fu the function name where the exception originates from.
+ * @param l the line number where the exception originate from.
+ * @param w the error message.
+ * @param cn the component name.
+ * @param ln the line of the component source where the error occured.
+ */
+ preprocessor_error(const string& fi,const string& fu,int l,const string& w,const string& cn,int ln)
+ : konforka::exception(fi,fu,l,w), component_name(cn), line_number(ln) { }
+ /**
+ * @param fi file name where the exception originates from.
+ * @param fu the function name where the exception originates from.
+ * @param l the line number where the exception originate from.
+ * @param w the error message.
+ * @param cn the component name.
+ */
+ preprocessor_error(const string& fi,const string& fu,int l,const string& w,const string& cn)
+ : konforka::exception(fi,fu,l,w), component_name(cn), line_number(-1) { }
+ /**
+ * @param fi file name where the exception originates from.
+ * @param fu the function name where the exception originates from.
+ * @param l the line number where the exception originate from.
+ * @param w the error message.
+ * @param ln the line of the component source where the error occured.
+ */
+ preprocessor_error(const string& fi,const string& fu,int l,const string& w,int ln)
+ : konforka::exception(fi,fu,l,w), line_number(ln) { }
+ /**
+ * @param fi file name where the exception originates from.
+ * @param fu the function name where the exception originates from.
+ * @param l the line number where the exception originate from.
+ * @param w the error message.
+ */
+ preprocessor_error(const string& fi,const string& fu,int l,const string& w)
+ : konforka::exception(fi,fu,l,w), line_number(-1) { }
+
+ ~preprocessor_error() throw() {}
+ };
+
+}
+
+#endif /* __SITECING_SITECING_EXCEPTION_H */
diff --git a/include/sitecing/sitecing_interface.h b/include/sitecing/sitecing_interface.h
new file mode 100644
index 0000000..0cba2bb
--- a/dev/null
+++ b/include/sitecing/sitecing_interface.h
@@ -0,0 +1,40 @@
+#ifndef __SITECING_SITECING_INTERFACE_H
+#define __SITECING_SITECING_INTERFACE_H
+
+#include <ostream>
+
+/**
+ * @file
+ * @brief The sitecing_interface call declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * @brief the interface to site-C-ing.
+ *
+ * The basic class used to convey communications between the component and
+ * the sitecing core.
+ */
+ class sitecing_interface {
+ public:
+ /**
+ * Pointer to the output stream.
+ */
+ ostream *out;
+
+ /**
+ * The default constructor doesn't do much.
+ */
+ sitecing_interface() : out(0) {}
+ /**
+ * The constructor initializes the output stream pointer.
+ * @param o the value to initialize the output stream pointer with.
+ */
+ sitecing_interface(ostream* o) : out(o) {}
+ };
+
+}
+
+#endif /* __SITECING_SITECING_INTERFACE_H */
diff --git a/include/sitecing/sitecing_interface_cgi.h b/include/sitecing/sitecing_interface_cgi.h
new file mode 100644
index 0000000..cab947c
--- a/dev/null
+++ b/include/sitecing/sitecing_interface_cgi.h
@@ -0,0 +1,62 @@
+#ifndef __SITECING_SITECING_INTERFACE_CGI_H
+#define __SITECING_SITECING_INTERFACE_CGI_H
+
+#include <sstream>
+#include <string>
+#include <map>
+#include "kingate/cgi_gateway.h"
+#include "sitecing/sitecing_interface.h"
+#include "sitecing/sitespace.h"
+
+/**
+ * @file
+ * @brief The sitecing_interface_cgi class declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * The interface to site-C-ing core for the CGI component.
+ */
+ class sitecing_interface_cgi : public sitecing_interface {
+ public:
+ /**
+ * Pointer to the CGI gateway interface.
+ */
+ kingate::cgi_gateway* cgigw;
+ /**
+ * Type for the map of headers to spit out.
+ */
+ typedef map<string,string> headers_t;
+ /**
+ * The list of headers to spit out.
+ */
+ headers_t headers;
+ /**
+ * Here is where we prebuffer output.
+ */
+ ostringstream prebuffer;
+ /**
+ * Pointer to the sitespace object.
+ */
+ sitespace *ss; // XXX: or does it belong to the generic interface? or should this 'generic' interface exist at all?
+
+ /**
+ * @param s Pointer to the sitespace object.
+ */
+ sitecing_interface_cgi(sitespace *s);
+
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void prepare(kingate::cgi_gateway *cg);
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ void flush();
+
+ };
+}
+
+#endif /* __SITECING_SITECING_INTERFACE_CGI_H */
diff --git a/include/sitecing/sitecing_parser.h b/include/sitecing/sitecing_parser.h
new file mode 100644
index 0000000..22d716f
--- a/dev/null
+++ b/include/sitecing/sitecing_parser.h
@@ -0,0 +1,326 @@
+#ifndef __SITECING_SITECING_PARSER_H
+#define __SITECING_SITECING_PARSER_H
+
+#include <string>
+#include <list>
+#include <map>
+#include <stdexcept>
+using namespace std;
+
+#include "sitecing/component_factory.h"
+using namespace sitecing;
+
+/**
+ * @file
+ * @brief The component source parser.
+ */
+
+#ifndef sitecing_parser_flexlexer_once
+#define sitecing_parser_flexlexer_once
+#undef yyFlexLexer
+#define yyFlexLexer sitecing_parserFlexLexer
+#include <FlexLexer.h>
+#undef yyFlexLexerOnce
+#endif
+
+/**
+ * The component source parser.
+ */
+class sitecing_parser : public sitecing_parserFlexLexer {
+ public:
+ /**
+ * The ancestor class definition.
+ */
+ class ancestor_class {
+ public:
+ /**
+ * The class name.
+ */
+ string name;
+ /**
+ * The source component path.
+ */
+ string path;
+
+ /**
+ * @param n the class name.
+ * @param p the component path.
+ */
+ ancestor_class(const string& n,const string& p)
+ : name(n), path(p) { }
+ };
+ /**
+ * The list of ancestor classes.
+ */
+ typedef list<ancestor_class> ancestor_classes_t;
+ /**
+ * The ancestor classes.
+ */
+ ancestor_classes_t ancestor_classes;
+ /**
+ * The member variable definition.
+ */
+ class member_variable {
+ public:
+ /**
+ * The member variable type.
+ */
+ string type;
+ /**
+ * The member variable name.
+ */
+ string name;
+ /**
+ * The member variable is a component.
+ */
+ bool bComponent;
+ /**
+ * The variable initializer.
+ */
+ string initializer;
+ /**
+ * @todo TODO: wish I could remember -- document me.
+ */
+ bool bTypeOnly;
+
+ /**
+ * @param t type.
+ * @param n name.
+ * @param i initializer.
+ * @param bc whether it is a component.
+ * @param bto @todo TODO: @see bTypeOnly.
+ */
+ member_variable(const string& t,const string& n,const string& i,bool bc = false,bool bto = false)
+ : type(t), name(n), initializer(i), bComponent(bc), bTypeOnly(bto) { }
+ };
+ /**
+ * The list of member variables.
+ */
+ typedef list<member_variable> member_variables_t;
+ /**
+ * Member variables.
+ */
+ member_variables_t member_variables;
+ /**
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ bool have_initializers;
+ /**
+ * Whether the component has a constructor defined.
+ */
+ bool have_constructor;
+ /**
+ * Member function definition.
+ */
+ class member_function {
+ public:
+ /**
+ * Return type.
+ */
+ string type;
+ /**
+ * Function name.
+ */
+ string name;
+ /**
+ * Arguments declaration.
+ */
+ string args;
+ /**
+ * Function body.
+ */
+ string body;
+
+ /**
+ * @param t type.
+ * @param n name.
+ * @param a arguments.
+ * @param b body.
+ */
+ member_function(const string& t,const string& n,const string& a,const string& b)
+ : type(t), name(n), args(a), body(b) { }
+ };
+ /**
+ * The list of member functions.
+ */
+ typedef list<member_function> member_functions_t;
+ /**
+ * Member functions.
+ */
+ member_functions_t member_functions;
+ /**
+ * Current mode of operation.
+ */
+ class modus_operandi {
+ public:
+ /**
+ * The state enumeration.
+ */
+ enum modus_t {
+ /**
+ * Building the code.
+ */
+ modus_code = 0,
+ /**
+ * Ready to do the '<<' thing.
+ */
+ modus_preop,
+ /**
+ * Just made a '<<'.
+ */
+ modus_postop,
+ /**
+ * Outputting raw output data.
+ */
+ modus_text,
+ /**
+ * The number of modes.
+ */
+ modi
+ };
+ /**
+ * Processing flags enumeration.
+ */
+ enum {
+ /**
+ * Eat the comments.
+ */
+ flag_devour_comments = 0x0001,
+ /**
+ * Eat whitespace.
+ */
+ flag_devour_whitespace = 0x0002
+ };
+ /**
+ * The processing mode.
+ */
+ modus_t modus;
+ /**
+ * The processing flags.
+ */
+ int flags;
+ /**
+ * Output being built.
+ */
+ string output;
+ /**
+ * The type for compound modes.
+ */
+ string _type;
+ /**
+ * The last id encountered.
+ */
+ string _lastid;
+ /**
+ * The name for compound modes.
+ */
+ string _name;
+ /**
+ * The argument declaration. Obviously for member functions.
+ */
+ string _args;
+
+ /**
+ * @param flags.
+ * @see flags
+ */
+ modus_operandi(int f = 0)
+ : modus(modus_code), flags(f) { }
+
+ /**
+ * Change the processing mode.
+ */
+ void modify(modus_t m);
+
+ /**
+ * See if we're eating up whitespaces.
+ */
+ bool devour_whitespace() { return flags&flag_devour_whitespace; }
+ /**
+ * See if we're eating up the comments.
+ */
+ bool devour_comments() { return flags&flag_devour_comments; }
+ };
+ /**
+ * The modes stack type.
+ */
+ typedef list<modus_operandi> modi_operandi;
+ /**
+ * The modes stack.
+ */
+ modi_operandi modi;
+ /**
+ * Input file name.
+ */
+ string input_file;
+ /**
+ * Base class name.
+ */
+ string base_class;
+ /**
+ * Base class header.
+ */
+ string base_header;
+ /**
+ * Component's basename.
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ string component_basename;
+ /**
+ * The skeleton file name.
+ */
+ string skeleton;
+ /**
+ * The component class name.
+ */
+ string class_name;
+ /**
+ * Output basename.
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ string output_basename;
+ /**
+ * Verbatim declaration part.
+ */
+ string decl;
+ /**
+ * Verbatim implementation part.
+ */
+ string impl;
+ /**
+ * The reference to the component factory object.
+ */
+ component_factory& factory;
+
+ /**
+ * @param f the component factory.
+ */
+ sitecing_parser(component_factory& f);
+
+ /**
+ * Preprocess file.
+ * @param in input file name.
+ */
+ void preprocess(const string& in);
+
+ virtual void LexerOutput(const char *buf,int size);
+ virtual int yylex();
+
+ /**
+ * Retrieve reference to the to of the modes stack.
+ * @return the reference in question.
+ */
+ modus_operandi& M() {
+ return modi.front();
+ }
+ /**
+ * Anchor the output with the #line, if we're not in the text output mode.
+ */
+ void soft_anchor();
+ /**
+ * Anchor the output with the #line directive, changing to the appropriate output mode if needed.
+ */
+ void anchor();
+};
+
+#endif /* __SITECING_SITECING_PARSER_H */
diff --git a/include/sitecing/sitecing_util.h b/include/sitecing/sitecing_util.h
new file mode 100644
index 0000000..d1a6c4a
--- a/dev/null
+++ b/include/sitecing/sitecing_util.h
@@ -0,0 +1,341 @@
+#ifndef __SITECING_SITECING_UTIL_H
+#define __SITECING_SITECING_UTIL_H
+
+#include <sys/types.h>
+#include <string>
+#include <konforka/exception.h>
+
+/**
+ * @file
+ * @brief utility classes and functions.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * Base class for utility exceptions.
+ */
+ class utility_error : public konforka::exception {
+ public:
+ utility_error(const string& fi,const string& fu,int l,const string& w)
+ : konforka::exception(fi,fu,l,w) { }
+ };
+ /**
+ * Restricted sequence encountered.
+ */
+ class utility_restricted_sequence : public utility_error {
+ public:
+ utility_restricted_sequence(const string& fi,const string& fu,int l,const string& w)
+ : utility_error(fi,fu,l,w) { }
+ };
+ /**
+ * No prefix or suffix found to strip out.
+ */
+ class utility_no_affix : public utility_error {
+ public:
+ utility_no_affix(const string& fi,const string& fu,int l,const string& w)
+ : utility_error(fi,fu,l,w) { }
+ };
+ /**
+ * No prefix to strip found.
+ */
+ class utility_no_prefix : public utility_no_affix {
+ public:
+ utility_no_prefix(const string& fi,const string& fu,int l,const string& w)
+ : utility_no_affix(fi,fu,l,w) { }
+ };
+ /**
+ * No suffix to strip found.
+ */
+ class utility_no_suffix : public utility_no_affix {
+ public:
+ utility_no_suffix(const string& fi,const string& fu,int l,const string& w)
+ : utility_no_affix(fi,fu,l,w) { }
+ };
+
+ /**
+ * Went up beyond root.
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ class utility_beyond_root : public utility_error {
+ public:
+ utility_beyond_root(const string& fi,const string& fu,int l,const string& w)
+ : utility_error(fi,fu,l,w) { }
+ };
+
+ /**
+ * The file lock object. Released at the object destruction.
+ */
+ class file_lock {
+ public:
+ /**
+ * The file descriptor.
+ */
+ int fd;
+
+ file_lock()
+ : fd(-1) { }
+ /**
+ * @param f file name.
+ */
+ file_lock(const string& f)
+ : fd(-1) { lock(f); }
+ ~file_lock() { unlock(); }
+
+ /**
+ * Do lock.
+ * @param f file name.
+ */
+ void lock(const string& f);
+ /**
+ * @todo TODO: wish I could remember the details -- document me.
+ */
+ void lock();
+ /**
+ * Release the lock obtained.
+ */
+ void unlock();
+ };
+
+ /**
+ * The pid file. Removed at object destruction.
+ */
+ class pid_file {
+ public:
+ /**
+ * The file name.
+ */
+ string file_name;
+ /**
+ * Do we unlink the file after we're done?
+ */
+ bool unlink_pid;
+
+ pid_file()
+ : unlink_pid(false) { }
+ ~pid_file() { unlink(); }
+
+ /**
+ * @param f file name.
+ * @param u whether we want to unlink the file.
+ */
+ void set(const string& f,bool u=true);
+ /**
+ * Unlink the file if we wanted to in the first place.
+ */
+ void unlink();
+ };
+
+ /**
+ * The semaphore object.
+ */
+ class semaphore {
+ public:
+ /**
+ * The semaphore id.
+ */
+ int semid;
+
+ semaphore()
+ : semid(-1) { }
+ /**
+ * @param sid semaphore id.
+ */
+ semaphore(int sid)
+ : semid(sid) { }
+ ~semaphore() {
+ deinit();
+ }
+
+ /**
+ * Init semaphore.
+ */
+ void init();
+ /**
+ * Undo the init.
+ */
+ void deinit();
+
+ /**
+ * Semaphore on.
+ */
+ void on();
+ /**
+ * Semaphore off.
+ */
+ void off();
+ };
+
+ /**
+ * The semaphor lock object, released at object destruction.
+ */
+ class semaphore_lock {
+ public:
+ /**
+ * Pointer to the semaphore we're operating on.
+ */
+ semaphore* sem;
+ /**
+ * Whether it is locked.
+ */
+ bool locked;
+
+ semaphore_lock()
+ : sem(NULL), locked(false) {}
+ /**
+ * @param s pointer to the semaphore.
+ * @param l lock at creation?
+ */
+ semaphore_lock(semaphore* s,bool l=true)
+ : sem(s), locked(false) {
+ if(l) lock();
+ }
+ /**
+ * @param s reference to the semaphore.
+ * @param l lock at creation?
+ */
+ semaphore_lock(semaphore& s,bool l=true)
+ : sem(&s), locked(false) {
+ if(l) lock();
+ }
+
+ ~semaphore_lock() {
+ unlock();
+ }
+
+ /**
+ * Lock it.
+ */
+ void lock();
+ /**
+ * Unlock it.
+ */
+ void unlock();
+ };
+
+ /**
+ * normalize_path options enumeration.
+ * @see normalize_path()
+ */
+ enum normalize_path_options {
+ /**
+ * Restrict the /../ sequence.
+ */
+ restrict_dotdot = 1,
+ /**
+ * Strip out the leading slash.
+ */
+ strip_leading_slash = 2,
+ /**
+ * Strip out the trailing slash.
+ */
+ strip_trailing_slash = 4
+ };
+ /**
+ * combine_path options enumeration.
+ * @see combine_path()
+ */
+ enum combine_path_options {
+ /**
+ * The origin is file. Otherwise it is directory.
+ */
+ origin_is_file = 1,
+ /**
+ * Fail if we've gone up beyond root.
+ */
+ fail_beyond_root = 2
+ };
+
+ /**
+ * Normalize pathname by stripping duplicate slashes, etc.
+ * @param path the path name.
+ * @param opts options.
+ * @return the normalized path.
+ * @see normalize_path_options
+ * @todo TODO: document exceptions.
+ */
+ string normalize_path(const string& path,int opts=(restrict_dotdot|strip_trailing_slash));
+ /**
+ * Strip prefix from the string.
+ * @param str the string.
+ * @param prefix prefix to strip.
+ * @return the string without prefix.
+ * @todo TODO: document exceptions.
+ */
+ string strip_prefix(const string& str,const string& prefix);
+ /**
+ * Strip suffix from the string.
+ * @param str the string.
+ * @param suffix suffix to strip.
+ * @return the string without suffix.
+ * @todo TODO: document exceptions.
+ */
+ string strip_suffix(const string& str,const string& suffix);
+ /**
+ * Get the directory part of the filename.
+ * @param filename the full file name.
+ * @return the directory part.
+ */
+ string dir_name(const string& filename);
+ /**
+ * Combine path with the relative path.
+ * @param origin the origin.
+ * @param relative relative path to combine origin with.
+ * @param opts options.
+ * @return the pathc combined.
+ * @see combine_path_options
+ * @todo TODO: document exceptions.
+ */
+ string combine_path(const string& origin,const string& relative,int opts=origin_is_file);
+
+ /**
+ * Create directory and parent directories if needed.
+ * @param path the pathname.
+ * @param mode the mode for newly created directories.
+ */
+ void make_path(const string& path,mode_t mode);
+
+ /**
+ * Change to the directory and pop back at object's destruction (e.g. when
+ * the object goes out of scope).
+ */
+ class auto_chdir {
+ public:
+ /**
+ * Saved working directory.
+ */
+ string saved_pwd;
+ /**
+ * Whether we want to change back automatically.
+ */
+ bool autopop;
+
+ auto_chdir()
+ : autopop(false) { }
+ /**
+ * @param td destination path.
+ * @param ap automatically come back?
+ */
+ auto_chdir(const string& td,bool ap=true)
+ : autopop(false) { pushdir(td,ap); }
+ ~auto_chdir() {
+ if(autopop)
+ popdir();
+ }
+
+ /**
+ * Change into directory.
+ * @param td the directory.
+ * @param ap automaticall pop back?
+ */
+ void pushdir(const string& td,bool ap=true);
+ /**
+ * Change to the saved directory.
+ */
+ void popdir();
+ };
+
+}
+
+#endif /* __SITECING_SITECING_UTIL_H */
diff --git a/include/sitecing/sitespace.h b/include/sitecing/sitespace.h
new file mode 100644
index 0000000..38fafe4
--- a/dev/null
+++ b/include/sitecing/sitespace.h
@@ -0,0 +1,76 @@
+#ifndef __SITECING_SITESPACE_H
+#define __SITECING_SITESPACE_H
+
+#include <string>
+#include <map>
+#include <list>
+#include "sitecing/component_factory.h"
+#include "sitecing/component_so.h"
+#include "sitecing/configuration.h"
+
+/**
+ * @file
+ * @brief The sitespace class declaration.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * The class responsible for handling the whole environment (as far as I can
+ * remember).
+ */
+ class sitespace {
+ public:
+ /**
+ * The type for the map of components from the component name/path
+ * to the loaded component objects.
+ */
+ typedef map<string,component_so*> components_t;
+ /**
+ * The type for listing the components.
+ */
+ typedef list<component_so*> sentenced_t;
+ /**
+ * The main configuration object.
+ */
+ configuration& config;
+ /**
+ * The components producing factory.
+ */
+ component_factory factory;
+ /**
+ * The components loaded.
+ */
+ components_t components;
+ /**
+ * The list of components sentenced to death.
+ */
+ sentenced_t sentenced;
+
+ /**
+ * Create an object in accordance with the configuration parsed.
+ * @param c the coniguration container.
+ */
+ sitespace(configuration& c);
+ ~sitespace();
+
+ /**
+ * Fetch the component, providing it with the interface object
+ * pointer.
+ * @param c the component name.
+ * @param scif the interface object.
+ * @return the component fetches.
+ */
+ so_component fetch(const string& c,sitecing_interface* scif);
+
+ private:
+ /**
+ * Execute the death sentence as much as we can.
+ */
+ void execute_sentenced();
+ };
+
+}
+
+#endif /* __SITECING_SITESPACE_H */
diff --git a/include/sitecing/util.h b/include/sitecing/util.h
new file mode 100644
index 0000000..5750ab6
--- a/dev/null
+++ b/include/sitecing/util.h
@@ -0,0 +1,148 @@
+#ifndef __SITECING_UTIL_H
+#define __SITECING_UTIL_H
+
+#include <ostream>
+#include <string>
+#include "sitecing/acomponent.h"
+
+/**
+ * @file
+ * @brief more or less non-internal utility classes and functions.
+ */
+
+namespace sitecing {
+ using namespace std;
+
+ /**
+ * the html_escape options enumeration.
+ */
+ enum html_escape_options {
+ /**
+ * Turn spaces into &nbsp;
+ */
+ html_escape_nbsp = 0x0001,
+ /**
+ * Turn newlines into <br/> or <br>.
+ */
+ html_escape_br = 0x0002,
+ /**
+ * Turn quotes to &quot;
+ */
+ html_escape_quot = 0x0004,
+ /**
+ * Do not put '/' into <br/> consruct.
+ */
+ html_escape_br_noslash = 0x0008
+ };
+ /**
+ * Escape string suitable for html output.
+ * @param str the string.
+ * @param flags options.
+ * @return the string escaped.
+ * @see html_escape_options
+ */
+ string html_escape(const string& str,int flags=html_escape_br);
+
+ /**
+ * The output string checkpoint object, letting one to rollback output.
+ */
+ class checkpoint {
+ public:
+ /**
+ * The object's death will enumeration.
+ */
+ enum will_t {
+ /**
+ * The stream is to be rolled back at object destruction.
+ */
+ will_rollback,
+ /**
+ * The stream is not to be rolled back at object destruction.
+ */
+ will_commit,
+ /**
+ * The object will die intestate. What's the point then?
+ */
+ will_intestate
+ };
+ /**
+ * The output stream in question.
+ */
+ ostream* stream;
+ /**
+ * The point at which objhect was created.
+ */
+ ostream::pos_type point;
+ /**
+ * The last will.
+ */
+ will_t last_will;
+
+ /**
+ * @param s reference to the stream.
+ * @param lw the last will.
+ */
+ checkpoint(ostream& s, will_t lw=will_rollback)
+ : stream(&s), last_will(lw) { set(); }
+ /**
+ * @param s pointer to the stream.
+ * @param lw the last will.
+ */
+ checkpoint(ostream* s, will_t lw=will_rollback)
+ : stream(s), last_will(lw) { set(); }
+ /**
+ * @param s reference to the sitecing interface where to get output
+ * stream from.
+ * @param lw the last will.
+ */
+ checkpoint(sitecing_interface& s, will_t lw=will_rollback)
+ : stream(s.out), last_will(lw) { set(); }
+ /**
+ * @param s pointer to the sitecing interface where to get output
+ * stream from.
+ * @param lw the last will.
+ */
+ checkpoint(sitecing_interface* s, will_t lw=will_rollback)
+ : stream(s->out), last_will(lw) { set(); }
+ /**
+ * @param c reference to the component from which the output stream
+ * is obtained.
+ * @param lw the last will.
+ */
+ checkpoint(acomponent& c, will_t lw=will_rollback)
+ : stream(c.__SCIF->out), last_will(lw) { set(); }
+ /**
+ * @param c pointer to the component from which the output stream is
+ * obtained.
+ * @param lw the last will.
+ */
+ checkpoint(acomponent* c, will_t lw=will_rollback)
+ : stream(c->__SCIF->out), last_will(lw) { set(); }
+ ~checkpoint() {
+ if(last_will==will_rollback)
+ rollback();
+ }
+
+ /**
+ * Set the possible rolback point to the current position in stream.
+ */
+ void set();
+ /**
+ * Make or change will.
+ */
+ void make_will(will_t lw);
+ /**
+ * Rollback the output made so far. In case of rollback will
+ * change to intestate.
+ */
+ void rollback();
+ /**
+ * Commit output so far. In case of rollback will, change to
+ * intestate.
+ */
+ void commit();
+ };
+
+}
+
+#endif /* __SITECING_UTIL_H */