Blame CODING_STYLE

Packit 324a5c
Cairo coding style.
Packit 324a5c
Packit 324a5c
This document is intended to be a short description of the preferred
Packit 324a5c
coding style for the cairo source code. Good style requires good
Packit 324a5c
taste, which means this can't all be reduced to automated rules, and
Packit 324a5c
there are exceptions.
Packit 324a5c
Packit 324a5c
We want the code to be easy to understand and maintain, and consistent
Packit 324a5c
style plays an important part in that, even if some of the specific
Packit 324a5c
details seem trivial. If nothing else, this document gives a place to
Packit 324a5c
put consistent answers for issues that would otherwise be arbitrary.
Packit 324a5c
Packit 324a5c
Most of the guidelines here are demonstrated by examples, (which means
Packit 324a5c
this document is quicker to read than it might appear given its
Packit 324a5c
length). Most of the examples are positive examples that you should
Packit 324a5c
imitate. The few negative examples are clearly marked with a comment
Packit 324a5c
of /* Yuck! */. Please don't submit code to cairo that looks like any
Packit 324a5c
of these.
Packit 324a5c
Packit 324a5c
Indentation
Packit 324a5c
-----------
Packit 324a5c
Each new level is indented 4 more spaces than the previous level:
Packit 324a5c
Packit 324a5c
	if (condition)
Packit 324a5c
	    do_something ();
Packit 324a5c
Packit 324a5c
This may be achieved with space characters or a combination of tab
Packit 324a5c
characters and space characters. It may not be achieved with tab
Packit 324a5c
characters exclusively (see below).
Packit 324a5c
Packit 324a5c
Tab characters
Packit 324a5c
--------------
Packit 324a5c
The tab character must always be interpreted according to its
Packit 324a5c
traditional meaning:
Packit 324a5c
Packit 324a5c
	Advance to the next column which is a multiple of 8.
