X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=docs%2Fcoding-style.html;h=8fbb27688cc975c3823ed19517201e9f299a7a72;hp=ba935092ba32b7a8fb97687d25d988517c14c0b6;hb=dcf739bd7fb7de140be3bafb4ce211e2e5c7bba9;hpb=05f35ec5085e59c3fd2d36fdba7df3b9978f4f60 diff --git a/docs/coding-style.html b/docs/coding-style.html index ba93509..8fbb276 100644 --- a/docs/coding-style.html +++ b/docs/coding-style.html @@ -1,22 +1,23 @@ - Access To The GHC CVS Repository - + + Style Guidelines for fptools -

Coding suggestions for GHC/Hugs related code

+

Style Guidelines for fptools

Comments

-NB These are just suggestions. They're not set in stone. Some of -them are probably misguided. If you disagree with them, feel free to -modify this document (and make your commit message reasonably informative) -or mail someone (eg The FP-CVS mailing list or -reid-alastair@cs.yale.edu). +

These coding style guidelines are mainly intended for use in +ghc/rts and ghc/includes. +

NB These are just suggestions. They're not set in stone. Some of +them are probably misguided. If you disagree with them, feel free to +modify this document (and make your commit message reasonably +informative) or mail someone (eg. The GHC mailing list)

References

@@ -24,68 +25,90 @@ If you haven't read them already, you might like to check the following. Where they conflict with our suggestions, they're probably right.

