aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-12-27 15:23:31 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-12-27 15:23:31 +0000
commit0eb0172c3c3cea2981ed728653cee127130e3177 (patch)
tree17f810c06291dd54a7d416c8c89a3815f48198ae
parent2275d0b9ebeda6a1edffb3f1f38d3b3af7c9c8a3 (diff)
downloadrspamd-0eb0172c3c3cea2981ed728653cee127130e3177.tar.gz
rspamd-0eb0172c3c3cea2981ed728653cee127130e3177.zip
Initial implementation of documentation strings in rspamd
-rw-r--r--src/libserver/cfg_file.h1
-rw-r--r--src/libserver/cfg_rcl.c82
-rw-r--r--src/libserver/cfg_rcl.h31
-rw-r--r--src/libserver/cfg_utils.c4
4 files changed, 112 insertions, 6 deletions
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index 3db5233df..929f8a78d 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -270,6 +270,7 @@ struct rspamd_config {
GList *workers; /**< linked list of all workers params */
GHashTable *wrk_parsers; /**< hash for worker config parsers, indexed by worker quarks */
ucl_object_t *rcl_obj; /**< rcl object */
+ ucl_object_t *doc_strings; /**< documentation strings for config options */
GHashTable * metrics; /**< hash of metrics indexed by metric name */
GList * metrics_list; /**< linked list of metrics */
GHashTable * metrics_symbols; /**< hash table of metrics indexed by symbol */
diff --git a/src/libserver/cfg_rcl.c b/src/libserver/cfg_rcl.c
index bff732c4f..aa5c91864 100644
--- a/src/libserver/cfg_rcl.c
+++ b/src/libserver/cfg_rcl.c
@@ -61,6 +61,7 @@ struct rspamd_rcl_section {
struct rspamd_rcl_default_handler_data *default_parser; /**< generic parsing fields */
rspamd_rcl_section_fin_t fin; /** called at the end of section parsing */
gpointer fin_ud;
+ ucl_object_t *doc_ref; /**< reference to the section's documentation */
};
struct rspamd_worker_param_key {
@@ -1214,6 +1215,7 @@ rspamd_rcl_add_section (struct rspamd_rcl_section **top,
enum ucl_type type, gboolean required, gboolean strict_type)
{
struct rspamd_rcl_section *new;
+ ucl_object_t *parent_doc;
new = g_slice_alloc0 (sizeof (struct rspamd_rcl_section));
new->name = name;
@@ -1222,6 +1224,43 @@ rspamd_rcl_add_section (struct rspamd_rcl_section **top,
new->type = type;
new->strict_type = strict_type;
+ if (*top == NULL) {
+ parent_doc = NULL;
+ new->doc_ref = NULL;
+ }
+ else {
+ parent_doc = (*top)->doc_ref;
+ new->doc_ref = new->doc_ref = rspamd_rcl_add_doc_obj (parent_doc,
+ NULL,
+ name,
+ type,
+ NULL,
+ 0);
+ }
+
+ HASH_ADD_KEYPTR (hh, *top, new->name, strlen (new->name), new);
+ return new;
+}
+
+struct rspamd_rcl_section *
+rspamd_rcl_add_section_doc (struct rspamd_rcl_section **top,
+ const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
+ enum ucl_type type, gboolean required, gboolean strict_type,
+ ucl_object_t *doc_target,
+ const gchar *doc_string)
+{
+ struct rspamd_rcl_section *new;
+
+ new = g_slice_alloc0 (sizeof (struct rspamd_rcl_section));
+ new->name = name;
+ new->key_attr = key_attr;
+ new->handler = handler;
+ new->type = type;
+ new->strict_type = strict_type;
+
+ new->doc_ref = rspamd_rcl_add_doc_obj (doc_target, doc_string,
+ name, type, NULL, 0);
+
HASH_ADD_KEYPTR (hh, *top, new->name, strlen (new->name), new);
return new;
}
@@ -1242,6 +1281,11 @@ rspamd_rcl_add_default_handler (struct rspamd_rcl_section *section,
new->pd.offset = offset;
new->pd.flags = flags;
+ if (section->doc_ref != NULL) {
+ rspamd_rcl_add_doc_obj (section->doc_ref, doc_string, name, UCL_NULL,
+ handler, flags);
+ }
+
HASH_ADD_KEYPTR (hh, section->default_parser, new->key, strlen (
new->key), new);
return new;
@@ -2804,3 +2848,41 @@ rspamd_config_read (struct rspamd_config *cfg, const gchar *filename,
return TRUE;
}
+
+ucl_object_t *
+rspamd_rcl_add_doc_obj (ucl_object_t *doc_target,
+ const char *doc_string,
+ const char *doc_name,
+ ucl_type_t type,
+ rspamd_rcl_default_handler_t handler,
+ gint flags)
+{
+ ucl_object_t *doc_obj;
+
+ if (doc_target == NULL || doc_name == NULL) {
+ return NULL;
+ }
+
+ doc_obj = ucl_object_typed_new (UCL_OBJECT);
+
+ /* Insert doc string itself */
+ if (doc_string) {
+ ucl_object_insert_key (doc_obj, ucl_object_fromstring (doc_string),
+ "data", 0, false);
+ }
+ else {
+ ucl_object_insert_key (doc_obj, ucl_object_fromstring ("undocumented"),
+ "data", 0, false);
+ }
+
+ if (type != UCL_NULL) {
+ ucl_object_insert_key (doc_obj,
+ ucl_object_fromstring (ucl_object_type_to_string (type)),
+ "type", 0, false);
+ }
+
+ /* TODO: add type from handler */
+ ucl_object_insert_key (doc_target, doc_obj, doc_name, 0, true);
+
+ return doc_obj;
+}
diff --git a/src/libserver/cfg_rcl.h b/src/libserver/cfg_rcl.h
index d7b1c0de2..43f240157 100644
--- a/src/libserver/cfg_rcl.h
+++ b/src/libserver/cfg_rcl.h
@@ -118,11 +118,20 @@ struct rspamd_rcl_default_handler_data *rspamd_rcl_add_default_handler (
* @param strict_type turn on strict check for types for this section
* @return newly created structure
*/
-struct rspamd_rcl_section * rspamd_rcl_add_section (
- struct rspamd_rcl_section **top,
- const gchar *name, const gchar *key_attr,
- rspamd_rcl_handler_t handler,
- enum ucl_type type, gboolean required, gboolean strict_type);
+struct rspamd_rcl_section *rspamd_rcl_add_section (
+ struct rspamd_rcl_section **top,
+ const gchar *name, const gchar *key_attr,
+ rspamd_rcl_handler_t handler,
+ enum ucl_type type, gboolean required, gboolean strict_type);
+
+struct rspamd_rcl_section *rspamd_rcl_add_section_doc (
+ struct rspamd_rcl_section **top,
+ const gchar *name, const gchar *key_attr,
+ rspamd_rcl_handler_t handler,
+ enum ucl_type type, gboolean required,
+ gboolean strict_type,
+ ucl_object_t *doc_target,
+ const gchar *doc_string);
/**
* Init common sections known to rspamd
@@ -337,4 +346,16 @@ void rspamd_rcl_register_worker_option (struct rspamd_config *cfg,
*/
void rspamd_rcl_register_worker_parser (struct rspamd_config *cfg, gint type,
gboolean (*func)(ucl_object_t *, gpointer), gpointer ud);
+
+/**
+ * Adds new documentation object to the configuration
+ * @param doc_target target object where to insert documentation (top object is used if this is NULL)
+ * @param doc_object documentation object to insert
+ */
+ucl_object_t* rspamd_rcl_add_doc_obj (ucl_object_t *doc_target,
+ const char *doc_string,
+ const char *doc_name,
+ ucl_type_t type,
+ rspamd_rcl_default_handler_t handler,
+ gint flags);
#endif /* CFG_RCL_H_ */
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index 185c28adb..a3d801939 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -200,6 +200,7 @@ rspamd_config_new (void)
cfg->cache = rspamd_symbols_cache_new (cfg);
cfg->ups_ctx = rspamd_upstreams_library_init ();
cfg->re_cache = rspamd_re_cache_new ();
+ cfg->doc_strings = ucl_object_typed_new (UCL_OBJECT);
REF_INIT_RETAIN (cfg, rspamd_config_free);
@@ -210,7 +211,8 @@ void
rspamd_config_free (struct rspamd_config *cfg)
{
rspamd_map_remove_all (cfg);
- ucl_obj_unref (cfg->rcl_obj);
+ ucl_object_unref (cfg->rcl_obj);
+ ucl_object_unref (cfg->doc_strings);
g_hash_table_remove_all (cfg->metrics);
g_hash_table_unref (cfg->metrics);
g_hash_table_unref (cfg->c_modules);