#ifndef V_h
#define V_h	VBSID

#define audit_h	VBSID
#define verbose_h	VBSID
#define VBSID	"John Chambers' C aud/V package R.3.5."
#define USE_V	9
#ifndef DEBUG	/* Some packages like to use this symbol */
#define DEBUG	9
#endif

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright 1984, 1988, 1992, 1994, 1996 by John Chambers <jc@trillian.mit.edu>. *
* This copyright is solely to prevent other people from claiming that they *
* own this package.  You are free to use it however you wish.  If you make *
* any modifications thay may be of use to others, please send me a copy.   *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
* This is the header  file  for  John  Chambers'  C/Unix  audit/debug/verbose
* package.   We  use  all three names to satisfy various constituencies.  See
* V.d (or verbose.d) for instructions. You will probably have to study this
* header  file  to  reach  a  good  understanding  of  what's going on.  Note
* especially that we #include a variety of other files.  You should  probably
* replace  stdio.h  with  this  file (audit.h or V.h or verbose.h).  If you
* insist on retaining stdio.h or any of the header files #included here,  you
* should include this file after them all to avoid multiple #includes.
*
* Note that there are some other .h files that must be present if you are  to
* use this package. This file, "V.h", also #includes "local.h", which you
* will want to examine and edit.  There are a few others ...
*
* The  "local.h"  file  is  used  to define things that are hopelessly system
* dependent, and you should edit it before doing anything else.
*/
#ifndef local_h
#include	"local.h"	/* Things specific to this system */
#endif
#ifndef sys_h
#include	"sys.h"	/* Wrappers for system library functions */
#endif
#ifndef str_h
#include	"str.h"	/* JC's string-handling package */
#endif
#if	defined(USE_syscall)	&& !defined(SYS_open)
#include	<syscall.h>
#endif

/*
* Next, some useful pseudo-types.  We check to  make  sure  that  they  aren't
* already defined, because lots of other packages use them, too. It sure would
* be nice if C gave us a way to test whether a typedef is defined.
*/
#ifndef Flag	/* Used only for for true/false flags */
#define Flag	char
#endif
#ifndef byte	/* Common term for 8-bit unsigned bytes */
#define byte	unsigned char
#endif
#ifndef Uint	/* Common pseudo-type */
#define Uint	unsigned int
#endif
#ifndef global	/* Used for emphasis and documentation */
#define global
#endif
#ifndef BP	/* Useful abbreviations */
#define BP	byte*
#endif
#ifndef CCP
#define CCP	const char*
#endif
#ifndef VP	/* Useful abbreviations */
#define VP	void*
#endif
#if	!defined(CP) && !defined(NULLCP)	/* Isode typedefs CP and #defines NULLCP */
#define CP	char*
#endif
#if	!defined(Sizt)	/* Used for sizes of arrays */
#define Sizt unsigned long	/* Correct on most systems these days */
#endif

/*
* Here are some pseudo-types (abbreviations) that come in  handy  when
* we  want  to  specify types by the number of bits.  This offends the
* theoreticians, of course, but when writing comm code, you often have
* no alternative.
*/
#ifndef I8
#define I8	char
#endif
#ifndef I16
#define I16	short
#endif
#ifndef I32
#define I32	long
#endif
#ifndef U8
#define U8	unsigned char
#endif
#ifndef U16
#define U16	unsigned short
#endif
#ifndef U32
#define U32	unsigned long
#endif

/*
* Here are some pseudo-types that abbreviate some common structures:
*/
#ifndef DIRE	/* Directory entry has various names */
#if	USE_direct
#define DIRE	struct direct
#endif
#if	USE_dirent
#define DIRE	struct dirent
#endif
#endif
#ifndef HOST	/* Host names and addresses */
#define HOST	struct hostent
#endif
#ifndef INAD	/* Internet addres struct */
#define INAD	struct in_addr
#endif
#ifndef IPKT	/* IP packet header */
#define IPKT	struct ip
#endif
#ifndef IP32	/* 32-bit IP address */
#define IP32	unsigned long
#endif
#ifndef SKAD	/* Generic socket structure */
#define SKAD	struct sockaddr
#endif
#ifndef SKln	/* Generic socket address length */
#define SKln	socklen_t
#endif
#ifndef SKaddr
#define SKaddr sin_addr.s_addr
#endif
#ifndef SKDN	/* DECnet socket structure */
#define SKDN	struct dn_naddr
#endif
#ifndef SKin	/* Internet socket structure */
#define SKin	struct sockaddr_in
#endif
#ifndef STat	/* Unix file-status structure */
#define STat	struct stat
#endif
#ifndef TIME	/* Unix broken-out time structure */
#define TIME	struct tm
#endif
#ifndef TIMV	/* Unix microsecond timer structure */
#define TIMV	struct timeval
#endif
#ifndef TIMZ	/* Unix timezone structure */
#define TIMZ	struct timezone
#endif

/*
* We get around the insanities involved with the system header in one  of  two
* ways:   We put the job into little header files with names like "sys_time.h"
* and "sys_types.h", or we just edit this file for every system.  If you don't
* see  the  "sys_"  files  here, it means you're looking at a version that was
* doctored for a task that "doesn't need to be portable".  [Yeah, sure! ;-]
*/
#ifdef	NOTNOW
#include	<ctype.h>	/* Unix character types */
#include	<sys/types.h>	/* Unix pseudo-types */
#include	<time.h>	/* Unix ctime and tm structure */
#include	<sys/time.h>	/* Unix timeval structure */
#include	<errno.h>	/* Unix error handling */
#include	<stdio.h>	/* Unix I/O package */
#define ctype_h	/* Prevent multiple inclusion */
#define errno_h
#define sys_time_h
#define sys_types_h
#else
#include	"sys_ctype.h"	/* Unix character types */
#include	"sys_types.h"	/* Unix pseudo-types */
#include	"sys_time.h"	/* Unix ctime and timeval types */
#include	"sys_stdio.h"	/* Unix I/O package */
#include	"sys_errno.h"	/* Unix error handling */
#endif

