/*******************************************************************************
* 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 / LTD compiler                                       *
* STATUS           = Version 0, Release 1, Level 34 and up                     *
* COMPONENT NAME   = oltcomp.c                                                 *
* DESCRIPTIVE NAME = Compile the Link Type Declaration (Main)                  *
* DATE_WR          = 09/27/1989                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
*                                                                              *
* IMPLEMENTATION NOTE =                                                        *
*                                                                              *
* DEPENDENCIES =  (see Include list)                                           *
*                                                                              *
* IMPORT=                                                                      *
*                                                                              *
* EXPORT=                                                                      *
*                                                                              *
* CHANGE HISTORY =                                                             *
* Number Date     Inits    Change & Reason (brief)                             *
*******************************************************************************/

/*-------------+
|Include Files |
+-------------*/
#include "machine.h"
#include "portable.h"
#include "yaspapi.h"
#include "global.h"
#include "usrlib.h"
#include "sgml.h"
#include "yasp.h"
#include "olt.h"

/*--------------+
|Local Functions|
+--------------*/
static CHOICES const * _loadds P_FCT adr_ltss_choices(void);
static void     P_FCT olt_process       (COMMON_P);
static void     P_FCT olt_term          (COMMON_P, uchar *);

/*----------------+
|Local Definitions|
+----------------*/

/*STATIC--------------------------------------------------------------olt_term-+
|Stringize and unlod the structure to an utility file                          |
+-----------------------------------------------------------------------------*/
static void P_FCT olt_term(COMMON_P M_p, uchar *LTname_p)
{
   GA_P gbla_p = M_p->gbla_p;

   errorh(gbla_p,NIMPL,ERH_T_SEV+ERH_LOCATE,1008);
}

/*STATIC------------------------------------------------------adr_ltss_choices-+
| Allow temporary access to local constant area (choices)                      |
+-----------------------------------------------------------------------------*/
static CHOICES const * _loadds P_FCT adr_ltss_choices(void)
{
   static CHOICES const ltss_choices[] = {
      { offsetof(GNWDTAB,ATTLIST),  (int)ATTLIST_TK   },
      { offsetof(GNWDTAB,ENTITY),   (int)ENTITY_TK    },
      { offsetof(GNWDTAB,LINK),     (int)LINK_TK      },
      { -1,                         (int)NOT_FOUND_TK }
   };
   return(ltss_choices);
}

/*STATIC-----------------------------------------------------------olt_process-+
|process LTD MDs:                                                              |
|                                                                              |
| [161] link type declaration subset =                                         |
|             link attribute set?, (link set declaration | entity set)*        |
|                                                                              |
| [162] link attribute set =                                                   |
|             (attribute definition list declaration | entity set)*            |
|                                                                              |
| [163] link set declaration =                                                 |
|             mdo, "LINK", ps+, link set name,                                 |
|             ((ps+,source element specification)+ |                           |
|             (ps+,explicit link definition)+)                                 |
|              ps*, mdc                                                        |
|                                                                              |
| [113] entity set = (entity declaration | ds)*                                |
|                                                                              |
+-----------------------------------------------------------------------------*/
static void P_FCT olt_process(COMMON_P M_p)
{
   GA_P gbla_p = M_p->gbla_p;

   psh_mode(gbla_p,DS_MODE);
   for(;;) {
      skip_ds(gbla_p);
      switch(GA(curr_token)) {
      case MDO_TK:
         psh_mode(gbla_p,MD_MODE);
         switch (choos_in(gbla_p,adr_ltss_choices(),(GNWD *)&GA(gnwdtab))) {
         default:
            errorh(gbla_p,INVKWD,ERH_T_SEV+ERH_LOCATE);   /* Invalid */
            break;
         case ENTITY_TK:
            /* ety_deco(M_p); ** uses a COMMON_ODT_AREA !! */
            errorh(gbla_p,NIMPL,ERH_T_SEV+ERH_LOCATE,1005);
            break;
         case ATTLIST_TK:
            /* adl_deco(M_p); ** uses a COMMON_ODT_AREA !! */
            errorh(gbla_p,NIMPL,ERH_T_SEV+ERH_LOCATE,1006);
            break;
         case LINK_TK:
            /* lnk_deco(M_p); ** is not implemented !! */
            errorh(gbla_p,NIMPL,ERH_T_SEV+ERH_LOCATE,1007);
            break;
         }
         if (GA(curr_token) != MDC_TK) {
            errorh(gbla_p,NOMDC,ERH_T_SEV+ERH_LOCATE);
         }
/* must also check that parameter entity reference have been closed */
         pop_mode(gbla_p);
         continue;
      default:
         break;
      }
      break;
   }
   pop_mode(gbla_p);
}

