/*******************************************************************************
* 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 / General Library                                    *
* STATUS           = Version 0, Release 1, Level 34 and up                     *
* COMPONENT NAME   = utmgr.c                                                   *
* DESCRIPTIVE NAME = Utility Files Manager                                     *
* DATE_WR          = 07/10/1989                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
*                                                                              *
* CHANGE HISTORY =                                                             *
* Number Date     Inits    Change & Reason (brief)                             *
*      1 01/07/90 PGR      Do not issue FIND_PFC twice                         *
*      2 05/29/92 PGR      Procures the EXID of the source whenever possible   *
*******************************************************************************/

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

/*---------------------------------------------------------------------ut_find-+
|Find a utility file: returns a pointer to its Id-AHL, or NULL if not found.   |
|                                                                              |
|where:                                                                        |
|    class is one of:                                                          |
|         UTSYNL_XFC for the Local OCS,                                        |
|         UTSYNR_XFC for the Reference OCS,                                    |
|         UTSYNU_XFC for the User-owned OCS,                                   |
|         UTODTR_XFC / UTODTW_XFC for the ODT                                  |
|    name is defined only for UTODTx_XFC (and is the base document name)       |
|    exid is describing the exid of the source (DTD), if possible              |
|                                                                              |
|FIND_PFC is issued only once.  Then, the Id-AHL is kept in an UTID table      |
|where the first entries are (in order) for the local OCS, the user OCS        |
|and the ODT's.                                                                |
+-----------------------------------------------------------------------------*/
AHL * P_FCT ut_find(GA_P gbla_p, uint class, uchar *name_p, EXID *exid_p)
{
   EXID exid;
   PAC *pac_p;
   uint len;
   UTID *utid_p = GA(utid_tbl);

   switch (class) {
   case UTSYNU_XFC:                        /* utid_tbl[1] for the User OCS */
      utid_p += 1;
      /* fall thru */
   case UTSYNL_XFC:                        /* utid_tbl[0] for the Local OCS */
   case UTSYNR_XFC:                        /* or the RefCon OCS */
      if (utid_p->name[0]) return(&(utid_p->id_ahl));   /* found */
      utid_p->name[0] = 'X';               /* not found: put a dummy name */
      len = 0;                             /* no real name for FIND_PFC */
      break;                               /* to get its Id_AHL */
   default:                                /* doc type name or link type name */
      utid_p += 2;
      for (;;) {
         if (!(utid_p->name[0])) {         /* not found */
            memcpy(utid_p->name,name_p,len=strlen(name_p));
            break;                         /* to get its Id_AHL */
         }
         if (!(strcmp(name_p, utid_p->name))) return(&(utid_p->id_ahl));
         ++utid_p;                         /* next entry */
      }
      break;
   }
   if (exid_p) {
      exid = *exid_p;
   }else {
      memset((uchar *)&exid,0,sizeof(EXID));
   }
   exid.asgn_cls = (uchar)class;
   exid.name._.p = name_p;
   exid.name.len = len;
   pac_p = gbla_p->pac_p;
   pac_p->dad._.p = (uchar *)&exid;
   pac_p->func = FIND_PFC;
   switch (pac_p->ase(pac_p)) {            /* issue FIND */
   case 0:                                 /* OK */
      utid_p->id_ahl = pac_p->ahl;         /* Save the Id-AHL */
      return(&(utid_p->id_ahl));           /* return its address */
   case END_PARSE_RC:
      exit(END_PARSE_RC);
   case END_RESUME_RC:
      exit(END_RESUME_RC);
   default:
      utid_p->name[0] = '\0';              /* was not found */
      return((AHL *)0);
   }
}