Portability issues

  • When defining a macro, always put parens round args - just in case. @@ -234,73 +294,9 @@ instead of #define add(x,y) x+y -
  • -Don't define macros that expand to a list of statements. -You could just use braces as in: - -
    -  #define ASSIGN_CC_ID(ccID)              \
    -        {                                 \
    -        ccID = CC_ID;                     \
    -        CC_ID++;                          \
    -        }
    -
    - -but it's better to use the "do { ... } while (0)" trick instead: - -
    -  #define ASSIGN_CC_ID(ccID)              \
    -        do {                              \
    -        ccID = CC_ID;                     \
    -        CC_ID++;                          \
    -        } while(0)
    -
    - -The following explanation comes from -The Usenet C programming FAQ -
    -10.4:   What's the best way to write a multi-statement macro?
    -
    -A:      The usual goal is to write a macro that can be invoked as if it
    -        were a statement consisting of a single function call.  This
    -        means that the "caller" will be supplying the final semicolon,
    -        so the macro body should not.  The macro body cannot therefore
    -        be a simple brace-enclosed compound statement, because syntax
    -        errors would result if it were invoked (apparently as a single
    -        statement, but with a resultant extra semicolon) as the if
    -        branch of an if/else statement with an explicit else clause.
    -
    -        The traditional solution, therefore, is to use
    -
    -                #define MACRO(arg1, arg2) do {  \
    -                        /* declarations */      \
    -                        stmt1;                  \
    -                        stmt2;                  \
    -                        /* ... */               \
    -                        } while(0)      /* (no trailing ; ) */
    -
    -        When the caller appends a semicolon, this expansion becomes a
    -        single statement regardless of context.  (An optimizing compiler
    -        will remove any "dead" tests or branches on the constant
    -        condition 0, although lint may complain.)
    -
    -        If all of the statements in the intended macro are simple
    -        expressions, with no declarations or loops, another technique is
    -        to write a single, parenthesized expression using one or more
    -        comma operators.  (For an example, see the first DEBUG() macro
    -        in question 10.26.)  This technique also allows a value to be
    -        "returned."
    -
    -        References: H&S Sec. 3.3.2 p. 45; CT&P Sec. 6.3 pp. 82-3.
    -
    - -
  • -Don't even write macros that expand to 0 statements - they can mess you -up as well. Use the doNothing macro instead. -
    -  #define doNothing() do { } while (0)
    -
    - +
  • Don't declare and initialize variables at the same time. +Separating the declaration and initialization takes more lines, but +make the code clearer.
  • Use inline functions instead of macros if possible - they're a lot @@ -315,6 +311,10 @@ of side effects, evaluation order, multiple evaluation, etc.
  • Inline functions have call-by-value semantics whereas macros are call-by-name. You can be bitten by duplicated computation if you aren't careful. + +
  • You can use inline functions from inside gdb if you compile with + -O0 or -fkeep-inline-functions. If you use macros, you'd better + know what they expand to. However, note that macros can serve as both l-values and r-values and @@ -378,11 +378,53 @@ If any uses of the function remain, they will refer to the single copy in the library. +

  • +Don't define macros that expand to a list of statements. +You could just use braces as in: + +
    +  #define ASSIGN_CC_ID(ccID)              \
    +        {                                 \
    +        ccID = CC_ID;                     \
    +        CC_ID++;                          \
    +        }
    +
    + +(but it's usually better to use an inline function instead - see above). + +

  • +Don't even write macros that expand to 0 statements - they can mess you +up as well. Use the doNothing macro instead. +
    +  #define doNothing() do { } while (0)
    +
    +
  • -Try to use ANSI C's enum feature when defining lists of constants of the -same type. You'll notice that gdb works better when you do this. -For example: +This code +
    +int* p, q;
    +
    +looks like it declares two pointers but, in fact, only p is a pointer. +It's safer to write this: +
    +int* p;
    +int* q;
    +
    +You could also write this: +
    +int *p, *q;
    +
    +but it is preferrable to split the declarations. + +
  • +Try to use ANSI C's enum feature when defining lists of constants of +the same type. Among other benefits, you'll notice that gdb uses the +name instead of its (usually inscrutable) number when printing values +with enum types and gdb will let you use the name in expressions you +type. +

    +Examples:

         typedef enum { /* N.B. Used as indexes into arrays */
          NO_HEAP_PROFILING,		
    @@ -424,44 +466,35 @@ instead of
         # define TYPEchar  'Y'
         # define TIMEchar  'T'
     
    -ToDo: at the time of writing, we still use the former. -
  • -Alastair likes to use stgCast instead of C syntax. He claims -it's easier to write and easier to grep for. YMMV. -
    -#define stgCast(ty,e) ((ty)(e))
    -
    +
  • Please keep to 80 columns: the line has to be drawn somewhere, +and by keeping it to 80 columns we can ensure that code looks OK on +everyone's screen. Long lines are hard to read, and a sign that the +code needs to be restructured anyway. -
  • We don't care too much about your indentation style but, if -you're modifying a function, please try to use the same style as the -rest of the function (or file). +
  • When commenting out large chunks of code, use #ifdef 0 +... #endif rather than /* ... */ because C doesn't +have nested comments. + +
  • When declaring a typedef for a struct, give the struct a name +as well, so that other headers can forward-reference the struct name +and it becomes possible to have opaque pointers to the struct. Our +convention is to name the struct the same as the typedef, but add a +leading underscore. For example: -

    -On which note: -Hugs related pieces of code often start with the line: -

    -  /* -*- mode: hugs-c; -*- */
    -
    -which helps Emacs mimic the indentation style used by Mark P Jones -within Hugs. Add this to your .emacs file.
    -  (defun hugs-c-mode ()
    -    "C mode with adjusted defaults for use with Hugs (based on linux-c-mode)"
    -    (interactive)
    -    (c-mode)
    -    (setq c-basic-offset 4)
    -    (setq indent-tabs-mode nil) ; don't use tabs to indent
    -    (setq c-recognize-knr-r nil)  ; no K&R here - don't pay the price
    -    ; no: (setq tab-width 4)
    -
    -    (c-set-offset 'knr-argdecl-intro    0)
    -    (c-set-offset 'case-label           0)
    -    (c-set-offset 'statement-case-intro '++)
    -    (c-set-offset 'statement-case-open  '+)
    -    )
    +  typedef struct _Foo {
    +    ...
    +  } Foo;
     
    +
  • Do not use ! instead of explicit comparison against +NULL or '\0'; the latter is much clearer. + +
  • We don't care too much about your indentation style but, if +you're modifying a function, please try to use the same style as the +rest of the function (or file). If you're writing new code, a +tab width of 4 is preferred. @@ -473,12 +506,37 @@ Don't be tempted to reindent or reorganise large chunks of code - it generates large diffs in which it's hard to see whether anything else was changed.

    -If you must reindent or reorganise, don't do anything else in that commit -and give advance warning that you're about to do it in case anyone else -is changing that file. +If you must reindent or reorganise, don't include any functional +changes that commit and give advance warning that you're about to do +it in case anyone else is changing that file. +

    Commandline arguments

    + +A program in fptools should try follow the following rules for +commandline arguments: + + + +When an unknown commandline argument is encountered, the program +should display usage information on stderr and exit unsuccessfully.