#ifndef str_h
#define str_h
/*
* This contains definitions for John Chambers' string and block packages. This
* has  been  developed in a number of projects, as features are needed.  Also,
* due to the demands of various project managers, there is redundancy  in  how
* things are named here.
*
* You might note that there is a clone of this package around called "blk"
* which differs from "str" only in that the v field is an unsigned char *.
*/
#ifndef   sys_types_h
#include "sys_types.h"
#endif
#if !defined(Sizt)	/* Used for sizes of arrays */
#define Sizt size_t
#endif
#ifndef byte
#define byte unsigned char
#endif
/*
* You wouldn't believe how much disk space these can save:
*/
#ifndef BP
#define BP unsigned char*
#endif
#if !defined(CP) && !defined(NULLCP)	/* Isode typedefs char* and #defines NULLCP */
#define CP char*
#endif
/*
* Here is the string structure.  For  unallocated  (e.g.,  static)  data,  you
* should  set m to 0.  If m > 0, it will be a signal to cssorted routines that
* the v should be freed when we are done with it; m==0 means that  the  string
* hasn't been allocated.  Note the following rules:
*   if (m >  0) then (l <= m)
*   if (v == 0) then the string is null; both l and m should be zero.
* Any violations of these should be flagged as an error; see ChkStr(s,m) for a
* convenient way to do error checking..
*
* On  some  systems, or with some applications, the l and m field need only be
* 16 bits; others need 32 bits.  We also define  some  aliases,  because  some
* projects have insisted on longer names than "Str".
#define String struct _string_
*/
#define Strng  struct _string_
#define Str    struct _string_
Str {
	char*  v;	/* The string itself */
	Sizt   l;	/* Actual length of string */
	Sizt   m;	/* Number of bytes malloc'd for the string */
	char*  p;	/* Some applications need an internal pointer */
};

/*
* The MEMUNIT function rounds up a byte count to the chunk size  used  by  the
* d_malloc routine. It should be defined in local.h; if it isn't, we define it
* here in a way that is safe everywhere, although  somewhat  inefficient.   By
* replacing  this  definition  with  an  accurate one, we will be able to make
* better use of allocated space.  Note that it doesn't hurt if MEMUNIT gives a
* value  that  is  too  small,  but a too-big value will be a fatal error when
* something believes it and tries to write beyond the end of the chunk.   Here
* we assume that all systems have at least an 8-byte chunk size.
*/
#ifndef MEMUNIT			/* Round n up to size of malloc's chunk */
#define MEMUNIT(n) (n)	/* Minimum function that works everywhere */
/*efine MEMUNIT(n) ((((n)+7)>>3)<<3) -- Shift definition for 8-byte chunks */
/*efine MEMUNIT(n) ((((n)+7)/8)*8)   -- Div/mul definition for 8-byte chunks */
#endif

/*
* Extra bytes malloced, at least 1 for null terminator.  You might want to add
* more  if  you are having problems with something writing beyond the end of a
* string, and add to the StrChk routine to holler if there are non-null  chars
* in the padding.
*/
#define StrPadLen 1

/*
* Here are the global functions, and some type-enforcing wrappers.  Note  that
* the  "internal"  names  are somewhat bizarre; this was done intentionally to
* minimize the chance of duplicating others' library routines. There have been
* many implementations of packages like this one.
global Str *minStrM(Str*sp,int n,char*dsc);
*/
extern Str  NullStr;		/* Should always be null Str structure */
extern Str* str_appscm();	/* Append a char* to a Str */
extern int  str_chksm();	/* Check Str for validity */
extern int  str_cmpssm();	/* Compare two Str values */
extern Str* str_dupssm();	/* Duplicate a Str */
extern Str* str_dupscm();	/* Duplicate a char* to a Str */
extern Str* str_minstr();	/* Make sure a Str has a min allocated size */
extern Str* str_zapsm();	/* Wipe out the value of a Str */

