[LC++]Producing a log of routine entry and exit

Carlo Wood carlo at alinoe.com
Fri Aug 30 21:56:08 UTC 2002


On Fri, Aug 30, 2002 at 02:15:10PM +0930, Dr Mark H Phillips wrote:
> I am going through the tutorial for libcwd and found this
> quote from the FAQ:
> 
> "Any project should have one header file that is included at the top of
> every source file.  If you already have one then you can add #include
> <libcw/sysd.h> to that file.  Otherwise you should add such a header
> file: its a Good Thing(tm) to have."
> 
> Am I right in thinking this is something you wrote?  If so, could you
> please explain the reasons why it is a "Good Thing(tm)".

Out of many many years of experience.

It turns out that often you need something that is not
directly related to your application but has external
reasons.  The most common reason is porting (differences
between OS).  It is a Good Thing to have those things
at one place, in one header file - so it stays maintainable
and surveyable.  Code duplication is bad in general :).
Furthermore it turns out having this header _standard_
at the *start* of each source file, before ANY system
header file is included, gives you much more power to
use it for Operating System differences.

Finally, there is no good reason not to do it :p.
Just like adding a license header to each file,
and

#ifndef MYAPP_HEADENAME_H
#define MYAPP_HEADENAME_H

...

#endif // MYAPP_HEADENAME_H

is standard for every header file; it will pay back if you
get used to starting each source (.cc, .cpp) file with:

#include "sys.h"

Examples of stuff that can go into such a file are given
below.  Please realize these ONLY *EXAMPLES* - what you
will ACTUALLY add to it will be very project specific,
despite that all of this is somehow not really related
to the project.

// autoconf dependency
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

// libcwd dependency
#ifdef CWDEBUG
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <libcw/sysd.h>
#endif

// Use __attribute__((noreturn)) but support compilers that don't have it
// Functions whose use force me to use a return type but never return
// now will look like:
// int foo() __attribute__ ((noreturn));
// int foo()
// {
//   this_function_never_return();
//   NEED_FAKE_RETURN(0);	// Avoid compiler warning
// }
#ifdef __GNUC__
  #if (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
    #define NO_ATTRIBUTE
  #endif
#else // !__GNUC__
  // No attributes if we don't have gcc-2.7 or higher
  #define NO_ATTRIBUTE
#endif // !__GNUC__

#if defined(NO_ATTRIBUTE) && !defined(__attribute__)
#define __attribute__(x)
#define NEED_FAKE_RETURN(x) return x;
#endif

#ifndef NEED_FAKE_RETURN
#define NEED_FAKE_RETURN(x)
#endif

// Definition of macros used to add a ident string to each file:
#ifndef RCSTAG_CC
#define RCSTAG_CC(string) static char rcs_ident[] __attribute__ ((__unused__)) = string;
#endif
#ifndef RCSTAG_H
#define RCSTAG_H(name, string) static char const rcs_ident_##name##_h[] __attribute__ ((__unused__)) = string;
#endif
#ifndef RCSTAG_INL
#define RCSTAG_INL(name, string) static char rcs_ident##name##_inl[] __attribute__ ((__unused__)) = string;
#endif

// Use __restrict keyword, but support compilers that don't have it
#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
#define __restrict /*ignore*/
#endif

// This is to avoid warnings like:
// /usr/include/g++-3/iostream.h:253:5: "_G_CLOG_CONFLICT" is not defined
#define NEED_G_CONFIG_H_MACROS
#ifdef NEED_G_CONFIG_H_MACROS
#include <_G_config.h>
#ifndef _G_CLOG_CONFLICT
#define _G_CLOG_CONFLICT 0
#endif
#ifndef _G_HAS_LABS
#define _G_HAS_LABS 1
#endif
#endif

...

Well, you get the idea.

-- 
Carlo Wood <carlo at alinoe.com>




More information about the tuxCPProgramming mailing list