<commit_before>===========
Code issues
===========

This document covers C coding issues related to Duktape implementation
such as:

* Conventions
* Portability concerns
* Specific platforms and compilers
* Size and performance optimization issues

Some code conventions are checked by the ``make codepolicycheck`` target.

Basic conventions
=================

Indentantion, naming, etc
-------------------------

Indent with tab.  On continuation lines indent with tab to shared indent
depth and then indent with spaces.  For example, denoting tab indent with
colon and space indent with period::

  ::::::::snprintf(buf,
  ::::::::.........sizeof(buf), 
  ::::::::........."%d",
  ::::::::.........123);

Names are lowercase, underscore separated::

  void duk_func(void) {
          /* ... */
  }

Local functions, arrays, structs, typedefs, etc have a double underscore
after "duk"::

  typedef int duk__temptype;

  static void duk__frobnicate_helper(void) {
          /* ... */
  }

The prefix is useful when looking at object files to clearly identify an
internal symbol as originating from Duktape.  It will also show up in
debugger tracebacks and such.

Macros are uppercase, underscore separated::

  #define DUK_MACRO(x)  /* ... */

Macro names must not begin with an underscore.  Macros which are of local
interest only can have a local name or have a double underscore after "DUK"::

  /* 'foo' alternatives, not to be used directly */
  #define DUK__FOO_ALT1  /* ... */
  #define DUK__FOO_ALT2  /* ... */

  /* select DUK_FOO provider */
  #define DUK_FOO  DUK_FOO_ALT2

There is only one space after a ``#define``, ``#if``, etc, but there may be
multiple spaces between the a macro name and its definition.  There is no
strict rule on the alignment of a macro value; successive definitions usually
keep values in the same column.

Comments are always traditional C comments, never ``//``, as they are not
portable to older compilers::

  /* always used traditional C comments */

Opening brace on the same line as the start of the construct, even
for functions::

  void func(int x) {
          if (x) {
                  /* ... */
          } else {
                  /* ... */
          }
  }

The case-statements of a switch are at the same level as the switch
to reduce indent.  If case clauses have their own blocks, this leads
to a confusing closing brace, so a comment for that may be in order::

  switch (x) {
  case A: {
          /* ... */
          break;
  }
  case B: {
          /* ... */
          break;
  }
  default: {
  }
  }  /* switch */

Space after ``if``, ``switch``, etc::

  if (x) { ... }   /* correct */
  if(x) { ... }    /* incorrect */

  switch (x) { ... }  /* correct */
  switch(x) { ... }   /* incorrect */

Use of goto for error cleanup and shared error handling is not only
allowed but encouraged.  Some goto notes:

* Avoid goto to an inner block as that might have portability impact.

* Jumping to skip blocks should be used only when it saves considerable
  indentation.

No naked statements in e.g. ``if-then-else``, always use a block.
This is more macro compatible.  Example::

  if (x) {
          return 1;  /* correct */
  }

  if (x)
          return 1;  /* incorrect */

Multi-statement macros should use a ``do-while(0)`` construct::

  #define FROBNICATE(x,y)  do { \
                  x = x * x; \
                  y = y * y; \
          } while (0)

When the body of a macro is sometimes empty, use an empty do-while so that
the macro still yields a statement::

  #if defined(DUK_USE_FROB)
  #define FROBNICATE(x,y)  do { \
                  x = x * x; \
                  y = y * y; \
          } while (0)
  #else
  #define FROBNICATE(x,y)  do { } while (0)
  #endif

Use parentheses when referring to macro arguments and the final macro
result to minimize error proneness::

  #define MULTIPLY(a,b)  ((a) * (b))

  /* Now MULTIPLY(1 + 2, 3) expands to ((1 + 2) * (3)) == 9, not
   * 1 + 2 * 3 == 7.  Parentheses are used around macro result for
   * similar reasons.
   */

Local variable declarations
---------------------------

C variables should only be declared in the beginning of the block.  Although
this is usually not a portability concern, some older still compilers require
it.  In particular, MSVC (at least Visual Studio 2010 Express) seems to
require this.

Be careful especially of assertions, debug prints, and other macros::

  int x, y;
  DUK_UNREF(y);
  int flags = 0;  /* problem: DUK_UNREF() */

Note that even **disabled** debug prints break the variable declaration
part because disabled debug prints are replaced with ``do {} while (0)``
(this is intentional to flush out this kind of errors even in release
builds)::

  {
          int x;

          DUK_DDD(DUK_DDDPRINT("debug print"));

          int y;  /* error here */

          x = 123;
          ...
  }
<commit_msg>Add code issues for label indent<commit_after>===========
Code issues
===========

This document covers C coding issues related to Duktape implementation
such as:

* Conventions
* Portability concerns
* Specific platforms and compilers
* Size and performance optimization issues

Some code conventions are checked by the ``make codepolicycheck`` target.

Basic conventions
=================

