/* National Institute of Standards and Technology (NIST)
/* National Computer System Laboratory (NCSL)
/* Office Systems Engineering (OSE) Group
/* ********************************************************************
/*                            D I S C L A I M E R
/*                              (March 8, 1989)
/*  
/* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
/* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
/* validation suite is modified by someone else and passed on, NIST wants
/* the parser's recipients to know that what they have is not what NIST
/* distributed, so that any problems introduced by others will not
/* reflect on our reputation.
/* 
/* Policies
/* 
/* 1. Anyone may copy and distribute verbatim copies of the SGML source
/* code as received in any medium.
/* 
/* 2. Anyone may modify your copy or copies of SGML parser source code or
/* any portion of it, and copy and distribute such modifications provided
/* that all modifications are clearly associated with the entity that
/* performs the modifications.
/* 
/* NO WARRANTY
/* ===========
/* 
/* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
/* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
/* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
/* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
/* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
/* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
/* 
/* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
/* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
/* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
/* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
/* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
/* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
/* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
/* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
*/

/************************************************************************/
/*   TITLE:          SGML PARSER                                        */
/*   SYSTEM:         DTD PROCESSOR                                      */
/*   SUBSYSTEM:                                                         */
/*   SOURCE FILE:    DTUMISC.C                                          */
/*   AUTHOR:         Jim Heath                                          */
/*                                                                      */
/*   DATE CREATED:                                                      */
/*   LAST MODIFIED:                                                     */
/*                                                                      */
/*                  REVISIONS                                           */
/*   WHEN      WHO            WHY                                       */
/************************************************************************/
#include <stdio.h>
#include <setjmp.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include "qntyset.h"
#include "dtd.h"
#include "dtdfncs.h"
#include "dtdglbl.h"

/* ============================================================ */
void nullfnc()
{
}
/* ============================================================ */
int noxlat(x)
int x;
{
   return(x);
}

