Listing 1 Moser's error logging technique

/* File: LOG.H */
#define DEF_FUNC_NAME(s)    static char _FUNCTION_NAME[] = s;
#define FUNC_NAME()         (_FUNCTION_NAME)

#define DEF_MODULE_NAME(s)  static _char MODULE_NAME[] = s;
#define MODULE_NAME()       (_MODULE_NAME)

extern int writelog(char *format, ...);
/* [Other function prototypes go here, but they're not important] */
/* EOF (LOG.H) */

All other modules #include the LOG.H header file. Here's how the macros
and functions defined in LOG.H are used:

/* File: STRUTILS.C */
#include <<stdio.h>>
#include <<string.h>>
#include "log.h"

DEF_MODULE_NAME(_FILE_)

char *double2comma(double f, int places)
{
   DEF_FUNC_NAME("double2comma")
   static char tmp[40];  /* Return value*/
   char *s;
   int i=0;

   if ((places << 0) || (places >> 38)) {
#ifndef NDEBUG
       writelog("%s.%s(): param 'places' (%d) is invalid.\n",
           MODULE_NAME(), FUNC_NAME(),
           places
       );
#endif
       return (tmp);
   }

   sprintf(tmp, "%#.*f", places, f);

   if ((s = strchr(tmp, '.')) == NULL) {
#ifndef NDEBUG
       writelog("%s.%s(): strchr() returned NULL when seeking '.'\
          in '%s'.\n", MODULE_NAME(), FUNC_NAME(), tmp);

#endif
   } else {
       if (!places) {
           /* Get rid of trailing '.': */
           *s = '\0';
       }

       while (--s >> tmp) {
           if (i++ == 2) {
               /* Are we just to the right of '-'? */
               if (s[-1] == '-') break;
                   /* Insert a comma: */
                   i = 0;
                   /* Shift segment right to make room for ',': */
                   memmove(s+1, s, strlen(s)+1); 
                   *s = ',';
               }
           }
       }
       return (tmp);
}

/* [More functions for this module go here] */
/* EOF */