~ubuntu-branches/ubuntu/wily/freerdp/wily-proposed

« back to all changes in this revision

Viewing changes to asn1/constr_CHOICE.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
3
 
 * All rights reserved.
4
 
 * Redistribution and modifications are permitted subject to BSD license.
5
 
 */
6
 
#include <asn_internal.h>
7
 
#include <constr_CHOICE.h>
8
 
#include <per_opentype.h>
9
 
 
10
 
/*
11
 
 * Number of bytes left for this structure.
12
 
 * (ctx->left) indicates the number of bytes _transferred_ for the structure.
13
 
 * (size) contains the number of bytes in the buffer passed.
14
 
 */
15
 
#define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
16
 
 
17
 
/*
18
 
 * If the subprocessor function returns with an indication that it wants
19
 
 * more data, it may well be a fatal decoding problem, because the
20
 
 * size is constrained by the <TLV>'s L, even if the buffer size allows
21
 
 * reading more data.
22
 
 * For example, consider the buffer containing the following TLVs:
23
 
 * <T:5><L:1><V> <T:6>...
24
 
 * The TLV length clearly indicates that one byte is expected in V, but
25
 
 * if the V processor returns with "want more data" even if the buffer
26
 
 * contains way more data than the V processor have seen.
27
 
 */
28
 
#define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)
29
 
 
30
 
/*
31
 
 * This macro "eats" the part of the buffer which is definitely "consumed",
32
 
 * i.e. was correctly converted into local representation or rightfully skipped.
33
 
 */
34
 
#undef  ADVANCE
35
 
#define ADVANCE(num_bytes)      do {            \
36
 
                size_t num = num_bytes;         \
37
 
                ptr = ((const char *)ptr) + num;\
38
 
                size -= num;                    \
39
 
                if(ctx->left >= 0)              \
40
 
                        ctx->left -= num;       \
41
 
                consumed_myself += num;         \
42
 
        } while(0)
43
 
 
44
 
/*
45
 
 * Switch to the next phase of parsing.
46
 
 */
47
 
#undef  NEXT_PHASE
48
 
#define NEXT_PHASE(ctx) do {                    \
49
 
                ctx->phase++;                   \
50
 
                ctx->step = 0;                  \
51
 
        } while(0)
52
 
 
53
 
/*
54
 
 * Return a standardized complex structure.
55
 
 */
56
 
#undef  RETURN
57
 
#define RETURN(_code)   do {                    \
58
 
                rval.code = _code;              \
59
 
                rval.consumed = consumed_myself;\
60
 
                return rval;                    \
61
 
        } while(0)
62
 
 
63
 
/*
64
 
 * See the definitions.
65
 
 */
66
 
static int _fetch_present_idx(const void *struct_ptr, int off, int size);
67
 
static void _set_present_idx(void *sptr, int offset, int size, int pres);
68
 
 
69
 
/*
70
 
 * Tags are canonically sorted in the tag to member table.
71
 
 */
72
 
static int
73
 
_search4tag(const void *ap, const void *bp) {
74
 
        const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
75
 
        const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
76
 
 
77
 
        int a_class = BER_TAG_CLASS(a->el_tag);
78
 
        int b_class = BER_TAG_CLASS(b->el_tag);
79
 
 
80
 
        if(a_class == b_class) {
81
 
                ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
82
 
                ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
83
 
 
84
 
                if(a_value == b_value)
85
 
                        return 0;
86
 
                else if(a_value < b_value)
87
 
                        return -1;
88
 
                else
89
 
                        return 1;
90
 
        } else if(a_class < b_class) {
91
 
                return -1;
92
 
        } else {
93
 
                return 1;
94
 
        }
95
 
}
96
 
 
97
 
/*
98
 
 * The decoder of the CHOICE type.
99
 
 */
100
 
asn_dec_rval_t
101
 
CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
102
 
        void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
103
 
        /*
104
 
         * Bring closer parts of structure description.
105
 
         */
106
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
107
 
        asn_TYPE_member_t *elements = td->elements;
108
 
 
109
 
        /*
110
 
         * Parts of the structure being constructed.
111
 
         */
112
 
        void *st = *struct_ptr; /* Target structure. */
113
 
        asn_struct_ctx_t *ctx;  /* Decoder context */
114
 
 
115
 
        ber_tlv_tag_t tlv_tag;  /* T from TLV */
116
 
        ssize_t tag_len;        /* Length of TLV's T */
117
 
        asn_dec_rval_t rval;    /* Return code from subparsers */
118
 
 
119
 
        ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
120
 
 
121
 
        ASN_DEBUG("Decoding %s as CHOICE", td->name);
122
 
 
123
 
        /*
124
 
         * Create the target structure if it is not present already.
125
 
         */
126
 
        if(st == 0) {
127
 
                st = *struct_ptr = CALLOC(1, specs->struct_size);
128
 
                if(st == 0) {
129
 
                        RETURN(RC_FAIL);
130
 
                }
131
 
        }
132
 
 
133
 
        /*
134
 
         * Restore parsing context.
135
 
         */
136
 
        ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
137
 
        
138
 
        /*
139
 
         * Start to parse where left previously
140
 
         */
