Allow YAZ 2 series only
[ir-tcl-moved-to-github.git] / grs.c
diff --git a/grs.c b/grs.c
index cdd12a4..2adc2e0 100644 (file)
--- a/grs.c
+++ b/grs.c
@@ -1,11 +1,46 @@
 /*
  * IR toolkit for tcl/tk
- * (c) Index Data 1995
+ * (c) Index Data 1995-1997
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: grs.c,v $
- * Revision 1.2  1995-09-20 11:37:01  adam
+ * Revision 1.11  1997-11-19 11:22:09  adam
+ * Object identifiers can be accessed in GRS-1 records.
+ *
+ * Revision 1.10  1997/09/09 10:19:52  adam
+ * New MSV5.0 port with fewer warnings.
+ *
+ * Revision 1.9  1996/08/16 15:07:44  adam
+ * First work on Explain.
+ *
+ * Revision 1.8  1996/07/03  13:31:10  adam
+ * The xmalloc/xfree functions from YAZ are used to manage memory.
+ *
+ * Revision 1.7  1996/06/05  09:26:20  adam
+ * Bug fix: the change above introduced an error.
+ *
+ * Revision 1.6  1996/06/05  08:59:23  adam
+ * Changed syntax of element specs in GRS-1 retrieval.
+ *
+ * Revision 1.5  1996/05/29  20:28:08  adam
+ * Bug fix: Function ir_tcl_grs_del sometimes free'd bad memory.
+ *
+ * Revision 1.4  1996/05/29  06:37:42  adam
+ * Function ir_tcl_get_grs_r enhanced so that specific elements can be
+ * extracted.
+ *
+ * Revision 1.3  1996/03/05 09:21:01  adam
+ * Bug fix: memory used by GRS records wasn't freed.
+ * Rewrote some of the error handling code - the connection is always
+ * closed before failback is called.
+ * If failback is defined the send APDU methods (init, search, ...) will
+ * return OK but invoke failback (as is the case if the write operation
+ * fails).
+ * Bug fix: ref_count in assoc object could grow if fraction of PDU was
+ * read.
+ *
+ * Revision 1.2  1995/09/20  11:37:01  adam
  * Configure searches for tk4.1 and tk7.5.
  * Work on GRS.
  *
 
 #include "ir-tclp.h"
 
-void ir_tcl_read_grs (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
+void ir_tcl_grs_del (IrTcl_GRS_Record **grs_record)
+{
+    struct GRS_Record_entry *e;
+    int i;
+
+    while (!*grs_record)
+        return;
+    e = (*grs_record)->entries;
+    for (i = 0; i < (*grs_record)->noTags; i++, e++)
+    {
+        switch (e->tagWhich)
+        {
+        case Z_StringOrNumeric_numeric:
+            break;
+        default:
+            xfree (e->tagVal.str);
+        }
+        switch (e->dataWhich)
+        {
+        case Z_ElementData_octets:
+            xfree (e->tagData.octets.buf);
+            break;
+        case Z_ElementData_numeric:
+            break;
+        case Z_ElementData_date:
+            xfree (e->tagData.str);
+            break;            
+        case Z_ElementData_ext:
+            break;
+        case Z_ElementData_string:
+           xfree (e->tagData.str);
+            break;
+        case Z_ElementData_trueOrFalse:
+        case Z_ElementData_oid:
+           xfree (e->tagData.oid);
+           break;
+        case Z_ElementData_intUnit:
+        case Z_ElementData_elementNotThere:
+        case Z_ElementData_elementEmpty:
+        case Z_ElementData_noDataRequested:
+        case Z_ElementData_diagnostic:
+            break;
+        case Z_ElementData_subtree:
+            ir_tcl_grs_del (&e->tagData.sub);
+            break;
+        }
+    }
+    xfree ((*grs_record)->entries);
+    xfree (*grs_record);
+    *grs_record = NULL;
+}
+
+void ir_tcl_grs_mk (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
 {
     int i;
     struct GRS_Record_entry *e;
@@ -40,6 +127,7 @@ void ir_tcl_read_grs (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
     for (i = 0; i < r->num_elements; i++, e++)
     {
         Z_TaggedElement *t;
+       int len;
 
         t = r->elements[i];
         if (t->tagType)
@@ -76,6 +164,10 @@ void ir_tcl_read_grs (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
             e->tagData.bool = *t->content->u.trueOrFalse;
             break;
         case Z_ElementData_oid:
+           len = 1+oid_oidlen (t->content->u.oid);
+           e->tagData.oid = ir_tcl_malloc (len * sizeof(*e->tagData.oid));
+           memcpy (e->tagData.oid, t->content->u.oid,
+                   len * sizeof(*e->tagData.oid));
             break;
         case Z_ElementData_intUnit:
             break;
@@ -86,7 +178,7 @@ void ir_tcl_read_grs (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
         case Z_ElementData_diagnostic:
             break;
         case Z_ElementData_subtree:
-            ir_tcl_read_grs (t->content->u.subtree, &e->tagData.sub);
+            ir_tcl_grs_mk (t->content->u.subtree, &e->tagData.sub);
             break;
         }
     }
@@ -99,74 +191,120 @@ static int ir_tcl_get_grs_r (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record,
     int i;
     struct GRS_Record_entry *e = grs_record->entries;
 
-    if (argno >= argc)
+    for (i = 0; i<grs_record->noTags; i++, e++)
     {
-        for (i = 0; i<grs_record->noTags; i++, e++)
+        int yes = 0;
+        if (argno >= argc)
+            yes = 1;
+        else
         {
+            const char *cp0 = argv[argno];
+            const char *cp1 = strchr (cp0, ',');
 
-            Tcl_AppendResult (interp, "{ ", NULL);
-            sprintf (tmpbuf, "%d", e->tagType);
-            Tcl_AppendElement (interp, tmpbuf);
-
-            if (e->tagWhich == Z_StringOrNumeric_numeric)
-            {
-                Tcl_AppendResult (interp, " numeric ", NULL);
-                sprintf (tmpbuf, "%d", e->tagVal.num);
-                Tcl_AppendElement (interp, tmpbuf);
-            }
+            if (!cp1 || cp1-cp0 < 1)
+                yes = 1;
             else
             {
-                Tcl_AppendResult (interp, " string ", NULL);
-                Tcl_AppendElement (interp, e->tagVal.str);
-            }
-            switch (e->dataWhich)
-            {
-            case Z_ElementData_octets:
-                Tcl_AppendResult (interp, " octets {} ", NULL);
-                break;
-            case Z_ElementData_numeric:
-                Tcl_AppendResult (interp, " numeric {} ", NULL);
-                break;
-            case Z_ElementData_date:
-                Tcl_AppendResult (interp, " date {} ", NULL);
-                break;
-            case Z_ElementData_ext:
-                Tcl_AppendResult (interp, " ext {} ", NULL);
-                break;
-            case Z_ElementData_string:
-                Tcl_AppendResult (interp, " string ", NULL);
-                Tcl_AppendElement (interp, e->tagData.str );
-                break;
-            case Z_ElementData_trueOrFalse:
-                Tcl_AppendResult (interp, " bool ",
-                                  e->tagData.bool ? "1" : "0", " ", NULL);
-                break;
-            case Z_ElementData_oid:
-                Tcl_AppendResult (interp, " oid {} ", NULL);
-                break;
-            case Z_ElementData_intUnit:
-                Tcl_AppendResult (interp, " intUnit {} ", NULL);
-                break;
-            case Z_ElementData_elementNotThere:
-                Tcl_AppendResult (interp, " notThere {} ", NULL);
-                break;
-            case Z_ElementData_elementEmpty:
-                Tcl_AppendResult (interp, " empty {} ", NULL);
-                break;
-            case Z_ElementData_noDataRequested:
-                Tcl_AppendResult (interp, " notRequested {} ", NULL);
-                break;
-            case Z_ElementData_diagnostic:
-                Tcl_AppendResult (interp, " diagnostic {} ", NULL);
-                break;
-            case Z_ElementData_subtree:
-                Tcl_AppendResult (interp, " subtree { ", NULL);
-                ir_tcl_get_grs_r (interp, e->tagData.sub, argc, argv, argno+1);
-                Tcl_AppendResult (interp, " } ", NULL);
-                break;
+                if (*cp0 == '(')
+                    cp0++;
+                if (atoi(cp0) == e->tagType) 
+                {
+                    if (e->tagWhich == Z_StringOrNumeric_numeric)
+                    {
+                        if (atoi (cp1+1) == e->tagVal.num)
+                            yes = 1;
+                    }
+                    else
+                    {
+                        size_t len = strlen(cp1+1);
+                        if (cp1[len] == ')')
+                            len--;
+                        if (len && strlen(e->tagVal.str) == len &&
+                            !memcmp (cp1+1, e->tagVal.str, len))
+                            yes = 1;
+                    }
+                }
             }
+        }
+        if (!yes)
+            continue;
+        Tcl_AppendResult (interp, "{ ", NULL);
+        sprintf (tmpbuf, "%d", e->tagType);
+        Tcl_AppendElement (interp, tmpbuf);
+
+        if (e->tagWhich == Z_StringOrNumeric_numeric)
+        {
+            Tcl_AppendResult (interp, " numeric ", NULL);
+            sprintf (tmpbuf, "%d", e->tagVal.num);
+            Tcl_AppendElement (interp, tmpbuf);
+        }
+        else
+        {
+            Tcl_AppendResult (interp, " string ", NULL);
+            Tcl_AppendElement (interp, e->tagVal.str);
+        }
+        switch (e->dataWhich)
+        {
+        case Z_ElementData_octets:
+            Tcl_AppendResult (interp, " octets {} ", NULL);
+            break;
+        case Z_ElementData_numeric:
+            Tcl_AppendResult (interp, " numeric ", NULL);
+            sprintf (tmpbuf, "%d", e->tagData.num);
+            Tcl_AppendElement (interp, tmpbuf);
+            break;
+        case Z_ElementData_date:
+            Tcl_AppendResult (interp, " date {} ", NULL);
+            break;
+        case Z_ElementData_ext:
+            Tcl_AppendResult (interp, " ext {} ", NULL);
+            break;
+        case Z_ElementData_string:
+            Tcl_AppendResult (interp, " string ", NULL);
+            Tcl_AppendElement (interp, e->tagData.str);
+            break;
+        case Z_ElementData_trueOrFalse:
+            Tcl_AppendResult (interp, " bool ",
+                              e->tagData.bool ? "1" : "0", " ", NULL);
+            break;
+        case Z_ElementData_oid:
+            Tcl_AppendResult (interp, " oid", NULL);
+           if (!e->tagData.oid)
+               Tcl_AppendResult (interp, "{}", NULL);
+           else
+           {
+               int i;
+               int sep = ' ';
+               for (i = 0; e->tagData.oid[i] >= 0; i++)
+               {
+                   sprintf (tmpbuf, "%c%d", sep, e->tagData.oid[i]);
+                   Tcl_AppendResult (interp, tmpbuf, NULL);
+                   sep = '.';
+               }
+           }
+            break;
+        case Z_ElementData_intUnit:
+            Tcl_AppendResult (interp, " intUnit {} ", NULL);
+            break;
+        case Z_ElementData_elementNotThere:
+            Tcl_AppendResult (interp, " notThere {} ", NULL);
+            break;
+        case Z_ElementData_elementEmpty:
+            Tcl_AppendResult (interp, " empty {} ", NULL);
+            break;
+        case Z_ElementData_noDataRequested:
+            Tcl_AppendResult (interp, " notRequested {} ", NULL);
+            break;
+        case Z_ElementData_diagnostic:
+            Tcl_AppendResult (interp, " diagnostic {} ", NULL);
+            break;
+        case Z_ElementData_subtree:
+            Tcl_AppendResult (interp, " subtree { ", NULL);
+            ir_tcl_get_grs_r (interp, e->tagData.sub, argc, argv, argno+1);
             Tcl_AppendResult (interp, " } ", NULL);
+            break;
         }
+        Tcl_AppendResult (interp, " } ", NULL);
     }
     return TCL_OK;
 }
@@ -174,6 +312,6 @@ static int ir_tcl_get_grs_r (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record,
 int ir_tcl_get_grs (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record, 
                      int argc, char **argv)
 {
-    return ir_tcl_get_grs_r (interp, grs_record, argc, argv, 4);
+    return ir_tcl_get_grs_r (interp, grs_record, argc, argv, 3);
 }