wiki:doc/CodingForTor/CodingInC

Did you remember...

- To build your code while configured with --enable-gcc-warnings?
- To run "make check-spaces" on your code?
- To write unit tests, as possible?
- To base your code on the appropriate branch?
- To include a file in the "changes" directory as appropriate?

Whitespace and C conformance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Invoke "make check-spaces" from time to time, so it can tell you about
deviations from our C whitespace style. Generally, we use:

- Unix-style line endings
- K&R-style indentation
- No space before newlines
- A blank line at the end of each file
- Never more than one blank line in a row
- Always spaces, never tabs
- No more than 79-columns per line.
- Two spaces per indent.
- A space between control keywords and their corresponding paren
"if (x)", "while (x)", and "switch (x)", never "if(x)", "while(x)", or
"switch(x)".
- A space between anything and an open brace.
- No space between a function name and an opening paren. "puts(x)", not
"puts (x)".
- Function declarations at the start of the line.

We try hard to build without warnings everywhere. In particular, if you're
using gcc, you should invoke the configure script with the option
"--enable-gcc-warnings". This will give a bunch of extra warning flags to
the compiler, and help us find divergences from our preferred C style.

Getting emacs to edit Tor source properly
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Nick likes to put the following snippet in his .emacs file:

-----
(add-hook 'c-mode-hook
(lambda ()
(font-lock-mode 1)
(set-variable 'show-trailing-whitespace t)

(let ((fname (expand-file-name (buffer-file-name))))
(cond
((string-match "^/home/nickm/src/libevent" fname)
(set-variable 'indent-tabs-mode t)
(set-variable 'c-basic-offset 4)
(set-variable 'tab-width 4))
((string-match "^/home/nickm/src/tor" fname)
(set-variable 'indent-tabs-mode nil)
(set-variable 'c-basic-offset 2))
((string-match "^/home/nickm/src/openssl" fname)
(set-variable 'indent-tabs-mode t)
(set-variable 'c-basic-offset 8)
(set-variable 'tab-width 8))
))))
-----

You'll note that it defaults to showing all trailing whitespace. The "cond"
test detects whether the file is one of a few C free software projects that I
often edit, and sets up the indentation level and tab preferences to match
what they want.

If you want to try this out, you'll need to change the filename regex
patterns to match where you keep your Tor files.

If you use emacs for editing Tor and nothing else, you could always just say:

-----
(add-hook 'c-mode-hook
(lambda ()
(font-lock-mode 1)
(set-variable 'show-trailing-whitespace t)
(set-variable 'indent-tabs-mode nil)
(set-variable 'c-basic-offset 2)))
-----

There is probably a better way to do this. No, we are probably not going
to clutter the files with emacs stuff.


Functions to use
~~~~~~~~~~~~~~~~

We have some wrapper functions like tor_malloc, tor_free, tor_strdup, and
tor_gettimeofday; use them instead of their generic equivalents. (They
always succeed or exit.)

You can get a full list of the compatibility functions that Tor provides by
looking through src/common/util.h and src/common/compat.h. You can see the
available containers in src/common/containers.h. You should probably
familiarize yourself with these modules before you write too much code, or
else you'll wind up reinventing the wheel.

Use 'INLINE' instead of 'inline', so that we work properly on Windows.

Calling and naming conventions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Whenever possible, functions should return -1 on error and 0 on success.

For multi-word identifiers, use lowercase words combined with
underscores. (e.g., "multi_word_identifier"). Use ALL_CAPS for macros and
constants.

Typenames should end with "_t".

Function names should be prefixed with a module name or object name. (In
general, code to manipulate an object should be a module with the same name
as the object, so it's hard to tell which convention is used.)

Functions that do things should have imperative-verb names
(e.g. buffer_clear, buffer_resize); functions that return booleans should
have predicate names (e.g. buffer_is_empty, buffer_needs_resizing).

If you find that you have four or more possible return code values, it's
probably time to create an enum. If you find that you are passing three or
more flags to a function, it's probably time to create a flags argument that
takes a bitfield.

What To Optimize
~~~~~~~~~~~~~~~~

Don't optimize anything if it's not in the critical path. Right now, the
critical path seems to be AES, logging, and the network itself. Feel free to
do your own profiling to determine otherwise.

Logging and Documentation
~~~~~~~~~~~~~~~~

Please see also: doc/CodingForTor/LoggingAndDocumentation

Last modified 6 years ago Last modified on Jun 11, 2011, 3:28:24 PM