Listing 9 Member functions of class complaint_dict

/* complain.cpp - message dictionary manager */

#include <stdio.h>
#ifdef __ZTC__
#include <io.h>                 /* fseek() */
#endif
#include <stdlib.h>
#include <string.h>
#include "utils.hpp"
#include "errmgr.hpp"
#include "complain.hpp"

/* a singly linked list of keys - should use hash */
/* table for speed */
class complain_ptr {
   public:
      complain_ptr(char *name,long offset,
                 complain_ptr *head);
      ~complain_ptr(void);
      const char *errname(void) const
         { return_errname; }
      int complaint_text(const char *filename,
                      char *line,int linelen);
      complain_ptr *next;
   private:
      char * _errname;
      long foffset;
};

/************** class complaint_dict ***************/

static complain_ptr *read_complaint_file(
                     const char *filename);

complaint_dict::complaint_dict(const char *filename)
{
   /* constructor - remember file name, read all */
   /* messages and store offsets */
   _filename= newstring(filename);
   complain_table = read_complaint_file(_filename);
}

complaint_dict: :~complaint_dict (void)
{
   /* cleanup - delete all of the offset records */
   /* in the table. */
   complain_ptr *keyptr;

   free(_filename);
   while ((keyptr= complain_table) != 0) {
      complain_table = complain_table->next;
      delete keyptr;
   }
}

static complain_ptr *key(complain_ptr *complain_table,
                     const char *name)
{
   /* look for the key in the list of complain_ptr */
   /* objects. returns 0 if not found. */
   while (complain_table != 0 &&
         strcmp(name,complain_table->errname()))
      complain_table= complain_table->next;
   return complain_table;
}

int complaint_dict::key_defined(const char *name) const
{
   /* return 1 if the key is defined here. */
   return key(complain_table,name) != 0;
}

int complaint_dict::complaint_text(const char *name,
                             char *line,
                             int linelen) const
{
   /* retrieve the text for the named message and */
   /* store it in the buffer. returns 0 on failure. */
   complain_ptr *fmt;

   fmt = key(complain_table,name);
   if (fmt == 0) {
      sprintf(line,"Error key \"%s\" not found\n",
             key);
      return 0;               /* failed */
   }
   if (fmt->complaint_text(_filename,line,linelen)) {
      sprintf(line,"Unable to re-read text for"
             "error key \"%s\"\n",key);
      return 0;               /* failed */
   }

   return 1;                   /* all OK */

} /* end of complaint_dict::complaint_text() */

/************* local utility routines **************/

static complain_ptr *read_complaint_file(
                      const char *filename)
{
   /* read all of the error keys in the complaint */
   /* file. */
   FILE *complaintfile;
   char line[512];
   long thisoffset;
   char *keyname,*p,*name;
   int all_ok = 1;
   complain_ptr *keyptr,*complain_table = 0;

   if ((complaintfile = fopen(filename,"r")) == 0) {
      err_mgr.error("Unable to read error text"
                  "file %s\n",filename);
      return 0;               /* OK to continue */
   }

   for (;;) {                  /* exit from within */
      /* remember the start of each line. */
      thisoffset = ftell(complaintfile);
      read_continued_line(complaintfile,line,
                       sizeof(line));
      if (strlen(line) == 0)  /* EOF? done*/

         break;

      /* skip blank lines and comments. */
      keyname = p = line + skipblanks(line);
      if (!*p || *p == '\n' || *P == '#')
         continue;
      p += skip_ident(p);     /* get key name */
      if (p == keyname) {
         err_mgr.warn("Missing error key in error"
                    text file \"%s\":\n%s",
                    filename,line);
         all_ok = 0;
         continue;
      }

      name = newstring(keyname,p - keyname);
      if (key(complain_table,name) != 0) {
         err_mgr.warn("Duplicate error key in"
                    "error text file \"%s\":\n%s",
                    filename,line);
         free(name);
         all_ok = 0;
         continue;
      }
      p += skipblanks(p);
      if (*p != ':') {
         err_mgr.warn("Missing ':' in error text"
                    "file \"%s\":\n%s",
                    filename,line);
         free(name);

         all_ok = 0;
         continue;
      }
      
      /* everything looks good - remember key. */
      keyptr = new complain_ptr(name,thisoffset,
                            complain_table);
      complain_table = keyptr;
   }

   /* if problems were found ignore entire file. */
   fclose(complaintfile);
   if (!all_ok) {
      while ((keyptr = complain_table) != 0) {
         complain table = complain_table->next;
         delete keyptr;
      }
      return 0;
   }
   return complain_table;
}

/**************** class complain_ptr ****************/

complain_ptr:: complain_ptr(char *name, long offset,
                       complain_ptr *head)
{                                /* constructor */
   /* add the new complain_ptr to the front of */
   /* the list. name is allocated for us; the */
   /* destructor must free it. */
   _errname = name;
   foffset = offset;
   next = head;
}

complain_ptr::~complain_ptr(void)  /* destructor */
{
   /* our caller cleans up the chain in next. */
   free(_errname);
}

int complain_ptr::complaint text(
                  const char *filename,
                  char *line,int linelen)
{
   /* re-read the message text for the key. */
   /* returns 1 on error (file has disappeared or */
   /* been edited). */
   FILE *complaintfile;
   char *keyname,*p;
   int newlen;

   line[0] = '\0';             /* clear old text */
   if ((complaintfile = fopen(filename,"r")) == 0)
      return 1;
   if (fseek(complaintfile,foffset,SEEK_SET)) {
      fclose(complaintfile);
      return 1;
   }
   read_continued_line(complaintfile,line,linelen);
   fclose(complaintfile);

   /* make sure we still have the same key! (file */
   /* may have been edited) */
   keyname = p = line + skipblanks(line);
   p += skip_ident(p);
   if (p == keyname ||
      strncmp(keyname, errname,strlen(_errname)))
      return 1;
   p += skipblanks(p);

   if (*p != ':')
      return 1;
   ++p;                        /* skip ':', */
   p += skipblanks(p);         /* leading blanks */

   /* shift everything over to cover the key. */
   newlen = strlen(p);
   memmove(line,p,newlen + 1);
   return 0;                   /* all OK */
}
// End of File