/*--------------------------------------------------------------------olt_main-+
|process a LTD                                                                 |
|Enter here when LINKTYPE has been decoded.                                    |
|Fill the link type name in callers area.                                      |
+-----------------------------------------------------------------------------*/
void P_FCT olt_main(
   GA_P gbla_p,
   uchar *LTname_p)    /* will be updated */
{
   COMMON_OLT_AREA common;
   uchar  srce_DTname[NAMELEN_MAX+1];
   uchar  rslt_DTname[NAMELEN_MAX+1];
   boolean ltd_processed = FALSE;
   boolean external_ltd_found = FALSE;
   int curr_floor_level;
   EXID ltd_exid;
   ETY  ltd_ety;
   COMMON_P M_p;               /* points the OLT common area on the stack */

   pl_sppsh(gbla_p);           /* do all malloc/free in another sub-pool */
   psh_mode(gbla_p,MD_MODE);
   /*---------------------------------------------------------+
   | [154] link type declaration =                            |
   |       mdo, "LINKTYPE", ps+, link type name, ps+,         |
   |       simple link specification |                        |
   |       implicit link specification |                      |
   |       explicit link specification ),                     |
   |       (ps +, external identifier)?,                      |
   |       (ps +, dso, link type declaration subset, dsc)?,   |
   |       ps*, mdc                                           |
   +---------------------------------------------------------*/
   skip_ps(gbla_p);
   get_name(gbla_p,LTname_p);
   skip_ps(gbla_p);

   /*-----------------------------+
   |Initialize the COMMON_OLT_AREA|
   +-----------------------------*/
   memset(&common,0,sizeof(COMMON_OLT_AREA));
   common.gbla_p = gbla_p;
   M_p = &common;

   switch (GA(curr_token)) {
   case RNI_TK:                        /* must be a simple link... */
      /*---------------------------------+
      |[156] simple link specification = |
      |rni, "SIMPLE", ps+, rni, "IMPLIED"|
      +---------------------------------*/
      chk_gnam(gbla_p,GA(gnwdtab).SIMPLE.s.p);
      skip_ps(gbla_p);
      chk_gnam(gbla_p,GA(gnwdtab).IMPLIED.s.p);
      if (!IS_BITON(GA(opt).ft,SIMPLE_FT)) {  /* check if it's allowed */
/**** if ((++(GA(simple_count))) > GA(opt).max_simple) { ***************/
         errorh(gbla_p,BIGLINK,ERH_T_SEV+ERH_LOCATE);
      }
      break;
   case NOT_FOUND_TK:                  /* Explicit or Implicit */
      /*-----------------------------------+
      |[157] implicit link specification = |
      |source document type name, ps+,     |
      |rni, "IMPLIED"                      |
      |                                    |
      |[158] explicit link specification = |
      |source document type name, ps+,     |
      |result document type name           |
      +-----------------------------------*/
      get_gi(gbla_p,srce_DTname);
      skip_ps(gbla_p);
      switch (GA(curr_token)) {
      case RNI_TK:                   /* must be an implicit link... */
         chk_gnam(gbla_p,GA(gnwdtab).IMPLIED.s.p);
         if (!IS_BITON(GA(opt).ft,IMPLICIT_FT)) { /* check if it's allowed */
            errorh(gbla_p,BIGLINK,ERH_T_SEV+ERH_LOCATE);
         }
         break;
      case NOT_FOUND_TK:             /* must be an explicit link */
         get_gi(gbla_p,rslt_DTname);
         if (!IS_BITON(GA(opt).ft,EXPLICIT_FT)) { /* check if it's allowed */
/****    if ((++(GA(explicit_count))) > GA(opt).max_explicit) { ******/
            errorh(gbla_p,BIGLINK,ERH_T_SEV+ERH_LOCATE);
         }
         break;
      default:
         errorh(gbla_p,INVDLM,ERH_T_SEV+ERH_LOCATE);
         break;
      }
   default:
      errorh(gbla_p,INVDLM,ERH_T_SEV+ERH_LOCATE);
      break;
   }
   skip_ps(gbla_p);
   switch (GA(curr_token)) {
   case NOT_FOUND_TK:
      /*-----------------------+
      |Build an ETY to em_open |
      |the DTD file.           |
      +-----------------------*/
      external_ltd_found = TRUE;
      xid_fill(gbla_p, &ltd_exid, LPD_XFC);       /* Skip_ps done */
      ltd_exid.name._.p = LTname_p;
      ltd_exid.name.len = strlen(LTname_p);
      ltd_ety.name._.p = GA(gnwdtab).LINKTYPE.s.p;
      ltd_ety.is = EXTERNAL_EF | RCDATA_EF;       /* Tell what it is ...*/
      ltd_ety.kind = SGML_EFK;
      ltd_ety.val.ext._.exid.p = &ltd_exid;
      ltd_ety.val.ext.nad.p = (NAD *)0;
      if (GA(curr_token) != DSO_TK) break;        /* else, fall thru */
   case DSO_TK:
      olt_process(M_p);
      ltd_processed = TRUE;
      if (GA(curr_token) != DSC_TK) {
         errorh(gbla_p,NODSC,ERH_W_SEV+ERH_LOCATE);
         break;
      }
   default:
      skip_ps(gbla_p);
      break;
   case MDC_TK:
      break;
   }
   if (GA(curr_token) != MDC_TK) errorh(gbla_p,NOMDC,ERH_T_SEV+ERH_LOCATE);
   if (external_ltd_found) {
      if (em_open(gbla_p,&ltd_ety)) {
         curr_floor_level = GA(floor_level); /* save current floor_level */
         GA(floor_level) = GA(enty_level);
         olt_process(M_p);
         ltd_processed = TRUE;
/****    first check it's Ee! and the enty_level == floor_level ****/
         em_close(gbla_p);
         GA(floor_level) = curr_floor_level; /* restore current floor_level */
      }
      free(ltd_exid.val._.p);          /* free chunk allocated by xid_fill */
   }
   if (ltd_processed) olt_term(M_p,LTname_p); /* Write OLT */
   /* otherwise, assume it exists ?? */
   pop_mode(gbla_p);
   pl_rels(gbla_p);
   pl_sppop(gbla_p);     /* back to previous pool */
}
/******************************************************************************/
