Commit 11c9a8c7 authored by Lev Walkin's avatar Lev Walkin
Browse files

update asn1c-usage.pdf

parent 2655eb3f
???:
* Made -fskeletons-copy a default one; removed cmdline option.
* Updated asn1c-usage.pdf.
0.9.24: 2013-Mar-16
......
No preview for this file type
<
......@@ -3,58 +3,88 @@
\usepackage{xunicode}
\usepackage{xltxtra}
\usepackage[hmargin={1in,1in},vmargin={2in,2in}]{geometry}
\usepackage[hmargin={1in,1in},vmargin={1.5in,1.5in}]{geometry}
\defaultfontfeatures{Mapping=tex-text}
\setmainfont{Myriad Pro}
\setsansfont{Myriad Pro}
\setmainfont{PT Sans}
\setsansfont{PT Sans}
\setmonofont{Consolas}
\usepackage{fancyhdr}
\pagestyle{fancy}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{varioref}
\usepackage{url}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{setspace}
\makeatletter
\setstretch{1.1}
% Courier 10 Pitch
\def\courierFont{Courier10 BT WGL4}
%\def\courierFont{Consolas}
\setmonofont[Scale=1.05]{\courierFont}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
%% Because html converters don't know tabularnewline
\providecommand{\tabularnewline}{\\}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
\newenvironment{lyxcode}
{\par\begin{list}{}{
\setlength{\rightmargin}{\leftmargin}
\setlength{\listparindent}{0pt}% needed for AMS classes
\raggedright
\setlength{\itemsep}{0pt}
\setlength{\parsep}{0pt}
\normalfont\ttfamily}%
\item[]}
{\end{list}}
\lstloadlanguages{C,bash}
\newfontfamily\listingfont[Scale=1.05]{\courierFont}
\newfontfamily\inlinelistingfont[Scale=1.05]{\courierFont}
\definecolor{clrlcomment}{gray}{0.3}
\definecolor{clrlkeyword}{rgb}{0.588,0.145,0.18}
\newcommand{\listingkeyword}[1]{\color{clrlkeyword}{#1}}
\newcommand{\listingstring}[1]{\color{clrlcomment}{#1}}
\newcommand{\listingcomment}[1]{\color{clrlcomment}{#1}}
\lstset{tabsize=4,
showstringspaces=false,
showtabs=false,
showspaces=false,
keywordstyle=\listingkeyword,
stringstyle=\listingstring,
commentstyle=\listingcomment,
xleftmargin=\parindent,
columns=fixed,
escapechar=\%,
texcl
}
\lstdefinestyle{listingStyle}{
basicstyle=\small\listingfont,
stringstyle=\listingstring,
breaklines=true,
breakatwhitespace=true,
flexiblecolumns=false
}
\lstdefinelanguage{asn1}{
morekeywords={DEFINITIONS,BEGIN,END,SEQUENCE,SET,OF,CHOICE,OPTIONAL},
morecomment=[l]{--},
morecomment=[n]{/*}{*/}
}
\lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{}
\lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,morekeywords={-fnative-types},language=bash,#1}}{}
\lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{}
\def\code{lstinline}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
\usepackage{extramarks}
\lhead{\firstxmark}
\rfoot{\lastxmark}
\usepackage{color}
\definecolor{linkred}{rgb}{0.8235,0.0863,0.1843}
\definecolor{urlblue}{rgb}{0,0,.6}
\definecolor{clrlink}{rgb}{0,0.4,0}
\definecolor{clrurl}{rgb}{0,0,.6}
\usepackage[colorlinks=true,
linkcolor={linkred},
urlcolor={urlblue},
pdfauthor={Lev Walkin},
pdftitle={Using the Open Source ASN.1 Compiler},
pdfkeywords={ASN.1,asn1c,compiler},
xetex
linkcolor={clrlink},
citecolor={clrlink},
urlcolor={clrurl},
pdfauthor={Lev Walkin},
pdftitle={Using the Open Source ASN.1 Compiler},
pdfkeywords={ASN.1,asn1c,compiler},
bookmarksopen,bookmarksopenlevel=1,
pdffitwindow,
xetex
]{hyperref}
%\fancyhf{}
%\fancyhead[LE,RO]{\thepage}
%\fancyhead[LO]{\rightmark}
%\fancyhead[RE]{\leftmark}
%\fancyfoot[R]{\lastxmark}
\makeatother
......@@ -63,20 +93,15 @@ xetex
\begin{document}
\title{Using the Open Source ASN.1 Compiler}
\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>}
\pagestyle{fancy}
\fancyhead[L]{\leftmark}
\fancyhead[R]{\href{http://lionet.info/asn1c}{asn1c-0.9.25}}
\maketitle
\lhead{This document describes \href{http://lionet.info/asn1c}{asn1c-0.9.21}}
\rhead{$Revision$}
\tableofcontents{}
\pagestyle{headings}
\part{Using the ASN.1 Compiler}
......@@ -96,40 +121,24 @@ standardized encoding rules (BER, DER, XER, PER).
For example, suppose the following ASN.1 module is given%
\footnote{Part \vref{par:ASN.1-Basics} provides a quick reference
on the ASN.1 notation.}:
\begin{lyxcode}
RectangleTest~DEFINITIONS~::=
\begin{asn}
RectangleTest DEFINITIONS ::= BEGIN
BEGIN
~
Rectangle~::=~SEQUENCE~\{
~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
\}
~
Rectangle ::= SEQUENCE {
height INTEGER, -- Height of the rectangle
width INTEGER -- Width of the rectangle
}
END
\end{lyxcode}
\end{asn}
The compiler would read this ASN.1 definition and produce the following
C type%
\footnote{\emph{-fnative-types} compiler option is used to produce basic C \emph{int}
types instead of infinite width INTEGER\_t structures. See Section
\vref{sec:Command-line-options}.%
}:
\begin{lyxcode}
typedef~struct~Rectangle\_s~\{
~~~~int~height;
~~~~int~width;
\}~Rectangle\_t;
\end{lyxcode}
C type:
\begin{codesample}
typedef struct Rectangle_s {
long height;
long width;
} Rectangle_t;
\end{codesample}
It would also create the code for converting this structure into platform-independent
wire representation (a serializer API) and the decoder of such wire
representation back into local, machine-specific type (a deserializer
......@@ -138,29 +147,34 @@ API).
\section{Quick start with asn1c}
After building and installing the compiler, the \emph{asn1c}%
\footnote{The 1 symbol in asn\textbf{1}c is a digit, not an ``ell'' letter.%
} command may be used to compile the ASN.1 module%
After building and installing the compiler, the \emph{asn1c}
command may be used to compile the ASN.1 modules%
\footnote{This is probably \textbf{not} what you want to try out right now. Read through the rest of this chapter and check the Section \vref{sec:Command-line-options}
to find out about \textbf{-P} and \textbf{-R} options.%
}:
\begin{lyxcode}
asn1c~\emph{<module.asn1>}
\end{lyxcode}
\begin{bash}
asn1c %\emph{<modules.asn1>}%
\end{bash}
The asn1c takes a number of command line options,
such as an option to produce native long types
for integers instead of infinite width INTEGER\_t structures:
\begin{bash}
asn1c %\textbf{-fnative-types} \emph{<modules.asn1>}%
\end{bash}
If several ASN.1 modules contain interdependencies, all of the files
must be specified altogether:
\begin{lyxcode}
asn1c~\emph{<module1.asn1>~<module2.asn1>~...}
\end{lyxcode}
\begin{bash}
asn1c %\emph{<module1.asn1> <module2.asn1> ...}%
\end{bash}
The compiler \textbf{-E} and \textbf{-EF} options are used for testing
the parser and the semantic fixer, respectively. These options will
instruct the compiler to dump out the parsed (and fixed, if \textbf{-F}
is involved) ASN.1 specification as it was ``understood''
by the compiler. It might be useful to check whether a particular
syntactic construction is properly supported by the compiler.
\begin{lyxcode}
asn1c~\textbf{-EF}~\emph{<module-to-test.asn1>}
\end{lyxcode}
syntactic construct is properly supported by the compiler.
\begin{bash}
asn1c %\textbf{-EF} \emph{<module-to-test.asn1>}%
\end{bash}
The \textbf{-P} option is used to dump the compiled output on the
screen instead of creating a bunch of .c and .h files on disk in the
current directory. You would probably want to start with \textbf{-P}
......@@ -170,109 +184,102 @@ need to be generated, and supress linking in the numerous support
files.
Print the compiled output instead of creating multiple source files:
\begin{lyxcode}
asn1c~\textbf{-P}~\emph{<module-to-compile-and-print.asn1>}
\end{lyxcode}
\begin{bash}
asn1c %\textbf{-P} \emph{<module-to-compile-and-print.asn1>}%
\end{bash}
\section{Recognizing compiler output}
After compiling, the following entities will be created in your current
directory:
The asn1c compiler produces a number of files:
\begin{itemize}
\item A set of .c and .h files, generally a single pair for each type defined
in the ASN.1 specifications. These files will be named similarly to
\item A set of .c and .h files for each type defined
in the ASN.1 specification. These files will be named similarly to
the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the
RectangleTest ASN.1 module defined in the beginning of this document).
\item A set of helper .c and .h files which contain generic encoders, decoders
and other useful routines. There will be quite a few of them, some
of them even are not always necessary, but the overall amount of code
\item A set of helper .c and .h files which contain the generic encoders,
decoders and other useful routines. There will be quite a few of them, some
of them are not even always necessary, but the overall amount of code
after compilation will be rather small anyway.
\item A \emph{converter-sample.c} file containing the \emph{int main()} function with a fully functioning decoder. It can convert a given PDU between BER, XER and possibly PER (if -gen-PER option to asn1c was in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function.
\item A \emph{Makefile.am.sample} file mentioning all the files created
at the earlier steps. This file is suitable for either automake suite
or the plain `make` utility.
or the plain `make` utility. Just rename it into \emph{Makefile}.
\end{itemize}
It is your responsibility to create .c file with the \emph{int main()}
routine.
In other words, after compiling the Rectangle module, you have the
following set of files: \{~Makefile.am.sample, Rectangle.c, Rectangle.h,
\textbf{\ldots{}} \}, where ``\textbf{\ldots{}}'' stands for the
set of additional ``helper'' files created by the compiler. If you
add a simple file with the \emph{int main()} routine, it would even
be possible to compile everything with the single instruction:
\begin{lyxcode}
cc~-I.~-o~rectangle.exe~{*}.c~~~\#~It~could~be~\emph{that}~simple
\end{lyxcode}
It is possible to compile everything with just a couple of instructions:
\begin{bash}
asn1c -fnative-types -pdu=%\emph{Rectangle}% *.asn1
make -f Makefile.am.sample # If you use `make`
\end{bash}
or
\begin{bash}
asn1c -fnative-types *.asn1
cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this
\end{bash}
Refer to the Chapter \vref{cha:Step-by-step-examples} for a sample
\emph{int main()} routine.
\emph{int main()} function if you want some custom logic and not satisfied
with the supplied \emph{converter-sample.c}.
\clearpage{}
\section{\label{sec:Command-line-options}Command line options}
The following table summarizes the asn1c command line options.
\renewcommand{\arraystretch}{1.33}
\begin{longtable}{lp{4in}}
\toprule
\textbf{\small Overall Options} & \textbf{\small Description}\tabularnewline
\textbf{Overall Options} & \textbf{Description}\\
\midrule
{\small -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
specification code to the standard output.}\tabularnewline
{\small -F} & {\small Used together with -E, instructs the compiler to stop after
{-E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
specification code to the standard output.}\\
{-F} & {\small Used together with -E, instructs the compiler to stop after
the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1
specification to the standard output.}\tabularnewline
{\small -P} & {\small Dump the compiled output to the standard output instead of
creating the target language files on disk.}\tabularnewline
{\small -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\tabularnewline
{\small -S }\emph{\small <directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\tabularnewline
{\small -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\tabularnewline
\midrule\tabularnewline
\textbf{\small Warning Options} & \textbf{\small Description}\tabularnewline
specification to the standard output.}\\
{-P} & {\small Dump the compiled output to the standard output instead of
creating the target language files on disk.}\\
{-R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\
{-S}~\emph{<directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\\
{-X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\
\textbf{Warning Options} & \textbf{Description}\\
\midrule
{\small -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\tabularnewline
{\small -Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\tabularnewline
{\small -Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the
fixing stage.}\tabularnewline
{\small -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\tabularnewline
\midrule\tabularnewline
\textbf{\small Language Options} & \textbf{\small Description}\tabularnewline
{-Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\
{-Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\\
{-Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the
fixing stage.}\\
{-Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\
\textbf{Language Options} & \textbf{Description}\\
\midrule
{\small -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other
{-fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other
types for which this constraint is normally prohibited by the standard.
This is a violation of an ASN.1 standard and compiler may fail to
produce the meaningful code.}\tabularnewline
{\small -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents
produce the meaningful code.}\\
{-fcompound-names} & {\small Use complex names for C structures. Using complex names prevents
name clashes in case the module reuses the same identifiers in multiple
contexts.}\tabularnewline
{\small -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
contexts.}\\
{-findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
members as indirect pointers instead of declaring them inline. Consider
using this option together with }\textbf{\small -fno-include-deps}{\small{}
to prevent circular references. }\tabularnewline
{\small -fknown-extern-type=}\emph{\small <name>} & {\small Pretend the specified type is known. The compiler will assume
using this option together with \textbf{-fno-include-deps}
to prevent circular references. }\\
{-fknown-extern-type=}\emph{<name>} & {\small Pretend the specified type is known. The compiler will assume
the target language source files for the given type have been provided
manually. }\tabularnewline
{\small -fnative-types} & {\small Use the native machine's data types (int, double) whenever
manually. }\\
{-fnative-types} & {\small Use the native machine's data types (long, double) whenever
possible, instead of the compound INTEGER\_t, ENUMERATED\_t and REAL\_t
types. }\tabularnewline
{\small -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
may produce a shorter executable.}\tabularnewline
{\small -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical
dependencies.}\tabularnewline
{\small -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's
structures.}\tabularnewline
\midrule\tabularnewline
\textbf{\small Codecs Generation Options} & \textbf{\small Description}\tabularnewline
types. }\\
{-fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
may produce a shorter executable.}\\
{-fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical
dependencies.}\\
{-funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's
structures.}\\\\
\textbf{Codecs Generation Options} & \textbf{Description}\\
\midrule
{\small -gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\tabularnewline
{\small -pdu=}\emph{\small auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically.}\tabularnewline
\midrule\tabularnewline
\textbf{\small Output Options} & \textbf{\small Description}\tabularnewline
{-gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\\
{-pdu=}\emph{auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically. Also accepts a special keyword \emph{all} or a particular type to be used as a PDU.}\\ \\
\textbf{Output Options} & \textbf{Description}\\
\midrule
{\small -print-constraints} & {\small When -EF are also specified, this option forces the compiler
to explain its internal understanding of subtype constraints.}\tabularnewline
{\small -print-lines} & {\small Generate ``-{}- \#line'' comments
in -E output.}\tabularnewline
\bottomrule
{-print-constraints} & {\small When -EF are also specified, this option forces the compiler
to explain its internal understanding of subtype constraints.}\\
{-print-lines} & {\small Generate ``-{}- \#line'' comments
in -E output.}\\
\end{longtable}
\renewcommand{\arraystretch}{1}
......@@ -286,21 +293,19 @@ First of all, you should include one or more header files into your
application. Typically, it is enough to include the header file of
the main PDU type. For our Rectangle module, including the Rectangle.h
file is sufficient:
\begin{lyxcode}
\#include~<Rectangle.h>
\end{lyxcode}
\begin{codesample}
#include <Rectangle.h>
\end{codesample}
The header files defines the C structure corresponding to the ASN.1
definition of a rectangle and the declaration of the ASN.1 type descriptor,
which is used as an argument to most of the functions provided by
the ASN.1 module. For example, here is the code which frees the Rectangle\_t
structure:
\begin{lyxcode}
Rectangle\_t~{*}rect~=~...;
\begin{codesample}
Rectangle_t *rect = ...;
~
asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle, rect,~0);
\end{lyxcode}
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
\end{codesample}
This code defines a \emph{rect} pointer which points to the Rectangle\_t
structure which needs to be freed. The second line invokes the generic
\emph{free\_struct()} routine created specifically for this Rectangle\_t
......@@ -356,7 +361,7 @@ versions of BER, so the generic BER parser is also capable of decoding
the data encoded by CER and DER encoders. The opposite is not true.
\emph{The ASN.1 compiler provides the generic BER decoder which is
implicitly capable of decoding BER, CER and DER encoded data.}
capable of decoding BER, CER and DER encoded data.}
The decoder is restartable (stream-oriented), which means that in
case the buffer has less data than it is expected, the decoder will
......@@ -367,59 +372,42 @@ the next buffer contain the unprocessed part of the previous buffer.
Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
\begin{itemize}
\item You may concatenate these buffers and feed the BER decoder with 300
\item You can concatenate these buffers and feed the BER decoder with 300
bytes of data, or
\item You may feed it the first buffer of 100 bytes of data, realize that
\item You can feed it the first buffer of 100 bytes of data, realize that
the ber\_decoder consumed only 95 bytes from it and later feed the
decoder with 205 bytes buffer which consists of 5 unprocessed bytes
from the first buffer and the additional 200 bytes from the second
buffer.
\end{itemize}
This is not as convenient as it could be (like, the BER encoder could
This is not as convenient as it could be (the BER encoder could
consume the whole 100 bytes and keep these 5 bytes in some temporary
storage), but in case of existing stream based processing it might
actually fit well into existing algorithm. Suggestions are welcome.
Here is the simplest example of BER decoding.
\begin{lyxcode}
Rectangle\_t~{*}
simple\_deserializer(const~void~{*}buffer,~size\_t~buf\_size)~\{
~~~~Rectangle\_t~{*}rect~=~0;~~~~/{*}~Note~this~0!~{*}/
~~~~asn\_dec\_rval\_t~rval;
~
~~~~rval~=~\textbf{asn\_DEF\_Rectangle.ber\_decoder}(0,
~~~~~~~~~~\&asn\_DEF\_Rectangle,
~~~~~~~~~~(void~{*}{*})\&rect,
~~~~~~~~~~buffer,~buf\_size,
~~~~~~~~~~0);
~
~~~~if(rval\textbf{.code}~==~RC\_OK)~\{
~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/
~~~~\}~else~\{
~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/
~~~~~~~~asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle,~rect,~0);
~~~~~~~~return~0;
~~~~\}
\}
\end{lyxcode}
Here is the simplest example of BER decoding:
\begin{codesample}
Rectangle_t *
simple_deserializer(const void *buffer, size_t buf_size) {
Rectangle_t *rect = 0; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
asn_dec_rval_t rval;
rval = %\textbf{asn\_DEF\_Rectangle.ber\_decoder}%(0,
&asn_DEF_Rectangle,
(void **)&rect, /* Decoder %\emph{moves}% the pointer */
buffer, buf_size,
0);
if(rval%\textbf{.code}% == RC_OK) {
return rect; /* Decoding succeeded */
} else {
/* Free partially decoded rect */
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
return 0;
}
}
\end{codesample}
The code above defines a function, \emph{simple\_deserializer}, which
takes a buffer and its length and is expected to return a pointer
to the Rectangle\_t structure. Inside, it tries to convert the bytes
......@@ -436,11 +424,9 @@ be decoded into the structure by the time something goes wrong.
A little less wordy would be to invoke a globally available \emph{ber\_decode()}
function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
\begin{lyxcode}
rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect,
~~~~buffer,~buf\_size);
\end{lyxcode}
\begin{codesample}
rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
\end{codesample}
Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference
is gone, and also the last argument (0) is no longer necessary.
......@@ -479,55 +465,30 @@ to encode X.509 certificates.
As with BER decoder, the DER encoder may be invoked either directly
from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
function, which is somewhat simpler:
\begin{lyxcode}
~
/{*}
~{*}~This~is~the~serializer~itself,
~{*}~it~supplies~the~DER~encoder~with~the
~{*}~pointer~to~the~custom~output~function.
~{*}/
ssize\_t
simple\_serializer(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{
~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/
~
~~~~er~=~der\_encode(\&asn\_DEF\_Rect,~rect,
~~~~~~~~write\_stream,~ostream);
~~~~if(er.\textbf{encoded}~==~-1)~\{
~~~~~~~~/{*}
~~~~~~~~~{*}~Failed~to~encode~the~rectangle~data.
~~~~~~~~~{*}/
~~~~~~~~fprintf(stderr,~''Cannot~encode~\%s:~\%s\textbackslash{}n'',
~~~~~~~~~~~~er.\textbf{failed\_type}->name, strerror(errno));
~~~~~~~~return~-1;
~~~~\}~else~\{
~~~~~~~~/{*}~Return~the~number~of~bytes~{*}/
~~~~~~~~return~er.encoded;
~~~~\}
\}
\end{lyxcode}
\begin{codesample}
/*
* This is the serializer itself.
* It supplies the DER encoder with the
* pointer to the custom output function.
*/
ssize_t
simple_serializer(FILE *ostream, Rectangle_t *rect) {
asn_enc_rval_t er; /* Encoder return value */
er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream);
if(er%\textbf{.encoded}% == -1) {
/*
* Failed to encode the rectangle data.
*/
fprintf(stderr, "Cannot encode %\%%s: %\%%s\n",
er%\textbf{.failed\_type}%->name, strerror(errno));