TOP

ASN.1/C++ Compiler Directives

Applies to: ASN.1/C++ 6.7

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.
  • Two dollar signs ("$$") followed by an index number to reference a particular WITH COMPONENT or WITH COMPONENTS 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

To access ASN.1 types located within CONSTRAINED BY clauses, you must specify the dollar sign ("$") followed by a number index indicating a particular CONSTRAINED BY. This number index can be optionally followed by a colon (":") and another number index or a component identifier which indicates a particular component within the CONSTRAINED BY braces. If the colon and the index or the identifier following it are left out, the first component within the CONSTRAINED BY is targeted by default.

To access ASN.1 types located within WITH COMPONENT or WITH COMPONENTS clauses, you must specify two dollar signs ("$$") followed by a number index indicating a particular WITH COMPONENT or WITH COMPONENTS.

The following example illustrates CONSTRAINED BY constraints applied within WITH COMPONENTS clauses:

--<OSS.FIELDNAME Mod.Type.$$1.data.$1:1.alt "my_alt">--
--<OSS.FIELDNAME Mod.Type.$$2.data.$1:1.fld "my_fld">--

Mod DEFINITIONS ::= BEGIN
Type ::= SEQUENCE {data OCTET STRING }
	 (WITH COMPONENTS{..., data (CONSTRAINED BY {CHOICE {alt BOOLEAN}})})
	 (WITH COMPONENTS{..., data (CONSTRAINED BY {SEQUENCE {fld INTEGER OPTIONAL}})})
END

In the above absolute reference, $$1.data.$1:1 refers to the type within the CONSTRAINED BY of the first WITH COMPONENTS clause. The first directive changes the name of the "alt" field to "my_alt". $$2.data.$1:1 refers to the type within the CONSTRAINED BY of the second WITH COMPONENTS clause. The second directive changes the name of the "fld" field to "my_fld".

The following example illustrates a CONTAINING constraint applied within WITH COMPONENTS clauses.

--<OSS.TYPENAME Mod.Type.$$1.bit.* "MyChoice">--
--<OSS.FIELDNAME Mod.Type.$$1.bit.*.alt "my_alt">--
--<OSS.FIELDNAME Mod.BaseType.other.fld "my_other_fld">--

Mod DEFINITIONS ::= BEGIN
BaseType ::= SEQUENCE {
	bit    BIT STRING OPTIONAL,
	other  SEQUENCE {
		fld INTEGER OPTIONAL
	} OPTIONAL
} 
Type ::= BaseType 
	(WITH COMPONENTS {..., bit 
		(CONTAINING 
			CHOICE {alt INTEGER}) }) 
END

In the first absolute reference, $$1.bit.* refers to the CHOICE type within the CONTAINING clause of the first WITH COMPONENTS clause applied to Type. $$1.bit.*.alt refers to the field of the CHOICE type. Note that you can use the "$$ <num> " syntax only for components whose names are explicitly included in the WITH COMPONENTS syntax (that is, for the bit field in the above example). The absolute references of the fields within the original type, BaseType, apply to the names within the original type and also to the ones within all the types that are created when using contents constraints within WITH COMPONENTS. Therefore, to change the names that are not included in the WITH COMPONENTS clause of the derived type, Type, you would need to change the names of the original type, BaseType.

Example

The following table contains examples of using absoluteReference:

ASN.1 module absoluteReference
MyMod DEFINITIONS ::= BEGIN
  Comp1 ::= SET OF SEQUENCE {
    a INTEGER,
    b OCTET STRING OPTIONAL,
    c CHOICE {
      nest1 BOOLEAN,
      nest2 BIT STRING
    }
  }
  Comp2 ::= BOOLEAN 
     (CONSTRAINED BY {--Just a comment--})
     (CONSTRAINED BY {
        SET {con1 NULL, con2 REAL}})
END 
referencing  entire module: MyMod
referencing  SET OF: MyMod.Comp1
referencing  SEQUENCE series: MyMod.Comp1.*
referencing  b: MyMod.Comp1.*.b or MyMod.Comp1.*.2
referencing  nest1: MyMod.Comp1.*.c.nest1 or MyMod.Comp1.*.c.1
referencing  con1: MyMod.Comp2.$2.con1 
Mod DEFINITIONS ::= BEGIN
  C ::= BOOLEAN 
    (CONSTRAINED BY {})
       (CONSTRAINED BY {
          INTEGER, -- "1st" parameter
          IA5String,
          CHOICE {
            f REAL (CONSTRAINED BY
               {SET {e NULL}})
          } -- "3rd" parameter
     })
END
referencing e: Mod.C.$2:3.f.$1.e
Mod DEFINITIONS ::= BEGIN
   Type ::= SEQUENCE {data OCTET STRING }
      (WITH COMPONENTS{..., data    -- "1st" inner subtype
         (CONSTRAINED BY { 
              CHOICE {
                  alt BOOLEAN
              }
      })})
      ((WITH COMPONENTS{..., data   -- "2nd" inner subtype
         (CONSTRAINED BY { 
              SEQUENCE {
                  fld1 INTEGER OPTIONAL
              }
      })}) |
      (WITH COMPONENTS{..., data    -- "3d" inner subtype
         (CONSTRAINED BY { 
              SEQUENCE OF SET {
                  fld2 INTEGER OPTIONAL
              }
      })}))
END





referencing alt: Mod.Type.$$1.data.$1:1.alt





referencing fld1: Mod.Type.$$2.data.$1:1.fld1





referencing fld2: Mod.Type.$$3.data.$1:1.*.fld2

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.

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.7 and later of the OSS® ASN.1 Tools for C++.

Copyright © 2020 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.