X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fcoding-style.html;h=8fbb27688cc975c3823ed19517201e9f299a7a72;hb=8dbd52c7606588ab7fc7ffd3a54641b7cadc4431;hp=4f39cbfc53ea0fcfb9db4096c431c675e1935d1a;hpb=5e2b22a5efbc9444a56346f3f93d863703dd1263;p=ghc-hetmet.git diff --git a/docs/coding-style.html b/docs/coding-style.html index 4f39cbf..8fbb276 100644 --- a/docs/coding-style.html +++ b/docs/coding-style.html @@ -1,15 +1,19 @@
-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.
+
no_return
and
-unused
)
+Some of these gcc/ANSI features could be avoided (for example, we -could use __inline__ instead of inline or use the usual PROTO((...)) -trick in function prototypes) - but some of them can't be avoided -so we don't try with the others.
+In addition we use ANSI-C-style function declarations and +prototypes exclusively. Every function should have a prototype; +static function prototypes may be placed near the top of the file in +which they are declared, and external prototypes are usually placed in +a header file with the same basename as the source file (although there +are exceptions to this rule, particularly when several source files +together implement a subsystem which is described by a single external +header file). -
Most of these features are actually part of the new C9X standard, -so we hope to have mostly conformant code at some point in the future. +
no_return
and
+unused
)
+Rts.h
,
-POSIX_SOURCE
is automatically defined for you before any
-system headers are slurped in, unless you define
-NON_POSIX_SOURCE
prior to including Rts.h
.
-A good C library will use the POSIX_SOURCE
define to
-eliminate non-posix types and function prototypes, so the compiler
-should complain if you venture outside the POSIX spec.POSIX_SOURCE
by default, but found that this caused more
+problems than it solved, so now we require any code that is
+POSIX-compliant to explicitly say so by having #include
+"PosixSource.h"
at the top. Try to do this whenever possible.
-/* minimum alignment of unsigned int */ @@ -116,47 +124,37 @@ These macros tell you which alignment to use #define ALIGNMENT_DOUBLE 4-
sizeof(int) != sizeof(ptr)
on that platform.
--Use PK_FLT(addr), PK_DBL(addr) to read StgFloat and -StgDouble values from the stack/heap, and ASSIGN_FLT(val,addr)/ -ASSIGN_DBL(val,addr) to assign StgFloat/StgDouble values to heap/stack -locations. These macros take care of alignment restrictions. +
-Heap/Stack locations are StgWord aligned; the alignment requirements -of an StgDouble may be more than that of StgWord, but we don't pad -misaligned StgDoubles (doing so would be too much hassle). +
-Doing a direct assignment/read of an StgDouble to/from a mis-aligned
-location may not work, so we use the ASSIGN_DBL(,)/PK_DBL() macro,
-which goes via a temporary.
+Use PK_FLT(addr)
, PK_DBL(addr)
to read
+StgFloat and StgDouble values from the stack/heap,
+and ASSIGN_FLT(val,addr)
/
+ASSIGN_DBL(val,addr)
to assign StgFloat/StgDouble values
+to heap/stack locations. These macros take care of alignment
+restrictions.
-Problem: if the architecture allows mis-aligned accesses, but prefers
-aligned accesses, these macros just add an extra level of indirection.
-We need to distinguish between an architecture that allows mis-aligned
-accesses and one that just imposes a performance penalty (this is most
-of them). Perhaps have PREFERRED_ALIGNMENT and REQUIRED_ALIGMENT
-configurations?
+Heap/Stack locations are always StgWord aligned; the
+alignment requirements of an StgDouble may be more than that
+of StgWord, but we don't pad misaligned StgDoubles
+because doing so would be too much hassle (see PK_DBL
&
+co above).
@@ -176,7 +174,7 @@ the result of that test instead. #endif-The problem is that things change from one version of an OS to another +
The problem is that things change from one version of an OS to another - things get added, things get deleted, things get broken, some things are optional extras. Using "feature tests" instead of "system tests" makes things a lot less brittle. Things also tend to get documented @@ -194,27 +192,56 @@ than trying to find a bug which only shows up when running GHC on itself and doesn't manifest itself until 10 seconds after the actual cause of the problem. +
We put all our debugging code inside #ifdef DEBUG. The +general policy is we don't ship code with debugging checks and +assertions in it, but we do run with those checks in place when +developing and testing. Anything inside #ifdef DEBUG should +not slow down the code by more than a factor of 2. + +
We also have more expensive "sanity checking" code for hardcore +debugging - this can slow down the code by a large factor, but is only +enabled on demand by a command-line flag. General sanity checking in +the RTS is currently enabled with the -DS RTS flag. + +
There are a number of RTS flags which control debugging output and +sanity checking in various parts of the system when DEBUG is +defined. For example, to get the scheduler to be verbose about what +it is doing, you would say +RTS -Ds -RTS. See +includes/RtsFlags.h and rts/RtsFlags.c for the full +set of debugging flags. To check one of these flags in the code, +write: + +
+ IF_DEBUG(gc, fprintf(stderr, "...")); ++ +would check the gc flag before generating the output (and the +code is removed altogether if DEBUG is not defined). + +
All debugging output should go to stderr. +
-The ideas in this section are mostly aimed at this issue: +Particular guidelines for writing robust code:
In particular:
@@ -265,89 +294,25 @@ instead of #define add(x,y) x+y-
- #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. -- -
- #define doNothing() do { } while (0) --
+ #define ASSIGN_CC_ID(ccID) \ + { \ + ccID = CC_ID; \ + CC_ID++; \ + } ++ +(but it's usually better to use an inline function instead - see above). + +
+ #define doNothing() do { } while (0) ++ +
int* p, q; @@ -430,7 +416,7 @@ int *p, *q;but it is preferrable to split the declarations. -
#ifdef 0
+... #endif
rather than /* ... */
because C doesn't
+have nested comments.
+
+-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;+
-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.
-v
and --verbose
options should be
+used to generate verbose output (intended for the user).
+
+-d
and --debug
options should be
+used to generate debugging output (intended for the developer).
+
+-?
and --help
options should be used
+to display usage information on stdout. The program should exit
+successfully afterwards.
+
+-V
and --version
options should be
+used to output version information on stdout, which includes one line
+of the form 'Program version
+Major.Minor[.Patchlevel] ...
'. The program
+should exit successfully afterwards.
+