quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

CODE_STYLE.md (8793B)


      1 <!--
      2 Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      3 
      4 SPDX-License-Identifier: curl
      5 -->
      6 
      7 # curl C code style
      8 
      9 Source code that has a common style is easier to read than code that uses
     10 different styles in different places. It helps making the code feel like one
     11 single code base. Easy-to-read is an important property of code and helps
     12 making it easier to review when new things are added and it helps debugging
     13 code when developers are trying to figure out why things go wrong. A unified
     14 style is more important than individual contributors having their own personal
     15 tastes satisfied.
     16 
     17 Our C code has a few style rules. Most of them are verified and upheld by the
     18 `scripts/checksrc.pl` script. Invoked with `make checksrc` or even by default
     19 by the build system when built after `./configure --enable-debug` has been
     20 used.
     21 
     22 It is normally not a problem for anyone to follow the guidelines, as you just
     23 need to copy the style already used in the source code and there are no
     24 particularly unusual rules in our set of rules.
     25 
     26 We also work hard on writing code that are warning-free on all the major
     27 platforms and in general on as many platforms as possible. Code that obviously
     28 causes warnings is not accepted as-is.
     29 
     30 ## Readability
     31 
     32 A primary characteristic for code is readability. The intent and meaning of
     33 the code should be visible to the reader. Being clear and unambiguous beats
     34 being clever and saving two lines of code. Write simple code. You and others
     35 who come back to this code over the coming decades want to be able to quickly
     36 understand it when debugging.
     37 
     38 ## Naming
     39 
     40 Try using a non-confusing naming scheme for your new functions and variable
     41 names. It does not necessarily have to mean that you should use the same as in
     42 other places of the code, just that the names should be logical,
     43 understandable and be named according to what they are used for. File-local
     44 functions should be made static. We like lower case names.
     45 
     46 See the [INTERNALS](https://curl.se/dev/internals.html#symbols) document on
     47 how we name non-exported library-global symbols.
     48 
     49 ## Indenting
     50 
     51 We use only spaces for indentation, never TABs. We use two spaces for each new
     52 open brace.
     53 
     54 ```c
     55 if(something_is_true) {
     56   while(second_statement == fine) {
     57     moo();
     58   }
     59 }
     60 ```
     61 
     62 ## Comments
     63 
     64 Since we write C89 code, **//** comments are not allowed. They were not
     65 introduced in the C standard until C99. We use only __/* comments */__.
     66 
     67 ```c
     68 /* this is a comment */
     69 ```
     70 
     71 ## Long lines
     72 
     73 Source code in curl may never be wider than 79 columns and there are two
     74 reasons for maintaining this even in the modern era of large and high
     75 resolution screens:
     76 
     77 1. Narrower columns are easier to read than wide ones. There is a reason
     78    newspapers have used columns for decades or centuries.
     79 
     80 2. Narrower columns allow developers to easier show multiple pieces of code
     81    next to each other in different windows. It allows two or three source
     82    code windows next to each other on the same screen - as well as multiple
     83    terminal and debugging windows.
     84 
     85 ## Braces
     86 
     87 In if/while/do/for expressions, we write the open brace on the same line as
     88 the keyword and we then set the closing brace on the same indentation level as
     89 the initial keyword. Like this:
     90 
     91 ```c
     92 if(age < 40) {
     93   /* clearly a youngster */
     94 }
     95 ```
     96 
     97 You may omit the braces if they would contain only a one-line statement:
     98 
     99 ```c
    100 if(!x)
    101   continue;
    102 ```
    103 
    104 For functions the opening brace should be on a separate line:
    105 
    106 ```c
    107 int main(int argc, char **argv)
    108 {
    109   return 1;
    110 }
    111 ```
    112 
    113 ## 'else' on the following line
    114 
    115 When adding an **else** clause to a conditional expression using braces, we
    116 add it on a new line after the closing brace. Like this:
    117 
    118 ```c
    119 if(age < 40) {
    120   /* clearly a youngster */
    121 }
    122 else {
    123   /* probably grumpy */
    124 }
    125 ```
    126 
    127 ## No space before parentheses
    128 
    129 When writing expressions using if/while/do/for, there shall be no space
    130 between the keyword and the open parenthesis. Like this:
    131 
    132 ```c
    133 while(1) {
    134   /* loop forever */
    135 }
    136 ```
    137 
    138 ## Use boolean conditions
    139 
    140 Rather than test a conditional value such as a bool against TRUE or FALSE, a
    141 pointer against NULL or != NULL and an int against zero or not zero in
    142 if/while conditions we prefer:
    143 
    144 ```c
    145 result = do_something();
    146 if(!result) {
    147   /* something went wrong */
    148   return result;
    149 }
    150 ```
    151 
    152 ## No assignments in conditions
    153 
    154 To increase readability and reduce complexity of conditionals, we avoid
    155 assigning variables within if/while conditions. We frown upon this style:
    156 
    157 ```c
    158 if((ptr = malloc(100)) == NULL)
    159   return NULL;
    160 ```
    161 
    162 and instead we encourage the above version to be spelled out more clearly:
    163 
    164 ```c
    165 ptr = malloc(100);
    166 if(!ptr)
    167   return NULL;
    168 ```
    169 
    170 ## New block on a new line
    171 
    172 We never write multiple statements on the same source line, even for short
    173 if() conditions.
    174 
    175 ```c
    176 if(a)
    177   return TRUE;
    178 else if(b)
    179   return FALSE;
    180 ```
    181 
    182 and NEVER:
    183 
    184 ```c
    185 if(a) return TRUE;
    186 else if(b) return FALSE;
    187 ```
    188 
    189 ## Space around operators
    190 
    191 Please use spaces on both sides of operators in C expressions. Postfix **(),
    192 [], ->, ., ++, --** and Unary **+, -, !, ~, &** operators excluded they should
    193 have no space.
    194 
    195 Examples:
    196 
    197 ```c
    198 bla = func();
    199 who = name[0];
    200 age += 1;
    201 true = !false;
    202 size += -2 + 3 * (a + b);
    203 ptr->member = a++;
    204 struct.field = b--;
    205 ptr = &address;
    206 contents = *pointer;
    207 complement = ~bits;
    208 empty = (!*string) ? TRUE : FALSE;
    209 ```
    210 
    211 ## No parentheses for return values
    212 
    213 We use the 'return' statement without extra parentheses around the value:
    214 
    215 ```c
    216 int works(void)
    217 {
    218   return TRUE;
    219 }
    220 ```
    221 
    222 ## Parentheses for sizeof arguments
    223 
    224 When using the sizeof operator in code, we prefer it to be written with
    225 parentheses around its argument:
    226 
    227 ```c
    228 int size = sizeof(int);
    229 ```
    230 
    231 ## Column alignment
    232 
    233 Some statements cannot be completed on a single line because the line would be
    234 too long, the statement too hard to read, or due to other style guidelines
    235 above. In such a case the statement spans multiple lines.
    236 
    237 If a continuation line is part of an expression or sub-expression then you
    238 should align on the appropriate column so that it is easy to tell what part of
    239 the statement it is. Operators should not start continuation lines. In other
    240 cases follow the 2-space indent guideline. Here are some examples from
    241 libcurl:
    242 
    243 ```c
    244 if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
    245    (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
    246    (handle->set.httpreq == HTTPREQ_GET ||
    247     handle->set.httpreq == HTTPREQ_HEAD))
    248   /* did not ask for HTTP/1.0 and a GET or HEAD */
    249   return TRUE;
    250 ```
    251 
    252 If no parenthesis, use the default indent:
    253 
    254 ```c
    255 data->set.http_disable_hostname_check_before_authentication =
    256   (0 != va_arg(param, long)) ? TRUE : FALSE;
    257 ```
    258 
    259 Function invoke with an open parenthesis:
    260 
    261 ```c
    262 if(option) {
    263   result = parse_login_details(option, strlen(option),
    264                                (userp ? &user : NULL),
    265                                (passwdp ? &passwd : NULL),
    266                                NULL);
    267 }
    268 ```
    269 
    270 Align with the "current open" parenthesis:
    271 
    272 ```c
    273 DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
    274              "server response left\n",
    275              (int)clipamount));
    276 ```
    277 
    278 ## Platform dependent code
    279 
    280 Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
    281 particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
    282 shall be generated by the configure script for Unix-like systems and they are
    283 hard-coded in the `config-[system].h` files for the others.
    284 
    285 We also encourage use of macros/functions that possibly are empty or defined
    286 to constants when libcurl is built without that feature, to make the code
    287 seamless. Like this example where the **magic()** function works differently
    288 depending on a build-time conditional:
    289 
    290 ```c
    291 #ifdef HAVE_MAGIC
    292 void magic(int a)
    293 {
    294   return a + 2;
    295 }
    296 #else
    297 #define magic(x) 1
    298 #endif
    299 
    300 int content = magic(3);
    301 ```
    302 
    303 ## No typedefed structs
    304 
    305 Use structs by all means, but do not typedef them. Use the `struct name` way
    306 of identifying them:
    307 
    308 ```c
    309 struct something {
    310    void *valid;
    311    size_t way_to_write;
    312 };
    313 struct something instance;
    314 ```
    315 
    316 **Not okay**:
    317 
    318 ```c
    319 typedef struct {
    320    void *wrong;
    321    size_t way_to_write;
    322 } something;
    323 something instance;
    324 ```
    325 
    326 ## Banned functions
    327 
    328 To avoid footguns and unintended consequences we forbid the use of a number of
    329 C functions. The `checksrc` script finds and yells about them if used. This
    330 makes us write better code.
    331 
    332 This is the full list of functions generally banned.
    333 
    334     _access
    335     _mbscat
    336     _mbsncat
    337     _tcscat
    338     _tcsncat
    339     _waccess
    340     _wcscat
    341     _wcsncat
    342     access
    343     gets
    344     gmtime
    345     LoadLibrary
    346     LoadLibraryA
    347     LoadLibraryEx
    348     LoadLibraryExA
    349     LoadLibraryExW
    350     LoadLibraryW
    351     localtime
    352     snprintf
    353     sprintf
    354     sscanf
    355     strcat
    356     strerror
    357     strncat
    358     strncpy
    359     strtok
    360     strtol
    361     strtoul
    362     vsnprint
    363     vsprintf