\chapter{The Module Data Structure ASN.1 Definition}
The ASN.1 modules are parsed into an internal data structure. The
data structure was initially defined in ASN.1 with the idea that if
we needed to write a parsed module to disk, the ASN.1 encoding
routines could be used. No file format was needed so the ASN.1 was
merely an exercise.
This procedure highlighted the problem with circular links and index
like links in ASN.1 data structures. BER does not support this type
of linking; to handle it, the offending links can be made optional
and not encoded. After decoding, these links need to be
re-established. See the type table data structure for a format
suitable for writing to files.
The following is the ASN.1 definition of the Module data structure.
The C translation (as generated by an early version of Snacc) can be
found in {\ufn \dots/compiler/core/asn1module.h}\footnote{
The {\ufn asn1module.h} that is produced by a current version of Snacc cannot be compiled because its type definitions are in the wrong order.
This may be caused by the {\ASN --\,--snacc cTypeName} compiler directives, since one of the affected types is BasicTypeChoiceId, but i'm not really sure.
---rj
}.
\begin{small}
\begin{verbatim}
-- .../asn1specs/asn1module.asn1
--
-- This module describes the data structure used to represent the
-- compiled ASN.1.
-- Using ASN.1 for the internal data structure allows writing
-- (encoding) to disk for storage (not done yet due to recursive
-- refs back to the module)
--
-- Mike Sample 91/08/29
-- Modifed 92/05 MS
--
Asn1Module DEFINITIONS IMPLICIT TAGS ::=
BEGIN
-- exports everything
-- imports nothing
Modules ::= [APPLICATION 0] IMPLICIT SEQUENCE
{
creationTime INTEGER,
modules ModuleList
}
ModuleList ::= SEQUENCE OF Module
Module ::= SEQUENCE
{
status ENUMERATED { mod-ok(0), mod-not-linked(1), mod-error(2) },
modId ModuleId,
tagDefault ENUMERATED { explicit-tags(0), implicit-tags(1) },
exportStatus ENUMERATED { exports-all(0), exports-nothing(1),
exports-some(2) },
imports ImportModuleList,
typeDefs TypeDefList,
valueDefs ValueDefList,
hasAnys BOOLEAN,
asn1SrcFileName MyString,
cHdrFileName MyString,
cSrcFileName MyString,
cxxHdrFileName MyString,
cxxSrcFileName MyString
cxxname MyString, -- META
idlFileName MyString, -- IDL
idlname MyString -- IDL
}
ModuleId ::= SEQUENCE
{
name MyString,
oid OBJECT IDENTIFIER OPTIONAL --snacc cTypeName:"OID" isPtr:"TRUE"
}
ImportModuleList ::= SEQUENCE OF ImportModule
ImportModule ::= SEQUENCE
{
modId ModuleId,
importElmts ImportElmtList,
moduleRef Module, --snacc isEncDec:"FALSE"
lineNo INTEGER
}
ImportElmtList ::= SEQUENCE OF ImportElmt
ImportElmt ::= SEQUENCE
{
resolvedRef CHOICE
{
type [0] TypeDef, -- not encoded
value [1] ValueDef -- not encoded
} OPTIONAL,
name MyString,
privateScope BOOLEAN, -- true if from MODNAME.TYPE ref
lineNo INTEGER
}
TypeDefList ::= SEQUENCE OF TypeDef
OidOrInt ::= CHOICE
{
oid OBJECT IDENTIFIER,
intId INTEGER
}
AnyRef ::= SEQUENCE
{
anyIdName MyString,
id OidOrInt
}
AnyRefList ::= SEQUENCE OF AnyRef
TypeDef ::= SEQUENCE
{
exported BOOLEAN,
recursive BOOLEAN,
isPdu BOOLEAN,
localRefCount INTEGER,
importRefCount INTEGER,
tmpRefCount INTEGER,
visited BOOLEAN,
definedName MyString,
type Type,
cTypeDefInfo CTDI,
cxxTypeDefInfo CxxTDI,
attrList AttributeList,
refList TypeDefList,
anyRefs AnyRefList
}
Tag ::= SEQUENCE
{
tclass INTEGER, -- swap this for the BER_CLASS enum from basetypes.h
form INTEGER, -- swap this for the BER_FORM enum
code INTEGER,
explicit BOOLEAN,
valueRef Value
}
Type ::= SEQUENCE
{
optional BOOLEAN,
implicit BOOLEAN,
tags TagList,
defaultVal [0] IMPLICIT NamedValue OPTIONAL,
subtypes [1] Subtype OPTIONAL,
basicType [2] BasicType,
lineNo INTEGER,
cTypeRefInfo CTRI,
cxxTypeRefInfo CxxTRI,
attrList AttributeList
}
TagList ::= SEQUENCE OF Tag
AttributeList ::= SEQUENCE OF MyString
NamedNumberList ::= ValueDefList
-- BasicTypes with NULL need no more info that which type it is
-- (this is known from the choice id)
BasicType ::= CHOICE
{
unknown [0] IMPLICIT NULL,
boolean [1] IMPLICIT NULL,
integer [2] IMPLICIT NamedNumberList,
bitString [3] IMPLICIT NamedNumberList,
octetString [4] IMPLICIT NULL,
null [5] IMPLICIT NULL,
oid [6] IMPLICIT NULL,
real [7] IMPLICIT NULL,
enumerated [8] IMPLICIT NamedNumberList,
sequence [9] IMPLICIT NamedTypeList,
sequenceOf [10] IMPLICIT Type,
set [11] IMPLICIT NamedTypeList,
setOf [12] IMPLICIT Type,
choice [13] IMPLICIT NamedTypeList,
selection [14] IMPLICIT SelectionType,
componentsOf [15] IMPLICIT Type, -- [Resolved](local/import) type ref
any [16] IMPLICIT NULL,
anyDefinedBy [17] IMPLICIT AnyDefinedByType,
localTypeRef [19] IMPLICIT TypeRef,
importTypeRef [20] IMPLICIT TypeRef,
macroType [21] MacroType,
macroDef [22] IMPLICIT MacroDef --snacc isPtr:"FALSE"
}
MacroDef ::= MyString -- just keep the text for now
MacroType ::= CHOICE
{
rosOperation [0] IMPLICIT RosOperationMacroType,
rosError [1] IMPLICIT RosErrorMacroType,
rosBind [2] IMPLICIT RosBindMacroType,
rosUnbind [3] IMPLICIT RosBindMacroType,
rosAse [4] IMPLICIT RosAseMacroType,
rosAc [5] IMPLICIT RosAcMacroType,
mtsasExtension [6] IMPLICIT MtsasExtensionMacroType,
mtsasExtensions [7] IMPLICIT MtsasExtensionsMacroType,
mtsasExtensionAttribute [8] IMPLICIT MtsasExtensionAttributeMacroType,
mtsasToken [9] IMPLICIT MtsasTokenMacroType,
mtsasTokenData [10] IMPLICIT MtsasTokenDataMacroType,
mtsasSecurityCategory [11] IMPLICIT MtsasSecurityCategoryMacroType,
asnObject [12] IMPLICIT AsnObjectMacroType,
asnPort [13] IMPLICIT AsnPortMacroType,
asnRefine [14] IMPLICIT AsnRefineMacroType,
asnAbstractBind [15] IMPLICIT AsnAbstractBindMacroType,
asnAbstractUnbind [16] IMPLICIT AsnAbstractBindMacroType,
asnAbstractOperation [17] IMPLICIT RosOperationMacroType,
asnAbstractError [18] IMPLICIT RosErrorMacroType,
afAlgorithm [19] IMPLICIT Type,
afEncrypted [20] IMPLICIT Type,
afProtected [21] IMPLICIT Type,
afSignature [22] IMPLICIT Type,
afSigned [23] IMPLICIT Type,
snmpObjectType [24] IMPLICIT SnmpObjectTypeMacroType
}
AnyDefinedByType ::= SEQUENCE
{
fieldName MyString, -- name of field that its defined by
link NamedType OPTIONAL -- REFERENCE not encoded
}
SelectionType ::= SEQUENCE
{
fieldName MyString, -- name of field in choice
typeRef Type, -- [Resolved](local/import) type ref
link NamedType OPTIONAL -- REFERENCE not encoded
}
NamedTypeList ::= SEQUENCE OF NamedType
NamedType ::= SEQUENCE
{
fieldName MyString, -- may be empty or NULL str
type Type
}
TypeRef ::= SEQUENCE
{
typeName MyString,
moduleName MyString, -- used for "modname.type" refs (may be null)
module Module, --snacc isEncDec:"FALSE"
link TypeDef --snacc isEncDec:"FALSE"
}
RosOperationMacroType ::= SEQUENCE
{
arguments NamedType,
result NamedType,
errors [0] IMPLICIT TypeOrValueList OPTIONAL,
linkedOps [1] IMPLICIT TypeOrValueList OPTIONAL
}
ValueList ::= SEQUENCE OF Value
TypeOrValueList ::= SEQUENCE OF TypeOrValue
TypeOrValue ::= CHOICE
{
type [0] IMPLICIT Type,
value [1] IMPLICIT Value
}
OidList ::= SEQUENCE OF OBJECT IDENTIFIER
RosErrorMacroType ::= SEQUENCE
{
parameter NamedType
}
RosBindMacroType ::= SEQUENCE
{
argument NamedType,
result NamedType,
error NamedType
}
RosAseMacroType ::= SEQUENCE
{
operations ValueList,
consumerInvokes ValueList,
supplierInvokes ValueList
}
RosAcMacroType ::= SEQUENCE
{
nonRoElements ValueList,
bindMacroType Type,
unbindMacroType Type,
remoteOperations Value,
operationsOf ValueList,
initiatorConsumerOf ValueList,
responderConsumerOf ValueList,
abstractSyntaxes OidList
}
MtsasExtensionMacroType ::= SEQUENCE
{
elmtType [0] IMPLICIT NamedType OPTIONAL,
defaultValue [1] IMPLICIT Value OPTIONAL,
criticalForSubmission [2] IMPLICIT BOOLEAN OPTIONAL,
criticalForTransfer [3] IMPLICIT BOOLEAN OPTIONAL,
criticalForDelivery [4] IMPLICIT BOOLEAN OPTIONAL
}
MtsasExtensionsMacroType ::= SEQUENCE
{
extensions ValueList
}
MtsasExtensionAttributeMacroType ::= SEQUENCE
{
type Type OPTIONAL
}
MtsasTokenMacroType ::= SEQUENCE
{
type Type OPTIONAL
}
MtsasTokenDataMacroType ::= SEQUENCE
{
type Type OPTIONAL
}
MtsasSecurityCategoryMacroType ::= SEQUENCE
{
type Type OPTIONAL
}
AsnObjectMacroType ::= SEQUENCE
{
ports AsnPortList OPTIONAL
}
AsnPortList ::= SEQUENCE OF AsnPort
AsnPort ::= SEQUENCE
{
portValue Value,
portType ENUMERATED
{
consumer-port (0),
supplier-port (1),
symmetric-port (2)
}
}
AsnPortMacroType ::= SEQUENCE
{
abstractOps [0] IMPLICIT TypeOrValueList OPTIONAL,
consumerInvokes [1] IMPLICIT TypeOrValueList OPTIONAL,
supplierInvokes [2] IMPLICIT TypeOrValueList OPTIONAL
}
AsnRefineMacroType ::= INTEGER
AsnAbstractBindMacroType ::= SEQUENCE
{
ports [0] IMPLICIT AsnPortList OPTIONAL,
type [1] IMPLICIT Type OPTIONAL
}
SnmpObjectTypeMacroType ::= SEQUENCE
{
syntax Type,
access ENUMERATED
{ snmp-read-only (0), snmp-read-write (1),
snmp-write-only (2), snmp-not-accessible (3)},
status ENUMERATED
{ snmp-mandatory (0), snmp-optional (1),
snmp-obsolete (2), snmp-deprecated (3)},
description [0] IMPLICIT Value OPTIONAL,
reference [1] IMPLICIT Value OPTIONAL,
index [2] IMPLICIT TypeOrValueList OPTIONAL,
defVal [3] IMPLICIT Value OPTIONAL
}
Subtype ::= CHOICE
{
single [0] SubtypeValue,
and [1] IMPLICIT SubtypeList,
or [2] IMPLICIT SubtypeList,
not [3] Subtype
}
SubtypeList ::= SEQUENCE OF Subtype
SubtypeValue ::= CHOICE
{
singleValue [0] IMPLICIT Value,
contained [1] IMPLICIT Type,
valueRange [2] IMPLICIT ValueRangeSubtype,
permittedAlphabet [3] Subtype, -- only valuerange or singleval
sizeConstraint [4] Subtype, -- only single value ints or val range
innerSubtype [5] IMPLICIT InnerSubtype
}
ValueRangeSubtype ::= SEQUENCE
{
lowerEndInclusive BOOLEAN,
upperEndInclusive BOOLEAN,
lowerEndValue Value,
upperEndValue Value
}
InnerSubtype ::= SEQUENCE
{
constraintType ENUMERATED { full-ct (0), partial-ct (1), single-ct (2) },
constraints ConstraintList
}
ConstraintList ::= SEQUENCE OF Constraint
Constraint ::= SEQUENCE
{
fieldRef MyString, -- not used if in single-ct, may be null
presenceConstraint ENUMERATED
{
present-ct (0),
absent-ct (1),
empty-ct (2),
optional-ct (3)
},
valueConstraints Subtype
}
ValueDefList ::= SEQUENCE OF ValueDef
ValueDef ::= SEQUENCE
{
exported BOOLEAN,
definedName MyString,
value Value
}
Value ::= SEQUENCE
{
type Type OPTIONAL,
valueType INTEGER, -- holds one of choiceId's def'd for BasicType
basicValue BasicValue,
lineNo INTEGER
}
BasicValue ::= CHOICE
{
unknown [0] IMPLICIT NULL,
empty [1] IMPLICIT NULL,
integer [2] IMPLICIT INTEGER,
specialInteger [3] IMPLICIT SpecialIntegerValue,
longInteger [4] IMPLICIT INTEGER, -- put LONG before INTGEGER
boolean [5] IMPLICIT BOOLEAN,
real [6] IMPLICIT REAL,
specialReal [7] IMPLICIT SpecialRealValue,
asciiText [8] IMPLICIT OCTET STRING,
asciiHex [9] IMPLICIT OCTET STRING,
asciiBitString [10] IMPLICIT OCTET STRING,
oid [11] IMPLICIT OBJECT IDENTIFIER,
linkedOid [12] IMPLICIT OBJECT IDENTIFIER, --snacc cTypeName:"OID"
berValue [13] IMPLICIT OCTET STRING,
perValue [14] IMPLICIT OCTET STRING,
namedValue [15] IMPLICIT NamedValue,
null [16] IMPLICIT NULL,
localValueRef [17] IMPLICIT ValueRef,
importValueRef [18] IMPLICIT ValueRef,
valueNotation [19] IMPLICIT OCTET STRING
}
SpecialIntegerValue ::= ENUMERATED { min-int (0), max-int (1) }
SpecialRealValue ::= ENUMERATED { minus-infinity-real (0), plus-infinity-real (1) }
ValueRef ::= SEQUENCE
{
valueName MyString,
moduleName MyString, -- used for "modname.value" refs (may be null)
link ValueDef, --snacc isEncDec:"FALSE"
module Module --snacc isEncDec:"FALSE"
}
NamedValue ::= SEQUENCE
{
fieldName MyString, -- may be null
value Value
}
NamedValueList ::= SEQUENCE OF NamedValue
CTypeId ::= ENUMERATED { c-choice (0), c-list (1), c-any (2), c-anydefinedby (3),
c-lib (4), c-struct (5), c-typeref (6), c-no-type (7),
c-typedef (8) }
-- C Type Def Info - info used for routine naming
-- and referencing from other types
CTDI ::= SEQUENCE
{
asn1TypeId INTEGER, --snacc cTypeName:"enum BasicTypeChoiceId"
cTypeId CTypeId,
cTypeName MyString,
isPdu BOOLEAN,
isEncDec BOOLEAN, -- if false, no routines are gen
-- and not included in encodings
isPtrForTypeDef BOOLEAN,
isPtrForTypeRef BOOLEAN,
isPtrInChoice BOOLEAN,
isPtrForOpt BOOLEAN,
-- defines these names, used by references
optTestRoutineName MyString, -- routine/macro to check whether
-- opt type is present
defaultFieldName MyString, -- base for generating field names
printRoutineName MyString,
encodeRoutineName MyString,
decodeRoutineName MyString,
freeRoutineName MyString,
genPrintRoutine BOOLEAN,
genEncodeRoutine BOOLEAN,
genDecodeRoutine BOOLEAN,
genFreeRoutine BOOLEAN,
genTypeDef BOOLEAN
}
--
-- CTRI (C Type Ref Info) is used for generating C typedefinitions
-- from the ASN.1 types info
CTRI ::= SEQUENCE
{
cTypeId CTypeId,
cFieldName MyString,
cTypeName MyString,
isPtr BOOLEAN,
-- isEndCType BOOLEAN, -- false for struct/union def
cNamedElmts CNamedElmts OPTIONAL, -- for C_LIB bits/int/enums
choiceIdValue INTEGER, -- enum value of this c field
choiceIdSymbol MyString, -- this fields sym in choiceId enum
choiceIdEnumName MyString,
choiceIdEnumFieldName MyString,
optTestRoutineName MyString, -- these names are gained from refd type def
printRoutineName MyString, -- or are over-ridden snacc attribute comment
encodeRoutineName MyString,
decodeRoutineName MyString,
freeRoutineName MyString,
isEncDec BOOLEAN -- whether part of enc value
}
CNamedElmts ::= SEQUENCE OF CNamedElmt
CNamedElmt ::= SEQUENCE
{
name MyString,
value INTEGER
}
CxxTDI ::= SEQUENCE
{
asn1TypeId INTEGER, --snacc cTypeName:"enum BasicTypeChoiceId"
className MyString,
isPdu BOOLEAN,
isEnc BOOLEAN,
isPtrForTypeDef BOOLEAN,
isPtrForOpt BOOLEAN,
isPtrInChoice BOOLEAN,
isPtrInSetAndSeq BOOLEAN,
isPtrInList BOOLEAN,
optTestRoutineName MyString,
defaultFieldName MyString -- base for generating field names
}
CxxTRI ::= SEQUENCE
{
isEnc BOOLEAN,
className MyString,
fieldName MyString,
isPtr BOOLEAN,
namedElmts CNamedElmts,
choiceIdSymbol MyString,
choiceIdValue INTEGER,
optTestRoutineName MyString
}
IDLTDI ::= SEQUENCE
{
asn1TypeId INTEGER, --snacc cTypeName:"enum BasicTypeChoiceId"
typeName MyString,
isPdu BOOLEAN,
isEnc BOOLEAN,
isPtrForTypeDef BOOLEAN,
isPtrForOpt BOOLEAN,
isPtrInChoice BOOLEAN,
isPtrInSetAndSeq BOOLEAN,
isPtrInList BOOLEAN,
optTestRoutineName MyString,
defaultFieldName MyString -- base for generating field names
}
IDLTRI ::= SEQUENCE
{
isEnc BOOLEAN,
typeName MyString,
fieldName MyString,
isPtr BOOLEAN,
namedElmts CNamedElmts,
choiceIdSymbol MyString,
choiceIdValue INTEGER,
optTestRoutineName MyString
}
-- use snacc compiler directives to overide the builtin types.
--
-- All strings used in module data struct are null terminated so
-- can just use a char *
-- Note the snacc comments before the PrintableString
-- bind with the MyString TypeDef and the ones after PrintableString
-- bind with the PrintableString Type ref.
MyString ::= --snacc isPtrForTypeDef:"FALSE"
--snacc isPtrForTypeRef:"FALSE"
--snacc isPtrInChoice:"FALSE"
--snacc isPtrForOpt:"FALSE"
--snacc optTestRoutineName:"MYSTRING_NON_NULL"
--snacc genPrintRoutine:"FALSE"
--snacc genEncodeRoutine:"FALSE"
--snacc genDecodeRoutine:"FALSE"
--snacc genFreeRoutine:"FALSE"
--snacc printRoutineName:"printMyString"
--snacc encodeRoutineName:"EncMyString"
--snacc decodeRoutineName:"DecMyString"
--snacc freeRoutineName:"FreeMyString"
PrintableString --snacc cTypeName:"char *"
END
\end{verbatim}
\end{small}
\chapter{The Type Table (TBL) Data Structure ASN.1 Definition}
The following is the type table data structure that Snacc uses for
type table values. Using ASN.1 gives a representation suitable for
saving tables to files or sending them over a network to reconfigure a
device (e.g. SNMP mib).
This file is actually compiled by Snacc to compile itself.
For bootstrapping purposes, an initial version is included in the distribution.
\begin{small}
\begin{verbatim}
-- .../asn1specs/tbl.asn1
--
-- TBL types describe ASN.1 data structures.
-- These can be used in generic, interpretive encoders/decoders.
-- Interpretive decoders are typically slower, but don't eat memory
-- with type-specific encoding and decoding code.
-- The tbl types can also be sent over the network
-- and allow dynamic re-configuration of encoders/decoders.
--
-- This definition is fairly small so it should be reasonable easy
-- to understand. To learn more about semantics of this data
-- struct, look in snacc/tbl-tools/print-tbl/pasn1.c.
--
-- Copyright Mike Sample and UBC, 1992, 1993
--
TBL DEFINITIONS ::=
BEGIN
-- imports nothing
-- exports nothing
TBL ::= --snacc isPdu:"TRUE" -- SEQUENCE
{
totalNumModules INTEGER, -- these totals can help allocation
totalNumTypeDefs INTEGER, -- when decoding (ie use arrays)
totalNumTypes INTEGER,
totalNumTags INTEGER,
totalNumStrings INTEGER,
totalLenStrings INTEGER,
modules SEQUENCE OF TBLModule
}
TBLModule ::= SEQUENCE
{
name [0] IMPLICIT PrintableString,
id [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
isUseful [2] IMPLICIT BOOLEAN, -- true if useful types module
typeDefs [3] IMPLICIT SEQUENCE OF TBLTypeDef
}
TBLTypeDef ::= SEQUENCE
{
typeDefId TBLTypeDefId,
typeName PrintableString OPTIONAL, -- I have forgotten why this is opt!
type TBLType
}
TBLType ::= SEQUENCE
{
typeId [0] IMPLICIT TBLTypeId,
optional [1] IMPLICIT BOOLEAN,
tagList [2] IMPLICIT SEQUENCE OF TBLTag OPTIONAL,
content [3] TBLTypeContent,
fieldName [4] IMPLICIT PrintableString OPTIONAL
}
TBLTypeContent ::= CHOICE
{
primType [0] IMPLICIT NULL,
elmts [1] IMPLICIT SEQUENCE OF TBLType,
typeRef [2] IMPLICIT TBLTypeRef
}
TBLTypeRef ::= SEQUENCE
{
typeDef TBLTypeDefId,
implicit BOOLEAN
}
TBLTypeId ::= ENUMERATED
{
tbl-boolean (0),
tbl-integer (1),
tbl-bitstring (2),
tbl-octetstring (3),
tbl-null (4),
tbl-oid (5),
tbl-real (6),
tbl-enumerated (7),
tbl-sequence (8),
tbl-set (9),
tbl-sequenceof (10),
tbl-setof (11),
tbl-choice (12),
tbl-typeref (13)
}
TBLTypeDefId ::= INTEGER
TBLTag ::= SEQUENCE
{
tclass TBLTagClass,
code INTEGER (0..MAX)
}
TBLTagClass ::= ENUMERATED { universal (0), application (1),
context (2), private (3)}
END
\end{verbatim}
\end{small}
\chapter{\label{edex-files}ASN.1 Files for the Editor Example}
The files can be found in {\ufn \dots/tcl-example/}.
\begin{ASNcode}
\label{edex0.asn1}--\,-- file: edex0.asn1\\
--\,--\\
--\,-- SnaccEd example, simple types module\\
\\
EdEx-Simple DEFINITIONS ::=\\
BEGIN\\
\\
RainbowColor ::= INTEGER\\
\{\\
\>red(0), orange(1), yellow(2), green(3), blue(4), indigo(5), violet(6)\\
\}\\
\\
DayOfTheWeek ::= ENUMERATED\\
\{\\
\>sunday(0), monday(1), tuesday(2), wednesday(3), thursday(4), friday(5), saturday(6)\\
\}\\
\\
Hand ::= BIT STRING\\
\{\\
\>thumb(0), forefinger(1), middle-finger(2), ring-finger(3), little-finger(4)\\
\}\\
\\
victory Hand ::= \{ forefinger, middle-finger \}\\
\\
END
\end{ASNcode}
\begin{ASNcode}
\label{edex1.asn1}--\,-- file: edex1.asn1\\
--\,--\\
--\,-- SnaccEd example, structured types module\\
\\
EdEx-Structured DEFINITIONS ::=\\
BEGIN\\
\\
IMPORTS RainbowColor, DayOfTheWeek, Hand FROM EdEx-Simple;\\
\\
RGBColor ::= SEQUENCE\\
\{\+\\
red INTEGER,\\
green INTEGER,\\
blue INTEGER\-\\
\}\\
\\
Coordinate ::= CHOICE\\
\{\+\\
cartesian [0] SEQUENCE \{ x REAL, y REAL \},\\
polar [1] SEQUENCE \{ angle REAL, distance REAL \}\-\\
\}\\
\\
File ::= SET\\
\{\+\\
name [0] PrintableString,\\
contents [1] OCTET STRING,\\
checksum [2] INTEGER OPTIONAL,\\
read-only [3] BOOLEAN DEFAULT FALSE\-\\
\}\\
\\
Directory ::= SET\\
\{\+\\
name PrintableString,\\
files SET OF File\-\\
\}\\
\\
Simple ::= SET\\
\{\+\\
null [0] NULL,\\
bool [1] BOOLEAN,\\
day [2] DayOfTheWeek,\\
int [3] INTEGER,\\
color [4] RainbowColor,\\
real [5] REAL,\\
bits [6] Hand,\\
str [7] OCTET STRING,\\
optstr [8] OCTET STRING OPTIONAL\-\\
\}\\
\\
Structured ::= SET\\
\{\+\\
coord [0] Coordinate,\\
color [1] CHOICE \{ rainbow RainbowColor, rgb RGBColor \}\-\\
\}\\
\\
Various ::= SET\\
\{\+\\
simple [0] Simple,\\
struct [1] Structured,\\
recursion [2] Various OPTIONAL\-\\
\}\\
\\
END
\end{ASNcode}