141
 
        switch(ctx->phase) {
142
 
        case 0:
143
 
                /*
144
 
                 * PHASE 0.
145
 
                 * Check that the set of tags associated with given structure
146
 
                 * perfectly fits our expectations.
147
 
                 */
148
 
 
149
 
                if(tag_mode || td->tags_count) {
150
 
                        rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
151
 
                                tag_mode, -1, &ctx->left, 0);
152
 
                        if(rval.code != RC_OK) {
153
 
                                ASN_DEBUG("%s tagging check failed: %d",
154
 
                                        td->name, rval.code);
155
 
                                return rval;
156
 
                        }
157
 
 
158
 
                        if(ctx->left >= 0) {
159
 
                                /* ?Substracted below! */
160
 
                                ctx->left += rval.consumed;
161
 
                        }
162
 
                        ADVANCE(rval.consumed);
163
 
                } else {
164
 
                        ctx->left = -1;
165
 
                }
166
 
 
167
 
                NEXT_PHASE(ctx);
168
 
 
169
 
                ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
170
 
                        (long)ctx->left, (long)size);
171
 
 
172
 
                /* Fall through */
173
 
        case 1:
174
 
                /*
175
 
                 * Fetch the T from TLV.
176
 
                 */
177
 
                tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
178
 
                ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
179
 
                switch(tag_len) {
180
 
                case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
181
 
                        /* Fall through */
182
 
                case -1: RETURN(RC_FAIL);
183
 
                }
184
 
 
185
 
                do {
186
 
                        asn_TYPE_tag2member_t *t2m;
187
 
                        asn_TYPE_tag2member_t key;
188
 
 
189
 
                        key.el_tag = tlv_tag;
190
 
                        t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
191
 
                                        specs->tag2el, specs->tag2el_count,
192
 
                                        sizeof(specs->tag2el[0]), _search4tag);
193
 
                        if(t2m) {
194
 
                                /*
195
 
                                 * Found the element corresponding to the tag.
196
 
                                 */
197
 
                                NEXT_PHASE(ctx);
198
 
                                ctx->step = t2m->el_no;
199
 
                                break;
200
 
                        } else if(specs->ext_start == -1) {
201
 
                                ASN_DEBUG("Unexpected tag %s "
202
 
                                        "in non-extensible CHOICE %s",
203
 
                                        ber_tlv_tag_string(tlv_tag), td->name);
204
 
                                RETURN(RC_FAIL);
205
 
                        } else {
206
 
                                /* Skip this tag */
207
 
                                ssize_t skip;
208
 
 
209
 
                                ASN_DEBUG("Skipping unknown tag %s",
210
 
                                        ber_tlv_tag_string(tlv_tag));
211
 
 
212
 
                                skip = ber_skip_length(opt_codec_ctx,
213
 
                                        BER_TLV_CONSTRUCTED(ptr),
214
 
                                        (const char *)ptr + tag_len,
215
 
                                        LEFT - tag_len);
216
 
 
217
 
                                switch(skip) {
218
 
                                case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
219
 
                                        /* Fall through */
220
 
                                case -1: RETURN(RC_FAIL);
221
 
                                }
222
 
 
223
 
                                ADVANCE(skip + tag_len);
224
 
                                RETURN(RC_OK);
225
 
                        }
226
 
                } while(0);
227
 
 
228
 
        case 2:
229
 
                /*
230
 
                 * PHASE 2.
231
 
                 * Read in the element.
232
 
                 */
233
 
            do {
234
 
                asn_TYPE_member_t *elm;/* CHOICE's element */
235
 
                void *memb_ptr;         /* Pointer to the member */
236
 
                void **memb_ptr2;       /* Pointer to that pointer */
237
 
 
238
 
                elm = &elements[ctx->step];
239
 
 
240
 
                /*
241
 
                 * Compute the position of the member inside a structure,
242
 
                 * and also a type of containment (it may be contained
243
 
                 * as pointer or using inline inclusion).
244
 
                 */
245
 
                if(elm->flags & ATF_POINTER) {
246
 
                        /* Member is a pointer to another structure */
247
 
                        memb_ptr2 = (void **)((char *)st + elm->memb_offset);
248
 
                } else {
249
 
                        /*
250
 
                         * A pointer to a pointer
251
 
                         * holding the start of the structure
252
 
                         */
253
 
                        memb_ptr = (char *)st + elm->memb_offset;
254
 
                        memb_ptr2 = &memb_ptr;
255
 
                }
256
 
                /* Set presence to be able to free it properly at any time */
257
 
                _set_present_idx(st, specs->pres_offset,
258
 
                                specs->pres_size, ctx->step + 1);
259
 
                /*
260
 
                 * Invoke the member fetch routine according to member's type
261
 
                 */
262
 
                rval = elm->type->ber_decoder(opt_codec_ctx, elm->type,
263
 
                                memb_ptr2, ptr, LEFT, elm->tag_mode);
264
 
                switch(rval.code) {
265
 
                case RC_OK:
266
 
                        break;
267
 
                case RC_WMORE: /* More data expected */
268
 
                        if(!SIZE_VIOLATION) {
269
 
                                ADVANCE(rval.consumed);
270
 
                                RETURN(RC_WMORE);
271
 
                        }
272
 
                        RETURN(RC_FAIL);
273
 
                case RC_FAIL: /* Fatal error */
274
 
                        RETURN(rval.code);
275
 
                } /* switch(rval) */
276
 
                
277
 
                ADVANCE(rval.consumed);
278
 
          } while(0);
279
 
 
280
 
                NEXT_PHASE(ctx);
