/ 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