Allow YAZ 2 series only
[ir-tcl-moved-to-github.git] / marc.c
diff --git a/marc.c b/marc.c
index 5b546ab..f04316b 100644 (file)
--- a/marc.c
+++ b/marc.c
@@ -5,7 +5,17 @@
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: marc.c,v $
- * Revision 1.8  1995-11-14 16:48:00  adam
+ * Revision 1.11  2005-03-10 13:54:38  adam
+ * Define irtcl_atoi_n rather than the YAZ function atoi_n
+ *
+ * Revision 1.10  1999/02/08 09:22:31  franck
+ * Added a grs mode for ir_tcl_get_marc which returns MARC records in a TCL
+ * structure similar to that of ir_tcl_get_grs.
+ *
+ * Revision 1.9  1996/07/03 13:31:13  adam
+ * The xmalloc/xfree functions from YAZ are used to manage memory.
+ *
+ * Revision 1.8  1995/11/14  16:48:00  adam
  * Bug fix: record extraction in line mode merged lines with same tag.
  *
  * Revision 1.7  1995/11/09  15:24:02  adam
@@ -49,7 +59,7 @@
 #define ISO2709_FS 036
 #define ISO2709_IDFS 037
 
-static int atoi_n (const char *buf, int len)
+static int irtcl_atoi_n (const char *buf, int len)
 {
     int val = 0;
 
@@ -108,14 +118,14 @@ char *ir_tcl_fread_marc (FILE *inf, size_t *size)
 
     if (fread (length, 1, 5, inf) != 5)
         return NULL;
-    *size = atoi_n (length, 5);
+    *size = irtcl_atoi_n (length, 5);
     if (*size <= 6)
         return NULL;
-    if (!(buf = malloc (*size+1)))
+    if (!(buf = xmalloc (*size+1)))
         return NULL;
     if (fread (buf+5, 1, *size-5, inf) != (*size-5))
     {
-        free (buf);
+        xfree (buf);
        return NULL;
     }
     memcpy (buf, length, 5);
@@ -141,6 +151,8 @@ int ir_tcl_get_marc (Tcl_Interp *interp, const char *buf,
         mode = 'f';
     else if (!strcmp (argv[3], "line"))
         mode = 'l';
+    else if (!strcmp (argv[3], "grs"))
+        mode = 'g';
     else
     {
         Tcl_AppendResult (interp, "Unknown MARC extract mode", NULL);
@@ -151,19 +163,19 @@ int ir_tcl_get_marc (Tcl_Interp *interp, const char *buf,
         Tcl_AppendResult (interp, "Not a MARC record", NULL);
         return TCL_ERROR;
     }
-    record_length = atoi_n (buf, 5);
+    record_length = irtcl_atoi_n (buf, 5);
     if (record_length < 25)
     {
         Tcl_AppendResult (interp, "Not a MARC record", NULL);
         return TCL_ERROR;
     }
-    indicator_length = atoi_n (buf+10, 1);
-    identifier_length = atoi_n (buf+11, 1);
-    base_address = atoi_n (buf+12, 4);
+    indicator_length = irtcl_atoi_n (buf+10, 1);
+    identifier_length = irtcl_atoi_n (buf+11, 1);
+    base_address = irtcl_atoi_n (buf+12, 4);
 
-    length_data_entry = atoi_n (buf+20, 1);
-    length_starting = atoi_n (buf+21, 1);
-    length_implementation = atoi_n (buf+22, 1);
+    length_data_entry = irtcl_atoi_n (buf+20, 1);
+    length_starting = irtcl_atoi_n (buf+21, 1);
+    length_implementation = irtcl_atoi_n (buf+22, 1);
 
     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
         entry_p += 3+length_data_entry+length_starting;
@@ -182,9 +194,9 @@ int ir_tcl_get_marc (Tcl_Interp *interp, const char *buf,
         memcpy (tag, buf+entry_p, 3);
        entry_p += 3;
         tag[3] = '\0';
-       data_length = atoi_n (buf+entry_p, length_data_entry);
+       data_length = irtcl_atoi_n (buf+entry_p, length_data_entry);
        entry_p += length_data_entry;
-       data_offset = atoi_n (buf+entry_p, length_starting);
+       data_offset = irtcl_atoi_n (buf+entry_p, length_starting);
        entry_p += length_starting;
        i = data_offset + base_address;
        end_offset = i+data_length-1;
@@ -223,7 +235,7 @@ int ir_tcl_get_marc (Tcl_Interp *interp, const char *buf,
            }
             if (marc_compare (identifier, argv[6])==0)
             {
-                char *data = malloc (i-i0+1);
+                char *data = xmalloc (i-i0+1);
              
                 memcpy (data, buf+i0, i-i0);
                 data[i-i0] = '\0';
@@ -247,12 +259,35 @@ int ir_tcl_get_marc (Tcl_Interp *interp, const char *buf,
                     Tcl_AppendElement (interp, data);
                     Tcl_AppendResult (interp, "} ", NULL);
                 }
+                else if (mode == 'g')
+                {
+                    if (strcmp (tag, ptag))
+                    {
+                        if (*ptag)
+                            Tcl_AppendResult (interp, "}} ", NULL);
+                        if (*indicator)
+                            Tcl_AppendResult (interp, "{ 0 numeric {", tag,
+                                              indicator, "} subtree {", NULL);
+                        else
+                            Tcl_AppendResult (interp, "{ 0 numeric ", tag,
+                                              " subtree {", NULL);
+                        strcpy (ptag, tag);
+                    }
+                    if (*identifier)
+                        Tcl_AppendResult (interp, "{3 string ", identifier,
+                                          " string ", NULL);
+                    else
+                        Tcl_AppendResult (interp, "{1 numeric 19 string ",
+                                          NULL);
+                    Tcl_AppendElement (interp, data);
+                    Tcl_AppendResult (interp, "} ", NULL);
+                }
                 else
                     Tcl_AppendElement (interp, data);
-                free (data);
+                xfree (data);
             }
        }
-        if (mode == 'l' && *ptag)
+        if (((mode == 'l') || (mode == 'g')) && *ptag)
             Tcl_AppendResult (interp, "}} ", NULL);
        if (i < end_offset)
             logf (LOG_WARN, "MARC: separator but not at end of field");