281
 
 
282
 
                /* Fall through */
283
 
        case 3:
284
 
                ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
285
 
                        td->name, (long)ctx->left, (long)size,
286
 
                        tag_mode, td->tags_count);
287
 
 
288
 
                if(ctx->left > 0) {
289
 
                        /*
290
 
                         * The type must be fully decoded
291
 
                         * by the CHOICE member-specific decoder.
292
 
                         */
293
 
                        RETURN(RC_FAIL);
294
 
                }
295
 
 
296
 
                if(ctx->left == -1
297
 
                && !(tag_mode || td->tags_count)) {
298
 
                        /*
299
 
                         * This is an untagged CHOICE.
300
 
                         * It doesn't contain nothing
301
 
                         * except for the member itself, including all its tags.
302
 
                         * The decoding is completed.
303
 
                         */
304
 
                        NEXT_PHASE(ctx);
305
 
                        break;
306
 
                }
307
 
 
308
 
                /*
309
 
                 * Read in the "end of data chunks"'s.
310
 
                 */
311
 
                while(ctx->left < 0) {
312
 
                        ssize_t tl;
313
 
 
314
 
                        tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
315
 
                        switch(tl) {
316
 
                        case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
317
 
                                /* Fall through */
318
 
                        case -1: RETURN(RC_FAIL);
319
 
                        }
320
 
 
321
 
                        /*
322
 
                         * Expected <0><0>...
323
 
                         */
324
 
                        if(((const uint8_t *)ptr)[0] == 0) {
325
 
                                if(LEFT < 2) {
326
 
                                        if(SIZE_VIOLATION)
327
 
                                                RETURN(RC_FAIL);
328
 
                                        else
329
 
                                                RETURN(RC_WMORE);
330
 
                                } else if(((const uint8_t *)ptr)[1] == 0) {
331
 
                                        /*
332
 
                                         * Correctly finished with <0><0>.
333
 
                                         */
334
 
                                        ADVANCE(2);
335
 
                                        ctx->left++;
336
 
                                        continue;
337
 
                                }
338
 
                        } else {
339
 
                                ASN_DEBUG("Unexpected continuation in %s",
340
 
                                        td->name);
341
 
                                RETURN(RC_FAIL);
342
 
                        }
343
 
 
344
 
                        /* UNREACHABLE */
345
 
                }
346
 
 
347
 
                NEXT_PHASE(ctx);
348
 
        case 4:
349
 
                /* No meaningful work here */
350
 
                break;
351
 
        }
352
 
        
353
 
        RETURN(RC_OK);
354
 
}
355
 
 
356
 
asn_enc_rval_t
357
 
CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
358
 
                int tag_mode, ber_tlv_tag_t tag,
359
 
                asn_app_consume_bytes_f *cb, void *app_key) {
360
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
361
 
        asn_TYPE_member_t *elm; /* CHOICE element */
362
 
        asn_enc_rval_t erval;
363
 
        void *memb_ptr;
364
 
        size_t computed_size = 0;
365
 
        int present;
366
 
 
367
 
        if(!sptr) _ASN_ENCODE_FAILED;
368
 
 
369
 
        ASN_DEBUG("%s %s as CHOICE",
370
 
                cb?"Encoding":"Estimating", td->name);
371
 
 
372
 
        present = _fetch_present_idx(sptr,
373
 
                specs->pres_offset, specs->pres_size);
374
 
 
375
 
        /*
376
 
         * If the structure was not initialized, it cannot be encoded:
377
 
         * can't deduce what to encode in the choice type.
378
 
         */
379
 
        if(present <= 0 || present > td->elements_count) {
380
 
                if(present == 0 && td->elements_count == 0) {
381
 
                        /* The CHOICE is empty?! */
382
 
                        erval.encoded = 0;
383
 
                        _ASN_ENCODED_OK(erval);
384
 
                }
385
 
                _ASN_ENCODE_FAILED;
386
 
        }
387
 
 
388
 
        /*
389
 
         * Seek over the present member of the structure.
390
 
         */
391
 
        elm = &td->elements[present-1];
392
 
        if(elm->flags & ATF_POINTER) {
393
 
                memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
394
 
                if(memb_ptr == 0) {
395
 
                        if(elm->optional) {
396
 
                                erval.encoded = 0;
397
 
                                _ASN_ENCODED_OK(erval);
398
 
                        }
399
 
                        /* Mandatory element absent */
400
 
                        _ASN_ENCODE_FAILED;
401
 
                }
402
 
        } else {
403
 
                memb_ptr = (void *)((char *)sptr + elm->memb_offset);
404
 
        }
405
 
 
406
 
        /*
407
 
         * If the CHOICE itself is tagged EXPLICIT:
408
 
         * T ::= [2] EXPLICIT CHOICE { ... }
409
 
         * Then emit the appropriate tags.
410
 
         */
411
 
        if(tag_mode == 1 || td->tags_count) {
412
 
                /*
413
 
                 * For this, we need to pre-compute the member.
414
 
                 */
415
 
                ssize_t ret;
416
 
 
417
 
                /* Encode member with its tag */
418
 
                erval = elm->type->der_encoder(elm->type, memb_ptr,
419
 
                        elm->tag_mode, elm->tag, 0, 0);
420
 
                if(erval.encoded == -1)
421
 
                        return erval;
422
 
 
423
 
                /* Encode CHOICE with parent or my own tag */
424
 
                ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
425
 
                        cb, app_key);
426
 
                if(ret == -1)
427
 
                        _ASN_ENCODE_FAILED;
428
 
                computed_size += ret;
429
 
        }
