The following information was cherry-picked from doc/HACKING/CodingStandards.md (onion) and doc/HACKING/HelpfulTools.md (onion). These *.md
files are up-to-date living documents and thus should be preferred over the following infomation.
= Coding in C
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