Use the following order for laying out the code in the application C source code:
Application standard header
Inclusion of system header files
Inclusion of local header files
Definition of constants
Definition of data types
Global variables (try to avoid these altogether)
Function prototypes
main()
function
Functions
A template application C source code file is provided in the myemboss applications directory, e.g.:
.../embassy/myemboss/src/template.c |
The file is shown below:
** @source __ApplicationName__ ** ** __ShortDescription__ ** ** @author Copyright (C) __Year__ __AuthorName__ ** @version __VersionNumber__ __description of version__</replaceable> ** @modified __EditDate__ __EditorName__ __description of edit__</replaceable> ** @@ ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ********************************************************************/ /* ==================================================================== */ /* ========================== include files =========================== */ /* ==================================================================== */ #include "emboss.h" /* Inclusion of system and local header files goes here */ /* ==================================================================== */ /* ============================ constants ============================= */ /* ==================================================================== */ /* #define and enum statements go here */ /* ==================================================================== */ /* ======================== global variables ========================== */ /* ==================================================================== */ /* Global variables definitions go here */ /* ==================================================================== */ /* ============================== data ================================ */ /* ==================================================================== */ /* Definition of datatypes go here */ /* ==================================================================== */ /* ==================== function prototypes =========================== */ /* ==================================================================== */ /* Function prototypes for public (external) functions go here */ /* @prog __ApplicationName **************************************************** ** ** __ShortDescription__ ** ******************************************************************************/ int main(int argc, char **argv) { } /* ==================================================================== */ /* ============================ functions ============================= */ /* ==================================================================== */
Standard sections in the file .../embassy/myemboss/src/template.c
are summarised below.
All application source code files must begin with the standard documentation header (see Appendix D, Code Documentation Standards).
The EMBOSS header file emboss.h
is included first followed by includes for any required system files. For example:
#include "emboss.h" #include <limits.h> #include <float.h>
emboss.h
includes the EMBOSS header file ajax.h
which has the following includes:
#include <stdio.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
There is therefore no need to include these files explicitly in the application source code.
These should be given in a block and documented where necessary. For example:
#define TIMEOUT 30 /* Arbitrary pipe timeout (secs) */ #define TIMEBUFFER 256 /* Arbitrary length buffer for time printing */ #define PUTTIMEOUT 120 /* Max no. of secs to write a file */ #define R_BUFFER 2048 /* Arbitrary length buffer for reentrant syscalls */
Or:
enum blastdbtype {BLAST1P, BLAST1N, BLAST2P, BLAST2N};
You should not use global variables unless absolutely necessary. Where they are used they should be documented.
Any unions and C data structure definitions that are specific to the application should be given next. All datatypes should be defined in the EMBOSS style. It is recommended, but not strictly required, that application data structures are documented in a standard way (see Appendix D, Code Documentation Standards).
The programming of new datatypes is covered in detail elsewhere (Section 5.3, “Objects (C Data Structures)”).
The main function is preceded with a standard documentation header (see Appendix D, Code Documentation Standards). The main()
function should be given before other functions. This saves people from having to wade through many functions before they find it, and also helps avoid accidental implicit function declarations.
Functions should be listed in the order they are prototyped and separated by whitespace (4 newlines). All application-specific functions should be declared static
and have a name that begins with the application name. It is recommended that all application functions are documented in a standard way (see Appendix D, Code Documentation Standards).
The programming of new functions is covered in more detail elsewhere (Section 5.3, “Objects (C Data Structures)”).
In header files, use the following order for the code:
Standard pre-processor directives
Inclusion of system header files
Inclusion of local header files
Definition of constants
Definition of public (external) data types
Function prototypes for public (external) functions
All exported prototype definitions must be bounded by the following comment definitions:
/* ** Prototype definitions */ ... exported function prototypes here ... /* ** End of prototype definitions */
This is to allow the information to be extracted for Windows compilation. The function names of exported prototypes must be on the same line as their return datatype.
A template header file is provided in the AJAX and NUCLEUS directories, e.g.:
.../emboss/ajax/core/template.h |
The file (which is the same for AJAX and NUCLEUS) is shown below:
#ifdef __cplusplus extern "C" { #endif #ifndef LibraryFileName_h #define LibraryFileName_h /* ==================================================================== */ /* ========================== include files =========================== */ /* ==================================================================== */ /* Inclusion of system and local header files goes here */ /* ==================================================================== */ /* ============================ constants ============================= */ /* ==================================================================== */ /* #define and enum statements go here */ /* ==================================================================== */ /* ========================== public data ============================= */ /* ==================================================================== */ /* Definition of public (external) data types go here */ /* ==================================================================== */ /* ======================= public functions =========================== */ /* ==================================================================== */ /* Function prototypes for public (external) functions go here */ #endif #ifdef __cplusplus } #endif
Use the following order for the source file:
Standard library documentation header
Inclusion of system header files
Inclusion of local header files
Definition of constants
Definition of global variables (avoid them!)
Definition of private data types
Function prototypes for private (static) functions
Definition of functions
A template source file is provided in the AJAX and NUCLEUS directories, e.g.:
.../emboss/ajax/core/template.c |
The file is shown below:
** @source __AJAX or NUCLEUS__ __LibraryArea__ functions ** ** __ShortDescription__ ** ** @author Copyright (C) __Year__ __AuthorName__ ** @version __VersionNumber__ __description of version__</replaceable> ** @modified __EditDate__ __EditorName__ __description of edit__</replaceable> ** @@ ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ********************************************************************/ /* ==================================================================== */ /* ========================== include files =========================== */ /* ==================================================================== */ /* Inclusion of system and local header files goes here */ /* ==================================================================== */ /* ============================ constants ============================= */ /* ==================================================================== */ /* #define and enum statements go here */ /* ==================================================================== */ /* ======================== global variables ========================== */ /* ==================================================================== */ /* Global variables definitions go here */ /* ==================================================================== */ /* ========================== private data ============================ */ /* ==================================================================== */ /* Definition of private datatypes go here */ /* ==================================================================== */ /* ====================== private functions =========================== */ /* ==================================================================== */ /* Function prototypes for private (static) functions go here */ /* ==================================================================== */ /* ===================== All functions by section ===================== */ /* ==================================================================== */ /* Functions definitions go here, organised into sections */
Standard sections in the library header and C source files are summarised below.
The contents of every header (*.h
) file must be enclosed in a standard pre-processor directive (below). LibraryFileName
is the name of the library file, e.g. str
for ajstr.h/c
:
#ifdef __cplusplus extern "C" { #endif #ifndef ajLibraryFileName
_h #define ajLibraryFileName
_h/* Everything else goes here */
#endif #ifdef __cplusplus } #endif
A standard documentation header (see Appendix D, Code Documentation Standards) should go at the top of every library source (*.c
) file.
Any files that are required for compilation are included before any code proper. Inclusions of system files are given before local files. You should never use nested includes.
These include #define
and enum
statements and should be given in a block and documented where necessary.
Global variables follow constants in the library source (*.c
) file. Global variables should normally be commented if their function is not obvious from their name. They should be avoided wherever possible.
Any unions and C data structures (objects) that are private (and should be declared as static
) are given in the library source (*.c
) file. Any public (external) unions and structures are given in the library header (*.h
) file. All datatypes should be defined in the EMBOSS style (Section C.8, “Structures and Unions”). All public datatypes must be documented in a standard way (see Appendix D, Code Documentation Standards). Such documentation is not required for private structures and unions, although it is recommended.
Programming of objects is covered in detail elsewhere (Section 5.3, “Objects (C Data Structures)”).
Avoid exporting names outside individual C source files; i.e., declare as static
(in the library source file *.c
) every function that you possibly can (i.e. any which are not known to be externally required). All functions must be prototyped using the full ANSI C style.
The functions are given last of all in the library source (*.c
) file. All public functions must be documented in a standard way (see Appendix D, Code Documentation Standards below). Such documentation is not required for private functions, although it is recommended.
The programming of new functions is covered in more detail elsewhere (Section 5.3, “Objects (C Data Structures)”).
Your code should be easy to read. This is perhaps more important than the code actually working. If it's easy to read then at least someone else stands a chance of fixing it, whereas if it's difficult to read, no one is ever easily going to be able to modify or improve it.
Lines should typically be no longer than 79/80 characters to avoid line-wrap on screen (or premature line termination on printouts), which can be confusing. Exceptions are allowed where it renders the code easier to read.
Variable names should not be too short or too long. Overly long variable names can make the code unreadable, names that are too short can make the code incomprehensible. That said, single characters (i
, j
, k
etc) are fine for standard loop counters. Use common sense to strike a balance. If for example you're coding a mathematical formula or algorithm from a paper, then use variables with the same name as the symbols. If a variable is a temporary one then make that clear in its name. Consider:
for (elementindex = 0; elementindex < DIMENSION; ++elementindex) printf("%d\n", element[elementindex]); for (i = 0; i < DIMENSION; ++i) printf("%d\n", element[i]);
In the first example, you have to read more text before you can recognize the for
loop idiom, and then you have more hard work to parse the loop body. Since clarity is the goal, a name should contain only necessary and sufficient information to identify the variable. Informative names are unnecessary, however, if the declaration and use of the variable is limited to a small, local section of code. Longer, more informative names are often suitable for variables with larger scope.
Matching braces should appear in the same column and indentation should be consistent. This is good:
int fred(void) { ... for(i=0; i<LIMIT; ++i) { ... } return 0; }
whereas this is messy:
int fred(void) { ... for(i=0; i<LIMIT; ++i) { ... } return 0; }
and so is this:
int fred(void) { ... for(i=0; i<LIMIT; ++i) { ... } return 0; }
Don't use braces unnecessarily. The following is good:
for(i=0; i<LIMIT; ++i) sum += i;
but this code is cluttered:
for(i=0; i<LIMIT; ++i) { sum += i; }
The body of a for
statement should appear in its own block distinct from the for
statement itself. The following could be confusing if nested in a larger body of code:
for(i=0; i<LIMIT; ++i) sum += i;
Indentation of 4 characters is recommended but more importantly, be consistent. If you find that indentation within nested loops results in many of the lines wrapping then you should check whether the code structure can be improved.
There are some lines you can add to your .emacs
file which will (usually) automatically place braces in the correct places and indent properly. They are available in the file http://emboss.open-bio.org/downloads/EmacsConfig and are shown below:
(defun set-if-void (symbol value) (or (boundp symbol) (set symbol value))) (require 'cc-mode) (setq auto-mode-alist (append '(("\\.C$" . c++-mode) ("\\.H$" . c++-mode) ("\\.cc$" . c++-mode) ("\\.hh$" . c++-mode) ("\\.c$" . c-mode) ("\\.h$" . c-mode) ("\\.m$" . objc-mode) ("\\.java$" . java-mode) ) auto-mode-alist)) (defconst emboss-c-style '((c-tab-always-indent . t) (c-comment-only-line-offset . 0) (c-hanging-braces-alist . ((brace-list-open))) (c-hanging-colons-alist . ((member-init-intro before) (inher-intro) (case-label after) (label after) (access-label after))) (c-cleanup-list . (scope-operator empty-defun-braces defun-close-semi)) ;; Uncomment the following line if you don't want newlines after semicolons ;; (c-hanging-semi&;comma-criteria) (c-offsets-alist . ((arglist-close . c-lineup-arglist) (substatement-open . 0) (case-label . 4) (block-open . 0) (knr-argdecl-intro . -))) ) "EMBOSS C Programming Style") ;; Customisations for all of c-mode, c++-mode, and objc-mode (defun emboss-c-mode-common-hook () ;; add EMBOSS style and set it for the current buffer (c-add-style "EMBOSS" emboss-c-style t) ;; offset customisations not in emboss-c-style (c-set-offset 'member-init-intro '++) ;; other customisations (setq tab-width 8 ;; this will make sure spaces are used instead of tabs indent-tabs-mode nil) ;; auto-newline [for hungry-delete use (c-toggle-auto-hungry-state 1)] (c-toggle-auto-state 1) ;; keybindings for C, C++, and Objective-C. Can put these in ;; c-mode-map because c++-mode-map and objc-mode-map inherit it (define-key c-mode-map "\C-m" 'newline-and-indent) ) (add-hook 'c-mode-common-hook 'emboss-c-mode-common-hook)
This will also let you reformat existing code (with some manual intervention) using the emacs command M-x indent-region
.