/* lookup.c - perform a similar function to msgs library, but allow non alpha characters in tokens */

#include <string.h>
#include <ctype.h>

#include "os.h"

#include "misc.h"
#include "tracker.h"

static struct
{  char *file;
   char **lp;
   int size, lc;
} lookup__info;

os_error *lookup_init(char *name)
{  os_filestr fcb;
   os_error *err;
   char *cp, *cpl;
   int lc;

   fcb.action = 17;
   fcb.name   = name;
   if (err = os_file(&fcb), err) return err;

   if (fcb.action != 1)
   {  fcb.loadaddr = fcb.action;
      fcb.action   = 19;
      return os_file(&fcb);
   }

   lookup__info.size = fcb.start;

   if (err = misc_malloc((void **) &lookup__info.file, lookup__info.size + 1), err)
      return err;

   fcb.action   = 0xFF;
   fcb.loadaddr = (int) lookup__info.file;
   fcb.execaddr = 0;

   if (err = os_file(&fcb), err) goto fail;

   /* Loaded file, count lines */

   for (cp = lookup__info.file, cpl = lookup__info.file + lookup__info.size, lc = 0; cp < cpl; cp++)
      if (*cp == '\n') ++lc;

   if (lookup__info.file[lookup__info.size-1] != '\n')
   {  lookup__info.file[lookup__info.size++] = '\n';
      ++lc; /* + one if last line has no \n */
   }

   if (err = misc_malloc((void **) &lookup__info.lp, lc * sizeof(char *)), err)
      goto fail;

   for (cp = lookup__info.file, cpl = lookup__info.file + lookup__info.size, lc = 0; cp < cpl; )
   {  char *lp = cp; /* remember line start */

      while (cp < cpl && *cp != '\n' && isspace(*cp))
         cp++;

      switch (*cp)
      {  case '\n': case '#':
            break;

         default:  /* look for a ':' */
            while (cp < cpl && !isspace(*cp) && *cp != ':')
               cp++;

            if (*cp == ':')
               lookup__info.lp[lc++] = lp;
            else
            {  err = misc_err("lookup1", name);
               goto fail2;
            }
            break;
      }

      while (cp < cpl && *cp != '\n')
         cp++;

      if (*cp == '\n') *cp++ = '\0'; /* convert '\n' to '\0'; */
   }

   lookup__info.lc = lc;

   return NULL;

fail2:
   misc_free((void **) &lookup__info.lp);
   lookup__info.lp = NULL;

fail:
   misc_free((void **) &lookup__info.file);
   lookup__info.file = NULL;
   return err;
}

char *lookup(char *token)
{  int ln, l;

   for (l = 0; token[l]; l++) if (token[l] == ':') break;

   for (ln = 0; ln < lookup__info.lc; ln++)
   {  if (strlen(lookup__info.lp[ln]) > l + 1 &&
          lookup__info.lp[ln][l] == ':' &&
          memcmp(token, lookup__info.lp[ln], l) == 0)
         return lookup__info.lp[ln] + l + 1;
   }

   return token[l] == ':' ? token + l + 1 : token;
}
