From c2c77dbd91905c58a81f43e433053dbe15f8894b Mon Sep 17 00:00:00 2001 From: CSRG Date: Thu, 21 Jun 1990 19:35:46 -0800 Subject: [PATCH] BSD 4_3_Net_2 development Work on file usr/src/contrib/isode/pepsy/doc/DESCRIPTION Work on file usr/src/contrib/isode/pepsy/doc/Makefile Work on file usr/src/contrib/isode/pepsy/doc/overview.ms Work on file usr/src/contrib/isode/pepsy/doc/tables.ms Work on file usr/src/contrib/isode/pepsy/doc/wt-pep.ms Synthesized-from: CSRG/cd2/net.2 --- usr/src/contrib/isode/pepsy/doc/DESCRIPTION | 1056 +++++++++++++++++++ usr/src/contrib/isode/pepsy/doc/Makefile | 10 + usr/src/contrib/isode/pepsy/doc/overview.ms | 271 +++++ usr/src/contrib/isode/pepsy/doc/tables.ms | 353 +++++++ usr/src/contrib/isode/pepsy/doc/wt-pep.ms | 201 ++++ 5 files changed, 1891 insertions(+) create mode 100644 usr/src/contrib/isode/pepsy/doc/DESCRIPTION create mode 100644 usr/src/contrib/isode/pepsy/doc/Makefile create mode 100644 usr/src/contrib/isode/pepsy/doc/overview.ms create mode 100644 usr/src/contrib/isode/pepsy/doc/tables.ms create mode 100644 usr/src/contrib/isode/pepsy/doc/wt-pep.ms diff --git a/usr/src/contrib/isode/pepsy/doc/DESCRIPTION b/usr/src/contrib/isode/pepsy/doc/DESCRIPTION new file mode 100644 index 0000000000..2f861f5264 --- /dev/null +++ b/usr/src/contrib/isode/pepsy/doc/DESCRIPTION @@ -0,0 +1,1056 @@ + + + + + + +_1. _O_v_e_r_v_i_e_w _o_f _p_e_p_s_y _s_y_s_t_e_m + + This section describes how the various parts fit +together to make the system work. The principle behind +pepsy is fairly simple. The ASN.1 is summarised as tables +of integers. These tables are read by driver routines which +encode or decode data to or from the internal format that +ISODE OSI implementation uses. In ISODE specific functions +are generated for each ASN.1 type defined in contrast the +pepsy merely generates a new table of data which is far far +smaller. + + As there is a great deal of effort invested in the +ISODE interface to the encoding/decoding routines pepsy +automatically provides macros which map the original func- +tions into the appropriate function call of a driver. This +allows existing posy using code to switch to the pepsy sys- +tem with no changes to the code provided no function +pointers are used to the original ISODE functions. Even +when there are function pointers used the changes are very +simple and take only a few hours to implement. + +_1._1. _B_r_i_e_f _d_e_s_c_r_i_p_t_i_o_n _o_f _t_h_e _u_s_e _o_f _t_h_e _p_e_p_s_y _s_y_s_t_e_m. + +_1._1._1. _O_u_t_l_i_n_e _o_f _t_h_e _f_i_l_e_s _p_r_o_d_u_c_e_d _u_n_d_e_r _t_h_e _p_e_p_s_y _s_y_s_- +_t_e_m. + + The pepsy system consists of a program called _p_o_s_y +which translates ASN.1 modules into a set of tables, called +_p_o_s_y at the moment, and library of driver routines, called +_l_i_b_p_e_p_s_y._a. Running this _p_o_s_y program on the ASN.1 file +will produce several files. If the name of the ASN.1 module +is MODULE the following files are generated: + +MODULE-types.h + which contains C structure definitions. The user of + the library provides data as a linked list of these C + data structures and expects to receive data back as a + similar linked list. These data structures are exactly + the same as those produced by the original ISODE _p_o_s_y + so that existing software written for the old _p_o_s_y pro- + gram needs no change. For details on the C data struc- + tures types generated see the documentation of the ori- + ginal _p_o_s_y program in volume 4 Chapter 5 of the ISODE + manuals. + +MODULE_tables.c + This file contains the tables generated by the new _p_o_s_y + program. These tables consist of three parts, the + first which contains the summary of ASN.1 types. Each + type is summarised as an array of a primitive type, + struct pte, for encoding and decoding, and struct ptpe + for printing. As implied there is one array for each + type for each of encoding, decoding and printing as + + + + January 23, 1990 + + + + + + - 2 - + + + specified when _p_o_s_y is run. The next part contains up + to three tables of pointers to these arrays. Each of + the three different types of arrays, encoding, decoding + and printing, has its own table of pointers. Finally + there is the module type definition which contains con- + tains pointers to these tables and some other useful + information about the module such as its name. This + module type structure, which is typedefed to modtyp, is + the only piece of data which is global, all the rest of + the data is static and is only addressable via the mod- + typ data structure. This provides a kind of object + oriented approach to handling the tables. Once you are + passed a pointer to an ASN.1's modtyp structure you can + encode, decode and print any of its types by calling + the appropriate libpepsy.a routine with its type + number. + +MODULE_pre_defs.h + This file contains #defines symbol of each of the ASN.1 + types to its type number, which is used when calling a + libpepsy.a routine. Each symbol is _Ztype-nameMODULE + where _t_y_p_e-_n_a_m_e is the name of the type with dashes (-) + turned into underscores (_) and _M_O_D_U_L_E is the name of + the module. For example of the ASN.1 universal type + _G_r_a_p_h_i_c_S_t_r_i_n_g would have the #define symbol _ZGra- + phicStringUNIV. The __Z is prepended to try to make the + symbols unique. This file also contains and extern + declaration for the modtyp data for its module. + +MODULE_defs.h + This file contains macros for all the encoding, decod- + ing and printing functions that the _p_e_p_y program would + have for these ASN.1 types. This allows much of the + code that uses the routines generated by running the + old _p_o_s_y program and taking its output and running _p_e_p_y + on augmented ASN.1 output can be recompiled unchanged. + If the code used pointers to these functions it is + necessary to change it to pass around the type numbers + instead and to call appropriately call a libpepsy.a + library routine with the type number. As pointers to + the printing routines in ISODE are passed as arguments + a #define is provided to turn the argument into the + pair of arguments, type number and pointer to modtyp + structure, which are needed to allow the diagnostic + printing code to work with no change for the current + ISODE stack. This file also contains a #include of the + _M_O_D_U_L_E__p_r_e__d_e_f_s._h file. + + As the _M_O_D_U_L_E-_t_y_p_e_s._h file #include's the _M_O_D_U_L_E__d_e_f_s._h +file no further #includes need to be added to the files +using the encoding/decoding/printing functions. This means +that code written to use posy/pepy system may need no change +at all and the only effort required is to change the +Makefile to use the pepsy system. If there is code changes + + + + January 23, 1990 + + + + + + - 3 - + + +required it would most likely be because function pointers +are used to reference the functions generated by posy. If +only the _p_e_p_y system was used, not posy then pepy, with code +placed inside action statements then quite a large amount of +work may be needed to change over to the new system, depend- +ing on how large and complex the _p_e_p_y module is. + +_1._1._2. _O_u_t_l_i_n_e _o_f _t_h_e _p_e_p_s_y _l_i_b_r_a_r_y. + +enc.cThis contains the routines that encode data from the C + data structures into ISODE's PElement linked list data + structure which it uses for all presentation data. The + most important function to pepsy users is enc_f which + called to encode a particular type. It is passed the + type number and a pointer to modtyp structure for that + module and then the rest of the arguments which are + passed to an encode function generated by _p_o_s_y/_p_e_p_y + system. See the documentation in Volume 4, "The Appli- + cations Cookbook", Section 6.4 called "Pepy Environ- + ment". Most of these latter arguments are ignored, + only parm and pe, are used. + + Contrary to what the ISODE documentation says these +ignored parameters are hardly ever used by existing code. +We have not found a single case where used for encoding a +named type, which is all that the user can reference anyway, +so we don't see any problems with ignoring these other +parameters. Hopefully one day they can be thrown away +entirely, until then they are actually passed the the encod- +ing function. + + The rest of the functions are mostly recursive routines +which encode a particular type of table entry. For example +SEQUENCE is encoded by en_seq which may call itself or oth- +ers to encode the types from which it is built up. The +function en_type builds up a simple type and en_obj encodes +a new type (object) and so on with other functions. There +are a few utility routines in the file such as same which +determines whether the value is the same as the default +value also. + +dec.cThis file contains the decoding routines that translate + presentation data into C data structures defined in the + MODULE-types.h is like _e_n_c._c. It is very much like the + file _e_n_c._c except the routines do the reverse tasks The + routines are structured in a very similar way. We have + dec_f which is called by the user to decode a type and + like enc_f takes the same arguments as the decoding + functions generated by _p_o_s_y with two additions, the + type number and a pointer to the modtyp structure for + that module. Likewise the other functions are very + much like those of enc.c + +prnt.cThis file contains the routines that print the + + + + January 23, 1990 + + + + + + - 4 - + + + presentation data in a format similar to that generated + by _p_e_p_y's printing functions. It's main function + prnt_f is takes the same arguments as the printing + function generated by _p_e_p_y as well as the now familiar + type number and modtyp pointer. The functions are + modeled on the decoding routines as it has similar job + to. The only difference is that instead of storing the + decoded data into a C data structure it is nicely + printed out. + +fr.c This file contains code to free the data structures + defined in MODULE-types.h. Likewise if the -f flag is + given when generating the types file it also includes + macros in the types file which replace the freeing + functions generated by ISODE's _p_o_s_y. The function that + the user calls us fre_obj which takes a pointer to the + data structure, its decoding table entry and a pointer + to the modtyp structure for the module. The freeing is + based on the decoding routines except instead of decod- + ing all it does is free each part of the data struc- + ture, which might involve recursive calls, then it + frees the data structure at the end. + +util.cThis contains the utility routines used by more than + one of the above files. This is mostly diagnostic rou- + tines at the moment, more general routines could be + included in here. If there is an error at the moment + which it can't recover from it just prints out a mes- + sage on standard error and calls exit. Not perfect and + this is something that will need work. + +main.cThis contains code to perform a series of tests on the + _p_e_p_s_y library which is a useful check to see whether + any of the routines has been broken by any changes + made. It basically loops through a whole series of + test cases. Each test case is encoded from some built + in test data and then decoded and checked to see if the + data has changed in the transfer. If it is compiled + with -_D_P_R_N_T=_1 the encoded data is also printed out to + check the printing routines which generates a vast + amount of output. Finally the free routines are used + to free the allocated data, although it can not + directly check the free routines to see if they work, + it can be used with a malloc tracing package to check + that the routines work. + +test_table.h + This contains the test cases that _m_a_i_n._c program runs. + Each entry in the table corresponds to a type. One of + the fields is count of how many times that type is to + be tested to try out the different possibly data values + it might have. + +pep.h and pepdefs.h + + + + January 23, 1990 + + + + + + - 5 - + + + These files contain the definition of types used for + the tables that drive the encoding/decoding/printing + routines. All the constants used in that table are + defined here via #defines. The modtyp structure is + defined in _p_e_p_d_e_f_s._h. + +t1.py and t2.py + These are test ASN.1 modules that are used by _m_a_i_n._c + routines to check the _p_e_p_s_y library. The file _t_1._p_y + contains the majority of different types with a few of + a different module provided in _t_2._p_y. This allows the + testing of the code for handling ASN.1 external refer- + ences, i.e. references to types defined in other, + external, modules. + +_1._1._3. _N_e_w _f_i_l_e_s _i_n _t_h_e _p_e_p_y _d_i_r_e_c_t_o_r_y + +etabs.c, dtabs.c and ptabs.c + These files contain the code to generate the + encoding/decoding/printing tables. The main routine in + _e_t_a_b_s._c is tenc_typ which is called on each ASN.1 type + to generate an array of entries which describe how to + encode that type. See the details section for more + information about how the table entries function. + Similarly _d_t_a_b_s._c contains the routine tdec_typ which + is called on each type to generate its decoding table + entries. Likewise tprnt_typ routine generates the + arrays of table entries for the printing tables. This + function is in _p_t_a_b_s._c. + +dfns.cThis file contains miscellaneous string handling rou- + tines and hash table routines that don't really belong + anywhere else. Some of the routines could be cleaned + up in that they tend not to free memory they use. + +mine.hThis file contains the definitions for the hash + table(s) that are used to keep track of the ASN.1 + types. This could probably be done with out a hash + table, should anyone want to clean this up, feel wel- + come. The lookup function is in _d_f_n_s._c. + +pass2.h + This file has most of the #defines for the table gen- + erating program. Most of the prefixes and suffixes of + function names and files names are defined here so, + hopefully, the names can be changed by merely changing + the definition. This contains most of the important + definitions needed by the changes to the _p_o_s_y program + needed to generate tables. + +posy.hThis contains the definition of a symbol which is now + needed outside of the the main routine and the yacc + file. By putting it here we can include it any file + that needs to know it with out putting in any that + + + + January 23, 1990 + + + + + + - 6 - + + + doesn't need it and with out including all the other + definitions that occur in _p_e_p_y._h. The structure and + meaning of the tables generated from the ASN.1 grammar + + Each collection of ASN.1 grammar is called a module. +(See ASN.1 ) Each ASN.1 module is completely specified in +the program by a single C structure of type modtyp and the +data which it references. See the _p_e_p_d_e_f_s._h file in the +_p_e_p_s_y directory. For each ASN.1 module there are three +tables that are generated fromASN.1 grammar. These initial- +ised arrays which we call tables are called the encoding, +decoding and printing tables. Each of these tables is +referenced through a different pointer of the modtyp struc- +ture. + + Each of these pointers references an array of pointers, +one pointer for each ASN.1 type defined in the module. The +position of one of these pointers is the unique type number +we give to its corresponding type. The pointer references +an array of type tpe or ptpe, depending whether it is an +entry in the decoding/encoding tables or printing tables +respectively. See _p_e_p._h in the _p_e_p_s_y directory. This array +actually contains the necessary information to +encode/decode/print that ASN.1 type. So given the modtyp +structure of an ASN.1 module and its type number you can +call a routine to encode, decode or print that type. + + The rest of this document assumes a good knowledge of +ASN.1 notation so go read a copy if you haven't already. +From here on I shall mention only tpe and this means tpe in +the case of encoding or decoding and ptpe in the case of +printing, unless otherwise stated. Each type is represented +by an array of tpe (or ptpe for printing). The basic ele- +ment consists of four integer fields, the printing table is +the same with an addition char pointer field which contains +the name corresponding to that entry in the ASN.1 grammar. +The first specifies the type of the entry and determines how +the 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 an +entry of type PE_START and ends with one of type PE_END. +Each primitive type requires one entry to specify it, apart +from possible PE_START and PE_END used to specify the start +and end of the type. Constructed types are represented by a +list of entries terminated by an entry of type PE_END. As +ASN.1 types can be nested inside so will the representation +in 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 the +first SEQ_START. The entries which correspond to the other +primative types are pretty obvious, with the INTEGER entry +corresponding to the primative INTEGER. For fields that +generate data the general interpretation of the other three +fields 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 are +arranged for a type definition I will proceed to go through +the possible type of entries and describe what they do and +how 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 that +don't correspond to data to be encoded/decoded and are for +other 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 present +and it is not present if the bit is not set. Each bit has a +#define generated for it. The bit map is merely an integer +field called "optionals" limiting maximum number of such +optionals to 32 on Sun machines, 16 on some others. (An +array of char as BSD fd_sets would have avoid all such lim- +its, not that this limit is expected to be exceeded very +often !) Like the SCTRL entry this entry merely serves to +specify where this field is so it can be test and set by the +encoding 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 + entry type formed by removing the starting `S'. The + above forms would do to handle ASN.1 but we also have + to be compatible with the C data structures generated + by _p_o_s_y. The implementors decided to optimise the C + data structures generated a little means we have to + have all these S type entries. If a type was a single + field in most cases they produced a #define which elim- + inates the need to have a whole structure just for that + type. In all the places where this type is used the + field of the C structure is changed from a pointer to + field which holds the value directly in the structure. + See the ISODE reference given above for more details. + + We handle this by generating the same tables that would + + + + January 23, 1990 + + + + + + - 12 - + + +be generated with out the optimisation, except the optimised +types the S-type of entries instead of the normal ones. For +example an optimised OCTET STRING would have the type field +of its entry as SOCTETSTRING instead of OCTETSTRING. The +only difference in how S type and its corresponding normal +are handle is how they find the C data structure for that +entry. That difference is that there is no indirection +through pointers. + +Flags field + Besides the encoding the class the pe_flags field also + contains a few possible flags. Mainly FL_OPTIONAL + which means the ASN.1 type corresponding to this flag + is OPTIONAL. Consequently when encoding it has to + determine if the type is present in the user data pos- + sibly using the bit map as described under the OPTL + entry. Likewise when decoding it may have to set a bit + in the bit map appropriately. The other flag at the + moment is FL_DEFAULT which means the entry corresponds + to an ASN.1 DEFAULT type. This bit is still needed as + not all types have DFLT_* entries implmented for them + at the moment. In particular compound value things + like SEQUENCE and SET can't have thier default value + specified. This is consistent with ISODE, if fact + implementing that may even break existing ISODE code. + This last flag FL_IMPLICIT is obsolete and not not used + any where. + + +_1._2. _W_a_l_k _t_h_r_o_u_g_h _o_f _p_e_p_s_y _l_i_b_r_a_r_y _r_o_u_t_i_n_e_s. + + Here we walk through all the pepsy library routines at +least briefly. If any new routines are added or a routine +changed this documentation is the most likely part that will +need changing. First we give some theory as to how the task +have have been brocken into routines then describe each +function in detail. We assume you are familiar with ISODE's +PE data structure manipulation routines. if not they are +documented in the ISODE manuals, Volume one, chapter 5, +"Encoding of Data-Structures" (It actually covers decoding +as well). + +_1._2._1. _O_v_e_r_v_i_e_w _o_f _p_e_p_s_y _l_i_b_r_a_r_y + + Each seperate task is put into a different file. So +all the encoding stuff is in _e_n_c._c, all the decoding stuff +is in _d_e_c._c, printing stuff in _p_r_n_t._c and freeing stuff in +_f_r_e._c. Actually it breaks down a little in practice, some +of the routines for moving around the tables are used in +both _e_n_c._c and _d_e_c._c for example. Probably they should +defined in _u_t_i_l._c so that linking one of the files from the +library doesn't force linking any other except _u_t_i_l._o. + + There is a common structure to each of the major files + + + + January 23, 1990 + + + + + + - 13 - + + +as well. There is a main routine which the user calls to +obtain the services provided by that file's routines. As +all the files revolve about processing the table entries +their structure is based on running through the table +entries. + + We shall call each array of entries a table or an +object. There is a routine, usually with a name ending in +_obj, which is designed to process an object. For example +en_obj is the routine called to generated an encoded object. +Then there are routines to call on each compound type such +as en_seq for encode a SEQUENCE. Finally all the primitives +are handled by a one function that ends in _type. This lets +each routine concentrate on handling the features particular +to its type and call the appropriate routine to handle each +type it finds with in its compound type. + + Most of these table processing routines have just three +arguements: which are called parm, p, mod. The parm is char +* or char ** in the encoding and decoding routines respec- +tively. This points to the user's C structure that data to +be encoded is taken from when encoding. When decoding it is +the address of a pointer which is made to point the C struc- +ture filled with the decode data. The freeing, which is +based on the decoding routines, has a char ** while the +printing routines don't look at the user's data and so don't +have such a pointer. The p points to the current table +entry we are up to processing and the mod arguement points +to the modtyp structure for the current module we are pro- +cessing. + + All these processing routines return a PE type, which +is defined in ISODE's file _h/_p_s_a_p._h, and to return zero if +they have an error, but not always. In fact the error han- +dling is needs some work and has not been tested very well. +Generally it tries to print out the table entry where some- +thing went wrong and the name of the function it was in. It +then sometimes does an exit which may not be very pleasent +for the user. + +_1._2._2. _T_h_e _e_n_c_o_d_i_n_g _r_o_u_t_i_n_e_s - _e_n_c._c + +enc_fThis is the the routine made available to the user for + the encoding routines. It is fairly simple as it + leaves all the hard things up to other routines. All + it does is use the type number and modtyp pointer to + get a pointer to the table for encoding that type. + Then it calls the table or object encoding routine, + en_obj, on that object. It first does a consistency + check of making sure the first entry in the table is a + PE_start. Note that it returns an integer (OK or + NOTOK) instead of a PE pointer. This is to be consi- + tent with ISODE functions. + + + + + January 23, 1990 + + + + + + - 14 - + + +en_objWe loop through the entries until we come to the end + of the table and then we return the PE we have built up + from the user's data which is pointed to by parm. In + looping through each entry we call the appropriate rou- + tine to encode its data. The default case is handled + by calling en_type which takes care of all the primi- + tive types. + + The macro NEXT_TPE sets its arguement to point to the +next type in the table, counting compound types as one type. +Thus if NEXT_TPE is called on a SET_START it will skip all +the entries up to and including the matching PE_END. As +many objects consist of one compound type and its components +the main loop will only be run through once. Even when the +object is not based on a compound type it will then consist +of one simple type which is processed by en_type, again +probably going through the loop only once. In fact the only +way it can go through the loop more than once is to process +entries that subsidary to the main type, e.g. ETAG entries +and things like that. To double check this is the case +there is some code that looks for the processing of more +than one data generating entry. + + Much of that testing could probably be eliminated with +no loss. Similarly prehaps the IMP_OBJ and ETAG could be +handled by the default action of calling en_type. As these +routines have evolved after many changes there are things +like that which really need to be looked at closely before +trying. The comment /*SUPRESS 288*/ means suppress warning +288 to saber C debugging tool that we use. + +en_type + This is one of the longest functions as it has so many + cases to handle. It again is structure as a loop over + the types until PE_END but it actually returns as soon + as it has encoded the next type. We can now look at + the encoding of the primative ASN.1 types in detail. + +DFLT_FBecause we have arranged that for encoding tables, + that we precede the entry with a DFLT_F entry we can + neatly handle all the default cases. All we do is + check if the parameter passed in the user data, in + parm, is the same as the default value specified in the + DFLT_F entry. The function same performs this check. + If it is the same don't encode anything just return, + otherwise continue on and encode it. + +ETAG To handle explicit tags we merely allocate a PE with + the right tag and call en_etype to encode its contents, + which are in the following entries. The switch on the + pe_ucode field use to make a difference but now it is + meaningless and should be cleaned up. + +SEQ_START, SEQOF_START, SET_START, SETOF_START + + + + January 23, 1990 + + + + + + - 15 - + + + We merely call the appropriate function handle them. + Note one _i_m_p_o_r_t_a_n_t difference in the way they are + called here from that in enc_obj, the parm arguement is + used as a base to index off and fetch a new pointer to + pass the next function. This seemly bizarre action is + quite straight forward when seen written as it is nor- + mally in C, "parm->offset". Where the field offset is + a pointer which has an offset from the start of the + structure of p->pe_ucode bytes. + + This is the magic of how we access all the different +fields of the C data structures with the one piece of code. +It is also prehaps the most critical dependency of the whole +system on the implementation of the C language. As the BGNU +C compiler supports this feature then it is compilerable on +most machines. But any porters should pay attention to this +to ensure that thier compiler is happy generating these +offsets and compiling these casts properly. + + The reason why this is different from the calls in +en_obj is that this is not the first compound type in the +table. The first and only the first does not have an offset +and does not need to be indirected through any pointers. +All the compound types inside this type will have as their +field a pointer which points to a structure. From here on +we shall say _i_n_d_i_r_e_c_t_i_o_n to mean this adding the pe_ucode +field to the pointer to the structure and using it to refer- +ence a pointer. Whether to use _i_n_d_i_r_e_c_t_i_o_n or not is very +important matter that really needs to be understood to +understand how the routines are structured. + +IMP_OBJ + Here we have to handle the case where we can encode the + object then have to change its tag and class after + encoding. At the end of this entry this is done very + simply by assigning the right values to the appropriate + fields after the object has been built. This means + that if the intermeadiate form is altered this piece of + code may have to be altered as well. There seems to be + no better way of handling this. + + The complication in handling this field is the handling +of all the possible types of object. If it is an external +object we have to perform a call to enc_f with all the right +arguements where a normal OBJECT, the last else branch, +requires a normal call to en_obj. Note the case of SOBJECT +is the same as OBJECT _e_x_c_e_p_t _t_h_e_r_e _i_s _n_o _i_n_d_i_r_e_c_t_i_o_n. + +SOBJECT and OBJECT + Here is the code that handles the two cases sperately. + It is exactly as in the IMP_OBJ case except seperated + out. Note the only difference between the two cases is + lack of indirection in the SOBJECT case. + + + + + January 23, 1990 + + + + + + - 16 - + + +CHOICE_START + This is exactly as all other compound types, like + SEQ_START and OBJECT, we call the appropriate routine + with indirection. From reading the ISODE manuals that + the ASN.1 CHOICE type is handled by a structure of its + own like the other compund types. + +EXTOBJ and SEXTOBJ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + January 23, 1990 + + diff --git a/usr/src/contrib/isode/pepsy/doc/Makefile b/usr/src/contrib/isode/pepsy/doc/Makefile new file mode 100644 index 0000000000..33e7b01211 --- /dev/null +++ b/usr/src/contrib/isode/pepsy/doc/Makefile @@ -0,0 +1,10 @@ + +FILES = overview.ms tables.ms wt-pep.ms + +pepsy.info: $(FILES) + ditroff -ms $(FILES) + +DESCRIPTION: $(FILES) + -rm -f ../DESCRIPTION + nroff -ms $(FILES) > DESCRIPTION + ln DESCRIPTION .. diff --git a/usr/src/contrib/isode/pepsy/doc/overview.ms b/usr/src/contrib/isode/pepsy/doc/overview.ms new file mode 100644 index 0000000000..ad0528fc89 --- /dev/null +++ b/usr/src/contrib/isode/pepsy/doc/overview.ms @@ -0,0 +1,271 @@ +.NH 1 +Overview of pepsy system +.XS +Overview of pepsy system +.XE +.PP +This section describes how the various parts fit together to make +the system work. +The principle behind pepsy is fairly simple. +The \fBASN.1\fR is summarised as tables of integers. +These tables are read by driver routines which encode or decode +data to or from the internal format that \fBISODE\fR \fBOSI\fR implementation uses. +In \fBISODE\fR specific functions are generated for each \fBASN.1\fR type +defined in contrast the pepsy merely generates a new table of data which +is far far smaller. +.PP +As there is a great deal of effort invested in the \fBISODE\fR interface to the +encoding/decoding routines pepsy automatically provides macros which map +the original functions into the appropriate function call of a driver. +This allows existing posy using code to switch to the +pepsy system with \fBno changes\fR +to the code \fBprovided\fR no function pointers are used to the original +\fBISODE\fR functions. +Even when there are function pointers used the changes are very simple and +take only a few hours to implement. +.NH 2 +Brief description of the use of the pepsy system. +.XS +A Brief description of the use of the pepsy system. +.XE +.NH 3 +Outline of the files produced under the pepsy system. +.XS +Outline of the files produced under the pepsy system. +.XE +.PP +The pepsy system consists of a program called \fIposy\fR +which translates \fBASN.1\fR modules into a set of tables, called \fIposy\fR at the moment, +and library of driver routines, called \fIlibpepsy.a\fR. +Running this \fIposy\fR program on the \fBASN.1\fR file will produce several +files. +If the name of the \fBASN.1\fR module is \fBMODULE\fR the following files +are generated: +.I +.IP MODULE-types.h +.R +which contains \fBC\fR structure definitions. +The user of the library provides data as a linked list of +these \fBC\fR data structures and expects to receive data back as a similar +linked list. +These data structures are exactly the same as those produced by the original +\fBISODE\fR \fIposy\fR so that existing software written for the old \fIposy\fR +program needs no change. +For details on the \fBC\fR data structures types generated +see the documentation of the original \fIposy\fR program in +volume 4 Chapter 5 of the \fBISODE\fR manuals. +.I +.IP MODULE_tables.c +.R +This file contains the tables generated by the new \fIposy\fR program. +These tables consist of three parts, the first which contains the summary of +\fBASN.1\fR types. +Each type is summarised as an array of a primitive type, \fBstruct pte\fR, +for encoding and decoding, and \fBstruct ptpe\fR for printing. +As implied there is one array for each type for each of encoding, decoding and +printing as specified when \fIposy\fR is run. +The next part contains up to three tables of pointers to these arrays. +Each of the three different types of arrays, encoding, decoding and printing, +has its own table of pointers. +Finally there is the module type definition which contains contains pointers +to these tables and some other useful information about the module such as its +name. +This module type structure, which is \fBtypedef\fRed to \fBmodtyp\fR, +is the only piece of data which is global, all the +rest of the data is static and is only addressable via the \fBmodtyp\fR +data structure. +This provides a kind of object oriented approach to handling the tables. +Once you are passed a pointer to an \fBASN.1\fR's \fBmodtyp\fR structure +you can encode, decode and print any of its types by calling the appropriate +\fBlibpepsy.a\fR routine with its type number. +.I +.IP MODULE_pre_defs.h +.R +This file contains \fB#define\fRs symbol of each of the \fBASN.1\fR types +to its type number, which is used when calling a \fBlibpepsy.a\fR routine. +Each symbol is \fB_Ztype-nameMODULE\fR where \fItype-name\fR is the name of +the type with dashes (\fB-\fR) turned into underscores (\fB_\fR) and +\fIMODULE\fR is the name of the module. +For example of the \fBASN.1\fR universal type \fIGraphicString\fR would +have the \fB#define\fR symbol \fB_ZGraphicStringUNIV\fR. +The \fI_Z\fR is prepended to try to make the symbols unique. +This file also contains and extern declaration for the \fBmodtyp\fR data +for its module. +.I +.IP MODULE_defs.h +.R +This file contains macros for all the encoding, decoding and printing +functions that the \fIpepy\fR program would have for these \fBASN.1\fR +types. +This allows much of the code that uses the routines generated by running +the old \fIposy\fR program and taking its output and running \fIpepy\fR on +augmented \fBASN.1\fR output can be recompiled unchanged. +If the code used pointers to these functions it is necessary to change it +to pass around the type numbers instead and to call appropriately call +a \fBlibpepsy.a\fR library routine with the type number. +As pointers to the printing routines in ISODE are passed as arguments +a \fB#define\fR is provided to turn the argument into the pair of arguments, +type number and pointer to \fBmodtyp\fR structure, which are needed to allow +the diagnostic printing code to work with no change for +the current \fBISODE\fR stack. +This file also contains a \fB#include\fR of the \fIMODULE_pre_defs.h\fR file. +.PP +As the \fIMODULE-types.h\fR file \fB#include\fR's the \fIMODULE_defs.h\fR +file no further \fB#include\fRs need to be added to the files using the +encoding/decoding/printing functions. +This means that code written to use posy/pepy system may need no change at all +and the only effort required is to change the Makefile to use the pepsy +system. +If there is code changes required it would most likely be because function +pointers are used to reference the functions generated by posy. +If only the \fIpepy\fR system was used, +not posy then pepy, +with code placed inside action statements then quite a large amount of work +may be needed to change over to the new system, depending on how large and +complex the \fIpepy\fR module is. +.NH 3 +Outline of the pepsy library. +.XS +Outline of the pepsy library. +.XE +.IP enc.c +This contains the routines that encode data from the \fBC\fR data structures +into \fBISODE\fR's \fBPElement\fR linked list data structure which it +uses for all presentation data. +The most important function to pepsy users is \fBenc_f\fR which called to +encode a particular type. +It is passed the type number and a pointer to \fBmodtyp\fR structure for that +module and then the rest of the arguments which are passed to an encode +function generated by \fIposy\fR/\fIpepy\fR system. +See the documentation in Volume 4, "The Applications Cookbook", +Section 6.4 called "Pepy Environment". +Most of these latter arguments are ignored, only \fBparm\fR and \fBpe\fR, +are used. +.PP +Contrary to what the \fBISODE\fR documentation says these ignored parameters +are hardly ever used by existing code. +We have not found a single case where used for encoding a named type, +which is all that the user can reference anyway, +so we don't see any problems with ignoring these other parameters. +Hopefully one day they can be thrown away entirely, until then they are +actually passed the the encoding function. +.PP +The rest of the functions are mostly recursive routines which encode a +particular type of table entry. +For example \fBSEQUENCE\fR is encoded by \fBen_seq\fR which may call itself +or others to encode the types from which it is built up. +The function \fBen_type\fR builds up a simple type and \fBen_obj\fR encodes +a new type (object) and so on with other functions. +There are a few utility routines in the file such as \fBsame\fR which +determines whether the value is the same as the default value also. +.IP dec.c +This file contains the decoding routines that translate +presentation data into \fBC\fR data structures defined in +the \fBMODULE-types.h\fR +is like \fIenc.c\fR. +It is very much like the file \fIenc.c\fR except the routines do the +reverse tasks +The routines are structured in a very similar way. +We have \fBdec_f\fR which is called by the user to decode a type +and like \fBenc_f\fR takes the same arguments as the decoding functions +generated by \fIposy\fR with two additions, the type number and a pointer +to the \fBmodtyp\fR structure for that module. +Likewise the other functions are very much like those of enc.c +.IP prnt.c +This file contains the routines that print the presentation data in a format +similar to that generated by \fIpepy\fR's printing functions. +It's main function \fBprnt_f\fR is takes the same arguments as the printing +function generated by \fIpepy\fR as well as the now familiar type number +and \fBmodtyp\fR pointer. +The functions are modeled on the decoding routines as it has similar job to. +The only difference is that instead of storing the decoded data +into a \fBC\fR data structure it is nicely printed out. +.IP fr.c +This file contains code to free the data structures +defined in \fBMODULE-types.h\fR. +Likewise if the \fB-f\fR flag is given when generating the types file it also +includes macros in the types file which replace the freeing functions generated +by ISODE's \fIposy\fR. +The function that the user calls us \fBfre_obj\fR which takes a pointer to +the data structure, its decoding table entry and a pointer +to the \fBmodtyp\fR structure for the module. +The freeing is based on the decoding routines except instead of decoding all +it does is free each part of the data structure, which might involve recursive +calls, then it frees the data structure at the end. +.IP util.c +This contains the utility routines used by more than one of the above files. +This is mostly diagnostic routines at the moment, more general routines could +be included in here. +If there is an error at the moment which it can't recover from it just prints +out a message on standard error and calls \fBexit\fR. +Not perfect and this is something that will need work. +.IP main.c +This contains code to perform a series of tests on the \fIpepsy\fR library +which is a useful check to see whether any of the routines has been broken +by any changes made. +It basically loops through a whole series of test cases. +Each test case is encoded from some built in test data and then decoded +and checked to see if the data has changed in the transfer. +If it is compiled with \fI-DPRNT=1\fR the encoded data is also printed +out to check the printing routines which generates a vast amount of output. +Finally the free routines are used to free the allocated data, although it +can not directly check the free routines to see if they work, it can be used +with a malloc tracing package to check that the routines work. +.IP test_table.h +This contains the test cases that \fImain.c\fR program runs. +Each entry in the table corresponds to a type. +One of the fields is count of how many times that type is to be tested +to try out the different possibly data values it might have. +.IP "pep.h and pepdefs.h" +These files contain the definition of types used for the tables that drive the +encoding/decoding/printing routines. +All the constants used in that table are defined here via \fB#define\fRs. +The \fBmodtyp\fR structure is defined in \fIpepdefs.h\fR. +.IP "t1.py and t2.py" +These are test \fBASN.1\fR modules that are used by \fImain.c\fR routines +to check the \fIpepsy\fR library. +The file \fIt1.py\fR contains the majority of different types with +a few of a different module provided in \fIt2.py\fR. +This allows the testing of the code for handling \fBASN.1\fR +external references, i.e. references to types defined in other, external, +modules. +.NH 3 +New files in the pepy directory +.XS +New files in the pepy directory +.XE +.IP "etabs.c, dtabs.c and ptabs.c" +These files contain the code to generate the encoding/decoding/printing tables. +The main routine in \fIetabs.c\fR is \fBtenc_typ\fR which is called +on each \fBASN.1\fR type +to generate an array of entries which describe how to encode that type. +See the details section for more information about how the +table entries function. +Similarly \fIdtabs.c\fR contains the routine \fBtdec_typ\fR which is +called on each type to generate its decoding table entries. +Likewise \fBtprnt_typ\fR routine generates the arrays of table entries for +the printing tables. +This function is in \fIptabs.c\fR. +.IP "dfns.c" +This file contains miscellaneous string handling routines and hash table +routines that don't really belong anywhere else. +Some of the routines could be cleaned up in that they tend not to free memory +they use. +.IP mine.h +This file contains the definitions for the hash table(s) that are used to keep +track of the \fBASN.1\fR types. +This could probably be done with out a hash table, should anyone want to +clean this up, feel welcome. +The lookup function is in \fIdfns.c\fR. +.IP pass2.h +This file has most of the \fB#define\fRs for the table generating program. +Most of the prefixes and suffixes of function names and files names are defined +here so, hopefully, the names can be changed by merely changing the definition. +This contains most of the important definitions needed by the changes +to the \fIposy\fR program needed to generate tables. +.IP posy.h +This contains the definition of a symbol which is now needed outside of the +the main routine and the yacc file. +By putting it here we can include it any file that needs to know it with out +putting in any that doesn't need it and with out including all the other +definitions that occur in \fIpepy.h\fR. diff --git a/usr/src/contrib/isode/pepsy/doc/tables.ms b/usr/src/contrib/isode/pepsy/doc/tables.ms new file mode 100644 index 0000000000..8f5b3f62ff --- /dev/null +++ b/usr/src/contrib/isode/pepsy/doc/tables.ms @@ -0,0 +1,353 @@ +.NS 2 +The structure and meaning of the tables generated from the ASN.1 grammar +.XS +The structure and meaning of the tables generated from the ASN.1 grammar +.XE +.PP +Each collection of \fBASN.1\fR grammar is called a module. +(See +.[ +ASN.1 +.] +) +Each \fBASN.1\fR module is completely specified in the program by a +single \fBC\fR structure of type \fBmodtyp\fR and the data which it references. +See the \fIpepdefs.h\fR file in the \fIpepsy\fR directory. +For each \fBASN.1\fR module +there are three tables that are generated from\fBASN.1\fR grammar. +These initialised arrays which we call tables are +called the encoding, decoding and printing tables. +Each of these tables is referenced through a different pointer +of the \fBmodtyp\fR structure. +.PP +Each of these pointers references an array of pointers, +one pointer for each \fBASN.1\fR type defined in the module. +The position of one of these pointers is the unique type number we give to +its corresponding type. +The pointer references an array of type \fBtpe\fR or \fBptpe\fR, depending +whether it is an entry in the decoding/encoding tables or printing tables +respectively. +See \fIpep.h\fR in the \fIpepsy\fR directory. +This array actually contains the necessary information to encode/decode/print +that \fBASN.1\fR type. +So given the \fBmodtyp\fR structure of an \fBASN.1\fR module and its +type number you can call a routine to encode, decode or print that type. +.PP +The rest of this document assumes a good knowledge of \fBASN.1\fR notation +so go read a copy if you haven't already. +From here on I shall mention only \fBtpe\fR and this means \fBtpe\fR in the +case of encoding or decoding and \fBptpe\fR in the case of printing, unless +otherwise stated. +Each type is represented by an array of \fBtpe\fR (or \fBptpe\fR for printing). +The basic element consists of four integer fields, +the printing table is the same with an addition \fBchar\fR pointer field which +contains the name corresponding to that entry in the \fBASN.1\fR grammar. +The first specifies the type of the entry and determines how the +rest are interpreted. +The possible types are listed in \fIpepsy/pep.h\fR. +Each type is an array which starts with an entry of type \fBPE_START\fR +and ends with one of type \fBPE_END\fR. +Each primitive type requires one entry to specify it, +apart from possible \fBPE_START\fR and \fBPE_END\fR used to specify the start +and end of the type. +Constructed types are represented by a list of entries terminated by an +entry of type \fBPE_END\fR. +As \fBASN.1\fR types can be nested inside so will the +representation in \fBtpe\fR entries be nested. +For example the \fBASN.1\fR type definition: +.nf + Example1 ::= + SEQUENCE { + seq1 SEQUENCE { + an-i INTEGER, + an-ostring OCTET STRING + }, + a-bool IMPLICIT [0] BOOLEAN + } +.fi +.ce 1 +Will generate an encoding array: +.nf +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 } + }; + +.fi +.PP +Here the second last \fBPE_END\fR matches and closes off the +first \fBSEQ_START\fR. +The entries which correspond to the other primative types are pretty +obvious, with the INTEGER entry corresponding to the primative INTEGER. +For fields that generate data the general interpretation of the other three +fields is offset, tag and flags/class fields respectively. +.IP offset +The second field gives the offset in a \fBC\fR data structure +needed to reference the data that corresponds to this table entry. +Each \fBASN.1\fR type has \fBC\fR 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 \fBC\fR preprocessor macro is used hide the actual details. +.IP tag +This is the tag associated with the \fBASN.1\fR 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. +Likewise SEQUENCE has the correct tag of 16 in its \fBSEQ_START\fR entry +and so on for the others. +.IP flags/class +This contains the \fBASN.1\fR 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. +.PP +Now that you have some idea of how these arrays are arranged for a type +definition I will proceed to go through the possible type of +entries and describe what they do and how they work. +These values are defined in \fIpepsy/pep.h\fR. +Those entries with a value below \fBTYPE_DATA\fR are entries that +don't correspond to data to be encoded/decoded and are for other book keeping +type purposes. +.IP "PE_START and PE_END" +As explained above \fBPE_START\fR starts the beginning of a \fBASN.1\fR 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 \fBPE_END\fR is necessary to mark the end of some +compound type as well as the end of \fBASN.1\fR data type. +.IP "XOBJECT and UCODE" +These are obsolete types and probably should be removed. +They were to allow \fBC\fR 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 \fIpepy\fR which is what we first attempted to +do until we found this to be much easier. +.IP MALLOC +This field only occurs in the decoding tables. +It specifies how much space to malloc out for the current \fBC\fR structure +it is just inside of. +For instance in the example above the decoding table has the following entry: +.DS C +{ MALLOC, 0, sizeof (struct type_Test_Example1), 0 }, +.DE +just after the first \fBSEQ_START\fR entry. +It tells it to \fBmalloc\fR out a \fBstruct type_Test_Example1\fR structure +to hold the data from the sequence when it is decoded. +.IP SCTRL +This entry is used in handling the \fBASN.1\fR CHOICE type. +The \fBC\fR type generated for \fBASN.1\fR CHOICE type is a structure with +an offset field in it and a +union of all the \fBC\fR types present in the CHOICE. +Each \fBASN.1\fR type in the CHOICE of types has a \fBC\fR 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 \fImember\fR should selected). +As such it needs to be read by the encoding routines +when encoding the data from the \fBC\fR data structures +and to be set by the decoding routines when it is decoding the data into +the \fBC\fR data structures. +There is one such entry for each \fBCHOICE\fR type to specify where the +offset field is. +.IP CH_ACT +Another redundant entry type. +I think this was also used in code to handle \fBC\fR statements or +actions specified by the user. +It probably should be removed. +.IP OPTL +This is used to handle the optionals field that is generated by +\fBposy\fR when optional types that are \fInot\fR implemented by pointers +are present in the \fBASN.1\fR type. +For example if an \fBASN.1\fR type has an optional integer field how +does the encoding routine determine if the integer is to be +present or not? +If it was implemented as a pointer it could use a \fBNULL\fR (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. +.PP +If that bit is set the corresponding type is present and it is not +present if the bit is not set. +Each bit has a \fB#define\fR generated for it. +The bit map is merely an integer field called "\fBoptionals\fR" limiting +maximum number of such optionals to 32 on Sun machines, 16 on some others. +(An array of \fBchar\fR as BSD fd_sets would have avoid all such limits, +not that this limit is expected to be exceeded very often !) +Like the \fBSCTRL\fR entry this entry merely serves to specify where +this field is so it can be test and set by the encoding and decoding routines +respectively. +.IP "ANY and CONS_ANY" +The \fBC\fR type corresponding to the entry is a \fBPE\fR pointer. +To conform with \fIpepy\fR the tag and class of this entry are ignored, +which may or may not be the most sensible thing. +The \fBCONS_ANY\fR is a redundant symbol which means the same thing but +is not used. +This should be clean up and removed. +.IP "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 \fBC\fR data +type to implement them. +The offset fields says where to find this data type with in the current +structure. +.IP "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 \fBPE_END\fR. +The entries with \fBOF\fR in them correspond to the \fBASN.1\fR types +which have \fBOF\fR in them +e.g. \fBSET OF\fR. +Allowing the \fBOF\fR items to have an arbitrary number of entries is +excessive flexibility, they can only have one type by the \fBASN.1\fR grammar +rules. +The \fBC\fR 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 processing of these structures a little but not greatly. +The \fBOF\fR types differ one other important way, +they may occur zero, one or more times, with no upper bound. +To cope with this the \fBC\fR 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 pointer to the next occurrence, the offset of +this pointer is placed in the \fBPE_END\fR field where it can conveniently +be used to determine whether or not to make another pass through the +table entry. +.IP OBJECT +When one type references another it generates an \fBOBJECT\fR entry. +This specifies the type number of the type +which is present in the 3rd field of the \fBtpe\fR structure, +\fBpe_tag\fR. +The 2nd field still gives the offset in the \fBC\fR data structure +which specifies where the user's data for that type is to be found. +Usually this a pointer to the \fBC\fR data structure for that type. +.IP T_NULL +This entry means the \fBASN.1\fR primative type \fBNULL\fR. +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 \fBOPTL\fR entry. +.IP T_OID +This use to be used for Object Identifiers and now is unused, +it should be got rid. +.IP OBJID +This corresponds to the Object Identifier \fBASN.1\fR type primitive. +It is implemented the same as other primative types like \fBINTEGER\fR +and \fBOCTET STRING\fR. +.IP 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 \fBETAG\fR entries it is possibly to build up +an limited number explicit tags, although this hasn't been tested yet. +.IP 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 reference 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 \fBOBJECT\fR 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 \fBDEFAULT\fR +and \fBOPTIONAL\fR) +So a new entry type is used, \fBIMP_OBJ\fR, to hold the tag and class. +It must be followed by an \fBOBJECT\fR entry which is used to handle the type +as normal, the \fBIMP_OBJ\fR entry gives the tag and class to be used. +Like the \fBETAG\fR entry the \fBIMP_OBJ\fR affects the entry that follows it. +.IP "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. +Similarly because there are no more free fields in the \fBOBJECT\fR type +we need two entries to hold all the information we need. +The \fBEXTMOD\fR occurs first and holds the type number and the offset +into the \fBC\fR data structure and the flags, exactly as for an \fBOBJECT\fR +entry. +The next entry, which must be an \fBEXTMOD\fR, contains a pointer to +the \fBmodtyp\fR structure for its module. +Like a normal \fBOBJECT\fR entry to handle the case of an implicit tag +an \fBIMP_OBJ\fR 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 proceeded by an \fBETAG\fR entry. +.IP "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 allocate 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 handle 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. +.B DFLT_F +contains the default value for the following entry (F = Front) +and \fBDFLT_B\fR contains that for the entry before it (B = Back). +Consequently \fBDFLT_F\fR are only used in the decoding tables +and \fBDFLT_B\fR entries are only used in the decoding (and printing tables). +.IP S-Types +These types are entries for the same \fBASN.1\fR type as the entry type +formed by removing the starting `S'. +The above forms would do to handle \fBASN.1\fR but we also have to be +compatible with the \fBC\fR data structures generated by \fIposy\fR. +The implementors decided to optimise the \fBC\fR data structures generated +a little means we have to have all these \fBS\fR type entries. +If a type was a single field in most cases they produced a \fB#define\fR +which eliminates the need to have a whole structure just for that type. +In all the places where this type is used the field of the \fBC\fR structure +is changed from a pointer to field which holds the value directly in the +structure. +See the \fBISODE\fR reference given above for more details. +.PP +We handle this by generating the same tables that would be generated +with out the optimisation, except the optimised types the S-type of entries +instead of the normal ones. +For example an optimised \fBOCTET STRING\fR would have +the type field of its entry as \fBSOCTETSTRING\fR instead of \fBOCTETSTRING\fR. +The only difference in how \fBS\fR type and its corresponding normal are handle +is how they find the \fBC\fR data structure for that entry. +That difference is that there is no indirection through pointers. +.IP "Flags field" +Besides the encoding the class the \fBpe_flags\fR field +also contains a few possible flags. +Mainly \fBFL_OPTIONAL\fR which means the \fBASN.1\fR type +corresponding to this flag is OPTIONAL. +Consequently when encoding it has to determine if the type is present in the +user data possibly using the bit map as described under the \fBOPTL\fR entry. +Likewise when decoding it may have to set a bit in the bit map appropriately. +The other flag at the moment is \fBFL_DEFAULT\fR which means the entry +corresponds to an \fBASN.1\fR DEFAULT type. +This bit is still needed as not all types have \fBDFLT_*\fR entries implmented +for them at the moment. +In particular compound value things like SEQUENCE and SET can't have thier +default value specified. +This is consistent with \fBISODE\fR, if fact implementing that may even +break existing \fBISODE\fR code. +This last flag \fBFL_IMPLICIT\fR is obsolete and not not used any where. diff --git a/usr/src/contrib/isode/pepsy/doc/wt-pep.ms b/usr/src/contrib/isode/pepsy/doc/wt-pep.ms new file mode 100644 index 0000000000..8045bd9e67 --- /dev/null +++ b/usr/src/contrib/isode/pepsy/doc/wt-pep.ms @@ -0,0 +1,201 @@ +\" Walk through of the pepsy library routines +.NH 2 +Walk through of pepsy library routines. +.XS +Walk through of pepsy library routines. +.XE +.PP +Here we walk through all the pepsy library routines at least briefly. +If any new routines are added or a routine changed this documentation +is the most likely part that will need changing. +First we give some theory as to how the task have have been brocken +into routines then describe each function in detail. +We assume you are familiar with \fBISODE\fR's \fBPE\fR data +structure manipulation routines. +if not they are documented in the \fBISODE\fR manuals, Volume one, chapter 5, +"Encoding of Data-Structures" (It actually covers decoding as well). +.NH 3 +Overview of pepsy library +.XS +Overview of pepsy library +.XE +.PP +Each seperate task is put into a different file. +So all the encoding stuff is in \fIenc.c\fR, all the decoding stuff is +in \fIdec.c\fR, printing stuff in \fIprnt.c\fR and freeing stuff in \fIfre.c\fR. +Actually it breaks down a little in practice, some of the routines for +moving around the tables are used in both \fIenc.c\fR and \fIdec.c\fR +for example. +Probably they should defined in \fIutil.c\fR so that linking one of the files +from the library doesn't force linking any other except \fIutil.o\fR. +.PP +There is a common structure to each of the major files as well. +There is a main routine which the user calls to obtain the services +provided by that file's routines. +As all the files revolve about processing the table entries their +structure is based on running through the table entries. +.PP +We shall call each array of entries a table or an object. +There is a routine, usually with a name ending in _obj, which is designed +to process an object. +For example \fBen_obj\fR is the routine called to generated an encoded +object. +Then there are routines to call on each compound type +such as \fBen_seq\fR for encode a SEQUENCE. +Finally all the primitives are handled by a one function that ends in _type. +This lets each routine concentrate on handling the features particular to +its type and call the appropriate routine to handle each type it finds +with in its compound type. +.PP +Most of these table processing routines have just three arguements: +which are called \fBparm\fR, \fBp\fR, \fBmod\fR. +The \fBparm\fR is char * or char ** in the encoding and decoding routines +respectively. +This points to the user's \fBC\fR structure that data to be encoded +is taken from when encoding. +When decoding it is the address of a pointer which is made to point +the \fBC\fR structure filled with the decode data. +The freeing, which is based on the decoding routines, has a char ** +while the printing routines don't look at the user's data and so don't +have such a pointer. +The \fBp\fR points to the current table entry we are up to processing and +the \fBmod\fR arguement points to the \fBmodtyp\fR structure for the current +module we are processing. +.PP +All these processing routines return a \fBPE\fR type, +which is defined in \fBISODE\fR's file \fIh/psap.h\fR, and to return zero +if they have an error, but not always. +In fact the error handling is needs some work and has not +been tested very well. +Generally it tries to print out the table entry where something went wrong and +the name of the function it was in. +It then sometimes does an exit which may not be very pleasent for the +user. +.NH 3 +The encoding routines - enc.c +.XS +The encoding routines - enc.c +.XE +.IP enc_f +This is the the routine made available to the user for the encoding routines. +It is fairly simple as it leaves all the hard things up to other routines. +All it does is use the type number and \fBmodtyp\fR pointer to get +a pointer to the table for encoding that type. +Then it calls the table or object encoding routine, \fBen_obj\fR, +on that object. +It first does a consistency check of making sure the first entry in the table +is a \fBPE_start\fR. +Note that it returns an integer (OK or NOTOK) instead of a \fBPE\fR pointer. +This is to be consitent with \fBISODE\fR functions. +.IP en_obj +We loop through the entries until we come to the end of the table and then we +return the \fBPE\fR we have built up from the user's data which is pointed +to by \fBparm\fR. +In looping through each entry we call the appropriate routine to encode its +data. +The default case is handled by calling \fBen_type\fR which takes care of +all the primitive types. +.PP +The macro \fBNEXT_TPE\fR sets its arguement to point to the next type +in the table, counting compound types as one type. +Thus if \fBNEXT_TPE\fR is called on a \fBSET_START\fR it will skip all the +entries up to and including the matching \fBPE_END\fR. +As many objects consist of one compound type and its components the main +loop will only be run through once. +Even when the object is not based on a compound type it will then consist of +one simple type which is processed by \fBen_type\fR, again probably +going through the loop only once. +In fact the only way it can go through the loop more than once +is to process entries that subsidary to the main type, e.g. \fBETAG\fB entries +and things like that. +To double check this is the case there is some code that looks for +the processing of more than one data generating entry. +.PP +Much of that testing could probably be eliminated with no loss. +Similarly prehaps the \fBIMP_OBJ\fR and \fBETAG\fR could be handled by the +default action of calling \fBen_type\fR. +As these routines have evolved after many changes there are things like +that which really need to be looked at closely before trying. +The comment /*SUPRESS 288*/ means suppress warning 288 to saber C debugging +tool that we use. +.IP en_type +This is one of the longest functions as it has so many cases to handle. +It again is structure as a loop over the types until \fBPE_END\fR but it +actually returns as soon as it has encoded the next type. +We can now look at the encoding of the primative \fBASN.1\fR types in detail. +.IP DFLT_F +Because we have arranged that for encoding tables, that we precede +the entry with a \fBDFLT_F\fR entry we can neatly handle all the default +cases. +All we do is check if the parameter passed in the user data, in \fBparm\fR, +is the same as the default value specified in the \fBDFLT_F\fR entry. +The function \fBsame\fR performs this check. +If it is the same don't encode anything just return, otherwise continue on +and encode it. +.IP ETAG +To handle explicit tags we merely allocate a \fBPE\fR with the right tag +and call \fBen_etype\fR to encode its contents, which are in the following +entries. +The switch on the \fBpe_ucode\fR field use to make a difference +but now it is meaningless and should be cleaned up. +.IP "SEQ_START, SEQOF_START, SET_START, SETOF_START" +We merely call the appropriate function handle them. +Note one \fIimportant\fR difference in the way they are called here from that +in \fBenc_obj\fR, the parm arguement is used as a base to index off and +fetch a new pointer to pass the next function. +This seemly bizarre action is quite straight forward when seen written as +it is normally in \fBC\fR, "\fBparm->offset\fR". +Where the field \fBoffset\fR is a pointer which has an offset from the start +of the structure of \fBp->pe_ucode\fR bytes. +.PP +This is the magic of how we access all the different fields +of the \fBC\fR data structures with the one piece of code. +It is also prehaps the most critical dependency of the whole system +on the implementation of the \fBC\fR language. +As the \BGNU\fR \fBC\fR compiler supports this feature then it is +compilerable on most machines. +But any porters should pay attention to this to ensure that thier compiler +is happy generating these offsets and compiling these casts properly. +.PP +The reason why this is different from the calls in \fBen_obj\fR is that +this is not the first compound type in the table. +The first and only the first does not have an offset and does not need to be +indirected through any pointers. +All the compound types inside this type will have +as their field a pointer which points to a structure. +From here on we shall say \fIindirection\fR to mean this +adding the \fBpe_ucode\fR field +to the pointer to the structure and using it to reference a pointer. +Whether to use \fIindirection\fR or not is very important matter +that really needs to be understood to understand how the routines are +structured. +.IP IMP_OBJ +Here we have to handle the case where we can encode the object then have to +change its tag and class after encoding. +At the end of this entry this is done very simply by assigning the +right values to the appropriate fields after the object has been built. +This means that if the intermeadiate form is altered this piece of code +may have to be altered as well. +There seems to be no better way of handling this. +.PP +The complication in handling this field is the handling of all the possible +types of object. +If it is an external object we have to perform a call to \fBenc_f\fR with +all the right arguements +where a normal OBJECT, the last else branch, requires a normal call +to \fBen_obj\fR. +Note the case of \fBSOBJECT\fR is the same +as \fBOBJECT\fR \fIexcept there is no indirection\fR. +.IP "SOBJECT and OBJECT" +Here is the code that handles the two cases sperately. +It is exactly as in the \fBIMP_OBJ\fR case except seperated out. +Note the only difference between the two cases is lack of indirection in +the \fBSOBJECT\fR case. +.IP CHOICE_START +This is exactly as all other compound types, +like \fBSEQ_START\fR and \fBOBJECT\fR, we call the appropriate routine with +indirection. +From reading the \fBISODE\fR manuals that the \fBASN.1\fR CHOICE type +is handled by a structure of its own like the other compund types. +.IP "EXTOBJ and SEXTOBJ" + -- 2.20.1