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