/*
* Here are some silly  little  things  to  make  the  anti-goto  crowd
* happier  with  our  code.  These pseudo-commands are, of course, the
* pro-goto crowd's favorite counterexamples to debunk this  particular
* bit of ideology.  They are also quite useful control structures that
* are sorely missing from C.  But cpp can create them for us, so ...
*/
#ifndef Done
#define Done	goto done
#endif
#ifndef Fail
#define Fail	goto fail
#endif
#ifndef FailM
#define FailM(m)	{Vmsg=m;goto fail;}
#endif
#ifndef FailR
#define FailR(v)	{r=v;goto fail;}
#endif
#ifndef Loop
#define Loop	goto loop
#endif
#ifndef Next
#define Next	goto next
#endif
#ifndef forever
#define forever	while(1)
#endif
#ifndef elsif	/* Useful "typo" from various shells */
#define elsif else if
#endif
#ifndef until	/* Useful "typo" from perl */
#define until(e) while (!(e))
#endif
#ifndef unless	/* Useful "typo" from perl */
#define unless(e) if (!(e))
#endif

/*
* Some useful pseudo-types:
*/
#ifndef Flag	/* Pseudo-type for true/false flags */
#define Flag	char
#endif
#ifndef byte	/* Popular pseudo-type for 8-bit unsigned bytes */
#define byte	unsigned char
#endif
#ifndef FCT	/* Pseudo-class for documentation */
#define FCT
#endif
#ifndef global	/* Pseudo-class for documentation */
#define global
#endif
#ifndef NP
#define NP	(char*)0
#endif
#ifndef DIRE
#ifdef	USE_direct
#define DIRE	struct direct
#endif
#ifdef	USE_dirent
#define DIRE	struct dirent
#endif
#endif
#ifndef Ile
#define Ile(x,y)	((I32)(x)<=(I32)(y))
#endif
#ifndef Ige
#define Ige(x,y)	((I32)(x)>=(I32)(y))
#endif
#ifndef Ilt
#define Ilt(x,y)	((I32)(x)<(I32)(y))
#endif
#ifndef Igt
#define Igt(x,y)	((I32)(x)>(I32)(y))
#endif
#ifndef Max
#define Max(x,y)	(Lt((x),(y))?(y):(x))
#endif
#ifndef Min
#define Min(x,y)	(Gt((x),(y))?(y):(x))
#endif
#ifndef Max3
#define Max3(x,y,z)	(Lt((x),(y))?Max(y,z):Max(x,z))
#endif
#ifndef Min3
#define Min3(x,y,z)	(Gt((x),(y))?Min(y,z):Min(x,z))
#endif
#ifndef MinSS
#define MinSS(x) Strnlen(x,sizeof(x))
#endif

/*
* Here's a kludge for dealing with compilers that don't grok the void type.
#define Call	(void)
#define Subr	int
*/

/*
* Our open-file table, openfiles, is used to hold the names of files, and  an
* cssortment  of other useful information tidbits.  We need to know how big to
* make our file table.  In a perfect world, we'd have time to change both this
* and  the kernel's table to a linked list, and be done with the problems that
* a fixed-size table causes.
*/
#ifndef OPEN_MAX
#include	<limits.h>	/* This is where it's usually defined */
#endif
#ifndef OPEN_MAX
#define OPEN_MAX	20 /* If all else fails */
#endif

/*
* Sometimes Vout is null; V_out should always be non-null.
*/
#define V_out ((Vout)?(Vout):(stderr))

/*
* Here are some definitions that may be already set up, so let's  be  careful.
* It  sure would be nice if C had a way of testing for the existence of things
* like typedefs.
*/
#ifndef CHARSETSIZE	/* Number of distinct bytes */
#define CHARSETSIZE	256 /* 8-bit bytes */
#endif
#ifndef NETADDRLEN
#define NETADDRLEN	48 /* Max length of network address, including port, in bytes */
#endif

/*
* Here is what we remember about open files.  This is our own open-file  table
* in parallel with the kernel's, so that we can do things like report the name
* that was used to open a file, something that has been sorely lacking in Unix
* libraries from the start.  If you use the debug macros to do I/O, the offset
* (addr) field will also be maintained here.
*/
#define File	struct V_open_file
File {
	File* next;		/* Next one in list */
	Str   name;		/* Copy of name used to open the file */
	int   lfd;		/* Local file descriptor */
	int   rfd;		/* Remote file descriptor */
	long  addr;		/* Byte offset, if known */
	U16   flgs;		/* Assorted 1-bit flags */
	U16   port;		/* TCP/UDP port, if any */
	U32   ipad;		/* IP address, if any */
	Uint  reads;	/* Number of read operations */
	Uint  writes;	/* Number of write operations */
};
extern	File* openfiles;	/* List of open files */
extern	File* openfilez;	/* Last open file in list */
extern  int   openfilemax;	/* Highest file number seen so far */
extern	File* d_openfile();	/* Find descriptor for open file */
extern	File* d_newfile();	/* Make descriptor for new file */
#define File_OPEN	0x01 /* File is open */
#define File_SOCK	0x02 /* File is a socket */
#define File_PIPE	0x04 /* File is a pipe */
#define File_FIFO	0x04 /* File is a fifo */
#define File_PNI	0x08 /* File is a PNI device */
#define File_TERM	0x10 /* File is a tty or pty */
#define File_MBOX	0x20 /* File is a mailbox */
#define File_LOCAL	0x40 /* File source is local kernel */
#define File_REMOTE	0x80 /* File source is remote server */

/*
* Here is the real start of the debug-package definitions.  Note our kludge to
* handle  variable numbers of args.  Perhaps eventually the ANSI C solution to
* this problem will become universal, and we can dispense with this.
*/
#define ARGLIST	x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf
#define B8(x)	(((int)(x))&0x00FF)
#define B7(x)	(((int)(x))&0x007F)
#define B4(x)	(((int)(x))&0x000F)
#define Ctrl(x)	((int)(x)&0x0001F)
#define E	V1

/*
* The U(x) function is used mostly to overcome idiotic strong typing.
*/
#define U(x)	((U32)(x))

/*
* The IV(x) and PV(x) functions are used to safely dereference a pointer.
* IV gives just the value; PV gives the pointer and the value.
*/
#define IV(x)	((x)?(*x):0)
#define PV(x) (x),((x)?(*x):0)

