home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / lookup.c < prev    next >
Text File  |  1994-11-24  |  6KB  |  256 lines

  1. /* lookup.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* A simple database lookup.
  6.  * every entry in the database files is of the form: initial string value
  7.  * We just have to match the initial string, no separators required.
  8.  * Not that the specification just asks for a matching entry, not
  9.  * necessarily the first or the last.
  10.  */
  11. /* $Id: lookup.c,v 4.3 1994/11/15 16:11:01 espie Exp espie $ */
  12.  
  13. /* $Log: lookup.c,v $
  14.  * Revision 4.3  1994/11/15  16:11:01  espie
  15.  * *** empty log message ***
  16.  *
  17.  *
  18.  * Revision 1.2  1992/07/22  14:50:25  espie
  19.  * open_file changed, so lookup had to change to incorporate paths as well.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <malloc.h>
  25.  
  26. #include "defs.h"
  27. #include "extern.h"
  28.  
  29. ID("$Id: lookup.c,v 4.3 1994/11/15 16:11:01 espie Exp espie $")
  30.  
  31. /* the lookup structure is PRIVATE */
  32.  
  33. #define HANDLE 0    /* a null type, for memory handling */
  34. #define FNAME 1     /* a filename, which has not yet been opened */
  35. #define FOPENED 2   /* a file, once opened */
  36. #define STRING 3    /* an already accounted for string */
  37.  
  38. struct lookup
  39.    {
  40.    int type;
  41.    union 
  42.       {
  43.       char *filename;
  44.       FILE *file;
  45.       char *string;
  46.       char *path;
  47.       } value;
  48.    struct lookup *next;
  49.    };
  50.  
  51. /***
  52.  *
  53.  * lookup memory handling 
  54.  *
  55.  ***/
  56.  
  57. /* link_lookup(base, new): link a new element inside the existing chain */
  58. LOCAL void link_lookup(handle, new)
  59. struct lookup *handle, *new;
  60.    {
  61.    new->next = handle->next;
  62.    handle->next = new;
  63.    }
  64.  
  65. LOCAL void set_lookup(handle, path)
  66. struct lookup *handle;
  67. char *path;
  68.    {
  69.    handle->type = HANDLE;
  70.    handle->value.path = path;
  71.    }
  72.  
  73. /* new = create_lookup(): create an empty element, 
  74.  * chain anchor or to be filled 
  75.  */
  76. struct lookup *create_lookup(path)
  77. char *path;
  78.    {
  79.    struct lookup *new;
  80.  
  81.    new = (struct lookup *)malloc(sizeof(struct lookup));
  82.    if (!new)
  83.       exit(10);
  84.    set_lookup(path);
  85.    new->next = NULL;
  86.    return new;
  87.    }
  88.  
  89. /* free_lookup(handle): free the whole chain. Note that filenames
  90.  * do not belong to us
  91.  */
  92. void free_lookup(handle)
  93. struct lookup *handle;
  94.    {
  95.    struct lookup *to_free;
  96.  
  97.    while(handle)
  98.       {
  99.       to_free = handle;
  100.       handle = handle->next;
  101.       switch(to_free->type)
  102.          {
  103.       case HANDLE:
  104.       case FNAME: /* filenames don't belong to you */
  105.          break;
  106.       case FOPENED:
  107.          close_file(to_free->value.file.fhandle, 
  108.             to_free->value.file.filetype);
  109.          break;
  110.       case STRING:
  111.          free(to_free->value.string);
  112.          break;
  113.          }
  114.       free(to_free);
  115.       }
  116.    }
  117.  
  118. /* add_lookup(handle, filename): add a new potential filename to the lookup
  119.  * handle
  120.  */
  121. void add_lookup(handle, filename)
  122. struct lookup *handle;
  123. char *filename;
  124.    {
  125.    struct lookup *new;
  126.  
  127.    new = create_lookup();
  128.    new->type = FNAME;
  129.    new->value.filename = filename;
  130.    link_lookup(handle, new);
  131.    }
  132.  
  133.  
  134. /* postfix = check_prefix(template, s):
  135.  * if s is a prefix of template, return the remaining part of template,
  136.  * else return NULL.
  137.  * Note difference between NULL result and empty postfix (pointer to NULL)
  138.  */
  139. static char *check_prefix(template, s)
  140. char *template;
  141. char *s;
  142.    {
  143.    for (; *s; template++, s++)
  144.       /* *s != 0 at that point */
  145.       if (*template != *s)
  146.          return NULL;
  147.    while(*template == ' ' || *template == '\t')
  148.       template++;
  149.    return template;
  150.    }
  151.  
  152. /* copy = create_copy(s): allocate memory and create a copy of string s.
  153.  * get rid of spurious \n at the end.
  154.  */
  155. static char *create_copy(s)
  156. char *s;
  157.    {
  158.    char *new;
  159.    int len;
  160.  
  161.    len = strlen(s);
  162.    while(s[len - 1] == '\n')
  163.       s[--len] = 0;
  164.    new = malloc(len + 1);
  165.    if (!new)
  166.       exit(10);
  167.    return strcpy(new, s);
  168.    }
  169.  
  170. #define BUFSIZE 1500
  171.  
  172. LOCAL char *internal_lookup();
  173.  
  174. /* postfix = lookup(handle, s): lookup string s in the database indexed by
  175.  * handle.
  176.  */
  177. char *lookup(handle, s)
  178. struct lookup *handle;
  179. char *s;
  180.    {
  181.       /* the internal handler also maintains a current path */
  182.    return internal_lookup(handle, s, NULL);
  183.    }
  184.  
  185.  
  186. LOCAL char *internal_lookup(handle, s, path)
  187. struct lookup *handle;
  188. char *s;
  189. char *path;
  190.    {
  191.    char *r;
  192.    static char buffer[BUFSIZE];
  193.    struct lookup *new;
  194.  
  195.    if (handle)
  196.       {
  197.       switch(handle->type)
  198.          {
  199.       case STRING:
  200.          r = check_string(handle->value.string, s);
  201.          if (r)
  202.             return r;
  203.          else
  204.             return internal_lookup(handle->next, s, path);
  205.       case HANDLE:
  206.          return internal_lookup(handle->next, s,
  207.             handle->value.path ? handle->value.path : path);
  208.       case FNAME:
  209.          r = internal_lookup(handle->next, s, path);
  210.          if (r)
  211.             return r;
  212.          else
  213.             {
  214.             if (handle->value.file = 
  215.                open_file(handle->value.filename, "r", path))
  216.                {
  217.                handle->type = FOPENED;
  218.                return internal_lookup(handle, s, path);
  219.                }
  220.             else
  221.                {
  222.                set_lookup(handle, NULL);
  223.                return NULL;
  224.                }
  225.             }
  226.       case FOPENED:
  227.          r = internal_lookup(handle->next, s, path);
  228.          if (r)
  229.             return r;
  230.          else
  231.             {
  232.             if (fgets(buffer, BUFSIZE, handle->value.file))
  233.                {
  234.                new = create_lookup(NULL);
  235.                new->type = STRING;
  236.                new->value.string = create_copy(buffer);
  237.                link_lookup(handle, new);
  238.                r = check_prefix(new->value.string, s);
  239.                if (r)
  240.                   return r;
  241.                else
  242.                   return internal_lookup(handle, s, path);
  243.                }
  244.             else
  245.                {
  246.                close_file(handle->value.file);
  247.                set_lookup(new, NULL);
  248.                }
  249.             }
  250.          }
  251.       }
  252.    else
  253.       return NULL;
  254.    }
  255.             
  256.