/*
* Here are some more mnemonic macros for  invoking  the  above  functions  in
* various ways.  Note that the order is the same as in C assignment commands;
* the destination comes first, and the source (if any) second. Note also that
* the  functions  that  return  values  will  return  the  first arg if it is
* nonnull, or will allocate a new Str if none is passed in.
*/
#define AppStr(d,s,l)    (Str*)str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))
#define AppStrF(d,s,l)    if (!str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))) Fail
#define AppStrM(d,s,l,m) (Str*)str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define AppStrMF(d,s,l,m) if (!str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))) Fail
#define CatStr(d,s,t)    (Str*)str_cats2m((Str*)(d),(Str*)(s),(Str*)(t),(char*)(0))
#define CatStrM(d,s,t,m) (Str*)str_cats2m((Str*)(d),(Str*)(s),(Str*)(t),(char*)(m))
#define ChkStr(p)         (int)str_chksm((Str*)(p),(char*)(0))
#define ChkStrM(p,m)      (int)str_chksm((Str*)(p),(char*)(m))
#define  EqStr(d,s)     (int)(!str_cmpssm((Str*)(d),(Str*)(s),(char*)(0)))
#define  NeStr(d,s)     (int)(str_cmpssm((Str*)(d),(Str*)(s),(char*)(0)))
#define CmpStr(d,s)       (int)str_cmpssm((Str*)(d),(Str*)(s),(char*)(0))
#define CmpStrM(d,s,m)    (int)str_cmpssm((Str*)(d),(Str*)(s),(char*)(m))
#define CpyStr(d,s)      (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(0))
#define CpyStrM(d,s,m)   (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(m))
#define DupStr(d,s)      (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(0))
#define DupStrM(d,s,m)   (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(m))
#define FreeStr(s)       (Str*)str_zapsm((Str*)(s),(char*)0)
#define FreeStrM(s,m)    (Str*)str_zapsm((Str*)(s),(char*)(m))
#define GetStr(s,n)      (Str*)str_dupscm((Str*)(s),(char*)0,(int)(n),(char*)(0))
#define GetStrM(s,n,m)   (Str*)str_dupscm((Str*)(s),(char*)0,(int)(n),(char*)(m))
#define MakStr(d,s,l)    (Str*)str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))
#define MakStrM(d,s,l,m) (Str*)str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define MinStr(s,n)      (Str*)str_minstr((Str*)(s),(int)(n),(char*)(0))
#define MinStrM(s,n,m)   (Str*)str_minstr((Str*)(s),(int)(n),(char*)(m))
//#define MinStrM(s,n,d)   ((((s)->m)<=(n))?minStrM((s),(int)(n),(char*)(d)):(s))
#define ZapStr(s)        (Str*)str_zapsm((Str*)(s),(char*)0)
#define ZapStrM(s,m)     (Str*)str_zapsm((Str*)(s),(char*)(m))

/*
* Here are some more mnemonic macros for invoking the above  functions
* in various ways.  Note that the order is the same as in C assignment
* commands; the destination  comes  first,  and  the  source  (if any)
* second.  Note also that the functions that return values will return
* the first arg ifit is nonnull, or will allocate a new Str ifnone  is
* passed in.
*/
#define AppStrF(d,s,l)    if (!str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))) Fail
#define AppStrMF(d,s,l,m) if (!str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))) Fail
#define CatStrF(d,s,t)    if (!str_cats2m((Str*)(d),(Str*)(s),(Str*)(t),(char*)(0))) Fail
#define CatStrMF(d,s,t,m) if (!str_cats2m((Str*)(d),(Str*)(s),(Str*)(t),(char*)(m))) Fail
#define ChkStrF(p)         if (str_chksm((p),(char*)(0))) Fail
#define ChkStrMF(p,m)      if (str_chksm((p),(char*)(m))) Fail
#define CmpStrF(d,s)       if (str_cmpssm((d),(Str*)(s),(char*)(0))) Fail
#define CmpStrMF(d,s,m)    if (str_cmpssm((d),(Str*)(s),(char*)(m))) Fail
#define CpyStrF(d,s)      if (!str_dupssm((Str*)(d),(Str*)(s),(char*)(0))) Fail
#define CpyStrMF(d,s,m)   if (!str_dupssm((Str*)(d),(Str*)(s),(char*)(m))) Fail
#define DupStrF(d,s)      if (!str_dupssm((Str*)(d),(Str*)(s),(char*)(0))) Fail
#define DupStrMF(d,s,m)   if (!str_dupssm((Str*)(d),(Str*)(s),(char*)(m))) Fail
#define FreeStrF(s)       if (!str_zapsm((Str*)(s),(char*)0)) Fail
#define FreeStrMF(s,m)    if (!str_zapsm((Str*)(s),(char*)(m))) Fail
#define GetStrF(s,n)      if (!str_dupscm((Str*)(s),(char*)0,(int)(n),(char*)(0))) Fail
#define GetStrMF(s,n,m)   if (!str_dupscm((Str*)(s),(char*)0,(int)(n),(char*)(m))) Fail
#define MakStrF(d,s,l)    if (!str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))) Fail
#define MakStrMF(d,s,l,m) if (!str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))) Fail
#define MinStrF(s,n)      if (!str_minstr((Str*)(s),(int)(n),(char*)(0))) Fail
#define MinStrMF(s,n,m)   if (!str_minstr((Str*)(s),(int)(n),(char*)(m))) Fail
#define ZapStrF(s)        if (!str_zapsm((Str*)(s),(char*)0)) Fail
#define ZapStrMF(s,m)     if (!str_zapsm((Str*)(s),(char*)(m))) Fail

