From ce1f37aae46ea95020d7b865f7a80e8abdfad0d8 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Sat, 29 Jan 2005 21:21:05 +0000 Subject: initial commit into repository --- (limited to 'include') diff --git a/include/.gitignore b/include/.gitignore new file mode 100644 index 0000000..3dda729 --- a/dev/null +++ b/include/.gitignore @@ -0,0 +1,2 @@ +Makefile.in +Makefile diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..88148d5 --- a/dev/null +++ b/include/Makefile.am @@ -0,0 +1,18 @@ +# TODO: separate installable headers from internals +# but to make it sensible one need to elimitate +# abnoxious sitecing_interface_cgi.h inclusion of +# sitespace.h +nobase_include_HEADERS = \ + sitecing/acomponent.h sitecing/cgi_component.h \ + sitecing/component_so.h \ + sitecing/file_factory.h sitecing/component_factory.h \ + sitecing/sitecing_interface.h sitecing/sitecing_interface_cgi.h \ + sitecing/sitecing_parser.h sitecing/sitecing_enflesher.h \ + sitecing/sitespace.h \ + sitecing/configuration.h \ + sitecing/magic.h sitecing/util.h \ + sitecing/exception.h sitecing/sitecing_exception.h \ + sitecing/sitecing_util.h \ + sitecing/process_manager.h \ + sitecing/scoreboard.h + 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 +#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 +#include +#include +#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& 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 +#include +#include +#include +#include +#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 used_chickens_t; + /** + * The type for storing the list of unused instances. + */ + typedef list 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 + 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(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 +#include +#include +#include +#include +#include + +/** + * @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 cpp_flags; + /** + * The flags to pass to linker. + */ + list 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 intermediate_deps; + /** + * Enforced depencies for .so objects. + */ + list 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 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_handlers_t; + /** + * The list of action handlers. + */ + action_handlers_t action_handlers; + /** + * Type for the map of HTTP status handler components. + */ + typedef map http_status_handlers_t; + /** + * The map of HTTP status handler components. + */ + http_status_handlers_t http_status_handlers; + /** + * Files to be built automatically. + */ + list 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 specs_t; + /** + * The local config options map. + */ + specs_t specs; + typedef map 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 +#include + +/** + * @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 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* 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 + +/** + * @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 + +/** + * @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 +#include +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 +#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 + +/** + * @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 + +/** + * @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 +#include +#include +#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 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 +#include +#include +#include +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 +#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_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_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_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 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 +#include +#include + +/** + * @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 +#include +#include +#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 components_t; + /** + * The type for listing the components. + */ + typedef list 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 +#include +#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   + */ + html_escape_nbsp = 0x0001, + /** + * Turn newlines into
or
. + */ + html_escape_br = 0x0002, + /** + * Turn quotes to " + */ + html_escape_quot = 0x0004, + /** + * Do not put '/' into
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 */ -- cgit v0.9.0.2