430
 
 
431
 
        /*
432
 
         * Encode the single underlying member.
433
 
         */
434
 
        erval = elm->type->der_encoder(elm->type, memb_ptr,
435
 
                elm->tag_mode, elm->tag, cb, app_key);
436
 
        if(erval.encoded == -1)
437
 
                return erval;
438
 
 
439
 
        ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
440
 
                (long)erval.encoded, (long)computed_size);
441
 
 
442
 
        erval.encoded += computed_size;
443
 
 
444
 
        return erval;
445
 
}
446
 
 
447
 
ber_tlv_tag_t
448
 
CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
449
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
450
 
        int present;
451
 
 
452
 
        assert(tag_mode == 0); (void)tag_mode;
453
 
        assert(tag == 0); (void)tag;
454
 
 
455
 
        /*
456
 
         * Figure out which CHOICE element is encoded.
457
 
         */
458
 
        present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
459
 
 
460
 
        if(present > 0 || present <= td->elements_count) {
461
 
                asn_TYPE_member_t *elm = &td->elements[present-1];
462
 
                const void *memb_ptr;
463
 
 
464
 
                if(elm->flags & ATF_POINTER) {
465
 
                        memb_ptr = *(const void * const *)
466
 
                                        ((const char *)ptr + elm->memb_offset);
467
 
                } else {
468
 
                        memb_ptr = (const void *)
469
 
                                        ((const char *)ptr + elm->memb_offset);
470
 
                }
471
 
 
472
 
                return asn_TYPE_outmost_tag(elm->type, memb_ptr,
473
 
                        elm->tag_mode, elm->tag);
474
 
        } else {
475
 
                return (ber_tlv_tag_t)-1;
476
 
        }
477
 
}
478
 
 
479
 
int
480
 
CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
481
 
                asn_app_constraint_failed_f *ctfailcb, void *app_key) {
482
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
483
 
        int present;
484
 
 
485
 
        if(!sptr) {
486
 
                _ASN_CTFAIL(app_key, td, sptr,
487
 
                        "%s: value not given (%s:%d)",
488
 
                        td->name, __FILE__, __LINE__);
489
 
                return -1;
490
 
        }
491
 
 
492
 
        /*
493
 
         * Figure out which CHOICE element is encoded.
494
 
         */
495
 
        present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
496
 
        if(present > 0 && present <= td->elements_count) {
497
 
                asn_TYPE_member_t *elm = &td->elements[present-1];
498
 
                const void *memb_ptr;
499
 
 
500
 
                if(elm->flags & ATF_POINTER) {
501
 
                        memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
502
 
                        if(!memb_ptr) {
503
 
                                if(elm->optional)
504
 
                                        return 0;
505
 
                                _ASN_CTFAIL(app_key, td, sptr,
506
 
                                        "%s: mandatory CHOICE element %s absent (%s:%d)",
507
 
                                        td->name, elm->name, __FILE__, __LINE__);
508
 
                                return -1;
509
 
                        }
510
 
                } else {
511
 
                        memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
512
 
                }
513
 
 
514
 
                if(elm->memb_constraints) {
515
 
                        return elm->memb_constraints(elm->type, memb_ptr,
516
 
                                ctfailcb, app_key);
517
 
                } else {
518
 
                        int ret = elm->type->check_constraints(elm->type,
519
 
                                        memb_ptr, ctfailcb, app_key);
520
 
                        /*
521
 
                         * Cannot inherit it eralier:
522
 
                         * need to make sure we get the updated version.
523
 
                         */
524
 
                        elm->memb_constraints = elm->type->check_constraints;
525
 
                        return ret;
526
 
                }
527
 
        } else {
528
 
                _ASN_CTFAIL(app_key, td, sptr,
529
 
                        "%s: no CHOICE element given (%s:%d)",
530
 
                        td->name, __FILE__, __LINE__);
531
 
                return -1;
532
 
        }
533
 
}
534
 
 
535
 
#undef  XER_ADVANCE
536
 
#define XER_ADVANCE(num_bytes)  do {                    \
537
 
                size_t num = num_bytes;                 \
538
 
                buf_ptr = ((const char *)buf_ptr) + num;\
539
 
                size -= num;                            \
540
 
                consumed_myself += num;                 \
541
 
        } while(0)
542
 
 
543
 
/*
544
 
 * Decode the XER (XML) data.
545
 
 */
546
 
asn_dec_rval_t
547
 
CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
548
 
        void **struct_ptr, const char *opt_mname,
