Start Info Community Spielen

Morgengrauner Dokumentation

Dateipfad: /home/mud/mudlib/doc//driver/codestyle

    The LPMud gamedriver is by nature the result of the cooperative work
    of multiple programmers, often separated by large oceans and years
    of time. In order to keep the appearance of the driver source consistent
    (and with that maintainable), the following guidelines should be followed
    for all code contributions.

    For a quick start in how good driver source should look like, take
    a look at comm.{c,h}, object.{c,h} and mapping.{c.h}.

    The guidelines have a strong emphasis on code layout and commenting,
    stemming from the fact that proper layout and comments gave the
    incentive for LDMud in the first place. Right now, 50% of all lines
    are comments, and that has been proven to be a Good Thing.

    Any reader of the "real programmers don't write comments"-school
    of thought is asked to take his or her incompetence elsewhere.

    The language is ISO Standard C (also known as 'C89' or 'ANSI C').
    Common compiler extensions or features from the new C99 standard are
    permitted if their addition is transparent for other C89 compilers.
    For example: the 'inline' keyword permitted through the use of the
    INLINE macro; so are the Metrowerks-pragmas and GNU-attributes. Not
    permitted are GNU's local functions.

    System/Platform specifics are to be detected by the configure script
    and provided with transparent implementations in port.{c,h} (or for
    module-specific dependencies in the respective modules).

    Adherence to the Standard has the following implications:

     - All functions must be fully prototyped.
     - Standard types like size_t, ssize_t or ptrdiff_t are to be used
       whereever possible.
     - Unixisms like
           a = malloc(20);
           b = malloc(20);
           c = b-a;
       are not legal and shouldn't be used.
     - Don't make assumptions about the size of the base types (e.g.
       a char might have more than 8 bits). If such an assumption
       is unavoidable, comment it clearly and if possible add a test
       to raise a compile or runtime error if the assumption is not met.

    All modules (.c-files) have to have their interface in an accompaning
    .h-file. The header file must be guarded against repeated inclusion
    with the normal
        #ifndef HEADERNAME_H
        #define HEADERNAME_H 1
        #endif /* HEADERNAME_H */
    construct. To use a module, its headerfile must be included - no random
    'extern' declarations.

    Every module must include "driver.h" which in turn includes the
    portability headers and provides common defines.

    Use the driver-provided types and macros like Bool or p_int.

    Code should be written defensively and readable. This is not the IOCCC.

    No magic numbers - use #defines to give them names.

    Add sanity checks where useful. If the checks are costly, enclose
    them in a #ifdef DEBUG...#endif bracket.

    Comment questionable code or opportunities for possible extensions with a
    'TODO: ...' comment. For multiline comments, use 'TODO::' on the second
    and following lines (this makes reading a grep easier).

    Comment temporary debug code with a 'DEBUG:' comment. Similar, debug
    output should always begin with 'DEBUG:'.

    Variable identifiers should start with a lowercase letter, function
    identifiers may start with upper or lowercase, constant identifiers
    should start with an uppercase letter. Macro identifiers should be
    all UPPERCASE, other identifiers may be under_scored or SkudlyCaps.
    Hungarian notation is accepted only in a very light form: pFoo for
    pointers, ppFoo for pointer to pointers, iFoo for integer types,
    sFoo for string pointers, aFoo for complex types - you get the
    idea. But no alpzsFoo and friends.

    f_xxx() function names are reserved for efun implementations.
    typedef'd typenames should end in _t (e.g. 'mapping_t'), struct
    names should end in _s (e.g. 'struct instrs_s').

    Indentation is 4 spaces per level. No tab characters anywhere!

    The indentation style is a variant of the 'Allman style':

        if (foo)
        } /* if (foo) */

    Note the comment at the closing brace!

    One line bodies may be written as

        if (foo) body;


        if (foo)

    _if_ it improves the readability.

    Similar, the typical layout of a function is:

        static int
        function_name ( arg1 , arg2)

        /* Twiddle  with  and return the result.

        } /* function_name() */

    If an expression (argument list, ...) extends over several, the first
    literal element on a line should be an operator or syntactical marker:

        if (condition1
         && (   condition2
             || condition3)

        printf( "..."
              , arg1, arg2, arg3

    Be generous with whitespace - both horizontal and vertical.

    [ The reasoning behind this style is to use the language elements
      to create strong visual structures for the eyes to follow. By doing so,
      the structure of the program becomes obvious without much
      conscious thought.

    The comments also follow the idea of giving strong visual clues of
    how the program is structured.

    Horizontal lines should be created as

        /* - - -... - - - */

    The '---' line is the normal separator between the components of a
    source file (includes, variable declarations, macro declarations,
    the separate functions). The '===' line can be used to separate
    larger sections of a source file (e.g. the lowlevel routines from
    the efun implementations). '- -' lines, which usally span less than
    the whole line, can be used to subdivide large functions (though then
    it's often better to split the function into several small ones).

    A '***' line is reserved for the end of every source file.

    A '/* --- Subsection --- */' is also good to separate subsections.

    Vertical lines are to be constructed as


    No box comments.

    Every function must have a head comment explaining the meaning
    of the arguments, what the function does, and the possible results.
    For efun implementations, this comment should be identical to the
    man page.

    Within a function, every variable should be commented as

       int foo;  /* short comment */
       int bar;
         /* long comment which doesn't fit on one line.

    The major steps in a function should be preceeded by a comment
    explaining them. Also, wherever a critical design decision has
    been made, a comment should line out the whats and whys:

        /* Duplicate the stored arguments for the function call.
         * (It's tempting to use the stored arguments directly
         *  in the last pass; however it's not guaranteed that
         *  the last pass actually comes this far.)

    A typical file layout, commentwise, looks like this:

         * Gamedriver Bouncing module.
         * 'Big picture' description of the module and its
         * relation to the other gamedriver parts.
         * Tricky design discussions also belong in here.

        #include "driver.h"
        #include "typedefs.h"


        #include "bounce.h"
        #include "backend.h"


        /* --- User information --- */
        interactive_t *all_bouncers[MAX_PLAYERS];

        /* ---  Statistics --- */

        p_int number_of_calls;

        add_bouncer (interactive_t *bouncer)

        /* This function adds  to the all_bouncers[].
            int i;  /* search index */

        } /* add_bouncer() */


zurück zur Übersicht