Engineering Standards Manual$Header: /cvsroot/aolserver/aolserver.com/docs/devel/tech/standards.html,v 1.2 2002/09/26 19:51:33 kriston Exp $
Contributed by George Nachman.
IntroductionThis manual is based on the Tcl/Tk Engineering Manual by John K. Ousterhout that is available at ActiveState. Most of this document is a subset of what his manual specifies, with the goal of being more practical and up-to-date than the original. For example, it is assumed that only an ANSI compiler will be used, whereas the Ousterhout's manual describes conventions that will also work with non-ANSI compilers. The Tcl/Tk Engineering Manual is still recommended reading, particularly with respect to the section on code documentation, which is not reproduced here.Table of Contents
Overall StructureEach module will be named nsxxx, where xxx is a short name that describes the module. Each module will have its own directory, and contain at least the following files:
If a module exports symbols, then a header file by the name of nsxxx.h should also be in that directory.
Makefile StructureUse this as a template for module makefiles:# # (dollar-sign)Header: (dollar-sign) # # nsexample -- # # Example AOLserver module Makefile. # # # AOLserver's location # # Since your module probably doesn't live inside the "aolserver" # directory, you can tell make where to find aolserver. # #NSHOME = /home/user/cvs/aolserver NSHOME = ../aolserver # # Module name # MOD = nsexample.so # # Objects to build # OBJS = nsexample.o # # Header files in THIS directory (included with your module) # HDRS = # # Extra libraries required by your module (-L and -l go here) # MODLIBS = # # Compiler flags required by your module (-I for external headers goes here) # CFLAGS = include $(NSHOME)/include/Makefile.module Header file structureUse this as a template for all header files:/* * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * file.h -- * * Description of file. * */ #ifndef FILE_H #define FILE_H static const char *RCSID_FILE_H = "(dollar-sign)Header: (dollar-sign), compiled: " __DATE__; /* * The following constants... */ #define ... /* * The following structure defines... */ typedef struct ... /* * Exported functions */ extern ... #endif /* FILE_H */ Header files never contain static symbols. Code File StructureEach source code file should contain a related set of procedures. The most manageable size for files is usually in the range of 500-2000 lines. Closely related functions should be placed as close together as possible.API functions (Ns_*) come first; exported functions that are not API calls (Ns*) come after those; static functions come last. Logical groups of functions can be separated like this:
/* *========================================================================== * This is where we torque the wingnut on the widget. *========================================================================== */ Use this as a template for all code files: /* * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * file.c -- * * Description of file. */ static const char *RCSID = "(dollar-sign)Header: (dollar-sign), compiled: " __DATE__ " " __TIME__; #include "file.h" /* * The following constants... */ #define ... /* * The following structure defines... */ typedef struct ... /* * Local functions defined in this file */ static int FunctionName(int x); /* * Static variables defined in this file */ static int nsNumFooBar; /* Number of foobars allocated */ ... /* *========================================================================== * API functions *========================================================================== */ (API function definitions go here) /* *========================================================================== * Exported functions *========================================================================== */ (Exported, non-api functions go here) /* *========================================================================== * Static functions *========================================================================== */ (Static functions go here) Source files should never contain extern statements; those belong in header files (called file.h in the above template). Function definitionsFunction definitions should follow this template:
/*
*----------------------------------------------------------------------
* FunctionName -
*
* Description of function.
*
* Results:
* This function returns ...
*
* Side effects:
* A new thread will be created.
*
*----------------------------------------------------------------------
*/
static int
FunctionName(int x)
{
...
}
All functions definitions begin on a new page (which is to say they should be preceeded by a control-L character). All functions must be typed: use void if the function returns no result. The second line gives the function's name and argument list. If there are many arguments, they should spill onto additional lines as such:
static int
FunctionThatTakesLotsOfParameters(int a, int b, int c, int d, int e,
int f, int g)
{
...
}
The same rule applies to prototypes. Parameter orderFunction parameters may be divided into three categories. In parameters only pass information into the function (either directly or by pointing to information that the function reads). Out parameters point to things in the caller's memory that the function modifies. In-out parameters do both. Below is a set of rules for deciding on the order of parameters to a function:
Naming Conventions
Basic Syntax Rules
Function names contain meaningPublic exported functions that are part of the API should begin with Ns_, as in:extern int Ns_ConnPort(Ns_Conn *conn); Functions that are to be used by other files in a module, but are not meant to be called from outside the module, should begin with Ns, as in: extern void NsDbInit(void); Global variables that do not have static scope begin with ns, as in: Ns_Cache *nsAdpCachePtr = NULL; C implementations of Tcl commands should be static functions ending with Cmd, as in: static int RegisterTagCmd(ClientData ignored, Tcl_Interp *interp,
int argc, char **argv);
Low-level coding conventionsIf you use Emacs, the following lisp (which you can put in your .emacs file) will make C-mode do much of the formatting for you (its default behavior is almost correct--this just makes indents be four spaces):(add-hook 'c-mode-hook (function (lambda () (setq c-basic-offset 4) (setq c-indent-level 4))))
foo(); /* * This is a comment. */ bar();
if (x == y) {
FooBar();
}
if (!strcmp(cmd, "put")) {
...
} else if (!strcmp(cmd, "get")) {
...
} else if (!strcmp(cmd, "reset")) {
...
} else {
...
}
switch (adPtr->exception) {
case ADP_OK:
exception = "ok";
break;
case ADP_BREAK:
exception = "break";
break;
....
}
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
if (foo == bar &&
baz == spoo &&
Ns_FooBarBaz() == NS_TRUE) {
...
}
Idioms, Canonical Forms, and Recommended PracticesThe following conventions are frequently used in AOLserver. They are the recommended way of implementing a behavior.
|