549
 
                const void *buf_ptr, size_t size) {
550
 
        /*
551
 
         * Bring closer parts of structure description.
552
 
         */
553
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
554
 
        const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
555
 
 
556
 
        /*
557
 
         * Parts of the structure being constructed.
558
 
         */
559
 
        void *st = *struct_ptr; /* Target structure. */
560
 
        asn_struct_ctx_t *ctx;  /* Decoder context */
561
 
 
562
 
        asn_dec_rval_t rval;            /* Return value of a decoder */
563
 
        ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
564
 
        int edx;                        /* Element index */
565
 
 
566
 
        /*
567
 
         * Create the target structure if it is not present already.
568
 
         */
569
 
        if(st == 0) {
570
 
                st = *struct_ptr = CALLOC(1, specs->struct_size);
571
 
                if(st == 0) RETURN(RC_FAIL);
572
 
        }
573
 
 
574
 
        /*
575
 
         * Restore parsing context.
576
 
         */
577
 
        ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
578
 
        if(ctx->phase == 0 && !*xml_tag)
579
 
                ctx->phase = 1; /* Skip the outer tag checking phase */
580
 
 
581
 
        /*
582
 
         * Phases of XER/XML processing:
583
 
         * Phase 0: Check that the opening tag matches our expectations.
584
 
         * Phase 1: Processing body and reacting on closing tag.
585
 
         * Phase 2: Processing inner type.
586
 
         * Phase 3: Only waiting for closing tag.
587
 
         * Phase 4: Skipping unknown extensions.
588
 
         * Phase 5: PHASED OUT
589
 
         */
590
 
        for(edx = ctx->step; ctx->phase <= 4;) {
591
 
                pxer_chunk_type_e ch_type;      /* XER chunk type */
592
 
                ssize_t ch_size;                /* Chunk size */
593
 
                xer_check_tag_e tcv;            /* Tag check value */
594
 
                asn_TYPE_member_t *elm;
595
 
 
596
 
                /*
597
 
                 * Go inside the member.
598
 
                 */
599
 
                if(ctx->phase == 2) {
600
 
                        asn_dec_rval_t tmprval;
601
 
                        void *memb_ptr;         /* Pointer to the member */
602
 
                        void **memb_ptr2;       /* Pointer to that pointer */
603
 
 
604
 
                        elm = &td->elements[edx];
605
 
 
606
 
                        if(elm->flags & ATF_POINTER) {
607
 
                                /* Member is a pointer to another structure */
608
 
                                memb_ptr2 = (void **)((char *)st
609
 
                                        + elm->memb_offset);
610
 
                        } else {
611
 
                                memb_ptr = (char *)st + elm->memb_offset;
612
 
                                memb_ptr2 = &memb_ptr;
613
 
                        }
614
 
 
615
 
                        /* Start/Continue decoding the inner member */
616
 
                        tmprval = elm->type->xer_decoder(opt_codec_ctx,
617
 
                                        elm->type, memb_ptr2, elm->name,
618
 
                                        buf_ptr, size);
619
 
                        XER_ADVANCE(tmprval.consumed);
620
 
                        ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
621
 
                                elm->type->name, tmprval.code);
622
 
                        if(tmprval.code != RC_OK)
623
 
                                RETURN(tmprval.code);
624
 
                        assert(_fetch_present_idx(st,
625
 
                                specs->pres_offset, specs->pres_size) == 0);
626
 
                        /* Record what we've got */
627
 
                        _set_present_idx(st,
628
 
                                specs->pres_offset, specs->pres_size, edx + 1);
629
 
                        ctx->phase = 3;
630
 
                        /* Fall through */
631
 
                }
632
 
 
633
 
                /* No need to wait for closing tag; special mode. */
634
 
                if(ctx->phase == 3 && !*xml_tag) {
635
 
                        ctx->phase = 5; /* Phase out */
636
 
                        RETURN(RC_OK);
637
 
                }
638
 
 
639
 
                /*
640
 
                 * Get the next part of the XML stream.
641
 
                 */
642
 
                ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
643
 
                switch(ch_size) {
644
 
                case -1: RETURN(RC_FAIL);
645
 
                case 0:  RETURN(RC_WMORE);
646
 
                default:
647
 
                        switch(ch_type) {
648
 
                        case PXER_COMMENT:      /* Got XML comment */
649
 
                        case PXER_TEXT:         /* Ignore free-standing text */
650
 
                                XER_ADVANCE(ch_size);   /* Skip silently */
651
 
                                continue;
652
 
                        case PXER_TAG:
653
 
                                break;  /* Check the rest down there */
654
 
                        }
655
 
                }
656
 
 
657
 
                tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
658
 
                ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
659
 
                        ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
660
 
                        ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
661
 
                        ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
662
 
                        ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
663
 
                xml_tag, tcv);
664
 
 
665
 
                /* Skip the extensions section */
666
 
                if(ctx->phase == 4) {
667
 
                        ASN_DEBUG("skip_unknown(%d, %ld)",
668
 
                                tcv, (long)ctx->left);
669
 
                        switch(xer_skip_unknown(tcv, &ctx->left)) {
670
 
                        case -1:
671
 
                                ctx->phase = 5;
672
 
                                RETURN(RC_FAIL);
673
 
                                continue;
674
 
                        case 1:
675
 
                                ctx->phase = 3;
676
 
                                /* Fall through */
677
 
                        case 0:
678
 
                                XER_ADVANCE(ch_size);
679
 
                                continue;
680
 
                        case 2:
681
 
                                ctx->phase = 3;
682
 
                                break;
683
 
                        }
684
 
                }
