C++ compilation.
[idzebra-moved-to-github.git] / util / charmap.c
index 3548efe..5b5b81e 100644 (file)
@@ -1,10 +1,38 @@
 /*
- * Copyright (C) 1994, Index Data I/S 
+ * Copyright (C) 1996-1998, Index Data
  * All rights reserved.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: charmap.c,v $
- * Revision 1.7  1996-06-06 12:08:56  quinn
+ * Revision 1.15  1999-05-26 07:49:14  adam
+ * C++ compilation.
+ *
+ * Revision 1.14  1998/10/13 20:09:18  adam
+ * Changed call to readconf_line.
+ *
+ * Revision 1.13  1997/10/27 14:33:06  adam
+ * Moved towards generic character mapping depending on "structure"
+ * field in abstract syntax file. Fixed a few memory leaks. Fixed
+ * bug with negative integers when doing searches with relational
+ * operators.
+ *
+ * Revision 1.12  1997/09/05 15:30:11  adam
+ * Changed prototype for chr_map_input - added const.
+ * Added support for C++, headers uses extern "C" for public definitions.
+ *
+ * Revision 1.11  1997/09/05 09:52:32  adam
+ * Extra argument added to function chr_read_maptab (tab path).
+ *
+ * Revision 1.10  1997/07/01 13:01:08  adam
+ * Bug fix in routine find_entry: didn't take into account the len arg.
+ *
+ * Revision 1.9  1996/10/29 13:48:14  adam
+ * Updated to use zebrautl.h instead of alexutil.h.
+ *
+ * Revision 1.8  1996/10/18 12:39:23  adam
+ * Uses LOG_DEBUG instead of LOG_WARN for "Character map overlap".
+ *
+ * Revision 1.7  1996/06/06  12:08:56  quinn
  * Fixed bug.
  *
  * Revision 1.6  1996/06/04  13:28:00  quinn
 #include <string.h>
 #include <assert.h>
 
-#include <alexutil.h>
 #include <yaz-util.h>
 #include <charmap.h>
-#include <tpath.h>
 
 #define CHR_MAXSTR 1024
 #define CHR_MAXEQUIV 32
 
+int chr_map_chrs(chr_t_entry *t, char **from, int len,
+                int *read, char **to, int max);
+
 const char *CHR_UNKNOWN = "\001";
 const char *CHR_SPACE   = "\002";
 const char *CHR_BASE    = "\003";
 
-extern char *data1_tabpath;
+struct chrmaptab_info
+{
+    chr_t_entry *input;         /* mapping table for input data */
+    chr_t_entry *query_equiv;   /* mapping table for queries */
+    unsigned char *output[256]; /* return mapping - for display of registers */
+    int base_uppercase;         /* Start of upper-case ordinals */
+    char **tmp_buf;
+    NMEM nmem;
+};
 
 /*
  * Character map trie node.
@@ -66,19 +103,19 @@ struct chr_t_entry
  */
 typedef struct chrwork 
 {
-    chrmaptab *map;
+    chrmaptab map;
     char string[CHR_MAXSTR+1];
 } chrwork;
 
 /*
  * Add an entry to the character map.
  */
