TOP

ASN.1/C++ Compiler Directives

Applies to: ASN.1/C++ 6.5

OSS ASN.1/C++ Compiler directives let you control how data is encoded, decoded, and represented locally. Compiler directives are not required: if none are used in an ASN.1 module, the compiler uses default settings to generate the header and C++ files.

Format

Every compiler directive begins with "--<" and ends with ">--", so compilers that do not support these directives see them as comments. All directives are case-sensitive and have the following format:

  --<[prefix.]directive [absoluteReference] [operand1[, operand2]...[, operandx]]>--

Where

  • prefix is the directive type.
  • directive is the name of the directive.
  • absoluteReference specifies the ASN.1 item(s) the directive will be applied to.
  • operand1...operandx is one or more tokens used to configure the directive as outlined in the Compiler Directives Reference. Note that operands are mandatory for some directives and optional for others.

Specifying Multiple Directives

These examples show three equivalent ways to specify multiple directives:

  --<OSS.DECIMAL>-- --<OSS.ROOT Module1>--
  --<OSS.DECIMAL>--
  --<OSS.ROOT Module1>--
  --<OSS.DECIMAL>--
  --<OSS.ROOT
  --Module1>--

Directives at the Local, Module, or Global Level

Local

Directives are specified in-line (old method), for example,

A ::= [1] REAL --<DECIMAL>--

Directives reference a specific item (preferred method), for example,

--<OSS.DECIMAL MyModule.A>--

Module

Directives are specified at the module level, before BEGIN, and do not reference any specific item, for example,

MyModule DEFINITIONS --<OSS.DECIMAL>-- ::= BEGIN ...

Global

Directives are specified outside modules, usually in a directives file, and do not reference any specific item, for example,

--<OSS.DECIMAL>--
MyModule DEFINITIONS ::= BEGIN ...

Contradictory Directives

It is possible to specify contradictory directives, such as OSS.DEFINITE and OSS.INDEFINITE. If this occurs, the last directive specified is used and the previous ones are ignored.

Directive Types

The OSS ASN.1 C++ Compiler recognizes three types of directives: Standard, OSS-specific, and OSS-specific legacy-style.

Standard Directives

Syntax

--<ASN1.directive ...>--

Remarks

A standard directive can be placed anywhere in the ASN.1 syntax provided it appears before the referenced item. Standard directives usually have an ASN1 prefix.

Some standard directives and their operands have no effect on the compiler-generated output files. These directives can still be specified in the input ASN.1 file, but one of the following warning messages will be issued by the ASN.1/C++ Compiler during compilation:

  • The -genDirectives command line option is not specified:
    C0492I: There are unused standard directives.  Specify the -genDirectives command line option, 
            then look at all lines containing "WARNING:" in the generated .gen file.
  • The -genDirectives option is specified:
    C0064I: There are unused standard or OSS-specific directives. Look at all lines containing "WARNING:"
            in the .gen file.

Example

--<ASN1.WorkingSet Module1, Module2, Module3>--

OSS-Specific Directives

Syntax

--<OSS.directive...>--

Remarks

OSS-specific directives are used in the ASN.1 input wherever spaces or tabs are allowed: locally, at the module-level, and globally. When used globally, specify the directives before the first module definition.

The OSS prefix should be present when the directive is being specified globally, even though its presence is not mandatory. Likewise, when an OSS-specific directive is used at the module-level, the OSS prefix is not required. However, directives specified at the local-level should not be prefixed with OSS.

These directives can also be captured in a .gen file using the –genDirectives command-line option. Then all directives in the ASN.1 syntax can be removed and the .gen file is passed as the first command-line parameter when invoking the ASN.1 Compiler.

Example

--<OSS.DTD XModule.StringType>--

OSS-Specific Legacy-Style Directives

Syntax

--<directive...>--

Remarks

OSS-specific legacy-style directives are the same as non-legacy versions, except the OSS prefix is never used. Most of these directives cannot globally specify that a directive affects only particular type instances. Historically, they were used as inline directives.

These directives can have local, module, or global scope, depending on placement. When specified locally, multiple legacy-style directives can be specified together when separated by vertical bars ('|'). For example, the following two directive specifications are equivalent:

A ::= [1] REAL  --<PDU>--  --<DECIMAL>--
A ::= [1] REAL  --<PDU | DECIMAL>--

These directives can also be captured in a .gen file using the –genDirectives command-line option. Then all directives in the ASN.1 syntax can be removed and the .gen file is passed as the first command-line parameter when invoking the ASN.1 Compiler.

Example

A ::= [1] REAL --<DECIMAL>--

Other Directive Types

If you use implementation-specific directives (for example, those having prefixes of HP, TCSI, etc.), warning messages are issued during compilation, otherwise these directives are ignored.

Precedence

