XER support

This commit is contained in:
Lev Walkin 2004-09-22 16:06:28 +00:00
parent e4d6ab83d7
commit a9cc46e3f3
94 changed files with 3421 additions and 1423 deletions

View File

@ -48,7 +48,8 @@ static void
check(int is_ok, uint8_t *buf, int size, size_t consumed) {
T1_t t, *tp;
ber_dec_rval_t rval;
der_enc_rval_t erval;
asn_enc_rval_t erval;
int ret;
int i;
tp = memset(&t, 0, sizeof(t));
@ -104,8 +105,12 @@ check(int is_ok, uint8_t *buf, int size, size_t consumed) {
assert(buf1[i] == buf2[i]);
}
fprintf(stderr, "=== PRINT ===\n");
asn_fprint(stderr, &asn1_DEF_T1, tp);
fprintf(stderr, "=== asn_fprint() ===\n");
ret = asn_fprint(stderr, &asn1_DEF_T1, tp);
assert(ret == 0);
fprintf(stderr, "=== xer_fprint() ===\n");
ret = xer_fprint(stderr, &asn1_DEF_T1, tp);
assert(ret == 0);
fprintf(stderr, "=== EOF ===\n");
}

View File

@ -136,6 +136,7 @@ check(int is_ok, uint8_t *buf, int size, size_t consumed) {
assert(buf_pos == sizeof(buf1_reconstr));
asn_fprint(stderr, &asn1_DEF_Forest, &t);
xer_fprint(stderr, &asn1_DEF_Forest, &t);
asn1_DEF_Forest.free_struct(&asn1_DEF_Forest, &t, 1);
}

View File

