Up: Top   [Contents][Index]


5.3 Coding Standards

5.3.1 Source indentation

Most of the DJGPP sources are formatted in a standard way; please observe and preserve this formatting when writing new code.

The indentation style generally looks like this:

 if (foo)
 {
   bar(baz);
 }

That is, the braces are on a separate line and in the same column as the if (or for, or while) clause that opens the block.

Here’s how to set up Emacs’s C Mode for this indentation style:

(c-add-style
 "DJ"
 '((c-basic-offset . 2)
   (c-comment-only-line-offset . (0 . 0))
   (c-offsets-alist . ((substatement-open . 0)
		       (label . 0)
		       (statement-case-open . +)
		       (statement-cont . +)
		       (arglist-intro . c-lineup-arglist-intro-after-paren)
		       (arglist-close . c-lineup-arglist)
		       ))
   ))

(c-set-style "DJ")

And here’s the list of options for the GNU indent program, to be put on your .indent.pro profile file, in case you need to reformat your sources to comply with the DJGPP style:

/* DJ */
-nbad -bap -nbc -bbo -bl -bli0 -brs -ncdb -nce -cp1 -cs -di2
-nfc1 -fca -hnl -i2 -ip2 -ci0 -lp -npcs -nprs -psl -nsc -nsob

5.3.2 Stubs

A C application’s namespace should not be polluted with non-ANSI and non-POSIX functions from the C libraries, unless the application explicitly uses these symbols. An example of a non-ANSI and non-POSIX function is uclock (see (libc)uclock).

But what happens if you wish to call a non-ANSI and/or non-POSIX function from C library code? The actual implementation is placed in the C library’s private namespace with a stub function that calls the implementation. Consider uclock — the library would use the __uclock function internally, but application code would use the stub uclock.

Functions that are stubbed have an entry in the include file libc/stubs.h, e.g.:

#define uclock __uclock

Any C library sources defining or calling the implementation should include libc/stubs.h as the first include file. This is so that we can refer to, e.g., uclock as uclock in the library code, but the library code will actually define/call, e.g., __uclock and will not pollute the application namespace.

The stub files are assembly language files generated automagically from libc/stubs.h as part of the C library build process.

NB: The private name, e.g., __uclock, is not part of the published API.

5.3.3 Far pointers usage

If a library function uses one of the _far* far pointer functions, it should include libc/farptrgs.h instead of sys/farptr.h. The inline functions in farptrgs.h use the GS register instead of FS, to avoid clobbering FS which might be used by the application.

5.3.4 Filename manipulation

When manipulating filenames, don’t use the ctype functions from ctype.h, because they are locale sensitive. For example, instead of using tolower (see (libc)tolower), convert the case with explicit code.

5.3.5 Assertions

Assertions should not generally be used in library code. To catch an error, the code should check for the error and return an error code. Using assert (see (libc)assert) causes the debug and final release (‘NDEBUG’ defined) versions of the code to differ, so that the final release is not as well tested.

5.3.6 Coping with restarted programs

Uninitialised static and global data is placed in the .bss section. BSS stands for Block Started by Symbol. The .bss section is zeroed by the start-up code.

Initialised static and global data is placed in the .data section.

So it would seem that one can rely on static and global variables being initialised to zero or some specified value. Unfortunately this may not be true, where programs are unexecuted and then restarted — Emacs is the primary example.

Part of Emacs’s build procedure is that Emacs unexecutes (dumps) itself to a file. The dumping process records the value of each variable at the time of the dump to a file. The symbols in the .bss section are moved to the .data section. The values at the time of the dump are recorded, not the original values. So if the library code is relying on the value of a static or global variable, e.g., to see whether it needs to initialise some device or allocate memory, then it may break when the program restarts.

Fortunately there is a way that library code can detect a restart. The variable __bss_count contains a counter of the number of times that the program has been started — it is incremented by the start-up code. A routine can store __bss_count and then check whether it needs to initialise its data by comparing __bss_count with its stored value. Here is an example:

#include <string.h>
#include <libc/bss.h>

extern int do_something_interesting (const int n);

static int my_bss_count = -1;
static int my_array[20];

int
myfunc (const int n)
{
  if (my_bss_count != __bss_count)
    {
      my_bss_count = __bss_count;
      memset(my_array, 0, sizeof(my_array));
    }

  if (n >= 20)
    return 0;

  if (!my_array[n])
    my_array[n] = do_something_interesting(n);

  return(my_array[n]);
}

For more details see src/libc/crt0/crt1.c in the DJGPP libc sources.

5.4 The DJGPP Build System

5.4.1 Profiling

src/gcc.opt controls how the DJGPP sources are compiled. To build the C libraries for profiling, add the profiling options (e.g., ‘-pg’) to gcc.opt, one option per line. The library will need to be rebuilt from scratch for the new options to take effect, so a ‘make clean’ is needed before rebuilding in the directory of interest, e.g.:

cd /path/to/djgpp/sources
cd src
echo "Adding profiling option to gcc.opt"
echo -pg >> gcc.opt
cd libc
echo "Building a profiling version of libc"
make clean
make

For example of how some of the sources are built without profiling, please see src/libc/crt0/makefile to see how the profiling support code, src/libc/crt0/mcount.c, is built.

There are currently some problems with profiling support. The math co-processor support code, emu387.dxe, in src/libemu cannot be built with profiling.

5.5 Submitting patches

When you prepare a patch use ‘diff -upr djgpp.old djgpp.new’ or ‘diff -cpr djgpp.old djgpp.new’. The directory names ‘djgpp.old’ and ‘djgpp.new’ are just examples, but you should preferably use a descriptive name. If you have added any new files the option ‘-N’ comes in handy.

Similarly if you use cvs diff use ‘cvs -z3 diff -up djgpp’ or ‘cvs -z3 diff -cp djgpp’. To get cvs diff to notice any new files you must make cvs aware of them with the cvs add command.

5.6 Texinfo documentation

5.6.1 Formatting


Up: Top   [Contents][Index]