]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/doc/c++-gen.tex
Security-28.tar.gz
[apple/security.git] / SecuritySNACCRuntime / doc / c++-gen.tex
1 % file: .../doc/c++-gen.tex
2
3 % $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/doc/c++-gen.tex,v 1.1.1.1 2001/05/18 23:14:10 mb Exp $
4 % $Log: c++-gen.tex,v $
5 % Revision 1.1.1.1 2001/05/18 23:14:10 mb
6 % Move from private repository to open source repository
7 %
8 % Revision 1.1.1.1 1999/03/16 18:05:51 aram
9 % Originals from SMIME Free Library.
10 %
11 % Revision 1.1 1997/01/01 22:47:35 rj
12 % first check-in
13 %
14
15 \chapter{\label{c++-code-gen-chapter}C++ Code Generation}
16
17 \section{\label{intro-C++-section}Introduction}
18
19 The C++ backend of snacc was designed after the C backend had been
20 written. The basic model that the generated C++ uses is similar to
21 that of the generated C, but benefits from the object oriented features of
22 C++. This was my first real foray into C++ which may be evident from
23 some of the design.
24
25 As with C, two files are generated for each ASN.1 module, a {\ufn .C}
26 and a {\ufn .h} file.
27
28 Some cleaner designs were rejected either due to their poor
29 performance or the inability of the available C++ compiler to handle
30 those features.
31
32 Tags and lengths would fit nicely into their own classes but
33 performance was considerably worse than the technique used in the C
34 environment. The C design was retained in the C++ model for its
35 superior performance.
36
37 For error management C++'s {\C try} and {\C throw} are obvious
38 replacements for the {\C setjmp} and {\C longjmp} used by the C
39 decoders. Unfortunately this is a newer C++ feature and is not yet
40 supported by gcc.
41
42 C++ templates are very attractive for type safe lists (for SET OF and
43 SEQUENCE OF) without duplicating code. Template support was shaky in
44 gcc at the time the generated code was being tested so they were
45 rejected. Instead, each list generates its own new class with all of
46 the standard list routines.
47
48 As with the C code generation chapter, we will use the EX1 module to
49 help illustrate some of the code generation. The following is the
50 same EX1 module used in the C section.
51
52 \begin{ASNcode}
53 EX1 DEFINITIONS ::=\\
54 BEGIN\\
55 \\
56 anOidVal OBJECT IDENTIFIER ::= \{ joint-iso-ccitt 40 foobar(29) \}\\
57 theSameOidVal OBJECT IDENTIFIER ::= \{ 2 40 29 \}\\
58 anIntVal INTEGER ::= 1\\
59 aBoolVal BOOLEAN ::= TRUE\\
60 \\
61 T1 ::= SEQUENCE\\
62 \{\+\\
63 INTEGER OPTIONAL,\\
64 OCTET STRING OPTIONAL,\\
65 ENUMERATED \{ a(0), b(1), c(2) \},\\
66 SEQUENCE OF INTEGER,\\
67 SEQUENCE \{ id OBJECT IDENTIFIER, value OCTET STRING \},\\
68 CHOICE \{ INTEGER, OBJECT IDENTIFIER \}\-\\
69 \}\\
70 \\
71 END
72 \end{ASNcode}
73
74 The C++ backend to snacc is in the {\ufn \dots/compiler/back-ends/c++-gen/} directory if you want to alter it.
75
76 \section{\label{naming-C++-section}ASN.1 to C++ Naming Conventions}
77
78 The C++ name for a type or value is the same as its ASN.1 name with
79 any hyphens converted to underscores.
80
81 When an ASN.1 type or value name (after converting any hyphens to
82 underscores) conflicts with a C++ keyword or the name of a type in
83 another ASN.1 module (name clashes within the same ASN.1 scope are
84 considered errors and are detected earlier), the resulting C++ class
85 name will be the conflicting name with digits appended to it.
86
87 Empty field names in SETs, SEQUENCEs, and CHOICEs will be filled. The
88 field name is derived from the type name for that field. The library
89 types such as INTEGER etc. have default field names defined by the
90 compiler (see {\ufn \dots/compiler/back-ends/c-gen/rules.c} and
91 {\ufn \dots/compiler/back-ends/c++-gen/rules.c}).
92 The first letter of the field name is in lower case.
93 Empty field names should be fixed properly by adding them to the ASN.1 source.
94
95 New type definitions will be generated for SETs, SEQUENCEs, CHOICEs,
96 ENUMERATED, INTEGERs with named numbers and BIT STRINGs with named bits
97 whose definitions are embedded in other SET, SEQUENCE, SET OF,
98 SEQUENCE OF, or CHOICE definitions. The name of the new type
99 is derived from the name of the type in which it was embedded and will
100 be made unique by appending digits if necessary.
101
102 \section{\label{type-gen-C++-section}ASN.1 to C++ Class Translation}
103
104 This section describes how C++ classes are used to represent each
105 ASN.1 type. First, the general characteristics of each ASN.1 type's
106 C++ class will be discussed followed by how the aggregate types (SETs,
107 SEQUENCEs, CHOICEs, SET OFs, and SEQUENCE OFs) are represented. The
108 representations of non-aggregate types (INTEGER, BOOLEAN, OCTET
109 STRING, BIT STRING, OBJECT IDENTIFIER) and ANY and ANY DEFINED BY
110 types are presented in the next chapter since they form part of the
111 C++ ASN.1 runtime library.
112
113 Every ASN.1 type is represented by a C++ class with the following
114 characteristics:
115 \newcounter{saveenumi}
116 \begin{enumerate}
117 \item it inherits from the {\C AsnType} base class
118 \item it has a parameterless constructor
119 \item it has a copy constructor
120 \item it has a destructor
121 \item it has a clone method, {\C Clone}
122 \item it has an assignment operator
123 \item it has a content encode and decode method, {\C BEncContent} and {\C BDecContent}
124 \item it has a PDU encode and decode method, {\C BEnc} and {\C BDec}
125 \item it has a top level interfaces to the PDU encode and decode methods (handles the {\C setjmp} etc.) for the user, {\C BEncPdu} and {\C BDecPdu}
126 \item it has a print method, {\C Print}, a virtual function that gets called from a global <\/<-operator
127 \setcounter{saveenumi}{\value{enumi}}
128 \end{enumerate}
129 If the metacode has been enabled:
130 \begin{enumerate}
131 \setcounter{enumi}{\value{saveenumi}}
132 \item it has a virtual function {\C \_getdesc} that returns the classes meta description% (only if metacode is enabled)
133 \item if it is a structured type, it has a virtual function {\C \_getref} that returns a pointer to one of its components/members, specified through its name% (only if metacode is enabled)
134 \setcounter{saveenumi}{\value{enumi}}
135 \end{enumerate}
136 If the Tcl code has been enabled:
137 \begin{enumerate}
138 \setcounter{enumi}{\value{saveenumi}}
139 \item it has a virtual function {\C TclGetDesc} to access the metacode's {\C \_getdesc} routine from Tcl% (only if Tcl code is enabled)
140 \item it has a virtual function {\C TclGetVal} to retrieve an instance's value% (only if Tcl code is enabled)
141 \item it has a virtual function {\C TclSetVal} to change an instance's value% (only if Tcl code is enabled)
142 \item for SET, SEQUENCE, SET OF and SEQUENCE of: it has a virtual function {\C TclUnsetVal} to clear OPTIONAL members or to delete list elements, respectively% (only if Tcl code is enabled)
143 \end{enumerate}
144
145 The following C++ fragment shows the class features listed above in greater
146 detail.
147 \begin{Ccode}
148 class Foo: public AsnType\\
149 \{\+\\
150 \dots // data members\\
151 \\
152 \<public:\\
153 \>\>Foo();\\
154 \>\>Foo (const Foo \&);\\
155 \>\>\~{}Foo();\\
156 AsnType \>\>*Clone() const;\\
157 Foo \>\>\&operator = (const Foo \&);\\
158 \\
159 // content encode and decode routines\\
160 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
161 void \>\>BDecContent (BUF\_TYPE b, AsnTag tag, AsnLen elmtLen,\\
162 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
163 \\
164 // PDU (tags/lengths/content) encode and decode routines\\
165 AsnLen \>\>BEnc (BUF\_TYPE b);\\
166 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
167 \\
168 // methods most likely to be used by your code.\\
169 // Returns non-zero for success\\
170 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
171 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
172 \\
173 void \>\>Print (ostream \&os) const;\\
174 \\
175 \<\#if META\\
176 const AsnTypeDesc \>\>*\_getdesc() const;\\
177 AsnType \>\>*\_getref (const char *membername, bool create = false);\\
178 \<\#if TCL\\
179 int \>\>TclGetDesc (Tcl\_DString *) const;\\
180 int \>\>TclGetVal (Tcl\_Interp *) const;\\
181 int \>\>TclSetVal (Tcl\_Interp *, const char *valstr);\\
182 int \>\>TclUnsetVal (Tcl\_Interp *, const char *membername);\\
183 \<\#endif\\
184 \<\#endif\\
185 \<\};
186 \end{Ccode}
187
188 {\C BEnc} and {\C BDec} are PDU encode and decode methods.
189 {\C BEnc} encodes the tag and length pairs for the object's type as
190 well as the content (the object's value) to the given buffer,
191 {\C b}, and returns the number of bytes written to the buffer for
192 the encoding.
193
194 {\C BDec} decodes the expected tag and length pairs as well as the
195 content of the object it is invoked upon from the given buffer,
196 {\C b}, and increments {\C bytesDecoded} by the byte length of
197 the tag(s), length(s) and value decoded. The {\C env} parameter
198 will be used with {\C longjmp} if any decoding error occurs.
199 Decoding errors can be reported via {\C longjmp} from any of the
200 routines that {\C BDec} calls, such as {\C BDecContent};
201 {\C BDec} will call {\C longjmp} directly if the value does not
202 have the correct tag(s).
203
204 {\C BEncContent} and {\C BDecContent} only deal with the content
205 of the type their object represents. {\C BEncContent} encodes the
206 object's value to the given buffer, {\C b}.
207
208 {\C BDecContent} decodes the object's value from the given buffer,
209 {\C b}. The last tag and length pair on the content must be passed in
210 via the {\C tag} and {\C elmtLen} parameters. The {\C tag},
211 although always present, will only be used when decoding OCTET STRING and
212 BIT STRING related types, to determine whether the encoding is
213 constructed. The {\C elmtLen} is the length of the content and may
214 be the indefinite length form. {\C bytesDecoded} is incremented by
215 the actual number of bytes in the content; this is normally the same
216 as {\C elmtLen} unless the indefinite length form was decoded. The
217 {\C env} parameter will be used with {\C longjmp} if any decoding
218 error occurs. The possible decoding errors depend on the type that is
219 being decoded.
220
221 {\C BEncPdu} and {\C BDecPdu} are top-level interfaces to the PDU
222 encode and decode routines. They present the simplest interface;
223 they return TRUE if the operation succeeded and FALSE if an error
224 occurred. Note that the {\C BDecPdu} routine sets up the
225 {\C env} parameter using {\C setjmp} for any {\C longjmp} calls
226 that may occur. If you call {\C BDec} or {\C BDecContent}
227 directly from your code, you must use {\C setjmp} to setup the
228 {\C env} parameter. {\C BEncPdu} checks for any buffer writing
229 errors and {\C BDecPdu} checks for any buffer reading errors.
230
231 The {\C Print} method prints the object's value in ASN.1 value
232 notation. When printing SETs and SEQUENCEs, a global variable
233 is used for the current indent.
234
235 The {\C AsnType} base class, parameterless constructor and
236 {\C Clone} method are required by the ANY and ANY DEFINED BY type
237 handling mechanism explained in Sections \ref{asntype-C++-section} and
238 \ref{any-C++-section}. In brief, the {\C AsnType} provides a base type
239 that has virtual {\C BEnc}, {\C BDec} and {\C Clone} routines.
240 The {\C Clone} routine is used to generate a new instance (not a
241 copy) of the object that it is invoked on. This allows the ANY
242 DEFINED BY type decoder to create a new object of the correct type
243 from one stored in a hash table, when decoding (the {\C Clone}
244 routine calls the parameterless constructor). The virtual {\C BEnc}
245 and {\C BDec} are called from {\C AsnAny} {\C BEnc} and
246 {\C BDec} methods.
247
248 The meta routines and the Tcl interface will be described in chapters \ref{meta-chapter} and \ref{tcl-if-chapter}, respectively.
249
250 \subsection{\label{C++-set-seq-section}SET and SEQUENCE}
251
252 SET and SEQUENCE types generate classes that have their components as
253 public data members. This makes accessing the components similar to
254 referencing the fields of a C struct. For example the {\C T1} type in
255 module EX1 will produce the following C++ class:
256
257 \begin{Ccode}
258 class T1: public AsnType\\
259 \{\\
260 public:\+\\
261 AsnInt \>\>*integer;\\
262 AsnOcts \>\>*octs;\\
263 T1Enum \>\>t1Enum;\\
264 T1SeqOf \>\>t1SeqOf;\\
265 T1Seq \>\>*t1Seq;\\
266 T1Choice \>\>*t1Choice;\\
267 \\
268 \>\>T1();\\
269 % {\\
270 % /* init optional/default elements to NULL */\\
271 % integer = NULL;\\
272 % octs = NULL;\\
273 % }\\
274 \>\>T1 (const T1 \&);\\
275 \>\>\~{}T1();\\
276 % AsnType *Clone() { return new T1; }\\
277 AsnType \>\>*Clone() const;\\
278 \\
279 T1 \>\>\&operator = (const T1 \&);\\
280 \\
281 AsnLen \>\>BEnc (BUF\_TYPE b);\\
282 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
283 \\
284 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
285 void \>\>BDecContent (BUF\_TYPE b, AsnTag tag, AsnLen elmtLen,\\
286 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
287 \\
288 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
289 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
290 \\
291 void \>\>Print (ostream \&os) const;\\
292 \\
293 \<\#if META\\
294 static const AsnSequenceTypeDesc \\
295 \>\>\_desc;\\
296 static const AsnSequenceMemberDesc \\
297 \>\>mdescs[];\\
298 const AsnTypeDesc \>\>*\_getdesc() const;\\
299 AsnType \>\>*\_getref (const char *membername, bool create = false);\\
300 \\
301 \<\#if TCL\\
302 int \>\>TclGetDesc (Tcl\_DString *) const;\\
303 int \>\>TclGetVal (Tcl\_Interp *) const;\\
304 int \>\>TclSetVal (Tcl\_Interp *, const char *valstr);\\
305 int \>\>TclUnsetVal (Tcl\_Interp *, const char *membname);\\
306 \<\#endif // TCL\\
307 \<\#endif // META\\
308 \<\};
309 \end{Ccode}
310
311 All OPTIONAL components in a SET or SEQUENCE are referenced by pointer.
312 The constructor will automatically set OPTIONAL fields to {\C NULL}\@. The
313 other methods are as described at the beginning of this section.
314
315 SETs and SEQUENCEs must contain all non-OPTIONAL components and
316 SEQUENCEs must be ordered, otherwise an error is reported. Tagging
317 errors are also reported. All detected errors abort the decoding
318 process via {\C longjmp}.
319
320 \subsection{\label{C++-choice-section}CHOICE}
321
322 Each CHOICE type generates a class that has an anonymous union to hold the
323 components of the CHOICE and a {\C choiceId} field to indicate which
324 component is present.
325
326 Anonymous (un-named) unions allow you to reference the choice components
327 with just the field name of the component; this makes referencing the
328 contents of a CHOICE the same a referencing the contents of a SET or
329 SEQUENCE\@.
330
331 The {\C choiceId} field contains a value in the {\C ChoiceIdEnum}
332 that indicates the CHOICE field that is present. The names in the
333 enumeration are derived from the field names of the CHOICE components.
334
335 When building a local value to be encoded, you must be sure to set the
336 {\C choiceId} such that it corresponds to the value in the union. The
337 decoder will set the {\C choiceId} when decoding incoming values.
338
339 Tagging errors are reported and abort the decoding process via
340 {\C longjmp}.
341
342 The following C++ class is produced for the CHOICE in the EX1 module.
343
344 \begin{Ccode}
345 class T1Choice: public AsnType\\
346 \{\\
347 public:\+\\
348 enum ChoiceIdEnum\\
349 \{\+\\
350 integerCid = 0,\\
351 oidCid = 1\-\\
352 \};\\
353 \\
354 enum ChoiceIdEnum \>\>choiceId;\\
355 union\\
356 \{\+\\
357 AsnInt \>*integer;\\
358 AsnOid \>*oid;\-\\
359 \};\\
360 \\
361 \>\>T1Choice();\\
362 \>\>T1Choice (const T1Choice \&);\\
363 \>\>\~{}T1Choice();\\
364 AsnType \>\>*Clone() const;\\
365 \\
366 T1Choice \>\>\&operator = (const T1Choice \&);\\
367 \\
368 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
369 void \>\>BDecContent (BUF\_TYPE b, AsnTag tag, AsnLen elmtLen,\\
370 \`AsnLen \&bytesDecoded, ENV\_TYPE env);\\
371 \\
372 AsnLen \>\>BEnc (BUF\_TYPE b);\\
373 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
374 \\
375 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
376 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
377 \\
378 void \>\>Print (ostream \&os) const;\\
379 \\
380 \<\#if META\\
381 static const AsnChoiceTypeDesc \>\>\_desc;\\
382 static const AsnChoiceMemberDesc \\
383 \>\>\_mdescs[];\\
384 \\
385 const AsnTypeDesc \>\>*\_getdesc() const;\\
386 AsnType \>\>*\_getref (const char *membername, bool create = false);\\
387 \\
388 \<\#if TCL\\
389 int \>\>TclGetDesc (Tcl\_DString *) const;\\
390 int \>\>TclGetVal (Tcl\_Interp *) const;\\
391 int \>\>TclSetVal (Tcl\_Interp *, const char *valstr);\\
392 \<\#endif // TCL\\
393 \<\#endif // META\\
394 \<\};
395 \end{Ccode}
396
397
398
399 \subsection{\label{C++-set-of-section}SET OF and SEQUENCE OF}
400
401 Each SET OF and SEQUENCE OF type produces its own list class, unlike
402 the C backend which uses a single generic list type for all lists.
403 This makes the C++ list routines type safe which allows the C++
404 compiler to detect more programmer errors.
405
406 C++ templates should be used to reduce the code duplication when they
407 become widespread and reliably implemented. The duplicated list
408 handling methods may bloat the size of the generated code.
409
410 Any tagging errors are reported and abort the decoding process via
411 {\C longjmp}.
412
413 From the EX1 ASN.1 module the following list is produced:
414 \begin{Ccode}
415 class T1SeqOf: public AsnType\\
416 \{\\
417 protected:\+\\
418 unsigned long int\>\>count;\\
419 struct AsnListElmt\\
420 \{\+\\
421 struct AsnListElmt \>*next;\\
422 struct AsnListElmt \>*prev;\\
423 AsnInt \>*elmt;\-\\
424 \} \>\>*first, *curr, *last;\\
425 \\
426 \<public:\\
427 \>\>T1SeqOf() \{ count = 0; first = curr = last = NULL; \}\\
428 \>\>\~{}T1SeqOf();\\
429 AsnType \>\>*Clone() const;\\
430 \\
431 void \>\>SetCurrElmt (unsigned long int index);\\
432 unsigned long int \>\>GetCurrElmtIndex();\\
433 void \>\>SetCurrToFirst();\\
434 void \>\>SetCurrToLast();\\
435 \\
436 // reading member fcns\\
437 int \>\>Count() const;\\
438 AsnInt \>\>*First() const;\\
439 AsnInt \>\>*Last() const;\\
440 AsnInt \>\>*Curr() const;\\
441 AsnInt \>\>*Next() const;\\
442 AsnInt \>\>*Prev() const;\\
443 \\
444 // routines that move the curr elmt\\
445 AsnInt \>\>*GoNext();\\
446 AsnInt \>\>*GoPrev();\\
447 \\
448 // write \& alloc fcns--returns new elmt\\
449 AsnInt \>\>*Append(); // add elmt to end of list\\
450 AsnInt \>\>*Prepend(); // add elmt to beginning of list\\
451 AsnInt \>\>*InsertBefore(); // insert elmt before current elmt\\
452 AsnInt \>\>*InsertAfter(); // insert elmt after current elmt\\
453 \\
454 // write \& alloc \& copy--returns list after copying elmt\\
455 T1SeqOf \>\>\&AppendCopy (AsnInt \&elmt); // add elmt to end of list\\
456 T1SeqOf \>\>\&PrependCopy (AsnInt \&elmt); // add elmt to beginning of list\\
457 T1SeqOf \>\>\&InsertBeforeAndCopy (AsnInt \&elmt); // insert elmt before current elmt\\
458 T1SeqOf \>\>\&InsertAfterAndCopy (AsnInt \&elmt); // insert elmt after current elmt\\
459 \\
460 // removing the current elmt from the list\\
461 void \>\>RemoveCurrFromList();\\
462 \\
463 // encode and decode routines\\
464 AsnLen \>\>BEncContent (BUF\_TYPE b);\\
465 void \>\>BDecContent (BUF\_TYPE b, AsnTag tag, AsnLen elmtLen,\\
466 \` AsnLen \&bytesDecoded, ENV\_TYPE env);\\
467 \\
468 AsnLen \>\>BEnc (BUF\_TYPE b);\\
469 void \>\>BDec (BUF\_TYPE b, AsnLen \&bytesDecoded, ENV\_TYPE env);\\
470 \\
471 int \>\>BEncPdu (BUF\_TYPE b, AsnLen \&bytesEncoded);\\
472 int \>\>BDecPdu (BUF\_TYPE b, AsnLen \&bytesDecoded);\\
473 \\
474 void \>\>Print (ostream \&os);\\
475 \\
476 \<\#if META\\
477 static const AsnListTypeDesc \>\>\_desc;\\
478 const AsnTypeDesc \>\>*\_getdesc() const;\\
479 AsnType \>\>*\_getref (const char *index, bool create = false);\\
480 \\
481 \<\#if TCL\\
482 int \>\>TclGetDesc (Tcl\_DString *) const;\\
483 int \>\>TclGetVal (Tcl\_Interp *) const;\\
484 int \>\>TclSetVal (Tcl\_Interp *, const char *valstr);\\
485 int \>\>TclUnsetVal (Tcl\_Interp *, const char *valstr);\\
486 \<\#endif // TCL\\
487 \<\#endif // META\\
488 \<\};
489 \end{Ccode}
490
491 Each list is doubly linked to allow simple reverse traversal for
492 backwards encoding. The {\C prev} pointer will be {\C NULL} for the
493 first element of the list and the {\C next} pointer will be {\C NULL} for
494 the last element of the list.
495
496 Each list maintains a pointer to the current element of the list.
497 Several routines are provided to manipulate the current item. Since
498 there is only one current pointer, you may have to save and restore
499 the current pointer with the {\C GetCurrElmtIndex} and
500 {\C SetCurrElmt} methods if you call routines that deal with the
501 list while iterating through it.
502
503 In addition to the standard encode, decode and print methods, some
504 list utility routines are included in each list class. They are
505 fairly simple and are described briefly here.
506
507 \begin{Ccode}
508 void \>\>\>SetCurrElmt (unsigned long int index);
509 \end{Ccode}
510 This sets the current pointer to the element with the given index.
511 Indexes start at zero, that is, the first element in the list has an
512 index of zero. If the given index is greater than or equal to the
513 number of elements in the list, the current pointer is set to the last
514 element of the list.
515
516 \begin{Ccode}
517 unsigned long int \>\>\>GetCurrElmtIndex();
518 \end{Ccode}
519 This returns the index of the current element. If the current pointer
520 is {\C NULL} (or does not reference an element of the list, which is an
521 error condition), the index returned will be greater than or equal to
522 the number of elements in the list (indexes start at zero so this is
523 an invalid index).
524
525
526 \begin{Ccode}
527 void \>\>\>SetCurrToFirst();
528 \end{Ccode}
529 This sets the current pointer to the first element of the list. If the
530 list is empty, it is set to {\C NULL}\@.
531 \begin{Ccode}
532 void \>\>\>SetCurrToLast();
533 \end{Ccode}
534 This sets the current pointer to the last element of the list. If the
535 list is empty, it is set to {\C NULL}\@.
536
537
538 \begin{Ccode}
539 int \>\>\>Count() const;
540 \end{Ccode}
541 This returns the number of elements in the list.
542
543 \begin{Ccode}
544 AsnInt \>\>\>*First() const;\\
545 AsnInt \>\>\>*Last() const;\\
546 AsnInt \>\>\>*Curr() const;\\
547 AsnInt \>\>\>*Next() const;\\
548 AsnInt \>\>\>*Prev() const;
549 \end{Ccode}
550 The above routines return a pointer to the list element that the
551 routine name indicates. They return {\C NULL} if the requested element is
552 not present. For example {\C First} will return a pointer to the
553 first element in the list or {\C NULL} if the list is empty. These
554 routines do not affect the state of the list; the current pointer and
555 the count remain the same.
556
557 \begin{Ccode}
558 AsnInt \>\>\>*GoNext();\\
559 AsnInt \>\>\>*GoPrev();
560 \end{Ccode}
561 These routines change the current pointer to the next/previous element
562 and return a pointer to that element. If the current element is {\C NULL} or
563 points to the last element, {\C GetNext} returns {\C NULL}\@. Similarly, if
564 the current element is {\C NULL} or points to the first element, {\C GetPrev}
565 returns {\C NULL}\@.
566
567
568 \begin{Ccode}
569 AsnInt \>\>\>*Append();
570 \end{Ccode}
571 This allocates a new list element, appends it to the end of the list
572 and returns a pointer to the new list element. Notice that you must
573 set the value of the returned list element.
574
575 \begin{Ccode}
576 AsnInt \>\>\>*Prepend();
577 \end{Ccode}
578 This allocates a new list element, prepends it to the beginning of the
579 list and returns a pointer to the new list element. You must set the
580 value of the returned list element.
581
582 \begin{Ccode}
583 AsnInt \>\>\>*InsertBefore();
584 \end{Ccode}
585 This allocates a new list element, inserts it before the current list
586 element and returns a pointer to the new list element. You must set
587 the value of the returned list element. If the current pointer is
588 {\C NULL}, the new element is placed at the beginning of the list.
589
590 \begin{Ccode}
591 AsnInt \>\>\>*InsertAfter();
592 \end{Ccode}
593 This allocates a new list element, inserts it after the current list
594 element and returns a pointer to the new list element. You must set
595 the value of the returned list element. If the current pointer is
596 {\C NULL}, the new element is placed at the end of the list.
597
598 \begin{Ccode}
599 T1SeqOf \>\>\>\&AppendCopy (AsnInt \&elmt);\\
600 T1SeqOf \>\>\>\&PrependCopy (AsnInt \&elmt);\\
601 T1SeqOf \>\>\>\&InsertBeforeAndCopy (AsnInt \&elmt);\\
602 T1SeqOf \>\>\>\&InsertAfterAndCopy (AsnInt \&elmt);
603 \end{Ccode}
604 These are similar to the {\C Append}, {\C Prepend},
605 {\C InsertBefore} and {\C InsertAfter} routines except that a
606 copy of the given element's value is placed in the list and the list
607 itself is returned.
608
609 \subsection{\label{C++-enumerated-section}ENUMERATED, Named Numbers and Named Bits}
610
611 The C++ type generator encapsulates each ENUMERATED type, INTEGER
612 with named numbers and BIT STRING with named bits in a new class that
613 inherits from the proper base class and defines the named elements.
614 This provides a separate scope for these identifiers so their symbol
615 will be exactly the same as their ASN.1 counterpart. Currently these
616 identifiers are not checked for conflicts with C++ keywords, so you
617 may have to modify some of them in the ASN.1 modules.
618
619 Inheritance is used for attaching ENUMERATED, named number and named
620 bit information. ENUMERATED types inherit from the {\C AsnEnum} class,
621 INTEGERs with named number types inherit from the {\C AsnInt} class and BIT
622 STRINGs with named bits inherit from the {\C AsnBits} class.
623
624 If the tagging on the type is different from the type it inherits
625 from, the PDU encode and decode methods are re-defined with the
626 correct tags to override the PDU encode and decode methods of the base
627 class.
628
629 As with the other types, any tagging errors are reported and abort the
630 decoding process via {\C longjmp}. No range checking is done on the
631 decoded values although it would be easy to provide a new
632 {\C BDecContent} method in the new class that calls the base class's
633 and then checks the range of the result.
634
635 \begin{Ccode}
636 /* ENUMERATED { a(0), b(1), c(2) } */\\
637 class T1Enum: public AsnEnum\\
638 \{\\
639 public:\\
640 \#if TCL\\
641 \> \>\>T1Enum(): AsnEnum (\_nmdescs[0].value) \{\}\\
642 \#else\\
643 \> \>\>T1Enum(): AsnEnum () \{\}\\
644 \#endif\+\\
645 \>\>T1Enum (int i): AsnEnum (i) \{\}\\
646 enum\\
647 \{\+\\
648 a = 0,\\
649 b = 1,\\
650 c = 2\-\\
651 \};\\
652 \\
653 \<\#if META\\
654 static const AsnNameDesc \>\>\_nmdescs[];\\
655 static const AsnEnumTypeDesc \>\>\_desc;\\
656 const AsnTypeDesc \>\>*\_getdesc() const;\\
657 \<\#endif // META\\
658 \<\};
659 \end{Ccode}
660
661 \section{\label{val-gen-C++-section}ASN.1 to C++ Value Translation}
662
663 C++ {\C const} values are used to hold ASN.1 defined values. C++
664 values will be produced for INTEGER, BOOLEAN and OBJECT IDENTIFIER
665 ASN.1 values. An {\C extern} declaration for each {\C const} value is
666 written at the end of the header file of the value's module. The
667 {\C const} values are defined at the beginning of the {\ufn .C} file
668 of the value's module. The {\C extern} declarations are at the end
669 of the header file so that any required class definitions are
670 available.
671
672 The following is from the end of the header file generated for the EX1
673 module:
674 \begin{Ccode}
675 extern const AsnOid \>\>\>anOidVal;\\
676 extern const AsnOid \>\>\>theSameOidVal;\\
677 extern const AsnInt \>\>\>anIntVal;\\
678 extern const AsnBool \>\>\>aBoolVal;
679 % \\ extern const AsnInt \>\>\>foobar;
680 \end{Ccode}
681
682 The following is from the beginning of the {\ufn .C} file generated
683 for the EX1 module:
684 \begin{Ccode}
685 const AsnOid \>\>\>anOidVal (2, 40, 29);\\
686 const AsnOid \>\>\>theSameOidVal (2, 40, 29);\\
687 const AsnInt \>\>\>anIntVal (1);\\
688 const AsnBool \>\>\>aBoolVal (true);
689 % \\ const AsnInt \>\>\>foobar (29);
690 \end{Ccode}
691
692 The C++ constructor mechanism is used to generate these values. This
693 mechanism is superior to C static initialization because it allows C++
694 code to be run to initialize the values.
695
696 \section{\label{compiler-dir-C++-section}Compiler Directives}
697 Compiler directives are ignored by the C++ backend of snacc. If you want
698 to implement them, look at the {\C FillCxxTypeDefInfo} routine in
699 file {\ufn \dots/compiler/back-ends/c++-gen/types.c}. Then look at the
700 way it is done for the C backend (file
701 {\ufn \dots/compiler/back-ends/c-gen/type-info.c})
702
703 \section{\label{compiling-gen-C++-section}Compiling the Generated C++ Code}
704
705 When compiling the generated C++ code you will need:
706 \begin{enumerate}
707 \item
708 The include directory where the files from {\ufn \dots/c++-lib/inc/} have been installed in your include path so that the C++ sources can include these library header files.
709 The header files should be included with statements like {\C \#include <snacc/c++/asn-incl.h>} and your C++ compiler should be supplied with {\ufn -I/usr/local/include} in case snacc got installed under {\ufn /usr/local/}.
710 \item
711 to link with the C++ ASN.1 runtime library, {\ufn \dots/c++-lib/libasn1c++.a}.
712 In case snacc got installed under {\ufn /usr/local/}, your linker may need to be supplied with {\ufn -L/usr/local/lib} and {\ufn -lasn1c++} as arguments.
713 \item
714 to link with the math library ({\ufn -lm}), since the ASN.1 REAL type's encode and decode routine use some math routines.
715 \end{enumerate}
716
717 See the example in {\ufn \dots/c++-examples/simple/} for a complete
718 example. The makefile and main routines are probably the most
719 important. There are several other examples in the
720 {\ufn \dots/c++-examples/} directory.