@ -131,6 +131,9 @@ check(T_t *tp, uint8_t *buf, int size, size_t consumed) {
assert(strcmp(tp->a.buf, "ns") == 0);
assert(strcmp(tp->b.choice.b1.buf, "z") == 0
&& strcmp(tp->b.choice.b2.buf, "z") == 0);
asn_fprint(stderr, &asn1_DEF_T, tp);
xer_fprint(stderr, &asn1_DEF_T, tp);
}
size_t buf_pos;
@ -157,7 +160,7 @@ buf_fill(const void *buffer, size_t size, void *app_key) {
static void
compare(T_t *tp, uint8_t *cmp_buf, int cmp_buf_size) {
der_enc_rval_t erval;
asn_enc_rval_t erval;
int i;
buf_size = cmp_buf_size + 100;
@ -268,12 +271,10 @@ main(int ac, char **av) {
check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Split the buffer in parts and check decoder restartability */

View File

@ -132,10 +132,11 @@ uint8_t buf2_reconstr[] = {
static void
check(T_t *tp, uint8_t *buf, int size, size_t consumed) {
ber_dec_rval_t rval;
int ret;
tp = memset(tp, 0, sizeof(*tp));
fprintf(stderr, "Buf %p (%d)\n", buf, size);
fprintf(stderr, "Buf %p (%d)\n", (int)buf, (int)size);
rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
fprintf(stderr, "Returned code %d, consumed %d\n",
(int)rval.code, (int)rval.consumed);
@ -143,6 +144,14 @@ check(T_t *tp, uint8_t *buf, int size, size_t consumed) {
assert(rval.code == RC_OK);
assert(rval.consumed == consumed);
fprintf(stderr, "=== asn_fprint() ===\n");
ret = asn_fprint(stderr, &asn1_DEF_T, tp);
assert(ret == 0);
fprintf(stderr, "=== xer_fprint() ===\n");
ret = xer_fprint(stderr, &asn1_DEF_T, tp);
fprintf(stderr, "=== END ===\n");
assert(ret == 0);
/*
assert(tp->string.size == 128);
assert(strncmp(tp->string.buf, "zz") == 0);
@ -153,32 +162,33 @@ check(T_t *tp, uint8_t *buf, int size, size_t consumed) {
size_t buf_pos;
size_t buf_size;
uint8_t *buf;
uint8_t *buffer;
static int
buf_fill(const void *buffer, size_t size, void *app_key) {
buf_fill(const void *bufp, size_t size, void *app_key) {
(void)app_key; /* Unused argument */
if(buf_pos + size > buf_size) {
fprintf(stderr, "%d + %d > %d\n", buf_pos, (int)size, buf_size);
fprintf(stderr, "%d + %d > %d\n",
(int)buf_pos, (int)size, (int)buf_size);
return -1;
}
memcpy(buf + buf_pos, buffer, size);
memcpy(buffer + buf_pos, bufp, size);
buf_pos += size;
fprintf(stderr, " written %d (%d)\n", (int)size, buf_pos);
fprintf(stderr, " written %d (%d)\n", (int)size, (int)buf_pos);
return 0;
}
static void
compare(T_t *tp, uint8_t *cmp_buf, int cmp_buf_size) {
der_enc_rval_t erval;
asn_enc_rval_t erval;
int i;
buf_size = cmp_buf_size + 100;
buf = alloca(buf_size);
buffer = alloca(buf_size);
buf_pos = 0;
/*
@ -187,19 +197,19 @@ compare(T_t *tp, uint8_t *cmp_buf, int cmp_buf_size) {
erval = der_encode(&asn1_DEF_T, tp, buf_fill, 0);
assert(erval.encoded != -1);
if(erval.encoded != cmp_buf_size) {
printf("%d != %d\n", erval.encoded, cmp_buf_size);
printf("%d != %d\n", (int)erval.encoded, (int)cmp_buf_size);
}
assert(erval.encoded == cmp_buf_size);
for(i = 0; i < cmp_buf_size; i++) {
if(buf[i] != cmp_buf[i]) {
if(buffer[i] != cmp_buf[i]) {
fprintf(stderr, "Recreated buffer content mismatch:\n");
fprintf(stderr, "Byte %d, %x != %x (%d != %d)\n",
i,
buf[i], cmp_buf[i],
buf[i], cmp_buf[i]
buffer[i], cmp_buf[i],
buffer[i], cmp_buf[i]
);
}
assert(buf[i] == cmp_buf[i]);
assert(buffer[i] == cmp_buf[i]);
}
}
@ -230,7 +240,7 @@ partial_read(uint8_t *buf, size_t size) {
size_t size3 = size - size1 - size2;
fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
size, size1, size2, size3);
(int)size, (int)size1, (int)size2, (int)size3);
memset(buf1, 0, size);
memset(buf2, 0, size);
@ -241,7 +251,7 @@ partial_read(uint8_t *buf, size_t size) {
tp = memset(&t, 0, sizeof(t));
fprintf(stderr, "=> Chunk 1 (%d):\n", size1);
fprintf(stderr, "=> Chunk 1 (%d):\n", (int)size1);
rval = ber_decode(&asn1_DEF_T, (void **)&tp,
buf1, size1);
assert(rval.code == RC_WMORE);
@ -253,7 +263,7 @@ partial_read(uint8_t *buf, size_t size) {
size2 += leftover;
}
fprintf(stderr, "=> Chunk 2 (%d):\n", size2);
fprintf(stderr, "=> Chunk 2 (%d):\n", (int)size2);
rval = ber_decode(&asn1_DEF_T, (void **)&tp,
buf2, size2);
assert(rval.code == RC_WMORE);
@ -265,7 +275,7 @@ partial_read(uint8_t *buf, size_t size) {
size3 += leftover;
}
fprintf(stderr, "=> Chunk 3 (%d):\n", size3);
fprintf(stderr, "=> Chunk 3 (%d):\n", (int)size3);
rval = ber_decode(&asn1_DEF_T, (void **)&tp,
buf3, size3);
assert(rval.code == RC_OK);
@ -283,31 +293,26 @@ main() {
/* Check exact buf0 */
check(&t, buf0, sizeof(buf0), sizeof(buf0));
compare(&t, buf0_reconstr, sizeof(buf0_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Check exact buf1 */
check(&t, buf1, sizeof(buf1), sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Check slightly more than buf1 */
check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Check exact buf2 */
check(&t, buf2, sizeof(buf2), sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Check slightly more than buf2 */
check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
asn_fprint(stderr, &asn1_DEF_T, &t);
asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
/* Split the buffer in parts and check decoder restartability */

View File

@ -29,7 +29,7 @@ _buf_writer(const void *buffer, size_t size, void *app_key) {
static int
save_object(void *bs, asn1_TYPE_descriptor_t *td) {
der_enc_rval_t rval; /* Return value */
asn_enc_rval_t rval; /* Return value */
int i;
rval = der_encode(td, bs, _buf_writer, 0);
@ -44,6 +44,7 @@ save_object(void *bs, asn1_TYPE_descriptor_t *td) {
buf[buf_offset++] = 123; /* Finalize with garbage */
asn_fprint(stderr, td, bs);
xer_fprint(stderr, td, bs);
printf("OUT: [");
for(i = 0; i < buf_offset; i++)
@ -63,6 +64,7 @@ load_object(void *bs, asn1_TYPE_descriptor_t *td) {
assert(rval.code == RC_OK);
asn_fprint(stderr, td, bs);
xer_fprint(stderr, td, bs);
return (rval.code == RC_OK)?0:-1;
}

View File

@ -27,6 +27,7 @@ static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
static int check_if_extensible(asn1p_expr_t *expr);
static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
@ -156,7 +157,6 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int elements; /* Number of elements */
int comp_mode = 0; /* {root,ext=1,root,root,...} */
int ext_start = -1;
int ext_stop = -1;
tag2el_t *tag2el = NULL;
@ -183,22 +183,28 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
/*
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
if(expr_elements_count(arg, expr)) {
int comp_mode = 0; /* {root,ext=1,root,root,...} */
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if((++comp_mode) == 1)
ext_start = elements - 1;
else
ext_stop = elements - 1;
continue;
}
elements++;
emit_member_table(arg, v);
});
OUT("};\n");
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if((++comp_mode) == 1)
ext_start = elements - 1;
else
ext_stop = elements - 1;
continue;
}
elements++;
emit_member_table(arg, v);
});
OUT("};\n");
} else {
elements = 0;
}
/*
* Print out asn1_DEF_<type>_[all_]tags[] vectors.
@ -307,7 +313,6 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int elements;
int comp_mode = 0; /* {root,ext=1,root,root,...} */
tag2el_t *tag2el = NULL;
int tag2el_count = 0;
int tags_count;
@ -332,22 +337,28 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
/*
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
if(expr_elements_count(arg, expr)) {
int comp_mode = 0; /* {root,ext=1,root,root,...} */
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if(comp_mode < 3) comp_mode++;
} else {
if(comp_mode == 1
|| expr_better_indirect(arg, v))
v->marker.flags |= EM_INDIRECT;
elements++;
emit_member_table(arg, v);
}
});
OUT("};\n");
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if(comp_mode < 3) comp_mode++;
} else {
if(comp_mode == 1
|| expr_better_indirect(arg, v))
v->marker.flags |= EM_INDIRECT;
elements++;
emit_member_table(arg, v);
}
});
OUT("};\n");
} else {
elements = 0;
}
/*
* Print out asn1_DEF_<type>_[all_]tags[] vectors.
@ -443,12 +454,15 @@ asn1c_lang_C_type_SEx_OF(arg_t *arg) {
tmp.expr = &tmp_memb;
tmp_memb = *memb;
tmp_memb._anonymous_type = 1;
tmp_memb.Identifier = strdup(
asn1c_make_identifier(0,
expr->Identifier, "member", 0));
assert(tmp_memb.Identifier);
if(tmp_memb.Identifier == 0) {
tmp_memb.Identifier = strdup(
asn1c_make_identifier(0,
expr->Identifier, "member", 0));
assert(tmp_memb.Identifier);
}
tmp.default_cb(&tmp);
free(tmp_memb.Identifier);
if(tmp_memb.Identifier != memb->Identifier)
free(tmp_memb.Identifier);
arg->embed--;
assert(arg->target->target == OT_TYPE_DECLS);
} else {
@ -496,11 +510,17 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
*/
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
INDENTED(
INDENT(+1);
v = TQ_FIRST(&(expr->members));
if(!v->Identifier) {
v->Identifier = strdup("member");
assert(v->Identifier);
}
v->_anonymous_type = 1;
arg->embed++;
emit_member_table(arg, v);
);
arg->embed--;
INDENT(-1);
OUT("};\n");
/*
@ -513,6 +533,10 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
INDENTED(
OUT("sizeof(struct %s),\n", p);
OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
if(expr_as_xmlvaluelist(arg, v))
OUT("1,\t/* XER encoding is XMLValueList */\n");
else
OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
);
OUT("};\n");
@ -589,7 +613,6 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int elements; /* Number of elements */
int comp_mode = 0; /* {root,ext=1,root,root,...} */
tag2el_t *tag2el = NULL;
int tag2el_count = 0;
int tags_count;
@ -614,22 +637,28 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
/*
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
if(expr_elements_count(arg, expr)) {
int comp_mode = 0; /* {root,ext=1,root,root,...} */
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if(comp_mode < 3) comp_mode++;
} else {
if(comp_mode == 1
|| expr_better_indirect(arg, v))
v->marker.flags |= EM_INDIRECT;
elements++;
emit_member_table(arg, v);
}
});
OUT("};\n");
p = MKID(expr->Identifier);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if(comp_mode < 3) comp_mode++;
} else {
if(comp_mode == 1
|| expr_better_indirect(arg, v))
v->marker.flags |= EM_INDIRECT;
elements++;
emit_member_table(arg, v);
}
});
OUT("};\n");
} else {
elements = 0;
}
if(arg->embed) {
@ -683,7 +712,7 @@ asn1c_lang_C_type_REFERENCE(arg_t *arg) {
arg_t tmp;
int ret;
extract = asn1f_class_access_ex(arg->asn, arg->mod,
extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
arg->expr, ref);
if(extract == NULL)
return -1;
@ -808,12 +837,14 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
INDENT(+1);
{
asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
OUT("td->xer_decoder = asn1_DEF_%s.xer_decoder;\n", type_name);
OUT("td->xer_encoder = asn1_DEF_%s.xer_encoder;\n", type_name);
if(!terminal && !tags_count) {
OUT("/* The next four lines are here because of -fknown-extern-type */\n");
OUT("td->tags = asn1_DEF_%s.tags;\n", type_name);
@ -832,24 +863,12 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("\n");
p = MKID(expr->Identifier);
OUT("ber_dec_rval_t\n");
OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
OUT("void\n");
OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
OUT("\tvoid *struct_ptr, int contents_only) {\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->ber_decoder(td, structure, bufptr, size, tag_mode);\n");
);
OUT("}\n");
OUT("\n");
p = MKID(expr->Identifier);
OUT("der_enc_rval_t\n");
OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
OUT("td->free_struct(td, struct_ptr, contents_only);\n");
);
OUT("}\n");
OUT("\n");
@ -866,12 +885,36 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("\n");
p = MKID(expr->Identifier);
OUT("void\n");
OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
OUT("ber_dec_rval_t\n");
OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid *struct_ptr, int contents_only) {\n");
OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("td->free_struct(td, struct_ptr, contents_only);\n");
OUT("return td->ber_decoder(td, structure, bufptr, size, tag_mode);\n");
);
OUT("}\n");
OUT("\n");
p = MKID(expr->Identifier);
OUT("asn_enc_rval_t\n");
OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
);
OUT("}\n");
OUT("\n");
p = MKID(expr->Identifier);
OUT("asn_enc_rval_t\n");
OUT("%s_encode_xer(asn1_TYPE_descriptor_t *td, void *structure,\n", p);
INDENTED(
OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
);
OUT("}\n");
OUT("\n");
@ -883,11 +926,12 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
OUT("\n");
OUT("asn_struct_free_f %s_free;\n", p);
OUT("asn_struct_print_f %s_print;\n", p);
OUT("asn_constr_check_f %s_constraint;\n", p);
OUT("ber_type_decoder_f %s_decode_ber;\n", p);
OUT("der_type_encoder_f %s_encode_der;\n", p);
OUT("asn_struct_print_f %s_print;\n", p);
OUT("asn_struct_free_f %s_free;\n", p);
OUT("xer_type_encoder_f %s_encode_xer;\n", p);
REDIR(OT_TYPE_DECLS);
@ -1031,7 +1075,8 @@ _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
assert(el_no >= 0);
ret = asn1f_fetch_outmost_tag(arg->asn, arg->mod, arg->expr, &tag, 1);
ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
arg->expr, &tag, 1);
if(ret == 0) {
tag2el_t *te;
int new_count = (*count) + 1;
@ -1137,12 +1182,12 @@ emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_ta
*all_tags_count_r = 0;
/* Fetch a chain of tags */
tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr, &tags, 0);
tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
if(tags_count < 0)
return -1;
/* Fetch a chain of tags */
all_tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr,
all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
&all_tags, AFT_FULL_COLLECT);
if(all_tags_count < 0) {
if(tags) free(tags);
@ -1207,7 +1252,7 @@ expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
asn1p_expr_t *v;
int elements = 0;
topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
if(!topmost_parent) return 0;
if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
@ -1254,15 +1299,15 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
} else {
OUT("0, ");
}
if(expr->Identifier) {
if(expr->_anonymous_type) {
assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
|| arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
OUT("0,\n");
} else {
OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
if(arg->expr->expr_type == ASN_CONSTR_CHOICE
&& (!UNNAMED_UNIONS)) OUT("choice.");
OUT("%s),\n", MKID(expr->Identifier));
} else {
assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
|| arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
OUT("0,\n");
}
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
@ -1286,9 +1331,7 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
OUT("0,\n");
}
if(C99_MODE) OUT(".type = ");
if((expr->expr_type & ASN_CONSTR_MASK)
&& (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
|| arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
OUT("(void *)&asn1_DEF_%s_member,\n",
MKID(arg->expr->Identifier));
} else if(expr->expr_type & ASN_CONSTR_MASK) {
@ -1301,7 +1344,7 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
if(C99_MODE) OUT(".memb_constraints = ");
if(expr->constraints) {
char *id = MKID(expr->Identifier);
if(!expr->Identifier)
if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
id = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("memb_%s_%d_constraint,\n", id,
++global_memb_unique);
@ -1309,7 +1352,7 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
OUT("0,\t/* Defer to actual type */\n");
}
if(C99_MODE) OUT(".name = ");
OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
OUT("},\n");
INDENT(-1);
@ -1319,10 +1362,10 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
save_target = arg->target->target;
REDIR(OT_CODE);
if(expr->Identifier)
p = MKID(expr->Identifier);
else
if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
p = asn1c_type_name(arg, expr, TNF_SAFE);
else
p = MKID(expr->Identifier);
OUT("static int\n");
OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
INDENT(+1);
@ -1357,11 +1400,13 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_
p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
}
OUT("%s_free,\n", p);
OUT("%s_print,\n", p);
OUT("%s_constraint,\n", p);
OUT("%s_decode_ber,\n", p);
OUT("%s_encode_der,\n", p);
OUT("%s_print,\n", p);
OUT("%s_free,\n", p);
OUT("0, /* Not implemented yet */\n");
OUT("%s_encode_xer,\n", p);
p = MKID(expr->Identifier);
@ -1468,7 +1513,24 @@ expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
return 0;
}
terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
return (terminal == top_parent);
}
static int
expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
expr = asn1f_find_terminal_type_ex(arg->asn, expr);
if(!expr) return 0;
/* X.680, 25.5, Table 5 */
switch(expr->expr_type) {
case ASN_CONSTR_CHOICE:
case ASN_BASIC_BOOLEAN:
case ASN_BASIC_ENUMERATED:
case ASN_BASIC_NULL:
return 1;
default:
return 0;
}
}

