1 % file: .../doc/meta.tex
3 % $Header: /cvs/root/Security/SecuritySNACCRuntime/doc/Attic/meta.tex,v 1.1.1.1 2001/05/18 23:14:10 mb Exp $
5 % Revision 1.1.1.1 2001/05/18 23:14:10 mb
6 % Move from private repository to open source repository
8 % Revision 1.1.1.1 1999/03/16 18:05:53 aram
9 % Originals from SMIME Free Library.
11 % Revision 1.1 1997/01/01 22:47:38 rj
15 \chapter{\label{meta-chapter
}The Metacode
}
17 %-----------------------------------------------------------------------------------------------------------------------------------
18 \section{\label{intro-meta-section
}Introduction
}
20 When you call snacc, during its compilation, the text in the
{\ufn .asn1
} files gets turned into e.g. C++ classes.
21 Names become identifiers, and after the C++ compilation, the user program has no more access to the original module and type names, only to pointers and the bits and bytes of the classes' contents.
23 The metacode remedies this.
24 Using it, a program can access the modules, their types, their subtypes and the named values via strings.
25 Generic programs do not have to know any of the modules' or types' names---all the information can be traversed starting at a single well-known place.
27 The metacode has to map strings (``component
{\C "name"
} in type
{\C "Person"
} in ASN
.1 module
{\C "Mail"
}'') into the in-core address of the indicated object.
28 Moreover, using the metacode, a generic program has to be able to traverse all modules, types and their components to learn about their names and types.
29 Given the name of a type, the metacode must be able to return a newly allocated object instance.
31 The metacode is an extension to the Snacc compiler's C++ backend and the C++ runtime library.
33 Since the metacode relies heavyly on the virtual function call mechanism, it is only implemented for the C++ backend.
35 A number of functions has been added to the C++ runtime library.
36 All code extensions have been wrapped into preprocessor conditionals.
37 Currently, only one or two libraries are made in
{\ufn \dots/c++-lib/
}, one with neither metacode nor Tcl interface, and an optional additional one with both extensions.
38 If you cannot or do not want to (as stated in
{\ufn \dots/policy.h
}) use the metacode or the Tcl interface, Snacc will be compiled without it, and only the normal library will get made.
40 If you want to use the metacode but not the Tcl interface, you have got to change the makefile to compile another set of
{\ufn .o
} files in a directory you may want to name
{\ufn \dots/c++-lib/meta/
} and archive the resulting files in
{\ufn libasn1meta.a
}.
41 Compile with
{\ufn -DMETA=
1 -DTCL=
0}.
43 %-----------------------------------------------------------------------------------------------------------------------------------
44 \section{Implementation
}
46 %leftover:----------------
47 With the metacode, the strings and the ASN
.1 type components' type information are stored in arrays, one per structured ASN
.1 type.
48 The type descriptions are listed in another array, one per ASN
.1 module.
50 In the C++ code generated by snacc, every ASN
.1 type is represented by a C++ class.
51 These C++ classes for ASN
.1 simple types are implemented in the runtime library, and for structured types they are generated by the backend.
52 The metacode is an extension to all of those C++ classes.
53 The metacode put into every C++ class is very similar:
55 \item a static
{\C \_desc} member is always present.
56 \item simple types with names (ENUMERATED, INTEGER, BIT STRING) get an additional static
{\C \_nmdescs[]} member.
57 The array is exclusively referenced from
{\C \_desc}.
58 The array provides the bidirectional mapping of symbolic and numeric values.
59 \item structured types with members (SET, SEQUENCE, CHOICE) get an additional static
{\C \_mdescs[]} member.
60 The array is exclusively referenced from
{\C \_desc}.
61 The array references the components' type descriptions (their
{\C \_desc} data members).
62 \item every class gets a virtual
{\C \_getref()
} function.
63 Its only purpose is to return the address of
{\C \_desc}\footnote{
64 This sounds as if virtual data members were a nice idea, and in fact they are.
65 The C++ standards committees are currently discussing this.
66 % Of course, there are not a lot of compilers already implementing this feature.
68 \item structured types with members (SET, SEQUENCE, CHOICE) get an additional virtual
{\C \_getref()
} function.
69 This function provides the member name to member address mapping.
71 The data members are
{\C static
}, and therefore get instantiated exactly once per executable, not once per class object instance.
73 To get an impression, let us have a look at an example:
78 name
[0] PrintableString,\\
79 contents
[1] OCTET STRING,\\
80 checksum
[2] INTEGER OPTIONAL,\\
81 read-only
[3] BOOLEAN DEFAULT FALSE\-\\
86 name PrintableString,\\
91 get turned into two individual C++ classes:
94 class File: public AsnType\\
97 PrintableString \>\>name;\\
98 AsnOcts \>\>contents;\\
99 AsnInt \>\>*checksum;\\
100 AsnBool \>\>*read
\_only;\\
103 static const AsnSetTypeDesc \>\>
\_desc;\\
104 static const AsnSetMemberDesc \>\>
\_mdescs[];\\
105 const AsnTypeDesc \>\>*
\_getdesc() const;\\
106 AsnType \>\>*
\_getref (const char *membername, bool create = false);\\
109 //
\dots other functions omitted
\dots\-\\
112 class Directory: public AsnType\\
115 PrintableString \>\>name;\\
116 DirectorySetOf \>\>files;\\
119 static const AsnSetTypeDesc \>\>
\_desc;\\
120 static const AsnSetMemberDesc \>\>
\_mdescs[];\\
121 const AsnTypeDesc \>\>*
\_getdesc() const;\\
122 AsnType \>\>*
\_getref (const char *membername, bool create = false);\\
125 //
\dots other functions omitted
\dots\\
129 The above definitions stem from the
{\ufn .h
} file, the following code is taken from the
{\ufn .C
} file.
130 Only the code for the
{\ASN Directory
} type is shown, because the code for the
{\ASN File
} type looks very similar.
135 static AsnType *createDirectory()\\
137 \>return new Directory;\\
140 const AsnSetMemberDesc Directory::
\_mdescs[] =\\
142 AsnSetMemberDesc ("name", \&PrintableString::
\_desc, false), // `name'\\
143 AsnSetMemberDesc ("files", \&DirectorySetOf::
\_desc, false), // `files'\\
144 AsnSetMemberDesc()\-\\
147 const AsnSetTypeDesc Directory::
\_desc\\
149 \&EdEx
\_StructuredModuleDesc,\\
150 "Directory", // `Directory'\\
157 const AsnTypeDesc *Directory::
\_getdesc() const\\
162 AsnType *Directory::
\_getref (const char *membername, bool create)\\
164 if (!strcmp (membername, "name"))\\
166 if (!strcmp (membername, "files"))\\
174 The two ASN
.1 types get turned into two individual C++ classes, but their
{\C \_desc} members point to two different instances of the same type.
175 The C++ backend generates an individual C++ class for every structured ASN
.1 type.
176 The metacode is different:
177 The types of the descriptions data members (
{\C \_desc},
{\C \_nmdesc} and
{\C \_mdesc}) despend on the
\emph{general
} ASN
.1 type (i.e. e.g.
{\ASN SET
}, not
{\ASN File
}).
185 %leftover:----------------
186 Every
{\ufn .asn1
} file contains an ASN
.1 module and gets translated into a
{\ufn .C
} file that contains an array that lists all the module's type descriptions.
188 Snacc generates an additional file
{\ufn modules.C
} that contains an array that lists all the module descriptions.
189 This single top level array provides the well known entry point for the whole module and type hierarchy.
190 %leftover:----------------
196 The type of the
{\C \_desc} member differs depending on the ASN
.1 type it describes.
197 The different
{\C \_desc} types mirror the
{\C AsnType
} class hierarchy.
198 For example, the ASN
.1 BOOLEAN type is mapped into a C++ class called
{\C AsnBool
} and is described by a C++ class
{\C AsnBoolTypeDesc
}.
199 The root of the
{\C \_desc} class hierarchy is called
{\C AsnTypeDesc
} and looks as follows
200 (taken from
{\ufn \dots/c++-lib/inc/meta.h
}):
204 const AsnModuleDesc \>\>*module;\\
205 const char \>\>*const name; // NULL for basic types\\
206 const bool \>\>pdu;\\
207 const enum Type
\qquad // NOTE: keep this enum in sync with the typenames
[]\\
214 NUL
\_, // sic! (can't fight the ubiquitous NULL \#define)\\
219 OBJECT
\_IDENTIFIER,\\
229 static const char \>\>*const typenames
[];\\
231 \>\>AsnTypeDesc (const AsnModuleDesc *, const char *,\\
232 \`bool ispdu, AsnType *
(*create)(), Type);\\
234 AsnType \>\>*(*create)();\\
236 virtual const AsnModuleDesc \>\>*getmodule() const;\\
237 virtual const char \>\>*getname() const;\\
238 virtual bool \>\>ispdu() const;\\
239 virtual Type \>\>gettype() const;\\
240 virtual const AsnNameDesc \>\>*getnames() const;\\
241 %//virtual const AsnMemberDesc \>\>*getmembers() const;\\
244 virtual int \>\>TclGetDesc (Tcl\_DString *) const;\\
245 virtual int \>\>TclGetDesc2 (Tcl
\_DString *) const;\-\\
249 typedef AsnTypeDesc \>\>\>AsnRealTypeDesc;\\
250 typedef AsnTypeDesc \>\>\>AsnNullTypeDesc;\\
251 typedef AsnTypeDesc \>\>\>AsnBoolTypeDesc;\\
253 typedef AsnTypeDesc \>\>\>AsnOctsTypeDesc;\\
254 typedef AsnTypeDesc \>\>\>AsnOidTypeDesc;
257 {\C AsnTypeDesc
}'s data members provide the following information:
259 \item[\textnormal{The
} {\C module
}] data member points to the module description described at the end of this chapter in section~
\ref{meta-modules-sect
}.
261 \item[\textnormal{The
} {\C name
}] is either the type's name as used by the backend code (default, or if snacc was called with the
{\ufn -mC
} switch) or the type's given names as defined in the
{\ufn .asn1
} file (if snacc has been called with the
{\ufn -mA
} command line option).
262 Section~
\ref{naming-C++-section
} on page~
\pageref{naming-C++-section
} explains the differences.
263 (For example, the backend code sometimes has an additional number tacked to the name---you can see the effect in figure~
\ref{snacced-example
} on page~
\pageref{snacced-example
}.)
264 The generated source code contains the respective counterpart printed in a comment.
266 \item[\textnormal{The
} {\C pdu
}] flag is set to
{\C true
} iff the type was listed after snacc's
{\ufn -meta
} or
{\ufn -tcl
} switch.
268 \item[\textnormal{The
} {\C type
}] member is used as an index into the
{\C typenames
} array---the virtual function call mechanism obliviates the use for any
{\C switch
} statements.
270 \item[\textnormal{The
} {\C create
}] data member points to a global function that returns a pointer to a newly allocated object of the description type's mirror type, that is, gives you an instance for the generic description.
271 It is the counterpart to the
{\C AsnType
}'s
{\C \_getdesc} function which goes in the opposite direction, from the object instance to its generic description.
272 The
{\C AsnType
}'s
{\C Clone
} function serves a similar purpose as the
{\C AsnTypeDesc
}'s
{\C create
} function.
275 The
{\C AsnTypeDesc
} class is the only class in the hierarchy that has got the
{\C module
},
{\C name
},
{\C pdu
} and
{\C type
} data members, and
{\C AsnNamesTypeDesc
} the only class to implement a
{\C names
} data member.
276 Therefore, unlike
{\C \_getdesc()
} mentioned above, the five virtual functions
{\C getmodule
},
{\C getname
},
{\C ispdu
},
{\C gettype
} and
{\C getnames
} are not meant to implement some kind of virtual data members, but help to implement the alias type description functionality described in section~
\ref{meta-aliases
}.
278 As you can see looking at the last five code lines with the
{\C typedef
}s, the five ASN
.1 simple types REAL, NULL, BOOLEAN, OCTET STRING and OBJECT IDENTIFIER are directly described by instances of this class.
279 The other types, having either named values or components, are more demanding and have their own classes derived from
{\C AsnTypeDesc
}.
281 %-----------------------------------------------------------------------------------------------------------------------------------
282 \subsection{Named Values
}
284 Some basic ASN
.1 types allow values to be named, namely INTEGER, ENUMERATED and BIT STRING.
285 The accompanying description types contain arrays listing the names and values.
286 The virtual function
{\C getnames()
} returns this array.
287 The respective C++ classes in the runtime library contain an
{\C AsnNameDesc
\_nmdescs[]} array, the address of which is given to the type descriptions constructor as last argument.
292 const char \>\>*const name;\\
293 const long int \>\>value;\-\\
296 struct AsnNamesTypeDesc: AsnTypeDesc\\
298 const AsnNameDesc \>\>*const names;\\
300 \>\>AsnNamesTypeDesc (const AsnModuleDesc *, const char *,\\
301 \`bool ispdu, AsnType *
(*create)(), Type, const AsnNameDesc *);\\
303 const AsnNameDesc \>\>*getnames() const;\\
306 int \>\>TclGetDesc (Tcl
\_DString *) const;\\
307 // for BIT STRING and INTEGER, ENUMERATED has its own:\\
308 int \>\>TclGetDesc2 (Tcl
\_DString *) const;\-\\
312 struct AsnEnumTypeDesc: AsnNamesTypeDesc\\
314 \> \>\>AsnEnumTypeDesc (const AsnModuleDesc *, const char *,\\
315 \`bool ispdu, Type, AsnType *
(*create)(), const AsnNameDesc *);\\
318 \>int \>\>TclGetDesc2 (Tcl
\_DString *) const;\\
322 typedef AsnNamesTypeDesc \>\>\>AsnIntTypeDesc;\\
323 typedef AsnNamesTypeDesc \>\>\>AsnBitsTypeDesc;
326 The ENUMERATED type gets its own description class because the Tcl interface for ENUMERATED types behaves differently than for the INTEGER and BIT STRING types.
328 As for
{\C AsnTypeDesc::name
} above, the content of
{\C AsnNameDesc::name
} is either the value's name as used by the backend code (default, or if snacc was called with the
{\ufn -mC
} switch) or the value's name as given in the
{\ufn .asn1
} file (if snacc has been called with the
{\ufn -mA
} command line option).
329 The generated source code contains the respective counterpart printed in a comment.
331 \subsection{Types with Members
}
333 The ASN
.1 types CHOICE, SET and SEQUENCE are defined in terms of other types, their so-called components.
334 The ASN
.1 components map into C++ data members.
336 The three ASN
.1 structured types get mapped into C++ classes that contain an
{\C Asn
\dots{}MemberDesc
\_mdescs[]} array (with the `
{\C \dots}' replaced by `
{\C Choice
}' `
{\C Set
}' or `
{\C Sequence
}').
337 The address of this array is given to the description type's constructor as last argument.
338 The elements of this array point to the descriptions of the data classes data members.
339 This is similar to the named values above, only the integral value has been replaced by a pointer to a type description.
342 struct AsnMemberDesc // description of CHOICE member; base class for AsnSe
\_MemberDesc\\
344 const char \>\>*const name;\\
345 const AsnTypeDesc \>\>*const desc;\\
347 \>\>AsnMemberDesc (const char *, const AsnTypeDesc *);\\
348 \>\>AsnMemberDesc();\\
351 virtual int \>\>TclGetDesc (Tcl
\_DString *) const;\\
352 virtual int \>\>TclGetDesc2 (Tcl
\_DString *) const;\-\\
356 struct AsnSe
\_MemberDesc: AsnMemberDesc
\qquad//
\_ == t/quence; description of SET or SEQUENCE member\\
360 \>\>AsnSe
\_MemberDesc (const char *, const AsnTypeDesc *, bool);\\
361 \>\>AsnSe
\_MemberDesc();\\
364 \>int \>\>TclGetDesc2 (Tcl
\_DString *) const;\\
368 typedef AsnMemberDesc \>\>\>AsnChoiceMemberDesc;\\
369 typedef AsnSe
\_MemberDesc \>\>\>AsnSetMemberDesc;\\
370 typedef AsnSe
\_MemberDesc \>\>\>AsnSequenceMemberDesc;\\
372 struct AsnMembersTypeDesc: AsnTypeDesc\\
374 \>\>AsnMembersTypeDesc (const AsnModuleDesc *, const char *,\\
375 \`bool ispdu, AsnType *
(*create)(), Type);\\
378 int \>\>TclGetDesc (Tcl\_DString *) const;\-\\
382 struct AsnChoiceTypeDesc: AsnMembersTypeDesc\\
384 const AsnChoiceMemberDesc \>\>*const members;\\
386 \>\>AsnChoiceTypeDesc (const AsnModuleDesc *, const char *,\\
387 \`bool ispdu, AsnType *
(*create)(), Type, const AsnChoiceMemberDesc *);\\
389 int \>\>choicebyname (const char *name) const;\\
390 const char \>\>*choicebyvalue (int value) const;\\
393 int \>\>TclGetDesc2 (Tcl
\_DString *) const;\-\\
397 struct AsnSe
\_TypeDesc: AsnMembersTypeDesc
\qquad//
\_ == t/quence\\
399 const AsnSe
\_MemberDesc \>\>*const members;\\
401 \>\>AsnSe
\_TypeDesc (const AsnModuleDesc *, const char *,\\
402 \`bool ispdu, AsnType *
(*create)(), Type, const AsnSe\_MemberDesc *);\\
405 int \>\>TclGetDesc2 (Tcl
\_DString *) const;\-\\
409 typedef AsnSe
\_TypeDesc \>\>\>AsnSetTypeDesc;\\
410 typedef AsnSe
\_TypeDesc \>\>\>AsnSequenceTypeDesc;
413 As for
{\C AsnTypeDesc::name
} above, the content of
{\C AsnMemberDesc::name
} is either the member's name as used by the backend code (default, or if snacc was called with the
{\ufn -mC
} switch) or the component's name as defined in the
{\ufn .asn1
} file (if snacc has been called with the
{\ufn -mA
} command line option).
414 The generated source code contains the respective counterpart printed in a comment.
415 In case the ASN
.1 component was not given a name, the backend's member name is used instead.
417 The data classes have a member function called
{\C \_getref}, that allows the C++ class members to be accessed by their name.
418 {\C \_getref()
} is the second metacode function and it is present in all C++ classes representing composed ASN
.1 types.
420 A class for a SET contains the following code fragment:
422 class FooSet: public AsnType\+\\
423 AsnInt \>\>bar; // an example data member\\
424 \dots // lots of member functions\\
426 static const AsnSetTypeDesc \>\>
\_desc;\\
427 static const AsnSetMemberDesc \>\>mdescs
[];\\
428 const AsnTypeDesc \>\>*
\_getdesc() const;\\
429 AsnType \>\>*
\_getref (const char *membername, bool create = false);\\
431 int \>\>TclGetDesc (Tcl
\_DString *) const;\\
432 int \>\>TclGetVal (Tcl
\_Interp *) const;\\
433 int \>\>TclSetVal (Tcl
\_Interp *, const char *valstr);\\
434 int \>\>TclUnsetVal (Tcl
\_Interp *, const char *membername);\-\\
440 {\C \_getref()
}'s
{\C bool
} parameter
{\C create
} determines whether a non-existing member should be returned as a
{\C NULL
} pointer or whether it should instead be allocated and its address be returned.
441 This parameter is used by value reading and writing routines to implement their different member access semantics.
443 The following four assignments are equivalent:
447 *(AsnInt *)foo.
\_getref ("bar") =
1;\\
448 foo.bar.TclSetVal (interp, "
1");\\
449 foo.
\_getref ("bar")-->TclSetVal (interp, "
1");
451 {\C TclSetVal()
} is a virtual member function and therefore no cast from
{\C AsnType~*
} to
{\C AsnInt~*
} is required.
452 The Tcl interface will be described in chapter~
\ref{tcl-if-chapter
}.
454 The C++ classes that represent CHOICE types contain an
{\C enum ChoiceIdEnum
} that allows
{\C \_getref()
} to be written using a
{\C switch
} statement.
455 The functions
{\C choicebyname()
} and
{\C choicebyvalue()
} turn the component's name into its enumeration value and vice versa.
456 (The enum has not been introduced with the metacode, it is used by Snacc's encoding and printing functions as well.)
458 \subsection{\label{meta-list
}SET OF and SEQUENCE OF
}
460 The list description behaves like an ASN
.1 simple type's---the description type is derived directly from the type descriptions' base class and does not redefine any of the metacode functions:
463 struct AsnListTypeDesc: AsnTypeDesc\\
465 const AsnTypeDesc \>\>*const base;\\
467 \>\>AsnListTypeDesc (const AsnModuleDesc *, const char *,\\
468 \`bool ispdu, Type, AsnType *
(*create)(), const AsnTypeDesc *);\-\\
471 \>int \>\>TclGetDesc (Tcl
\_DString *) const;\\
476 The
{\C TclGetDesc
} function merely adds the base type's standard type description (module and type name, pdu flag and type) after its own, so that a programmer may take the base type's name and ask the metacode once again for the base type's full description.
478 A list type's data class on the other hand has got a
{\C \_getref()
} function that gives access to the list's elements and it can be used to insert new elements at any desired position.
480 \subsection{\label{meta-aliases
}Aliases
}
482 For ASN
.1 types being defined as a direct copy of another type, snacc in normal operation uses a C++
{\C typedef
} to define the C++ type.
483 Since this
{\C typedef
} makes the two types totally equivalent, the metacode has no chance to preserve the two types' different names and thus, this contruct cannot be used.
484 A new C++ class has got to be defined instead.
486 Example: the following ASN
.1 code snippet
\dots
488 Int1 ::= INTEGER \
{ foo(
42) \
}\\
491 \dots maps into the following C++ definitions:
493 class Int1: public AsnInt\\
496 \>\>Int1(): AsnInt() \
{\
}\\
497 \>\>Int1 (int i): AsnInt (i) \
{\
}\\
504 static const AsnNameDesc \>\>
\_nmdescs[];\\
505 static const AsnIntTypeDesc \>\>
\_desc;\\
506 const AsnTypeDesc \>\>*
\_getdesc() const;\-\\
511 struct Int2: public Int1\\
513 \>\>Int2(): Int1() \
{\
}\\
514 \>\>Int2 (int i): Int1 (i) \
{\
}\\
515 AsnType \>\>*Clone() const;\\
517 static const AsnAliasTypeDesc \>\>
\_desc;\\
518 const AsnTypeDesc \>\>*
\_getdesc() const;\-\\
523 typedef Int1 \>\>\>Int2;\\
528 The descriptor type's definition points to the reference type:
531 struct AsnAliasTypeDesc: AsnTypeDesc\\
533 const AsnTypeDesc \>\>*const alias;\\
535 \>\>AsnAliasTypeDesc (const AsnModuleDesc *, const char *,\\
536 \`bool ispdu, AsnType *
(*create)(), Type, const AsnTypeDesc *);\\
538 const AsnModuleDesc \>\>*getmodule() const;\\
539 const char \>\>*getname() const;\\
540 bool \>\>ispdu() const;\\
541 Type \>\>gettype() const;\\
542 const AsnNameDesc \>\>*getnames() const;\\
543 %//const AsnMemberDesc \>\>*getmembers() const;\\
546 int \>\>TclGetDesc (Tcl
\_DString *) const;\-\\
551 The
{\C AsnAliasTypeDesc
} is the reason for the five virtual functions from
{\C getmodule
} to
{\C getnames
} defined in both
{\C AsnTypeDesc
} and
{\C AsnNamesTypeDesc
} on the one hand and
{\C AsnAliasTypeDesc
} on the other hand.
552 While the alias type belongs to a different module or has another type name, and it may have another
{\C pdu
} flag value, its type and names array values are those of its reference type.
553 Therefore,
{\C AsnAliasTypeDesc
}'s first three functions of return the description's own values, and the latter two call their reference type's functions.
555 The
{\C getnames
} function has to be defined in the hierarchy's base class because the aliases may be defined for any type of type, not only for types with named values.
557 \subsection{\label{meta-any
}ANY (DEFINED BY)
}
559 ANY DEFINED BY is quite problematic.
560 The ASN
.1 Book
\cite{ASN
.1Book
} calls it ``a rather half-baked attempt at solution''.
561 Since snacc has problems with it---the user has to modify the snacc generated code---and none of our applications requires this construct, no effort has been made to implement it.
563 ANY itself on the other hand would be quite simple to implement---the virtual function call mechanism that is used to implement the ANY type is the basis for the metacode as well.
564 But again, since we have no need for the ANY type, it is as far unimplemented.
565 Besides that, according to the ASN
.1 book, the ``use of ANY without the DEFINED BY construct is ``deprecated'' (frowned upon) by the standard''.
566 The next ASN
.1 standard will probably not have the ANY type any more.
567 In the
1993 draft standard
\cite{asn1:
1993}, ANY and ANY DEFINED BY can be found in ``Annex I: Superseded features'', Section
3: ``The any type''.
568 % Macros can be found in this annex as well.
570 \subsection{\label{meta-modules-sect
}Modules
}
572 Every
{\ufn .C
} file (that corresponds to an
{\ufn .asn1
} file, or, an ASN
.1 module), gets an array that lists all the module's types.
573 This array contains pointers to all the
{\C \_desc} members of all classes of a module.
576 struct AsnModuleDesc\\
578 const char \>\>*const name;\\
579 const AsnTypeDesc \>\>**const types;\-\\
582 extern const AsnModuleDesc \>\>\>*asnModuleDescs
[];
585 The modules themselves are listed in yet another array, the declaration of which is shown in the preceeding line.
586 This array has got its own source file named
{\ufn modules.C
}.
587 This array allows all modules to be found, and every type that is defined for these modules.
589 %-----------------------------------------------------------------------------------------------------------------------------------
592 The metacode is designed with efficiency in mind.
593 The metacode is intended for interpreted interfaces and therefore does not need to be highly optimized.
594 On the other hand, the same object code should be useable for normal (non-metacode) tasks without loss of performance.
596 \subsection{Normal Operation
}
598 The metacode does not significantly affect the normal mode of operation.
599 The static data members
{\C \_mdescs} and
{\C \_desc} do not increase the class instances' size.
600 The virtual function tables, which have already been present (they are used for the ANY type), get a little longer, but since these tables exist only once for every class, this difference is neglible.
601 The class instances reference their virtual function table with a pointer, and so the metacode does not introduce any change here.
602 Except for alias types, the C++ classes generated are exactly the same.
603 The metacode introduces a new class for alias types, but since no new data members are introduced their size stays the same; only the virtual function table pointer is different.
605 All normal member functions (constructor, destructor, assignment operator, encode, decode and print functions) are identical---with only one exception: if the metacode is compiled to be usable by the Tcl interface, the constructors initialize their mandatory members.
607 To sum it up, both code and data grow, but except for a longer loading time from disk and an increased probability for cache misses, the code will run as fast as it does without the metacode.
609 \subsection{Metacode
}
611 The metacode routines are kept quite simple.
612 Intended to be used in conjunction with a Tcl interface, speed was not the most important concern.
613 Consequently, the code is optimized more towards memory usage than run time efficiency.
614 As an example, name to member resolution uses a linear lookup strategy instead of more elaborated algorithms like binary search or hash tables.
615 I think for data types that typically have up to a dozen components, more sophisticated algorithms would have been overkill.
617 A typical object file gets almost
20\% larger due to the metacode (the Tcl interface adds another
25\%).
619 %-----------------------------------------------------------------------------------------------------------------------------------
620 \section{\label{meta-ttab-comparison
}Metacode Vs. Type Tables
}
622 Here's a list of both the type tables' (see chapter~
\ref{ttab-chapter
}) and the metacode's (dis)advantages:
625 \item source code language:
627 \item[$-$
] The type tables are implemented for C only.
628 \item[$-$
] The metacode works only for C++.
633 \item[$-$
] Encoding and decoding using the type tables is said to be about
4 times slower than using the C routines.
634 \item[$+$
] The metacode does not (significantly) harm performance.
639 \item[$+$
] The tables are a lot smaller than the compiled routines.
640 \item[$-$
] The metacode makes the compiled code even larger.
643 \item value constants:
645 \item[$-$
] The type tables lack the values defined in the
{\ufn .asn1
} files.
646 \item[$+$
] The metacode interacts fine with these values.
651 \item[$-$
] The type tables lack the named values defined ENUMERATED, INTEGER and BIT STRING types.
652 \item[$+$
] The metacode interacts fine with these names.
655 \item compatibility to normal snacc code:
657 \item[$-$
] The C structures defined by mkchdr and used by the type table encoding and decoding routines and the C structures defined by snacc's C backend are quite different.
658 \item[$
\pm$
] Where the backend's structures generated for SEQUENCE contain madatory members by value, the type table's structures contain only pointer members!
663 %-----------------------------------------------------------------------------------------------------------------------------------
664 \section{\label{metacode-setup
}Setup for the Metacode Generator
}
666 To compile Snacc with the metacode generator, the following condition must be met:
668 \item either the configure script must be able to find
{\ufn tclsh
} and the Tcl/Tk libraries or you have to insert a
{\C \#define META
1} into
{\ufn \dots/policy.h
}
669 \item the
{\C NO
\_META} preprocessor macro in
{\ufn \dots/policy.h
} must not be set