/*
* Here are two symbolic names for the error code and message.  We have done it
* as two symbols, because some libraries (e.g. on DOS) handle the "system" and
* "network" errors separately.  On Unix, these are synonyms.  A typical use of
* these might be:
*   V3 "### Can't write to \"%s\" [Err %d=%s]",filnam,Erreason D;
* The Errinfo macro requires the err.c module, delivers the E* acronym, and is
* used cs:
*   V3 "### Can't write to \"%s\" [Err %d=%s=%s]",filnam,Errinfo D;
*/
#define s_errmsg sys_errmessage
#define Erreason	errno,s_errmsg(errno)
#define Errmsg	Errinfo
#define Errlist	Errinfo
#define Errcnm	Errinfo
#define Errinfo	errno,sys_errname(errno),sys_errmessage(errno)
#define Netreason	errno,s_errmsg(errno)
#define Ereason	e,s_errmsg(e)

/*
* If you'd like the debug output to show the  function  nesting,  include  the
* Fenter("foo") macro at the entry and Fexit at the return of functions.  Note
* that Fenter() must be between the local variables and the  first  executable
* instruction,  unless  your  compiler  can handle intermixed declarations and
* statements.  Even if it can, it's advisable to put  Fenter  after  the  last
* local declaration, to ensure portability.
*
* The Freturn(x) macro is a combined pop-and-return; there is also a Return(x)
* macro defined  for  backwards  compatibility,  and  for  experimenting  with
* different definitions on some systems. You'd think they would be equivalent,
* but they may not be, depending on your compiler.  The  FExit  macro  invokes
* ChkFlvl to do a sanity check on the function stack.
*
* Note that if you use Fenter() on entry to a function, you can use Fctname in
* output to produce the function's name.  We define the older names, too,  for
* backwards  compatibility, and for the benefit of those people whose like the
* push/pop metaphore better than the enter/exit metaphor.  Note also the Fexit
* and  FExit  macros; the latter invokes the ChkFlvl macro, to verify that the
* function stack is OK.
*/
extern	CP Fctname;	/* Global, in case there's no local */
#define V_f	struct V_fct_struct

#ifdef USE__LINE__	/* Are we doing line numbers? */
V_f {
	char* name;
	V_f* list;
	int   line;
	char* file;
};
#define VBSline (Vfcts->line=__LINE__)
#define Fenter(fct) \
	static CP Fctname = fct; \
	V_f Vf; \
	int  flevel; \
	Vf.name = Fctname; \
	Vf.list = Vfcts; \
	Vf.line = __LINE__; \
	Vf.file = __FILE__; \
	Vfcts = &Vf; \
	flevel = ++Vflvl;
#else	/*USE__LINE__*/	/* We aren't doing line numbers */
V_f {
	char* name;
	V_f* list;
};
#define VBSline 0
#define Fenter(fct) \
	static CP Fctname = fct; \
	V_f Vf; \
	int  flevel; \
	Vf.name = Fctname; \
	Vf.list = Vfcts; \
	Vfcts = &Vf; \
	flevel = ++Vflvl;
#endif	/*USE__LINE__*/
extern	V_f * Vfcts;
extern	V_f   Vf;
#define Fexit	(        (Vfcts)?((Vfcts=Vfcts->list),Vflvl--):0)
#define FExit	(ChkFlvl,(Vfcts)?((Vfcts=Vfcts->list),Vflvl--):0)
#define FReturn(x) {Fexit; return(x);}
#define Freturn(x) {Fexit; return(x);}
#define FReturnVoid {Fexit; return;}
#define FreturnVoid {Fexit; return;}

/*
* This symbol is used inside ifs to store some local info into global vars
* just before calling debug functions.
*/
#define VBSdmsg Vdmsg(&Vf,
#define VBSpmsg Vpmsg(
#define VBSsmsg Vsmsg(
#define VBSvmsg Vvmsg(

/*
* The D macro is  used  to  terminate  a  D*  param  list.   Too  bad  the  C
* preprocessor  can't  handle  variable-length  lists;  it if could, we could
* dispense with this cruft and just use function notation.  Now if only m4 or
* perl were available everywhere that C is used.
*/
#define D )
#define V )
#define Vfl ),fflush(V_out)

/*
* Here we define VBSinitial and VBSfinal to be the char strings that we  need
* to  put  before  and  after  the  V?msg() function call.  This is usually
* trivial, but we've used it to do some  nontrivial  things,  such  as  mutex
* locking when using threads.
*/
#define VBSinitial 0,
#define VBSfinal )

/*
* Here's a pair of macros for wrapping a fprintf(...) call:
*/
#define P  )
#define PF printf(
#define FP fprintf(
#define IFP(f) if (f) fprintf(f,
/*
#define P  VBSfinal;}
#define FP {VBSinitial fprintf(
#define PF {VBSinitial printf(
*/

/*
* Here are two macros for checking the function stack for validity. The second
* has an extra identifying message.  Note that we first check that the Vfcts
* pointer points to the current function; if that is correct, we  don't  check
* further.  If it is different (usually because someone didn't call Fexit), we
* invoke the Vchkstk() routine to do some more extensive checking.
*/
#define ChkFlvl \
	(Une(&Vf,Vfcts)?(((Vlvl>=2)?Vpmsg(m_fctbad,NulC(Vf.name),__FILE__,__LINE__):0),Vchkstk(&Vf,__FILE__,__LINE__)):0)
#define ChkFlvlM(m) \
	if(Une(&Vf,Vfcts)){Vpmsg(m_fctbad,NulC(m)),__FILE__,__LINE__;Vchkstk(&Vf,__FILE__,__LINE__);}

/*
* The following define debug macros called like:
*   Dy('m',3)("The value of x is %d.",x);
* which means to write the debug message if the 'm' debug flag is 3 or higher.
* Note  that  various  packages may define their own further abbreviations for
* such macros, to save on typing and source code, and increase readability.
*/
#define DD(c,l)	if(Vflg[c]>=l)VBSdmsg l,
#define DP(c,l)	if(Vflg[c]>=(Vl=l))VBSpmsg l,
#define DS(c,l)	if(Vflg[c]>=(Vl=l))VBSsmsg l,
#define DV(c,l)	if(Vflg[c]>=(Vl=l))VBSvmsg l,
#define DH(c,l,p,n,m) \
	if(Vflg[c]>=(Vl=l))dmp_hexd(Fileno(V_out),(CP)(p),(CP)(p)+(n)-1,m,(U32)(p))

