/*******************************************************************************
* 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 / SGML Library                                       *
* STATUS           = Version 0, Release 1, Level 25 and up                     *
* COMPONENT NAME   = loadocs.c                                                 *
* DESCRIPTIVE NAME = Load the .OCS file in memory  (<!SGML declaration>)       *
* DATE_WR          = 07/04/1987                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
*                                                                              *
* CHANGE HISTORY =                                                             *
* Number Date     Inits    Change & Reason (brief)                             *
*      1 04/20/88 PGR      Relocation of all OFS within strbuf                 *
*      2 09/20/88 PGR      Uses ut_vget (as load_odt)                          *
*      3 01/09/93 PGR      APPINFO field                                       *
*******************************************************************************/

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

/*---------------+
|Local Functions |
+---------------*/
static void LP_FCT relocate_dvtab(DV *, uint, uchar *);


/*STATIC--------------------------------------------------------relocate_dvtab-+
|Relocate the DV array                                                         |
|                                                                              |
|(S): Relocate string in stringbuf                                             |
|(V): Relocate DV in DVTAB                                                     |
|                                                                              |
|                           +-------------------+---------+------------------+ |
|For a Primary Node,   PDV= |count, is_bseq     |  Token  | Pred Char Str(S) | |
|                           +-------------------+---------+------------------+ |
|                                                                              |
|                           +-------------------+---------+------------------+ |
|For a Secondary Node, SDV= |Next_PDV(V) or NULL|  Token  |  Contin Str(S)   | |
|                           +-------------------+---------+------------------+ |
|                                                                              |
|                           +-------------------+---------+------------------+ |
|For a Bseq Node:      BDV= |Next_PDV(V) or NULL|  Token  |  Contin Str(S)   | |
|                           --------------------+---------+------------------- |
|                           |Prev_BDV(V) or NULL| Bseqlen |  must_recur      | |
|                           +-------------------+---------+------------------+ |
|                                                                              |
+-----------------------------------------------------------------------------*/
static void LP_FCT relocate_dvtab(DV *dvtab, uint dv_max, uchar *strbuf)
{
   int j;
   boolean is_BSEQ;
   DV *dv_p;

   for (dv_p=dvtab, j=0; dv_max--; ++dv_p) {
      if ((j!=1)||(!is_BSEQ)) {                 /* not a B-seq Extension */
         dv_p->s.str = strbuf + dv_p->s.stix;   /* cont str, or pcl */
      }
      if (!j) {                                 /* Primary Node */
         j = dv_p->i.h.count;                   /* Reset secondary node count */
         if (dv_p->i.h.is_bseq) {               /* B-Seq included ? */
            j += 2;                             /* Yes: bump count */
            is_BSEQ = TRUE;                     /* Remember a B-Seq follows */
         }else {
            is_BSEQ = FALSE;                    /* No B-Seq in the list */
         }
      }else {                                   /* Secondary or B-Seq Node */
         dv_p->i.next = (dv_p->i.dvix) ? dvtab + dv_p->i.dvix : (DV *)0;
         --j;
      }
   }
}

