/ story-22-Docstrings.org
story-22-Docstrings.org
  1  #+TITLE: Story 22 - Docstrings
  2  #+OPTIONS: author:nil date:nil
  3  #+LANGUAGE: en
  4  #+CATEGORY: core
  5  
  6  Docstrings are present in certain programming languages, such as Common Lisp
  7  and Python.  C doesn't have that concept, but C libraries can certainly
  8  implement them, and applications could use them in diverse ways!
  9  
 10  In Le'Sec Core, there are the items where it would be obvious to add
 11  docstrings:
 12  
 13  - plugins
 14  - data sets
 15  - parameter descriptors.
 16  
 17  Another thing that needs to be considered is how the docstrings are to be made
 18  available.  The obvious choices are:
 19  For all those cases, there's a question revolving around how to make a
 20  docstring available.  There are essentially two ways:
 21  
 22  - make the docstring directly available (i.e. a ~const char *~).
 23  - make the docstring available through a function call.
 24  
 25  Exploring this in more depth:
 26  
 27  - Plugins ::
 28  
 29    There isn't much that Le'Sec Core can do here, since all the parts of
 30    plugins are handled by the calling application.  The only thing that Le'Sec
 31    Core can do is to recommend a symbol name for it in dynamically loadable
 32    plugins, alongside ~LSC_plugin_start~ and ~LSC_plugin_stop~, perhaps this,
 33    for example:
 34  
 35    ~LSC_plugin_docstring~
 36  
 37    - as a constant string pointer:
 38  
 39      #+begin_src C
 40        LSC_EXPORT const char LSC_plugin_docstring[];
 41      #+end_src
 42  
 43    - as a function passing back the docstring:
 44  
 45      #+begin_src C
 46        LSC_EXPORT LE_STATUS LSC_plugin_docstring(const char **docs);
 47      #+end_src
 48  
 49  - Data Sets ::
 50  
 51    Every Data Set (Object, Operation, ...) could potentially be documented with
 52    docstrings.
 53  
 54    - as a constant string pointer:
 55  
 56      That's an added field in the Data Set structure itself.  This would be
 57      fine, but it has consequences, most of all on the registration functions,
 58      which will have to have another argument for the docstring:
 59  
 60      #+begin_src C
 61        typedef LE_STATUS LSC_do_all_{name}_implementation_callback_fn
 62          (const char *class, const char *id,
 63           const LSC_plugin_t *plugin, const LSC_env_t *env,
 64           LSC_{name}_dispatch_fn *dispatch_function,
 65           LSC_{name}_destroy_fn *destroy_function,
 66           const void *dispatch_data,
 67           const char *docstring,       /* <-- Added argument */
 68           void *user_arg);
 69        static inline LE_STATUS LSC_register_{name}_implementation
 70          (LSC_env_t *env, LSC_plugin_t *plugin, const char *id,
 71           LSC_{name}_dispatch_fn *dispatch_function,
 72           LSC_{name}_destroy_fn *destroy_function,
 73           const void *dispatch_data,
 74           const char *docstring);      /* <-- Added argument */
 75        static inline LE_STATUS LSC_deregister_{name}_implementation
 76          (LSC_env_t *env, LSC_plugin_t *plugin, const char *id,
 77           LSC_{name}_dispatch_fn *dispatch_function,
 78           LSC_{name}_destroy_fn *destroy_function,
 79           const void *dispatch_data,
 80           const char *docstring);      /* <-- Added argument */
 81        static inline LE_STATUS LSC_find_{name}_implementation
 82          (LSC_env_t *env, const char *id, LSC_plugin_t **plugin,
 83           LSC_{name}_dispatch_fn **dispatch_function,
 84           LSC_{name}_destroy_fn **destroy_function,
 85           const void **dispatch_data,
 86           const char **docstring);      /* <-- Added argument */
 87      #+end_src
 88  
 89    - as a function passing back the docstring:
 90  
 91      That's an added public function:
 92  
 93      #+begin_src C
 94        static inline LE_STATUS
 95        LSC_get_{name}_docstring(LSC_{name}_t *lsc_data_set,
 96                                 const char **lsc_docstring);
 97      #+end_src
 98  
 99      That's also an extra case for plugin implementors to handle:
100  
101      #+begin_src C
102        case LSC_NR_get_docstring:
103          lsc_status = LE_STS_ERROR;
104          {
105            void **lsc_docstring = va_arg(lsc_valist, void **); /* Result */
106            if (lsc_docstring == NULL)
107              break;                    /* TODO: Set more precise status */
108  
109            ,*lsc_docstring = "...";
110          }
111          lsc_status = LE_STS_SUCCESS;
112          break;
113      #+end_src
114      
115  - Param descriptors ::
116  
117    - as a constant string pointer:
118  
119      This would be an added field in ~LSC_param_desc_t~.
120  
121    - as a function passing back the docstring:
122  
123      There are two possibilities:
124  
125      - get the docstrings in an array, indexed by parameter identity:
126  
127        #+begin_src C
128          typedef struct LSC_param_docstring_st {
129            uint8_t       p_id;
130            const char   *p_docstring;
131          } LSC_param_docstring_t;
132  
133          static inline LE_STATUS
134          LSC_get_gettable_{name}_param_docstrings
135            (LSC_{name}_t *o, const LSC_param_docstring_t **docstrings);
136  
137          static inline LE_STATUS
138          LSC_get_settable_{name}_param_docstrings
139            (LSC_{name}_t *o, const LSC_param_docstring_t **docstrings);
140        #+end_src
141  
142      - get the docstring separately for each parameter:
143  
144        #+begin_src C
145          static inline LE_STATUS
146          LSC_get_gettable_{name}_param_docstring
147            (LSC_{name}_t *o, unsigned int param_num,
148             const LSC_param_docstring_t **docstrings);
149  
150          static inline LE_STATUS
151          LSC_get_settable_{name}_param_docstring
152            (LSC_{name}_t *o, unsigned int param_num,
153             const LSC_param_docstring_t **docstrings);
154        #+end_src  
155  
156  As can be seen, not matter of docstrings are directly available as strings
157  pointers, or are available through a function call, there are breaking
158  changes, and there is added churn.
159  
160  /There are also other considerations to be made./
161  
162  A goal is for the Data Set structure to be permanently fixed at some point, no
163  more changes allowed, at least as far as Le'Sec Core and plugins are concerned.
164  Every added field comes with a worry that this isn't the end, that more may be
165  coming.  It's also been a long while since the last change (the dispatch data
166  addition), so this can feal like quite an upheaval.
167  
168  That being said, if the function call option is chosen, that's a lot of added
169  churn for applications and plugin implementations, especially with docstrings
170  for parameter descriptors, which may also be undesirable.
171  
172  The decision on which route to choose is left to the implementation and
173  experimentation.