/*
* Here are macros for  stuffing  block  and  string  descriptors  with
* zeroes  or  values.   This  is  needed  for local strings, because C
* refuses to initialize local structs.  Be careful using these  macros
* for  other  purposes, due to the risk of memory leaks.  It's hard to
* say whether ZeroBlk or InitBlk is more efficient.   Note  the  funny
* names  used  for the fields in the Stuff macros, to prevent cpp from
* expanding the field names.  Note also that the Init and Zero  macros
* take structs, while the Stuff macros take pointers.
*/
#define InitBlk(b) BZero(&(b),sizeof(Blk))
#define InitStr(s) BZero(&(s),sizeof(Str))
#define ZeroBlk(s) {s.v=s.p=0; s.l=s.m=0;}
#define ZeroStr(s) {s.v=s.p=0; s.l=s.m=0;}
#define StuffBlk(b,a,i,j) \
	(((b)->v=(b)->p=(byte*)(a)),((b)->l=(Sizt)(i)),((b)->m=(Sizt)(j)))
#define StuffStr(s,a,i,j) \
	(((s)->v=(s)->p=(char*)(a)),((s)->l=(Sizt)(i)),((s)->m=(Sizt)(j)))
#define StuffBP(b,a,i,j) \
	(((b)->v=(b)->p=(byte*)(a)),((b)->l=(Sizt)(i)),((b)->m=(Sizt)(j)))
#define StuffSP(s,a,i,j) \
	(((s)->v=(s)->p=(char*)(a)),((s)->l=(Sizt)(i)),((s)->m=(Sizt)(j)))
#define StuffBV(b,a,i,j) \
	(((b).v=(b).p=(byte*)(a)),((b).l=(Sizt)(i)),((b).m=(Sizt)(j)))
#define StuffSV(s,a,i,j) \
	(((s).v=(s).p=(char*)(a)),((s).l=(Sizt)(i)),((s).m=(Sizt)(j)))

/*
* Here are macros that copy a Str.  Four of them so that  we  can  use
* either vals or ptrs:
*/
#define RepSPP(d,s) {(d)->v=(s)->v;(d)->l=(s)->l;(d)->m=(s)->m;(d)->p=(s)->p;}
#define RepSPV(d,s) {(d)->v=(s).v;(d)->l=(s).l;(d)->m=(s).m;(d)->p=(s).p;}
#define RepSVV(d,s) {(d).v=(s).v;(d).l=(s).l;(d).m=(s).m;(d).p=(s).p;}
#define RepSVP(d,s) {(d).v=(s)->v;(d).l=(s)->l;(d).m=(s)->m;(d).p=(s)->p;}

