📄 gen_decode.c
字号:
/* * Copyright (c) 1997 - 2006 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "gen_locl.h"#include "lex.h"RCSID("$Id: gen_decode.c 21503 2007-07-12 11:57:19Z lha $");static voiddecode_primitive (const char *typename, const char *name, const char *forwstr){#if 0 fprintf (codefile, "e = decode_%s(p, len, %s, &l);\n" "%s;\n", typename, name, forwstr);#else fprintf (codefile, "e = der_get_%s(p, len, %s, &l);\n" "if(e) %s;\np += l; len -= l; ret += l;\n", typename, name, forwstr);#endif}static intis_primitive_type(int type){ switch(type) { case TInteger: case TBoolean: case TOctetString: case TBitString: case TEnumerated: case TGeneralizedTime: case TGeneralString: case TOID: case TUTCTime: case TUTF8String: case TPrintableString: case TIA5String: case TBMPString: case TUniversalString: case TVisibleString: case TNull: return 1; default: return 0; }}static voidfind_tag (const Type *t, Der_class *cl, Der_type *ty, unsigned *tag){ switch (t->type) { case TBitString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_BitString; break; case TBoolean: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_Boolean; break; case TChoice: errx(1, "Cannot have recursive CHOICE"); case TEnumerated: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_Enumerated; break; case TGeneralString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_GeneralString; break; case TGeneralizedTime: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_GeneralizedTime; break; case TIA5String: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_IA5String; break; case TInteger: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_Integer; break; case TNull: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_Null; break; case TOID: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_OID; break; case TOctetString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_OctetString; break; case TPrintableString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_PrintableString; break; case TSequence: case TSequenceOf: *cl = ASN1_C_UNIV; *ty = CONS; *tag = UT_Sequence; break; case TSet: case TSetOf: *cl = ASN1_C_UNIV; *ty = CONS; *tag = UT_Set; break; case TTag: *cl = t->tag.tagclass; *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; *tag = t->tag.tagvalue; break; case TType: if ((t->symbol->stype == Stype && t->symbol->type == NULL) || t->symbol->stype == SUndefined) { error_message("%s is imported or still undefined, " " can't generate tag checking data in CHOICE " "without this information", t->symbol->name); exit(1); } find_tag(t->symbol->type, cl, ty, tag); return; case TUTCTime: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_UTCTime; break; case TUTF8String: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_UTF8String; break; case TBMPString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_BMPString; break; case TUniversalString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_UniversalString; break; case TVisibleString: *cl = ASN1_C_UNIV; *ty = PRIM; *tag = UT_VisibleString; break; default: abort(); }}static voidrange_check(const char *name, const char *length, const char *forwstr, struct range *r){ if (r->min == r->max + 2 || r->min < r->max) fprintf (codefile, "if ((%s)->%s > %d) {\n" "e = ASN1_MAX_CONSTRAINT; %s;\n" "}\n", name, length, r->max, forwstr); if (r->min - 1 == r->max || r->min < r->max) fprintf (codefile, "if ((%s)->%s < %d) {\n" "e = ASN1_MIN_CONSTRAINT; %s;\n" "}\n", name, length, r->min, forwstr); if (r->max == r->min) fprintf (codefile, "if ((%s)->%s != %d) {\n" "e = ASN1_EXACT_CONSTRAINT; %s;\n" "}\n", name, length, r->min, forwstr);}static intdecode_type (const char *name, const Type *t, int optional, const char *forwstr, const char *tmpstr){ switch (t->type) { case TType: { if (optional) fprintf(codefile, "%s = calloc(1, sizeof(*%s));\n" "if (%s == NULL) %s;\n", name, name, name, forwstr); fprintf (codefile, "e = decode_%s(p, len, %s, &l);\n", t->symbol->gen_name, name); if (optional) { fprintf (codefile, "if(e) {\n" "free(%s);\n" "%s = NULL;\n" "} else {\n" "p += l; len -= l; ret += l;\n" "}\n", name, name); } else { fprintf (codefile, "if(e) %s;\n", forwstr); fprintf (codefile, "p += l; len -= l; ret += l;\n"); } break; } case TInteger: if(t->members) { fprintf(codefile, "{\n" "int enumint;\n"); decode_primitive ("integer", "&enumint", forwstr); fprintf(codefile, "*%s = enumint;\n" "}\n", name); } else if (t->range == NULL) { decode_primitive ("heim_integer", name, forwstr); } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { decode_primitive ("integer", name, forwstr); } else if (t->range->min == 0 && t->range->max == UINT_MAX) { decode_primitive ("unsigned", name, forwstr); } else if (t->range->min == 0 && t->range->max == INT_MAX) { decode_primitive ("unsigned", name, forwstr); } else errx(1, "%s: unsupported range %d -> %d", name, t->range->min, t->range->max); break; case TBoolean: decode_primitive ("boolean", name, forwstr); break; case TEnumerated: decode_primitive ("enumerated", name, forwstr); break; case TOctetString: decode_primitive ("octet_string", name, forwstr); if (t->range) range_check(name, "length", forwstr, t->range); break; case TBitString: { Member *m; int pos = 0; if (ASN1_TAILQ_EMPTY(t->members)) { decode_primitive ("bit_string", name, forwstr); break; } fprintf(codefile, "if (len < 1) return ASN1_OVERRUN;\n" "p++; len--; ret++;\n"); fprintf(codefile, "do {\n" "if (len < 1) break;\n"); ASN1_TAILQ_FOREACH(m, t->members, members) { while (m->val / 8 > pos / 8) { fprintf (codefile, "p++; len--; ret++;\n" "if (len < 1) break;\n"); pos += 8; } fprintf (codefile, "(%s)->%s = (*p >> %d) & 1;\n", name, m->gen_name, 7 - m->val % 8); } fprintf(codefile, "} while(0);\n"); fprintf (codefile, "p += len; ret += len;\n"); break; } case TSequence: { Member *m; if (t->members == NULL) break; ASN1_TAILQ_FOREACH(m, t->members, members) { char *s; if (m->ellipsis) continue; asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); if (s == NULL) errx(1, "malloc"); decode_type (s, m->type, m->optional, forwstr, m->gen_name); free (s); } break; } case TSet: { Member *m; unsigned int memno; if(t->members == NULL) break; fprintf(codefile, "{\n"); fprintf(codefile, "unsigned int members = 0;\n"); fprintf(codefile, "while(len > 0) {\n"); fprintf(codefile, "Der_class class;\n" "Der_type type;\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -