File: ttab.tex

package info (click to toggle)
snacc 1.3.1-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,792 kB
  • ctags: 3,605
  • sloc: ansic: 33,001; cpp: 5,163; yacc: 2,217; sh: 2,146; makefile: 839; lex: 517; sed: 4
file content (526 lines) | stat: -rw-r--r-- 17,338 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
% file: .../doc/ttab.tex

% $Header: /usr/app/odstb/CVS/snacc/doc/ttab.tex,v 1.1 1997/01/01 22:47:43 rj Exp $
% $Log: ttab.tex,v $
% Revision 1.1  1997/01/01 22:47:43  rj
% first check-in
%

\chapter{\label{ttab-chapter}Type Tables}

Type tables are a flexible and compact way of dealing with ASN.1.
The type table data structure is included in the appendix.  It was
defined in ASN.1 to provide a good storage format for the tables.

When snacc produces a type table it includes the useful types module
as well, if one was specified.  If you are really trying to limit the
size of your type tables, put the only useful types that you need in
your ASN.1 module and compile it without using the useful types
module.

A generic buffer type ( la ISODE and XDR) was defined to allow type
table driven routines to read from a wide variety of buffer formats.
Currently slightly modified versions of the {\C ExpBuf} and the
{\C SBuf} are provided.  It shouldn't be too hard for you to add
support for your own buffer formats.  The generic buffers,
{\C GenBuf}s are described in more detail in a following section.

The general procedure for using type tables is to:
\begin{enumerate}
  \item Use snacc to compile your ASN.1 modules into a type table.
  \item Use {\ufn mkchdr} (make C header, not make cheddar) with the
    type table to produce a friendly C type description of the types in
    the type table.
  \item Load the type table during runtime and use it to configure the table
    encode, decode and other routines.
\end{enumerate}

Step two, making the C header file is not necessary but will make
dealing with the value easier and more type safe.  Internally the
table driven encoders and decoders know nothing of these header file
and treat the types in a uniform, generic manner.  This requires the
encoders and decoders to make assumptions about the way C represents
strucutures and values.  Look in the {\ufn \dots/c-lib/src/tbl-enc.c} and
{\ufn \dots/c-lib/src/tbl-dec.c} files to see how this generic data
structure is manipulated.

On the down side, the compiler directives do not affect the data
structures generated by mkchdr and the generated C type definitions
will generally be different from those generated by the C backend.
This can be fixed, but time was lacking. Type tables also do not
support ANY DEFINED BY types.  Someone could fix this without too much
difficulty.  Only a C type table library is provided.  I didn't have
time to deal with the complexities of creating C++ objects in a
generic way.

Currently the type tables are lacking subtyping information.  It is
available in snacc's main parse tree but I didn't have time to add it
to the tables.  If you want to add it, take the subtype related data
structures (in ASN.1) from asn1module.asn1 (quite a few), remove all
the cruft pertaining to linking and error checking etc, and add it to
the type table type definitions.  Then change the
{\ufn \dots/compiler/core/gen-tbls.c} file to take the subtype information from
the parse tree and put it into the type table.  See the appendix or
{\ufn \dots/asn1specs/} for the ASN.1 definitions of the parse tree
and type tables.

The parse tree itself was defined in ASN.1 so it could be the table
format.  The extra complexity required for linking and error checking
made this very difficult.  Cycles in the data structure and the many
links between the data elements made encoding in BER difficult.
[Maybe ASN.1 needs a type refernce type (i.e. pointer)].


\section{How Type Table See Values}

As mentioned in the last section, table driven encoding, decoding,
printing etc. routines see your values in a generic way.  They do not
have abstract syntax specific header files like those created by
{\ufn mkchdr}.

The basic idea is that all of the standard primitive and list
(SEQUENCE OF and SET OF) types are used and some regular rules are
used for allocating and laying out structs for SEQUENCE, SET and
CHOICE types.

\begin{small}
\begin{verbatim}
/* values from table driver routines' point of view */
typedef void AVal;

/* SEQUENCE and SET type use AStructVal */
typedef AVal *AStructVal;  /* an array of AVal ptrs */
\end{verbatim}
\end{small}

For SETs and SEQUENCEs, the {\C AStructVal} type is used. Its is
basically an array of pointers, one for each component of the
SET/SEQUENCE\@.  Every component is referenced by pointer to simplify
allocations.  OPTIONAL or DEFAULT components may be NULL\@.  For
example, the type:

\begin{small}
\begin{verbatim}
Foo ::= SEQUENCE { a INTEGER, b BOOLEAN, c OCTET STRING }
\end{verbatim}
\end{small}