/*
* The following define debug macros called like:
*   V3("The value of x is %d.",x);
* which writes the message to the logfile if Vlvl is 3 or greater. Note that
* a  newline  is  added  and fflush is called, so you shouldn't need to bother
* with these.
*/
#define V0	if(Vlvl>=0)VBSdmsg 0,
#define V1	if(Vlvl>=1)VBSdmsg 1,
#define V2	if(Vlvl>=2)VBSdmsg 2,
#define V3	if(Vlvl>=3)VBSdmsg 3,
#define V4	if(Vlvl>=4)VBSdmsg 4,
#define V5	if(Vlvl>=5)VBSdmsg 5,
#define V6	if(Vlvl>=6)VBSdmsg 6,
#define V7	if(Vlvl>=7)VBSdmsg 7,
#define V8	if(Vlvl>=8)VBSdmsg 8,
#define V9	if(Vlvl>=9)VBSdmsg 9,

/*
* The P* functions just print, add a newline, and flush, but don't add
* any initial identification to the messages.
*/
#define P0	if(Vlvl>=0)VBSpmsg 0,
#define P1	if(Vlvl>=1)VBSpmsg 1,
#define P2	if(Vlvl>=2)VBSpmsg 2,
#define P3	if(Vlvl>=3)VBSpmsg 3,
#define P4	if(Vlvl>=4)VBSpmsg 4,
#define P5	if(Vlvl>=5)VBSpmsg 5,
#define P6	if(Vlvl>=6)VBSpmsg 6,
#define P7	if(Vlvl>=7)VBSpmsg 7,
#define P8	if(Vlvl>=8)VBSpmsg 8,
#define P9	if(Vlvl>=9)VBSpmsg 9,

/*
* The Pf* functions are conditional calls  on  printf().   This  is  mostly  a
* keystroke-saving gimmick.  Recommended use is solely for simple verbose-mode
* messages that should be mixed in with the stdout stream.  This has also been
* used  with  threaded code to handle the ongoing problems with stdio packages
* that aren't thread-safe.
*/
#define Pf0	if(Vlvl>=0)printf(
#define Pf1	if(Vlvl>=1)printf(
#define Pf2	if(Vlvl>=2)printf(
#define Pf3	if(Vlvl>=3)printf(
#define Pf4	if(Vlvl>=4)printf(
#define Pf5	if(Vlvl>=5)printf(
#define Pf6	if(Vlvl>=6)printf(
#define Pf7	if(Vlvl>=7)printf(
#define Pf8	if(Vlvl>=8)printf(
#define Pf9	if(Vlvl>=9)printf(

/*
* Some similar macros for writing to the syslog:
*/
#define S0	if(Vlvl>=0)VBSsmsg
#define S1	if(Vlvl>=1)VBSsmsg
#define S2	if(Vlvl>=2)VBSsmsg
#define S3	if(Vlvl>=3)VBSsmsg
#define S4	if(Vlvl>=4)VBSsmsg
#define S5	if(Vlvl>=5)VBSsmsg
#define S6	if(Vlvl>=6)VBSsmsg
#define S7	if(Vlvl>=7)VBSsmsg
#define S8	if(Vlvl>=8)VBSsmsg
#define S9	if(Vlvl>=9)VBSsmsg

/*
* Here are some macros for conditional hex dumps.  Note the parameters:
*   p is a pointer to the first byte to dumpl.
*   n is the number of bytes to dump.
*   m is a short (8 char m) id message for the first line of the dump.
* The dump is written to Vout.
*/
#define H0(p,n,m)	if(Vlvl>=0)Hexdnm(p,n,m)
#define H1(p,n,m)	if(Vlvl>=1)Hexdnm(p,n,m)
#define H2(p,n,m)	if(Vlvl>=2)Hexdnm(p,n,m)
#define H3(p,n,m)	if(Vlvl>=3)Hexdnm(p,n,m)
#define H4(p,n,m)	if(Vlvl>=4)Hexdnm(p,n,m)
#define H5(p,n,m)	if(Vlvl>=5)Hexdnm(p,n,m)
#define H6(p,n,m)	if(Vlvl>=6)Hexdnm(p,n,m)
#define H7(p,n,m)	if(Vlvl>=7)Hexdnm(p,n,m)
#define H8(p,n,m)	if(Vlvl>=8)Hexdnm(p,n,m)
#define H9(p,n,m)	if(Vlvl>=9)Hexdnm(p,n,m)

/*
* Assorted obsolete and/or longer names, which should probably  be  left  here
* because  some  people  like things wordy or just like these alternate names.
* The main reason for doing all this is to handle code  from  various  sources
* that use any of these names for the global debug variables.  It'd be nice if
* we could establish a standard way of doing this in C,  but  that's  probably
* hopeless given the current anarchy.
#define D_level	Vlvl
#define V_level	Vlvl
#define Vlevel	Vlvl
#define debuglevel	Vlvl
#define debugflevel	Vflvl
#define debugflvl	Vflvl
#define debugfile	Vfile
#define debugfname	Vfnam
*/

/*
* We've used these names in other version of this package, but they probably
* shouldn't be used any more.  The above names are better, IMHO.
*/
#define Fname(fct)	Fenter(fct)
#define Fpush(fct)	Fenter(fct)
#define Fpop	Fexit
#define Return(x)	{Fexit;return(x);}

/*
* Here is some global data required by hex dumps:
*/
#define PERLINE	64+7
#define INDENT	9
#define HXLINE	(INDENT+PERLINE+3) /* Longest output line */
extern	char *hex_as;
extern	char *hex_hi;
extern	char *hex_lo;
extern	char hex_dig[];
extern	int  hex_fmt;		/* Format: 'H' or 'V' */
extern	Flag hex_base;		/* 0: show offset; 1: show base address */
extern	int  hex_word;		/* Word size in hex dumps [default=8] */
extern	char Vblanks[];	/* A buffer full of blanks */
extern	int  dspxword;	/* Word size for dspx() */
extern  Flag V_locking;	/* Should we use pthread_lock_global_np? */

