-#define CF_PARSER(n,p,f,c) { .cls = CC_PARSER, .name = n, .number = c, .ptr = p, .u.par = (cf_parser*) f }
-#define CF_SECTION(n,p,s) { .cls = CC_SECTION, .name = n, .number = 1, .ptr = p, .u.sec = s }
-#define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,clist*), .u.sec = s }
-#define CF_BITMAP_INT(n,p) { .cls = CC_BITMAP, .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*) }
-#define CF_BITMAP_LOOKUP(n,p,t) { .cls = CC_BITMAP, .type = CT_LOOKUP, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*), .u.lookup = t }
-/* Configuration items for basic types */
-#define CF_INT(n,p) CF_STATIC(n,p,INT,int,1)
-#define CF_INT_ARY(n,p,c) CF_STATIC(n,p,INT,int,c)
-#define CF_INT_DYN(n,p,c) CF_DYNAMIC(n,p,INT,int,c)
-#define CF_UNS(n,p) CF_STATIC(n,p,INT,uns,1)
-#define CF_UNS_ARY(n,p,c) CF_STATIC(n,p,INT,uns,c)
-#define CF_UNS_DYN(n,p,c) CF_DYNAMIC(n,p,INT,uns,c)
-#define CF_U64(n,p) CF_STATIC(n,p,U64,u64,1)
-#define CF_U64_ARY(n,p,c) CF_STATIC(n,p,U64,u64,c)
-#define CF_U64_DYN(n,p,c) CF_DYNAMIC(n,p,U64,u64,c)
-#define CF_DOUBLE(n,p) CF_STATIC(n,p,DOUBLE,double,1)
-#define CF_DOUBLE_ARY(n,p,c) CF_STATIC(n,p,DOUBLE,double,c)
-#define CF_DOUBLE_DYN(n,p,c) CF_DYNAMIC(n,p,DOUBLE,double,c)
-#define CF_IP(n,p) CF_STATIC(n,p,IP,u32,1)
-#define CF_IP_ARY(n,p,c) CF_STATIC(n,p,IP,u32,c)
-#define CF_IP_DYN(n,p,c) CF_DYNAMIC(n,p,IP,u32,c)
+#define CF_PARSER(n,p,f,c) { .cls = CC_PARSER, .name = n, .number = c, .ptr = p, .u.par = (cf_parser*) f } /** A low-level parser. **/
+#define CF_SECTION(n,p,s) { .cls = CC_SECTION, .name = n, .number = 1, .ptr = p, .u.sec = s } /** A sub-section. **/
+#define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,clist*), .u.sec = s } /** A list with sub-items. **/
+#define CF_BITMAP_INT(n,p) { .cls = CC_BITMAP, .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*) } /** A bitmap. **/
+#define CF_BITMAP_LOOKUP(n,p,t) { .cls = CC_BITMAP, .type = CT_LOOKUP, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*), .u.lookup = t } /** A bitmap with named bits. **/
+/***
+ * Basic configuration items
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * They describe basic data types used in the configuration. This should be enough for
+ * most real-life purposes.
+ *
+ * The parameters are as follows:
+ *
+ * * @n -- name of the item.
+ * * @p -- pointer to the variable where it shall be stored.
+ * * @c -- count.
+ **/
+#define CF_INT(n,p) CF_STATIC(n,p,INT,int,1) /** Single `int` value. **/
+#define CF_INT_ARY(n,p,c) CF_STATIC(n,p,INT,int,c) /** Static array of integers. **/
+#define CF_INT_DYN(n,p,c) CF_DYNAMIC(n,p,INT,int,c) /** Dynamic array of integers. **/
+#define CF_UNS(n,p) CF_STATIC(n,p,INT,uns,1) /** Single `uns` (`unsigned`) value. **/
+#define CF_UNS_ARY(n,p,c) CF_STATIC(n,p,INT,uns,c) /** Static array of unsigned integers. **/
+#define CF_UNS_DYN(n,p,c) CF_DYNAMIC(n,p,INT,uns,c) /** Dynamic array of unsigned integers. **/
+#define CF_U64(n,p) CF_STATIC(n,p,U64,u64,1) /** Single unsigned 64bit integer (`u64`). **/
+#define CF_U64_ARY(n,p,c) CF_STATIC(n,p,U64,u64,c) /** Static array of u64s. **/
+#define CF_U64_DYN(n,p,c) CF_DYNAMIC(n,p,U64,u64,c) /** Dynamic array of u64s. **/
+#define CF_DOUBLE(n,p) CF_STATIC(n,p,DOUBLE,double,1) /** Single instance of `double`. **/
+#define CF_DOUBLE_ARY(n,p,c) CF_STATIC(n,p,DOUBLE,double,c) /** Static array of doubles. **/
+#define CF_DOUBLE_DYN(n,p,c) CF_DYNAMIC(n,p,DOUBLE,double,c) /** Dynamic array of doubles. **/
+#define CF_IP(n,p) CF_STATIC(n,p,IP,u32,1) /** Single IPv4 address. **/
+#define CF_IP_ARY(n,p,c) CF_STATIC(n,p,IP,u32,c) /** Static array of IP addresses. **/.
+#define CF_IP_DYN(n,p,c) CF_DYNAMIC(n,p,IP,u32,c) /** Dynamic array of IP addresses. **/
+/**
+ * A string.
+ * You provide a pointer to a `char *` variable and it will fill it with
+ * dynamically allocated string. For example:
+ *
+ * static char *string = "Default string";
+ *
+ * static struct cf_section section = {
+ * CF_ITEMS {
+ * CF_STRING("string", &string),
+ * CF_END
+ * }
+ * };
+ **/