/*
* Here are some older names that are now obsolete, but which were used
* in the code for some projects:
*/
#define AppStrng(d,s,l,m) (Str*)str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define ChkStrng(p,m)      (int)str_chksm((Str*)(p),(char*)(m))
#define CpyStrng(d,s,m)   (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(m))
#define DupStrng(d,s)     (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(0))
#define DupStrngM(d,s,m)  (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(m))
#define FreeStrng(s)      (Str*)str_zapsm((Str*)(s),(char*)0)
#define FreeStrngM(s,m)   (Str*)str_zapsm((Str*)(s),(char*)(m))
#define GetStrng(s,n,m)   (Str*)str_dupscm((Str*)(s),(char*)0,(int)(n),(char*)(m))
#define MakStrng(d,s,l,m) (Str*)str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define ZapStrng(s)       (Str*)str_zapsm((Str*)(s),(char*)0)
#define ZapStrngM(s,m)    (Str*)str_zapsm((Str*)(s),(char*)(m))

/*
* Here are some proposed macros with orthogonal names.  The first word
* says what operation is to be done. After this, the following letters
* are used:
*   S  means (Str*)
*   s  means (char*), plus a length that may be -1.
*   M  means a final message string.
* Due to some linkers' dislike for upper-lower distinctions,  we  have
* named  the  actual  C  routines  somewhat  differently, with 's' for
* (Str*) and 'c' for (char*).  I hope  this  doesn't  cause  too  much
* confusion.
*/
#define AppSS(d,s)        (Str*)str_appssm((Str*)(d),(Str*)(s),(char*)(0))
#define AppSSM(d,s,m)     (Str*)str_appssm((Str*)(d),(Str*)(s),(char*)(m))
#define AppSs(d,s,l)      (Str*)str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))
#define AppSsM(d,s,l,m)   (Str*)str_appscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define ChkS(s)           (int)str_chksm((Str*)(s),(char*)(0))
#define ChkSM(s,m)        (int)str_chksm((Str*)(s),(char*)(m))
#define DupSS(d,s)        (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(0))
#define DupSSM(d,s,m)     (Str*)str_dupssm((Str*)(d),(Str*)(s),(char*)(m))
#define DupSs(d,s,l)      (Str*)str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(0))
#define DupSsM(d,s,l,m)   (Str*)str_dupscm((Str*)(d),(char*)(s),(int)(l),(char*)(m))
#define LRTrimStr(p,s)    (Str*)str_lrtrimsp((Str*)(p),(char*)(s),(char*)(0))
#define LRTrimStrM(p,s,m) (Str*)str_lrtrimsp((Str*)(p),(char*)(s),(char*)(m))
#define RTrimStr(p,s)     (Str*)str_rtrimsp((Str*)(p),(char*)(s),(char*)(0))
#define RTrimStrM(p,s,m)  (Str*)str_rtrimsp((Str*)(p),(char*)(s),(char*)(m))
#define LTrimStr(p,s)     (Str*)str_ltrimsp((Str*)(p),(char*)(s),(char*)(0))
#define LTrimStrM(p,s,m)  (Str*)str_ltrimsp((Str*)(p),(char*)(s),(char*)(m))

extern Str * str_lrtrimsp();
extern Str * str_rtrimsp();
extern Str * str_ltrimsp();

/*
* Here are a few macros that return a value if it is nonnull, and
* return some useful value for nulls.
*/
#define NulS(s)    (Str*)str_zapsm((Str*)(s),(char*)(0))
#define NulSM(s,m) (Str*)str_zapsm((Str*)(s),(char*)(m))
#define NulV(p)    ((p).v?(p).v:(char*)null)
#define NulP(p)    ((p)&&(p)->v?(p)->v:(char*)null)

/*
* Return a Str's value if it exists and is nonnull, otherwise return null
*/
#define SV(p) ((p).l?(p).v:null)
#define SP(p) ((p)?((p)->l?(p)->v:null):null)

/*
* Two macros for generating a plain, unquoted, printable char* from a Str:
* (Long and short versions for different projects).
*/
#define DspSP(s) ((s)?Dspa((s)->v,(s)->l):m_null)
#define DspSV(s)      Dspa((s).v,(s).l)
#define DSP(s)   ((s)?Dspa((s)->v,(s)->l):m_null)
#define DSV(s)        Dspa((s).v,(s).l)

/*
* Two macros for generating a quoted, printable char* from a Str:
* (Long and short versions for different projects).
*/
#define QuotSP(s) ((s)?Dsps((s)->v,(s)->l):m_null)
#define QuotSV(s)      Dsps((s).v,(s).l)
#define QSP(s)    ((s)?Dsps((s)->v,(s)->l):m_null)
#define QSV(s)         Dsps((s).v,(s).l)

/*
* And, finally, some error messages:
*/
extern char str_badstmsg[];
extern char str_needmsg[];

#ifndef Blk
/*
* Here is the block structure, which differs from the string structure
* only in that the value is an unsigned char* rather than signed.  Use
* the extra fields if you  need  them,  but  the  blk  package  itself
* doesn't use them.  On some systems, or with some applications, the l
* and m field need only be 16 bits; others  need  32  bits.   We  also
* define some aliases.
*/
#define Block struct _block_
#define Blck  struct _block_
#define Blk   struct _block_
Blk {
	byte* v;	/* The block itself */
	Sizt  l;	/* Actual length of block */
	Sizt  m;	/* Number of bytes malloc'd for the block */
	byte* p;	/* Some applications need an internal pointer */
};
#endif

/*
* Here are the global functions,  and  some  type-enforcing  wrappers.
* Note  that  the "internal" names are somewhat bizarre; this was done
* intentionally to minimize the chance of duplicating others'  library
* routines. There have been many implementations of packages like this
* one.
*/
extern Blk NullBlk;		/* Should always be null Blk structure */
extern Str* fmtStr(Str *sp, char *fmt, ...);

#define AppBlk(d,s,l)    (Blk*)str_appscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(0))
#define AppBlkM(d,s,l,m) (Blk*)str_appscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define CatBlk(d,s,t)    (Blk*)str_cats2m((Blk*)(d),(Blk*)(s),(Blk*)(t),(char*)(0))
#define CatBlkM(d,s,t,m) (Blk*)str_cats2m((Blk*)(d),(Blk*)(s),(Blk*)(t),(char*)(m))
#define ChkBlk(p)         (int)str_chksm((Blk*)(p),(char*)(0))
#define ChkBlkM(p,m)      (int)str_chksm((Blk*)(p),(char*)(m))
#define CmpBlk(d,s)       (int)str_cmpssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define CmpBlkM(d,s,m)    (int)str_cmpssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define CpyBlk(d,s)      (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define CpyBlkM(d,s,m)   (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define DupBlk(d,s)      (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define DupBlkM(d,s,m)   (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define FreeBlk(s)       (Blk*)str_zapsm((Blk*)(s),(byte*)0)
#define FreeBlkM(s,m)    (Blk*)str_zapsm((Blk*)(s),(char*)(m))
#define GetBlk(s,n)      (Blk*)str_dupscm((Blk*)(s),(byte*)0,(int)(n),(char*)(0))
#define GetBlkM(s,n,m)   (Blk*)str_dupscm((Blk*)(s),(byte*)0,(int)(n),(char*)(m))
#define MakBlk(d,s,l)    (Blk*)str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(0))
#define MakBlkM(d,s,l,m) (Blk*)str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define MinBlk(s,n)      (Blk*)str_minstr((Blk*)(s),(int)(n),(char*)(0))
#define MinBlkM(s,n,m)   (Blk*)str_minstr((Blk*)(s),(int)(n),(char*)(m))
#define SetNullStr(s)    ((s)->l=0,*(s)->p=0)		/* Set Str to null */
#define ZapBlk(s)        (Blk*)str_zapsm((Blk*)(s),(byte*)0)
#define ZapBlkM(s,m)     (Blk*)str_zapsm((Blk*)(s),(char*)(m))

#define MakBlkF(d,s,l)    if (!str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(0))) Fail
#define MakBlkMF(d,s,l,m) if (!str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))) Fail
#define MinBlkF(s,n)      if (!str_minstr((Blk*)(s),(int)(n),(char*)(0))) Fail
#define MinBlkMF(s,n,m)   if (!str_minstr((Blk*)(s),(int)(n),(char*)(m))) Fail