Indentantion, naming, etc
-------------------------

Indent with tab.  On continuation lines indent with tab to shared indent
depth and then indent with spaces.  For example, denoting tab indent with
colon and space indent with period::

  ::::::::snprintf(buf,
  ::::::::.........sizeof(buf), 
  ::::::::........."%d",
  ::::::::.........123);

Names are lowercase, underscore separated::

  void duk_func(void) {
          /* ... */
  }

Local functions, arrays, structs, typedefs, etc have a double underscore
after "duk"::

  typedef int duk__temptype;

  static void duk__frobnicate_helper(void) {
          /* ... */
  }

The prefix is useful when looking at object files to clearly identify an
internal symbol as originating from Duktape.  It will also show up in
debugger tracebacks and such.

Macros are uppercase, underscore separated::

  #define DUK_MACRO(x)  /* ... */

Macro names must not begin with an underscore.  Macros which are of local
interest only can have a local name or have a double underscore after "DUK"::

  /* 'foo' alternatives, not to be used directly */
  #define DUK__FOO_ALT1  /* ... */
  #define DUK__FOO_ALT2  /* ... */

  /* select DUK_FOO provider */
  #define DUK_FOO  DUK_FOO_ALT2

There is only one space after a ``#define``, ``#if``, etc, but there may be
multiple spaces between the a macro name and its definition.  There is no
strict rule on the alignment of a macro value; successive definitions usually
keep values in the same column.

Comments are always traditional C comments, never ``//``, as they are not
portable to older compilers::

  /* always used traditional C comments */

Opening brace on the same line as the start of the construct, even
for functions::

  void func(int x) {
          if (x) {
                  /* ... */
          } else {
                  /* ... */
          }
  }

The case-statements of a switch are at the same level as the switch
to reduce indent.  If case clauses have their own blocks, this leads
to a confusing closing brace, so a comment for that may be in order::

  switch (x) {
  case A: {
          /* ... */
          break;
  }
  case B: {
          /* ... */
          break;
  }
  default: {
  }
  }  /* switch */

Space after ``if``, ``switch``, etc::

  if (x) { ... }   /* correct */
  if(x) { ... }    /* incorrect */

  switch (x) { ... }  /* correct */
  switch(x) { ... }   /* incorrect */

Use of goto for error cleanup and shared error handling is not only
allowed but encouraged.  Some goto notes:

* Avoid goto to an inner block as that might have portability impact.

* Jumping to skip blocks should be used only when it saves considerable
  indentation.

No naked statements in e.g. ``if-then-else``, always use a block.
This is more macro compatible.  Example::

  if (x) {
          return 1;  /* correct */
  }

  if (x)
          return 1;  /* incorrect */

Multi-statement macros should use a ``do-while(0)`` construct::

  #define FROBNICATE(x,y)  do { \
                  x = x * x; \
                  y = y * y; \
          } while (0)

When the body of a macro is sometimes empty, use an empty do-while so that
the macro still yields a statement::

  #if defined(DUK_USE_FROB)
  #define FROBNICATE(x,y)  do { \
                  x = x * x; \
                  y = y * y; \
          } while (0)
  #else
  #define FROBNICATE(x,y)  do { } while (0)
  #endif

Use parentheses when referring to macro arguments and the final macro
result to minimize error proneness::

  #define MULTIPLY(a,b)  ((a) * (b))

  /* Now MULTIPLY(1 + 2, 3) expands to ((1 + 2) * (3)) == 9, not
   * 1 + 2 * 3 == 7.  Parentheses are used around macro result for
   * similar reasons.
   */

Labels are intended by one space relative to the parent tab depth::

  DUK_LOCAL void duk__helper(duk_context *ctx) {
          if (!ctx) {
                  DUK_D(DUK_DPRINT("ctx is NULL"));
                  goto fail;
          }

          return;

   fail:
          DUK_D(DUK_DPRINT("failed, detaching"));
  }

Local variable declarations
---------------------------

C variables should only be declared in the beginning of the block.  Although
this is usually not a portability concern, some older still compilers require
it.  In particular, MSVC (at least Visual Studio 2010 Express) seems to
require this.

Be careful especially of assertions, debug prints, and other macros::

  int x, y;
  DUK_UNREF(y);
  int flags = 0;  /* problem: DUK_UNREF() */

Note that even **disabled** debug prints break the variable declaration
part because disabled debug prints are replaced with ``do {} while (0)``
(this is intentional to flush out this kind of errors even in release
builds)::

  {
          int x;

          DUK_DDD(DUK_DDDPRINT("debug print"));

          int y;  /* error here */

          x = 123;
          ...
  }

{'fraction_non_alphanumeric': 0.1243554145180484, 'fraction_numerical': 0.006346687822292741, 'mean_word_length': 2.4117050067659, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4582808', 'n_tokens_mistral': 3065, 'n_tokens_neox': 2897, 'n_words': 1252}