685
 
 
686
 
                switch(tcv) {
687
 
                case XCT_BOTH:
688
 
                        break;  /* No CHOICE? */
689
 
                case XCT_CLOSING:
690
 
                        if(ctx->phase != 3)
691
 
                                break;
692
 
                        XER_ADVANCE(ch_size);
693
 
                        ctx->phase = 5; /* Phase out */
694
 
                        RETURN(RC_OK);
695
 
                case XCT_OPENING:
696
 
                        if(ctx->phase == 0) {
697
 
                                XER_ADVANCE(ch_size);
698
 
                                ctx->phase = 1; /* Processing body phase */
699
 
                                continue;
700
 
                        }
701
 
                        /* Fall through */
702
 
                case XCT_UNKNOWN_OP:
703
 
                case XCT_UNKNOWN_BO:
704
 
 
705
 
                        if(ctx->phase != 1)
706
 
                                break;  /* Really unexpected */
707
 
 
708
 
                        /*
709
 
                         * Search which inner member corresponds to this tag.
710
 
                         */
711
 
                        for(edx = 0; edx < td->elements_count; edx++) {
712
 
                                elm = &td->elements[edx];
713
 
                                tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
714
 
                                switch(tcv) {
715
 
                                case XCT_BOTH:
716
 
                                case XCT_OPENING:
717
 
                                        /*
718
 
                                         * Process this member.
719
 
                                         */
720
 
                                        ctx->step = edx;
721
 
                                        ctx->phase = 2;
722
 
                                        break;
723
 
                                case XCT_UNKNOWN_OP:
724
 
                                case XCT_UNKNOWN_BO:
725
 
                                        continue;
726
 
                                default:
727
 
                                        edx = td->elements_count;
728
 
                                        break;  /* Phase out */
729
 
                                }
730
 
                                break;
731
 
                        }
732
 
                        if(edx != td->elements_count)
733
 
                                continue;
734
 
 
735
 
                        /* It is expected extension */
736
 
                        if(specs->ext_start != -1) {
737
 
                                ASN_DEBUG("Got anticipated extension");
738
 
                                /*
739
 
                                 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
740
 
                                 * By using a mask. Only record a pure
741
 
                                 * <opening> tags.
742
 
                                 */
743
 
                                if(tcv & XCT_CLOSING) {
744
 
                                        /* Found </extension> without body */
745
 
                                        ctx->phase = 3; /* Terminating */
746
 
                                } else {
747
 
                                        ctx->left = 1;
748
 
                                        ctx->phase = 4; /* Skip ...'s */
749
 
                                }
750
 
                                XER_ADVANCE(ch_size);
751
 
                                continue;
752
 
                        }
753
 
 
754
 
                        /* Fall through */
755
 
                default:
756
 
                        break;
757
 
                }
758
 
 
759
 
                ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
760
 
                        " (ph=%d, tag=%s)",
761
 
                        ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
762
 
                        ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
763
 
                        ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
764
 
                        ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
765
 
                        td->name, ctx->phase, xml_tag);
766
 
                break;
767
 
        }
768
 
 
769
 
        ctx->phase = 5; /* Phase out, just in case */
770
 
        RETURN(RC_FAIL);
771
 
}
772
 
 
773
 
 
774
 
asn_enc_rval_t
775
 
CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
776
 
        int ilevel, enum xer_encoder_flags_e flags,
777
 
                asn_app_consume_bytes_f *cb, void *app_key) {
778
 
        asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
779
 
        asn_enc_rval_t er;
780
 
        int present;
781
 
 
782
 
        if(!sptr)
783
 
                _ASN_ENCODE_FAILED;
784
 
 
785
 
        /*
786
 
         * Figure out which CHOICE element is encoded.
787
 
         */
788
 
        present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
789
 
 
790
 
        if(present <= 0 || present > td->elements_count) {
791
 
                _ASN_ENCODE_FAILED;
792
 
        }  else {
793
 
                asn_enc_rval_t tmper;
794
 
                asn_TYPE_member_t *elm = &td->elements[present-1];
795
 
                void *memb_ptr;
796
 
                const char *mname = elm->name;
797
 
                unsigned int mlen = strlen(mname);
798
 
 
799
 
                if(elm->flags & ATF_POINTER) {
800
 
                        memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
801
 
                        if(!memb_ptr) _ASN_ENCODE_FAILED;
802
 
                } else {
803
 
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
804
 
                }
805
 
 
806
 
                er.encoded = 0;
807
 
 
808
 
                if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel);
809
 
                _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
810
 
 
811
 
                tmper = elm->type->xer_encoder(elm->type, memb_ptr,
812
 
                                ilevel + 1, flags, cb, app_key);
813
 
                if(tmper.encoded == -1) return tmper;
814
 
 
815
 
                _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
816
 
 
817
 
                er.encoded += 5 + (2 * mlen) + tmper.encoded;
818
 
        }
819
 
 
820
 
        if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel - 1);
821
 
 
822
 
        _ASN_ENCODED_OK(er);
823
 
cb_failed:
824
 
        _ASN_ENCODE_FAILED;
825
 
}
826
 
 
827
 
asn_dec_rval_t
828
 
CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
829
 
        asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
830
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
831
 
        asn_dec_rval_t rv;
832
 
        asn_per_constraint_t *ct;
833
 
        asn_TYPE_member_t *elm; /* CHOICE's element */
834
 
        void *memb_ptr;
835
 
        void **memb_ptr2;
836
 
        void *st = *sptr;
837
 
        int value;
838
 
 
839
 
        if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
840
 
                _ASN_DECODE_FAILED;
841
 
 
842
 
        /*
843
 
         * Create the target structure if it is not present already.
844
 
         */