View File

@ -2,17 +2,20 @@
* Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <ANY.h>
#include <assert.h>
#include <errno.h>
asn1_TYPE_descriptor_t asn1_DEF_ANY = {
"ANY",
OCTET_STRING_free,
OCTET_STRING_print,
asn_generic_no_constraint,
OCTET_STRING_decode_ber,
OCTET_STRING_encode_der,
OCTET_STRING_print,
OCTET_STRING_free,
0, /* Not implemented yet */
ANY_encode_xer,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
-1, /* Both ways are fine (primitive and constructed) */
@ -21,6 +24,23 @@ asn1_TYPE_descriptor_t asn1_DEF_ANY = {
};
asn_enc_rval_t
ANY_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
(void)ilevel;
(void)flags;
(void)cb;
(void)app_key;
/*
* XER-encoding of ANY type is not supported.
*/
_ASN_ENCODE_FAILED;
}
struct _callback_arg {
uint8_t *buffer;
size_t offset;
@ -32,7 +52,7 @@ static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
int
ANY_fromType(ANY_t *st, asn1_TYPE_descriptor_t *td, void *sptr) {
struct _callback_arg arg;
der_enc_rval_t erval;
asn_enc_rval_t erval;
if(!st || !td) {
errno = EINVAL;
@ -53,7 +73,7 @@ ANY_fromType(ANY_t *st, asn1_TYPE_descriptor_t *td, void *sptr) {
if(arg.buffer) FREEMEM(arg.buffer);
return -1;
}
assert(erval.encoded == arg.offset);
assert((size_t)erval.encoded == arg.offset);
if(st->buf) FREEMEM(st->buf);
st->buf = arg.buffer;

View File

@ -17,10 +17,11 @@ typedef struct ANY {
extern asn1_TYPE_descriptor_t asn1_DEF_ANY;
asn_struct_free_f ANY_free;
asn_struct_print_f ANY_print;
ber_type_decoder_f ANY_decode_ber;
der_type_encoder_f ANY_encode_der;
asn_struct_print_f ANY_print;
asn_struct_free_f ANY_free;
xer_type_encoder_f ANY_encode_xer;
/******************************
* Handy conversion routines. *

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <BIT_STRING.h>
/*
@ -12,11 +13,13 @@ static ber_tlv_tag_t asn1_DEF_BIT_STRING_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_BIT_STRING = {
"BIT STRING",
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
BIT_STRING_print,
BIT_STRING_constraint,
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
BIT_STRING_print,
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
0, /* Not implemented yet */
BIT_STRING_encode_xer,
0, /* Use generic outmost tag fetcher */
asn1_DEF_BIT_STRING_tags,
sizeof(asn1_DEF_BIT_STRING_tags)
@ -61,6 +64,66 @@ BIT_STRING_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
return 0;
}
static char *_bit_pattern[16] = {
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
};
asn_enc_rval_t
BIT_STRING_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
char scratch[128];
char *p = scratch;
char *scend = scratch + (sizeof(scratch) - 10);
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
uint8_t *buf;
uint8_t *end;
if(!st || !st->buf)
_ASN_ENCODE_FAILED;
er.encoded = 0;
buf = st->buf;
end = buf + st->size - 1; /* Last byte is special */
/*
* Binary dump
*/
for(buf++; buf < end; buf++) {
int v = *buf;
int nline = (flags & XER_F_CANONICAL)
?0:((((buf - st->buf) - 1) % 16) == 0);
if(p >= scend || nline) {
er.encoded += p - scratch;
_ASN_CALLBACK(scratch, p - scratch);
p = scratch;
if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
}
memcpy(p + 0, _bit_pattern[v >> 4], 4);
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
p += 8;
}
er.encoded += p - scratch;
_ASN_CALLBACK(scratch, p - scratch);
if(buf < end + 1) {
int v = *buf;
int mbit = st->buf[0]; /* bits to skip from the right */
int i;
for(i = 7; i >= mbit; i--)
*p++ = (v & (1 << i)) ? '1' : '0';
er.encoded += p - scratch;
_ASN_CALLBACK(scratch, p - scratch);
}
return er;
}
/*
* BIT STRING specific contents printer.
*/
@ -99,6 +162,7 @@ BIT_STRING_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) p--; /* Eat the tailing space */
/* Dump the incomplete 16-bytes row */
return cb(scratch, p - scratch, app_key);

View File

@ -14,5 +14,6 @@ extern asn1_TYPE_descriptor_t asn1_DEF_BIT_STRING;
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
asn_constr_check_f BIT_STRING_constraint;
xer_type_encoder_f BIT_STRING_encode_xer;
#endif /* _BIT_STRING_H_ */

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <BMPString.h>
/*
@ -13,11 +14,13 @@ static ber_tlv_tag_t asn1_DEF_BMPString_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_BMPString = {
"BMPString",
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
BMPString_print,
asn_generic_no_constraint, /* No constraint by default */
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
BMPString_print,
OCTET_STRING_free, /* -//- */
0, /* Not implemented yet */
BMPString_encode_xer, /* Conver to UTF8 */
0, /* Use generic outmost tag fetcher */
asn1_DEF_BMPString_tags,
sizeof(asn1_DEF_BMPString_tags)
@ -33,27 +36,22 @@ asn1_TYPE_descriptor_t asn1_DEF_BMPString = {
/*
* BMPString specific contents printer.
*/
int
BMPString_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
static ssize_t
BMPString__dump(const BMPString_t *st,
asn_app_consume_bytes_f *cb, void *app_key) {
const BMPString_t *st = (const BMPString_t *)sptr;
uint16_t *wchar;
uint16_t *wend;
char scratch[128]; /* Scratchpad buffer */
char *p;
char *p = scratch;
ssize_t wrote = 0;
uint8_t *ch;
uint8_t *end;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(!st || !st->buf) return cb("<absent>", 8, app_key);
wchar = (uint16_t *)st->buf;
wend = (uint16_t *)(st->buf + st->size);
for(p = scratch; wchar < wend; wchar++) {
uint16_t wc = (((uint8_t *)wchar)[0] << 8)
| ((uint8_t *)wchar)[1]; /* 2 bytes */
ch = st->buf;
end = (st->buf + st->size);
for(end--; ch < end; ch += 2) {
uint16_t wc = (ch[0] << 8) | ch[1]; /* 2 bytes */
if(sizeof(scratch) - (p - scratch) < 3) {
if(cb(scratch, p - scratch, app_key))
wrote += p - scratch;
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
p = scratch;
}
@ -69,5 +67,45 @@ BMPString_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
}
return cb(scratch, p - scratch, app_key);
wrote += p - scratch;
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
return wrote;
}
asn_enc_rval_t
BMPString_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const BMPString_t *st = (const BMPString_t *)sptr;
asn_enc_rval_t er;
(void)ilevel;
(void)flags;
if(!st || !st->buf)
_ASN_ENCODE_FAILED;
er.encoded = BMPString__dump(st, cb, app_key);
if(er.encoded < 0) _ASN_ENCODE_FAILED;
return er;
}
int
BMPString_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const BMPString_t *st = (const BMPString_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(!st || !st->buf) return cb("<absent>", 8, app_key);
if(BMPString__dump(st, cb, app_key) < 0)
return -1;
return 0;
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BMPString_H_
@ -13,5 +13,6 @@ typedef OCTET_STRING_t BMPString_t; /* Implemented in terms of OCTET STRING */
extern asn1_TYPE_descriptor_t asn1_DEF_BMPString;
asn_struct_print_f BMPString_print; /* Human-readable output */
xer_type_encoder_f BMPString_encode_xer;
#endif /* _BMPString_H_ */

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <BOOLEAN.h>
/*
@ -12,11 +13,13 @@ static ber_tlv_tag_t asn1_DEF_BOOLEAN_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_BOOLEAN = {
"BOOLEAN",
BOOLEAN_free,
BOOLEAN_print,
asn_generic_no_constraint,
BOOLEAN_decode_ber,
BOOLEAN_encode_der,
BOOLEAN_print,
BOOLEAN_free,
0, /* Not implemented yet */
BOOLEAN_encode_xer,
0, /* Use generic outmost tag fetcher */
asn1_DEF_BOOLEAN_tags,
sizeof(asn1_DEF_BOOLEAN_tags) / sizeof(asn1_DEF_BOOLEAN_tags[0]),
@ -93,11 +96,11 @@ BOOLEAN_decode_ber(asn1_TYPE_descriptor_t *td,
return rval;
}
der_enc_rval_t
asn_enc_rval_t
BOOLEAN_encode_der(asn1_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
der_enc_rval_t erval;
asn_enc_rval_t erval;
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
erval.encoded = der_write_tags(td, 1, tag_mode, tag, cb, app_key);
@ -126,6 +129,29 @@ BOOLEAN_encode_der(asn1_TYPE_descriptor_t *td, void *sptr,
return erval;
}
asn_enc_rval_t
BOOLEAN_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
asn_enc_rval_t er;
(void)ilevel;
(void)flags;
if(!st) _ASN_ENCODE_FAILED;
if(*st) {
_ASN_CALLBACK("<true/>", 7);
er.encoded = 7;
} else {
_ASN_CALLBACK("<false/>", 8);
er.encoded = 8;
}
return er;
}
int
BOOLEAN_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {

View File

@ -16,9 +16,10 @@ typedef int BOOLEAN_t;
extern asn1_TYPE_descriptor_t asn1_DEF_BOOLEAN;
asn_struct_free_f BOOLEAN_free;
asn_struct_print_f BOOLEAN_print;
ber_type_decoder_f BOOLEAN_decode_ber;
der_type_encoder_f BOOLEAN_encode_der;
asn_struct_print_f BOOLEAN_print;
asn_struct_free_f BOOLEAN_free;
xer_type_encoder_f BOOLEAN_encode_xer;
#endif /* _BOOLEAN_H_ */

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <ENUMERATED.h>
/*
@ -12,11 +13,13 @@ static ber_tlv_tag_t asn1_DEF_ENUMERATED_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_ENUMERATED = {
"ENUMERATED",
INTEGER_free, /* Implemented in terms of INTEGER */
INTEGER_print, /* Implemented in terms of INTEGER */
asn_generic_no_constraint,
INTEGER_decode_ber, /* Implemented in terms of INTEGER */
INTEGER_encode_der, /* Implemented in terms of INTEGER */
INTEGER_print, /* Implemented in terms of INTEGER */
INTEGER_free, /* Implemented in terms of INTEGER */
0, /* Not implemented yet */
INTEGER_encode_xer, /* Implemented in terms of INTEGER */
0, /* Use generic outmost tag fetcher */
asn1_DEF_ENUMERATED_tags,
sizeof(asn1_DEF_ENUMERATED_tags) / sizeof(asn1_DEF_ENUMERATED_tags[0]),

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <GeneralString.h>
/*
@ -13,11 +14,13 @@ static ber_tlv_tag_t asn1_DEF_GeneralString_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_GeneralString = {
"GeneralString",
OCTET_STRING_free,
OCTET_STRING_print, /* non-ascii string */
asn_generic_unknown_constraint,
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_print, /* non-ascii string */
OCTET_STRING_free,
0, /* Not implemented yet */
OCTET_STRING_encode_xer, /* Implemented in terms of OCTET STRING */
0, /* Use generic outmost tag fetcher */
asn1_DEF_GeneralString_tags,
sizeof(asn1_DEF_GeneralString_tags)

View File

@ -2,6 +2,7 @@
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <GeneralizedTime.h>
#include <time.h>
#include <errno.h>
@ -113,11 +114,13 @@ static ber_tlv_tag_t asn1_DEF_GeneralizedTime_tags[] = {
};
asn1_TYPE_descriptor_t asn1_DEF_GeneralizedTime = {
"GeneralizedTime",
OCTET_STRING_free,
GeneralizedTime_print,
GeneralizedTime_constraint, /* Check validity of time */
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
GeneralizedTime_encode_der, /* Implemented in terms of OCTET STRING */
GeneralizedTime_print,
OCTET_STRING_free,
0, /* Not implemented yet */
GeneralizedTime_encode_xer,
0, /* Use generic outmost tag fetcher */
asn1_DEF_GeneralizedTime_tags,
sizeof(asn1_DEF_GeneralizedTime_tags)
@ -153,12 +156,12 @@ GeneralizedTime_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
return 0;
}
der_enc_rval_t
asn_enc_rval_t
GeneralizedTime_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
GeneralizedTime_t *st = (GeneralizedTime_t *)ptr;
der_enc_rval_t erval;
asn_enc_rval_t erval;
/* If not canonical DER, re-encode into canonical DER. */
if(st->size && st->buf[st->size-1] != 'Z') {
@ -194,6 +197,36 @@ GeneralizedTime_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
return erval;
}
asn_enc_rval_t
GeneralizedTime_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,