1 % file: .../doc/ttab.tex
3 % $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/doc/ttab.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:55 aram
9 % Originals from SMIME Free Library.
11 % Revision 1.1 1997/01/01 22:47:43 rj
15 \chapter{\label{ttab-chapter
}Type Tables
}
17 Type tables are a flexible and compact way of dealing with ASN
.1.
18 The type table data structure is included in the appendix. It was
19 defined in ASN
.1 to provide a good storage format for the tables.
21 When snacc produces a type table it includes the useful types module
22 as well, if one was specified. If you are really trying to limit the
23 size of your type tables, put the only useful types that you need in
24 your ASN
.1 module and compile it without using the useful types
27 A generic buffer type (à la ISODE and XDR) was defined to allow type
28 table driven routines to read from a wide variety of buffer formats.
29 Currently slightly modified versions of the
{\C ExpBuf
} and the
30 {\C SBuf
} are provided. It shouldn't be too hard for you to add
31 support for your own buffer formats. The generic buffers,
32 {\C GenBuf
}s are described in more detail in a following section.
34 The general procedure for using type tables is to:
36 \item Use snacc to compile your ASN
.1 modules into a type table.
37 \item Use
{\ufn mkchdr
} (make C header, not make cheddar) with the
38 type table to produce a friendly C type description of the types in
40 \item Load the type table during runtime and use it to configure the table
41 encode, decode and other routines.
44 Step two, making the C header file is not necessary but will make
45 dealing with the value easier and more type safe. Internally the
46 table driven encoders and decoders know nothing of these header file
47 and treat the types in a uniform, generic manner. This requires the
48 encoders and decoders to make assumptions about the way C represents
49 strucutures and values. Look in the
{\ufn \dots/c-lib/src/tbl-enc.c
} and
50 {\ufn \dots/c-lib/src/tbl-dec.c
} files to see how this generic data
51 structure is manipulated.
53 On the down side, the compiler directives do not affect the data
54 structures generated by mkchdr and the generated C type definitions
55 will generally be different from those generated by the C backend.
56 This can be fixed, but time was lacking. Type tables also do not
57 support ANY DEFINED BY types. Someone could fix this without too much
58 difficulty. Only a C type table library is provided. I didn't have
59 time to deal with the complexities of creating C++ objects in a
62 Currently the type tables are lacking subtyping information. It is
63 available in snacc's main parse tree but I didn't have time to add it
64 to the tables. If you want to add it, take the subtype related data
65 structures (in ASN
.1) from asn1module.asn1 (quite a few), remove all
66 the cruft pertaining to linking and error checking etc, and add it to
67 the type table type definitions. Then change the
68 {\ufn \dots/compiler/core/gen-tbls.c
} file to take the subtype information from
69 the parse tree and put it into the type table. See the appendix or
70 {\ufn \dots/asn1specs/
} for the ASN
.1 definitions of the parse tree
73 The parse tree itself was defined in ASN
.1 so it could be the table
74 format. The extra complexity required for linking and error checking
75 made this very difficult. Cycles in the data structure and the many
76 links between the data elements made encoding in BER difficult.
77 [Maybe ASN
.1 needs a type refernce type (i.e. pointer)
].
80 \section{How Type Table See Values
}
82 As mentioned in the last section, table driven encoding, decoding,
83 printing etc. routines see your values in a generic way. They do not
84 have abstract syntax specific header files like those created by
87 The basic idea is that all of the standard primitive and list
88 (SEQUENCE OF and SET OF) types are used and some regular rules are
89 used for allocating and laying out structs for SEQUENCE, SET and
94 /* values from table driver routines' point of view */
97 /* SEQUENCE and SET type use AStructVal */
98 typedef AVal *AStructVal; /* an array of AVal ptrs */
102 For SETs and SEQUENCEs, the
{\C AStructVal
} type is used. Its is
103 basically an array of pointers, one for each component of the
104 SET/SEQUENCE\@. Every component is referenced by pointer to simplify
105 allocations. OPTIONAL or DEFAULT components may be NULL\@. For
110 Foo ::= SEQUENCE
{ a INTEGER, b BOOLEAN, c OCTET STRING
}
114 would be represented as an array of three pointers. The first pointer
115 would point to an
{\C AsnInt
} value, the second would point to an
116 {\C AsnBool
} value, and the third would point to an
{\C AsnOcts
}
117 value.
{\ufn mkchdr
} would give you the following C typedef for Foo:
132 /* Internal representation for a CHOICE type */
133 typedef struct AChoiceVal
135 enum
{ achoiceval_notused
} choiceId;
142 A CHOICE type is represented in a way similar to the C backend's
143 output. That is, an enum to hold the id of the CHOICE component
144 that is present and a pointer to the component itself. For example,
149 Bar ::= CHOICE
{ a INTEGER, b BOOLEAN, c OCTET STRING
}
153 would internally be represented as AChoiceVal type. However,
154 {\ufn mkchdr
} would give you the following:
177 \section{Type Table Utilities
}
179 There are a bunch of useful routines in
{\ufn \dots/c-lib/src/tbl*.c
}. Look
180 at the source code in
{\ufn \dots/tbl-tools/*/
} and
181 {\ufn \dots/tbl-example/
} to see how to use some of them.
183 The
{\C LoadTblFile
} will decode a type table from a given file.
184 Notice that its definition of the
{\C TBL
} data structure has been
185 augmented to simplify encoding and decoding operations. (Look at the
186 patch in
{\ufn \dots/c-lib/tbl.h.patch
} that is applied through the makefile automatically.)
187 % The additional fields do not screw up the compiled encoder/decoder (in {\ufn \dots/c-lib/src/tbl.c}) provided they are recompiled.
188 The compiler uses unmodified
{\ufn tbl.h
} and
{\ufn tbl.c
} files.
190 I don't have time to
document these routines. Look through the table
191 tools, examples and library code. Their usage should be fairly
195 \section{Type Table Tools
}
197 The
{\ufn \dots/tbl-tools/
} directory contains three tools,
{\ufn mkchdr
},
198 {\ufn pval
} and
{\ufn ptbl
}. These are described in the following
201 \subsection{Making C Header Files with mkchdr
}
203 {\ufn mkchdr
} produces a C header file from a type table. This header
204 file shows the representation of the types that the table tools will
205 expect or return for the types in the given type table.
207 The main use is to provide you with an easy to use definition of the
208 ASN
.1 types C representation. You do not need to use
{\ufn mkchdr
}
209 but it is definately recommended. Note that the table routines could
210 have used an even more generic data structure to represent values
211 (e.g. ISODE's Presentation Elements). If you have worked with these,
212 you know that they are cumbersome.
217 mkchdr <tbl-file>
[output-file
]
221 If the output file is omitted, the header file is printed to
{\C stdout
}.
223 Here is an example of the output. Given the table that has the
224 following ASN
.1 module in it:
228 P-REC DEFINITIONS ::=
230 PersonnelRecord ::=
[APPLICATION
0] IMPLICIT SET
236 nameOfSpouse
[2] Name,
237 children
[3] IMPLICIT SEQUENCE OF ChildInformation DEFAULT
{}
240 ChildInformation ::= SET
246 Name ::=
[APPLICATION
1] IMPLICIT SEQUENCE
253 EmployeeNumber ::=
[APPLICATION
2] IMPLICIT INTEGER
255 Date ::=
[APPLICATION
3] IMPLICIT IA5String -- YYYYMMDD
261 {\ufn mkchdr
} will produce:
264 typedef AsnInt EmployeeNumber;
268 IA5String *givenName;
270 IA5String *familyName;
273 typedef IA5String Date;
275 typedef struct ChildInformation
281 typedef AsnList PersonnelRecordSeqOf;
283 typedef struct PersonnelRecord
287 EmployeeNumber *field1;
290 PersonnelRecordSeqOf *children;
297 \subsection{Printing Tables with ptbl
}
299 {\ufn ptbl
} is a program that will show you the contents of a type
300 table. It can print a table in two modes:
302 \item The value notation for the TBL ASN
.1 data structure (see the appendix).
303 \item The ASN
.1 text version
314 For example, using
{\ufn ptbl -a p-rec.tt
} to print the
315 PersonnelRecord module used in the last section would yield:
319 P-REC DEFINITIONS ::=
321 EmployeeNumber ::=
[APPLICATION
2] IMPLICIT INTEGER
322 Name ::=
[APPLICATION
1] IMPLICIT SEQUENCE
328 Date ::=
[APPLICATION
3] IMPLICIT IA5String
329 ChildInformation ::= SET
334 PersonnelRecordSeqOf ::= SEQUENCE OF ChildInformation
335 PersonnelRecord ::=
[APPLICATION
0] IMPLICIT SET
341 nameOfSpouse
[2] Name,
342 children
[3] IMPLICIT PersonnelRecordSeqOf
345 -- Definitions for ASN-USEFUL
346 ASN-USEFUL DEFINITIONS ::=
348 ObjectDescriptor ::=
[UNIVERSAL
7] IMPLICIT OCTET STRING
349 NumericString ::=
[UNIVERSAL
18] IMPLICIT OCTET STRING
350 PrintableString ::=
[UNIVERSAL
19] IMPLICIT OCTET STRING
351 TeletexString ::=
[UNIVERSAL
20] IMPLICIT OCTET STRING
352 T61String ::=
[UNIVERSAL
20] IMPLICIT OCTET STRING
353 VideotexString ::=
[UNIVERSAL
21] IMPLICIT OCTET STRING
354 IA5String ::=
[UNIVERSAL
22] IMPLICIT OCTET STRING
355 GraphicString ::=
[UNIVERSAL
25] IMPLICIT OCTET STRING
356 VisibleString ::=
[UNIVERSAL
26] IMPLICIT OCTET STRING
357 ISO646String ::=
[UNIVERSAL
26] IMPLICIT OCTET STRING
358 GeneralString ::=
[UNIVERSAL
27] IMPLICIT OCTET STRING
359 UTCTime ::=
[UNIVERSAL
23] IMPLICIT OCTET STRING
360 GeneralizedTime ::=
[UNIVERSAL
24] IMPLICIT OCTET STRING
361 EXTERNAL ::=
[UNIVERSAL
8] IMPLICIT SEQUENCE
363 direct-reference OBJECT IDENTIFIER,
364 indirect-reference INTEGER,
365 data-value-descriptor ObjectDescriptor,
368 single-ASN1-type
[0] OCTET STRING,
369 octet-aligned
[1] IMPLICIT OCTET STRING,
370 arbitrary
[2] IMPLICIT BIT STRING
377 Note that the useful type module is included in the table. As
378 mentioned before, to minimize the size of your tables, put the
379 definitions of the useful types (from
{\ufn \dots/asn1specs/asn-useful.asn1
})
380 into your ASN
.1 module and do not compile with useful types module
381 (i.e. don't use the -u option). If your module doesn't use any
382 useful types, just don't use the -u option.
384 The other mode of
{\ufn ptbl
}, value notation for the TBL data
385 structure, produces a lot of output. It may be useful if you are
386 debugging one of the table drivers.
389 \subsection{Printing Values with pval
}
391 The
{\ufn pval
} program will convert BER values into their value
392 notation. Its arguments are a type table file, a module and type name
393 and a list of BER files of that type.
399 pval -T <tt file name>
[-m <module name>
] -n <type name> <ber value file list>
403 Running
{\ufn pval
} on a PersonnelRecord value produced the following:
407 -- Contents of file "demo-tbls/p-rec.ber"--
408 -- module = ???, type = PersonnelRecord --
410 value P-REC.PersonnelRecord ::=
413 givenName '
4a6f686e'H -- "John" --,
414 initial '
45'H -- "E" --,
415 familyName '
536d697468'H -- "Smith" --
417 title '
5468652042696720436865657365'H -- "The Big Cheese" --,
419 dateOfHire '
3139383230313034'H -- "
19820104" --,
421 givenName '
4d617279'H -- "Mary" --,
422 initial '
4c'H -- "L" --,
423 familyName '
536d697468'H -- "Smith" --
428 givenName '
4a616d6573'H -- "James" --,
429 initial '
52'H -- "R" --,
430 familyName '
536d697468'H -- "Smith" --
432 dateOfBirth '
3139353730333130'H -- "
19570310" --
436 givenName '
4c697361'H -- "Lisa" --,
437 initial '
4d'H -- "M" --,
438 familyName '
536d697468'H -- "Smith" --
440 dateOfBirth '
3139363130363231'H -- "
19610621" --
445 -- decoded
143 bytes for the above value --
450 \section{Using Tables in Your Own Applications
}
452 The best way to get a handle on using tables is to look at the example
453 in
{\ufn \dots/tbl-example/
}. The general idea is to compile your
454 ASN
.1 into a type table (use the snacc
{\ufn -T
} option). If you desire a
455 livable definition of the C data structures for the types in the type
456 table, run
{\ufn mkchdr
} and compile the generated header file with
457 your C code. During runtime, simply load your table file with
458 {\C LoadTblFile
} (I use the
{\ufn .tt
} suffix naming convention for type table
459 files but it doesn't matter) and then use the
{\C TblEncode
},
460 {\C TblDecode
},
{\C TblPrint
} and
{\C TblFree
} routines with
461 your table. Quite simple. Seriously.
463 \section{Using GenBufs
}
465 The
{\C GenBuf
} generic buffers are really a way of encapsulating
466 other buffer formats. A
{\C GenBuf
} contains a table of pointers to
467 the buffer functions (the standardized ones (see the buffer section)
468 plus ``Peek'' routines that the table drivers needed). They are
469 defined in
{\ufn \dots/c-lib/inc/gen-buf.h
}.
471 {\C GenBuf
}s require functions for the standard buffer routines,
472 macros will not do since you cannot have a pointer to macro.
474 The benefit of the
{\C GenBuf
}s is that since they can support other
475 buffer types, only one set of library routines is needed. (Note that
476 there are
3 libraries in
{\ufn \dots/c-lib/
} for the backend model and only one for the type table model.
478 Here is most of
{\ufn gen-buf.h
} to give you an idea of how things work:
482 typedef unsigned char
(*BufGetByteFcn) PROTO ((void *b));
483 typedef unsigned char *(*BufGetSegFcn) PROTO ((void *b,
484 unsigned long int *lenPtr));
485 typedef long int (*BufCopyFcn) PROTO ((char *dst, void *b,
486 unsigned long int len));
487 typedef void (*BufSkipFcn) PROTO ((void *b, unsigned long int len));
488 typedef unsigned char (*BufPeekByteFcn) PROTO ((void *b));
489 typedef unsigned char *(*BufPeekSegFcn) PROTO ((void *b,
490 unsigned long int lenPtr));
491 typedef long int (*BufPeekCopyFcn) PROTO ((char *dst, void *b,
492 unsigned long int len));
493 typedef void (*BufPutByteRvsFcn) PROTO ((void *b, unsigned char byte));
494 typedef void (*BufPutSegRvsFcn) PROTO ((void *b, char *data,
495 unsigned long int len));
496 typedef int (*BufReadErrorFcn) PROTO ((void *b));
497 typedef int (*BufWriteErrorFcn) PROTO ((void *b));
499 typedef struct GenBuf
501 BufGetByteFcn getByte;
505 BufPeekByteFcn peekByte;
506 BufPeekSegFcn peekSeg;
507 BufPeekCopyFcn peekCopy;
508 BufPutByteRvsFcn putByteRvs;
509 BufPutSegRvsFcn putSegRvs;
510 BufReadErrorFcn readError;
511 BufWriteErrorFcn writeError;
513 void *spare; /* hack to save space for ExpBuf ** type */
516 #define GenBufGetByte( b) ((b)->getByte (b->bufInfo))
517 #define GenBufGetSeg( b, lenPtr) ((b)->getSeg (b->bufInfo, lenPtr))
518 #define GenBufCopy( dst, b, len) ((b)->copy (dst, b->bufInfo, len))
519 #define GenBufSkip( b, len) ((b)->skip (b->bufInfo,len))
520 #define GenBufPeekByte( b) ((b)->peekByte (b->bufInfo))
521 #define GenBufPeekSeg( b, lenPtr) ((b)->peekSeg (b->bufInfo, lenPtr))
522 #define GenBufPeekCopy( dst, b, len) ((b)->peekCopy (dst, b->bufInfo, len))
523 #define GenBufPutByteRvs( b, byte) ((b)->putByteRvs (b->bufInfo, byte))
524 #define GenBufPutSegRvs( b, data, len) ((b)->putSegRvs (b->bufInfo, data, len))
525 #define GenBufReadError( b) ((b)->readError (b->bufInfo))
526 #define GenBufWriteError( b) ((b)->writeError (b->bufInfo))
530 \section{Type Tables Vs. Metacode}
532 Please refer to section~\ref{meta-ttab-comparison} on page~\pageref{meta-ttab-comparison}.