SPRAAK
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Code documentation and markup

Some definitions:

item
a class, type, (inline) function, macro, variable, a predefinition or a documentation block
main item
an item defined at the top level in the C-code (always true for classes and functions)
sub-item
a field in a structure/union/enum or a function/macro argument

General rules (describing what where):

All main items in SPRAAK must be documented. The c-files contain both the documentation and the code. Documentation is placed right before or after the definition of the item or sub-item. The parser will extract the item name, type and all relevant information from the code. This automatic extraction avoids duplication of information (and hence errors).

A few examples:

spr_public_lo_type
typedef struct
{float re; // Real part of the complex number.
float im; // Imaginary part of the complex number.
} Complex; // A complex number.
spr_public_lo_func
int list_len(
List *head) // Head of the list.
// Calculate the length of a NULL terminated list, starting from (and including) the element <head>.
{int cnt;
for(cnt=0;head!=NULL;cnt++)
head = head->next;
return(cnt);
}

The documentation starts with an item marker (see Item markers: for more information on the format of these markers). The marker is followed by the actual definition of the item, interweaved with pieces of documentation placed in C-comments. The follow set of rules describe the link between the C-comments and the item or sub-items:

  1. if there are multiple comment blocks for an item or sub-item, the first comment block is supposed to be a short description
  2. if the first comment block contains a long dash ('–') the part before/after the long dash is assumed to be the short/long description respectively
  3. comment after the marker (see Item markers:) and before the actual definition of the item is considered to be a description of that item
  4. comment starting on the first line after de complete definition of the item (header for functions) is considered to be a description of that item
  5. comment in between the definition of the item and its first sub-item is assumed to be a description of the item
  6. comment in between the definition of two subitems is assumed to be a description of the first subitem
  7. comment after the last subitem but before closing the subitem list, i.e. before the closing '}' or ')', is assumed to be a description of the last subitem
  8. comment after the last subitem and after closing the subitem list but still on the same code line is assumed to be a description of the last subitem
  9. escaped new-lines in macro definitions behave as spaces, not as new-lines!

Item markers:

Item markers have the following format:

  spr_<scope>_<item_type>

where scope is one of the following:

public_hi
an item known at the high level interface – described in the user's manual, the library exports this symbol
public_lo
an item known at the low level interface – described in the programmer's manual, the library exports this symbol
protected
an item known at the library level – described in the developers' manual, the library does not exports this symbol but it is known within the library
private
an item known at the file level (this is the default) – listed in the appendix of the developer's manual (for reference only), the library does not exports this symbol, the symbol is only known within the score of the file that defines it

and item_type is one of the following:

class
definition of a class
type
definition of a type
func
definition of a function
afunc
definition of a function for which it must be possible to take the address (since C99 requires that the address is unique, this prevents certain optimizations, hence the need to mark these functions differently)
ifunc
definition of an inline function
var
definition of a global variable
doc
documentation only (no real item)
predef
a pre-definition, an include or an unstructured item; only relevant for the include files (cf. spr_nodoc)

The item markers can be preceded by the following markers:

spr_sdoc
item is a structure the contains embedded documentation (e.g. the structures for argument decoding, command parsing, ...);
spr_nodoc
item is only relevant for the include files; prevent the output of documentation (e.g. objects that are needed for the internal operation only)
spr_cmdoc
don't document this function: it is a class method and must be documented in that context only (no one is supposed to call the function directly).
spr_nohdr
item is only relevant for the documentation; prevent the output to the include files, e.g. objects that are platform dependent and can hence be coded differently (macro, function, inline function) or can be not implemented at all.

On top of this, the following special markers can be used:

spr_private_func_ini
this private function having no arguments and returning nothing must be called when initializing this module; support for this is either provided by the compiler and run-time library or by means of the SPRAAK-parser and the required initial call to spraak_ini()
spr_private_func_fini
this private function having no arguments and returning nothing must be called before terminating the program (and is not enlisted as a terminating function by means of spr_ini_register()); support for this is either provided by the compiler and run-time library or by means of the SPRAAK-parser and the required closing call to spraak_fini()
Note
The 'private' marker implies the 'static' required when defining module internal functions and variables. Specifing both 'spr_private_xxx' and 'static' is invalid.
In case the 'ini' and 'fini' specials are handled by the parser (lack of compiler support), the 'ini' and 'fini' functions will be exported (made public within the library), so despite the 'private' designation, the function names must still be unique. In accordance with their 'private' character, these functions will be neither listed in the documentation nor added to any header file nor be accessible from outside the library.
For more info on the initialization and termination order, see Module initilisation and finalisation.
Rationale:
By adding some extra markers and a smart parser, we prevent having to describe items three times: C-code, header files and documentation. This approach thus both saves work and prevent inconsistencies between code, header files and documentation.

By specifying the scope as well (dev, pub_lo, pub_hi), we can extract SPRAAK libraries (with appropriate header files and documentation) for the three expected user groups:

Specifing the item_type may seem redundant since a good parser can make the distinction between predefinitions, classes, functions, type definitions and variable definitions. However, on some platforms, exporting functions and variables to a final DLL (high and/or low level) requires additional markers in the code. Hence, a distinction had to be made between functions and variables and the rest. In order to have a fully orthogonal set of keywords and to be future proof, we descided on making the distinction between all items instead of just splitting in two classes (functions+variables and the rest).

Markup in header files

When put in a header files, the markup drops except for functions and variables. For functions and variables in the header file, the prefix is identical to the markup in the code but with '_cdecl' appended, allowing us to cope with platfom and/or compiler specific export keywords.

Class/structure member markup

The following markup symbols specify the scope in which the fields of structures and methods in classes can be accessed. The meaning is identical to that of C++. However, the actual enforcement of these specifications by means of shielding access to these fiels is not implemented since this would break inline functions. The member markup information is used for the documentation (the developers manuals indicate whether fields are private or protected, the programmers and users manuals simply do not list the non-public members). Even without strict enforcement, programmers must adhere to these specifications or bad things will happen to them (voodoo).

spr_public
the field is publicly visible (everyone can access it)
spr_protected
the field may only be accessed in derived classes and friend functions
spr_private
the field is only accessible from within this class
spr_readonly
the field may only be read by the application software (but is set by some SPRAAK routines –usualy a read or create routine– and hence cannot be made const)

Limitations:

In order to have good documentation, including fully qualified names for all items and sub-items, combined definitions of types and variables/functions are not allowed.

Examples of what not to do:

struct t_complex // let's define a structure
{float re; // real part
float im; // imaginary part
} // and a function all at once
complex_add(struct t_complex x,struct t_complex y)
{struct t_complex r;
r.re = x.re+y.re;
r.im = x.im+y.im;
return(r);
}
struct t_list_el // let's define a structure
{struct t_list_el *next;
void *content;
} *list = NULL; // and a variable all at once