Coding Conventions
 
 
SILC code is consistent and documented throughout the source tree, and especially in the libraries, because we have a coding convention that our developers follow. When coding for SILC or submitting code for SILC software please follow these coding conventions. We care more about the consistency and documentation of the code rather than being able to identify who has written the piece of code.
 


Introduction
Naming Conventions
Indentation
Placing Braces
Commenting
General Appearance
Using Gotos
Debug Messages
Memory Allocation
Global Variables
Copyrights of the Code
 
 
Introduction
 
This document describes the coding style and coding conventions used in the SILC source tree. The purpose of the document is to describe the common way to program for SILC and thus should be learned when programming new code. The document describes various conventions regarding variable naming, function naming, indentation, overall appearance of a piece of code and how some of the technical issues has been done in the SILC and should be done in the future.
 
The coder should pay attention to the appearance, quality and the structure of the written code. When especially writing generic code, such as libraries the code should be written so that it is easy for another coder to look, read, understand, modify and add new code, even after a long time has passed since the code was last touched.
 
If you are editing existing source code you should preserve the same coding style. Even if you rewrite the code, or add large portions of new code try to preserve the consistensy of the old style. The key word here is the consistent look so that it is easy to read the code.
 
The language used in the code is English. It is used in variable naming, structures, types, comments, etc. Please, do not use any other language in SILC source tree.
 
 
Naming Conventions
 
Generic naming
 
All identifiers, whether they defines, functions or something else, with execption of variables, has a common naming convention. Usually all identifiers use `silc' prefix to indicate that the identifier is part of SILC distribution. For example, silc_server_init(), SILC_PACKET_TYPE_ERROR, etc. As mentioned however, variables, local or global, does not use this naming convention.
 
When coding generic and library code make sure the name space you are using is not already used. Also make sure that any identifier name is not a C or C++ reserved word or any system function name.
 
Lower lever routines, usually some library routines, may use their own naming convention if generic API is defined over them. The API uses the common naming convention while the lower level routines uses what ever they want. For example, ciphers are implemented currently in this way. They define common SILC Cipher API but the actual implementation of algorithms uses their own naming convention. Another example is the math library that uses its own function naming but we have our own SILC MP API over it that has been defined using common SILC naming.
 
When coding new library from scratch into the SILC source tree these naming conventions should be followed.
 
Variables
 
Variable names are always in lowercase and any mixed-case or totally uppercase variable names should be avoided. Variable names may include underscore if it is necessary.
 
Example:
unsigned char *id_string;
SilcClientEntry *client_entry;

 
The same name convention is used in structure field names. All fields in structures should be in lowercase. Global variables should have some sort of prefix to indicate that the variable is global. Note however, that in generic SILC code global variables should be avoided.
 
Local variable names should be as short as possible without losing meaning of the name. For example there is no reason to call loop counter as `loop_counter' when `i' is commonly used instead. Using variable name `tmp' is also ok and should be used when some temporary value is used.
 
#define's, Macros and Enumerations
 
All #define's should always be in uppercase to indicate that it is a define. As mentioned previously #define's and macros always use the `SILC' prefix. The names also uses always underscores.
 
Example:
#define SILC_PACKET_TYPE_NONE 0
#define SILC_SOME_MACRO (...)

 
Names of #define's and macros should be self explanatory. This may lead to long names but it is better than having some `#define SILC_KE1_SX' which does not tell you anything.
 
Type definitions
 
Type definitions (typedefs) uses some what different naming convention from variables and macros. Typedefs has mixed-case names and they never use underscores. Like in any other case the names should be self explanatory which may lead to long names but that is not a problem. The names should start with 'Silc'.
 
Example:
SilcSomeStruct
SilcServer
SilcClientConnection
SilcUInt32
SilcStatus

 
The names should tell what the typedef is about. If it is a typedef of a structure it should tell what the structure is for in the first place.
 
Structures
 
Same naming convention used in typedefs applies to names of structures as well. Same as with typedef, structure names should be self explanatory and should tell what the structure is made for.
 
Structures are used a lot in SILC. They are used as simple structures and as objects as well. When normal structures are needed they are defined as follows:
 
struct SilcDummyStruct {
  unsigned char *dummy;
};

struct SilcDummyStruct *dummy;
struct SilcDummyStruct foobar;

 
If the structure is a typedef then it is defined as follows:
 
typedef struct {
  unsigned char *dummy;
  unsigned int flags;
  void (*callback)(void *, unsigned int);
} SilcDummyStruct;

 
You can give name for the structure as well if you need it inside the structure, like to create a linked list. However, if you make it a typedef then usually the structure name is not used.
 
If the structure is a typedef to a pointer, which is very usual in SILC, then it is defined as follows:
 
typedef struct {
  unsigned char *dummy;
  unsigned int flags;
} *SilcDummy;

 
or if both pointer and structure are needed, then as follows:
 
