• C

non-programmer having a compilation error

I am trying to install some tools on Linux (kernel 2.2.12 on Redhat 6.0), and as a result a have to compile some sources, with virtually no C programming experience. So I am looking for help on the following error, I get when I issue (through an Imake-generated Makefile)

gcc -c -g -ansi -I/usr/local/src/dbug/include  -Dlinux -D__i386__ -D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE -DX_LOCALE  -DFUNCPROTO=15 -DNARROWPROTO -fPIC dbug.c

dbug.c:264: initializer element for `stack_head.out_file' is not constant

That's all the info I have, apart from the contents of dbug.c (I just hope it fits) (LINE 264 is marked)

Any help is welcome,

JM

---
dbug.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "dbug.h" /* self-test */


#if HASSTDARG
#include <stdarg.h>
#else
# if HASVARARGS
# include <varargs.h>            /* Use system supplied varargs package */
# else
# include "vargs.h"            /* Use our "fake" varargs */
# endif
#endif

#ifndef HZ
#define HZ (50)                  /* Probably in some header somewhere */
#endif

/*
 *      Manifest constants that should not require any changes.
 */

#define FALSE            0      /* Boolean FALSE */
#define TRUE            1      /* Boolean TRUE */
#define EOS            '\000'      /* End Of String marker */

/*
 *      Manifest constants which may be "tuned" if desired.
 */

#define PRINTBUF      1024      /* Print buffer size */
#define INDENT            4      /* Indentation per trace level */
#define MAXDEPTH      200      /* Maximum trace depth default */

/*
 *      The following flags are used to determine which
 *      capabilities the user has enabled with the state
 *      push macro.
 */

#define TRACE_ON      000001      /* Trace enabled */
#define DEBUG_ON      000002      /* Debug enabled */
#define FILE_ON       000004      /* File name print enabled */
#define LINE_ON            000010      /* Line number print enabled */
#define DEPTH_ON      000020      /* Function nest level print enabled */
#define PROCESS_ON      000040      /* Process name print enabled */
#define NUMBER_ON      000100      /* Number each line of output */
#define PROFILE_ON      000200      /* Print out profiling code */
#define PID_ON            000400      /* Identify each line with process id */

#define TRACING (stack -> flags & TRACE_ON)
#define DEBUGGING (stack -> flags & DEBUG_ON)
#define PROFILING (stack -> flags & PROFILE_ON)
#define STREQ(a,b) (strcmp(a,b) == 0)

/*
 *      Typedefs to make things more obvious.
 */

#define VOID void            /* Can't use typedef for most compilers */
typedef int BOOLEAN;

/*
 *      Make it easy to change storage classes if necessary.
 */

#define LOCAL static            /* Names not needed by outside world */
#define IMPORT extern            /* Names defined externally */
#define EXPORT                  /* Allocated here, available globally */
#define AUTO auto            /* Names to be allocated on stack */
#define REGISTER register      /* Names to be placed in registers */

/*
 * The default file for profiling.  Could also add another flag
 * (G?) which allowed the user to specify this.
 *
 * If the automatic variables get allocated on the stack in
 * reverse order from their declarations, then define AUTOS_REVERSE.
 * This is used by the code that keeps track of stack usage.  For
 * forward allocation, the difference in the dbug frame pointers
 * represents stack used by the callee function.  For reverse allocation,
 * the difference represents stack used by the caller function.
 *
 */

#define PROF_FILE      "dbugmon.out"
#define PROF_EFMT      "E\t%ld\t%s\n"
#define PROF_SFMT      "S\t%lx\t%lx\t%s\n"
#define PROF_XFMT      "X\t%ld\t%s\n"

#if M_I386            /* predefined by xenix 386 compiler */
#define AUTOS_REVERSE 1
#endif

/*
 *      Variables which are not available externally. They should only
 *      be accessed via the macro package facilities.
 */

/* Stack variables */

#define _db_fp_  (stack->out_file)      /* Output stream, default stderr */
#define _db_pfp_ (stack->prof_file)      /* Profile stream, 'dbugmon.out' */

LOCAL char *_db_process_ = "dbug";      /* Pointer to process name; argv[0] */

/*
 *      Externally supplied functions.
 */
#if HASPERROR
#include <errno.h>
#else
LOCAL VOID perror (char *s);      /* Fake system/library error print routine */
#endif

#ifdef _WIN32
/* different includes for getpid, access, and sleep */
# if HASGETPID
#  include <process.h>
#  ifndef getpid
#   define getpid _getpid
#  endif
# endif
# if HASACCESS
#  include <io.h>
#  ifndef access
#   define access _access
#  endif
#  /* _access of Visual C++ has the following modes:
#     * 0 for existence
#     * 2 for write permission
#     * 4 for read permission
#     * 6 for bot read and write permission
#  */
#  define F_OK      0      /* Test for file existance */
#  define X_OK      4      /* Test for execute permission */
#  define W_OK      2      /* Test for write access */
#  define R_OK      4      /* Test for read access */
# endif
# if HASSLEEP
#  include <stdlib.h>
#  include <time.h>
#  ifndef sleep
#   define sleep _sleep
#  endif
# endif

#else /* #ifdef _WIN32 */
/* ! _WIN32 */
# if HASCHOWN || HASGETGID || HASGETPID || HASGETUID || HASACCESS || HASSLEEP
# include <unistd.h>
# endif

#endif /* #ifdef _WIN32 */

#if HASFTIME
#include <sys/timeb.h>
#endif

#if HASGETRUSAGE
#include <sys/resource.h>
#endif

/*
 *      The user may specify a list of functions to trace or
 *      debug.  These lists are kept in a linear linked list,
 *      a very simple implementation.
 */

struct link {
    char *string;            /* Pointer to link's contents */
    struct link *next_link;      /* Pointer to the next link */
};

/*
 *      Debugging states can be pushed or popped off of a
 *      stack which is implemented as a linked list.  Note
 *      that the head of the list is the current state and the
 *      stack is pushed by adding a new state to the head of the
 *      list or popped by removing the first link.
 */

struct state {
    int flags;                        /* Current state flags */
    int maxdepth;                  /* Current maximum trace depth */
    unsigned int delay;                  /* Delay after each output line */
    int level;                        /* Current function nesting level */
    FILE *out_file;                  /* Current output stream */
    FILE *prof_file;                  /* Current profiling stream */
    struct link *functions;            /* List of functions */
    struct link *p_functions;            /* List of profiled functions */
    struct link *keywords;            /* List of debug keywords */
    struct link *processes;            /* List of process names */
    struct state *next_state;            /* Next state in the list */
};

LOCAL struct state stack_head = {
  0,
  MAXDEPTH,
  0,
  0,
  stderr,            /* LINE 264 */
  0,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};

LOCAL struct state *stack = &stack_head; /* Linked list of stacked states */

/*
 *      Local variables not seen by user.
 */

LOCAL int lineno = 0;            /* Current debugger output line number */
LOCAL char *func = "?func";      /* Name of current user function */
LOCAL char *file = "?file";      /* Name of current user file */
LOCAL BOOLEAN init_done = FALSE;/* Set to TRUE when initialization done */
LOCAL char **framep = NULL;      /* Pointer to current frame */

#if HASSETJMP
LOCAL int jmplevel;            /* Remember nesting level at setjmp () */
LOCAL char *jmpfunc;            /* Remember current function for setjmp */
LOCAL char *jmpfile;            /* Remember current file for setjmp */
#endif

LOCAL struct link *ListParse (char *);/* Parse a debug command string */
LOCAL char *StrDup (char *);            /* Make a fresh copy of a string */
LOCAL VOID OpenFile (char *);            /* Open debug output stream */
LOCAL VOID OpenProfile (char *);      /* Open profile output stream */
LOCAL VOID CloseFile (FILE *);      /* Close debug output stream */
LOCAL VOID PushState (void);      /* Push current debug state */
LOCAL VOID ChangeOwner (char *);      /* Change file owner and group */
LOCAL BOOLEAN DoTrace (void);      /* Test for tracing enabled */
LOCAL BOOLEAN DoProfile ( void );
LOCAL int DelayArg (int value);
LOCAL BOOLEAN Writable (char *);      /* Test to see if file is writable */
LOCAL unsigned long Clock (void);      /* Return current user time (ms) */
LOCAL long *DbugMalloc (int);      /* Allocate memory for runtime support */
LOCAL char *BaseName (char *);      /* Remove leading pathname components */
LOCAL VOID DoPrefix (int);            /* Print debugger line prefix */
LOCAL VOID FreeList (struct link *);            /* Free memory from linked list */
LOCAL VOID Indent (int);            /* Indent line to specified indent */

                        /* Supplied in Sys V runtime environ */

/*
 *      The following local variables are used to hold the state information
 *      between the call to _db_pargs_() and _db_doprnt_(), during
 *      expansion of the DBUG_PRINT macro.  This is the only macro
 *      that currently uses these variables.
 *
 *      These variables are currently used only by _db_pargs_() and
 *      _db_doprnt_().
 */

LOCAL int u_line = 0;            /* User source code line number */
LOCAL char *u_keyword = "?";      /* Keyword for current macro */

/*
 *      Miscellaneous printf format strings.
 */
 
#define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
#define ERR_OPEN "%s: can't open debug output stream \"%s\": "
#define ERR_CLOSE "%s: can't close debug file: "
#define ERR_ABORT "%s: debugger aborting because %s\n"
#define ERR_CHOWN "%s: can't change owner/group of \"%s\": "

/*
 *      Macros and defines for testing file accessibility.
 */

#if HASACCESS
#  define A_EXISTS      F_OK            /* Test for file existance */
#  define A_EXECUTE      X_OK            /* Test for execute permission */
#  define A_WRITE      W_OK            /* Test for write access */
#  define A_READ      R_OK            /* Test for read access */
#  define EXISTS(pathname) (access (pathname, A_EXISTS) == 0)
#  define WRITABLE(pathname) (access (pathname, A_WRITE) == 0)
#else
#  define EXISTS(pathname) (FALSE)      /* Assume no existance */
#  define WRITABLE(pathname) (TRUE)
#endif

/*
 *      Translate some calls among different systems.
 */

#if HASDELAY
IMPORT int Delay ( int seconds );            /* Pause for given number of ticks */
#else
# if HASSLEEP
#  define Delay sleep
# else
LOCAL int Delay ( int seconds );            /* Pause for given number of ticks */
# endif
#endif


/*
 *  FUNCTION
 *
 *      _db_get_on_    return whether debugging is on
 *
 *  DESCRIPTION
 *
 *      This function is created to make DBUG portable to Windows.
 *      The dymamic library didn't seem to like exported variables,
 *      hence I created this functions.
 */

int _db_get_on_ (void)
{
      return DEBUGGING;
}


/*
 *  FUNCTION
 *
 *      _db_get_fp_    returns file pointer where output is being written to.
 *
 *  DESCRIPTION
 *
 *      This function is created to make DBUG portable to Windows.
 *      The dymamic library didn't seem to like exported variables,
 *      hence I created this functions.
 */

FILE *_db_get_fp_( void )
{
      return _db_fp_;
}

/*
 *  FUNCTION
 *
 *      _db_set_process_    sets the process name
 *
 *  DESCRIPTION
 *
 *      This function is created to make DBUG portable to Windows.
 *      The dymamic library didn't seem to like exported variables,
 *      hence I created this functions.
 */

VOID _db_set_process_( char * process )
{
      _db_process_ = process;
}

/*
 *  FUNCTION
 *
 *      _db_push_    push current debugger state and set up new one
 *
 *  SYNOPSIS
 *
 *      VOID _db_push_ (control)
 *      char *control;
 *
 *  DESCRIPTION
 *
 *      Given pointer to a debug control string in "control", pushes
 *      the current debug state, parses the control string, and sets
 *      up a new debug state.
 *
 *      The only attribute of the new state inherited from the previous
 *      state is the current function nesting level.  This can be
 *      overridden by using the "r" flag in the control string.
 *
 *      The debug control string is a sequence of colon separated fields
 *      as follows:
 *
 *            <field_1>:<field_2>:...:<field_N>
 *
 *      Each field consists of a mandatory flag character followed by
 *      an optional "," and comma separated list of modifiers:
 *
 *            flag[,modifier,modifier,...,modifier]
 *
 *      The currently recognized flag characters are:
 *
 *            d      Enable output from DBUG_<N> macros for
 *                  for the current state.  May be followed
 *                  by a list of keywords which selects output
 *                  only for the DBUG macros with that keyword.
 *                  A null list of keywords implies output for
 *                  all macros.
 *
 *            D      Delay after each debugger output line.
 *                  The argument is the number of tenths of seconds
 *                  to delay, subject to machine capabilities.
 *                  I.E.  -#D,20 is delay two seconds.
 *
 *            f      Limit debugging and/or tracing, and profiling to the
 *                  list of named functions.  Note that a null list will
 *                  disable all functions.  The appropriate "d" or "t"
 *                  flags must still be given, this flag only limits their
 *                  actions if they are enabled.
 *
 *            F      Identify the source file name for each
 *                  line of debug or trace output.
 *
 *            i      Identify the process with the pid for each line of
 *                  debug or trace output.
 *
 *            g      Enable profiling.  Create a file called 'dbugmon.out'
 *                  containing information that can be used to profile
 *                  the program.  May be followed by a list of keywords
 *                  that select profiling only for the functions in that
 *                  list.  A null list implies that all functions are
 *                  considered.
 *
 *            L      Identify the source file line number for
 *                  each line of debug or trace output.
 *
 *            n      Print the current function nesting depth for
 *                  each line of debug or trace output.
 *      
 *            N      Number each line of dbug output.
 *
 *            o      Redirect the debugger output stream to the
 *                  specified file.  The default output is stderr.
 *
 *            p      Limit debugger actions to specified processes.
 *                  A process must be identified with the
 *                  DBUG_PROCESS macro and match one in the list
 *                  for debugger actions to occur.
 *
 *            P      Print the current process name for each
 *                  line of debug or trace output.
 *
 *            r      When pushing a new state, do not inherit
 *                  the previous state's function nesting level.
 *                  Useful when the output is to start at the
 *                  left margin.
 *
 *            t      Enable function call/exit trace lines.
 *                  May be followed by a list (containing only
 *                  one modifier) giving a numeric maximum
 *                  trace level, beyond which no output will
 *                  occur for either debugging or tracing
 *                  macros.  The default is a compile time
 *                  option.
 *
 *      Some examples of debug control strings which might appear
 *      on a shell command line (the "-#" is typically used to
 *      introduce a control string to an application program) are:
 *
 *            -#d:t
 *            -#d:f,main,subr1:F:L:t,20
 *            -#d,input,output,files:n
 *
 *      For convenience, any leading "-#" is stripped off.
 *
 */

VOID _db_push_ (char *control)
{
    REGISTER char *scan;
    REGISTER struct link *temp;

    if (control && *control == '-') {
      if (*++control == '#') {
          control++;
      }      
    }
    control = StrDup (control);
    PushState ();
    scan = strtok (control, ":");
    for (; scan != NULL; scan = strtok ((char *)NULL, ":")) {
      switch (*scan++) {
          case 'd':
            stack -> flags |= DEBUG_ON;
            if (*scan++ == ',') {
                stack -> keywords = ListParse (scan);
            }
                break;
          case 'D':
            stack -> delay = 0;
            if (*scan++ == ',') {
                temp = ListParse (scan);
                stack -> delay = DelayArg (atoi (temp -> string));
                FreeList (temp);
            }
            break;
          case 'f':
            if (*scan++ == ',') {
                stack -> functions = ListParse (scan);
            }
            break;
          case 'F':
            stack -> flags |= FILE_ON;
            break;
          case 'i':
            stack -> flags |= PID_ON;
            break;
          case 'g':
            OpenProfile(PROF_FILE);
            stack -> flags |= PROFILE_ON;
            if (*scan++ == ',') {
                stack -> p_functions = ListParse (scan);
            }
            break;
          case 'L':
            stack -> flags |= LINE_ON;
            break;
          case 'n':
            stack -> flags |= DEPTH_ON;
            break;
          case 'N':
            stack -> flags |= NUMBER_ON;
            break;
          case 'o':
            if (*scan++ == ',') {
                temp = ListParse (scan);
                OpenFile (temp -> string);
                FreeList (temp);
            } else {
                OpenFile ("-");
            }
            break;
          case 'p':
            if (*scan++ == ',') {
                stack -> processes = ListParse (scan);
            }
            break;
          case 'P':
            stack -> flags |= PROCESS_ON;
            break;
          case 'r':
            stack -> level = 0;
            break;
          case 't':
            stack -> flags |= TRACE_ON;
            if (*scan++ == ',') {
                temp = ListParse (scan);
                stack -> maxdepth = atoi (temp -> string);
                FreeList (temp);
            }
            break;
      }
    }
    free (control);
}


/*
 *  FUNCTION
 *
 *      _db_pop_    pop the debug stack
 *
 *  DESCRIPTION
 *
 *      Pops the debug stack, returning the debug state to its
 *      condition prior to the most recent _db_push_ invocation.
 *      Note that the pop will fail if it would remove the last
 *      valid state from the stack.  This prevents user errors
 *      in the push/pop sequence from screwing up the debugger.
 *      Maybe there should be some kind of warning printed if the
 *      user tries to pop too many states.
 *
 */

VOID _db_pop_ ( void )
{
    REGISTER struct state *discard;

    discard = stack;

    if (discard != NULL && discard -> next_state != NULL) {
      stack = discard -> next_state;
      if (discard -> keywords != NULL) {
          FreeList (discard -> keywords);
      }
      if (discard -> functions != NULL) {
          FreeList (discard -> functions);
      }
      if (discard -> processes != NULL) {
          FreeList (discard -> processes);
      }
      if (discard -> p_functions != NULL) {
          FreeList (discard -> p_functions);
      }

      CloseFile (discard -> out_file);

      CloseFile (discard -> prof_file);

      if ( discard != &stack_head ) free ((char *) discard);
    }
}

/*
 *  FUNCTION
 *
 *      _db_enter_    process entry point to user function
 *
 *  SYNOPSIS
 *
 *      VOID _db_enter_ (_func_, _file_, _line_,
 *                   _sfunc_, _sfile_, _slevel_, _sframep_)
 *      char *_func_;            points to current function name
 *      char *_file_;            points to current file name
 *      int _line_;            called from source line number
 *      char **_sfunc_;            save previous _func_
 *      char **_sfile_;            save previous _file_
 *      int *_slevel_;            save previous nesting level
 *      char ***_sframep_;      save previous frame pointer
 *
 *  DESCRIPTION
 *
 *      Called at the beginning of each user function to tell
 *      the debugger that a new function has been entered.
 *      Note that the pointers to the previous user function
 *      name and previous user file name are stored on the
 *      caller's stack (this is why the ENTER macro must be
 *      the first "executable" code in a function, since it
 *      allocates these storage locations).  The previous nesting
 *      level is also stored on the callers stack for internal
 *      self consistency checks.
 *
 *      Also prints a trace line if tracing is enabled and
 *      increments the current function nesting depth.
 *
 *      Note that this mechanism allows the debugger to know
 *      what the current user function is at all times, without
 *      maintaining an internal stack for the function names.
 *
 */

VOID _db_enter_ (
char *_func_,
char *_file_,
int _line_,
char **_sfunc_,
char **_sfile_,
int *_slevel_,
char ***_sframep_
)
{
    long stackused;

    if (!init_done) {
      _db_push_ ("");
    }
    *_sfunc_ = func;
    func = _func_;
    *_sfile_ = file;
    file = BaseName (_file_);
    stack -> level++;
    *_slevel_ = stack -> level;
    *_sframep_ = framep;
    framep = (char **) _sframep_;
    if (DoProfile ()) {
      if (*framep == NULL) {
          stackused = 0;
      } else {
          stackused = ((long)(*framep)) - ((long)(framep));
          stackused = stackused > 0 ? stackused : -stackused;
      }
      (VOID) fprintf (_db_pfp_, PROF_EFMT , Clock (), func);
#if AUTOS_REVERSE
      (VOID) fprintf (_db_pfp_, PROF_SFMT, framep, stackused, *_sfunc_);
#else
      (VOID) fprintf (_db_pfp_, PROF_SFMT, framep, stackused, func);
#endif
      (VOID) fflush (_db_pfp_);
    }
    if (DoTrace ()) {
      DoPrefix (_line_);
      Indent (stack -> level);
      (VOID) fprintf (_db_fp_, ">%s\n", func);
      (VOID) fflush (_db_fp_);
      (VOID) Delay (stack -> delay);
    }
}

/*
 *  FUNCTION
 *
 *      _db_return_    process exit from user function
 *
 *  SYNOPSIS
 *
 *      VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
 *      int _line_;            current source line number
 *      char **_sfunc_;            where previous _func_ is to be retrieved
 *      char **_sfile_;            where previous _file_ is to be retrieved
 *      int *_slevel_;            where previous level was stashed
 *
 *  DESCRIPTION
 *
 *      Called just before user function executes an explicit or implicit
 *      return.  Prints a trace line if trace is enabled, decrements
 *      the current nesting level, and restores the current function and
 *      file names from the defunct function's stack.
 *
 */

VOID _db_return_ (
int _line_,
char **_sfunc_,
char **_sfile_,
int *_slevel_ )
{
    if (!init_done) {
      _db_push_ ("");
    }
    if (stack -> level != *_slevel_ && (TRACING || DEBUGGING || PROFILING)) {
      (VOID) fprintf (_db_fp_, ERR_MISSING_RETURN, _db_process_, func);
    } else {
      if (DoProfile ()) {
            (VOID) fprintf (_db_pfp_, PROF_XFMT, Clock(), func);
          }
      if (DoTrace ()) {
            DoPrefix (_line_);
            Indent (stack -> level);
            (VOID) fprintf (_db_fp_, "<%s\n", func);
      }
    }
    (VOID) fflush (_db_fp_);
    (VOID) Delay (stack -> delay);
    stack -> level = *_slevel_ - 1;
    func = *_sfunc_;
    file = *_sfile_;
    if (framep != NULL) {
      framep = (char **) *framep;
    }
}

/*
 *  FUNCTION
 *
 *      _db_pargs_    log arguments for subsequent use by _db_doprnt_()
 *
 *  SYNOPSIS
 *
 *      VOID _db_pargs_ (_line_, keyword)
 *      int _line_;
 *      char *keyword;
 *
 *  DESCRIPTION
 *
 *      The new universal printing macro DBUG_PRINT, which replaces
 *      all forms of the DBUG_N macros, needs two calls to runtime
 *      support routines.  The first, this function, remembers arguments
 *      that are used by the subsequent call to _db_doprnt_().
*
 */

VOID _db_pargs_ (
int _line_,
char *keyword
)
{
    u_line = _line_;
    u_keyword = keyword;
}

/*
 *  FUNCTION
 *
 *      _db_doprnt_    handle print of debug lines
 *
 *  SYNOPSIS
 *
 *      VOID _db_doprnt_ (format, va_alist)
 *      char *format;
 *      va_dcl;
 *
 *  DESCRIPTION
 *
 *      When invoked via one of the DBUG macros, tests the current keyword
 *      set by calling _db_pargs_() to see if that macro has been selected
 *      for processing via the debugger control string, and if so, handles
 *      printing of the arguments via the format string.  The line number
 *      of the DBUG macro in the source is found in u_line.
 *
 *      Note that the format string SHOULD NOT include a terminating
 *      newline, this is supplied automatically.
 *
 */

/*VARARGS1*/
#if HASSTDARG
VOID _db_doprnt_ (char *format, ...)
{
    va_list args;

    va_start (args, format);
#else
VOID _db_doprnt_ (format, va_alist)
char *format;
va_dcl
{
    va_list args;

    va_start (args);
#endif
    if (_db_keyword_ (u_keyword)) {
      DoPrefix (u_line);
      if (TRACING) {
          Indent (stack -> level + 1);
      } else {
          (VOID) fprintf (_db_fp_, "%s: ", func);
      }
      (VOID) fprintf (_db_fp_, "%s: ", u_keyword);
      (VOID) vfprintf (_db_fp_, format, args);
      (VOID) fprintf (_db_fp_, "\n");
      (VOID) fflush (_db_fp_);
      (VOID) Delay (stack -> delay);
    }
    va_end (args);
}

/*
 *  FUNCTION
 *
 *      ListParse    parse list of modifiers in debug control string
 *
 *  SYNOPSIS
 *
 *      LOCAL struct link *ListParse (ctlp)
 *      char *ctlp;
 *
 *  DESCRIPTION
 *
 *      Given pointer to a comma separated list of strings in "cltp",
 *      parses the list, building a list and returning a pointer to it.
 *      The original comma separated list is destroyed in the process of
 *      building the linked list, thus it had better be a duplicate
 *      if it is important.
 *
 *      Note that since each link is added at the head of the list,
 *      the final list will be in "reverse order", which is not
 *      significant for our usage here.
 *
 */

LOCAL struct link *ListParse (char *ctlp)
{
    REGISTER char *start;
    REGISTER struct link *new;
    REGISTER struct link *head;

    head = NULL;
    while (*ctlp != EOS) {
      start = ctlp;
      while (*ctlp != EOS && *ctlp != ',') {
          ctlp++;
      }
      if (*ctlp == ',') {
          *ctlp++ = EOS;
      }
      new = (struct link *) DbugMalloc (sizeof (struct link));
      new -> string = StrDup (start);
      new -> next_link = head;
      head = new;
    }
    return (head);
}

/*
 *  FUNCTION
 *
 *      InList    test a given string for member of a given list
 *
 *  SYNOPSIS
 *
 *      LOCAL BOOLEAN InList (linkp, cp)
 *      struct link *linkp;
 *      char *cp;
 *
 *  DESCRIPTION
 *
 *      Tests the string pointed to by "cp" to determine if it is in
 *      the list pointed to by "linkp".  Linkp points to the first
 *      link in the list.  If linkp is NULL then the string is treated
 *      as if it is in the list (I.E all strings are in the null list).
 *      This may seem rather strange at first but leads to the desired
 *      operation if no list is given.  The net effect is that all
 *      strings will be accepted when there is no list, and when there
 *      is a list, only those strings in the list will be accepted.
 *
 */

LOCAL BOOLEAN InList (struct link *linkp, char *cp)
{
    REGISTER struct link *scan;
    REGISTER BOOLEAN accept;

    if (linkp == NULL) {
      accept = TRUE;
    } else {
      accept = FALSE;
      for (scan = linkp; scan != NULL; scan = scan -> next_link) {
          if (STREQ (scan -> string, cp)) {
            accept = TRUE;
            break;
          }
      }
    }
    return (accept);
}

/*
 *  FUNCTION
 *
 *      PushState    push current state onto stack and set up new one
 *
 *  SYNOPSIS
 *
 *      LOCAL VOID PushState ()
 *
 *  DESCRIPTION
 *
 *      Pushes the current state on the state stack, and initializes
 *      a new state.  The only parameter inherited from the previous
 *      state is the function nesting level.  This action can be
 *      inhibited if desired, via the "r" flag.
 *
 *      The state stack is a linked list of states, with the new
 *      state added at the head.  This allows the stack to grow
 *      to the limits of memory if necessary.
 *
 */

LOCAL VOID PushState (void)
{
    REGISTER struct state *new;

    new = (struct state *) DbugMalloc (sizeof (struct state));
    new -> flags = 0;
    new -> delay = 0;
    new -> maxdepth = MAXDEPTH;
    new -> level = stack -> level;
    new -> out_file = stderr;
    new -> functions = NULL;
    new -> p_functions = NULL;
    new -> keywords = NULL;
    new -> processes = NULL;
    new -> next_state = stack;
    stack = new;
    init_done = TRUE;
}

/*
 *  FUNCTION
 *
 *      DoTrace    check to see if tracing is current enabled
 *
 *  SYNOPSIS
 *
 *      LOCAL BOOLEAN DoTrace ()
 *
 *  DESCRIPTION
 *
 *      Checks to see if tracing is enabled based on whether the
 *      user has specified tracing, the maximum trace depth has
 *      not yet been reached, the current function is selected,
 *      and the current process is selected.  Returns TRUE if
 *      tracing is enabled, FALSE otherwise.
 *
 */

LOCAL BOOLEAN DoTrace (void)
{
    REGISTER BOOLEAN trace;

    trace = FALSE;
    if (TRACING) {
      if (stack -> level <= stack -> maxdepth) {
          if (InList (stack -> functions, func)) {
            if (InList (stack -> processes, _db_process_)) {
                trace = TRUE;
            }
          }
      }
    }
    return (trace);
}

/*
 *  FUNCTION
 *
 *      DoProfile    check to see if profiling is current enabled
 *
 *  SYNOPSIS
 *
 *      LOCAL BOOLEAN DoProfile ()
 *
 *  DESCRIPTION
 *
 *      Checks to see if profiling is enabled based on whether the
 *      user has specified profiling, the maximum trace depth has
 *      not yet been reached, the current function is selected,
 *      and the current process is selected.  Returns TRUE if
 *      profiling is enabled, FALSE otherwise.
 *
 */

LOCAL BOOLEAN DoProfile ( void )
{
    REGISTER BOOLEAN profile;

    profile = FALSE;
    if (PROFILING) {
      if (stack -> level <= stack -> maxdepth) {
          if (InList (stack -> p_functions, func)) {
            if (InList (stack -> processes, _db_process_)) {
                profile = TRUE;
            }
          }
      }
    }
    return (profile);
}

/*
 *  FUNCTION
 *
 *      _db_keyword_    test keyword for member of keyword list
 *
 *  SYNOPSIS
 *
 *      BOOLEAN _db_keyword_ (keyword)
 *      char *keyword;
 *
 *  DESCRIPTION
 *
 *      Test a keyword to determine if it is in the currently active
 *      keyword list.  As with the function list, a keyword is accepted
 *      if the list is null, otherwise it must match one of the list
 *      members.  When debugging is not on, no keywords are accepted.
 *      After the maximum trace level is exceeded, no keywords are
 *      accepted (this behavior subject to change).  Additionally,
 *      the current function and process must be accepted based on
 *      their respective lists.
 *
 *      Returns TRUE if keyword accepted, FALSE otherwise.
 *
 */

BOOLEAN _db_keyword_ (char *keyword)
{
    REGISTER BOOLEAN accept;

    if (!init_done) {
      _db_push_ ("");
    }
    accept = FALSE;
    if (DEBUGGING) {
      if (stack -> level <= stack -> maxdepth) {
          if (InList (stack -> functions, func)) {
            if (InList (stack -> keywords, keyword)) {
                if (InList (stack -> processes, _db_process_)) {
                  accept = TRUE;
                }
            }
          }
      }
    }
    return (accept);
}

/*
 *  FUNCTION
 *
 *      Indent    indent a line to the given indentation level
 *
 *  SYNOPSIS
 *
 *      LOCAL VOID Indent (indent)
 *      int indent;
 *
 *  DESCRIPTION
 *
 *      Indent a line to the given level.  Note that this is
 *      a simple minded but portable implementation.
 *      There are better ways.
 *
 *      Also, the indent must be scaled by the compile time option
 *      of character positions per nesting level.
 *
 */

LOCAL VOID Indent (int indent)
{
    REGISTER int count;
    AUTO char buffer[PRINTBUF];

    indent *= INDENT;
    for (count = 0; (count < (indent - INDENT)) && (count < (PRINTBUF - 1)); count++) {
      if ((count % INDENT)
jmvalkAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
You didn't post the header file (thus a comment ;-) - but changing

 stderr, /* LINE 264 */

to read

 (const FILE*) stderr, /* LINE 264 */

should IMHO be sufficiant...
0
jmvalkAuthor Commented:
jkr,

telling the compiler that stderr is a const didn't help. I am quite sure that the file compiled in its current state, so I suspect there to be something wrong with my environment, but off course I may be wrong. Just to make this question longer, here are the 2 non-standard headers config.h and dbug.h, respectively,

thanks,

JM
-----
config.h:

#define HASSTDARG 1
#define HASVARARGS 0
#define HASPERROR 1
#define HASCHOWN 1
#define HASGETGID 1
#define HASGETPID 1
#define HASGETUID 1
#define HASACCESS 1
#define HASCLOCK 1
#define HASFTIME 1
#define HASGETRUSAGE 1
#define HASDATESTAMP 0
#define HASSLEEP 1
#define SLEEPGRANULARITY 'S'
#define HASDELAY 0
#define HASSETJMP 1
#define DIRSEP '/'

dbug.h:
/*
 *  FILE
 *
 *      dbug.h    user include file for programs using the dbug package
 *
 *  SYNOPSIS
 *
 *      #include <local/dbug.h>
 *
 *  SCCS ID
 *
 *      @(#)dbug.h      1.12 4/2/89
 *
 *  DESCRIPTION
 *
 *      Programs which use the dbug package must include this file.
 *      It contains the appropriate macros to call support routines
 *      in the dbug runtime library.
 *
 *      To disable compilation of the macro expansions define the
 *      preprocessor symbol "DBUG_OFF".  This will result in null
 *      macros expansions so that the resulting code will be smaller
 *      and faster.  (The difference may be smaller than you think
 *      so this step is recommended only when absolutely necessary).
 *      In general, tradeoffs between space and efficiency are
 *      decided in favor of efficiency since space is seldom a
 *      problem on the new machines).
 *
 *      All externally visible symbol names follow the pattern
 *      "_db_xxx..xx_" to minimize the possibility of a dbug package
 *      symbol colliding with a user defined symbol.
 *      
 *      The DBUG_<N> style macros are obsolete and should not be used
 *      in new code.  Macros to map them to instances of DBUG_PRINT
 *      are provided for compatibility with older code.  They may go
 *      away completely in subsequent releases.
 *
 *  AUTHOR
 *
 *      Fred Fish
 *      (Currently employed by Motorola Computer Division, Tempe, Az.)
 *      hao!noao!mcdsun!fnf
 *      (602) 438-3614
 *
 */


/*
 *      Internally used dbug variables which must be global.
 */

#ifndef DBUG_OFF
    extern int _db_get_on_ (void);                  /* TRUE if debug currently enabled */
    extern FILE *_db_get_fp_( void );                  /* Current debug output stream */
    extern void _db_set_process_( char * process);      /* Name of current process */
    extern int _db_keyword_ (char *keyword);            /* Accept/reject keyword */
    extern void _db_push_ (char *control);            /* Push state, set up new state */
    extern void _db_pop_ ( void );                  /* Pop previous debug state */
    extern void _db_enter_ (                        /* New user function entered */
                      char *_func_,
                      char *_file_,
                      int _line_,
                      char **_sfunc_,
                      char **_sfile_,
                      int *_slevel_,
                      char ***_sframep_ );
    extern void _db_return_ (                        /* User function return */
                       int _line_,
                       char **_sfunc_,
                       char **_sfile_,
                       int *_slevel_ );
    extern void _db_pargs_ (                        /* Remember args for line */
                      int _line_,
                      char *keyword );
    extern void _db_doprnt_ (char *format, ...);      /* Print debug output */
    extern void _db_setjmp_ ( void );                  /* Save debugger environment */
    extern void _db_longjmp_ ( void );                  /* Restore debugger environment */
# endif


/*
 *      These macros provide a user interface into functions in the
 *      dbug runtime support library.  They isolate users from changes
 *      in the MACROS and/or runtime support.
 *
 *      The symbols "__LINE__" and "__FILE__" are expanded by the
 *      preprocessor to the current source file line number and file
 *      name respectively.
 *
 *      WARNING ---  Because the DBUG_ENTER macro allocates space on
 *      the user function's stack, it must precede any executable
 *      statements in the user function.
 *
 */

# ifdef DBUG_OFF
#    define DBUG_ENTER(a1)
#    define DBUG_RETURN(a1) return(a1)
#    define DBUG_VOID_RETURN return
#    define DBUG_EXECUTE(keyword,a1)
#    define DBUG_PRINT(keyword,arglist)
#    define DBUG_2(keyword,format)            /* Obsolete */
#    define DBUG_3(keyword,format,a1)            /* Obsolete */
#    define DBUG_4(keyword,format,a1,a2)      /* Obsolete */
#    define DBUG_5(keyword,format,a1,a2,a3)      /* Obsolete */
#    define DBUG_PUSH(a1)
#    define DBUG_POP()
#    define DBUG_PROCESS(a1)
#    define DBUG_FILE (stderr)
#    define DBUG_SETJMP setjmp
#    define DBUG_LONGJMP longjmp
# else
#    define DBUG_ENTER(a) \
      auto char *_db_func_; auto char *_db_file_; auto int _db_level_; \
      auto char **_db_framep_; \
      _db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_, \
                &_db_framep_)
#    define DBUG_LEAVE \
      (_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
#    define DBUG_RETURN(a1) return (DBUG_LEAVE, (a1))
/*   define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);}  Alternate form */
#    define DBUG_VOID_RETURN {DBUG_LEAVE; return;}
#    define DBUG_EXECUTE(keyword,a1) \
      {if (_db_get_on_()) {if (_db_keyword_ (keyword)) { a1 }}}
#    define DBUG_PRINT(keyword,arglist) \
      {if (_db_get_on_()) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
#    define DBUG_2(keyword,format) \
      DBUG_PRINT(keyword,(format))            /* Obsolete */
#    define DBUG_3(keyword,format,a1) \
      DBUG_PRINT(keyword,(format,a1))            /* Obsolete */
#    define DBUG_4(keyword,format,a1,a2) \
      DBUG_PRINT(keyword,(format,a1,a2))      /* Obsolete */
#    define DBUG_5(keyword,format,a1,a2,a3) \
      DBUG_PRINT(keyword,(format,a1,a2,a3))      /* Obsolete */
#    define DBUG_PUSH(a1) _db_push_ (a1)
#    define DBUG_POP() _db_pop_ ()
#    define DBUG_PROCESS(a1) _db_set_process_(a1)
#    define DBUG_FILE (_db_get_fp_())
#    define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
#    define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
# endif


/*
 *      These procedures provide a user interface for external programs
 *      who can not use macro's. An example is a Perl program.
 *      The dbug_call_info parameter is a handle and will be set by
 *      dbug_enter and reset by dbug_leave.
 *
 */

extern void dbug_enter( char * i_module, long *o_dbug_call_info );
extern void dbug_leave( long i_dbug_call_info );
extern void dbug_push( char * i_options );
extern void dbug_print1(
      char * i_keyword, char * i_fmt, char * i_arg1 );
extern void dbug_print2(
      char * i_keyword, char * i_fmt, char * i_arg1, char * i_arg2 );
extern void dbug_print3(
      char * i_keyword, char * i_fmt, char * i_arg1, char * i_arg2,
      char * i_arg3 );
extern void dbug_print4(
      char * i_keyword, char * i_fmt, char * i_arg1, char * i_arg2,
      char * i_arg3, char * i_arg4 );
extern void dbug_print5(
      char * i_keyword, char * i_fmt, char * i_arg1, char * i_arg2,
      char * i_arg3, char * i_arg4, char * i_arg5 );
extern void dbug_pop( void );
extern void dbug_process( char * i_process );
0
IsacCommented:
jmvalk,

The program doen't really use the structure allocated in line 264, so you may change it from

stderr, /* LINE 264 */

to be

 0, /* LINE 264 */

 and it will work well.

Best regards !
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jmvalkAuthor Commented:
Isac,

I tried it, and it works. Thanks! The only thing I wonder about now is why the initialization
fails in the first place? It seems that in other  places in the code initialization
works just fine using stderr.

The points are yours, Isac, but could someone give an answer to this question?

[ I have already accepted and graded the answer, since I may be unable to do so in the next weeks,
but the answer to the question above is still interesting IMO. I may have underrated the answer
as 'good' but the current solution is, I think, a work-around, more than a solution. If I did, I am sorry. ]

JM
0
IsacCommented:
The problem with initializing with "stderr" is that this is not a constant but a variable.
You may not initialize a global variable with the value of another variable.
Maybe in other OS the token "stderr" is a constant (I think its value is 2), and therefore the initializing works there OK.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.