845
 
        if(!st) {
846
 
                st = *sptr = CALLOC(1, specs->struct_size);
847
 
                if(!st) _ASN_DECODE_FAILED;
848
 
        }
849
 
 
850
 
        if(constraints) ct = &constraints->value;
851
 
        else if(td->per_constraints) ct = &td->per_constraints->value;
852
 
        else ct = 0;
853
 
 
854
 
        if(ct && ct->flags & APC_EXTENSIBLE) {
855
 
                value = per_get_few_bits(pd, 1);
856
 
                if(value < 0) _ASN_DECODE_STARVED;
857
 
                if(value) ct = 0;       /* Not restricted */
858
 
        }
859
 
 
860
 
        if(ct && ct->range_bits >= 0) {
861
 
                value = per_get_few_bits(pd, ct->range_bits);
862
 
                if(value < 0) _ASN_DECODE_STARVED;
863
 
                ASN_DEBUG("CHOICE %s got index %d in range %d",
864
 
                        td->name, value, ct->range_bits);
865
 
                if(value > ct->upper_bound)
866
 
                        _ASN_DECODE_FAILED;
867
 
        } else {
868
 
                if(specs->ext_start == -1)
869
 
                        _ASN_DECODE_FAILED;
870
 
                value = uper_get_nsnnwn(pd);
871
 
                if(value < 0) _ASN_DECODE_STARVED;
872
 
                value += specs->ext_start;
873
 
                if(value >= td->elements_count)
874
 
                        _ASN_DECODE_FAILED;
875
 
        }
876
 
 
877
 
        /* Adjust if canonical order is different from natural order */
878
 
        if(specs->canonical_order)
879
 
                value = specs->canonical_order[value];
880
 
 
881
 
        /* Set presence to be able to free it later */
882
 
        _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
883
 
 
884
 
        elm = &td->elements[value];
885
 
        if(elm->flags & ATF_POINTER) {
886
 
                /* Member is a pointer to another structure */
887
 
                memb_ptr2 = (void **)((char *)st + elm->memb_offset);
888
 
        } else {
889
 
                memb_ptr = (char *)st + elm->memb_offset;
890
 
                memb_ptr2 = &memb_ptr;
891
 
        }
892
 
        ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
893
 
 
894
 
        if(ct && ct->range_bits >= 0) {
895
 
                rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
896
 
                        elm->per_constraints, memb_ptr2, pd);
897
 
        } else {
898
 
                rv = uper_open_type_get(opt_codec_ctx, elm->type,
899
 
                        elm->per_constraints, memb_ptr2, pd);
900
 
        }
901
 
 
902
 
        if(rv.code != RC_OK)
903
 
                ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
904
 
                        elm->name, td->name, rv.code);
905
 
        return rv;
906
 
}
907
 
   
908
 
asn_enc_rval_t
909
 
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
910
 
        asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
911
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
912
 
        asn_TYPE_member_t *elm; /* CHOICE's element */
913
 
        asn_per_constraint_t *ct;
914
 
        void *memb_ptr;
915
 
        int present;
916
 
 
917
 
        if(!sptr) _ASN_ENCODE_FAILED;
918
 
 
919
 
        ASN_DEBUG("Encoding %s as CHOICE", td->name);
920
 
 
921
 
        if(constraints) ct = &constraints->value;
922
 
        else if(td->per_constraints) ct = &td->per_constraints->value;
923
 
        else ct = 0;
924
 
 
925
 
        present = _fetch_present_idx(sptr,
926
 
                specs->pres_offset, specs->pres_size);
927
 
 
928
 
        /*
929
 
         * If the structure was not initialized properly, it cannot be encoded:
930
 
         * can't deduce what to encode in the choice type.
931
 
         */
932
 
        if(present <= 0 || present > td->elements_count)
933
 
                _ASN_ENCODE_FAILED;
934
 
        else
935
 
                present--;
936
 
 
937
 
        /* Adjust if canonical order is different from natural order */
938
 
        if(specs->canonical_order)
939
 
                present = specs->canonical_order[present];
940
 
 
941
 
        ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
942
 
 
943
 
        if(ct && ct->range_bits >= 0) {
944
 
                if(present < ct->lower_bound
945
 
                || present > ct->upper_bound) {
946
 
                        if(ct->flags & APC_EXTENSIBLE) {
947
 
                                if(per_put_few_bits(po, 1, 1))
948
 
                                        _ASN_ENCODE_FAILED;
949
 
                        } else {
950
 
                                _ASN_ENCODE_FAILED;
951
 
                        }
952
 
                        ct = 0;
953
 
                }
954
 
        }
955
 
        if(ct && ct->flags & APC_EXTENSIBLE)
956
 
                if(per_put_few_bits(po, 0, 1))
957
 
                        _ASN_ENCODE_FAILED;
958
 
 
959
 
        elm = &td->elements[present];
960
 
        if(elm->flags & ATF_POINTER) {
961
 
                /* Member is a pointer to another structure */
962
 
                memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
963
 
                if(!memb_ptr) _ASN_ENCODE_FAILED;
964
 
        } else {
965
 
                memb_ptr = (char *)sptr + elm->memb_offset;
966
 
        }
