Bump year. Change Aps->ApS
[idzebra-moved-to-github.git] / util / charmap.c
index 96a390a..f39f706 100644 (file)
@@ -1,6 +1,6 @@
-/* $Id: charmap.c,v 1.29 2004-07-28 09:47:42 adam Exp $
-   Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004
-   Index Data Aps
+/* $Id: charmap.c,v 1.34 2005-01-15 19:38:41 adam Exp $
+   Copyright (C) 1995-2005
+   Index Data ApS
 
 This file is part of the Zebra server.
 
@@ -33,13 +33,15 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 typedef unsigned ucs4_t;
 
-#include <yaz/yaz-util.h>
 #include <charmap.h>
 
+#include <yaz/yaz-util.h>
 
 #define CHR_MAXSTR 1024
 #define CHR_MAXEQUIV 32
 
+const unsigned char CHR_FIELD_BEGIN = '^';
+
 const char *CHR_UNKNOWN = "\001";
 const char *CHR_SPACE   = "\002";
 const char *CHR_CUT     = "\003";
@@ -95,7 +97,7 @@ static chr_t_entry *set_map_string(chr_t_entry *root, NMEM nmem,
                 root->target && root->target[0] && root->target[0][0] &&
                 strcmp (root->target[0], CHR_UNKNOWN))
             {
-                yaz_log (LOG_WARN, "duplicate entry for charmap from '%s'",
+                yaz_log (YLOG_WARN, "duplicate entry for charmap from '%s'",
                          from_0);
             }
            root->target = (unsigned char **)
@@ -142,7 +144,7 @@ static chr_t_entry *find_entry(chr_t_entry *t, const char **from, int len)
     return t->target ? t : 0;
 }
 
-static chr_t_entry *find_entry_x(chr_t_entry *t, const char **from, int *len)
+static chr_t_entry *find_entry_x(chr_t_entry *t, const char **from, int *len, int first)
 {
     chr_t_entry *res;
 
@@ -153,35 +155,49 @@ static chr_t_entry *find_entry_x(chr_t_entry *t, const char **from, int *len)
        from++;
        len++;
     }
-    if (*len > 0 && t->children && t->children[(unsigned char) **from])
+    if (*len > 0 && t->children)
     {
        const char *old_from = *from;
        int old_len = *len;
+
+       res = 0;
+
+       if (first && t->children[CHR_FIELD_BEGIN])
+       {
+           if ((res = find_entry_x(t->children[CHR_FIELD_BEGIN], from, len, 0)) && res != t->children[CHR_FIELD_BEGIN])
+               return res;
+            else
+               res = 0;
+           /* otherwhise there was no match on beginning of field, move on */
+       } 
        
-       (*len)--;
-       (*from)++;
-       if ((res = find_entry_x(t->children[(unsigned char) *old_from],
-                               from, len)))
-           return res;
-       /* no match */
-       *len = old_len;
-       *from = old_from;
+       if (!res && t->children[(unsigned char) **from])
+       {
+           (*len)--;
+           (*from)++;
+           if ((res = find_entry_x(t->children[(unsigned char) *old_from],
+                                   from, len, 0)))
+               return res;
+           /* no match */
+           *len = old_len;
+           *from = old_from;
+       }
     }
     /* no children match. use ourselves, if we have a target */
     return t->target ? t : 0;
 }
 
-const char **chr_map_input_x(chrmaptab maptab, const char **from, int *len)
+const char **chr_map_input_x(chrmaptab maptab, const char **from, int *len, int first)
 {
     chr_t_entry *t = maptab->input;
     chr_t_entry *res;
 
-    if (!(res = find_entry_x(t, from, len)))
+    if (!(res = find_entry_x(t, from, len, first)))
        abort();
     return (const char **) (res->target);
 }
 
-const char **chr_map_input(chrmaptab maptab, const char **from, int len)
+const char **chr_map_input(chrmaptab maptab, const char **from, int len, int first)
 {
     chr_t_entry *t = maptab->input;
     chr_t_entry *res;
@@ -189,7 +205,7 @@ const char **chr_map_input(chrmaptab maptab, const char **from, int len)
 
     len_tmp[0] = len;
     len_tmp[1] = -1;
-    if (!(res = find_entry_x(t, from, len_tmp)))
+    if (!(res = find_entry_x(t, from, len_tmp, first)))
        abort();
     return (const char **) (res->target);
 }
@@ -206,7 +222,7 @@ unsigned char zebra_prim(char **s)
     unsigned char c;
     unsigned int i = 0;
 