/*
* Here are some macros for generating ASCII and hex dumps.  The last two chars
* of  the  name implies the types of the last two params.  Note that the dumps
* are always written to Vout.  The params are as follows:
*   p is a pointer to the first byte to dump.
*   q is a pointer to the last byte to dump.
*   n is the number of bytes to dump.
*   m is a short (8 bytes m) id string for the first line of output.
*   a is the address to use for the first line of the dump (instead of p).
*/
#define Ascdna(p,n,a)	dmp_ascd(Fileno(V_out),(CP)(p),(CP)(p)+(n)-1,0,(U32)(a))
#define Ascdnm(p,n,m)	dmp_ascd(Fileno(V_out),(CP)(p),(CP)(p)+(n)-1,m,(U32)(p))
#define Hexdna(p,n,a)	dmp_hexd(Fileno(V_out),(CP)(p),(CP)(p)+(n)-1,0,(U32)(a))
#define Hexdnm(p,n,m)	dmp_hexd(Fileno(V_out),(CP)(p),(CP)(p)+(n)-1,m,(U32)(p))
#define Hexdpa(p,q,a)	dmp_hexd(Fileno(V_out),(CP)(p),(CP)(q) ,0,(U32)(a))
#define Hexdpm(p,q,m)	dmp_hexd(Fileno(V_out),(CP)(p),(CP)(q) ,m,(U32)(p))

/*
* Here are some macros for those that want to write to a specific file:
*/
#define Ascfpna(f,p,n,a)	dmp_ascd(f,(CP)(p),(CP)(p)+(n)-1,(CP)0,(U32)(a))
#define Hexfpna(f,p,n,a)	dmp_hexd(f,(CP)(p),(CP)(p)+(n)-1,(CP)0,(U32)(a))

/*
* We have are lots of external  function  and  variable  declarations.
* Many  of these are useful to applications, though you should be wary
* of using the more obscure things, because  future  releases  may  do
* things differently. First, here are the main debug output-generating
* routines:
*/
extern	int    Vdmsg();		/* Annotated debug output */
extern	int    Vpmsg();		/* Plain debug output */
extern	int    Vsmsg();		/* Syslog debug output */
extern	int    Vvmsg();		/* Debug output to syserr */

extern	int    Vchklog();  /* Close and reopen logfile if missing or too big */

extern	char*  Venvvar;	/* Name of program's environment variable */
extern	char*  Venvar1;	/* Name of program's environment D_ variable */
extern	char*  Venvar2;	/* Name of program's environment V_ variable */
extern	char*  Vfile;		/* Name of debug output file */
extern	char   Vflgchr;	/* Debug option flag */
extern	char   Vflg[CHARSETSIZE];	/* Debug flags */
extern	int    Vflvl;		/* Debug function level */
extern	V_f   Vfctroot;	/* Should be program name */
extern	int    Vfshow;		/* Levels to show in V output; -1 means Vlvl */
extern	int    Vlvl;		/* Debug level [0-9] */
extern	int    Vl;			/* Debug level [0-9] of last message */
extern	char*  Vmodule;	/* Name of current module, if known */
extern	char*  Vmsg;		/* Error message */
extern	Str    Voptstr;	/* Saved copy of debug option string */
#define Voption Voptstr.v
extern	int    VoptLvl;	/* For preventing recursion in Vopt() */
extern	FILE*  Vout;		/* Debug output file, defaults to stderr */
extern	Flag   VshowLvl;	/* Show the debug level */
extern	Sizt   Vsizlim;	/* Output file size limit */
extern	int    Vsleep;		/* Sleep after debug output lines */
extern	TIMV   Vtimev;		/* The latest timestamp */
#define Vtiml Vtimev.tv_sec	/* old name for current timestamp */
extern	TIMZ   Vtimez;		/* Our timezone, if known */
extern	char*  Vtimh;		/* ASCII version of time, starts with hour */
extern	char*  Vtimm;		/* ASCII version of time, starts with month */
extern	char*  Vtimp;		/* ASCII version of time */
extern	char   Vtims[32];	/* Latest time, UT, ASCII */
extern	char*  Vtimy;		/* ASCII version of time, starts with year */
extern	char*  Vtimezone;	/* Timezone; see Vtime() */
extern	struct tm *Vtimep;	/* Latest (struct tm) */
extern	int    hex_word;		/* Word size in hex dumps */

extern	Flag   V_pthreads;	/* Are we debugging pthreads? */
extern	Flag   use_pthreads;	/* Are we using pthreads? */
extern	int    Vdmpft();	/* Dump the file table, return count */
extern	char*  Vfilnam();	/* Get name of file */
extern	int    Vinit();	/* Run-time initializer for V package */
extern	void   Vopt();		/* Initializer for the V package */
extern	void   V_df();		/* Generates function names in V output */
extern	Flag   V_inline;	/* Says that V_buf module has chars buffered */
extern	char*  getenv();		/* Unix environment get routine */
extern	int    putenv();		/* Unix environment set routine */
extern	char*  sys_errmessage();
extern	char*  sys_errname();
extern	int    verbose;		/* Verbose output goes to stderr */

#if	defined USE_syslog
extern	Flag   syslogf;		/* Try to use the syslog package */
#endif	/* USE_syslog */

extern	int   dfltVlvl;	/* See agent for this bit of kludgery */
extern	int   realVlvl;

extern	int   errno;			/* UNIX error code */
extern	char**environ;		/* UNIX environment vector */
extern	TIMV  Vtim0;		/* When the V package was last initialized */
extern	TIMZ  Vtimz;		/* The time zone that the kernel thinks it's in */
extern	char *Vtime();		/* Get current time as printable string */
extern	char *Vtimstr();	/* Convert timestamp to printable string */
extern	Flag  stdiofl;		/* Permission to write to stdio */
extern	char *s_errmsg();	/* Return errno message string */