/*--------------------------------------------------------------------load_ocs-+
| Load the OCS in memory.                                                      |
| syn_class is one of one of UTSYNL_CL / UTSYNU_CL                             |
+-----------------------------------------------------------------------------*/
void P_FCT load_ocs(GA_P gbla_p,uint syn_class)
{
   AHL ahl;
   uint i;
   uchar *strbuf;
   uint   dv_max;
   DV    *dvtab;
   FNCR  *fncr_p;
   GNWD  *gnwd_p;
   EQTK  *eqtk_p;
   DSTAB_ITM *dstab_itm_p;
   uchar  banner[81];
   uchar const * const ocs_banner = bnr_ocs();

   /*----------------+
   |Read the OCS file|
   +----------------*/
   if ((i=1, !ut_open(gbla_p, syn_class, FALSE, (uchar *)0, (EXID *)0, &ahl)) ||
      (ut_read(gbla_p,ahl,banner,1 + *ocs_banner) != 1 + *ocs_banner) ||
      (i=2, strlen(banner) != *ocs_banner) ||
      (i=3, strcmp(banner, ocs_banner+1))) {
      errorh(gbla_p,BADOPSRD,ERH_T_SEV,i);
   }
   ut_read(gbla_p,ahl,&GA(RE_char),   sizeof(uchar));
   ut_read(gbla_p,ahl,&GA(RS_char),   sizeof(uchar));
   ut_read(gbla_p,ahl,&GA(SPACE_char),sizeof(uchar));
   ut_read(gbla_p,ahl, GA(dstab),     sizeof(DSTAB));
   ut_read(gbla_p,ahl,&GA(gnwdtab),   sizeof(GNWDTAB));
   ut_read(gbla_p,ahl, GA(capmax),    sizeof(GA(capmax)));
   ut_read(gbla_p,ahl, GA(cappoint),  sizeof(GA(cappoint)));
   ut_read(gbla_p,ahl, GA(qntytab),   sizeof(QNTYTAB));
   ut_read(gbla_p,ahl,&GA(opt),       sizeof(OPT));
   if (GA(opt).appinfo.len) {
      GA(opt).appinfo._.p = malloc(GA(opt).appinfo.len);
      ut_read(gbla_p, ahl, GA(opt).appinfo._.p, GA(opt).appinfo.len);
      --(GA(opt).appinfo.len);            /* don't count ending '\0' */
   }else {
      GA(opt).appinfo._.p = (uchar *)0;   /* APPINFO NONE */
   }
   ut_read(gbla_p,ahl, GA(dvtbent),   sizeof(GA(dvtbent)));
   ut_read(gbla_p,ahl, GA(uctab),     sizeof(GA(uctab)));
   ut_read(gbla_p,ahl, GA(gtype),     sizeof(GA(gtype)));
   ut_read(gbla_p,ahl, GA(dltab),     sizeof(GA(dltab)));
   ut_read(gbla_p,ahl, GA(dsettab),   sizeof(GA(dsettab)));

   GA(fncr_max) = ut_vget(gbla_p,ahl,(void **)&GA(fncrtab))/sizeof(FNCR);
   dv_max       = ut_vget(gbla_p,ahl,(void **)&dvtab)/sizeof(DV);
   GA(sr_max)  = (ut_vget(gbla_p,ahl,(void **)&GA(srtab))/sizeof(EQTK)) - 1;
   ut_vget(gbla_p,ahl,(void **)&strbuf);
   ut_close(gbla_p,ahl);

   /*--------------------------+
   |Relocate dvtbent and dvtab |
   +--------------------------*/
   for (i=0; i < sizeof(GA(dvtbent)) / sizeof(DVTBENT); ++i) {
      GA(dvtbent)[i].dv_p = dvtab + GA(dvtbent)[i].rel;
   }
   relocate_dvtab(dvtab,dv_max,strbuf);

   /*----------------+
   |Relocate fncrtab |
   +----------------*/
   for (i=GA(fncr_max), fncr_p=GA(fncrtab); i--; ++fncr_p) {
      fncr_p->s.p = strbuf + fncr_p->s.ofs;
   }
   /*--------------+
   |Relocate dstab |
   +--------------*/
   for (i=0, dstab_itm_p = GA(dstab);
        i < sizeof(DSTAB)/sizeof(DSTAB_ITM);
        ++dstab_itm_p, ++i) {
      dstab_itm_p->p = strbuf + dstab_itm_p->ofs;
   }
   /*--------------+
   |Relocate srtab |
   +--------------*/
   for (eqtk_p = GA(srtab);  ;++eqtk_p) {
      eqtk_p->s.p = strbuf + (i=eqtk_p->s.ofs);
      if (!i) break;
   }
   /*----------------+
   |Relocate gnwdtab |
   +----------------*/
   for (i=0,gnwd_p=(GNWD *)&GA(gnwdtab); i < sizeof(GNWDTAB)/sizeof(GNWD);
      ++gnwd_p, ++i) {
      gnwd_p->s.p = strbuf + gnwd_p->s.ofs;
   }
   GA(is_ocs_done) = TRUE;                  /* Turn on ocs_done switch */
}
/******************************************************************************/
