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