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