26ca7bf785df633abf185b196fb21b9c32891dc9
[yaz-moved-to-github.git] / asn / proto.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: proto.c,v $
7  * Revision 1.26  1995-06-02 09:49:13  quinn
8  * Adding access control
9  *
10  * Revision 1.25  1995/05/25  11:00:08  quinn
11  * *** empty log message ***
12  *
13  * Revision 1.24  1995/05/22  13:58:18  quinn
14  * Fixed an ODR_NULLVAL.
15  *
16  * Revision 1.23  1995/05/22  11:30:18  quinn
17  * Adding Z39.50-1992 stuff to proto.c. Adding zget.c
18  *
19  * Revision 1.22  1995/05/17  08:40:56  quinn
20  * Added delete. Fixed some sequence_begins. Smallish.
21  *
22  * Revision 1.21  1995/05/16  08:50:24  quinn
23  * License, documentation, and memory fixes
24  *
25  * Revision 1.20  1995/05/15  11:55:25  quinn
26  * Smallish.
27  *
28  * Revision 1.19  1995/04/11  11:58:35  quinn
29  * Fixed bug.
30  *
31  * Revision 1.18  1995/04/11  11:52:02  quinn
32  * Fixed possible buf in proto.c
33  *
34  * Revision 1.17  1995/04/10  10:22:22  quinn
35  * Added SCAN.
36  *
37  * Revision 1.16  1995/03/30  10:26:43  quinn
38  * Added Term structure
39  *
40  * Revision 1.15  1995/03/30  09:08:39  quinn
41  * Added Resource control protocol
42  *
43  * Revision 1.14  1995/03/29  08:06:13  quinn
44  * Added a few v3 elements
45  *
46  * Revision 1.13  1995/03/20  11:26:52  quinn
47  * *** empty log message ***
48  *
49  * Revision 1.12  1995/03/20  09:45:09  quinn
50  * Working towards v3
51  *
52  * Revision 1.11  1995/03/17  10:17:25  quinn
53  * Added memory management.
54  *
55  * Revision 1.10  1995/03/15  11:17:40  quinn
56  * Fixed some return-checks from choice.. need better ay to handle those..
57  *
58  * Revision 1.9  1995/03/15  08:37:06  quinn
59  * Fixed protocol bugs.
60  *
61  * Revision 1.8  1995/03/14  16:59:24  quinn
62  * Fixed OPTIONAL flag in attributeelement
63  *
64  * Revision 1.7  1995/03/07  16:29:33  quinn
65  * Added authentication stuff.
66  *
67  * Revision 1.6  1995/03/01  14:46:03  quinn
68  * Fixed protocol bug in 8777query.
69  *
70  * Revision 1.5  1995/02/14  11:54:22  quinn
71  * Fixing include.
72  *
73  * Revision 1.4  1995/02/10  15:54:30  quinn
74  * Small adjustments.
75  *
76  * Revision 1.3  1995/02/09  15:51:39  quinn
77  * Works better now.
78  *
79  * Revision 1.2  1995/02/06  21:26:07  quinn
80  * Repaired this evening's damages..
81  *
82  * Revision 1.1  1995/02/06  16:44:47  quinn
83  * First hack at Z/SR protocol
84  *
85  */
86
87 #include <odr.h>
88
89 #include <proto.h>
90
91 /* ---------------------- GLOBAL DEFS ------------------- */
92
93 int z_ReferenceId(ODR o, Z_ReferenceId **p, int opt)
94 {
95     return odr_implicit(o, odr_octetstring, (Odr_oct**) p, ODR_CONTEXT, 2, opt);
96 }
97
98 int z_DatabaseName(ODR o, Z_DatabaseName **p, int opt)
99 {
100     return odr_implicit(o, odr_visiblestring, (char **) p, ODR_CONTEXT, 105,
101         opt);
102 }
103
104 int z_ResultSetId(ODR o, char **p, int opt)
105 {
106     return odr_implicit(o, odr_visiblestring, (char **) p, ODR_CONTEXT, 31,
107         opt);
108 }
109
110 int z_UserInformationField(ODR o, Z_UserInformationField **p, int opt)
111 {
112     return odr_explicit(o, odr_external, (Odr_external **)p, ODR_CONTEXT,
113         11, opt);
114 }
115
116 int z_InfoCategory(ODR o, Z_InfoCategory **p, int opt)
117 {
118     if (!odr_sequence_begin(o, p, sizeof(**p)))
119         return opt && odr_ok(o);
120     return
121         odr_implicit(o, odr_oid, &(*p)->categoryTypeId, ODR_CONTEXT, 1, 1) &&
122         odr_implicit(o, odr_integer, &(*p)->categoryValue, ODR_CONTEXT, 2, 0) &&
123         odr_sequence_end(o);
124 }
125
126 int z_OtherInformationUnit(ODR o, Z_OtherInformationUnit **p, int opt)
127 {
128     static Odr_arm arm[] =
129     {
130         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_OtherInfo_characterInfo,
131             odr_visiblestring},
132         {ODR_IMPLICIT, ODR_CONTEXT, 3, Z_OtherInfo_binaryInfo,
133             odr_octetstring},
134         {ODR_IMPLICIT, ODR_CONTEXT, 4, Z_OtherInfo_externallyDefinedInfo,
135             odr_external},
136         {ODR_IMPLICIT, ODR_CONTEXT, 5, Z_OtherInfo_oid, odr_oid},
137         {-1, -1, -1, -1, 0}
138     };
139
140     if (!odr_sequence_begin(o, p, sizeof(**p)))
141         return opt && odr_ok(o);
142     return
143         odr_implicit(o, z_InfoCategory, &(*p)->category, ODR_CONTEXT, 1, 1) &&
144         odr_choice(o, arm, &(*p)->which, &(*p)->information) &&
145         odr_sequence_end(o);
146 }
147     
148 int z_OtherInformation(ODR o, Z_OtherInformation **p, int opt)
149 {
150     if (o->direction == ODR_ENCODE)
151         *p = odr_malloc(o, sizeof(**p));
152
153     odr_implicit_settag(o, ODR_CONTEXT, 201);
154     if (odr_sequence_of(o, z_OtherInformationUnit, &(*p)->list,
155         &(*p)->num_elements))
156         return 1;
157     *p = 0;
158     return opt && odr_ok(o);
159 }
160
161 int z_StringOrNumeric(ODR o, Z_StringOrNumeric **p, int opt)
162 {
163     static Odr_arm arm[] =
164     {
165         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_StringOrNumeric_string,
166             odr_visiblestring},
167         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_StringOrNumeric_numeric,
168             odr_integer},
169         {-1, -1, -1, -1, 0}
170     };
171
172     if (o->direction == ODR_DECODE)
173         *p = odr_malloc(o, sizeof(**p));
174     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
175         return 1;
176     *p = 0;
177     return opt && odr_ok(o);
178 }
179
180 /*
181  * check tagging!!
182  */
183 int z_Unit(ODR o, Z_Unit **p, int opt)
184 {
185     if (!odr_sequence_begin(o, p, sizeof(**p)))
186         return opt && odr_ok(o);
187     return
188         odr_implicit(o, odr_visiblestring, &(*p)->unitSystem, ODR_CONTEXT,
189             1, 1) &&
190         odr_explicit(o, z_StringOrNumeric, &(*p)->unitType, ODR_CONTEXT,
191             2, 1) &&
192         odr_explicit(o, z_StringOrNumeric, &(*p)->unit, ODR_CONTEXT, 3, 1) &&
193         odr_implicit(o, odr_integer, &(*p)->scaleFactor, ODR_CONTEXT, 4, 1) &&
194         odr_sequence_end(o);
195 }
196
197 int z_IntUnit(ODR o, Z_IntUnit **p, int opt)
198 {
199     if (!odr_sequence_begin(o, p, sizeof(**p)))
200         return opt && odr_ok(o);
201     return
202         odr_implicit(o, odr_integer, &(*p)->value, ODR_CONTEXT, 1, 0) &&
203         odr_implicit(o, z_Unit, &(*p)->unitUsed, ODR_CONTEXT, 2, 0) &&
204         odr_sequence_end(o);
205 }
206
207 /* ---------------------- INITIALIZE SERVICE ------------------- */
208
209 #if 0
210 int z_NSRAuthentication(ODR o, Z_NSRAuthentication **p, int opt)
211 {
212     if (!odr_sequence_begin(o, p, sizeof(**p)))
213         return opt && odr_ok(o);
214     return
215         odr_visiblestring(o, &(*p)->user, 0) &&
216         odr_visiblestring(o, &(*p)->password, 0) &&
217         odr_visiblestring(o, &(*p)->account, 0) &&
218         odr_sequence_end(o);
219 }
220 #endif
221
222 int z_IdPass(ODR o, Z_IdPass **p, int opt)
223 {
224     if (!odr_sequence_begin(o, p, sizeof(**p)))
225         return opt && odr_ok(o);
226     return
227         odr_implicit(o, odr_visiblestring, &(*p)->groupId, ODR_CONTEXT, 0, 1) &&
228         odr_implicit(o, odr_visiblestring, &(*p)->userId, ODR_CONTEXT, 1, 1) &&
229         odr_implicit(o, odr_visiblestring, &(*p)->password, ODR_CONTEXT, 2,
230             1) &&
231         odr_sequence_end(o);
232 }
233
234 int z_StrAuthentication(ODR o, char **p, int opt)
235 {
236     return odr_visiblestring(o, p, opt);
237 }
238
239 int z_IdAuthentication(ODR o, Z_IdAuthentication **p, int opt)
240 {
241     static Odr_arm arm[] =
242     {
243         {-1, -1, -1, Z_IdAuthentication_open, z_StrAuthentication},
244         {-1, -1, -1, Z_IdAuthentication_idPass, z_IdPass},
245         {-1, -1, -1, Z_IdAuthentication_anonymous, odr_null},
246         {-1, -1, -1, Z_IdAuthentication_other, odr_external},
247         {-1, -1, -1, -1, 0}
248     };
249
250     if (o->direction == ODR_DECODE)
251         *p = odr_malloc(o, sizeof(**p));
252
253     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
254         return 1;
255     *p = 0;
256     return opt && odr_ok(o);
257 }
258
259 int z_InitRequest(ODR o, Z_InitRequest **p, int opt)
260 {
261     Z_InitRequest *pp;
262
263     if (!odr_sequence_begin(o, p, sizeof(**p)))
264         return opt && odr_ok(o);
265     pp = *p;
266     return
267         z_ReferenceId(o, &pp->referenceId, 1) &&
268         odr_implicit(o, odr_bitstring, &pp->protocolVersion, ODR_CONTEXT, 
269             3, 0) &&
270         odr_implicit(o, odr_bitstring, &pp->options, ODR_CONTEXT, 4, 0) &&
271         odr_implicit(o, odr_integer, &pp->preferredMessageSize, ODR_CONTEXT,
272             5, 0) &&
273         odr_implicit(o, odr_integer, &pp->maximumRecordSize, ODR_CONTEXT,
274             6, 0) &&
275         odr_explicit(o, z_IdAuthentication, &pp->idAuthentication, ODR_CONTEXT,
276             7, 1) &&
277         odr_implicit(o, odr_visiblestring, &pp->implementationId, ODR_CONTEXT,
278             110, 1) &&
279         odr_implicit(o, odr_visiblestring, &pp->implementationName, ODR_CONTEXT,
280             111, 1) &&
281         odr_implicit(o, odr_visiblestring, &pp->implementationVersion,
282             ODR_CONTEXT, 112, 1) &&
283         z_UserInformationField(o, &pp->userInformationField, 1) &&
284 #ifdef Z_OTHERINFO
285         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
286 #endif
287         odr_sequence_end(o);
288 }
289
290 int z_InitResponse(ODR o, Z_InitResponse **p, int opt)
291 {
292     Z_InitResponse *pp;
293
294     if (!odr_sequence_begin(o, p, sizeof(**p)))
295         return opt && odr_ok(o);
296     pp = *p;
297     return
298         z_ReferenceId(o, &pp->referenceId, 1) &&
299         odr_implicit(o, odr_bitstring, &pp->protocolVersion, ODR_CONTEXT, 
300             3, 0) &&
301         odr_implicit(o, odr_bitstring, &pp->options, ODR_CONTEXT, 4, 0) &&
302         odr_implicit(o, odr_integer, &pp->preferredMessageSize, ODR_CONTEXT,
303             5, 0) &&
304         odr_implicit(o, odr_integer, &pp->maximumRecordSize, ODR_CONTEXT,
305             6, 0) &&
306         odr_implicit(o, odr_bool, &pp->result, ODR_CONTEXT, 12, 0) &&
307         odr_implicit(o, odr_visiblestring, &pp->implementationId, ODR_CONTEXT,
308             110, 1) &&
309         odr_implicit(o, odr_visiblestring, &pp->implementationName, ODR_CONTEXT,
310             111, 1) &&
311         odr_implicit(o, odr_visiblestring, &pp->implementationVersion,
312             ODR_CONTEXT, 112, 1) &&
313         z_UserInformationField(o, &pp->userInformationField, 1) &&
314 #ifdef Z_OTHERINFO
315         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
316 #endif
317         odr_sequence_end(o);
318 }
319
320 /* ------------------ RESOURCE CONTROL ----------------*/
321
322 int z_TriggerResourceControlRequest(ODR o, Z_TriggerResourceControlRequest **p,
323                                     int opt)
324 {
325     if (!odr_sequence_begin(o, p, sizeof(**p)))
326         return opt && odr_ok(o);
327     return
328         z_ReferenceId(o, &(*p)->referenceId, 1) &&
329         odr_implicit(o, odr_integer, &(*p)->requestedAction, ODR_CONTEXT,
330             46, 0) &&
331         odr_implicit(o, odr_oid, &(*p)->prefResourceReportFormat,
332             ODR_CONTEXT, 47, 1) &&
333         odr_implicit(o, odr_bool, &(*p)->resultSetWanted, ODR_CONTEXT,
334             48, 1) &&
335 #ifdef Z_OTHERINFO
336         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
337 #endif
338         odr_sequence_end(o);
339 }
340
341 int z_ResourceControlRequest(ODR o, Z_ResourceControlRequest **p, int opt)
342 {
343     if (!odr_sequence_begin(o, p, sizeof(**p)))
344         return opt && odr_ok(o);
345     return
346         z_ReferenceId(o, &(*p)->referenceId, 1) &&
347         odr_implicit(o, odr_bool, &(*p)->suspendedFlag, ODR_CONTEXT, 39, 1)&&
348         odr_explicit(o, odr_external, &(*p)->resourceReport, ODR_CONTEXT,
349             40, 1) &&
350         odr_implicit(o, odr_integer, &(*p)->partialResultsAvailable,
351             ODR_CONTEXT, 41, 1) &&
352         odr_implicit(o, odr_bool, &(*p)->responseRequired, ODR_CONTEXT,
353             42, 0) &&
354         odr_implicit(o, odr_bool, &(*p)->triggeredRequestFlag,
355             ODR_CONTEXT, 43, 1) &&
356 #ifdef Z_OTHERINFO
357         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
358 #endif
359         odr_sequence_end(o);
360 }
361
362 int z_ResourceControlResponse(ODR o, Z_ResourceControlResponse **p, int opt)
363 {
364     if (!odr_sequence_begin(o, p, sizeof(**p)))
365         return opt && odr_ok(o);
366     return
367         z_ReferenceId(o, &(*p)->referenceId, 1) &&
368         odr_implicit(o, odr_bool, &(*p)->continueFlag, ODR_CONTEXT, 44, 0) &&
369         odr_implicit(o, odr_bool, &(*p)->resultSetWanted, ODR_CONTEXT,
370             45, 1) &&
371 #ifdef Z_OTHERINFO
372         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
373 #endif
374         odr_sequence_end(o);
375 }
376
377 /* ------------------------ SEARCH SERVICE ----------------------- */
378
379 int z_ElementSetName(ODR o, char **p, int opt)
380 {
381     return odr_implicit(o, odr_visiblestring, (char**) p, ODR_CONTEXT, 103,
382         opt);
383 }
384
385 int z_PreferredRecordSyntax(ODR o, Z_PreferredRecordSyntax **p, int opt)
386 {
387     return odr_implicit(o, odr_oid, (Odr_oid**) p, ODR_CONTEXT, 104, opt);
388 }
389
390 int z_DatabaseSpecificUnit(ODR o, Z_DatabaseSpecificUnit **p, int opt)
391 {
392     if (!odr_sequence_begin(o, p, sizeof(**p)))
393         return opt && odr_ok(o);
394     return
395         z_DatabaseName(o, &(*p)->databaseName, 0) &&
396         z_ElementSetName(o, &(*p)->elementSetName, 0) &&
397         odr_sequence_end(o);
398 }
399
400 int z_DatabaseSpecific(ODR o, Z_DatabaseSpecific **p, int opt)
401 {
402     if (o->direction == ODR_DECODE)
403         *p = odr_malloc(o, sizeof(**p));
404     else if (!*p)
405         return opt;
406
407     odr_implicit_settag(o, ODR_CONTEXT, 1);
408     if (odr_sequence_of(o, z_DatabaseSpecificUnit, &(*p)->elements,
409         &(*p)->num_elements))
410         return 1;
411     *p = 0;
412     return 0;
413 }
414
415 int z_ElementSetNames(ODR o, Z_ElementSetNames **p, int opt)
416 {
417     static Odr_arm arm[] =
418     {
419         {ODR_IMPLICIT, ODR_CONTEXT, 0, Z_ElementSetNames_generic,
420             z_ElementSetName},
421         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ElementSetNames_databaseSpecific,
422             z_DatabaseSpecific},
423         {-1, -1, -1, -1, 0}
424     };
425
426     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 19))
427         return opt && odr_ok(o);
428
429     if (o->direction == ODR_DECODE)
430         *p = odr_malloc(o, sizeof(**p));
431
432     if (odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
433         odr_constructed_end(o))
434         return 1;
435     *p = 0;
436     return 0;
437 }
438
439 /* ----------------------- RPN QUERY -----------------------*/
440
441 int z_AttributeElement(ODR o, Z_AttributeElement **p, int opt)
442 {
443     if (!odr_sequence_begin(o, p, sizeof(**p)))
444         return opt && odr_ok(o);
445     return
446         odr_implicit(o, odr_integer, &(*p)->attributeType, ODR_CONTEXT,
447             120, 0) &&
448         odr_implicit(o, odr_integer, &(*p)->attributeValue, ODR_CONTEXT,
449             121, 0) &&
450         odr_sequence_end(o);
451 }
452
453 #ifdef Z_V3
454
455 int z_Term(ODR o, Z_Term **p, int opt)
456 {
457     static Odr_arm arm[] =
458     {
459         {ODR_IMPLICIT, ODR_CONTEXT, 45, Z_Term_general, odr_octetstring},
460         {ODR_IMPLICIT, ODR_CONTEXT, 215, Z_Term_numeric, odr_integer},
461         {ODR_IMPLICIT, ODR_CONTEXT, 216, Z_Term_characterString,
462             odr_visiblestring},
463         {ODR_IMPLICIT, ODR_CONTEXT, 217, Z_Term_oid, odr_oid},
464         {ODR_IMPLICIT, ODR_CONTEXT, 218, Z_Term_dateTime, odr_cstring},
465         {ODR_IMPLICIT, ODR_CONTEXT, 219, Z_Term_external, odr_external},
466         /* add intUnit here */
467         {ODR_IMPLICIT, ODR_CONTEXT, 221, Z_Term_null, odr_null},
468         {-1, -1, -1, -1, 0}
469     };
470
471     if (o->direction ==ODR_DECODE)
472         *p = odr_malloc(o, sizeof(**p));
473     else if (!*p)
474         return opt;
475     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
476         return 1;
477     *p = 0;
478     return opt && odr_ok(o);
479 }
480
481 #endif
482
483 int z_AttributesPlusTerm(ODR o, Z_AttributesPlusTerm **p, int opt)
484 {
485     if (!(odr_implicit_settag(o, ODR_CONTEXT, 102) &&
486         odr_sequence_begin(o, p, sizeof(**p))))
487         return opt && odr_ok(o);
488     return
489         odr_implicit_settag(o, ODR_CONTEXT, 44) &&
490         odr_sequence_of(o, z_AttributeElement, &(*p)->attributeList,
491             &(*p)->num_attributes) &&
492         z_Term(o, &(*p)->term, 0) &&
493         odr_sequence_end(o);
494 }
495
496 int z_ProximityOperator(ODR o, Z_ProximityOperator **p, int opt)
497 {
498     static Odr_arm arm[] =
499     {
500         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ProxCode_known, odr_integer},
501         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ProxCode_private, odr_integer},
502         {-1, -1, -1, -1, 0}
503     };
504
505     if (!odr_sequence_begin(o, p, sizeof(**p)))
506         return opt && odr_ok(o);
507     return
508         odr_implicit(o, odr_bool, &(*p)->exclusion, ODR_CONTEXT, 1, 1) &&
509         odr_implicit(o, odr_integer, &(*p)->distance, ODR_CONTEXT, 2, 0) &&
510         odr_implicit(o, odr_bool, &(*p)->ordered, ODR_CONTEXT, 3, 0) &&
511         odr_implicit(o, odr_integer, &(*p)->relationType, ODR_CONTEXT, 4, 0) &&
512         odr_constructed_begin(o, &(*p)->proximityUnitCode, ODR_CONTEXT, 5) &&
513         odr_choice(o, arm, &(*p)->proximityUnitCode, &(*p)->which) &&
514         odr_constructed_end(o) &&
515         odr_sequence_end(o);
516 }
517
518 int z_Operator(ODR o, Z_Operator **p, int opt)
519 {
520     static Odr_arm arm[] =
521     {
522         {ODR_IMPLICIT, ODR_CONTEXT, 0, Z_Operator_and, odr_null},
523         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Operator_or, odr_null},
524         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_Operator_and_not, odr_null},
525         {ODR_IMPLICIT, ODR_CONTEXT, 3, Z_Operator_prox, z_ProximityOperator},
526         {-1, -1, -1, -1, 0}
527     };
528
529     if (!*p && o->direction != ODR_DECODE)
530         return opt;
531     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 46))
532         return opt && odr_ok(o);
533     if (o->direction == ODR_DECODE)
534         *p = odr_malloc(o, sizeof(**p));
535     else
536         (*p)->u.and = ODR_NULLVAL;
537
538     if (odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
539         odr_constructed_end(o))
540         return 1;
541     *p = 0;
542     return opt && odr_ok(o);
543 }
544
545 int z_Operand(ODR o, Z_Operand **p, int opt)
546 {
547     static Odr_arm arm[] =
548     {
549         {-1, -1, -1, Z_Operand_APT, z_AttributesPlusTerm},
550         {-1, -1, -1, Z_Operand_resultSetId, z_ResultSetId},
551         {-1, -1, -1, -1, 0}
552     };
553
554     if (o->direction ==ODR_DECODE)
555         *p = odr_malloc(o, sizeof(**p));
556     else if (!*p)
557         return opt;
558     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
559         return 1;
560     *p = 0;
561     return opt && odr_ok(o);
562 }
563
564 int z_RPNStructure(ODR o, Z_RPNStructure **p, int opt);
565
566 int z_Complex(ODR o, Z_Complex **p, int opt)
567 {
568     if (!odr_sequence_begin(o, p, sizeof(**p)))
569         return opt && odr_ok(o);
570     return
571         z_RPNStructure(o, &(*p)->s1, 0) &&
572         z_RPNStructure(o, &(*p)->s2, 0) &&
573         z_Operator(o, &(*p)->operator, 0) &&
574         odr_sequence_end(o);
575 }
576
577 int z_RPNStructure(ODR o, Z_RPNStructure **p, int opt)
578 {
579     static Odr_arm arm[] = 
580     {
581         {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_RPNStructure_simple, z_Operand},
582         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_RPNStructure_complex, z_Complex},
583         {-1 -1, -1, -1, 0}
584     };
585
586     if (o->direction == ODR_DECODE)
587         *p = odr_malloc(o, sizeof(**p));
588     else if (!*p)
589         return opt;
590     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
591         return 1;
592     *p = 0;
593     return opt && odr_ok(o);
594 }
595
596 int z_RPNQuery(ODR o, Z_RPNQuery **p, int opt)
597 {
598     if (!odr_sequence_begin(o, p, sizeof(**p)))
599         return opt && odr_ok(o);
600     return
601         odr_oid(o, &(*p)->attributeSetId, 0) &&
602         z_RPNStructure(o, &(*p)->RPNStructure, 0) &&
603         odr_sequence_end(o);
604 }
605
606 /* -----------------------END RPN QUERY ----------------------- */
607
608 int z_Query(ODR o, Z_Query **p, int opt)
609 {
610     static Odr_arm arm[] = 
611     {
612         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Query_type_1, z_RPNQuery},
613         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_Query_type_2, odr_octetstring},
614         {-1, -1, -1, -1, 0}
615     };
616
617     if (o->direction == ODR_DECODE)
618         *p = odr_malloc(o, sizeof(**p));
619     else if (!*p)
620         return opt;
621     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
622         return 1;
623     *p = 0;
624     return opt && odr_ok(o);
625 }
626
627 int z_SearchRequest(ODR o, Z_SearchRequest **p, int opt)
628 {
629     Z_SearchRequest *pp;
630
631     if (!odr_sequence_begin(o, p, sizeof(**p)))
632         return opt && odr_ok(o);
633     pp = *p;
634     return
635         z_ReferenceId(o, &pp->referenceId, 1) &&
636         odr_implicit(o, odr_integer, &pp->smallSetUpperBound, ODR_CONTEXT,
637             13, 0) &&
638         odr_implicit(o, odr_integer, &pp->largeSetLowerBound, ODR_CONTEXT,
639             14, 0) &&
640         odr_implicit(o, odr_integer, &pp->mediumSetPresentNumber, ODR_CONTEXT,
641             15, 0) &&
642         odr_implicit(o, odr_bool, &pp->replaceIndicator, ODR_CONTEXT, 16, 1) &&
643         odr_implicit(o, odr_visiblestring, &pp->resultSetName, ODR_CONTEXT,
644             17, 9) &&
645         odr_implicit_settag(o, ODR_CONTEXT, 18) &&
646         odr_sequence_of(o, z_DatabaseName, &pp->databaseNames,
647             &pp->num_databaseNames) &&
648         odr_explicit(o, z_ElementSetNames, &pp->smallSetElementSetNames,
649             ODR_CONTEXT, 100, 1) &&
650         odr_explicit(o, z_ElementSetNames, &pp->mediumSetElementSetNames,
651             ODR_CONTEXT, 101, 1) &&
652         odr_implicit(o, z_PreferredRecordSyntax, &pp->preferredRecordSyntax,
653             ODR_CONTEXT, 104, 1) &&
654         odr_explicit(o, z_Query, &pp->query, ODR_CONTEXT, 21, 0) &&
655 #ifdef Z_OTHERINFO
656         odr_implicit(o, z_OtherInformation, &(*p)->additionalSearchInfo,
657             ODR_CONTEXT, 203, 1) &&
658         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
659 #endif
660         odr_sequence_end(o);
661 }
662
663 /* ------------------------ RECORD ------------------------- */
664
665 int z_DatabaseRecord(ODR o, Z_DatabaseRecord **p, int opt)
666 {
667     return odr_external(o, (Odr_external **) p, opt);
668 }
669
670 int z_DiagRec(ODR o, Z_DiagRec **p, int opt)
671 {
672     if (!odr_sequence_begin(o, p, sizeof(**p)))
673         return opt && odr_ok(o);
674     return
675         odr_oid(o, &(*p)->diagnosticSetId, 1) &&       /* SHOULD NOT BE OPT */
676         odr_integer(o, &(*p)->condition, 0) &&
677         (odr_visiblestring(o, &(*p)->addinfo, 0) ||
678         odr_implicit(o, odr_cstring, &(*p)->addinfo, ODR_CONTEXT, ODR_VISIBLESTRING, 1)) &&
679         odr_sequence_end(o);
680 }
681
682 int z_NamePlusRecord(ODR o, Z_NamePlusRecord **p, int opt)
683 {
684     static Odr_arm arm[] =
685     {
686         {ODR_EXPLICIT, ODR_CONTEXT, 1, Z_NamePlusRecord_databaseRecord,
687             z_DatabaseRecord},
688         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_NamePlusRecord_surrogateDiagnostic,
689             z_DiagRec},
690         {-1, -1, -1, -1, 0}
691     };
692
693     if (!odr_sequence_begin(o, p, sizeof(**p)))
694         return opt && odr_ok(o);
695     return
696         odr_implicit(o, z_DatabaseName, &(*p)->databaseName, ODR_CONTEXT,
697             0, 1) &&
698         odr_constructed_begin(o, &(*p)->u, ODR_CONTEXT, 1) &&
699         odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
700         odr_constructed_end(o) &&
701         odr_sequence_end(o);
702 }
703
704 int z_NamePlusRecordList(ODR o, Z_NamePlusRecordList **p, int opt)
705 {
706     if (o->direction == ODR_DECODE)
707         *p = odr_malloc(o, sizeof(**p));
708     if (odr_sequence_of(o, z_NamePlusRecord, &(*p)->records,
709         &(*p)->num_records))
710         return 1;
711     *p = 0;
712     return 0;
713 }
714
715 int z_Records(ODR o, Z_Records **p, int opt)
716 {
717     Odr_arm arm[] = 
718     {
719         {ODR_IMPLICIT, ODR_CONTEXT, 28, Z_Records_DBOSD, z_NamePlusRecordList},
720         {ODR_IMPLICIT, ODR_CONTEXT, 130, Z_Records_NSD, z_DiagRec},
721         {-1, -1, -1, -1, 0}
722     };
723
724     if (o->direction == ODR_DECODE)
725         *p = odr_malloc(o, sizeof(**p));
726     else if (!*p)
727         return opt;
728     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
729         return 1;
730     *p = 0;
731     return opt && odr_ok(o);
732 }
733
734 /* ------------------------ ACCESS CTRL SERVICE ----------------------- */
735
736 int z_AccessControlRequest(ODR o, Z_AccessControlRequest **p, int opt)
737 {
738     static Odr_arm arm[] = 
739     {
740         {ODR_IMPLICIT, ODR_CONTEXT, 37, Z_AccessRequest_simpleForm,
741             odr_octetstring},
742         {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_AccessRequest_externallyDefined,
743             odr_external},
744         {-1, -1, -1, -1, 0}
745     };
746     if (!odr_sequence_begin(o, p, sizeof(**p)))
747         return opt && odr_ok(o);
748     return
749         z_ReferenceId(o, &(*p)->referenceId, 1) &&
750         odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
751 #ifdef Z_OTHERINFO
752         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
753 #endif
754         odr_sequence_end(o);
755 }
756
757 int z_AccessControlResponse(ODR o, Z_AccessControlResponse **p, int opt)
758 {
759     static Odr_arm arm[] = 
760     {
761         {ODR_IMPLICIT, ODR_CONTEXT, 38, Z_AccessResponse_simpleForm,
762             odr_octetstring},
763         {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_AccessResponse_externallyDefined,
764             odr_external},
765         {-1, -1, -1, -1, 0}
766     };
767     if (!odr_sequence_begin(o, p, sizeof(**p)))
768         return opt && odr_ok(o);
769     return
770         z_ReferenceId(o, &(*p)->referenceId, 1) &&
771         odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
772         odr_explicit(o, z_DiagRec, &(*p)->diagnostic, ODR_CONTEXT, 223, 1) &&
773 #ifdef Z_OTHERINFO
774         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
775 #endif
776         odr_sequence_end(o);
777 }
778
779 /* ------------------------ SCAN SERVICE -------------------- */
780
781 int z_AttributeList(ODR o, Z_AttributeList **p, int opt)
782 {
783     if (o->direction == ODR_DECODE)
784         *p = odr_malloc(o, sizeof(**p));
785     else if (!*p)
786         return opt;
787
788     odr_implicit_settag(o, ODR_CONTEXT, 44);
789     if (odr_sequence_of(o, z_AttributeElement, &(*p)->attributes,
790         &(*p)->num_attributes))
791         return 1;
792     *p = 0;
793     return opt && odr_ok(o);
794 }
795
796 /*
797  * This is a temporary hack. We don't know just *what* old version of the
798  * protocol willow uses, so we'll just patiently wait for them to update
799  */
800 static int willow_scan = 0;
801
802 int z_WillowAttributesPlusTerm(ODR o, Z_AttributesPlusTerm **p, int opt)
803 {
804     if (!*p && o->direction != ODR_DECODE)
805         return opt;
806     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 4))
807     {
808         o->t_class = -1;
809         return opt && odr_ok(o);
810     }
811     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 1))
812         return 0;
813     if (!odr_constructed_begin(o, p, ODR_UNIVERSAL, ODR_SEQUENCE))
814         return 0;
815     if (!odr_implicit_settag(o, ODR_CONTEXT, 44))
816         return 0;
817     if (o->direction == ODR_DECODE)
818         *p = odr_malloc(o, sizeof(**p));
819     if (!odr_sequence_of(o, z_AttributeElement, &(*p)->attributeList,
820         &(*p)->num_attributes))
821         return 0;
822     if (!odr_sequence_end(o) || !odr_sequence_end(o))
823         return 0;
824     if (!z_Term(o, &(*p)->term, 0))
825         return 0;
826     if (!odr_constructed_end(o))
827         return 0;
828     willow_scan = 1;
829     return 1;
830 }
831
832 int z_AlternativeTerm(ODR o, Z_AlternativeTerm **p, int opt)
833 {
834     if (o->direction == ODR_DECODE)
835         *p = odr_malloc(o, sizeof(**p));
836     else if (!*p)
837     {
838         o->t_class = -1;
839         return opt && odr_ok(o);
840     }
841
842     if (odr_sequence_of(o, z_AttributesPlusTerm, &(*p)->terms,
843         &(*p)->num_terms))
844         return 1;
845     *p = 0;
846     return opt && !o->error;
847 }
848
849 int z_OccurrenceByAttributes(ODR o, Z_OccurrenceByAttributes **p, int opt)
850 {
851     if (!odr_sequence_begin(o, p, sizeof(**p)))
852         return opt && odr_ok(o);
853     return
854         odr_explicit(o, z_AttributeList, &(*p)->attributes, ODR_CONTEXT, 1, 1)&&
855         odr_explicit(o, odr_integer, &(*p)->global, ODR_CONTEXT, 2, 1) &&
856         odr_sequence_end(o);
857 }
858
859 int z_TermInfo(ODR o, Z_TermInfo **p, int opt)
860 {
861     if (!odr_sequence_begin(o, p, sizeof(**p)))
862         return opt && odr_ok(o);
863     return
864         (willow_scan ? 
865             odr_implicit(o, z_Term, &(*p)->term, ODR_CONTEXT, 1, 0) :
866             z_Term(o, &(*p)->term, 0)) &&
867         z_AttributeList(o, &(*p)->suggestedAttributes, 1) &&
868         odr_implicit(o, z_AlternativeTerm, &(*p)->alternativeTerm,
869             ODR_CONTEXT, 4, 1) &&
870         odr_implicit(o, odr_integer, &(*p)->globalOccurrences, ODR_CONTEXT,
871             2, 1) &&
872         odr_implicit(o, z_OccurrenceByAttributes, &(*p)->byAttributes,
873             ODR_CONTEXT, 3, 1) &&
874         odr_sequence_end(o);
875 }
876
877 int z_Entry(ODR o, Z_Entry **p, int opt)
878 {
879     static Odr_arm arm[] =
880     {
881         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Entry_termInfo, z_TermInfo},
882         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_Entry_surrogateDiagnostic,
883             z_DiagRec},
884         {-1, -1, -1, -1, 0}
885     };
886
887     if (o->direction == ODR_DECODE)
888         *p = odr_malloc(o, sizeof(**p));
889
890     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
891         return 1;
892     *p = 0;
893     return opt && odr_ok(o);
894 }
895
896 int z_Entries(ODR o, Z_Entries **p, int opt)
897 {
898     if (o->direction == ODR_DECODE)
899         *p = odr_malloc(o, sizeof(**p));
900     else if (!*p)
901         return opt;
902
903     if (odr_sequence_of(o, z_Entry, &(*p)->entries,
904         &(*p)->num_entries))
905         return 1;
906     *p = 0;
907     return 0;
908 }
909
910 int z_DiagRecs(ODR o, Z_DiagRecs **p, int opt)
911 {
912     if (o->direction == ODR_DECODE)
913         *p = odr_malloc(o, sizeof(**p));
914     else if (!*p)
915         return opt;
916
917         if (odr_sequence_of(o, z_DiagRec, &(*p)->diagRecs,
918         &(*p)->num_diagRecs))
919         return 1;
920     *p = 0;
921     return 0;
922 }
923
924 int z_ListEntries(ODR o, Z_ListEntries **p, int opt)
925 {
926     static Odr_arm arm[] =
927     {
928         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ListEntries_entries, z_Entries},
929         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_ListEntries_nonSurrogateDiagnostics,
930             z_DiagRecs},
931         {-1, -1, -1, -1, 0}
932     };
933
934     if (o->direction == ODR_DECODE)
935         *p = odr_malloc(o, sizeof(**p));
936
937     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
938         return 1;
939     *p = 0;
940     return opt && odr_ok(o);
941 }
942
943 int z_ScanRequest(ODR o, Z_ScanRequest **p, int opt)
944 {
945     if (!odr_sequence_begin(o, p, sizeof(**p)))
946         return opt && odr_ok(o);
947     willow_scan = 0;
948     return
949         z_ReferenceId(o, &(*p)->referenceId, 1) &&
950         odr_implicit_settag(o, ODR_CONTEXT, 3) &&
951         odr_sequence_of(o, z_DatabaseName, &(*p)->databaseNames,
952             &(*p)->num_databaseNames) &&
953         odr_oid(o, &(*p)->attributeSet, 1) &&
954         (z_AttributesPlusTerm(o, &(*p)->termListAndStartPoint, 1) ?
955             ((*p)->termListAndStartPoint ? 1 : 
956         z_WillowAttributesPlusTerm(o, &(*p)->termListAndStartPoint, 0)) : 0) &&
957         odr_implicit(o, odr_integer, &(*p)->stepSize, ODR_CONTEXT, 5, 1) &&
958         odr_implicit(o, odr_integer, &(*p)->numberOfTermsRequested,
959             ODR_CONTEXT, 6, 0) &&
960         odr_implicit(o, odr_integer, &(*p)->preferredPositionInResponse,
961             ODR_CONTEXT, 7, 1) &&
962         odr_sequence_end(o);
963 }
964
965 int z_ScanResponse(ODR o, Z_ScanResponse **p, int opt)
966 {
967     if (!odr_sequence_begin(o, p, sizeof(**p)))
968         return opt && odr_ok(o);
969     return
970         z_ReferenceId(o, &(*p)->referenceId, 1) &&
971         odr_implicit(o, odr_integer, &(*p)->stepSize, ODR_CONTEXT, 3, 1) &&
972         odr_implicit(o, odr_integer, &(*p)->scanStatus, ODR_CONTEXT, 4, 0) &&
973         odr_implicit(o, odr_integer, &(*p)->numberOfEntriesReturned,
974             ODR_CONTEXT, 5, 0) &&
975         odr_implicit(o, odr_integer, &(*p)->positionOfTerm, ODR_CONTEXT, 6, 1)&&
976         odr_explicit(o, z_ListEntries, &(*p)->entries, ODR_CONTEXT, 7, 1) &&
977         odr_implicit(o, odr_oid, &(*p)->attributeSet, ODR_CONTEXT, 8, 1) &&
978         odr_sequence_end(o);
979 }
980
981 /* ------------------------ SEARCHRESPONSE ----------------*/
982
983 int z_NumberOfRecordsReturned(ODR o, int **p, int opt)
984 {
985     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 24, opt);
986 }
987
988 int z_NextResultSetPosition(ODR o, int **p, int opt)
989 {
990     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 25, opt);
991 }
992
993 int z_PresentStatus(ODR o, int **p, int opt)
994 {
995     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 27, opt);
996 }
997
998 int z_SearchResponse(ODR o, Z_SearchResponse **p, int opt)
999 {
1000     Z_SearchResponse *pp;
1001
1002     if (!odr_sequence_begin(o, p, sizeof(**p)))
1003         return opt && odr_ok(o);
1004     pp = *p;
1005     return
1006         z_ReferenceId(o, &pp->referenceId, 1) &&
1007         odr_implicit(o, odr_integer, &pp->resultCount, ODR_CONTEXT, 23, 0) &&
1008         z_NumberOfRecordsReturned(o, &pp->numberOfRecordsReturned, 0) &&
1009         z_NextResultSetPosition(o, &pp->nextResultSetPosition, 0) &&
1010         odr_implicit(o, odr_bool, &pp->searchStatus, ODR_CONTEXT, 22, 0) &&
1011         odr_implicit(o, odr_integer, &pp->resultSetStatus, ODR_CONTEXT, 26, 1) &&
1012         z_PresentStatus(o, &pp->presentStatus, 1) &&
1013         z_Records(o, &pp->records, 1) &&
1014 #ifdef Z_OTHERINFO
1015         odr_implicit(o, z_OtherInformation, &(*p)->additionalSearchInfo,
1016             ODR_CONTEXT, 203, 1) &&
1017         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
1018 #endif
1019         odr_sequence_end(o);
1020 }
1021
1022 /* --------------------- PRESENT SERVICE ---------------------- */
1023
1024 int z_PresentRequest(ODR o, Z_PresentRequest **p, int opt)
1025 {
1026     Z_PresentRequest *pp;
1027
1028     if (!odr_sequence_begin(o, p, sizeof(**p)))
1029         return opt && odr_ok(o);
1030     pp = *p;
1031     return
1032         z_ReferenceId(o, &pp->referenceId, 1) &&
1033         z_ResultSetId(o, &pp->resultSetId, 0) &&
1034         odr_implicit(o, odr_integer, &pp->resultSetStartPoint, ODR_CONTEXT,
1035             30, 0) &&
1036         odr_implicit(o, odr_integer, &pp->numberOfRecordsRequested, ODR_CONTEXT,
1037             29, 0) &&
1038         z_ElementSetNames(o, &pp->elementSetNames, 1) &&
1039         z_PreferredRecordSyntax(o, &pp->preferredRecordSyntax, 1) &&
1040         odr_sequence_end(o);
1041 }
1042
1043 int z_PresentResponse(ODR o, Z_PresentResponse **p, int opt)
1044 {
1045     Z_PresentResponse *pp;
1046
1047     if (!odr_sequence_begin(o, p, sizeof(**p)))
1048         return opt && odr_ok(o);
1049     pp = *p;
1050     return
1051         z_ReferenceId(o, &pp->referenceId, 1) &&
1052         z_NumberOfRecordsReturned(o, &pp->numberOfRecordsReturned, 0) &&
1053         z_NextResultSetPosition(o, &pp->nextResultSetPosition, 0) &&
1054         z_PresentStatus(o, &pp->presentStatus, 0) &&
1055         z_Records(o, &pp->records, 1) &&
1056         odr_sequence_end(o);
1057 }
1058
1059 /* ----------------------DELETE -------------------------- */
1060
1061 int z_DeleteSetStatus(ODR o, int **p, int opt)
1062 {
1063     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 33, opt);
1064 }
1065
1066 int z_ListStatus(ODR o, Z_ListStatus **p, int opt)
1067 {
1068     if (!odr_sequence_begin(o, p, sizeof(**p)))
1069         return opt && odr_ok(o);
1070     return
1071         z_ResultSetId(o, &(*p)->id, 0) &&
1072         z_DeleteSetStatus(o, &(*p)->status, 0) &&
1073         odr_sequence_end(o);
1074 }
1075
1076 int z_DeleteResultSetRequest(ODR o, Z_DeleteResultSetRequest **p, int opt)
1077 {
1078     if (!odr_sequence_begin(o, p, sizeof(**p)))
1079         return opt && odr_ok(o);
1080     return
1081         z_ReferenceId(o, &(*p)->referenceId, 1) &&
1082         odr_implicit(o, odr_integer, &(*p)->deleteFunction, ODR_CONTEXT, 32,
1083             0) &&
1084         (odr_sequence_of(o, z_ListStatus, &(*p)->resultSetList,
1085             &(*p)->num_ids) || odr_ok(o)) &&
1086 #ifdef Z_OTHERINFO
1087         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
1088 #endif
1089         odr_sequence_end(o);
1090 }
1091
1092 int z_DeleteResultSetResponse(ODR o, Z_DeleteResultSetResponse **p, int opt)
1093 {
1094     if (!odr_sequence_begin(o, p, sizeof(**p)))
1095         return opt && odr_ok(o);
1096     return
1097         z_ReferenceId(o, &(*p)->referenceId, 1) &&
1098         odr_implicit(o, z_DeleteSetStatus, &(*p)->deleteOperationStatus,
1099             ODR_CONTEXT, 0, 1) &&
1100         odr_implicit_settag(o, ODR_CONTEXT, 1) &&
1101         (odr_sequence_of(o, z_ListStatus, &(*p)->deleteListStatuses,
1102             &(*p)->num_statuses) || odr_ok(o)) &&
1103         odr_implicit(o, odr_integer, &(*p)->numberNotDeleted, ODR_CONTEXT,
1104             34, 1) &&
1105         odr_implicit_settag(o, ODR_CONTEXT, 35) &&
1106         (odr_sequence_of(o, z_ListStatus, &(*p)->bulkStatuses,
1107             &(*p)->num_bulkStatuses) || odr_ok(o)) &&
1108         odr_implicit(o, odr_visiblestring, &(*p)->deleteMessage, ODR_CONTEXT,
1109             36, 1) &&
1110 #ifdef Z_OTHERINFO
1111         z_OtherInformation(o, &(*p)->otherInfo, 1) &&
1112 #endif
1113         odr_sequence_end(o);
1114 }
1115
1116 /* ------------------------ APDU ------------------------- */
1117
1118 int z_APDU(ODR o, Z_APDU **p, int opt)
1119 {
1120     static Odr_arm arm[] =
1121     {
1122         {ODR_IMPLICIT, ODR_CONTEXT, 20, Z_APDU_initRequest, z_InitRequest},
1123         {ODR_IMPLICIT, ODR_CONTEXT, 21, Z_APDU_initResponse, z_InitResponse},
1124         {ODR_IMPLICIT, ODR_CONTEXT, 22, Z_APDU_searchRequest, z_SearchRequest},
1125         {ODR_IMPLICIT, ODR_CONTEXT, 23, Z_APDU_searchResponse,
1126             z_SearchResponse},
1127         {ODR_IMPLICIT, ODR_CONTEXT, 24, Z_APDU_presentRequest,
1128             z_PresentRequest},
1129         {ODR_IMPLICIT, ODR_CONTEXT, 25, Z_APDU_presentResponse,
1130             z_PresentResponse},
1131         {ODR_IMPLICIT, ODR_CONTEXT, 26, Z_APDU_deleteResultSetRequest,
1132             z_DeleteResultSetRequest},
1133         {ODR_IMPLICIT, ODR_CONTEXT, 27, Z_APDU_deleteResultSetResponse,
1134             z_DeleteResultSetResponse},
1135         {ODR_IMPLICIT, ODR_CONTEXT, 30, Z_APDU_resourceControlRequest,
1136             z_ResourceControlRequest},
1137         {ODR_IMPLICIT, ODR_CONTEXT, 31, Z_APDU_resourceControlResponse,
1138             z_ResourceControlResponse},
1139         {ODR_IMPLICIT, ODR_CONTEXT, 32, Z_APDU_triggerResourceControlRequest,
1140             z_TriggerResourceControlRequest},
1141         {ODR_IMPLICIT, ODR_CONTEXT, 35, Z_APDU_scanRequest, z_ScanRequest},
1142         {ODR_IMPLICIT, ODR_CONTEXT, 36, Z_APDU_scanResponse, z_ScanResponse},
1143
1144         {-1, -1, -1, -1, 0}
1145     };
1146
1147     if (o->direction == ODR_DECODE)
1148         *p = odr_malloc(o, sizeof(**p));
1149     if (!odr_choice(o, arm, &(*p)->u, &(*p)->which))
1150     {
1151         if (o->direction == ODR_DECODE)
1152             *p = 0;
1153         return opt && odr_ok(o);
1154     }
1155     return 1;
1156 }