-static chr_t_entry *set_map_string(chr_t_entry *root, char *from, int len,
-    char *to)
+static chr_t_entry *set_map_string(chr_t_entry *root, NMEM nmem,
+                                  const char *from, int len, char *to)
 {
     if (!root)
     {
-       root = xmalloc(sizeof(*root));
+       root = (chr_t_entry *) nmem_malloc(nmem, sizeof(*root));
        root->children = 0;
        root->target = 0;
     }
@@ -86,9 +123,9 @@ static chr_t_entry *set_map_string(chr_t_entry *root, char *from, int len,
     {
        if (!root->target || (char*) root->target == CHR_SPACE ||
            (char*) root->target == CHR_UNKNOWN)
-           root->target = (unsigned char *) xstrdup(to);
+           root->target = (unsigned char *) nmem_strdup(nmem, to);
        else if ((char*) to != CHR_SPACE)
-           logf(LOG_WARN, "Character map overlap");
+           logf(LOG_DEBUG, "Character map overlap");
     }
     else
     {
@@ -96,13 +133,14 @@ static chr_t_entry *set_map_string(chr_t_entry *root, char *from, int len,
        {
            int i;
 
-           root->children = xmalloc(sizeof(chr_t_entry*) * 256);
+           root->children = (chr_t_entry **)
+               nmem_malloc(nmem, sizeof(chr_t_entry*) * 256);
            for (i = 0; i < 256; i++)
                root->children[i] = 0;
        }
        if (!(root->children[(unsigned char) *from] =
-           set_map_string(root->children[(unsigned char) *from], from + 1,
-           len - 1, to)))
+           set_map_string(root->children[(unsigned char) *from], nmem,
+                          from + 1, len - 1, to)))
            return 0;
     }
     return root;
@@ -133,15 +171,14 @@ int chr_map_chrs(chr_t_entry *t, char **from, int len, int *read, char **to,
     return i;
 }
 
-#if 1
 
-static chr_t_entry *find_entry(chr_t_entry *t, char **from, int len)
+static chr_t_entry *find_entry(chr_t_entry *t, const char **from, int len)
 {
     chr_t_entry *res;
 
-    if (t->children && t->children[(unsigned char) **from])
+    if (len && t->children && t->children[(unsigned char) **from])
     {
-       char *pos = *from;
+       const char *pos = *from;
 
        (*from)++;
        if ((res = find_entry(t->children[(unsigned char) *pos],
@@ -154,54 +191,25 @@ static chr_t_entry *find_entry(chr_t_entry *t, char **from, int len)
    return t->target ? t : 0;
 }
 
-char **chr_map_input(chr_t_entry *t, char **from, int len)
+const char **chr_map_input(chrmaptab maptab, const char **from, int len)
 {
-    static char *buf[2] = {0, 0};
+    chr_t_entry *t = maptab->input;
     chr_t_entry *res;
 
     if (!(res = find_entry(t, from, len)))
        abort();
-    buf[0] = (char *) res->target;
-    return buf;
+    maptab->tmp_buf[0] = (char*) res->target;
+    maptab->tmp_buf[1] = NULL;
+    return (const char **) maptab->tmp_buf;
 }
 
-#else
-
-char **chr_map_input(chr_t_entry *t, char **from, int len)
+const char *chr_map_output(chrmaptab maptab, const char **from, int len)
 {
-    static char *buf[2] = {0, 0}, str[2] = {0, 0};
-    char *start = *from;
-
-    if (t)
-    {
-       while (len && t->children && t->children[(unsigned char) **from])
-       {
-           t = t->children[(unsigned char) **from];
-           (*from)++;
-           len--;
-       }
-       buf[0] = (char*) t->target;
-    }
-    else /* null mapping */
-    {
-       if (isalnum(**from))
-       {
-           str[0] = **from;
-           buf[0] = str;
-       }
-       else if (isspace(**from))
-           buf[0] = (char*) CHR_SPACE;
-       else
-           buf[0] = (char*) CHR_UNKNOWN;
-    }
-    if (start == *from)
-       (*from)++;
-    return buf;
-    /* return (char*) t->target; */
+    unsigned char c = ** (unsigned char **) from;
+    (*from)++;
+    return (const char*) maptab->output[c];
 }
 
-#endif
-
 static unsigned char prim(char **s)
 {
     unsigned char c;
@@ -235,35 +243,37 @@ static unsigned char prim(char **s)
  * Callback function.
  * Add an entry to the value space.
  */
-static void fun_addentry(char *s, void *data, int num)
+static void fun_addentry(const char *s, void *data, int num)
 {
-    chrmaptab *tab = data;
+    chrmaptab tab = (chrmaptab) data;
     char tmp[2];
 
     tmp[0] = num; tmp[1] = '\0';
-    tab->input = set_map_string(tab->input, s, strlen(s), tmp);
-    tab->output[num + tab->base_uppercase] = (unsigned char *) xstrdup(s);
+    tab->input = set_map_string(tab->input, tab->nmem, s, strlen(s), tmp);
+    tab->output[num + tab->base_uppercase] =
+       (unsigned char *) nmem_strdup(tab->nmem, s);
 }
 
 /* 
  * Callback function.
  * Add a space-entry to the value space.
  */
-static void fun_addspace(char *s, void *data, int num)
+static void fun_addspace(const char *s, void *data, int num)
 {
-    chrmaptab *tab = data;
-    tab->input = set_map_string(tab->input, s, strlen(s), (char*) CHR_SPACE);
+    chrmaptab tab = (chrmaptab) data;
+    tab->input = set_map_string(tab->input, tab->nmem, s, strlen(s),
+                               (char*) CHR_SPACE);
 }
 
 /*
  * Create a string containing the mapped characters provided.
  */
-static void fun_mkstring(char *s, void *data, int num)
+static void fun_mkstring(const char *s, void *data, int num)
 {
-    chrwork *arg = data;
-    char **res, *p = s;
+    chrwork *arg = (chrwork *) data;
+    const char **res, *p = s;
 
-    res = chr_map_input(arg->map->input, &s, strlen(s));
+    res = chr_map_input(arg->map, &s, strlen(s));
     if (*res == (char*) CHR_UNKNOWN)
        logf(LOG_WARN, "Map: '%s' has no mapping", p);
     strncat(arg->string, *res, CHR_MAXSTR - strlen(arg->string));
@@ -273,16 +283,17 @@ static void fun_mkstring(char *s, void *data, int num)
 /*
  * Add a map to the string contained in the argument.
  */
-static void fun_addmap(char *s, void *data, int num)
+static void fun_addmap(const char *s, void *data, int num)
 {
-    chrwork *arg = data;
+    chrwork *arg = (chrwork *) data;
 
     assert(arg->map->input);
-    set_map_string(arg->map->input, s, strlen(s), arg->string);
+    set_map_string(arg->map->input, arg->map->nmem, s, strlen(s), arg->string);
 }
 
-static int scan_string(char *s, void (*fun)(char *c, void *data, int num),
-    void *data, int *num)
+static int scan_string(char *s,
+                      void (*fun)(const char *c, void *data, int num),
+                      void *data, int *num)
 {
     unsigned char c, str[1024], begin, end, *p;
 
@@ -338,34 +349,44 @@ static int scan_string(char *s, void (*fun)(char *c, void *data, int num),
     return 0;
 }
 
-chrmaptab *chr_read_maptab(char *name)
+chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only)
 {
     FILE *f;
     char line[512], *argv[50];
-    chrmaptab *res = xmalloc(sizeof(*res));
+    chrmaptab res;
+    int lineno = 0;
     int argc, num = (int) *CHR_BASE, i;
 
-    if (!(f = yaz_path_fopen(data1_tabpath, name, "r")))
+    if (!(f = yaz_path_fopen(tabpath, name, "r")))
     {
        logf(LOG_WARN|LOG_ERRNO, "%s", name);
        return 0;
     }
-    res = xmalloc(sizeof(*res));
-    res->input = xmalloc(sizeof(*res->input));
+    res = (chrmaptab) xmalloc(sizeof(*res));
+    res->nmem = nmem_create ();
+    res->tmp_buf = (char **)
+       nmem_malloc (res->nmem, sizeof(*res->tmp_buf) * 100);
+    res->input = (chr_t_entry *) nmem_malloc(res->nmem, sizeof(*res->input));
     res->input->target = (unsigned char*) CHR_UNKNOWN;
     res->input->equiv = 0;
-#if 1
-    res->input->children = xmalloc(sizeof(res->input) * 256);
+    res->input->children = (chr_t_entry **)
+       nmem_malloc(res->nmem, sizeof(res->input) * 256);
     for (i = 0; i < 256; i++)
     {
-       res->input->children[i] = xmalloc(sizeof(*res->input));
+       res->input->children[i] = (chr_t_entry *)
+           nmem_malloc(res->nmem, sizeof(*res->input));
        res->input->children[i]->children = 0;
-       res->input->children[i]->target = (unsigned char*) CHR_UNKNOWN;
+       if (map_only)
+       {
+           res->input->children[i]->target = (unsigned char *)
+               nmem_malloc (res->nmem, 2 * sizeof(char));
+           res->input->children[i]->target[0] = i;
+           res->input->children[i]->target[1] = 0;
+       }
+       else
+           res->input->children[i]->target = (unsigned char*) CHR_UNKNOWN;
        res->input->children[i]->equiv = 0;
     }
-#else
-    res->input->children = 0;
-#endif
     res->query_equiv = 0;
     for (i = *CHR_BASE; i < 256; i++)
        res->output[i] = 0;
@@ -373,8 +394,8 @@ chrmaptab *chr_read_maptab(char *name)
     res->output[(int) *CHR_UNKNOWN] = (unsigned char*) "@";
     res->base_uppercase = 0;
 
-    while ((argc = readconf_line(f, line, 512, argv, 50)))
-       if (!yaz_matchstr(argv[0], "lowercase"))
+    while ((argc = readconf_line(f, &lineno, line, 512, argv, 50)))
+       if (!map_only && !yaz_matchstr(argv[0], "lowercase"))
        {
            if (argc != 2)
            {
@@ -393,7 +414,7 @@ chrmaptab *chr_read_maptab(char *name)
            res->output[(int) *CHR_UNKNOWN + num] = (unsigned char*) "@";
            num = (int) *CHR_BASE;
        }
-       else if (!yaz_matchstr(argv[0], "uppercase"))
+       else if (!map_only && !yaz_matchstr(argv[0], "uppercase"))
        {
            if (!res->base_uppercase)
            {
@@ -414,7 +435,7 @@ chrmaptab *chr_read_maptab(char *name)
                return 0;
            }
        }
-       else if (!yaz_matchstr(argv[0], "space"))
+       else if (!map_only && !yaz_matchstr(argv[0], "space"))
        {
            if (argc != 2)
            {
@@ -456,12 +477,16 @@ chrmaptab *chr_read_maptab(char *name)
        }
        else
        {
-#if 0
-           logf(LOG_WARN, "Syntax error at '%s' in %s", line, file);
-           fclose(f);
-           return 0;
-#endif
+           logf(LOG_WARN, "Syntax error at '%s' in %s", line, name);
        }
     fclose(f);
     return res;
 }
+
+void chrmaptab_destroy(chrmaptab tab)
+{
+    nmem_destroy (tab->nmem);
+    xfree (tab);
+}
+
+