Commit 59b176ee authored by Lev Walkin's avatar Lev Walkin
Browse files

upgrade: PER related changes

parent 70853058
0.9.20: 2005-Nov-07
0.9.20: 2005-Nov-13
* SET OF CHOICE, SEQUENCE OF CHOICE and a certain named S/O types
are represented differently in XER. THIS IS AN ICOMPATIBLE CHANGE.
(Test case 70) (Severity: low; Security impact: low)
* PER implementation has started
* asn1c: Removed -ftypes88 command line option.
0.9.19: 2005-Oct-06
......
1. MAJOR:
1.1 Support for PER encoding. Requires advanced subtype constraints support,
which is already completed.
1.1 Support for PER encoding. PER decoding is already supported.
1.2 Support for Information Object Classes.
Status: Support for parsing IOCs is mostly present.
......@@ -12,7 +11,3 @@ which is already completed.
2.1 Support for EXTERNAL, EMBEDDED-PDV and CHARACTER STRING types.
Requires something from 1.2 (Information Object Classes).
3. MINOR:
3.1 Support for DEFAULT encoding and decoding, at least in INTEGER/ENUMERATED types.
......@@ -4,7 +4,7 @@ asn1c \- ASN.1 Compiler
.SH SYNOPSIS
asn1c [\fB\-E\fR [\fB-F\fR] | \fB\-P\fR | \fB\-R\fR]
[\fB\-S\fR\fIdir\fR] [\fB-X\fR]
[\fB\-W\fR\fIdebug-\fR...] [\fB\-f\fR\fIoption\fR...] [\fB\-p\fR\fIrint-\fR...]
[\fB\-W\fR\fIdebug-\fR...] [\fB\-f\fR\fIoption\fR] [\fB\-gen-\fR\fIoption\fR] [\fB\-print-\fR\fIoption\fR]
\fIinfile\fR...
.SH DESCRIPTION
asn1c compiles the ASN.1 specifications into the set of
......@@ -25,7 +25,11 @@ and other encoding standards.
.br
\fB\-fall-defs-global \-fbless-SIZE \-fcompound-names \-findirect-choice
.BI "\-fknown-extern-type="<name>
\fB\-fnative-types \-fno-constraints \-fno-include-deps \-funnamed-unions \-fskeletons-copy \-ftypes88\fR
\fB\-fnative-types \-fno-constraints \-fno-include-deps \-funnamed-unions \-fskeletons-copy
.TP
\fICodecs Generation Options\fR
.br
.B \-gen-PER
.TP
\fIOutput Options\fR
.br
......@@ -117,11 +121,10 @@ Enable unnamed unions in the definitions of target language's structures.
.TP
.B \-fskeletons-copy
Copy support files (skeletons) rather than symlink them.
.SH CODECS GENERATION OPTIONS
.TP
.B \-ftypes88
Pretend to support only ASN.1:1988 embedded types. Certain reserved words,
such as UniversalString and BMPString, become ordinary type references
and may be redefined by the specification.
.B \-gen-PER
Generate Packed Encoding Rules (PER) support code.
.SH OUTPUT OPTIONS
.TP
.B \-print-constraints
......
......@@ -62,7 +62,7 @@ main(int ac, char **av) {
/*
* Process command-line options.
*/
while((ch = getopt(ac, av, "EFf:hLPp:RS:vW:X")) != -1)
while((ch = getopt(ac, av, "EFf:g:hLPp:RS:vW:X")) != -1)
switch(ch) {
case 'E':
print_arg__print_out = 1;
......@@ -95,13 +95,19 @@ main(int ac, char **av) {
asn1_compiler_flags |= A1C_UNNAMED_UNIONS;
} else if(strcmp(optarg, "skeletons-copy") == 0) {
asn1_compiler_flags |= A1C_SKELETONS_COPY;
} else if(strcmp(optarg, "types88") == 0) {
asn1_parser_flags |= A1P_TYPES_RESTRICT_TO_1988;
} else {
fprintf(stderr, "-f%s: Invalid argument\n", optarg);
exit(EX_USAGE);
}
break;
case 'g':
if(strcmp(optarg, "en-PER") == 0) {
asn1_compiler_flags |= A1C_GEN_PER;
} else {
fprintf(stderr, "-g%s: Invalid argument\n", optarg);
exit(EX_USAGE);
}
break;
case 'h':
usage(av[0]);
case 'P':
......@@ -109,7 +115,15 @@ main(int ac, char **av) {
asn1_compiler_flags &= ~A1C_NO_C99;
break;
case 'p':
if(strcmp(optarg, "rint-constraints") == 0) {
if(strncmp(optarg, "du=", 3) == 0) {
char *pduname = optarg + 3;
if(strcmp(pduname, "auto")) {
fprintf(stderr, "-pdu=%s: expected -pdu=auto\n",
pduname);
exit(EX_USAGE);
}
asn1_compiler_flags |= A1C_PDU_AUTO;
} else if(strcmp(optarg, "rint-constraints") == 0) {
asn1_printer_flags |= APF_DEBUG_CONSTRAINTS;
} else if(strcmp(optarg, "rint-lines") == 0) {
asn1_printer_flags |= APF_LINE_COMMENTS;
......@@ -250,7 +264,8 @@ main(int ac, char **av) {
/*
* Make sure the skeleton directory is out there.
*/
if(skeletons_dir == NULL) {
if((asn1_compiler_flags & A1C_OMIT_SUPPORT_CODE) == 0
&& skeletons_dir == NULL) {
struct stat sb;
skeletons_dir = DATADIR;
if((av[-optind][0] == '.' || av[-optind][1] == '/')
......@@ -326,7 +341,10 @@ usage(const char *av0) {
" -fno-include-deps Do not generate courtesy #includes for dependencies\n"
" -funnamed-unions Enable unnamed unions in structures\n"
" -fskeletons-copy Force copying the support files\n"
" -ftypes88 Pretend to support only ASN.1:1988 embedded types\n"
"\n"
" -gen-PER Generate PER support code\n"
" -pdu=auto Generate PDU table (discover PDUs automatically)\n"
"\n"
" -print-constraints Explain subtype constraints (debug)\n"
......
......@@ -102,8 +102,8 @@ check(int is_ok, uint8_t *buf, int size, size_t consumed) {
assert(rval.code == RC_OK);
assert(rval.consumed == consumed);
assert(strcmp(t.e->buf, "xyz") == 0);
assert(strcmp(t.f->buf, "love_it") == 0);
assert(strcmp((char *)t.e->buf, "xyz") == 0);
assert(strcmp((char *)t.f->buf, "love_it") == 0);
assert(t.g->size == 2);
assert(t.g->bits_unused == 2);
......
......@@ -36,8 +36,12 @@ _buf_writer(const void *buffer, size_t size, void *app_key) {
b = buf + buf_offset;
bend = b + size;
fprintf(stderr, "=> [");
for(; b < bend; b++)
fprintf(stderr, "%c", *b);
for(; b < bend; b++) {
if(*b >= 32 && *b < 127 && *b != '%')
fprintf(stderr, "%c", *b);
else
fprintf(stderr, "%%02x", *b);
}
fprintf(stderr, "]:%ld\n", (long)size);
buf_offset += size;
return 0;
......
This diff is collapsed.
......@@ -4,7 +4,7 @@
#include "asn1c_out.h"
#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */
#include <asn1fix_export.h> /* other exportables from libasn1fix */
static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);
static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
......
......@@ -66,7 +66,12 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) {
asn1c_fdeps_t *cur;
char buf[4096];
FILE *f;
int hit_COMMON_FILES = 0;
enum {
SS_DYNAMIC, /* Dynamic list of dependencies */
SS_CODEC_PER, /* Use contents only if -gen-PER */
SS_COMMON_FILES, /* Section for dependencies */
SS_IGNORE /* Ignore contents of this section */
} special_section = SS_DYNAMIC;
(void)arg;
......@@ -91,17 +96,27 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) {
for(p = strtok(buf, " \t\r\n"); p;
p = strtok(NULL, " \t\r\n")) {
asn1c_fdeps_t *d;
/*
* If hit "COMMON-FILES:", treat everything else
* as a huge dependency.
* Special "prefix" section.
*/
if(strcmp(p, "COMMON-FILES:") == 0) {
hit_COMMON_FILES = 1;
if(strchr(p, ':')) {
special_section = SS_IGNORE;
if(strcmp(p, "COMMON-FILES:") == 0) {
special_section = SS_COMMON_FILES;
} else if((arg->flags & A1C_GEN_PER)
&& strcmp(p, "CODEC-PER:") == 0) {
special_section = SS_CODEC_PER;
}
break;
}
if(special_section == SS_IGNORE)
continue;
d = asn1c_new_dep(p);
assert(d);
d->used_somewhere = hit_COMMON_FILES;
d->used_somewhere = special_section;
if(asn1c_dep_add(cur, d) == 1)
cur = d;
......
......@@ -11,6 +11,7 @@ static int asn1c_print_streams(arg_t *arg);
static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *);
static int asn1c_copy_over(arg_t *arg, char *path);
static int identical_files(const char *fname1, const char *fname2);
static int generate_pdu_collection_file(arg_t *arg);
int
asn1c_save_compiled_output(arg_t *arg, const char *datadir,
......@@ -18,7 +19,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
asn1c_fdeps_t *deps = 0;
asn1c_fdeps_t *dlist;
asn1p_module_t *mod;
FILE *mkf;
FILE *mkf; /* Makefile.am.sample */
int i;
deps = asn1c_read_file_dependencies(arg, datadir);
......@@ -108,6 +109,12 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
}
}
if(arg->flags & A1C_PDU_AUTO) {
fprintf(mkf, "ASN_MODULE_SOURCES+=pdu_collection.c\n");
if(generate_pdu_collection_file(arg))
return -1;
}
fprintf(mkf, "\n\n"
"lib_LTLIBRARIES=libsomething.la\n"
"libsomething_la_SOURCES="
......@@ -438,3 +445,62 @@ asn1c_copy_over(arg_t *arg, char *path) {
return 1;
}
static int
generate_pdu_collection_file(arg_t *arg) {
asn1p_module_t *mod;
FILE *fp;
fp = asn1c_open_file("pdu_collection", ".c", 0);
if(fp == NULL) {
perror("pdu_collection.c");
return -1;
}
fprintf(fp,
"/*\n"
" * Generated by asn1c-" VERSION " (http://lionet.info/asn1c)\n"
" */\n\n");
fprintf(fp, "struct asn_TYPE_descriptor_s;\t"
"/* Forward declaration */\n\n");
TQ_FOR(mod, &(arg->asn->modules), mod_next) {
TQ_FOR(arg->expr, &(mod->members), next) {
if(arg->expr->_type_referenced
|| !asn1_lang_map[arg->expr->meta_type]
[arg->expr->expr_type].type_cb)
continue;
fprintf(fp, "extern struct asn_TYPE_descriptor_s "
"asn_DEF_%s;\n",
asn1c_make_identifier(0, arg->expr->Identifier,
NULL));
}
}
fprintf(fp, "\n\n");
fprintf(fp, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n");
TQ_FOR(mod, &(arg->asn->modules), mod_next) {
int mod_printed = 0;
TQ_FOR(arg->expr, &(mod->members), next) {
if(arg->expr->_type_referenced
|| !asn1_lang_map[arg->expr->meta_type]
[arg->expr->expr_type].type_cb)
continue;
if(!mod_printed++)
fprintf(fp, "\t/* From module %s in %s */\n",
arg->expr->module->ModuleName,
arg->expr->module->source_file_name);
fprintf(fp, "\t&asn_DEF_%s,\t\n",
asn1c_make_identifier(0, arg->expr->Identifier,
NULL));
}
}
fprintf(fp, "\t0\n};\n\n");
fclose(fp);
fprintf(stderr, "Generated pdu_collection.c\n");
return 0;
}
......@@ -56,6 +56,16 @@ enum asn1c_flags {
* Copy support files rather than symlink them.
*/
A1C_SKELETONS_COPY = 0x0800,
/*
* -gen-PER
* Generate PER support code
*/
A1C_GEN_PER = 0x1000,
/*
* -pdu=auto
* Generate PDU table
*/
A1C_PDU_AUTO = 0x2000
};
/*
......
#include "asn1fix_internal.h"
#define AFT_MAGIC_ANY 1 /* _fetch_tag() flag */
static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
......@@ -337,6 +335,7 @@ asn1f_check_constr_tags_distinct(arg_t *arg) {
case ASN_CONSTR_SEQUENCE:
case ASN_CONSTR_SET:
case ASN_CONSTR_CHOICE:
DEBUG("Checking tags of members of constructed types");
break;
default:
return 0;
......@@ -353,6 +352,8 @@ asn1f_check_constr_tags_distinct(arg_t *arg) {
if(expr->expr_type != ASN_CONSTR_SEQUENCE || v->marker.flags) {
asn1p_expr_t *nv;
for(nv = v; (nv = TQ_NEXT(nv, next));) {
DEBUG("S/C comparing tags %s s. %s",
v->Identifier, nv->Identifier);
if(_asn1f_compare_tags(arg, v, nv))
r_value = -1;
if(expr->expr_type == ASN_CONSTR_SEQUENCE
......@@ -404,12 +405,15 @@ _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
int ra, rb;
int ret;
ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a, &ta, AFT_MAGIC_ANY);
rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b, &tb, AFT_MAGIC_ANY);
ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a,
&ta, AFT_IMAGINARY_ANY);
rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b,
&tb, AFT_IMAGINARY_ANY);
/*
* If both tags are explicitly or implicitly given, use them.
*/
DEBUG("Fetching outmost tags: %d, %d", ra, rb);
if(ra == 0 && rb == 0) {
/*
* Simple case: fetched both tags.
......
......@@ -370,6 +370,7 @@ asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
return NULL;
}
tc->_type_referenced = 1;
tc->_mark |= TM_RECURSION;
WITH_MODULE(tc->module,
expr = asn1f_find_terminal_thing(arg, tc, what));
......
......@@ -18,6 +18,9 @@
if((flags & AFT_FETCH_OUTMOST)) return count; \
} while(0)
/* X.691, #22.2 */
static int asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags);
static int
asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
asn1p_expr_t *expr = arg->expr;
......@@ -44,9 +47,13 @@ asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int
if(expr->expr_type == ASN_TYPE_ANY
&& (flags & AFT_IMAGINARY_ANY))
tt.tag_value = -1;
else if(expr->expr_type == ASN_CONSTR_CHOICE)
return count ? count : -1;
else
else if(expr->expr_type != ASN_CONSTR_CHOICE)
return -1;
else if(count) return count;
else if((flags & AFT_CANON_CHOICE) == 0)
return -1;
else if(asn1f_fetch_minimal_choice_root_tag(arg,
&tt, flags))
return -1;
}
ADD_TAG(skip, tt);
......@@ -55,6 +62,7 @@ asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int
if(expr->meta_type == AMT_TYPEREF) {
asn1p_expr_t *nexpr;
DEBUG("Following the reference %s", expr->Identifier);
nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
if(nexpr == NULL) {
if(errno != EEXIST) /* -fknown-extern-type */
......@@ -87,18 +95,52 @@ asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int
return count;
}
DEBUG("No tags discovered for type %d", expr->expr_type);
return -1;
}
static int
asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
struct asn1p_type_tag_s min_tag;
asn1p_expr_t *v;
memset(&min_tag, 0, sizeof(min_tag));
min_tag.tag_class = TC_PRIVATE + 1;
TQ_FOR(v, &(arg->expr->members), next) {
arg_t tmparg = *arg;
struct asn1p_type_tag_s *tags = 0;
int count;
if(v->expr_type == A1TC_EXTENSIBLE)
break; /* Search only within extension root */
tmparg.expr = v;
count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
if(count <= 0) continue;
if(tags[0].tag_class < min_tag.tag_class)
min_tag = tags[0];
else if(tags[0].tag_class == min_tag.tag_class
&& tags[0].tag_value < min_tag.tag_value)
min_tag = tags[0];
free(tags);
}
if(min_tag.tag_class == TC_PRIVATE + 1)
return -1;
else
*tag = min_tag;
return 0;
}
int
asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) {
asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
struct asn1p_type_tag_s *tags;
enum asn1f_aft_flags_e flags;
int count;
flags = AFT_FETCH_OUTMOST;
flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any;
flags |= AFT_FETCH_OUTMOST;
count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
if(count <= 0) return count;
......
......@@ -5,6 +5,7 @@ enum asn1f_aft_flags_e {
AFT_IMAGINARY_ANY = 0x01, /* Treat ANY tag as [IMAGINARY ANY] */
AFT_FETCH_OUTMOST = 0x02, /* Fetch only outmost tag */
AFT_FULL_COLLECT = 0x04, /* Collect all tags */
AFT_CANON_CHOICE = 0x08, /* Fetch the minimal CHOICE root tag */
};
/*
......@@ -24,6 +25,6 @@ int asn1f_fetch_tags(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr,
* Type3 ::= SEQUENCE { ... }
* Will yield [2] for Type1.
*/
int asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any);
int asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e);
#endif /* _ASN1FIX_TAGS_H_ */
......@@ -21,8 +21,10 @@ asn_TYPE_descriptor_t asn_DEF_ANY = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
0,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
0, /* No PER visible constraints */
0, 0, /* No members */
&asn_DEF_ANY_specs,
};
......
......@@ -27,6 +27,7 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_binary,
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
......@@ -34,6 +35,7 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
asn_DEF_BIT_STRING_tags, /* Same as above */
sizeof(asn_DEF_BIT_STRING_tags)
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
&asn_DEF_BIT_STRING_specs
};
......@@ -124,9 +126,7 @@ BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
er.structure_ptr = 0;
er.failed_type = 0;
return er;
_ASN_ENCODED_OK(er);
cb_failed:
_ASN_ENCODE_FAILED;
}
......
......@@ -23,6 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
OCTET_STRING_encode_der,
BMPString_decode_xer, /* Convert from UTF-8 */
BMPString_encode_xer, /* Convert to UTF-8 */
0,
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
......@@ -30,6 +31,7 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
/ sizeof(asn_DEF_BMPString_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
......@@ -156,7 +158,7 @@ BMPString_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
er.encoded = BMPString__dump(st, cb, app_key);
if(er.encoded < 0) _ASN_ENCODE_FAILED;
return er;
_ASN_ENCODED_OK(er);
}
int
......
/*-
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
......@@ -22,11 +22,13 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
BOOLEAN_encode_der,
BOOLEAN_decode_xer,
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
asn_DEF_BOOLEAN_tags, /* Same as above */
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
......@@ -126,7 +128,7 @@ BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
erval.encoded += 1;
return erval;
_ASN_ENCODED_OK(erval);
}
......@@ -196,7 +198,7 @@ BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
er.encoded = 8;
}
return er;
_ASN_ENCODED_OK(er);
cb_failed:
_ASN_ENCODE_FAILED;
}
......@@ -234,3 +236,33 @@ BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
}
}
asn_dec_rval_t
BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
(void)opt_codec_ctx;
(void)constraints;
if(!st) {
st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
if(!st) _ASN_DECODE_FAILED;
}
/*
* Extract a single bit
*/
switch(per_get_few_bits(pd, 1)) {
case 1: *st = 1; break;
case 0: *st = 0; break;
case -1: default: _ASN_DECODE_FAILED;
}
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
rv.code = RC_OK;
rv.consumed = 1;
return rv;