would be represented as an array of three pointers.  The first pointer
would point to an {\C AsnInt} value, the second would point to an
{\C AsnBool} value, and the third would point to an {\C AsnOcts}
value. {\ufn mkchdr} would give you the following C typedef for Foo:

\begin{small}
\begin{verbatim}
typedef struct Foo
{
    AsnInt *a;
    AsnBool *b;
    AsnOcts *c;
} Foo;
\end{verbatim}
\end{small}

\begin{small}
\begin{verbatim}
/* Internal representation for a CHOICE type */
typedef struct AChoiceVal
{
   enum { achoiceval_notused } choiceId;
   AVal *val;
} AChoiceVal;
\end{verbatim}
\end{small}


A CHOICE type is represented in a way similar to the C backend's
output.  That is, an enum to hold the id of the CHOICE component
that is present and a pointer to the component itself.  For example,
the type:

\begin{small}
\begin{verbatim}
Bar ::= CHOICE { a INTEGER, b BOOLEAN, c OCTET STRING }
\end{verbatim}
\end{small}

would internally be represented as AChoiceVal type.  However,
{\ufn mkchdr} would give you the following:

\begin{small}
\begin{verbatim}
typedef struct Bar
{
    enum
    {
        a_ID = 0,
        b_ID = 1,
        c_ID = 2
    } choiceId;
    union
    {
        AsnInt *a;
        AsnBool *b;
        AsnOcts *c;
    } a;
} Bar;
\end{verbatim}
\end{small}


\section{Type Table Utilities}

