Check for config.h (currently not generated).
[yaz-moved-to-github.git] / odr / odr_cons.c
1 /*
2  * Copyright (c) 1995-2000, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Log: odr_cons.c,v $
6  * Revision 1.22  2000-02-29 13:44:55  adam
7  * Check for config.h (currently not generated).
8  *
9  * Revision 1.21  2000/01/31 13:15:21  adam
10  * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
11  * that some characters are not surrounded by spaces in resulting term.
12  * ILL-code updates.
13  *
14  * Revision 1.20  1999/11/30 13:47:11  adam
15  * Improved installation. Moved header files to include/yaz.
16  *
17  * Revision 1.19  1999/04/20 09:56:48  adam
18  * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
19  * Modified all encoders/decoders to reflect this change.
20  *
21  * Revision 1.18  1997/05/14 06:53:58  adam
22  * C++ support.
23  *
24  * Revision 1.17  1996/10/23 12:31:24  adam
25  * Added 'static' modifier to dummy variable in odr_constructed_begin.
26  *
27  * Revision 1.16  1996/07/26  13:38:20  quinn
28  * Various smaller things. Gathered header-files.
29  *
30  * Revision 1.15  1995/09/29  17:12:23  quinn
31  * Smallish
32  *
33  * Revision 1.14  1995/09/27  15:02:58  quinn
34  * Modified function heads & prototypes.
35  *
36  * Revision 1.13  1995/08/15  11:16:39  quinn
37  * Fixed pretty-printers.
38  *
39  * Revision 1.12  1995/06/19  12:38:47  quinn
40  * Added BER dumper.
41  *
42  * Revision 1.11  1995/05/16  08:50:53  quinn
43  * License, documentation, and memory fixes
44  *
45  * Revision 1.10  1995/04/18  08:15:21  quinn
46  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
47  * neater. We'll make the same change for decoding one day.
48  *
49  * Revision 1.9  1995/03/28  09:15:49  quinn
50  * Fixed bug in the printing mode
51  *
52  * Revision 1.8  1995/03/15  11:18:04  quinn
53  * Fixed serious bug in odr_cons
54  *
55  * Revision 1.7  1995/03/10  11:44:41  quinn
56  * Fixed serious stack-bug in odr_cons_begin
57  *
58  * Revision 1.6  1995/03/08  12:12:23  quinn
59  * Added better error checking.
60  *
61  * Revision 1.5  1995/02/10  18:57:25  quinn
62  * More in the way of error-checking.
63  *
64  * Revision 1.4  1995/02/10  15:55:29  quinn
65  * Bug fixes, mostly.
66  *
67  * Revision 1.3  1995/02/09  15:51:48  quinn
68  * Works better now.
69  *
70  * Revision 1.2  1995/02/07  17:52:59  quinn
71  * A damn mess, but now things work, I think.
72  *
73  * Revision 1.1  1995/02/02  16:21:53  quinn
74  * First kick.
75  *
76  */
77 #if HAVE_CONFIG_H
78 #include <config.h>
79 #endif
80
81 #include <yaz/odr.h>
82
83 void odr_setlenlen(ODR o, int len)
84 {
85     o->lenlen = len;
86 }
87
88 int odr_constructed_begin(ODR o, void *p, int zclass, int tag,
89                           const char *name)
90 {
91     int res;
92     int cons = 1;
93     int lenlen = o->lenlen;
94
95     if (o->error)
96         return 0;
97     o->lenlen = 1; /* reset lenlen */
98     if (o->t_class < 0)
99     {
100         o->t_class = zclass;
101         o->t_tag = tag;
102     }
103     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, 1)) < 0)
104         return 0;
105     if (!res || !cons)
106         return 0;
107
108     if (o->stackp == ODR_MAX_STACK - 1)
109     {
110         o->error = OSTACK;
111         return 0;
112     }
113     o->stack[++(o->stackp)].lenb = o->bp;
114     o->stack[o->stackp].len_offset = odr_tell(o);
115 #ifdef ODR_DEBUG
116     fprintf(stderr, "[cons_begin(%d)]", o->stackp);
117 #endif
118     if (o->direction == ODR_ENCODE)
119     {
120         static unsigned char dummy[sizeof(int)+1];
121
122         o->stack[o->stackp].lenlen = lenlen;
123
124         if (odr_write(o, dummy, lenlen) < 0) /* dummy */
125             return 0;
126     }
127     else if (o->direction == ODR_DECODE)
128     {
129         if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0)
130             return 0;
131         o->stack[o->stackp].lenlen = res;
132         o->bp += res;
133     }
134     else if (o->direction == ODR_PRINT)
135     {
136         odr_prname(o, name);
137         fprintf(o->print, "{\n");
138         o->indent++;
139     }
140     else
141     {
142         o->error = OOTHER;
143         return 0;
144     }
145     o->stack[o->stackp].base = o->bp;
146     o->stack[o->stackp].base_offset = odr_tell(o);
147     return 1;
148 }
149
150 int odr_constructed_more(ODR o)
151 {
152     if (o->error)
153         return 0;
154     if (o->stackp < 0)
155         return 0;
156     if (o->stack[o->stackp].len >= 0)
157         return o->bp - o->stack[o->stackp].base < o->stack[o->stackp].len;
158     else
159         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
160 }
161
162 int odr_constructed_end(ODR o)
163 {
164     int res;
165     int pos;
166
167     if (o->error)
168         return 0;
169     if (o->stackp < 0)
170     {
171         o->error = OOTHER;
172         return 0;
173     }
174     switch (o->direction)
175     {
176         case ODR_DECODE:
177             if (o->stack[o->stackp].len < 0)
178             {
179                 if (*o->bp++ == 0 && *(o->bp++) == 0)
180                 {
181                     o->stackp--;
182                     return 1;
183                 }
184                 else
185                 {
186                     o->error = OOTHER;
187                     return 0;
188                 }
189             }
190             else if (o->bp - o->stack[o->stackp].base !=
191                 o->stack[o->stackp].len)
192             {
193                 o->error = OCONLEN;
194                 return 0;
195             }
196             o->stackp--;
197             return 1;
198         case ODR_ENCODE:
199             pos = odr_tell(o);
200             odr_seek(o, ODR_S_SET, o->stack[o->stackp].len_offset);
201             if ((res = ber_enclen(o, pos - o->stack[o->stackp].base_offset,
202                 o->stack[o->stackp].lenlen, 1)) < 0)
203             {
204                 o->error = OLENOV;
205                 return 0;
206             }
207             odr_seek(o, ODR_S_END, 0);
208             if (res == 0)   /* indefinite encoding */
209             {
210 #ifdef ODR_DEBUG
211                 fprintf(stderr, "[cons_end(%d): indefinite]", o->stackp);
212 #endif
213                 if (odr_putc(o, 0) < 0 || odr_putc(o, 0) < 0)
214                     return 0;
215             }
216 #ifdef ODR_DEBUG
217             else
218             {
219                 fprintf(stderr, "[cons_end(%d): definite]", o->stackp);
220             }
221 #endif
222             o->stackp--;
223             return 1;
224         case ODR_PRINT:
225             o->stackp--;
226             o->indent--;
227             odr_prname(o, 0);
228             fprintf(o->print, "}\n");
229             return 1;
230         default:
231             o->error = OOTHER;
232             return 0;
233     }
234 }