#define IMinBlkF(s,n)    if(((s)->l)<(n))if(!str_minstr((Blk*)(s),(int)(n),(char*)(0)))Fail
#define IMinBlkMF(s,n,m) if(((s)->l)<(n))if(!str_minstr((Blk*)(s),(int)(n),(char*)(m)))Fail
#define IMinStrF(s,n)    if(((s)->l)<(n))if(!str_minstr((Blk*)(s),(int)(n),(char*)(0)))Fail
#define IMinStrMF(s,n,m) if(((s)->l)<(n))if(!str_minstr((Blk*)(s),(int)(n),(char*)(m)))Fail

/*
* Here are some older names that are now obsolete, but which were used in the
* code for some projects:
*/
#define AppBlck(d,s,l,m) (Blk*)str_appscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define ChkBlck(p,m)     (Blk*)str_chksm((Blk*)(p),(char*)(m))
#define CpyBlck(d,s,m)    (int)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define DupBlck(d,s)     (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define DupBlckM(d,s,m)  (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define FreeBlck(s)      (Blk*)str_zapsm((Blk*)(s),(byte*)0)
#define FreeBlckM(s,m)   (Blk*)str_zapsm((Blk*)(s),(char*)(m))
#define GetBlck(s,n,m)   (Blk*)str_dupscm((Blk*)(s),(byte*)0,(int)(n),(char*)(m))
#define MakBlck(d,s,l,m) (Blk*)str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define ZapBlck(s)       (Blk*)str_zapsm((Blk*)(s),(byte*)0)
#define ZapBlckM(s,m)    (Blk*)str_zapsm((Blk*)(s),(char*)(m))
/*
* Here are some proposed macros with orthogonal names.  The  first  word  says
* what operation is to be done.  After this, the following letters are used:
*   B  means (Blk*)
*   s  means (char*), plus a length that may be -1.
*   M  means a final message block.
* Due to some linkers' dislike for upper-lower distinctions, we have named the
* actual  C  routines  somewhat differently, with 's' for (Blk*) and 'c' for
* (char*).  I hope this doesn't cause too much confusion.
*
*/
#define AppBB(d,s)      (Blk*)str_appssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define AppBBM(d,s,m)   (Blk*)str_appssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define AppBs(d,s,l)    (Blk*)str_appscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(0))
#define AppBsM(d,s,l,m) (Blk*)str_appscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define ChkB(s)          (int)str_chksm((Blk*)(s),(char*)(0))
#define ChkBM(s,m)       (int)str_chksm((Blk*)(s),(char*)(m))
#define DupBB(d,s)      (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(0))
#define DupBBM(d,s,m)   (Blk*)str_dupssm((Blk*)(d),(Blk*)(s),(char*)(m))
#define DupBs(d,s,l)    (Blk*)str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(0))
#define DupBsM(d,s,l,m) (Blk*)str_dupscm((Blk*)(d),(byte*)(s),(int)(l),(char*)(m))
#define TrimBlk(p,s)    (Blk*)str_trim((Blk*)(p),(byte*)(s),(char*)(0))
#define TrimBlkM(p,s,m) (Blk*)str_trim((Blk*)(p),(byte*)(s),(char*)(m))
/*
* Some useful string- and block-related macros:
*/
#define IsNullStr(x)	(!((x)&&((x)->v)&&((x)->l)))
#define IsNullBlk(x)	(!((x)&&((x)->v)&&((x)->l)))
#define NonNullStr(x)	((x)&&((x)->v)&&((x)->l))
#define NonNullBlk(x)	((x)&&((x)->v)&&((x)->l))
/*
* Here are a few more useful string- and block-related macros:
*/
#define NulBV(bk)	((bk).v?(bk).v:(byte*)null)
#define NulBP(bp)	(((bp)&&(bp).v)?(bp).v:(byte*)null)
#define FldsBV(bk)	(bk).v,(bk).l,(bk).m,(bk).p
#define PrBV(bk)	&(bk),(bk).v,(bk).l,(bk).m,(bk).p
#define FldsBP(bp)	((bp)?(bp)->v:0),((bp)?(bp)->l:0),((bp)?(bp)->m:0),((bp)?(bp)->p:0)
#define PrBP(bp)	((bp)),((bp)?(bp)->v:0),((bp)?(bp)->l:0),((bp)?(bp)->m:0),((bp)?(bp)->p:0)
/*
* And thus endeth the block section of this header file.
*/
#endif
