/ CODING.org
CODING.org
  1  # SPDX-FileCopyrightText: 2023-2024 Le'Sec Core collective
  2  #
  3  # SPDX-License-Identifier: LGPL-3.0-or-later
  4  
  5  #+TITLE: Coding Nomenclature and Style
  6  #+OPTIONS: author:nil date:nil
  7  
  8  * Nomenclature: Topics
  9  
 10  In a discussion on Le'Sec code, a topic is a set of types, functions and
 11  macros that belong together as unit.
 12  
 13  A recognisable topic would be a specific Le'Sec type, plus all the
 14  sub-types, functions and macros that surround it.
 15  
 16  Another way to recognise a topic is that there is a design story related to
 17  it.
 18  
 19  ** Discussion
 20  
 21  In other projects, this is often called "API" or "feature", but those terms
 22  have come to mean a variety of things depending on who you ask, and
 23  have thereby become a source of confusion.
 24  
 25  Yet other words to describe the same thing could be "unit" or "component".
 26  
 27  * Style: Coding in C
 28  
 29  This project uses a coding style that is derived from [[https://www.gnu.org/prep/standards/standards.html#Writing-C][the GNU Coding
 30  Standards, Chapter 5 - Making The Best Use of C]], only making a few
 31  exceptions:
 32  
 33  ** Please don't have the starting curly braces on separate lines
 34  
 35  In other words, this:
 36  
 37  #+BEGIN_SRC C
 38    if (cond) {
 39      body();
 40    }
 41  #+END_SRC
 42  
 43  is preferable to this:
 44  
 45  #+BEGIN_SRC C
 46    if (cond)
 47      {
 48        body();
 49      }
 50  #+END_SRC
 51  
 52  The only exception is function definitions:
 53  
 54  #+BEGIN_SRC C
 55    int foo(int a)
 56    {
 57      // Do something
 58      return 1;
 59    }
 60  #+END_SRC
 61  
 62  For multi-keyword statements, this also implies not breaking after
 63  ending curly braces that is followed by a keyword.
 64  
 65  This includes:
 66  
 67  - if-else:
 68  
 69    #+BEGIN_SRC C
 70      if (cond) {
 71        body1();
 72      } else {
 73        body2();
 74      }
 75    #+END_SRC
 76  
 77  - do-while:
 78  
 79    #+BEGIN_SRC C
 80      do {
 81        body();
 82      } while (cond);
 83    #+END_SRC
 84  
 85  /NOTE: clang-format knows this as the =BreakBeforeBraces: WebKit= configuration, see
 86  https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakbeforebraces/
 87  
 88  ** Please don't separate function names from its argument list
 89  
 90  In other words, this:
 91  
 92  #+BEGIN_SRC C
 93    fn(a, b, c);
 94  #+END_SRC
 95  
 96  is preferable to this:
 97  
 98  #+BEGIN_SRC C
 99    fn (a, b, c);
