/*******************************************************************************
* YORKTOWN ADVANCED SGML PARSER (YASP)                                         *
*         An SGML Parser conforming to International Standard ISO 8879 --      *
*         Standard Generalized Markup Language                                 *
*------------------------------------------------------------------------------*
* Written 1987 - 1993 by                                                       *
*         Pierre G. Richard                                                    *
*         IBM T.J. Watson Research Center                                      *
*         Yorktown Heights, New York                                           *
*         petrus@watson.ibm.com                                                *
*------------------------------------------------------------------------------*
* FUNCTION NAME    = YASP / Header File                                        *
* STATUS           = Version 0, Release 1, Level 31 and up                     *
* COMPONENT NAME   = stower.h                                                  *
* DESCRIPTIVE NAME = stower COMMON block and functions                         *
* DATE_WR          = 03/06/1988                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
* IMPLEMENTATION NOTES =                                                       *
* CHANGE HISTORY =                                                             *
*******************************************************************************/

typedef enum {               /* Parse mode */
   TAG_PMO,                  /* tag, is also the floor state */
   CHAR_PMO,                 /* character data */
   ICHAR_PMO,                /* invalid character */
   DATATAG_PMO               /* mixed (data and tag) */
}PMO;

typedef struct {
   GA_P   gbla_p;
   PMO    parse_mode;        /* current parse_mode */
   uint   forced_data;       /* suppress recognition of char in unmapped SR */
   int    tcb_stk_ix;        /* current TCB stack level */
   int    tcb_stk_max;       /* highest TCB stack level reached */
   uchar  STACK_BASED *state_p; /* Pointer to the current FlowGraph */
   TCB_P  tcb_p;             /* point current TCB in TCB array */
   ELT   *last_ended_elt_p;
   ETY   *sr_ety_p;          /* shortref in process, mapped to ety_p */
   int    sr_id;             /* shortref identifier of this shortref */
   uchar  state[TAGLVL_MAX]; /* flowgraphs for record boundaries analysis */
   boolean is_shortref_in_process;
   TCB    tcb_stack[TAGLVL_MAX+1];
}COMMON;

/* Common area is on the stack (in the nearby) */
typedef COMMON STACK_BASED * COM_P;

/* extern uchar * P_FCT stw_note    (GA_P);  ** stw_note is a macro **  */
#define stw_note(gbla_p) gbla_p->odbf_pC->c_p

extern ELT *   P_FCT stw_gfgi  (GA_P);
extern void    P_FCT stw_base  (COM_P);
extern boolean P_FCT stw_otcb  (COM_P);
extern boolean P_FCT stw_dtcb  (COM_P);
extern void    P_FCT stw_etcb  (COM_P, uint, uchar, uchar);
extern void    P_FCT stw_xpel  (COM_P, uchar STACK_BASED *);
extern void    P_FCT stw_flsh  (COM_P);
extern void    P_FCT stw_init  (GA_P);
extern void    P_FCT stw_thro  (GA_P);
extern void    P_FCT stw_stRE  (COM_P);
extern void    P_FCT stw_data  (COM_P);

/*-----------------------------------------------------------------------------+
| Record boundaries conditions (7.6.1) are described by a FlowGraph,           |
| which is updated by FG_macros defined here.                                  |
|                                                                              |
| Theoretically each time a new element is started, either proper or included, |
| the element's current state is stacked a a new FlowGraph is started.  This   |
| enforces the rule for each element being treated as an atom.  According      |
| to this, the graph can be reduced to 5 states and 4 events:                  |
|                                                                              |
|   - RS      : Record Start                                                   |
|   - RE      : Record End                                                     |
|   - DATA    : Data or Proper subelement                                      |
|   - OTHER   : Included subelement, Markup Declaration, PI                    |
|                                                                              |
|   Current|   New State = f(Events)   |                                       |
|    State |                           |                                       |
|          |  RS  |  RE  | DATA |OTHER |                                       |
|   -------+------+------+------+------+                                       |
|      0   |  2   |  2   |  1   |  0   |                                       |
|      1   |  2   |  3   |  1   |  1   |                                       |
|      2   |  2   |  3   |  1   |  0   |                                       |
|      3   |  3   | 3+RE | 1+RE |  4   |                                       |
|      4   |  3   |  3   | 1+RE |  4   |                                       |
|                                                                              |
| State 0 and 2 reflect "RE due to markup" conditions.                         |
| State 3 and 4 are "RE pending" conditions: the RE will be generated          |
| or not according to the last RE rule (rule b).                               |
| State 0 and 4 are to discard the RE following an included subelement.        |
| State 0 is also the initial state (graph reduction).                         |
| State 1 is when a DATA or proper subelement is included.                     |
|                                                                              |
| Practically entering a new proper element doesn't require a stack operation: |
| the RE (if any) will be generated before the proper subelement is entered    |
| so the state "popped" when the proper subelement ends is always the same.    |
| So the start and ends of a proper subelement (STG and ETG) can be added to   |
| the list of events.  However, for included subelement, stacking the          |
| element's current state is mandatory.  So the final graph is:                |
|                                                                              |
|   Current|         New State = f(Events)           |                         |
|    State |                                         |                         |
|          |  RS  |  RE  | STG  | ETG  | DATA |OTHER |                         |
|   -------+------+------+------+------+------+------+                         |
|      0   |  2   |  2   |  0   |  1   |  1   |  0   |                         |
|      1   |  2   |  3   |  0   |  1   |  1   |  1   |                         |
|      2   |  2   |  3   |  0   |  1   |  1   |  0   |                         |
|      3   |  3   | 3+RE | 0+RE |  1   | 1+RE |  4   |                         |
|      4   |  3   |  3   | 0+RE |  1   | 1+RE |  4   |                         |
|                                                                              |
+-----------------------------------------------------------------------------*/

#define FG_RS(M_p) (*(M_p->state_p)) = (uchar)((*(M_p->state_p)) < 3 ? 2:3);

#define FG_RE(M_p)\
   if (*M_p->state_p == 3) stw_stRE(M_p); /* must be in PCDATA */\
   else  /* No RE to stw so far */ *M_p->state_p = (uchar)(*M_p->state_p? 3:2)

#define FG_STG(M_p)\
   if (*M_p->state_p > 2) stack_tse(M_p,tshdr_pp,(ELT *)0,RE_LF); /* RE SPTG */\
   *M_p->state_p = 0;

#define FG_ETG(M_p) (*M_p->state_p) = 1;

#define FG_DATA(M_p)\
   if (*M_p->state_p > 2) /* signal_RE */ stw_stRE(M_p);  *M_p->state_p = 1

#define FG_OTHER(state)\
   if (*M_p->state_p & 0x02) *M_p->state_p=(uchar)((*M_p->state_p==2)? 0:4)

#define STG_STATE 0
/******************************************************************************/