OSS-specific directives take precedence over OSS-specific legacy-style directives. In the following example, the --<LONG>-- legacy-style directive will be ignored.

     --<OSS.SHORT Sample.Name>--

Sample DEFINITIONS EXPLICIT TAGS ::= BEGIN
     Name ::= [1] INTEGER --<LONG>--
END

Standard directives also take precedence over OSS-specific legacy-style directives.

     --<ASN1.Nickname Module.Int ASN1_Nicknamed_Int>--

Module DEFINITIONS ::= BEGIN
     Int ::= INTEGER --<TYPENAME "OSS_Specific_New_Name">--
END

When the ASN.1 syntax above is compiled, the TYPENAME directive is ignored and the following is generated in the header file:

typedef OSS_INT32 ASN1_Nicknamed_Int;

Precedence is also affected by a directive's scope: local, module, or global. OSS-specific directives specified at the local level take precedence over those at the global level. In the following sample notation, A will be represented by a short while B and C will be represented by a long.

     --<OSS.LONG>--

Module DEFINITIONS ::= BEGIN
     A ::= [1] INTEGER --<SHORT>--
     B ::= [2] INTEGER
     C ::= [3] INTEGER
END

Absolute References

An absolute reference uniquely specifies one or more components in ASN.1 syntax. The notation is similar to that used by many programming languages to access components within named structures and records. The outermost structure is listed first using its identifier followed by a dot ("."). A component of the outermost structure (which could also be a structure) can be listed next. When the desired component is within a nested structure, a dot is added after the name of the containing structure and then the desired component is listed.

You can specify ASN.1 components using:

  • A component's identifier.
  • An asterisk ("*") to select all rows in a SEQUENCE OF or SET OF array.
  • An INTEGER index to designate an element in a SEQUENCE, SET, or CHOICE.
  • A dollar sign ("$") followed by a number index to reference a particular CONSTRAINED BY clause.

Example

MyMod DEFINITIONS ::= BEGIN
	Comp1 ::= SET OF SEQUENCE {
			a		INTEGER,
			b		OCTET STRING OPTIONAL,
			c		CHOICE {
						nest1	BOOLEAN,
						nest2	BIT STRING
					}
	}
	Comp2 ::= IA5String
END

In the ASN.1 definition above, the absolute reference for the

  • Entire module is MyMod
  • SET OF structure is MyMod.Comp1
  • SEQUENCE series is MyMod.Comp1.*
  • INTEGER is MyMod.Comp1.*.a or MyMod.Comp1.*.1
  • OCTET STRING is MyMod.Comp1.*.b or MyMod.Comp1.*.2
  • CHOICE is MyMod.Comp1.*.c or MyMod.Comp1.*.3
  • BOOLEAN is MyMod.Comp1.*.c.nest1 or MyMod.Comp1.*.c.1
  • BIT STRING is MyMod.Comp1.*.c.nest2 or MyMod.Comp1.*.c.2
  • IA5String is MyMod.Comp2

Warning

An absolute reference cannot be extended inside of another type reference. For example, in the following ASN.1 definition

MyMod DEFINITIONS ::= BEGIN
     Foo ::= SEQUENCE {
             foo INTEGER
     }
     Bar ::= SEQUENCE {
             bar Foo
     }
END

the absolute reference for the INTEGER is MyMod.Foo.foo, not MyMod.Bar.bar.foo.

Using Absolute References in CONSTRAINED BY Clauses

To access ASN.1 types located within CONSTRAINED BY clauses, specify the dollar sign ("$") followed by a number index that represents the chosen CONSTRAINED BY clause. This number index can be followed by a colon (":") and another number index that indicates a component within the CONSTRAINED BY braces. If the colon and the index following it are left out, the first component within the CONSTRAINED BY is targeted by default. Also, instead of the colon, the CONSTRAINED BY number index can be followed by a dot (".") and the component identifier of an ASN.1 item within the CONSTRAINED BY clause.

Example 1: Simple CONSTRAINED BY Clauses

--<OSS.FIELDNAME Mod.A.$2.c "my_c">--

Mod DEFINITIONS ::= BEGIN
   A ::= BOOLEAN (CONSTRAINED BY {--Just a comment--})
                    (CONSTRAINED BY {
                       SET {c NULL, d REAL}})
END

For the syntax above, $2.c in the absolute reference refers to field c in the SET type in the second CONSTRAINED BY clause. Note that using $2:1.c is unnecessary, since :1 is already implied by default.

Example 2: CONSTRAINED BY Types in Instances of Parameterized Types

--<OSS.TYPENAME Mod.B.$1 "my_bitstr">--
--<OSS.FIELDNAME Mod.B.$3.a "my_a">--

Mod DEFINITIONS ::= BEGIN
   B ::= Param {INTEGER} (CONSTRAINED BY {BIT STRING})

   Param {T} ::= T (CONSTRAINED BY {--Just a comment--})
                      (CONSTRAINED BY {
                          SEQUENCE {a BOOLEAN}})
END

For the syntax above, $1 in the first absolute reference refers to the BIT STRING type in the first CONSTRAINED BY clause applied to B, reading the ASN.1 definition top to bottom, left to right. In the second absolute reference, $3.a refers to field a in the SEQUENCE type in the third CONSTRAINED BY clause applied to the parameterized type B, counting from top to bottom, left to right. Be sure to count all of the CONSTRAINED BY clauses that are applied to the B type and not just those in the Param parameterized definition.

Example 3: Nested CONSTRAINED BY Clauses

--<ASN1.Nickname Mod.C.$2:3.f.$1.e "my_e">--

Mod DEFINITIONS ::= BEGIN
  C ::= BOOLEAN (CONSTRAINED BY {})
                  (CONSTRAINED BY {
                      INTEGER, -- "1st" parameter
                      IA5String,
                      CHOICE {
                         f REAL (CONSTRAINED BY
                                 {SET {e NULL}})
                                } -- "3rd" parameter
                  })
END

For the syntax above, $2:3 in the absolute reference refers to the 3rd parameter (i.e., the CHOICE type) in the second CONSTRAINED BY clause applied to the C type; furthermore, $1:e refers to the e component in the SET type that is the first (and only) parameter in the first CONSTRAINED BY applied to the f component of the CHOICE type.

Applying Directives to Parameterized Types

When you apply a directive to a parameterized type definition, that directive is applied to every instance of the type. For example, when the OSS.PDU directive is applied to a parameterized type, all instances of this type are treated as PDUs. Likewise, when the ASN1.WorkingSet directive is applied to a parameterized type, all instances of the type are included in the working set. The ASN1.Remove directive is the exception to the rule; it is explicitly applied to either a specific instance or every instance of a parameterized type.

Name-Changing Directives

Applying name-changing directives, such as ASN1.Nickname or OSS.TYPENAME, to a parameterized type could create types with duplicate type, variable, or #define names in the ASN.1 Compiler-generated header file. This occurs when there are several instances of the parameterized type in the ASN.1 input. When you try to compile the generated file the C++ compiler will issue an error message.

Example

The header file generated by compiling the following ASN.1 will contain two classes named NewTypeName:

--<ASN1.Nickname  Test.T2 ParmType>--
--<OSS.TYPENAME   Test.T2.bt2 NewTypeName>--

Test DEFINITIONS ::= BEGIN
T1 ::= SET {at1 INTEGER, bt1 BOOLEAN}
T11 ::= SET {at11 INTEGER, bt11 BOOLEAN}
T2 {X} ::= SEQUENCE {at2 BIT STRING OPTIONAL, bt2 SET OF X OPTIONAL }
T3 ::= T2 {T1}
T4 ::= T2 {T11}
END

Instances of Parameterized Types

Applying a directive to an instance of a parameterized type affects only that particular instance.

Example

The first directive only changes the name of S1. The second directive changes the name of the component in S2.

--<ASN1.Nickname  Test.S1     "Inst1_Seq">--
--<OSS.TYPENAME   Test.S1.a   "Inst1_Seq_a">--
    
Test DEFINITIONS ::= BEGIN
  Seq {Type} ::= SEQUENCE   {a Type OPTIONAL}
    S1 ::= [2] Seq{SEQUENCE {b INTEGER}}
    S2 ::= [3] Seq{SEQUENCE {c BOOLEAN OPTIONAL}}
END

Types Used as Substitution Types

A directive cannot be applied to any of the following:

  • A type used as a substitution type in a parameterized type instance.
  • The fields of such a type.
  • A type that is a parameter in a parameterized type.

Example

These directives have no effect.

--<ASN1.Nickname Test.T3.bt2.at1 bt2_nickname>--
--<OSS.TYPENAME Test.T3.bt2 NewName-instance>--
--<OSS.TYPENAME Test.T2.bt2 NewName-param>--

Test DEFINITIONS ::= BEGIN
   T2 {X} ::= SEQUENCE {at2 BIT STRING, bt2 X OPTIONAL}
   T3 ::= T2 {T1}
   T1 ::= SET {at1 INTEGER, bt1 BOOLEAN}
END

If you change the type for bt2 to a "non-direct" reference to the X parameter (such as SET OF X), the OSS.TYPENAME directives will succeed:

T2 {X} ::= SEQUENCE {at2 BIT STRING, bt2 SET OF X OPTIONAL}

Compiler Directives Index

The compiler directives listed below are grouped by category; a directive may be listed more than once. Use the check boxes to show only the basic compiler directives or to show advanced and deprecated directives as well. Get detailed information about a directive by clicking on its name.


This documentation applies to release 6.5 and later of the OSS® ASN.1 Tools for C++.

Copyright © 2017 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS® ASN.1 Tools for C++ is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS ASN.1 Tools for C++ are available to you.