#ifndef _status_h	/* Status handling. */
#define _status_h __FILE__
/* $Id: status.h,v 1.1 2001-10-17 18:00:20 eddy Exp $ */
/* See status.html for ramblings. */

typedef struct stat_s status, *stat_p;
typedef stat_p (*judge)(stat_p);
/* A judge's happy behaviour is to return the stat_p it was given.

   The archetypical use of a judge is to check the status of a context after it
   has delegated some task.  A routine somewhere in the code: first sets up a
   valid status record; then makes it available to some tool which (tries to) do
   a job for our routine.  If any difficulties arise, the tool frobs information
   accessible from the status record before returning control to the routine.
   If the tool does frob the status record, its caller needs to notice this has
   happened and respond: if not, the tool has `succeeded' and its caller carries
   on with what it was doing.

   The protocol by which the caller and the tool communicate via the status
   record is ultimately down to the caller and the tool.  Typically, there'll be
   a sentinel field of the record which the tool will frob whenever the caller
   needs to notice, and the caller will consult this before doing anything else.
   If this field has been frobbed, the caller diverts from normal proceedings
   to handle the situation: if the caller understands the changes it sees, it
   can do what it will about it, possibly including how to complain about the
   situation to *its* caller; but it may be at a loss - this is where it turns
   to a judge for help.

   Judges have a nice simple protocol: if a judge returns the status record it
   is given, it is happy with the status chain it sees by chasing ->up from the
   record.  Otherwise, it returns some other record, usually taken from that
   chain.
*/

struct stat_s {
  judge how;	/* The nearest thing you'll find to a `type'. */
  status *up;	/* status records are usually on the stack: ->up typically
		   points to a status record one function call up the stack.
		   The ->up-most stack status will point at a static record.
		   The ->up of any static status record is static.

		   Frobbing ->up is the standard means for a tool to tell its
		   caller that something is amiss.

		   I'll refer to the sequence of status records one reaches by
		   chasing ->up from some given status record as the status
		   `chain' of that record. */

  /* ...private; -- others according to the whim of how */
};
#define JUDGE(judge, self) ((self) != (*(judge))(self))
/* Failure of this test usually means you're in trouble. */

extern status *ready(status *);	/* so &ready is a judge */
extern judge catch;
extern status *Pull;	/* point your top auto status's ->up at this ... */

#ifndef NULL
#define NULL 0
#endif
/*
  $Log: status.h,v $
  Revision 1.1  2001-10-17 18:00:20  eddy
  added in all files previously missing from RCS

  Revision 1.12  1998/12/31 13:31:07  eddy
  Declared ready as something for outside judges to call, leaving catch as
  a judge.  Threw in definition of NULL for convenience.

  Revision 1.11  1998/12/29 17:36:29  eddy
  This should suffice.

  Revision 1.10  1998/12/16 01:21:42  eddy
  Exported the easy checker.

  Revision 1.9  1998/12/16 00:20:28  eddy
  Get ready.

  Revision 1.8  1998/12/15 21:58:01  eddy
  Slice zero, one, two out to zot.h

  Revision 1.7  1998/12/15 21:45:31  eddy
  Tuesday dinner-break.  Revolution coming.

  Revision 1.6  1998/12/13 21:43:12  eddy
  Packing up for the night.

  Revision 1.5  1998/12/13 09:46:25  eddy
  Revolution time.

  Revision 1.4  1998/12/11 22:49:04  eddy
  Check-point.

  Revision 1.3  1998/12/11 19:43:58  eddy
  A first protocol.

  Revision 1.2  1998/12/11 19:04:14  eddy
  It Begins.

  Initial Revision 1.1  1998/12/11 18:29:44  eddy
*/
#endif /* _status_h */