-    yaz_log (LOG_DEBUG, "prim %.3s", *s);
+    yaz_log (YLOG_DEBUG, "prim %.3s", *s);
     if (**s == '\\')
     {
         (*s)++;
@@ -259,7 +275,7 @@ ucs4_t zebra_prim_w(ucs4_t **s)
     ucs4_t i = 0;
     char fmtstr[8];
 
-    yaz_log (LOG_DEBUG, "prim %.3s", (char *) *s);
+    yaz_log (YLOG_DEBUG, "prim_w %.3s", (char *) *s);
     if (**s == '\\')
     {
        (*s)++;
@@ -325,7 +341,7 @@ ucs4_t zebra_prim_w(ucs4_t **s)
         c = **s;
         ++(*s);
     }
-    yaz_log (LOG_DEBUG, "out %d", c);
+    yaz_log (YLOG_DEBUG, "out %d", c);
     return c;
 }
 
@@ -374,9 +390,9 @@ static void fun_mkstring(const char *s, void *data, int num)
     chrwork *arg = (chrwork *) data;
     const char **res, *p = s;
 
-    res = chr_map_input(arg->map, &s, strlen(s));
+    res = chr_map_input(arg->map, &s, strlen(s), 0);
     if (*res == (char*) CHR_UNKNOWN)
-       logf(LOG_WARN, "Map: '%s' has no mapping", p);
+       yaz_log(YLOG_WARN, "Map: '%s' has no mapping", p);
     strncat(arg->string, *res, CHR_MAXSTR - strlen(arg->string));
     arg->string[CHR_MAXSTR] = '\0';
 }
@@ -389,11 +405,11 @@ static void fun_add_map(const char *s, void *data, int num)
     chrwork *arg = (chrwork *) data;
 
     assert(arg->map->input);
-    logf (LOG_DEBUG, "set map %.*s", (int) strlen(s), s);
+    yaz_log (YLOG_DEBUG, "set map %.*s", (int) strlen(s), s);
     set_map_string(arg->map->input, arg->map->nmem, s, strlen(s), arg->string,
                    0);
     for (s = arg->string; *s; s++)
