File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / docs / CODE_STYLE.md
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 10 months ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: # curl C code style
    2: 
    3: Source code that has a common style is easier to read than code that uses
    4: different styles in different places. It helps making the code feel like one
    5: single code base. Easy-to-read is a very important property of code and helps
    6: making it easier to review when new things are added and it helps debugging
    7: code when developers are trying to figure out why things go wrong. A unified
    8: style is more important than individual contributors having their own personal
    9: tastes satisfied.
   10: 
   11: Our C code has a few style rules. Most of them are verified and upheld by the
   12: `lib/checksrc.pl` script. Invoked with `make checksrc` or even by default by
   13: the build system when built after `./configure --enable-debug` has been used.
   14: 
   15: It is normally not a problem for anyone to follow the guidelines, as you just
   16: need to copy the style already used in the source code and there are no
   17: particularly unusual rules in our set of rules.
   18: 
   19: We also work hard on writing code that are warning-free on all the major
   20: platforms and in general on as many platforms as possible. Code that obviously
   21: will cause warnings will not be accepted as-is.
   22: 
   23: ## Naming
   24: 
   25: Try using a non-confusing naming scheme for your new functions and variable
   26: names. It doesn't necessarily have to mean that you should use the same as in
   27: other places of the code, just that the names should be logical,
   28: understandable and be named according to what they're used for. File-local
   29: functions should be made static. We like lower case names.
   30: 
   31: See the [INTERNALS](INTERNALS.md) document on how we name non-exported
   32: library-global symbols.
   33: 
   34: ## Indenting
   35: 
   36: We use only spaces for indentation, never TABs. We use two spaces for each new
   37: open brace.
   38: 
   39:     if(something_is_true) {
   40:       while(second_statement == fine) {
   41:         moo();
   42:       }
   43:     }
   44: 
   45: ## Comments
   46: 
   47: Since we write C89 code, **//** comments are not allowed. They weren't
   48: introduced in the C standard until C99. We use only **/* comments */**.
   49: 
   50:     /* this is a comment */
   51: 
   52: ## Long lines
   53: 
   54: Source code in curl may never be wider than 79 columns and there are two
   55: reasons for maintaining this even in the modern era of very large and high
   56: resolution screens:
   57: 
   58: 1. Narrower columns are easier to read than very wide ones. There's a reason
   59:    newspapers have used columns for decades or centuries.
   60: 
   61: 2. Narrower columns allow developers to easier show multiple pieces of code
   62:    next to each other in different windows. I often have two or three source
   63:    code windows next to each other on the same screen - as well as multiple
   64:    terminal and debugging windows.
   65: 
   66: ## Braces
   67: 
   68: In if/while/do/for expressions, we write the open brace on the same line as
   69: the keyword and we then set the closing brace on the same indentation level as
   70: the initial keyword. Like this:
   71: 
   72:     if(age < 40) {
   73:       /* clearly a youngster */
   74:     }
   75: 
   76: You may omit the braces if they would contain only a one-line statement:
   77: 
   78:     if(!x)
   79:       continue;
   80: 
   81: For functions the opening brace should be on a separate line:
   82: 
   83:     int main(int argc, char **argv)
   84:     {
   85:       return 1;
   86:     }
   87: 
   88: ## 'else' on the following line
   89: 
   90: When adding an **else** clause to a conditional expression using braces, we
   91: add it on a new line after the closing brace. Like this:
   92: 
   93:     if(age < 40) {
   94:       /* clearly a youngster */
   95:     }
   96:     else {
   97:       /* probably grumpy */
   98:     }
   99: 
  100: ## No space before parentheses
  101: 
  102: When writing expressions using if/while/do/for, there shall be no space
  103: between the keyword and the open parenthesis. Like this:
  104: 
  105:     while(1) {
  106:       /* loop forever */
  107:     }
  108: 
  109: ## Use boolean conditions
  110: 
  111: Rather than test a conditional value such as a bool against TRUE or FALSE, a
  112: pointer against NULL or != NULL and an int against zero or not zero in
  113: if/while conditions we prefer:
  114: 
  115:     result = do_something();
  116:     if(!result) {
  117:       /* something went wrong */
  118:       return result;
  119:     }
  120: 
  121: ## No assignments in conditions
  122: 
  123: To increase readability and reduce complexity of conditionals, we avoid
  124: assigning variables within if/while conditions. We frown upon this style:
  125: 
  126:     if((ptr = malloc(100)) == NULL)
  127:       return NULL;
  128: 
  129: and instead we encourage the above version to be spelled out more clearly:
  130: 
  131:     ptr = malloc(100);
  132:     if(!ptr)
  133:       return NULL;
  134: 
  135: ## New block on a new line
  136: 
  137: We never write multiple statements on the same source line, even for very
  138: short if() conditions.
  139: 
  140:     if(a)
  141:       return TRUE;
  142:     else if(b)
  143:       return FALSE;
  144: 
  145: and NEVER:
  146: 
  147:     if(a) return TRUE;
  148:     else if(b) return FALSE;
  149: 
  150: ## Space around operators
  151: 
  152: Please use spaces on both sides of operators in C expressions.  Postfix **(),
  153: [], ->, ., ++, --** and Unary **+, - !, ~, &** operators excluded they should
  154: have no space.
  155: 
  156: Examples:
  157: 
  158:     bla = func();
  159:     who = name[0];
  160:     age += 1;
  161:     true = !false;
  162:     size += -2 + 3 * (a + b);
  163:     ptr->member = a++;
  164:     struct.field = b--;
  165:     ptr = &address;
  166:     contents = *pointer;
  167:     complement = ~bits;
  168:     empty = (!*string) ? TRUE : FALSE;
  169: 
  170: ## No parentheses for return values
  171: 
  172: We use the 'return' statement without extra parentheses around the value:
  173: 
  174:     int works(void)
  175:     {
  176:       return TRUE;
  177:     }
  178: 
  179: ## Parentheses for sizeof arguments
  180: 
  181: When using the sizeof operator in code, we prefer it to be written with
  182: parentheses around its argument:
  183: 
  184:     int size = sizeof(int);
  185: 
  186: ## Column alignment
  187: 
  188: Some statements cannot be completed on a single line because the line would be
  189: too long, the statement too hard to read, or due to other style guidelines
  190: above. In such a case the statement will span multiple lines.
  191: 
  192: If a continuation line is part of an expression or sub-expression then you
  193: should align on the appropriate column so that it's easy to tell what part of
  194: the statement it is. Operators should not start continuation lines. In other
  195: cases follow the 2-space indent guideline. Here are some examples from
  196: libcurl:
  197: 
  198:     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
  199:        (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
  200:        (handle->set.httpreq == HTTPREQ_GET ||
  201:         handle->set.httpreq == HTTPREQ_HEAD))
  202:       /* didn't ask for HTTP/1.0 and a GET or HEAD */
  203:       return TRUE;
  204: 
  205: If no parenthesis, use the default indent:
  206: 
  207:     data->set.http_disable_hostname_check_before_authentication =
  208:       (0 != va_arg(param, long)) ? TRUE : FALSE;
  209: 
  210: Function invoke with an open parenthesis:
  211: 
  212:     if(option) {
  213:       result = parse_login_details(option, strlen(option),
  214:                                    (userp ? &user : NULL),
  215:                                    (passwdp ? &passwd : NULL),
  216:                                    NULL);
  217:     }
  218: 
  219: Align with the "current open" parenthesis:
  220: 
  221:     DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
  222:                  "server response left\n",
  223:                  (int)clipamount));
  224: 
  225: ## Platform dependent code
  226: 
  227: Use **#ifdef HAVE_FEATURE** to do conditional code. We avoid checking for
  228: particular operating systems or hardware in the #ifdef lines. The HAVE_FEATURE
  229: shall be generated by the configure script for unix-like systems and they are
  230: hard-coded in the `config-[system].h` files for the others.
  231: 
  232: We also encourage use of macros/functions that possibly are empty or defined
  233: to constants when libcurl is built without that feature, to make the code
  234: seamless. Like this example where the **magic()** function works differently
  235: depending on a build-time conditional:
  236: 
  237:     #ifdef HAVE_MAGIC
  238:     void magic(int a)
  239:     {
  240:       return a + 2;
  241:     }
  242:     #else
  243:     #define magic(x) 1
  244:     #endif
  245: 
  246:     int content = magic(3);

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>