|
|
|
Did you remember...[[BR]][[BR]] - To build your code while configured with --enable-gcc-warnings?[[BR]] - To run "make check-spaces" on your code?[[BR]] - To write unit tests, as possible?[[BR]] - To base your code on the appropriate branch?[[BR]] - To include a file in the "changes" directory as appropriate?[[BR]][[BR]]Whitespace and C conformance[[BR]]!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~[[BR]][[BR]]Invoke "make check-spaces" from time to time, so it can tell you about[[BR]]deviations from our C whitespace style. Generally, we use:[[BR]][[BR]] - Unix-style line endings[[BR]] - K&R-style indentation[[BR]] - No space before newlines[[BR]] - A blank line at the end of each file[[BR]] - Never more than one blank line in a row[[BR]] - Always spaces, never tabs[[BR]] - No more than 79-columns per line.[[BR]] - Two spaces per indent.[[BR]] - A space between control keywords and their corresponding paren[[BR]] "if (x)", "while (x)", and "switch (x)", never "if(x)", "while(x)", or[[BR]] "switch(x)".[[BR]] - A space between anything and an open brace.[[BR]] - No space between a function name and an opening paren. "puts(x)", not[[BR]] "puts (x)".[[BR]] - Function declarations at the start of the line.[[BR]][[BR]]We try hard to build without warnings everywhere. In particular, if you're[[BR]]using gcc, you should invoke the configure script with the option[[BR]]"--enable-gcc-warnings". This will give a bunch of extra warning flags to[[BR]]the compiler, and help us find divergences from our preferred C style.[[BR]][[BR]]Getting emacs to edit Tor source properly[[BR]]!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^!^[[BR]][[BR]]Nick likes to put the following snippet in his .emacs file:[[BR]][[BR]]-----[[BR]] (add-hook 'c-mode-hook[[BR]] (lambda ()[[BR]] (font-lock-mode 1)[[BR]] (set-variable 'show-trailing-whitespace t)[[BR]][[BR]] (let ((fname (expand-file-name (buffer-file-name))))[[BR]] (cond[[BR]] ((string-match "!^/home/nickm/src/libevent" fname)[[BR]] (set-variable 'indent-tabs-mode t)[[BR]] (set-variable 'c-basic-offset 4)[[BR]] (set-variable 'tab-width 4))[[BR]] ((string-match "!^/home/nickm/src/tor" fname)[[BR]] (set-variable 'indent-tabs-mode nil)[[BR]] (set-variable 'c-basic-offset 2))[[BR]] ((string-match "!^/home/nickm/src/openssl" fname)[[BR]] (set-variable 'indent-tabs-mode t)[[BR]] (set-variable 'c-basic-offset 8)[[BR]] (set-variable 'tab-width 8))[[BR]] ))))[[BR]]-----[[BR]][[BR]]You'll note that it defaults to showing all trailing whitespace. The "cond"[[BR]]test detects whether the file is one of a few C free software projects that I[[BR]]often edit, and sets up the indentation level and tab preferences to match[[BR]]what they want.[[BR]][[BR]]If you want to try this out, you'll need to change the filename regex[[BR]]patterns to match where you keep your Tor files.[[BR]][[BR]]If you use emacs for editing Tor and nothing else, you could always just say:[[BR]][[BR]]-----[[BR]] (add-hook 'c-mode-hook[[BR]] (lambda ()[[BR]] (font-lock-mode 1)[[BR]] (set-variable 'show-trailing-whitespace t)[[BR]] (set-variable 'indent-tabs-mode nil)[[BR]] (set-variable 'c-basic-offset 2)))[[BR]]-----[[BR]][[BR]]There is probably a better way to do this. No, we are probably not going[[BR]]to clutter the files with emacs stuff.[[BR]][[BR]][[BR]]Functions to use[[BR]]!~~!~~!~~!~~!~~!~~!~~!~~[[BR]][[BR]]We have some wrapper functions like tor_malloc, tor_free, tor_strdup, and[[BR]]tor_gettimeofday; use them instead of their generic equivalents. (They[[BR]]always succeed or exit.)[[BR]][[BR]]You can get a full list of the compatibility functions that Tor provides by[[BR]]looking through src/common/util.h and src/common/compat.h. You can see the[[BR]]available containers in src/common/containers.h. You should probably[[BR]]familiarize yourself with these modules before you write too much code, or[[BR]]else you'll wind up reinventing the wheel.[[BR]][[BR]]Use 'INLINE' instead of 'inline', so that we work properly on Windows.[[BR]][[BR]]Calling and naming conventions[[BR]]!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~!~~[[BR]][[BR]]Whenever possible, functions should return -1 on error and 0 on success.[[BR]][[BR]]For multi-word identifiers, use lowercase words combined with[[BR]]underscores. (e.g., "multi_word_identifier"). Use ALL_CAPS for macros and[[BR]]constants.[[BR]][[BR]]Typenames should end with "_t".[[BR]][[BR]]Function names should be prefixed with a module name or object name. (In[[BR]]general, code to manipulate an object should be a module with the same name[[BR]]as the object, so it's hard to tell which convention is used.)[[BR]][[BR]]Functions that do things should have imperative-verb names[[BR]](e.g. buffer_clear, buffer_resize); functions that return booleans should[[BR]]have predicate names (e.g. buffer_is_empty, buffer_needs_resizing).[[BR]][[BR]]If you find that you have four or more possible return code values, it's[[BR]]probably time to create an enum. If you find that you are passing three or[[BR]]more flags to a function, it's probably time to create a flags argument that[[BR]]takes a bitfield.[[BR]][[BR]]What To Optimize[[BR]]!~~!~~!~~!~~!~~!~~!~~!~~[[BR]][[BR]]Don't optimize anything if it's not in the critical path. Right now, the[[BR]]critical path seems to be AES, logging, and the network itself. Feel free to[[BR]]do your own profiling to determine otherwise.
|