-       logf (LOG_DEBUG, " %3d", (unsigned char) *s);
+       yaz_log (YLOG_DEBUG, " %3d", (unsigned char) *s);
 }
 
 /*
@@ -404,11 +420,11 @@ static void fun_add_qmap(const char *s, void *data, int num)
     chrwork *arg = (chrwork *) data;
 
     assert(arg->map->q_input);
-    logf (LOG_DEBUG, "set qmap %.*s", (int) strlen(s), s);
+    yaz_log (YLOG_DEBUG, "set qmap %.*s", (int) strlen(s), s);
     set_map_string(arg->map->q_input, arg->map->nmem, s,
                   strlen(s), arg->string, 0);
     for (s = arg->string; *s; s++)
-       logf (LOG_DEBUG, " %3d", (unsigned char) *s);
+       yaz_log (YLOG_DEBUG, " %3d", (unsigned char) *s);
 }
 
 static int scan_to_utf8 (yaz_iconv_t t, ucs4_t *from, size_t inlen,
@@ -425,9 +441,9 @@ static int scan_to_utf8 (yaz_iconv_t t, ucs4_t *from, size_t inlen,
         ret = yaz_iconv (t, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
         if (ret == (size_t) (-1))
         {
-           yaz_log(LOG_LOG, "from: %2X %2X %2X %2X",
+           yaz_log(YLOG_LOG, "from: %2X %2X %2X %2X",
                    from[0], from[1], from[2], from[3]);
-            yaz_log (LOG_WARN|LOG_ERRNO, "bad unicode sequence");
+            yaz_log (YLOG_WARN|YLOG_ERRNO, "bad unicode sequence");
             return -1;
         }
     }
@@ -443,6 +459,7 @@ static int scan_string(char *s_native,
     char str[1024];
 
     ucs4_t arg[512];
+    ucs4_t arg_prim[512];
     ucs4_t *s0, *s = arg;
     ucs4_t c, begin, end;
     size_t i;
@@ -477,14 +494,14 @@ static int scan_string(char *s_native,
            begin = zebra_prim_w(&s);
            if (*s != '-')
            {
-               logf(LOG_FATAL, "Bad range in char-map");
+               yaz_log(YLOG_FATAL, "Bad range in char-map");
                return -1;
            }
            s++;
            end = zebra_prim_w(&s);
            if (end <= begin)
            {
-               logf(LOG_FATAL, "Bad range in char-map");
+               yaz_log(YLOG_FATAL, "Bad range in char-map");
                return -1;
            }
            s++;
@@ -498,11 +515,11 @@ static int scan_string(char *s_native,
        case '[': s++; abort(); break;
        case '(':
             ++s;
-            s0 = s;
-            while (*s != ')' || s[-1] == '\\')
-                s++;
-           *s = 0;
-            if (scan_to_utf8 (t_utf8, s0, s - s0, str, sizeof(str)-1))
+           s0 = s; i = 0;
+           while (*s != ')' || s[-1] == '\\')
+               arg_prim[i++] = zebra_prim_w(&s);
+           arg_prim[i] = 0;
+            if (scan_to_utf8 (t_utf8, arg_prim, zebra_ucs4_strlen(arg_prim), str, sizeof(str)-1))
                 return -1;
            (*fun)(str, data, num ? (*num)++ : 0);
            s++;
@@ -537,10 +554,10 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
 
     t_utf8 = yaz_iconv_open ("UTF-8", ucs4_native);
 
-    logf (LOG_DEBUG, "maptab %s open", name);
+    yaz_log (YLOG_DEBUG, "maptab %s open", name);
     if (!(f = yaz_fopen(tabpath, name, "r", tabroot)))
     {
-       logf(LOG_WARN|LOG_ERRNO, "%s", name);
+       yaz_log(YLOG_WARN|YLOG_ERRNO, "%s", name);
        return 0;
     }
     nmem = nmem_create ();
@@ -587,13 +604,13 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
        {
            if (argc != 2)
            {
-               logf(LOG_FATAL, "Syntax error in charmap");
+               yaz_log(YLOG_FATAL, "Syntax error in charmap");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8, fun_addentry,
                             res, &num) < 0)
            {
-               logf(LOG_FATAL, "Bad value-set specification");
+               yaz_log(YLOG_FATAL, "Bad value-set specification");
                ++errors;
            }
            res->base_uppercase = num;
@@ -605,18 +622,18 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
        {
            if (!res->base_uppercase)
            {
-               logf(LOG_FATAL, "Uppercase directive with no lowercase set");
+               yaz_log(YLOG_FATAL, "Uppercase directive with no lowercase set");
                ++errors;
            }
            if (argc != 2)
            {
-               logf(LOG_FATAL, "Missing arg for uppercase directive");
+               yaz_log(YLOG_FATAL, "Missing arg for uppercase directive");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8, fun_addentry,
                             res, &num) < 0)
            {
-               logf(LOG_FATAL, "Bad value-set specification");
+               yaz_log(YLOG_FATAL, "Bad value-set specification");
                ++errors;
            }
        }
@@ -624,13 +641,13 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
        {
            if (argc != 2)
            {
-               logf(LOG_FATAL, "Syntax error in charmap for space");
+               yaz_log(YLOG_FATAL, "Syntax error in charmap for space");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8,
                             fun_addspace, res, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad space specification");
+               yaz_log(YLOG_FATAL, "Bad space specification");
                ++errors;
            }
        }
@@ -638,13 +655,13 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
        {
            if (argc != 2)
            {
-               logf(LOG_FATAL, "Syntax error in charmap for cut");
+               yaz_log(YLOG_FATAL, "Syntax error in charmap for cut");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8,
                             fun_addcut, res, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad cut specification");
+               yaz_log(YLOG_FATAL, "Bad cut specification");
                ++errors;
            }
        }
@@ -654,7 +671,7 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
 
            if (argc != 3)
            {
-               logf(LOG_FATAL, "charmap directive map requires 2 args");
+               yaz_log(YLOG_FATAL, "charmap directive map requires 2 args");
                ++errors;
            }
            buf.map = res;
@@ -662,13 +679,13 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
            if (scan_string(argv[2], t_unicode, t_utf8,
                             fun_mkstring, &buf, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad map target");
+               yaz_log(YLOG_FATAL, "Bad map target");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8,
                             fun_add_map, &buf, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad map source");
+               yaz_log(YLOG_FATAL, "Bad map source");
                ++errors;
            }
        }
@@ -678,7 +695,7 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
 
            if (argc != 3)
            {
-               logf(LOG_FATAL, "charmap directive qmap requires 2 args");
+               yaz_log(YLOG_FATAL, "charmap directive qmap requires 2 args");
                ++errors;
            }
            buf.map = res;
@@ -686,13 +703,13 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
            if (scan_string(argv[2], t_unicode, t_utf8, 
                             fun_mkstring, &buf, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad qmap target");
+               yaz_log(YLOG_FATAL, "Bad qmap target");
                ++errors;
            }
            if (scan_string(argv[1], t_unicode, t_utf8, 
                             fun_add_qmap, &buf, 0) < 0)
            {
-               logf(LOG_FATAL, "Bad qmap source");
+               yaz_log(YLOG_FATAL, "Bad qmap source");
                ++errors;
            }
        }
@@ -723,7 +740,7 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
         }
        else
        {
-           logf(LOG_WARN, "Syntax error at '%s' in %s", line, name);
+           yaz_log(YLOG_WARN, "Syntax error at '%s' in %s", line, name);
        }
     
     yaz_fclose(f);
@@ -732,7 +749,7 @@ chrmaptab chrmaptab_create(const char *tabpath, const char *name, int map_only,
        chrmaptab_destroy(res);
        res = 0;
     }
-    logf (LOG_DEBUG, "maptab %s close %d errors", name, errors);
+    yaz_log (YLOG_DEBUG, "maptab %s close %d errors", name, errors);
     if (t_utf8 != 0)
         yaz_iconv_close(t_utf8);
     if (t_unicode != 0)