Packit 324a5c
Packit 324a5c
With this definition, even levels of indentation can be achieved with
Packit 324a5c
a sequence of tab characters, while odd levels of indentation may
Packit 324a5c
begin with a sequence of tab character but must end with 4 space
Packit 324a5c
characters.
Packit 324a5c
Packit 324a5c
Some programmers have been misled by certain text editors into
Packit 324a5c
thinking that 4-space indentation can be achieved with tab characters
Packit 324a5c
exclusively by changing the meaning of tab character to be "advance to
Packit 324a5c
the next column which is a multiple of 4". Code formatted in this way,
Packit 324a5c
making an assumption of a fictitious 4-character-tab will not be
Packit 324a5c
accepted into cairo.
Packit 324a5c
Packit 324a5c
The rationale here is that tabs are used in the code for lining things
Packit 324a5c
up other than indentation, (see the Whitespace section below), and
Packit 324a5c
changing the interpretation of tab from its traditional meaning will
Packit 324a5c
break this alignment.
Packit 324a5c
Packit 324a5c
Braces
Packit 324a5c
------
Packit 324a5c
Most of the code in cairo uses bracing in the style of K&R:
Packit 324a5c
Packit 324a5c
	if (condition) {
Packit 324a5c
	    do_this ();
Packit 324a5c
	    do_that ();
Packit 324a5c
	} else {
Packit 324a5c
	    do_the_other ();
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
but some of the code uses an alternate style:
Packit 324a5c
Packit 324a5c
	if (condition)
Packit 324a5c
	{
Packit 324a5c
	    do_this ();
Packit 324a5c
	    do_that ();
Packit 324a5c
	}
Packit 324a5c
	else
Packit 324a5c
	{
Packit 324a5c
	    do_the_other ();
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
and that seems just fine. We won't lay down any strict rule on this
Packit 324a5c
point, (though there should be some local consistency). If you came
Packit 324a5c
here hoping to find some guidance, then use the first form above.
Packit 324a5c
Packit 324a5c
If all of the substatements of an if statement are single statements,
Packit 324a5c
the optional braces should not usually appear:
Packit 324a5c
Packit 324a5c
	if (condition)
Packit 324a5c
	    do_this ();
Packit 324a5c
	else
Packit 324a5c
	    do_that ();
Packit 324a5c
Packit 324a5c
But the braces are mandatory when mixing single statement and compound
Packit 324a5c
statements in the various clauses. For example, do not do this:
Packit 324a5c
Packit 324a5c
	if (condition) {
Packit 324a5c
	    do_this ();
Packit 324a5c
	    do_that ();
Packit 324a5c
	} else			/* Yuck! */
Packit 324a5c
	    do_the_other ();
Packit 324a5c
Packit 324a5c
And of course, there are exceptions for when the code just looks
Packit 324a5c
better with the braces:
Packit 324a5c
Packit 324a5c
	if (condition) {
Packit 324a5c
	    /* Note that we have to be careful here. */
Packit 324a5c
	    do_something_dangerous (with_care);
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
	if (condition &&
Packit 324a5c
	    other_condition &&
Packit 324a5c
	    yet_another)
Packit 324a5c
	{
Packit 324a5c
	    do_something ();
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
And note that this last example also shows a situation in which the
Packit 324a5c
opening brace really needs to be on its own line. The following looks awful:
Packit 324a5c
Packit 324a5c
	if (condition &&
Packit 324a5c
	    other_condition &&
Packit 324a5c
	    yet_another) {	/* Yuck! */
Packit 324a5c
	    do_something ();
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
As we said above, legible code that is easy to understand and maintain
Packit 324a5c
is the goal, not adherence to strict rules.
Packit 324a5c
Packit 324a5c
Whitespace
Packit 324a5c
----------
Packit 324a5c
Separate logically distinct chunks with a single newline. This
Packit 324a5c
obviously applies between functions, but also applies within a
Packit 324a5c
function or block and can even be used to good effect within a
Packit 324a5c
structure definition:
Packit 324a5c
Packit 324a5c
	struct _cairo_gstate {
Packit 324a5c
	    cairo_operator_t op;
Packit 324a5c
Packit 324a5c
	    double tolerance;
Packit 324a5c
Packit 324a5c
	    /* stroke style */
Packit 324a5c
	    double line_width;
Packit 324a5c
	    cairo_line_cap_t line_cap;
Packit 324a5c
	    cairo_line_join_t line_join;
Packit 324a5c
	    double miter_limit;
Packit 324a5c
Packit 324a5c
	    cairo_fill_rule_t fill_rule;
Packit 324a5c
Packit 324a5c
	    double *dash;
Packit 324a5c
	    int num_dashes;
Packit 324a5c
	    double dash_offset;
Packit 324a5c
Packit 324a5c
	    ...
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
Use a single space before a left parenthesis, except where the
Packit 324a5c
standard will not allow it, (eg. when defining a parameterized macro).
Packit 324a5c
Packit 324a5c
Don't eliminate newlines just because things would still fit on one
Packit 324a5c
line. This breaks the expected visual structure of the code making it
Packit 324a5c
much harder to read and understand:
Packit 324a5c
Packit 324a5c
	if (condition) foo (); else bar ();	/* Yuck! */
Packit 324a5c
Packit 324a5c
Do eliminate trailing whitespace (space or tab characters) on any
Packit 324a5c
line. Also, avoid putting initial or final blank lines into any file,
Packit 324a5c
and never use multiple blank lines instead of a single blank line.
Packit 324a5c
Packit 324a5c
Do enable the default git pre-commit hook that detect trailing
Packit 324a5c
whitespace for you and help you to avoid corrupting cairo's tree with
Packit 324a5c
it. Do that as follows:
Packit 324a5c
Packit 324a5c
	chmod a+x .git/hooks/pre-commit
Packit 324a5c
Packit 324a5c
You might also find the git-stripspace utility helpful which acts as a
Packit 324a5c
filter to remove trailing whitespace as well as initial, final, and
Packit 324a5c
duplicate blank lines.
Packit 324a5c
Packit 324a5c
As a special case of the bracing and whitespace guidelines, function
Packit 324a5c
definitions should always take the following form:
Packit 324a5c
Packit 324a5c
	void
Packit 324a5c
	my_function (argument)
Packit 324a5c
	{
Packit 324a5c
	    do_my_things ();
Packit 324a5c
	}
Packit 324a5c
Packit 324a5c
And function prototypes should similarly have the return type (and
Packit 324a5c
associated specifiers and qualifiers) on a line above the function, so
Packit 324a5c
that the function name is flush left.
Packit 324a5c
Packit 324a5c
Break up long lines (> ~80 characters) and use whitespace to align
Packit 324a5c
things nicely. For example the arguments in a long list to a function
Packit 324a5c
call should all be aligned with each other:
Packit 324a5c
Packit 324a5c
	align_function_arguments (argument_the_first,
Packit 324a5c
				  argument_the_second,
Packit 324a5c
				  argument_the_third);
Packit 324a5c
Packit 324a5c
And as a special rule, in a function prototype, (as well as in the
Packit 324a5c
definition), whitespace should be inserted between the parameter types
Packit 324a5c
and names so that the names are aligned:
Packit 324a5c
Packit 324a5c
	void
Packit 324a5c
	align_parameter_names_in_prototypes (const char *char_star_arg,
Packit 324a5c
					     int	 int_arg,
Packit 324a5c
					     double	*double_star_arg,
Packit 324a5c
					     double	 double_arg);
Packit 324a5c
Packit 324a5c
Note that parameters with a * prefix are aligned one character to the
Packit 324a5c
left so that the actual names are aligned.
Packit 324a5c
Packit 324a5c
Managing nested blocks
Packit 324a5c
----------------------
Packit 324a5c
Long blocks that are deeply nested make the code very hard to
Packit 324a5c
read. Fortunately such blocks often indicate logically distinct chunks
Packit 324a5c
of functionality that are begging to be split into their own
Packit 324a5c
functions. Please listen to the blocks when they beg.
Packit 324a5c
Packit 324a5c
In other cases, gratuitous nesting comes about because the primary
Packit 324a5c
functionality gets buried in a nested block rather than living at the
Packit 324a5c
primary level where it belongs. Consider the following:
Packit 324a5c
Packit 324a5c
	foo = malloc (sizeof (foo_t));
Packit 324a5c
	if (foo) {					/* Yuck! */
Packit 324a5c
	    ...
Packit 324a5c
	    /* lots of code to initialize foo */
Packit 324a5c
	    ...
Packit 324a5c
	    return SUCCESS;
Packit 324a5c
	}
Packit 324a5c
	return FAILURE;
Packit 324a5c
Packit 324a5c
This kind of gratuitous nesting can be avoided by following a pattern
Packit 324a5c
of handling exceptional cases early and returning:
Packit 324a5c
Packit 324a5c
	foo = malloc (sizeof (foo_t));
Packit 324a5c
	if (foo == NULL)
Packit 324a5c
	    return FAILURE;
Packit 324a5c
Packit 324a5c
	...
Packit 324a5c
	/* lots of code to initialize foo */
Packit 324a5c
	...
Packit 324a5c
	return SUCCESS;
Packit 324a5c
Packit 324a5c
The return statement is often the best thing to use in a pattern like
Packit 324a5c
this. If it's not available due to additional nesting above which
Packit 324a5c
require some cleanup after the current block, then consider splitting
Packit 324a5c
the current block into a new function before using goto.
Packit 324a5c
Packit 324a5c
Memory allocation
Packit 324a5c
-----------------
Packit 324a5c
Packit 324a5c
Because much of cairo's data consists of dynamically allocated arrays,
Packit 324a5c
it's very easy to introduce integer overflow issues whenever malloc()
Packit 324a5c
is called.  Use the _cairo_malloc2(), _cairo_malloc3(), and
Packit 324a5c
_cairo_malloc2_add1 macros to avoid these cases; these macros check
Packit 324a5c
for overflow and will return NULL in that case.
Packit 324a5c
Packit 324a5c
  malloc (n * size) => _cairo_malloc_ab (n, size)
Packit 324a5c
    e.g. malloc (num_elts * sizeof(some_type)) =>
Packit 324a5c
         _cairo_malloc2 (num_elts, sizeof(some_type))
Packit 324a5c
Packit 324a5c
  malloc (a * b * size) => _cairo_malloc_abc (a, b, size)
Packit 324a5c
    e.g. malloc (width * height * 4) =>
Packit 324a5c
         _cairo_malloc3 (width, height, 4)
Packit 324a5c
Packit 324a5c
  malloc (n * size + k) => _cairo_malloc_ab_plus_c (n, size, k)
Packit 324a5c
    e.g. malloc (num * sizeof(entry) + sizeof(header)) =>
Packit 324a5c
         _cairo_malloc2k (num, sizeof(entry), sizeof(header))
Packit 324a5c
Packit 324a5c
In general, be wary of performing any arithmetic operations in an
Packit 324a5c
argument to malloc.  You should explicitly check for integer overflow
Packit 324a5c
yourself in any more complex situations.
Packit 324a5c
Packit 324a5c
Mode lines
Packit 324a5c
----------
Packit 324a5c
Packit 324a5c
So given the rules above, what is the best way to simplify one's life as
Packit 324a5c
a code monkey? Get your editor to do most of the tedious work of
Packit 324a5c
beautifying your code!
Packit 324a5c
Packit 324a5c
As a reward for reading this far, here are some mode lines for the more
Packit 324a5c
popular editors:
Packit 324a5c
/*
Packit 324a5c
 * vim:sw=4:sts=4:ts=8:tw=78:fo=tcroq:cindent:cino=\:0,(0
Packit 324a5c
 * vim:isk=a-z,A-Z,48-57,_,.,-,>
Packit 324a5c
 */
Packit 324a5c
Packit 324a5c
Packit 324a5c
TODO
Packit 324a5c
----
Packit 324a5c
Packit 324a5c
Write rules for common editors to use this style.  Also cleanup/unify
Packit 324a5c
the modelines in the source files.