extern	Flag  sock0fl;		/* File0 is a socket; e.g., started by inetd */
extern	Flag  pipe0fl;		/* File0 is a fifo/pipe; e.g., started by csn1d */
extern	int   openfilemax;	/* Highest open file number */
extern	char *progname;		/* Program name */
extern	char *pname;		/* Program name, usually lastfld(progname) */

/*
* Here are some macros to extract the address and port number from sockaddr_in
* variables,  either as structs or as pointers.  Note that we convert the byte
* order to that of the host.
*/
#define IAhost(x)	ntohl((x).sin_addr.s_addr)
#define IPhost(x)	ntohl((x)->sin_addr.s_addr)
#define IAport(x)	ntohs((x).sin_port)
#define IPport(x)	ntohs((x)->sin_port)
#define IAfmly(x)	ntohs((x).sin_family)
#define IPfmly(x)	ntohs((x)->sin_family)
/*
* And here are macros to store a value into the sockaddr_in fields.
# Note that we convert from
## Some more comment lines seem to be missing here
*/
#define setIAhost(x,v)	((x).sin_addr.s_addr) = htonl(v)
#define setIPhost(x,v)	((x)->sin_addr.s_addr)= htonl(v)
#define setIAport(x,v)	((x).sin_port) = htonl(v)
#define setIPport(x,v)	((x)->sin_port)= htonl(v)
#define setIAfmly(x,v)	(x).sin_family = htons(v)
#define setIPfmly(x,v)	(x)->sin_family= htons(v)

/*
* Assorted global variables:
*/
extern	int  one;			/* Should always contain a 1 */
extern	char m_access[];	/* Generic file-access message */
extern	char m_Called[];	/* Function-entry message "Called." */
extern	char m_empty[];		/* Message for invalid nulls */
extern	char m_fctbad[];	/* Debug function-stack failure message */
extern	char m_malloc[];	/* Failed to malloc */
extern	char m_nomem[];		/* Out-of-memory message */
extern	char m_nothere[];	/* Not implemented here */
extern	char m_null[];		/* Should always be "[null]" */
extern	char m_unknown[];	/* Should always be "[unknown]" */
extern	char m_unnamed[];	/* Should always be "[unnamed]" */
extern	int  mypid;			/* This process's pid */
extern	char null[];		/* Should always be a null string */
extern	char unknown[];		/* Should always be "unknown" */
extern	int  zero;			/* Should always contain a 0 */
#define NulB(p)	((p)?(BP)(p):(BP)null)
#define NulC(p)	((p)?(CP)(p):(CP)null)
#define N(p)	((p)?(CP)(p):(CP)null)
#define BP0	((BP)(0))
#define CP0	((CP)(0))

/*
* Here's a message and a check macro to detect null pointers:
*/
#define ChkNull(p,descr) if(!p){V2 m_nullptr,descr D;Fail;}
extern	char* m_nullptr;   /* Message for invalid null pointers [works on SunOS] */
extern	char  m_badnull[]; /* Message for invalid null pointers [doesn't work on SunOS] */

/*
* Here is a routine to return the name of the function n levels higher in the
* stack.  Note that Vcaller(0) is our own name; Vcaller(1) is the routine
* that called you, and so on.  We also define some shorthand names for  these
* two.
*/

extern	char*  Vcaller();		/* Names of calling functions */
#define Caller	Vcaller(1)
#define MyName	Vcaller(0)

/*
* Assorted global functions:
*/
extern	char* decaddr();	/* Convert n bytes to dotted-decimal notation */
extern	int   dsp();		/* Convert char to printable char */
extern	char* dspa();	/* Displayable version of a string (ASCII) */
extern	char* dsps();	/* Displayable version of a string (ASCII or hex) */
extern	char* dspx();	/* Displayable version of a string (hex) */
extern	char* encodei();	/* Encode an int in ASCII */
extern	char* hexaddr();	/* Convert n bytes to hex-colon notation */
extern	char* inet_ntoa();	/* Convert (U32 ) IP address to dot notation */
extern	char* ipdot();		/* Convert (U32*) IP address to dot notation */
extern	char* symaddr();		/* Convert n bytes to symbolic notation */
extern	char* symsockaddr();	/* Convert a sockaddr to a printable string */
extern	U32   binsockaddr();	/* Convert cscii string to sockaddr */

/*
* Here are three names by which you can call the initialization routine:
#define VBSinit(ac,av)	Vinit((int)(ac),(CP*)(av))
*/
#define A_init(ac,av)	Vinit((int)(ac),(CP*)(av))
#define D_init(ac,av)	Vinit((int)(ac),(CP*)(av))
#define V_init(ac,av)	Vinit((int)(ac),(CP*)(av))

/*
* To alleviate the insanity of ANSI C type checking, we define some test
* macros that force signed and unsigned comparisons, plus two shifts and
* two "val" macros that just return numeric values:
*/
#define Eq(x,y)	((long)(x)==(long)(y))
#define Ge(x,y)	((long)(x)>=(long)(y))
#define Gt(x,y)	((long)(x)> (long)(y))
#define Le(x,y)	((long)(x)<=(long)(y))
#define Ls(x,y)	((long)(x)<<(long)(y))
#define Lt(x,y)	((long)(x)< (long)(y))
#define Ne(x,y)	((long)(x)!=(long)(y))
#define Rs(x,y)	((long)(x)>>(long)(y))

#define Sval(x)	((long)(x))
#define Uval(x)	((unsigned long)(x))

#define Seq(x,y)	(Sval(x)==Sval(y))
#define Sge(x,y)	(Sval(x)>=Sval(y))
#define Sgt(x,y)	(Sval(x)> Sval(y))
#define Sle(x,y)	(Sval(x)<=Sval(y))
#define Slt(x,y)	(Sval(x)< Sval(y))
#define Sne(x,y)	(Sval(x)!=Sval(y))
#define Ueq(x,y)	(Uval(x)==Uval(y))
#define Uge(x,y)	(Uval(x)>=Uval(y))
#define Ugt(x,y)	(Uval(x)> Uval(y))
#define Ule(x,y)	(Uval(x)<=Uval(y))
#define Ult(x,y)	(Uval(x)< Uval(y))
#define Une(x,y)	(Uval(x)!=Uval(y))

