/************************************************************************/
/*   TITLE:          SGML PARSER                                        */
/*   SYSTEM:         DTD PROCESSOR                                      */
/*   SUBSYSTEM:                                                         */
/*   SOURCE FILE:    BRKOUT.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   "qntyset.h"
#include   "dtd.h"

#define    NO       0
#define    YES      1


void       error();
void       heading();
void       bldsymbltbl();
void       showcontents();
char       *getmsg();
/* ==================================================================== */
#define    MAXSYM   100
/* ==================================================================== */
SYMBREC symbol[MAXSYM];
jmp_buf Xenv;
/* ==================================================================== */
main(argc, argv)
int argc;
char *argv[];
{
   int infile,numtokens,firsttoken;
   unsigned char temp[128], fname[128];
   int j;

   heading();
   if (argc == 1)
      strcpy(fname,"dtdfile.sgm");
   else
      strcpy(fname, argv[1]);
   if ((infile = open(fname, O_RDONLY)) == -1){
      sprintf(temp,"unable to open %s", fname);
      error(temp);
   }
   read(infile, &numtokens, sizeof(numtokens));
   printf("total tokens = %d\n", numtokens);
   read(infile, &firsttoken, sizeof(firsttoken));
   printf("first token  = %d\n", firsttoken);
   bldsymbltbl(infile, numtokens);
   if (setjmp(Xenv) != 0)
      goto DONE;
   for ( j = 0; j < numtokens; j++) {
     printf("------------------------------------------------------\n");
     printf("Content Model for: <token = %03d> ", j);
     printf("%s \n", symbol[j].Sname);
     showcontents(infile);
   }
DONE:
   close(infile);
}
/* ==================================================================== */
void error(msg)
unsigned char *msg;
{
   printf(msg);
   exit(1);
}
/* ==================================================================== */
void bldsymbltbl(infile, numtokens)
int infile, numtokens;
{
   int j;
   unsigned char tempname[128]; 
   for (j = 0; j < numtokens; j++){
      if(read(infile, &symbol[j], sizeof(symbol[j])) != sizeof(symbol[j])){
      perror("error in read() in bldsymbltbl()");
      exit(1);
     }
      memset(tempname, '\0', sizeof(tempname));
      strncpy(tempname, symbol[j].Sname, 8);
      tempname[8] = '\0';
      if (symbol[j].Smin == 0)
         printf("- - ");
      else if (symbol[j].Smin == 1)
         printf("O - ");
      else if (symbol[j].Smin == 2)
         printf("- O ");
      else if (symbol[j].Smin == 3)
         printf("O O ");
      symbol[j].Sname[NAMELEN - 1] = '\0';
      printf("NAME = %s; tokennbr = %03d\n", tempname, symbol[j].Sid);
   }
}
/* ==================================================================== */
void showcontents(infile)
int infile;
{
   DTDREC dtdrec;
   int count, j;
  
   if (read(infile, &dtdrec, sizeof(dtdrec)) <= 0) 
      longjmp(Xenv, 1);
   else {
      switch(dtdrec.Dtoken) {
         case (COMMA): 
         printf("connector = ',' oi = %c\n", dtdrec.Doi); 
         showcontents(infile);
         showcontents(infile);
         return;
         case (AMPERSAND): 
         printf("connector = '&' oi = %c", dtdrec.Doi); 
         read(infile, &count, sizeof(count));
         printf(" <items in & group = %d>\n", count);
         for (j = 0; j < count; j++)
         showcontents(infile);
         return;
         case (OR): 
         printf("connector = '|' oi = %c\n", dtdrec.Doi); 
         showcontents(infile);
         showcontents(infile);
         return;
         case (-1):  
         printf("#PCDATA %c\n", dtdrec.Doi); 
         return;
         case (-3):  
         printf("RCDATA %c\n", dtdrec.Doi); 
         return;
         case (-4):  
         printf("CDATA %c\n", dtdrec.Doi); 
         return;
         case (-5):  
         printf("EMPTY %c\n", dtdrec.Doi); 
         return;
         case (-6):  
         printf("ANY %c\n", dtdrec.Doi); 
         return;
      default:    
         printf("<token = %03d> %s  <oi = %c>  ",
                dtdrec.Dtoken, symbol[dtdrec.Dtoken].Sname,dtdrec.Doi);
         printf("\\%s\\\n", getmsg(dtdrec.Dcontreq));

         return;
      }
   }
}
/* ==================================================================== */
/* ==================================================================== */
/* ==================================================================== */
int safeopen(fname, mode)
unsigned char *fname;
int mode;
{
extern int debug;
int temp;
   if ((temp = open(fname, mode)) !=  -1) 
      return(temp);
   fprintf(stderr, "error in opening %s\n", fname);
   exit(1);
}
/* ==================================================================== */

/*----------------------------------------------*/
/*         HEADING         */
/* Simply prints a informatory heading */
/* when the document parser is invoked */
/* describing the document name to be  */
/* parsed.              */
/*----------------------------------------------*/

void heading()
{
   printf("\n                          DTDFILE Decoder\n");
   printf("                      Decodes DTDFILES built by PARSE2\n");
   printf("          --------------------------------------------------\n");
   printf("                      03Nov86      Version 1.01\n");
   printf("          --------------------------------------------------\n\n");
   return;
}
/* ==================================================================== */
/* ==================================================================== */
char *getmsg(x)
enum CONTEXT x;
{
    switch (x) {
       case C_NEVERO:      return("<start tag is never omissable>");
       case C_ALWAYSO:     return("<start tag is always omissable>");
       case C_SOMETIMESO:  return("<start tag is sometimes omissable>");
       case C_FTO:         return("<start tag is omissable first time only>");
       case C_FTOWR:       return("<start tag is omissable FTO with reset>");
       case C_FTOTSO:      return("<start tag is omissable FTO then sometimes>");
       default:
                           return("UNKNOWN ARGUMENT TO GETMSG()");
    }
}
