📄 description
字号:
position of one of these pointers is the unique type numberwe give to its corresponding type. The pointer referencesan array of type tpe or ptpe, depending whether it is anentry in the decoding/encoding tables or printing tablesrespectively. See _p_e_p._h in the _p_e_p_s_y directory. This arrayactually contains the necessary information toencode/decode/print that ASN.1 type. So given the modtypstructure of an ASN.1 module and its type number you cancall a routine to encode, decode or print that type. The rest of this document assumes a good knowledge ofASN.1 notation so go read a copy if you haven't already.From here on I shall mention only tpe and this means tpe inthe case of encoding or decoding and ptpe in the case ofprinting, unless otherwise stated. Each type is representedby an array of tpe (or ptpe for printing). The basic ele-ment consists of four integer fields, the printing table isthe same with an addition char pointer field which containsthe name corresponding to that entry in the ASN.1 grammar.The first specifies the type of the entry and determines howthe rest are interpreted. The possible types are listed in_p_e_p_s_y/_p_e_p._h. Each type is an array which starts with anentry of type PE_START and ends with one of type PE_END.Each primitive type requires one entry to specify it, apartfrom possible PE_START and PE_END used to specify the startand end of the type. Constructed types are represented by alist of entries terminated by an entry of type PE_END. AsASN.1 types can be nested inside so will the representationin tpe entries be nested. For example the ASN.1 type defin-ition: Example1 ::= SEQUENCE { seq1 SEQUENCE { an-i INTEGER, an-ostring OCTET STRING }, a-bool IMPLICIT [0] BOOLEAN January 23, 1990 - 7 - } Will generate an encoding array:static tpe et_Example1Test[] = { { PE_START, 0, 0, 0 }, { SEQ_START, 0, 16, FL_UNIVERSAL }, { SEQ_START, OFFSET(struct type_Test_Example1, seq1), 16, FL_UNIVERSAL }, { INTEGER, OFFSET(struct element_Test_0, an__i), 2, FL_UNIVERSAL }, { OCTETSTRING, OFFSET(struct element_Test_0, an__ostring), 4, FL_UNIVERSAL }, { PE_END, 0, 0, 0 }, { BOOLEAN, OFFSET(struct type_Test_Example1, a__bool), 0, FL_CONTEXT }, { PE_END, 0, 0, 0 }, { PE_END, 0, 0, 0 } }; Here the second last PE_END matches and closes off thefirst SEQ_START. The entries which correspond to the otherprimative types are pretty obvious, with the INTEGER entrycorresponding to the primative INTEGER. For fields thatgenerate data the general interpretation of the other threefields is offset, tag and flags/class fields respectively.offsetThe second field gives the offset in a C data struc- ture needed to reference the data that corresponds to this table entry. Each ASN.1 type has C structure types generated as described in the ISODE manuals, volume 4 "The applications Cookbook" Section 5.2, "POSY Environment". As this offset may have to be determined in a compiler dependent manner a C preprocessor macro is used hide the actual details.tag This is the tag associated with the ASN.1 type for that entry. Notice that in the example the [0] IMPLICIT which changes the tag associated with the BOOLEAN entry actually has the correct tag of 0 in the table. Like- wise SEQUENCE has the correct tag of 16 in its SEQ_START entry and so on for the others.flags/class This contains the ASN.1 class associated with the entry's type. That is UNIVERSAL for all except the BOOLEAN type which is CONTEXT class. This fourth can also contain flags that specify if the type is OPTIONAL or DEFAULT. There is plenty of room here as there is only four possibly classes. Now that you have some idea of how these arrays arearranged for a type definition I will proceed to go throughthe possible type of entries and describe what they do andhow they work. These values are defined in _p_e_p_s_y/_p_e_p._h.Those entries with a value below TYPE_DATA are entries thatdon't correspond to data to be encoded/decoded and are forother book keeping type purposes. January 23, 1990 - 8 -PE_START and PE_END As explained above PE_START starts the beginning of a ASN.1 type's array. It probably isn't necessary but the size of the tables is so small it isn't much of an over head to keep around for cosmetic reasons. The entry type PE_END is necessary to mark the end of some compound type as well as the end of ASN.1 data type.XOBJECT and UCODE These are obsolete types and probably should be removed. They were to allow C code written directly by the user to be incorporated into the encoding/decoding but it was found unnecessary. Prehaps some brave soul would like to use them in an attempt to implement a similar system based on _p_e_p_y which is what we first attempted to do until we found this to be much easier.MALLOCThis field only occurs in the decoding tables. It specifies how much space to malloc out for the current C structure it is just inside of. For instance in the example above the decoding table has the following entry: { MALLOC, 0, sizeof (struct type_Test_Example1), 0 }, just after the first SEQ_START entry. It tells it to malloc out a struct type_Test_Example1 structure to hold the data from the sequence when it is decoded.SCTRLThis entry is used in handling the ASN.1 CHOICE type. The C type generated for ASN.1 CHOICE type is a struc- ture with an offset field in it and a union of all the C types present in the CHOICE. Each ASN.1 type in the CHOICE of types has a C type definition generated for it. The union is of all these types, which is quite a logical way to implement a CHOICE type. The offset field specifies which possibility of interpreting the union should be used (which _m_e_m_b_e_r should selected). As such it needs to be read by the encoding routines when encoding the data from the C data structures and to be set by the decoding routines when it is decoding the data into the C data structures. There is one such entry for each CHOICE type to specify where the offset field is.CH_ACTAnother redundant entry type. I think this was also used in code to handle C statements or actions speci- fied by the user. It probably should be removed.OPTL This is used to handle the optionals field that is gen- erated by posy when optional types that are _n_o_t imple- mented by pointers are present in the ASN.1 type. For example if an ASN.1 type has an optional integer field how does the encoding routine determine if the integer January 23, 1990 - 9 - is to be present or not? If it was implemented as a pointer it could use a NULL (zero) pointer to mean that the type was not present because NULL is guaranteed to never occur as a legal pointer to a real object. But all the possible values for integer could be legally passed so instead for these types which are not pointers and are optional a bit map is allocated in the structure. Each non pointer optional type a bit from the bit map is allocated. If that bit is set the corresponding type is presentand it is not present if the bit is not set. Each bit has a#define generated for it. The bit map is merely an integerfield called "optionals" limiting maximum number of suchoptionals to 32 on Sun machines, 16 on some others. (Anarray of char as BSD fd_sets would have avoid all such lim-its, not that this limit is expected to be exceeded veryoften !) Like the SCTRL entry this entry merely serves tospecify where this field is so it can be test and set by theencoding and decoding routines respectively.ANY and CONS_ANY The C type corresponding to the entry is a PE pointer. To conform with _p_e_p_y the tag and class of this entry are ignored, which may or may not be the most sensible thing. The CONS_ANY is a redundant symbol which means the same thing but is not used. This should be clean up and removed.INTEGER, BOOLEAN, BITSTRING, OCTETSTRING and OBJID These are just as described in the first article. See the ISODE manual to find out what they are allocated as a C data type to implement them. The offset fields says where to find this data type with in the current structure.SET_START, SETOF_START, SEQ_START and SEQOF_START These compound entries differ from the above in that they group all the following entries together up to the matching PE_END. The entries with OF in them correspond to the ASN.1 types which have OF in them e.g. SET OF. Allowing the OF items to have an arbi- trary number of entries is excessive flexibility, they can only have one type by the ASN.1 grammar rules. The C data type corresponding to them is either a structure if it is the first such type in the array or a pointer to a structure is isn't. This complicates the process- ing of these structures a little but not greatly. The OF types differ one other important way, they may occur zero, one or more times, with no upper bound. To cope with this the C data type is a linked list structure. The pointer to the data structure determines whether or not there is another occurrence of the type, if it is NULL there isn't. Thus each data structure has this January 23, 1990 - 10 - pointer to the next occurrence, the offset of this pointer is placed in the PE_END field where it can con- veniently be used to determine whether or not to make another pass through the table entry.OBJECTWhen one type references another it generates an OBJECT entry. This specifies the type number of the type which is present in the 3rd field of the tpe structure, pe_tag. The 2nd field still gives the offset in the C data structure which specifies where the user's data for that type is to be found. Usually this a pointer to the C data structure for that type.T_NULLThis entry means the ASN.1 primative type NULL. It doesn't have any body and consequently has no offset as it cannot carry data directly. Only its absence or presence can mean anything so if it is optional it sets or clears a bit in the bit map as described earlier for OPTL entry.T_OIDThis use to be used for Object Identifiers and now is unused, it should be got rid.OBJIDThis corresponds to the Object Identifier ASN.1 type primitive. It is implemented the same as other prima- tive types like INTEGER and OCTET STRING.ETAG This entry gives the explicit tag of the following entry. The usual fields which define class and tag are the only ones which have meaning in this entry. By concatenating successive ETAG entries it is possibly to build up an limited number explicit tags, although this hasn't been tested yet.IMP_OBJ If a type has an implicit tag usually all we have to do is set its tag and class appropriately in its entry. This works for all but one important case, the refer- ence of another type. This is messy because we can't alter the definition of the type with out wrecking it for the other uses. So what we do for encoding is build the type normally and then afterward it is built change its tag and class to be the values we want. Similarly for decoding we match the tag and class up and then decode the body of the type. We can't use a OBJECT entry for this because among other reasons there 3rd field is already to store the type number. (The forth needs to be free to contain flags such as DEFAULT and OPTIONAL) So a new entry type is used, IMP_OBJ, to hold the tag and class. It must be followed by an OBJECT entry which is used to handle the type as nor- mal, the IMP_OBJ entry gives the tag and class to be used. Like the ETAG entry the IMP_OBJ affects the entry that follows it. January 23, 1990 - 11 -EXTOBJ and EXTMOD These handle external type references. This is just like a normal (internal?) type reference except we must now specify which module as well as the type. Simi- larly because there are no more free fields in the OBJECT type we need two entries to hold all the infor- mation we need. The EXTMOD occurs first and holds the type number and the offset into the C data structure and the flags, exactly as for an OBJECT entry. The next entry, which must be an EXTMOD, contains a pointer to the modtyp structure for its module. Like a normal OBJECT entry to handle the case of an implicit tag an IMP_OBJ entry would occur before these two entries which gives the class and tag. Likewise it could have an explicit tag in which the two entries would be pro- ceeded by an ETAG entry.DFLT_F and DFLT_B When a type has a default value, to handle decoding and encoding properly you need to know its value. As there is no space to store the value in most entries we allo- cate a whole entry to specify the value. When encoding it is convenient to have the default occur before the entry it refers to. This allows a single check to han- dle all the default encoding. All it has to do is check whether it is the same as the default value and if so not bother encoding the next type. On the other hand when decoding it is more convenient to have the entry after the one it refers to. In this case we need to determine that it is missing before we use the default value to determine the value to pass to the user. To handle this we have entries of both types. _D_F_L_T__F contains the default value for the following entry (F = Front) and DFLT_B contains that for the entry before it (B = Back). Consequently DFLT_F are only used in the decoding tables and DFLT_B entries are only used in the decoding (and printing tables).S-Types These types are entries for the same ASN.1 type as the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -