/*******************************************************************************
* 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 / CSD compiler                                       *
* STATUS           = Version 0, Release 1, Level 25 and up                     *
* COMPONENT NAME   = ocscap.c                                                  *
* DESCRIPTIVE NAME = SGML declaration capacity parameter                       *
* DATE_WR          = 06/30/1987                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
*                                                                              *
* Set up the capacity values.                                                  *
*                                                                              *
* IMPLEMENTATION NOTE =                                                        *
*                                                                              *
* DEPENDENCIES =  (see Include list)                                           *
*                                                                              *
* IMPORT=                                                                      *
*                                                                              *
* EXPORT=                                                                      *
*                                                                              *
* CHANGE HISTORY =                                                             *
* Number Date     Inits    Change & Reason (brief)                             *
*      1 02/14/89 PETRUS   Update directly the Reference table                 *
*      2 11/28/90 PETRUS   Increased some capmax to meet 28001A requirements   *
*      3 06/25/91 DUROT    Increased some capmax to new 28001A requirements    *
*******************************************************************************/

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

#define RCS_CAPACITY (ulong)35000L        /* 35000 in the reference CS */

/*---------------------------------------------------------------------cap_bld-+
| Update the CAPACITY Table                                                    |
|                                                                              |
| [180] capacity set = "CAPACITY", ps+,                                        |
|                  (("PUBLIC", ps+, public identifier) |                       |
|                   ("SGMLREF", (ps+, name, ps+, number)+ ))                   |
|                                                                              |
| IMPLEMENTATION NOTE: as the CAPACITY table is not used during the parse      |
| of the <!SGML MD, the REFERENCE table is updated directly.                   |
+-----------------------------------------------------------------------------*/
void P_FCT cap_bld(COMMON_P M_p)
{
   GA_P gbla_p = M_p->gbla_p;
   ulong *cap_max_p;
   ulong maxmax = 0;
   ulong value, max;
   uint i;
   uchar const **c_pp;
   int     ix, cond, num, low;
   uchar   name_p[NAMELEN_MAX+1];
   boolean external_capty_found = FALSE;
   boolean is_empty_set;
   int curr_floor_level;
   EXID cap_exid;
   ETY  cap_ety;

   /*--------------------+
   |Check where we are.. |
   +--------------------*/
   chk_gnam(gbla_p,GA(alwdtab_p)->CAPACITY.s.p);
   skip_Wps(gbla_p);
   if (get_gnam(gbla_p,GA(alwdtab_p)->SGMLREF.s.p)) {
      is_empty_set = TRUE;                   /* SGMLREF: check empty set */
      skip_Wps(gbla_p);                      /* Required ps */
   }else {
      is_empty_set = FALSE;                  /* Discard empty set check */
      /*------------------------+
      |Public Capacity Found    |
      |Build an exid to open it |
      +------------------------*/
      xid_fill(gbla_p,&cap_exid,CAPACITY_XFC);    /* skip_ps done */
      if (GA(curr_token) != NOT_FOUND_TK) {       /* SCOPE must follow */
         errorh(gbla_p,INVDLM,ERH_T_SEV+ERH_LOCATE);
      }
      if (!(IS_BITON(cap_exid.is,VALIDFPI_XF))) M_p->is_not_FPID = TRUE;
      cap_exid.name.len = cap_ety.name.len = strlen(
      cap_exid.name._.p = cap_ety.name._.p = GA(alwdtab_p)->CAPACITY.s.p);
      cap_ety.is = EXTERNAL_EF | RCDATA_EF;  /* tell what it is.. */
      cap_ety.kind = SGML_EFK;
      cap_ety.val.ext._.exid.p = &cap_exid;
      cap_ety.val.ext.nad.p = (NAD *)0;
      if (em_open(gbla_p,&cap_ety)) {
         external_capty_found = TRUE;
         curr_floor_level = GA(floor_level); /* save current floor_level */
         GA(floor_level) = GA(enty_level);   /* to trap the Ee */
         GA(quiet_at_floor) = TRUE;
         skip_ps(gbla_p);
      }
   }
   /*----------------------------------+
   |Enter the variant capacity values  |
   |Binary Search of the capacity name |
   +----------------------------------*/
   c_pp = GA(cap_names);
   for (;;) {
      if (GA(curr_token) != NOT_FOUND_TK) {
         errorh(gbla_p,INVDLM,ERH_T_SEV+ERH_LOCATE);
      }
      if (GA(curr_char) == Ee) break;
      get_name(gbla_p,name_p);      /* get capacity name */
      num = CAP_MAX_SIZE - 1;
      low = 0;                      /* low bound */
      while (low <= num) {
         cond = strcmp(name_p, *(c_pp + (ix=((uint)low+(uint)num)/2)));
         if (cond < 0) {
            num = ix - 1;           /* set low range */
         }else if (cond > 0) {
            low = ix + 1;
         }else {                    /* found */
            break;
         }
      }
      if (cond) {                                /* not found */
         em_unrd(gbla_p,strlen(name_p));         /* unread SCOPE */
         break;
      }
      is_empty_set = FALSE;                     /* At least one value found */
      /*----------------------+
      |limit each capacity to |
      |a specific max         |
      +----------------------*/
      switch (ix) {
      case DTACHCAP_ix:
      case DTACAP_ix:
         errorh(gbla_p,INVKWD,ERH_T_SEV+ERH_LOCATE);
         max = 0; /* avoid compiler warning - can't return from ERH_T */
         break;

#if (defined(DOS_SYS) || defined(OS2V1_SYS))    /* 16-bit systems */
      case TOTALCAP_ix:
         max = 500000L;
         break;
      case GRPCAP_ix:
         max = 300000L;                         /* BOOKIE requirements */
         break;
      default:
         max = 200000L;
         break;
#else                                           /* 32-bit systems */
      case TOTALCAP_ix:
      case GRPCAP_ix:
      case ATTCAP_ix:
         max = 1000000L;                        /* TEI requirements */
         break;
      default:
         max = 500000L;
         break;
#endif
      }
      cap_max_p = GA(capmax) + ix;
      skip_Wps(gbla_p);
      value = get_num(gbla_p);
      if (*cap_max_p) {
         errorh(gbla_p,DUPDEF,ERH_W_SEV+ERH_LOCATE,name_p);
      }else if (value > max) {
         errorh(gbla_p,INVCAP,ERH_W_SEV+ERH_LOCATE,max);
         *cap_max_p = max;
      }else {
         *cap_max_p = value;
      }
      skip_Wps(gbla_p);             /* Required even if PUBLIC: Ee is a ps */
   }
   /*------------------------------+
   |Default the unspecified values |
   |to the Ref Concrete Syntax ones|
   +------------------------------*/
   for (cap_max_p=GA(capmax), i=0; i < CAP_MAX_SIZE; ++cap_max_p, ++i) {
      if (!(*cap_max_p)) {
         if ((i==DTACHCAP_ix)||(i==DTACAP_ix)) {
            *cap_max_p = 0L;
         }else {
            *cap_max_p = RCS_CAPACITY;
         }
      }
      if (*cap_max_p > maxmax) maxmax = *cap_max_p;
   }
   /*------------------------------+
   |Check consistency of the TOTAL |
   +------------------------------*/
   cap_max_p = GA(capmax) + TOTALCAP_ix;
   if (maxmax > *cap_max_p) {
      errorh(gbla_p,BIGQTY,ERH_W_SEV,maxmax);
      *cap_max_p = maxmax;
   }
   if (external_capty_found) {
      if (GA(curr_char) != Ee) errorh(gbla_p,INVKWD,ERH_W_SEV+ERH_LOCATE);
      em_close(gbla_p);
      free(cap_exid.val._.p);             /* free chunk allocated by xid_fill */
      GA(floor_level) = curr_floor_level; /* restore current floor_level */
      GA(quiet_at_floor) = FALSE;
   }
   chk_gnam(gbla_p,GA(alwdtab_p)->SCOPE.s.p);
   if (is_empty_set) {                    /* SGMLREF can't have empty set */
      errorh(gbla_p,NOCAPSET,ERH_W_SEV+ERH_LOCATE);
   }
}
/******************************************************************************/