/* ============================================================ */
void FUNCTRACE(x)
char *x;
{
   extern int debug;

   if (debug & FUNCTRC)
      printf("%s\n", x);
}
/* ============================================================ */
void terminate(code, msg)
int code;
char *msg;
{
   char *decl;
   extern  int errflag;

   GETDECLADDR(&decl);
   printf("\n\n-------------- F A T A L    E R R O R --------------\n");
   printf("in document:  %s\n", docfname);
   printf("code = %d, msg = %s\n", code, msg);
   printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n");
   closeall();
   unlinkall(TRUE);
   if ((debug & WAITFORCR) != FALSE){
      printf("\n Press enter to continue -\n");
      (void) getchar();
   }
   exit(code);
}
/* ============================================================ */
int TOUPPER(x)
REGISTER int x;
{
   int j;
   if (isascii(x) && isalpha(x) && islower(x)) {
      j = toupper(x);
      return(j);
   }
   return(x & 0xFF);
}
/* ============================================================ */
/* ============================================================ */
void syntxerr(msg)
char *msg;
{
   char *decl;
   extern  int errflag;
   extern jmp_buf       Xenv;
   static int errcount = 0;

   GETDECLADDR(&decl);
   specflag = 0;
   errflag = 1;
   printf("\n\n-------------- E R R O R --------------\n");
   printf("in document:  %s\n", docfname);
   printf("%s\n", msg);
   printf("Current Declaration = \n%s\n", decl);
   printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n");

   if ((debug & WAITFORCR) != FALSE){
      printf("\n Press enter to continue -\n");
      (void) getchar();
   }
   if ((debug & ALLOWSYNTXERRS) == ALLOWSYNTXERRS)
      longjmp(Xenv, 1);
   else
      exit(1);
}
/* ============================================================ */
int ISALPHA(c)
REGISTER int c;
{
   if (isascii(c) && isalpha(c))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int ISDIGIT(c)
REGISTER int c;
{
   if (isascii(c) && isdigit(c))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int ISALNUM(c)
REGISTER int c;
{
   if (isascii(c) && (isalpha(c) || isdigit(c)))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int isnmchar(c)
REGISTER int c;
{
   if (ISALNUM(c) || (c == '.') || (c == '-'))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int isnmstrt(c)
REGISTER int c;
{
   if (isascii(c) && isalpha(c))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int isspcl(j)
REGISTER int j;
{
   switch(j) {
   case GRPO:
   case GRPC:
   case '+':
   case ',':
   case '-':
   case '.':
   case '/':
   case ':':
   case '=':
   case '?':
      return(TRUE);
   default:
      return(FALSE);
   }
}
/* ============================================================ */
void safewrite(file, buff, len)
int file;
char *buff;
unsigned len;
{
	int stat;
   if ((stat = write(file, buff, len)) != len){
		perror("error in writing to file\n");
      terminate(1, "Error in writing to file");
	}
}
/* ============================================================ */
int safeopen(fname, mode, maskbit)
char *fname;
int mode, maskbit;
{
   extern int debug;
   int temp;
   if (filemask & maskbit)
      goto ERROR1;
   filemask |= maskbit;
   if (debug & FILETRC)
      FPRINTF((stderr,"opening %s\n", fname));
#ifdef OLD
   mode = O_RDWR;
#endif
   if ((temp = open(fname, mode)) !=  -1)
      return(temp);
	perror("open failed\n");
ERROR1:
   FPRINTF((stderr, "error in opening %s\n", fname));
   closeall();
   unlinkall(TRUE);
   exit(1);
}
/* ============================================================ */
int safecreat(fname, maskbit)
char *fname;
int maskbit;
{
   /*#define CREATOPTS (O_CREAT|O_TRUNC|O_BINARY|S_IWRITE|S_IREAD)*/
#define CREATOPTS (O_CREAT|O_TRUNC|S_IWRITE|S_IREAD)
   extern int debug;
   int temp;
   if (filemask & maskbit)
      goto ERROR1;
   filemask |= maskbit;
   if (debug & FILETRC)
      FPRINTF((stderr,"creating %s\n", fname));
   if ((temp = creat(fname, CREATOPTS)) !=  -1)
      return(temp);
ERROR1:
   printf("Filename = %s :Filemask = %d : Maskbit = %d\n",fname,filemask,maskbit);
   FPRINTF((stderr, "error in creating %s\n", fname));
   closeall();
   unlinkall(TRUE);
   exit(1);
}
/* ============================================================ */
int safeunlink(fname)
char *fname;
{
   extern int debug;
   if (unlink(fname) !=  -1)
      return(0);
   return(-1);
}
/* ============================================================ */
FILE *safefopen(fname, mode, maskbit)
char *fname;
char *mode;
int maskbit;
{
   char mymode[32];
   extern int debug;
   FILE *temp, *fopen();
   if (debug & FILETRC)
      FPRINTF((stderr,"fopening %s\n", fname));
   if (filemask & maskbit)
      goto ERROR1;
   filemask |= maskbit;
   strcpy(mymode,mode);
   strcat(mymode,"b");
   if ((temp = fopen(fname, mymode)) !=  NULL)
      return(temp);
ERROR1:
   FPRINTF((stderr, "error in fopening %s\n", fname));
   closeall();
   unlinkall(TRUE);
   exit(1);
}
/* ============================================================ */
void safeclose(fd, fname, maskbit)
int fd;
char *fname;
int maskbit;
{
   extern int debug;
   if (debug & FILETRC)
      FPRINTF((stderr,"closing %s\n", fname));
   if ((filemask & maskbit) == 0)
      goto ERROR1;
   filemask &= (~maskbit);
   if (close(fd) != -1)
      return;
ERROR1:
   printf("error in closing %s\n", fname);
   exit(1);
}
/* ============================================================ */
void safefclose(fp, fname, maskbit)
FILE *fp;
char *fname;
int maskbit;
{
   extern int debug;
   if (debug & FILETRC)
      FPRINTF((stderr,"closing %s\n", fname));
   if ((filemask & maskbit) == 0)
      goto ERROR1;
   filemask &= (~maskbit);
   if (fclose(fp) == 0)
      return;
ERROR1:
   printf("error in closing %s\n", fname);
   exit(1);
}
/* ============================================================ */
char *synliteral(j)
REGISTER int j;
{
   switch (j){
   case KW_PUBLIC:
      return("PUBLIC");
   case KW_SYSTEM:
      return("SYSTEM");
   case KW_CDATA:
      return("CDATA");
   case KW_SDATA:
      return("SDATA");
   case KW_PI:
      return("PI");
   case KW_STARTTAG:
      return("STARTTAG");
   case KW_ENDTAG:
      return("ENDTAG");
   case KW_MS:
      return("MS");
   case KW_MD:
      return("MD");
   default:
      syntxerr("Unknown syntactic literal");
   }
   /* should never be reached, for lint only */
   return("");
}
/* ============================================================ */
void mprintf(ptr)
char *ptr;
{
}
/* ============================================================ */
int getnamegrp(temp, firstchar, otherchar)
char *temp;
int (*firstchar)(), (*otherchar)();
{
   REGISTER char *src, *dest;
   char *grp, *dptr;
   int nmcount = 0, namelen;
   enum {
      START, STARTNAME, INNAME      }
   state = START;

   memset(temp, '\0', (GRPCNT * (NAMELEN + 1)));
   grp = getagroup(0);
   for(src = dest = grp; *src != 0; src++){
      if (isspcl(*src) || isconnector(*src) || isnmchar(*src))
         *dest++ = *src;
   }
   *dest = '\0';

   for(src = grp, dest = dptr = temp;;src++){
      switch(state) {
      case START:
         if (*src != GRPO)
            syntxerr("expected GRPO");
         state = STARTNAME;
         break;
      case STARTNAME:
         if (!(*firstchar)(*src))
            syntxerr("expected name start character");
         nmcount++;
         *dest++ = *src;
         namelen = 1;
         state = INNAME;
         break;
      case INNAME:
         if ((*otherchar)(*src)) {
            if(namelen >= NAMELEN)
               syntxerr("name too long in group");
            *dest++ = *src;
            namelen++;
            break;
         }
         else if (isconnector(*src)) {
            dptr += NAMELEN + 1;
            dest = dptr;
            state = STARTNAME;
            break;
         }
         else if (*src == GRPC) {
            return(nmcount);
         }
      }
   }
}
/* =========================================================== */
int isconnector(c)
REGISTER char c;
{
   if ((c == '&') || (c == '|') || (c == ','))
      return(TRUE);
   return(FALSE);
}
/* =========================================================== */
int isoi(c)
REGISTER char c;
{
   if ((c == '?') || (c == '+') || (c == '*'))
      return(TRUE);
   return(FALSE);
}
/* ============================================================ */
int isnamerni(buff, len)
REGISTER char *buff;
int len;
{
   REGISTER int j;
   if (strncmp(buff, "#PCDATA", 7) == 0)
      return(TRUE);
   if (!isnmchar(*buff))
      return(FALSE);
   for (j = 0; j < (len + 1); j++, buff++)
      if(!(isnmchar(*buff)))
         break;
   if ((j == len) && isnmchar(*buff))
      return(FALSE);
   return(TRUE);
}
/* ============================================================ */
char *getnamerni(src)
REGISTER char *src;
{
   static char namearray[NAMELEN + 1];
   REGISTER char *dest = namearray;
   memset(namearray, '\0', sizeof(namearray));
   *dest++ = *src++;
   while (isnmchar(*src))
      *dest++ = *src++;
   return(namearray);
}
/* ============================================================ */
/* ============================================================ */