967
 
 
968
 
        if(ct && ct->range_bits >= 0) {
969
 
                if(per_put_few_bits(po, present, ct->range_bits))
970
 
                        _ASN_ENCODE_FAILED;
971
 
 
972
 
                return elm->type->uper_encoder(elm->type, elm->per_constraints,
973
 
                        memb_ptr, po);
974
 
        } else {
975
 
                asn_enc_rval_t rval;
976
 
                if(specs->ext_start == -1)
977
 
                        _ASN_ENCODE_FAILED;
978
 
                if(uper_put_nsnnwn(po, present - specs->ext_start))
979
 
                        _ASN_ENCODE_FAILED;
980
 
                if(uper_open_type_put(elm->type, elm->per_constraints,
981
 
                        memb_ptr, po))
982
 
                        _ASN_ENCODE_FAILED;
983
 
                rval.encoded = 0;
984
 
                _ASN_ENCODED_OK(rval);
985
 
        }
986
 
}
987
 
   
988
 
 
989
 
int
990
 
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
991
 
                asn_app_consume_bytes_f *cb, void *app_key) {
992
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
993
 
        int present;
994
 
 
995
 
        if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
996
 
 
997
 
        /*
998
 
         * Figure out which CHOICE element is encoded.
999
 
         */
1000
 
        present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
1001
 
 
1002
 
        /*
1003
 
         * Print that element.
1004
 
         */
1005
 
        if(present > 0 && present <= td->elements_count) {
1006
 
                asn_TYPE_member_t *elm = &td->elements[present-1];
1007
 
                const void *memb_ptr;
1008
 
 
1009
 
                if(elm->flags & ATF_POINTER) {
1010
 
                        memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
1011
 
                        if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
1012
 
                } else {
1013
 
                        memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
1014
 
                }
1015
 
 
1016
 
                /* Print member's name and stuff */
1017
 
                if(0) {
1018
 
                        if(cb(elm->name, strlen(elm->name), app_key) < 0
1019
 
                        || cb(": ", 2, app_key) < 0)
1020
 
                                return -1;
1021
 
                }
1022
 
 
1023
 
                return elm->type->print_struct(elm->type, memb_ptr, ilevel,
1024
 
                        cb, app_key);
1025
 
        } else {
1026
 
                return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
1027
 
        }
1028
 
}
1029
 
 
1030
 
void
1031
 
CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
1032
 
        asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
1033
 
        int present;
1034
 
 
1035
 
        if(!td || !ptr)
1036
 
                return;
1037
 
 
1038
 
        ASN_DEBUG("Freeing %s as CHOICE", td->name);
1039
 
 
1040
 
        /*
1041
 
         * Figure out which CHOICE element is encoded.
1042
 
         */
1043
 
        present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
1044
 
 
1045
 
        /*
1046
 
         * Free that element.
1047
 
         */
1048
 
        if(present > 0 && present <= td->elements_count) {
1049
 
                asn_TYPE_member_t *elm = &td->elements[present-1];
1050
 
                void *memb_ptr;
1051
 
 
1052
 
                if(elm->flags & ATF_POINTER) {
1053
 
                        memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
1054
 
                        if(memb_ptr)
1055
 
                                ASN_STRUCT_FREE(*elm->type, memb_ptr);
1056
 
                } else {
1057
 
                        memb_ptr = (void *)((char *)ptr + elm->memb_offset);
1058
 
                        ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
1059
 
                }
1060
 
        }
1061
 
 
1062
 
        if(!contents_only) {
1063
 
                FREEMEM(ptr);
1064
 
        }
1065
 
}
1066
 
 
1067
 
 
1068
 
/*
1069
 
 * The following functions functions offer protection against -fshort-enums,
1070
 
 * compatible with little- and big-endian machines.
1071
 
 * If assertion is triggered, either disable -fshort-enums, or add an entry
1072
 
 * here with the ->pres_size of your target stracture.
1073
 
 * Unless the target structure is packed, the ".present" member
1074
 
 * is guaranteed to be aligned properly. ASN.1 compiler itself does not
1075
 
 * produce packed code.
1076
 
 */
1077
 
static int
1078
 
_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
1079
 
        const void *present_ptr;
1080
 
        int present;
1081
 
 
1082
 
        present_ptr = ((const char *)struct_ptr) + pres_offset;
1083
 
 
1084
 
        switch(pres_size) {
1085
 
        case sizeof(int):       present =   *(const int *)present_ptr; break;
1086
 
        case sizeof(short):     present = *(const short *)present_ptr; break;
1087
 
        case sizeof(char):      present =  *(const char *)present_ptr; break;
1088
 
        default:
1089
 
                /* ANSI C mandates enum to be equivalent to integer */
1090
 
                assert(pres_size != sizeof(int));
1091
 
                return 0;       /* If not aborted, pass back safe value */
1092
 
        }
1093
 
 
1094
 
        return present;
1095
 
}
1096
 
 
1097
 
static void
1098
 
_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) {
1099
 
        void *present_ptr;
1100
 
        present_ptr = ((char *)struct_ptr) + pres_offset;
1101
 
 
1102
 
        switch(pres_size) {
1103
 
        case sizeof(int):       *(int *)present_ptr   = present; break;
1104
 
        case sizeof(short):     *(short *)present_ptr = present; break;
1105
 
        case sizeof(char):      *(char *)present_ptr  = present; break;
1106
 
        default:
1107
 
                /* ANSI C mandates enum to be equivalent to integer */
1108
 
                assert(pres_size != sizeof(int));
1109
 
        }
1110
 
}