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