typedef struct {
  unsigned int flags;
} *SilcDummy, SilcDummyStruct;

 
Most of the types in the SILC APIs are actually typedef pointers, and the structure is public and visible only if it really needs to be. Otherwise, it is common to define the structure in the source file, and forward declare it in the header.
 
Example:
typedef struct SilcMessagePayloadStruct
  *SilcMessagePayload;
typedef struct SilcDummyStruct *SilcDummy;

 
The pattern here is that all structures are named as `SilcXxxStruct', and when they are typedef'd pointers they are named as `SilcXxx'.
 
Functions
 
Function naming uses the common naming convention used in the SILC. All functions are always lowercase and they use underscores. The name of the function always starts with prefix `silc_'. The name of the function should be self explanatory which may lead to long names. The name of a function is constructed from following parts:
 
  silc_<application>_<module>_<function>
 
The <application> is for example <client> or <server>, however, it is always omitted (and must be omitted) when programming library code.
 
The <module> is the module you are programming currently. You should have a pretty good idea what you are programming and what the module does. For example, <cipher>, <config>, <command>, <packet>, etc.
 
The <function> is the description of the functionality of the function you are writing. Naturally it should be self explanatory and weird short names should be avoided. It is better to have long function names than some odd name that does not tell what it is about. Function naming could be for example, <read>, <new_id>, <register>, <find_by_name>, etc.
 
So, it is common in SILC to have function names, such as:
 
  silc_server_packet_send
  silc_server_packet_send_to_channel
  silc_client_packet_process
  silc_idcache_del_by_id
  silc_task_unregister_by_fd
  silc_protocol_excute_final
  silc_buffer_alloc

 
When function registers something the name of the function should generally be `silc_function_register' and unregistering should happen with `silc_function_unregister'. When function allocates something it should be called `silc_function_alloc' and when freeing it should be called `silc_function_free'. Respectively, with init/uninit functions.
 
When this naming convention is used consistently it is easy to remember what the name of the function is. For example, if you need buffer it is easy to figure out that the routines are most likely called `silc_buffer_*', and if you need to allocate buffer it is most likely called `silc_buffer_alloc'. This sort of naming makes the programming, in the long run, much cleaner, simpler and faster.
 
Inline functions
 
SILC uses quite a bit inline functions to optimize the code. The naming of inline functions must follow same convention as any normal function. All inline functions in SILC are defined and written into header files. Inline functions must be defined in following manner in the header file:
 
static inline void silc_dummy_inline(unsigned int flags)
{
  doing_little_dummy_things;
}

 
 
Indentation
 
SILC has been coded with Emacs so standard indentation of Emacs is used in the SILC code. The indentation is always 2 characters, not a tabulator. If you use Emacs then this should not be a problem. So, if you code for SILC be sure to format the code to the standard way used in the SILC before submitting the code.
 
A tip for those who think that these long function names etc are just too long to type, consider using dynamic abbreviation found in Emacs. With this cool feature you only have type some part of the string and then use the dabbrev to find the rest of the string. I guess, by default it is M-/ in Emacs but I have binded it into Shift-TAB so it is fast to use when typing. I also use a so called super-TAB to otherwise speed up the coding.
 
 
Placing Braces
 
The common fight about how the braces should be placed in the C code is solved in SILC code by using K&R style. Thus the opening of the brace is put to the last on the line and the closing brace is on first on its own line:
 
if (condition) {
  silc_something();
  silc_something_more();
}

 
The function's braces are as follows:
 
int silc_client_function(void)
{
  return 0;
}

 
More examples:
 
if (condition) {
  something;
  silc_something_more();
} else {
  something_else;
}
 
if (condition) {
  something;
  silc_something_more();
} else if (other_condition) {
  something;
  silc_something_more();
} else {
  something_else;
}

 
 
Commenting
 
SILC code is usually pretty well commented and this should be the way in the future as well. However, the comments should not tell how the code works, it should be apparent by looking at the code. Instead the commenting should tell what the function does. All functions should be commented. If nothing more a line of comment telling what the function is about helps a lot when you go back to it after six months. Static functions should be commented as well.
 
When writing a new header it is preferred that the header file is immediately written in the ROBOdoc documentation format. This is important when you are doing library code under lib/. There are plenty of examples of this format. The ROBOdoc is used automatically generate the Toolkit documentation.
 
Comments should use normal C-language comments /* */ and not C++ comments.
 
 
General Appearance
 
The code should be clean and good to eye, although the function of it must always supersede the appearance. However, it is nice to read code that looks good. Here are some issues on general appearance.
 
- Use empty lines when appropriate but not too much. There should not be excess empty lines at the end of file. However, using some empty lines in the code, instead of writing very compact code, makes the code better looking.
 
- The line is 79 characters long and not one character longer. Longer lines must be cut in two, or three, or ...
 
- Use spaces very much. Do not write things like `if(!k)', instead write `if (!k)'. Same with `for', `while', etc. Spaces should be put around all binary operators like `*', `==', `+', etc. Also, when setting a value to variable be sure to set spaces around `='. When writing argument list to a function, space should follow each of the comma in the list. However, do not use spaces with parenthesis, for example, `if ( !k )' is not accepted.
 
