First work on Explain.
[ir-tcl-moved-to-github.git] / grs.c
1 /*
2  * IR toolkit for tcl/tk
3  * (c) Index Data 1995-1996
4  * See the file LICENSE for details.
5  * Sebastian Hammer, Adam Dickmeiss
6  *
7  * $Log: grs.c,v $
8  * Revision 1.9  1996-08-16 15:07:44  adam
9  * First work on Explain.
10  *
11  * Revision 1.8  1996/07/03  13:31:10  adam
12  * The xmalloc/xfree functions from YAZ are used to manage memory.
13  *
14  * Revision 1.7  1996/06/05  09:26:20  adam
15  * Bug fix: the change above introduced an error.
16  *
17  * Revision 1.6  1996/06/05  08:59:23  adam
18  * Changed syntax of element specs in GRS-1 retrieval.
19  *
20  * Revision 1.5  1996/05/29  20:28:08  adam
21  * Bug fix: Function ir_tcl_grs_del sometimes free'd bad memory.
22  *
23  * Revision 1.4  1996/05/29  06:37:42  adam
24  * Function ir_tcl_get_grs_r enhanced so that specific elements can be
25  * extracted.
26  *
27  * Revision 1.3  1996/03/05 09:21:01  adam
28  * Bug fix: memory used by GRS records wasn't freed.
29  * Rewrote some of the error handling code - the connection is always
30  * closed before failback is called.
31  * If failback is defined the send APDU methods (init, search, ...) will
32  * return OK but invoke failback (as is the case if the write operation
33  * fails).
34  * Bug fix: ref_count in assoc object could grow if fraction of PDU was
35  * read.
36  *
37  * Revision 1.2  1995/09/20  11:37:01  adam
38  * Configure searches for tk4.1 and tk7.5.
39  * Work on GRS.
40  *
41  * Revision 1.1  1995/08/29  15:38:34  adam
42  * Added grs.c. new version.
43  *
44  */
45
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <ctype.h>
49 #include <assert.h>
50
51 #include "ir-tclp.h"
52
53 void ir_tcl_grs_del (IrTcl_GRS_Record **grs_record)
54 {
55     struct GRS_Record_entry *e;
56     int i;
57
58     while (!*grs_record)
59         return;
60     e = (*grs_record)->entries;
61     for (i = 0; i < (*grs_record)->noTags; i++, e++)
62     {
63         switch (e->tagWhich)
64         {
65         case Z_StringOrNumeric_numeric:
66             break;
67         default:
68             xfree (e->tagVal.str);
69         }
70         switch (e->dataWhich)
71         {
72         case Z_ElementData_octets:
73             xfree (e->tagData.octets.buf);
74             break;
75         case Z_ElementData_numeric:
76             break;
77         case Z_ElementData_date:
78             xfree (e->tagData.str);
79             break;            
80         case Z_ElementData_ext:
81             break;
82         case Z_ElementData_string:
83             xfree (e->tagData.str);
84             break;
85         case Z_ElementData_trueOrFalse:
86         case Z_ElementData_oid:
87         case Z_ElementData_intUnit:
88         case Z_ElementData_elementNotThere:
89         case Z_ElementData_elementEmpty:
90         case Z_ElementData_noDataRequested:
91         case Z_ElementData_diagnostic:
92             break;
93         case Z_ElementData_subtree:
94             ir_tcl_grs_del (&e->tagData.sub);
95             break;
96         }
97     }
98     xfree ((*grs_record)->entries);
99     xfree (*grs_record);
100     *grs_record = NULL;
101 }
102
103 void ir_tcl_grs_mk (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
104 {
105     int i;
106     struct GRS_Record_entry *e;
107
108     *grs_record = NULL;
109     if (!r)
110         return;
111     *grs_record = ir_tcl_malloc (sizeof(**grs_record));
112     if (!((*grs_record)->noTags = r->num_elements))
113     {
114         (*grs_record)->entries = NULL;
115         return;
116     }
117     e = (*grs_record)->entries = ir_tcl_malloc (r->num_elements *
118                                                 sizeof(*e));
119     for (i = 0; i < r->num_elements; i++, e++)
120     {
121         Z_TaggedElement *t;
122
123         t = r->elements[i];
124         if (t->tagType)
125             e->tagType = *t->tagType;
126         else
127             e->tagType = 0;
128         e->tagWhich = t->tagValue->which;
129         if (t->tagValue->which == Z_StringOrNumeric_numeric)
130             e->tagVal.num = *t->tagValue->u.numeric;
131         else
132             ir_tcl_strdup (NULL, &e->tagVal.str, t->tagValue->u.string);
133         e->dataWhich = t->content->which;
134
135         switch (t->content->which)
136         {
137         case Z_ElementData_octets:
138             e->tagData.octets.len = t->content->u.octets->len;
139             e->tagData.octets.buf = ir_tcl_malloc (t->content->u.octets->len);
140             memcpy (e->tagData.octets.buf, t->content->u.octets->buf, 
141                     t->content->u.octets->len);
142             break;
143         case Z_ElementData_numeric:
144             e->tagData.num = *t->content->u.numeric;
145             break;
146         case Z_ElementData_date:
147             ir_tcl_strdup (NULL, &e->tagData.str, t->content->u.string);
148             break;            
149         case Z_ElementData_ext:
150             break;
151         case Z_ElementData_string:
152             ir_tcl_strdup (NULL, &e->tagData.str, t->content->u.string);
153             break;
154         case Z_ElementData_trueOrFalse:
155             e->tagData.bool = *t->content->u.trueOrFalse;
156             break;
157         case Z_ElementData_oid:
158             break;
159         case Z_ElementData_intUnit:
160             break;
161         case Z_ElementData_elementNotThere:
162         case Z_ElementData_elementEmpty:
163         case Z_ElementData_noDataRequested:
164             break;
165         case Z_ElementData_diagnostic:
166             break;
167         case Z_ElementData_subtree:
168             ir_tcl_grs_mk (t->content->u.subtree, &e->tagData.sub);
169             break;
170         }
171     }
172 }
173
174 static int ir_tcl_get_grs_r (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record,
175                              int argc, char **argv, int argno)
176 {
177     static char tmpbuf[32];
178     int i;
179     struct GRS_Record_entry *e = grs_record->entries;
180
181     for (i = 0; i<grs_record->noTags; i++, e++)
182     {
183         int yes = 0;
184         if (argno >= argc)
185             yes = 1;
186         else
187         {
188             const char *cp0 = argv[argno];
189             const char *cp1 = strchr (cp0, ',');
190
191             if (!cp1 || cp1-cp0 < 1)
192                 yes = 1;
193             else
194             {
195                 if (*cp0 == '(')
196                     cp0++;
197                 if (atoi(cp0) == e->tagType) 
198                 {
199                     if (e->tagWhich == Z_StringOrNumeric_numeric)
200                     {
201                         if (atoi (cp1+1) == e->tagVal.num)
202                             yes = 1;
203                     }
204                     else
205                     {
206                         int len = strlen(cp1+1);
207                         if (cp1[len] == ')')
208                             len--;
209                         if (len && strlen(e->tagVal.str) == len &&
210                             !memcmp (cp1+1, e->tagVal.str, len))
211                             yes = 1;
212                     }
213                 }
214             }
215         }
216         if (!yes)
217             continue;
218         Tcl_AppendResult (interp, "{ ", NULL);
219         sprintf (tmpbuf, "%d", e->tagType);
220         Tcl_AppendElement (interp, tmpbuf);
221
222         if (e->tagWhich == Z_StringOrNumeric_numeric)
223         {
224             Tcl_AppendResult (interp, " numeric ", NULL);
225             sprintf (tmpbuf, "%d", e->tagVal.num);
226             Tcl_AppendElement (interp, tmpbuf);
227         }
228         else
229         {
230             Tcl_AppendResult (interp, " string ", NULL);
231             Tcl_AppendElement (interp, e->tagVal.str);
232         }
233         switch (e->dataWhich)
234         {
235         case Z_ElementData_octets:
236             Tcl_AppendResult (interp, " octets {} ", NULL);
237             break;
238         case Z_ElementData_numeric:
239             Tcl_AppendResult (interp, " numeric ", NULL);
240             sprintf (tmpbuf, "%d", e->tagData.num);
241             Tcl_AppendElement (interp, tmpbuf);
242             break;
243         case Z_ElementData_date:
244             Tcl_AppendResult (interp, " date {} ", NULL);
245             break;
246         case Z_ElementData_ext:
247             Tcl_AppendResult (interp, " ext {} ", NULL);
248             break;
249         case Z_ElementData_string:
250             Tcl_AppendResult (interp, " string ", NULL);
251             Tcl_AppendElement (interp, e->tagData.str);
252             break;
253         case Z_ElementData_trueOrFalse:
254             Tcl_AppendResult (interp, " bool ",
255                               e->tagData.bool ? "1" : "0", " ", NULL);
256             break;
257         case Z_ElementData_oid:
258             Tcl_AppendResult (interp, " oid {} ", NULL);
259             break;
260         case Z_ElementData_intUnit:
261             Tcl_AppendResult (interp, " intUnit {} ", NULL);
262             break;
263         case Z_ElementData_elementNotThere:
264             Tcl_AppendResult (interp, " notThere {} ", NULL);
265             break;
266         case Z_ElementData_elementEmpty:
267             Tcl_AppendResult (interp, " empty {} ", NULL);
268             break;
269         case Z_ElementData_noDataRequested:
270             Tcl_AppendResult (interp, " notRequested {} ", NULL);
271             break;
272         case Z_ElementData_diagnostic:
273             Tcl_AppendResult (interp, " diagnostic {} ", NULL);
274             break;
275         case Z_ElementData_subtree:
276             Tcl_AppendResult (interp, " subtree { ", NULL);
277             ir_tcl_get_grs_r (interp, e->tagData.sub, argc, argv, argno+1);
278             Tcl_AppendResult (interp, " } ", NULL);
279             break;
280         }
281         Tcl_AppendResult (interp, " } ", NULL);
282     }
283     return TCL_OK;
284 }
285
286 int ir_tcl_get_grs (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record, 
287                      int argc, char **argv)
288 {
289     return ir_tcl_get_grs_r (interp, grs_record, argc, argv, 3);
290 }
291