/*
* Here are some "Much" comparison macros; you may want to change
* the shift for different applications.
*/
#define SMgt(x,y)	((Sval(x)>>2)>Sval(y))	/* Much greater than */
#define SMlt(x,y)	((Sval(y)>>2)<Sval(x))	/* Much less than */
#define UMgt(x,y)	((Uval(x)>>2)>Uval(y))	/* Much greater than */
#define UMlt(x,y)	((Uval(y)>>2)<Uval(x))	/* Much less than */

/*
* Here are some pseudo-types that specify the size and signedness of things:
*/
#ifndef I8
#define I8	char
#endif
#ifndef U8
#define U8	unsigned char
#endif
#ifndef I16
#define I16	short
#endif
#ifndef U16
#define U16	unsigned short
#endif
#ifndef I32
#define I32	long
#endif
#ifndef U32
#define U32	unsigned long
#endif

/*
* Some functions for testing pointers and extracting values:
*/
#define II16(p) ((p)?(*((I16*)(p))):-1)
#define II32(p) ((p)?(*((I32*)(p))):-1)
#define IU16(p) ((p)?(*((U16*)(p))):-1)
#define IU32(p) ((p)?(*((U32*)(p))):-1)

/*
* Macro to calculate the difference (in bytes) between two pointers:
*/
#define Pdiff(p,q) (((Ulong)(p))-((Ulong)(q)))

/*
* Here are the extern declarations for the  debug  wrapper  functions  defined
* below.  The int functions could be omitted, but it's nice to document things
* even if they are the default, so the compiler can cross-check things.
*/
#ifdef USE_PROTO
extern	int    d_alarm();
extern	int    d_bcmp();
extern	void   d_bcopy();
extern	byte*  d_bshift();
extern	byte*  bshift();
extern	void   d_bzero();
extern	int    d_close();
extern	int    d_fclose();
extern	char*  d_fgets();
extern	char*  d_findenv();
extern	FILE*  d_fopen();
extern	int    d_fork();
extern	void*  d_free(void*,char*);
extern	char*  d_getenv();
extern	int    d_putenv();
extern	HOST*  d_gethstbyadr();
extern	HOST*  d_ghba();
extern	HOST*  d_ghbn();
extern	char*  d_index();
extern	void*  d_malloc();
extern	int    d_mknod();
extern	int    d_open();
extern	int    d_read();
extern	void*  d_realloc();
extern	U32    d_seek();
extern	int    d_select();
extern	int    d_setsockopt();
extern	int    d_getsockopt();
extern	int    d_socket();
extern	char*  d_strdup();
extern	time_t d_time();
extern	int    d_timediff();
extern	int    d_write();
extern	char*  dgbtime();
extern	char*  dgbtimstr();
extern	int    gethostname();
extern	char*  lastfld();	/* Last field of a string */
#else	/*USE_PROTO*/
extern	int    d_alarm();
extern	int    d_bcmp();
extern	void   d_bcopy();
extern	byte*  d_bshift();
extern	byte*  bshift();
extern	int    d_close();
extern	int    d_fclose();
extern	char*  d_fgets();
extern	char*  d_findenv();
extern	FILE*  d_fopen();
extern	int    d_fork();
extern	void*  d_free();
extern	char*  d_getenv();
extern	int    d_putenv();
extern	HOST*  d_gethstbyadr();
extern	HOST*  d_ghba();
extern	HOST*  d_ghbn();
extern	char*  d_index();
extern	void*  d_malloc();
extern	int    d_mknod();
extern	int    d_open();
extern	int    d_read();
extern	void*  d_realloc();
extern	U32    d_seek();
extern	int    d_select();
extern	int    d_setsockopt();
extern	int    d_getsockopt();
extern	int    d_socket();
extern	char*  d_strdup();
extern	time_t d_time(time_t*);
extern	int    d_timediff(TIMV*,TIMV*,TIMV*);
extern	int    d_write();
extern	char*  dgbtime();
extern	char*  dgbtimstr();
extern	int    gethostname();
extern	char*  lastfld();	/* Last field of a string */
extern  Str*   fmtStr(Str *sp, char *fmt, ...);
#endif	/*USE_PROTO*/

/*
* Some systems (e.g., AIX) define these as macros; we undef them so that we
* can re-define them to point to our debug macros:
#ifdef BZero
#undef BZero
#endif
#ifdef BCopy
#undef BCopy
#endif
#ifdef BCmp
#undef BCmp
#endif
#ifdef FRee
#undef FRee
#endif
*/