- If you are not sure about how something should be done or the code you've done is not finished, it should be commented with XXX plus explanation what is going on. For example, /* XXX hmm... how is this flushed? */
 
Source Files
 
All source files starts with a standard source file header. It includes author, copyright and other information. If you want you may write additional description of what the file is about after the header.
 
In the start of the source files should include the #include's that are needed. All library source files must include `silcincludes.h', this is a must. Client source file must include at least `clientincludes.h' and server source file must include `serverincludes.h'. Additional include's may be added as well, however, system specific includes should not be added directly (unless it is really a special case). Go see any source file as an example.
 
Header Files
 
As with source files, header files start with the default header. Header files are usually divided in three parts in SILC. At the start of header files should include all types and definitions, structure definitions, etc. After definitions should include macros and inline functions if any of those exist. After macros should include the public prototypes of the functions. Go see any header file as an example.
 
When you write new header file, remember to write it in the ROBOdoc format for Toolkit documentation.
 
 
Using gotos
 
Gotos are used in the SILC code quite often. If you know how to use goto's properly then it is ok to use them for example to optimize the code. If you use goto's then use them only to make forward jumps. Do not do backward jumps at all. If you don't know how to use goto's properly, do not use them.
 
 
Debug Messages
 
When writing new code it is recommended that the code produces some sort of debug messages. SILC has own debug logging system that must be used in the generic SILC code. Few macros exist:
 
  SILC_LOG_DEBUG
  SILC_LOG_HEXDUMP
  SILC_LOG_INFO
  SILC_LOG_WARNING
  SILC_LOG_ERROR
  SILC_LOG_FATAL

 
When doing debugging the most used macros are SILC_LOG_DEBUG and SILC_LOG_HEXDUMP. With first macro you can print out any sort of debug messages with variable argument list, for example:
 
  SILC_LOG_DEBUG(("Start"));
  SILC_LOG_DEBUG(("Packet length %d", packet_len));

 
Note the extra parenthesis that are required for the macro so that the variable argument list formatting would work correctly.
 
When you need to dump some data into screen you should use SILC_LOG_HEXDUMP macro. For example:
 
  SILC_LOG_HEXDUMP(("Packet"), packet->data,
    packet->len);
  SILC_LOG_HEXDUMP(("Packet, size %d", size),
    packet->data, packet->len);

 
In SILC_LOG_HEXDUMP the data to be dumped are set between the second last and last parenthesis in order that the data is first and the length of the data is next. If arguments are used they are used the same way as in SILC_LOG_DEBUG and the data to be dumped are set after the argument list is closed with the parenthesis.
 
 
Memory Allocation
 
Naturally, memory allocation is a big part of a program. However, there are few things that must be noted on the issue. SILC has defined its own memory allocation functions that must be used. System specific functions must not be used directly. There are functions like:
 
  silc_malloc
  silc_calloc
  silc_realloc
  silc_free

 
You should always use silc_calloc instead of silc_malloc because silc_calloc automatically zeroes the allocated memory area. This is important especially with structures because generally we want that all fields, by default, are zero.
 
So, instead of doing
 
  SilcStruct *ptr;
  ptr = silc_malloc(sizeof(*ptr));

 
You should do
 
  SilcStruct *ptr
  ptr = silc_calloc(1, sizeof(*ptr));

 
When freeing memory it should be zero'ed when appropriate. All memory allocations that handle sensitive data such as keys should be zero'ed by memset() before freeing the memory. Common way to do is:
 
  memset(ptr, 'F', sizeof(*ptr));
  silc_free(ptr);

 
Where 'F' indicates free'd memory if you'd ever check it with debugger. Other choice is to use 0 instead of 'F'. The pointer after freeing should be set to NULL if appropriate, ptr = NULL. Also, remember to zero any data inside the structure before freeing it if it contains sensitive data.
 
If you don't know what sensitive data is, ask about it. Generally, sensitive data is any secret key, private key, passwords, passphrases, and other similar information.
 
 
Global Variables
 
Avoid global variables at all cost in generic SILC code. They cause problems on some platforms, in Windows DLLs and when using multithreaded applications. If you absolutely need to use global variables, consult the other SILC developers first.
 
 
Copyrights of the Code
 
The original code in SILC is GPL licensed. The code that is in CVS is always GPL licensed. Some distributions may have some different license or dual license applied to it when it is packaged, but the actual raw SILC source is always GPL licensed.
 
New code will be accepted to the official SILC source tree if it is under GPL license or similar free license, or public domain. Code with restricting licenses will not be accepted to the SILC source tree. SILC is free software, open source, what ever, project and will remain as such. Also note, that code that must be in Toolkit distribution must be allowed to be relicensed under the Toolkit license. If this is not allowed, the code is not accepted to the SILC source tree.
 
Also, about authoring; If you write code to SILC don't forget to add yourself as author at the start of the file. The reason for this is of course that everybody should get the credits they deserve but also if problems occur we know who to blame. :)