100  #+END_SRC
101  
102  However, there are some statements that include a parenthesised condition,
103  and that may look like a function call.  Please continue to separate their
104  keyword from the condition, i.e.:
105  
106  #+begin_src C
107    if (cond) ...;
108    while (cond) ...;
109    switch (num) { ...; }
110    for (init; cond; increment) ...;
111    // ... etc ...
112  #+end_src
113  
114  /NOTE: clang-format knows this as the =SpaceBeforeParens: ControlStatements=
115  configuration, see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforeparens/
116  
117  ** Having the function return type and the function name on different lines is optional
118  
119  Go with what's practical in terms of line length and some modicum of
120  elegance.  Having them on the same line or on separate lines is all the
121  same, some tools non-withstanding.
122  
123  * Style: Symbols (function names, variables names, macro names)
124  
125  ** Prefix
126  
127  All public symbols must have an upper case prefix that corresponds to the
128  library, and is usually an acronym for its longer name (for example, Le'Sec
129  Core gives the prefix =LSC_=).
130  
131  Non-static internal symbols (which are still externalised in static
132  libraries) must have the same prefix, but in lower case.
133  
134  Internal static symbols do not need a prefix.
135  
136  ** The rest of the symbol
137  
138  /NOTE/: In this section, "object" is primarly the grammatical term, not an
139  Object in programming terms.
140  
141  The rest of the symbol should try to be close to normal english, so roughly
142  speaking follow these patterns:
143  
144  - verb followed by object (such as ~LSC_add_environment_bag()~)
145  
146    This only makes sense for functions and macros with arguments, as they
147    perform actions.
148  
149  - adjective followed by object (such as ~LSC_new_environment()~)
150  
151    NOTE: that's seen as bad form; the verb followed by object form is
152    preferred.  However, the form with ~new~ followed by the object is such a
153    common occurance that it can be treated as an acceptable exception.
154  
155    This only makes sense for functions and macros with arguments, as they
156    perform actions.
157  
158  - just the object (such as the internal ~lsc_env_dispatch()~).
159  
160  *** Shared [[*Nomenclature: Topics][topic]]
161  
162  For symbols belonging in a [[*Nomenclature: Topics][topic]], it's preferable that they include a
163  word that demonstrate this.  This would usually be the name of the topic
164  itself.  This word would normally be a verb or an object.
165  
166  /As an example, all public types and functions that are related to the
167  environment have the word =environment= or =env= in their symbols./
168  
169  The shared word doesn't have to be exactly the same, inflections are
170  allowed; they are even encouraged.
171  
172  /As an example, all public types and functions that are related to key
173  derivation have one of the words =derivator=, =derive= or =derivation= in
174  their symbols./
175  
176  *** Types and structures
177  
178  Le'Sec C types (typically defined with ~typedef~) should always have one of
179  the suffixes:
180  
181  - For a function signature type, ~_fn~
182  - Otherwise, ~_t~
183  
184  Le'Sec ~struct~ names should always have the suffix ~_st~.
185  
186  *** Macros
187  
188  Generally speaking, this follows the rules and recommendations above, except
189  that they are generally in all upper case.
190  
191  Macros that are simple constants may sometimes follow slightly different
192  rules, which will crystalize over time.  For example, all dispatch command
193  numbers in Le'Sec Core have macros with the prefix ~LSC_NR~.
194  
195  * Style: Argument lists
196  
197  The arguments for functions and macros with arguments should roughly be
198  these, in order:
199  
200  1. For functions and macros with arguments that are part of a topic, the
201     type they are associated with should generally come as the first
202     argument.  There may be arguable exceptions, see [[On the subject of the topical type coming first][discussion]] below.
203  2. All the mandatory and/or common input variables, except for an instance
204     of ~LSC_env_t~ (see [[On the subject of ~LSC_env_t~][discussion]] below).
205  3. Any output / result variable(s), if they are needed (in other word, there
206     is or may be more than merely the returned status code).
207  4. Optional arguments, primarly a [[On Parameter Sets][parameter set]].
208  5. A pointer to an instance of ~LSC_env_t~, unless that's the first argument
209     or expected to be embedded in the first argument.
210  
211  If variadic arguments are used, they should be treated in such a way that
212  this argument order is maintained.
213  
214  In all cases, any of the above are optional if there are no arguments that
215  fit the criteria for that location in the argument list.
216  
217  ** Discussion
218  
219  *** On the subject of ~LSC_env_t~
220  
221  ~LSC_env_t~ is a fairly special type, as it's the root of everything and
222  should be ever present, "magically".
223  
224  There is a different language where that's almost litererally the case:
225  Common Lisp.  That language has a special option for macros that take an
226  environment, =&environment=, which must /always/ come last in the macro
227  argument list, and which is never given explicitly in a macro call.
228  
229  C being the language it is, that level of magic isn't possible.  However, we
230  can still let ourselves be inspired by its location relative to other
231  arguments, to the extent that it's possible.
232  
233  *** On the subject of the topical type coming first
234  
235  One notable (and arguable) exception to this are the plugin invocation and
236  revocation functions, which take the plugin start an stop functions as first
237  argument.
238  
239  #+BEGIN_SRC C
240    LE_STATUS LSC_invoke_plugin(LSC_plugin_start_fn *start, LSC_PLUGIN **plugin,
241                                LSC_env_t *env);
242    LE_STATUS LSC_revoke_plugin(LSC_plugin_stop_fn *stop, LSC_PLUGIN *plugin);
243  #+END_SRC
244  
245  With ~LSC_invoke_plugin()~, it's not very difficult to argue for this
246  ordering, as ~plugin~ is an obvious output argument.
247  
248  With ~LSC_revoke_plugin()~, it could be argued that ~plugin~ should come
249  first, as it is of the topical type.  However, it can also be argued that it
250  makes for an ugly interface in relation with ~LSC_invoke_plugin()~, /and/
251  that it's mainly an input argument that's simply passed along to the ~stop~
252  function.
253