#ifndef _chain_h /* chains of alternates making up a record */
#define _chain_h __FILE__
/* $Id: chain.h,v 1.1 2001/10/17 18:00:19 eddy Exp $ */
#include "tot.h"

/* Links with which to build simple chains: */

/* Simple chains: */
extern be chainbe;
typedef struct golink_s golink;
typedef struct { be how /* e.g. chainbe */; golink *head; } gochain;
typedef record (*linkbe)(status *, golink *);
struct golink_s { linkbe how; golink *next; /* ...; */ };

extern ask chainask;
typedef struct getlink_s getlink;
typedef struct { ask how /* e.g. chainask */; getlink *head; } getchain;
typedef record (*linkask)(status *, getlink *, record);
struct getlink_s { linkask how; getlink *next; /* ...; */ };

extern join chainjoin;
typedef struct bindlink_s bindlink;
typedef struct { join how /* e.g. chainjoin */; bindlink *head; } bindchain;
typedef record (*linkjoin)(status *, bindlink *, record, record);
struct bindlink_s { linkjoin how; bindlink *next; /* ...; */ };

/* Headed chains: */
extern be headbe;
typedef struct getent_s getent;
typedef struct { be how /* e.g. headbe */; getent *head; } gohead;
typedef record (*entask)(status *, getent *, gohead *);
struct getent_s { entask how; getent *next; /* ...; */ };

extern ask headask;	/* might also use how == ask_lookup_chain */
typedef struct bindent_s bindent;
typedef struct { ask how /* e.g. headask */; bindent *head; } askhead;
typedef record (*entjoin)(status *, bindent *, askhead *, record what);
struct bindent_s { entjoin how; bindent *next; /* ...; */ };

/* Chain protocol:

   Links in a chain are attempted in order.  Each is invoked with the same
   arguments as the original chain-head, save that the link is substituted for
   the chain-head and the context (status) is that of the chain rather than its
   caller.  Headed chains take an extra argument - (stat, link, head, ...)
   rather than (stat, link, ...) when invoked as (stat, head, ...), but are
   otherwise handled exactly the same as plain chains.

   If a link frobs the ->up of its status, the chain's context judges the
   resulting status (with ->up restored if the frob pointed it at itself).  If
   this judgement is bad, the chain aborts (and presumes that its judge has
   propagated the frobbing up the stack): otherwise (including when the link
   doesn't frob ->up) the chain continues with its remaining links.  When it
   reaches its end, the chain returns happy.

   To do anything useful, you may want to raise an `error' (in the judge's eyes)
   which means success (in yours) and catch it.

   See also: lookup.[ch] (deprecated) and register.[ch] */

/*
  $Log: chain.h,v $
  Revision 1.1  2001/10/17 18:00:19  eddy
  added in all files previously missing from RCS

  Revision 1.3  1998/12/31 13:29:16  eddy
  Nicer attention to types for headed chains.

  Revision 1.2  1998/12/31 12:39:19  eddy
  Minor mods, made fatuous completion be viewed as success, revised docs.

  Initial Revision 1.1  1998/12/30 18:20:23  eddy
*/
#endif /* _chain_h */