/*---------------------------------------------------------------------ut_open-+
|Open a utility file                                                           |
|                                                                              |
|where:                                                                        |
|  class is one of: UTSYNL_XFC, UTSYNR_XFC, UTSYNU_XFC, UTODTR_XFC, UTODTW_XFC |
|  name  is defined only for UTODTx_XFC (and is the base document name)        |
|  for_write is TRUE, if the file is open in write mode                        |
|            is FALSE, if the file is open in read mode                        |
|  ahl_p is the address of an AHL where to put the Access-AHL of the file      |
|                                                                              |
|Notes:                                                                        |
| UTSYNL_XFC (Local OCS) and UTSYNR_XFC (Reference OCS) cannot be open         |
| in write mode.  UTSYNU_XFC (User-owned OCS) is always written first.         |
+-----------------------------------------------------------------------------*/
boolean P_FCT ut_open(
   GA_P gbla_p,
   uint class,
   boolean for_write,
   uchar *name_p,
   EXID *exid_p,
   AHL *ahl_p)
{
   PAC *pac_p;
   AHL *id_ahl_p;

   if ((id_ahl_p=ut_find(gbla_p, class, name_p, exid_p)) == (AHL *)0) {
      return(FALSE);
   }else {
      pac_p = gbla_p->pac_p;
      pac_p->ahl = *id_ahl_p;                  /* set the Id-AHL */
      pac_p->func = for_write ?  UTOPW_PFC : UTOPR_PFC;
      switch (pac_p->ase(pac_p)) {
      case 0:
         GA(ut_ahl) = *ahl_p =  pac_p->ahl;    /* Access-AHL */
         GA(ut_opened) = TRUE;                 /* For recovering */
         return(TRUE);
      case END_RESUME_RC:
         exit(END_RESUME_RC);
      case END_PARSE_RC:
         exit(END_PARSE_RC);
      default:
         return(FALSE);
      }
   }
}

/*--------------------------------------------------------------------ut_close-+
| Close a utility file                                                         |
| Note: This function is also called in case the Parser must EXIT:             |
|       code must not assume ERH_T_SEV or EXIT does not return !               |
+-----------------------------------------------------------------------------*/
boolean P_FCT ut_close(GA_P gbla_p, AHL ahl)
{
   PAC *pac_p = gbla_p->pac_p;

   pac_p->ahl = ahl;                  /* utility handle */
   pac_p->func = UTCL_PFC;            /* "utility close" service */
   GA(ut_opened) = FALSE;             /* For recovering */
   switch (pac_p->ase(pac_p)) {
   case 0:
      return(TRUE);
   case END_RESUME_RC:
   case END_PARSE_RC:
      exit(END_PARSE_RC);             /* can return (fall thru) */
   default:
      return(FALSE);
   }
}

/*---------------------------------------------------------------------ut_read-+
|Read size bytes into buffer from utility file AHL                             |
+-----------------------------------------------------------------------------*/
int P_FCT ut_read(GA_P gbla_p, AHL ahl, void *buffer, uint size)
{
   PAC *pac_p = gbla_p->pac_p;

   pac_p->dad._.p = buffer;
   pac_p->dad.len = size;             /* read "size" bytes */
   pac_p->ahl = ahl;                  /* utility handle */
   pac_p->func = UTRD_PFC;            /* "utility read" service */
   switch (pac_p->ase(pac_p)) {
   case 0:
      return(size);
   default:
      errorh(gbla_p,BADREADUT,ERH_T_SEV);
      return(0);
   }
}

/*--------------------------------------------------------------------ut_write-+
|Write size bytes from buffer into utility file AHL                            |
+-----------------------------------------------------------------------------*/
int P_FCT ut_write(GA_P gbla_p, AHL ahl, void const *buffer, uint size)
{
   PAC *pac_p = gbla_p->pac_p;

   pac_p->dad._.p = (void *)buffer;
   pac_p->dad.len = size;             /* write "size" bytes */
   pac_p->ahl = ahl;                  /* utility handle */
   pac_p->func = UTWRT_PFC;           /* "utility write" service */
   switch (pac_p->ase(pac_p)) {
   case 0:
      return(size);
   default:
      errorh(gbla_p,BADWRITUT,ERH_T_SEV);
      return(0);
   }
}

/*---------------------------------------------------------------------ut_vget-+
|Read a variable length record into a mallocated buffer                        |
+-----------------------------------------------------------------------------*/
int P_FCT ut_vget(GA_P gbla_p, AHL ahl, void **buffer_p)
{
   uint size;

   ut_read(gbla_p,ahl,&size,sizeof(size));
   return(ut_read(gbla_p,ahl, *buffer_p=malloc(size), size));
}

/*---------------------------------------------------------------------ut_vput-+
|Write a variable length record and free the mallocated source area            |
+-----------------------------------------------------------------------------*/
void P_FCT ut_vput(GA_P gbla_p, AHL ahl, void *buffer, uint size)
{
   ut_write(gbla_p,ahl,&size,sizeof(size));
   ut_write(gbla_p,ahl,buffer,size);
   free(buffer);
}
/******************************************************************************/
