The FreeTDS coding style for C code is close to K&R/Linux kernel style.
This document makes explicit the coding style found through most of the
project.  There are portions of code that do not follow this style; the
style is not enforced, but new code should follow it.

We are of course not trying to dictate how you code, but patches or submissions
to git should be converted to this style prior to committing.  The indent
program, using the src/.indent.pro profile, will do this nicely.

Code Blocks
-----------

Blocks of code should start with the { on the line with the control statement.

For example,

	for (i = 0; i < x; i++) {
		...
	}

This applies to for, do, while, switch, if and any other looping or branching
constructs.  An else goes on the same line as the closing brace:

	if (x) {
		...
	} else {
		...
	}

The exception to this is function definitions, in which the { should be on
its own line following the declaration, as in

	static void
	foo(int bar)
	{
		...
	}

Use a space after if, for, while and switch, and around binary operators.
Put a space after a cast, as in "(int) len".

Indenting
---------

Indenting should be done with one tab character per level. Default tabspace
is 8 characters. You can set in your editor whatever tabspace you want
but be sure that you indent using tabs and that line break work well with a
tabspace of 8.

Lines should not exceed 132 columns (counting tabs as 8 columns).

Variables
---------

Variables in FreeTDS should be all lower case with words separated by '_'
(underscore).  Furthermore, brevity is valued but not at the expense of clarity.
For instance, the variable 'minor_ver' is clear enough in context and doesn't
need to be labeled 'minor_version'.  The counter example to this is that the
variable 'can' is rather ambiguous and be expanded to 'canceled' for clarity.

The sole exception to this is arguments to the ODBC functions.  ODBC because of
its lineage uses hungarian notation for the names of the function arguments.
Variables that are internal to the functions should still follow the coding
style, but function arguments retain their Microsoft given names.

Variable declarations are indented like the code, and are followed by a
blank line.  Example,

	static void
	foo(int bar)
	{
		int i;

		for (i = 0; i < bar; i++) {
			...
		}
	}

a single space is generally preferred to separate the type from the variable
name, although some code pushes variable names to the right for clarity.
Which ever looks better is fine.

For boolean values use the bool type, true and false, from
include/freetds/bool.h.

Function Declarations
---------------------

Function definitions put the return type and modifiers on the line above and
start the next line with the name of the function (as in GNU style; this is
the only GNU convention we use, indentation and braces stay K&R as above):

	static void
	foo(int bar, int baz)
	{
	}

There are no spaces between the function name 'foo' and the left paren,
between the left paren and the first argument, nor the last argument and the
right paren.  A single space should follow the comma after each argument.
Having the function name aligned to the left side makes searching for
functions, and not the calls to them, easier.

When calling a function there is no space between its name and the left
paren: "foo(1, 2)".

A function with no arguments should be declared with void, not with empty
parens (which in C means unspecified arguments):

	void
	foobar(void)
	{
	}

Comments
--------

FreeTDS is a fairly portable package and runs on a number of platforms that
have either no C++ style comments or need special switches to turn them on
(the AIX C compiler comes to mind).  Therefore, all comments must be C-style
comments and not the C++ // comments.

	void
	foo(void)
	{
		// incorrect
	}

	void
	foo(void)
	{
		/* correct */
	}

Functions should be documented with doxygen (JavaDoc style) comments, so
that they can be extracted into the reference manual ("make doxy", see
tds.dox).  Most of the libraries already use them:

	/**
	 * Short description of foo.
	 * \param bar what bar is
	 * \return what is returned
	 */

See https://www.doxygen.nl/manual/ for details.



indent(1)
---------

The indent tool is a handy way to spiff up your formatting and bring it into
conformance.  It will compile faster!  No, it won't.  But it will be more
understandable to the lesser beings who want to try to follow you.

We use GNU indent with the src/.indent.pro profile file; running indent from
the src directory picks it up automatically.  These are the settings in the
profile, with a short explanation of each:

  -bad		  A blank line is forced after every block of declarations.
  -bap		  A blank line is forced after every procedure body.
  -nbbb		  Do not force a blank line before every block comment.
  -bbo		  Break long lines before boolean operators.
  -nbc		  Do not force a newline after each comma in a declaration.
  -br		  K & R braces, see above.
  -c33 		  The column in which comments on code start.
  -ncdb		  Allow single-line comments e.g.:
                              /* this is a comment */
  -cdw		  Cuddle "while" of do {} while; to the preceding "}".
  -ce		  Forcing `else's to cuddle up to the immediately preceding `}'.
  -cli0 	  Indentation of case labels from the containing switch
		  statement.  Existing code is not consistent about this.
  -cs		  Put a space after a cast operator.
  -d0		  Line up comments which are not to the right of code
		  with the code.
  -di1  	  One character position from a declaration keyword to the
		  following identifier.
  -nfc1		  Disable formatting comments that start in column 1.
  -i8		  The number of spaces for one indentation level.
  -ts8		  Tab stops at 8 positions.
  -l132		  Maximum length of an output line.
  -lp		  Line up code surrounded by parenthesis:
                           p1 = first_procedure(second_procedure(p2, p3),
                                                third_procedure(p4, p5));
  -npcs		  No space between a procedure name and the `('.
  -nprs		  No space after `(' and before `)'.
  -psl		  The return type of a procedure is placed on the line above
		  its name.
  -sc		  Put asterisks (`*'s) at the left edge of all comments.
  -nsob		  Do not swallow optional blank lines.
  -ut             Use tabs.
  -nv		  No verbose output.
  -saf, -sai, -saw  Put a space after for, if and while.
