X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=doc%2FCodingStyle;h=9160adcc60297fbff4599f0df7fb35c119de51b2;hb=HEAD;hp=251deb918c967d66cd05e3dd1f5cb6a7928f0afe;hpb=318d79b391bf6288e3e28c840217a7097f3d0392;p=runtime.git diff --git a/doc/CodingStyle b/doc/CodingStyle index 251deb91..9160adcc 100644 --- a/doc/CodingStyle +++ b/doc/CodingStyle @@ -15,20 +15,20 @@ Naming Generic naming -All identifiers, whether they defines, functions or something else, with -execption of variables, has a common naming convention. Usually all +All identifiers, whether they are defines, functions or something else, with +exception 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, +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. -Lower lever routines, usually some library routines, may use their +Lower level 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 GMP math library that uses its own function naming but we have our +the MPI 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 convention. @@ -95,39 +95,47 @@ And used as `struct SilcDummyStruct *dummy'. However, this is quite rarely used in the SILC, instead structures are typedef'd as following later. When structure is used as object they are defined as follows, - typedef struct SilcDummyStruct { + typedef struct SilcDummyObject { unsigned char *dummy; unsigned int flags; void (*callback)(void *, unsigned int); - } SilcDummyObject; + } SilcDummyStruct; -If the SilcDummyStruct is not needed it may be omitted (which is very +If the SilcDummyObject is not needed it may be omitted (which is very common in SILC code), leaving, typedef struct { unsigned char *dummy; unsigned int flags; void (*callback)(void *, unsigned int); - } SilcDummyObject; + } SilcDummyStruct; Finally, it is common that structures are typedef'd pointers as they are very flexible to use, - typedef SilcDummyObject *SilcDummy; + typedef SilcDummyStruct *SilcDummy; + +or, + + typedef struct { + unsigned char *dummy; + unsigned int flags; + void (*callback)(void *, unsigned int); + } SilcDummyStruct, *SilcDummy; It is common in SILC to typedef structures instead of defining name for the structure. In this case the structure may be used without defining `struct' to the code, For example, - SilcDummyObject dummy_obj; - SilcDummyObject *dummy; + SilcDummyStruct dummy_obj; + SilcDummyStruct *dummy; If the structure has a pointer typedef then they are defined as normal variables but for real they are pointers, For example, SilcDummy dummy; dummy = silc_calloc(1, sizeof(*dummy)); - dummy->flags = 0; + dummy->flags = SILC_DUMMY_EMPTY; This convention is very common in SILC code and has been used consistently throughout the code. The pattern here is that all structures are named @@ -177,8 +185,8 @@ 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 +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. @@ -191,21 +199,17 @@ 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, -extern inline void silc_dummy_inline(unsigned int flags) +static inline void silc_dummy_inline(unsigned int flags) { doing_little_dummy_things; } -Because the function is defined as extern they can be included into -public header files. Do not forget to define inline function as extern. -There are no any explicit prototype definitions for inline functions. - 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 +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. @@ -213,8 +217,8 @@ 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 +then use the dabbrev to find the rest of the string. I guess, by +default it is M-/ in Emacs but I have bound it into Shift-TAB so it is fast to use when typing. @@ -258,6 +262,9 @@ More examples, something_else; } + if (condition) + oneline_no_braces; + Commenting ========== @@ -270,11 +277,11 @@ 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. -The commenting of functions in SILC has been made into the source files, -and not in the header files where the function prototypes reside. Header -files usually includes structure comments, macro comments and perhaps -some other relevant commenting but usually not function comments. -It is also Ok to comment the code inside function when it is needed. +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. @@ -288,25 +295,25 @@ that looks good. Here are some issues on general appearance. o 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 makes the code better - looking. + using some empty lines in the code makes the code better + looking. o The line is 79 characters long and not one character longer. Longer lines must be cut in two, or three, or ... o 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 `*', + 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 + 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 + list. However, do not use spaces within parenthesis, for example, `if ( !k )' is not accepted. o 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? */ + /* XXX hmm... how is this flushed? */ Source Files @@ -317,9 +324,9 @@ Now, this really isn't that important but some sort of header should be in all source files. 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 +needed. All library source files must include `silc.h', this is +a must. Client source file must include at least `silcclient.h' and +server source file must include `silcserver.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. @@ -342,7 +349,9 @@ 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. However, if you don't know how to use goto's do not use them. +code. If you use goto's then use them only to make forward jumps, try +to avoid backward jumps at all cost. If you don't know how to use goto's +do not use them. Debug Messages @@ -359,7 +368,7 @@ in the generic SILC code. Few macros exist, SILC_LOG_ERROR SILC_LOG_FATAL -When doing debugging the most used macros are SILC_LOG_DEBUG and +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, @@ -421,7 +430,7 @@ by memset() before freeing the memory. Common way to do is, 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 +Other choice is to use 0 instead of 'F'. The pointer after freeing should be set to NULL if appropriate, ptr = NULL. Note that some functions in the SILC library handles the zeroing of @@ -480,7 +489,7 @@ static void silc_callback(void *context) /* Register async operation */ -void silc_async_operation_register(int fd, SilcAsyncCb callback, +void silc_async_operation_register(int fd, SilcAsyncCb callback, void *context) { /* Register and return immediately */ @@ -500,7 +509,7 @@ void silc_async_operation(int fd, SilcAsyncCb callback, void *context) if (callback) (*callback)(context); } - + Now, after the registeration of the async operation in this dumb example the silc_start returns immediately. Lets say, 10 seconds later the @@ -509,7 +518,7 @@ timeout) by calling silc_async_operation which on the other hand will call the callback function after it has finished. The context that was passed to the registeration function is now passed back to the callback function. Thus, you will get the context you wanted. This is -the typical scenario where callback functions come in very handy. This +the typical scenario where callback functions come in very handy. This is also the best way to pass context's that are needed later without making them global context's. And as long as the context's are defined as void * they can be what ever contexts making the functions, that @@ -528,7 +537,7 @@ and task system implemented in core library uses extensively callback functions. Timeout's uses callbacks as well. SILC Key Exchange protocol uses callback functions too. The callback function in SKE provides packet sending without defining into the SKE code how the packets -should be sent thus making it generic for both client and server +should be sent thus making it generic for both client and server (and actually to any application for that matter). There are some technical issues on callback programming that are @@ -556,9 +565,9 @@ common in SILC code. o You must explicitly cast the void * context's to correct type in the callback function. Of course you must be careful - to cast them to the correct type as they are void * they + to cast them to the correct type as they are void * they could be anything. Many times this causes problems when you - forget what was the type you passed to it. Callback + forget what was the type you passed to it. Callback programming may get very complex. o You cannot use inline functions as callback functions, @@ -566,15 +575,70 @@ common in SILC code. Callback programming may be hard to understand from first standing if you haven't done these before, and debugging them may be pain in the -ass sometimes. But after the grand idea behind callback functions +ass sometimes. But after the grand idea behind callback functions becomes clear they are a wonderful tool. +Lists +===== + +SILC has two different list API's. The List API and the Dynamic List API. +For definitions of List API see lib/silcutil/silclist.h and for Dynamic +List API see lib/silcutil/silcdlist.h. Following short example of the +List API. + +List API + +typedef struct SilcDummyStruct { + int dummy; + void *context; + struct SilcDummyStruct *next; +} SilcDummy; + +int main() +{ + SilcList list; + SilcDummy *dummy; + SilcDummy *entry; + + /* Initialize the list */ + silc_list_init(list, struct SilcDummyStruct, next); + + /* Allocate one list entry */ + dummy = silc_calloc(1, sizeof(*dummy)); + dummy->dummy = 100; + dummy->context = NULL; + + /* Add the entry to the list */ + silc_list_add(list, dummy); + + /* Allocate second list entry */ + dummy = silc_calloc(1, sizeof(*dummy)); + dummy->dummy = 3000; + dummy->context = NULL; + + /* Add the entry to the list */ + silc_list_add(list, dummy); + + /* Then traverse the list, print the values, remove from list and free + memory */ + silc_list_start(list); + while ((entry = silc_list_get(list)) != SILC_LIST_END) { + fprintf(stderr, "%d\n", entry->dummy); + + /* Remove from list and free memory */ + silc_list_del(list, entry); + silc_free(entry); + } + + return 0; +} + + Copyrights of the Code ====================== -The original code in SILC is GPL licensed. GMP is GPL licensed as well -and zlib is with free license as well. New code will be accepted to +The original code in SILC is GPL licensed. New code will be accepted to the official SILC source tree if it is coded in GPL or similiar free license as GPL is, and of course if it is public domain. Code with restricting licenses will not be accepted to the SILC source tree. @@ -583,5 +647,5 @@ as such. 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 +of course that everybody should get the credits they deserve but also if problems occur we know who to blame. :)