There are a bunch of useful routines in {\ufn \dots/c-lib/src/tbl*.c}.  Look
at the source code in {\ufn \dots/tbl-tools/*/} and
{\ufn \dots/tbl-example/} to see how to use some of them.

The {\C LoadTblFile} will decode a type table from a given file.
Notice that its definition of the {\C TBL} data structure has been
augmented to simplify encoding and decoding operations. (Look at the
patch in {\ufn \dots/c-lib/tbl.h.patch} that is applied through the makefile automatically.)
% The additional fields do not screw up the compiled encoder/decoder (in {\ufn \dots/c-lib/src/tbl.c}) provided they are recompiled.
The compiler uses unmodified {\ufn tbl.h} and {\ufn tbl.c} files.

I don't have time to document these routines.  Look through the table
tools, examples and library code.  Their usage should be fairly
obvious.


\section{Type Table Tools}

The {\ufn \dots/tbl-tools/} directory contains three tools, {\ufn mkchdr},
{\ufn pval} and {\ufn ptbl}.  These are described in the following
sections.

\subsection{Making C Header Files with mkchdr}

{\ufn mkchdr} produces a C header file from a type table.  This header
file shows the representation of the types that the table tools will
expect or return for the types in the given type table.

The main use is to provide you with an easy to use definition of the
ASN.1 types C representation.  You do not need to use {\ufn mkchdr}
but it is definately recommended.  Note that the table routines could
have used an even more generic data structure to represent values
(e.g. ISODE's Presentation Elements).  If you have worked with these,
you know that they are cumbersome.

Its synopsis is:
\begin{small}
\begin{verbatim}
mkchdr <tbl-file> [output-file]
\end{verbatim}
\end{small}

If the output file is omitted, the header file is printed to {\C stdout}.

Here is an example of the output.  Given the table that has the
following ASN.1 module in it:

\begin{small}
\begin{verbatim}
P-REC DEFINITIONS ::=
BEGIN
PersonnelRecord ::=  [APPLICATION 0] IMPLICIT SET
{
                     Name,
    title        [0] IA5String,
                     EmployeeNumber,
    dateOfHire   [1] Date,
    nameOfSpouse [2] Name,
    children     [3] IMPLICIT SEQUENCE OF ChildInformation DEFAULT {}
}

ChildInformation ::= SET
{
                    Name,
    dateOfBirth [0] Date
}

Name ::= [APPLICATION 1] IMPLICIT SEQUENCE
{
    givenName  IA5String,
    initial    IA5String,
    familyName IA5String
}

EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER

Date ::= [APPLICATION 3] IMPLICIT IA5String -- YYYYMMDD

END
\end{verbatim}
\end{small}

{\ufn mkchdr} will produce:
\begin{small}
\begin{verbatim}
typedef AsnInt EmployeeNumber;

typedef struct Name
{
    IA5String *givenName;
    IA5String *initial;
    IA5String *familyName;
} Name;

typedef IA5String Date;

typedef struct ChildInformation
{
    Name *field0;
    Date *dateOfBirth;
} ChildInformation;

typedef AsnList PersonnelRecordSeqOf;

typedef struct PersonnelRecord
{
    Name *field0;
    IA5String *title;
    EmployeeNumber *field1;
    Date *dateOfHire;
    Name *nameOfSpouse;
    PersonnelRecordSeqOf *children;
} PersonnelRecord;

\end{verbatim}
\end{small}


\subsection{Printing Tables with ptbl}

{\ufn ptbl} is a program that will show you the contents of a type
table.  It can print a table in two modes:
\begin{itemize}
  \item The value notation for the TBL ASN.1 data structure (see the appendix).
  \item The ASN.1 text version
\end{itemize}

Its synopsis is:

\begin{small}
\begin{verbatim}
ptbl [-a] <tbl-file>
\end{verbatim}
\end{small}

For example, using {\ufn ptbl -a p-rec.tt} to print the
PersonnelRecord module used in the last section would yield:

\begin{small}
\begin{verbatim}
P-REC  DEFINITIONS ::=
BEGIN
EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
Name ::= [APPLICATION 1] IMPLICIT SEQUENCE
{
    givenName IA5String,
    initial IA5String,
    familyName IA5String
}
Date ::= [APPLICATION 3] IMPLICIT IA5String
ChildInformation ::= SET
{
    Name,
    dateOfBirth [0] Date
}
PersonnelRecordSeqOf ::= SEQUENCE OF ChildInformation
PersonnelRecord ::= [APPLICATION 0] IMPLICIT SET
{
    Name,
    title [0] IA5String,
    EmployeeNumber,
    dateOfHire [1] Date,
    nameOfSpouse [2] Name,
    children [3] IMPLICIT PersonnelRecordSeqOf
}
END
--  Definitions for  ASN-USEFUL
ASN-USEFUL  DEFINITIONS ::=
BEGIN
ObjectDescriptor ::= [UNIVERSAL 7] IMPLICIT OCTET STRING
NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
T61String ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
VideotexString ::= [UNIVERSAL 21] IMPLICIT OCTET STRING
IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
GraphicString ::= [UNIVERSAL 25] IMPLICIT OCTET STRING
VisibleString ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
ISO646String ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
GeneralString ::= [UNIVERSAL 27] IMPLICIT OCTET STRING
UTCTime ::= [UNIVERSAL 23] IMPLICIT OCTET STRING
GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT OCTET STRING
EXTERNAL ::= [UNIVERSAL 8] IMPLICIT SEQUENCE
{
    direct-reference OBJECT IDENTIFIER,
    indirect-reference INTEGER,
    data-value-descriptor ObjectDescriptor,
    encoding CHOICE
    {
        single-ASN1-type [0] OCTET STRING,
        octet-aligned [1] IMPLICIT OCTET STRING,
        arbitrary [2] IMPLICIT BIT STRING
    }
}
END
\end{verbatim}
\end{small}

Note that the useful type module is included in the table.  As
mentioned before, to minimize the size of your tables, put the
definitions of the useful types (from {\ufn \dots/asn1specs/asn-useful.asn1})
into your ASN.1 module and do not compile with useful types module
(i.e. don't use the -u option).  If your module doesn't use any
useful types, just don't use the -u option.

The other mode of {\ufn ptbl}, value notation for the TBL data
structure, produces a lot of output.  It may be useful if you are
debugging one of the table drivers.


\subsection{Printing Values with pval}

The {\ufn pval} program will convert BER values into their value
notation.  Its arguments are a type table file, a module and type name
and a list of BER files of that type.

Its synopsis is:

\begin{small}
\begin{verbatim}
pval -T <tt file name> [-m <module name>] -n <type name> <ber value file list>
\end{verbatim}
\end{small}

Running {\ufn pval} on a PersonnelRecord value produced the following:

\begin{small}
\begin{verbatim}
-- Contents of file "demo-tbls/p-rec.ber"--
-- module = ???, type = PersonnelRecord --

value P-REC.PersonnelRecord ::=
{
  {
    givenName '4a6f686e'H  -- "John" --,
    initial '45'H  -- "E" --,
    familyName '536d697468'H  -- "Smith" --
  },
  title '5468652042696720436865657365'H  -- "The Big Cheese" --,
  99999,
  dateOfHire '3139383230313034'H  -- "19820104" --,
  nameOfSpouse {
    givenName '4d617279'H  -- "Mary" --,
    initial '4c'H  -- "L" --,
    familyName '536d697468'H  -- "Smith" --
  },
  children {
    {
      {
        givenName '4a616d6573'H  -- "James" --,
        initial '52'H  -- "R" --,
        familyName '536d697468'H  -- "Smith" --
      },
      dateOfBirth '3139353730333130'H  -- "19570310" --
    },
    {
      {
        givenName '4c697361'H  -- "Lisa" --,
        initial '4d'H  -- "M" --,
        familyName '536d697468'H  -- "Smith" --
      },
      dateOfBirth '3139363130363231'H  -- "19610621" --
    }
  }
}

 -- decoded 143 bytes for the above value --
\end{verbatim}
\end{small}


\section{Using Tables in Your Own Applications}

The best way to get a handle on using tables is to look at the example
in {\ufn \dots/tbl-example/}.  The general idea is to compile your
ASN.1 into a type table (use the snacc {\ufn -T} option).  If you desire a
livable definition of the C data structures for the types in the type
table, run {\ufn mkchdr} and compile the generated header file with
your C code.  During runtime, simply load your table file with
{\C LoadTblFile} (I use the {\ufn .tt} suffix naming convention for type table
files but it doesn't matter) and then use the {\C TblEncode},
{\C TblDecode}, {\C TblPrint} and {\C TblFree} routines with
your table.  Quite simple.  Seriously.

\section{Using GenBufs}

The {\C GenBuf} generic buffers are really a way of encapsulating
other buffer formats.  A {\C GenBuf} contains a table of pointers to
the buffer functions (the standardized ones (see the buffer section)
plus ``Peek'' routines that the table drivers needed).  They are
defined in {\ufn \dots/c-lib/inc/gen-buf.h}.

{\C GenBuf}s require functions for the standard buffer routines,
macros will not do since you cannot have a pointer to macro.

The benefit of the {\C GenBuf}s is that since they can support other
buffer types, only one set of library routines is needed.  (Note that
there are 3 libraries in {\ufn \dots/c-lib/} for the backend model and only one for the type table model.

Here is most of {\ufn gen-buf.h} to give you an idea of how things work:

\begin{small}
\begin{verbatim}
typedef unsigned char (*BufGetByteFcn) PROTO ((void *b));
typedef unsigned char *(*BufGetSegFcn) PROTO ((void *b,
                                               unsigned long int *lenPtr));
typedef long int (*BufCopyFcn) PROTO ((char *dst, void *b,
                                   unsigned long int len));
typedef void (*BufSkipFcn) PROTO ((void *b, unsigned long int len));
typedef unsigned char (*BufPeekByteFcn) PROTO ((void *b));
typedef unsigned char *(*BufPeekSegFcn) PROTO ((void *b,
                                               unsigned long int lenPtr));
typedef long int (*BufPeekCopyFcn) PROTO ((char *dst, void *b,
                                   unsigned long int len));
typedef void (*BufPutByteRvsFcn) PROTO ((void *b, unsigned char byte));
typedef void (*BufPutSegRvsFcn) PROTO ((void *b, char *data,
                                    unsigned long int len));
typedef int (*BufReadErrorFcn) PROTO ((void *b));
typedef int (*BufWriteErrorFcn) PROTO ((void *b));

typedef struct GenBuf
{
    BufGetByteFcn    getByte;
    BufGetSegFcn     getSeg;
    BufCopyFcn       copy;
    BufSkipFcn       skip;
    BufPeekByteFcn   peekByte;
    BufPeekSegFcn    peekSeg;
    BufPeekCopyFcn   peekCopy;
    BufPutByteRvsFcn putByteRvs;
    BufPutSegRvsFcn  putSegRvs;
    BufReadErrorFcn  readError;
    BufWriteErrorFcn writeError;
    void             *bufInfo;
    void             *spare; /* hack to save space for ExpBuf ** type */
} GenBuf;

#define GenBufGetByte( b)              ((b)->getByte (b->bufInfo))
#define GenBufGetSeg( b, lenPtr)       ((b)->getSeg (b->bufInfo, lenPtr))
#define GenBufCopy( dst, b, len)       ((b)->copy (dst, b->bufInfo, len))
#define GenBufSkip( b, len)            ((b)->skip (b->bufInfo,len))
#define GenBufPeekByte( b)             ((b)->peekByte (b->bufInfo))
#define GenBufPeekSeg( b, lenPtr)      ((b)->peekSeg (b->bufInfo, lenPtr))
#define GenBufPeekCopy( dst, b, len)   ((b)->peekCopy (dst, b->bufInfo, len))
#define GenBufPutByteRvs( b, byte)     ((b)->putByteRvs (b->bufInfo, byte))
#define GenBufPutSegRvs( b, data, len) ((b)->putSegRvs (b->bufInfo, data, len))
#define GenBufReadError( b)            ((b)->readError (b->bufInfo))
#define GenBufWriteError( b)           ((b)->writeError (b->bufInfo))
\end{verbatim}
\end{small}

\section{Type Tables Vs. Metacode}

Please refer to section~\ref{meta-ttab-comparison} on page~\pageref{meta-ttab-comparison}.