$Header: /cvsroot/aolserver/aolserver.com/docs/devel/tech/standards.html,v 1.1 2002/03/07 19:15:35 kriston Exp $
Contributed by George Nachman.
Based on the Tcl/Tk Engineering Manual by John K. Ousterhout
If a module exports symbols, then a header file by the name of nsxxx.h should also be in that directory.
# # (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
/* * 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.
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).
/* *---------------------------------------------------------------------- * 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.
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);
(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(); }and
static void FooBar(void) { Foo(); }
static void FooBar(void) { int blah; ... if (blah != 0) { char *string; ... } }
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 (++c != NULL) { foo(); }
if (foo == bar && baz == spoo && Ns_FooBarBaz() == NS_TRUE) { ... }
The leftmost asterisk should begin on the column that is one space after the rightmost character of the longest type name. If there are no pointers, then every variable name should begin on the column that is one space after the rightmost character of the longest type name.
void Foo(void) { int bar; unsigned int *fooPtr; int ****extremePtrPtrPtrPtr; /* Just an example! */ ...
void Foo(void) { int bar; unsigned int foo; char baz; ...
static void *Foo(int *fooPtr); int *fooPtr = (int *) barPtr;
static int Foo(void) { ... FooBar(); return code; }
#define CONFIG_CACHE "Cache" /* Enable caching in this module? */ #define CONFIG_FOO "Foo" /* What is foo? */ #define DEFAULT_CACHE NS_TRUE /* Caching is on */ #define DEFAULT_FOO "Bar" /* Foo is bar */
return foo;
return (foo);
return (sqrt(variance) + foo() / bar() - (MAGIC + getch()) % 99);
if (foo)
and if (!foo)
; rather, say:
if (foo == NS_TRUE) { ... }
if (foo == NS_FALSE) { ... }
For pointers, use NULL
:
if (fooPtr == NULL) { ... }
if (fooPtr != NULL) { ... }
'\0'
when checking for equality to zero:
if (*ch == '\0') { ... }
if (foo == 0) { ... }