/*
* Here are a set of macros that enforce type-checking on parameters. This is a
* useful technique to ensure that you have the right number of parameters, and
* that they are all (convertible to) the right type.  It's too bad that the  C
* language doesn't have this builtin; it can save a lot of debugging time.
*
* Note  that  some of the macros have a second version with a final 'M' on the
* name.  This means that the debug version will take an extra arg  that  is  a
* string  to  be  included  in error messages.  The library routines generally
* ignore this arg, of course.
*/
#define Acopy(p,n)	acopy((CP)(p),(Sizt)(n),CP0)
#define AcopyM(p,n,m)	acopy((CP)(p),(Sizt)(n),(CP)(m))
#define BCopy(s,d,n)	bcopy((VP)(s),(VP)(d),(Sizt)(n))
#define Bshift(p,len,off)	d_bshift((CP)(p),(Sizt)(len),(Sizt)(off))
#define BCmp(s1,s2,n)	d_bcmp((CP)(s1),(CP)(s2),(Sizt)(n))
#define BEq(s1,s2,n)	(!d_bcmp((CP)(s1),(CP)(s2),(Sizt)(n)))
#define Backup(f)	backup((CP)(f))
#define BinSockAddr(cp,ip)	binsockaddr((CP)(cp),(SKin*)ip)
#define Bpopt(f)	bpopt((CP)(f))
#define bpoption(f)	bpopt((CP)(f))
#define Bsearch(k,b,n,x,c)	bsearch((CP)(k),(CP)(b),(Sizt)(n),(Sizt)(x),(int)(c))
#define BZero(d,n)	bzero((CP)(d),(Sizt)(n))
#define DecAddr(p,n)	decaddr((BP)(p),(Sizt)(n))
#define Dspa(p,n)	dspa((BP)(p),(int)(n))
#define Dspp(p)	dsps((BP)(p),(-1))
#define Dsps(p,n)	dsps((BP)(p),(int)(n))
#define DspSS(p)	dsps((BP)(p),MinSS((p)))
#define Dspx(p,n)	dspx((BP)(p),(int)(n))
#define Dsp(c)	dsp((char)(c))
#define FileName(f)	Vfilnam((int)(f),(FILE*)(0))
#define FfileName(f)	Vfilnam(-1,(FILE*)(f))
#define TimeDiff(td,t1,t2)	d_timediff((TIMV*)(td),(TIMV*)(t1),(TIMV*)(t2))
#define TimeSpecDiff(td,t1,t2)	d_timespecdiff((struct timespec*)(td),(struct timespec*)(t1),(struct timespec*)(t2))
#define Ifclose(f)	if(f){d_fclose((FILE*)(f));f=0;}
#define Ifree(p)	((p)?d_free((void*)(p),(char*)(0)):0)
#define IfreeM(p,m)	((p)?d_free((void*)(p),(char*)(m)):0)
#define IPdot(p)	ipdot((BP)(p))
#ifndef ISupper
#define ISupper(x) (('A'<=(x))&&((x)<='Z'))
#endif
#define HexAddr(p,n)	hexaddr((BP)(p),(int)(n))
#define Index(s,c)	d_index((CP)(s),(char)(c))
#define SigTest	{V5("Send CONT to mypid=%d ...",mypid);Kill(mypid,SIGCONT);}
#define Labs(lnum)	abs(lnum)
#define LastFld(c,s)	lastfld((char)(c),(CP)(s))
#define Lastfld(c,s)	lastfld((char)(c),(CP)(s))
#define Makeraw(f,n,i,o,c,l) makeraw((int)(f),(CP)(n),(int)(i),(int)(o),(int)(c),(int)(l))
#define MakeRaw(f,n) makeraw((int)(f),(CP)(n),0,0,0,0)
#define Makesane(f,n,i,o,c,l) makesane((int)(f),(CP)(n),(int)(i),(int)(o),(int)(c),(int)(l))
#define MakeSane(f,n) makesane((int)(f),(CP)(n),0,0,0,0)
#define Now()	d_time((time_t*)(0))
#define Qsort(b,n,w,c)	qsort((char*)(b),(Sizt)(n),(Sizt)(w),(int(*)())(c))
#define Rand(n)	(minrand(n) % n)
#define Sort(b,n,w,c)	qsort((CP)(b),(Sizt)(n),(Sizt)(w),(int)(c))
#define Sprintf	(void)sprintf
#ifndef Strcat
#define Strcat(s,c)	strcat((CP)(s),(const CP)(c))
#endif
#ifndef Strchr
#define Strchr(s,c)	strchr((CP)(s),(int)(c))
#endif
#ifndef Strrchr
#define Strrchr(s,c)	strrchr((CP)(s),(int)(c))
#endif
#ifndef Strdup
#define Strdup(s)	d_strdup((CP)(s),CP0)
#endif
#ifndef StrDup
#define StrDup(s)	d_strdup((CP)(s),CP0)
#endif
#ifndef StrDupM
#define StrDupM(s,m)	d_strdup((CP)(s),(CP)(m))
#endif
#ifndef StrdupM
#define StrdupM(s,m)	d_strdup((CP)(s),(CP)(m))
#endif
#define Streq(p,q)	(!strcmp((CP)(p),(CP)(q)))
#define Streqic(p,q)	(!strcasecmp((CP)(p),(CP)(q)))
#define Streqn(p,q,n)	(!strncmp((CP)(p),(CP)(q),(Sizt)(n)))
#define Strinit(p,q)	(!strncmp((CP)(p),(CP)(q),Strlen(q)))
#define Strtok(p,q,x)	d_strtok((CP)(p),(CP)(q),(CP)(x))
#define Strlen(p)	strlen((CCP)(p))
#define Strnlen(p,n)	strnlen((CP)(p),(Sizt)(n))
#define Strcmp(d,s)	strcmp((CP)(d),(CP)(s))
#define Strncmp(d,s,n)	strncmp((CP)(d),(CP)(s),(Sizt)(n))
#define Strncpy(d,s,n)	strncpy((CP)(d),(CP)(s),(Sizt)(n))
#define Strnpad(p,l,n,x)	d_strnpad((CP)(p),(int)(l),(int)(n),(char)(x))
#define StrnPad(p,l,n,x)	d_strnpad((CP)(p),(int)(l),(int)(n),(char)(x))
#define Strntrim(p,n)	str_ntrim((CP)(p),(int)(n))
#define StrnTrim(p,n)	str_ntrim((CP)(p),(int)(n))
#define Strtrim(p)	strtrim((CP)(p))
#define StrTrim(p)	strtrim((CP)(p))
#define Strcpy(d,s)	strcpy((CP)(d),(CP)(s))
#define SymAddr(p,n)	symaddr((CP)(p),(int)(n))
#define Symlink(f,g)	symlink((CP)(f),(CP)(g))
#define SymSockAddr(ap)	symsockaddr((SKAD*)ap)
#define System(c)	d_system((CP)(c),(CP)(0))
#define SystemM(c,m)	d_system((CP)(c),(CP)(m))
#define SystemM(c,m)	d_system((CP)(c),(CP)(m))
#define Tell(f)	d_tell((int)(f))
#define UnixTime(t)	d_time((time_t*)(t))
#define Uname(u)	d_uname((struct utsname*)(u))
#define Within(lo,x,hi) (((lo)<=(x))&&((x)<=(hi)))

/*
* We've had grief from passing non-int values to a switch:
*/
#define Switch(x)	switch((int)(x))

#ifndef Sscanf
#define Sscanf (int)scanf
#endif

#define D_init(ac,av) Vinit((int)(ac),(CP*)(av))
#define V_init(ac,av) Vinit((int)(ac),(CP*)(av))

#endif
