TOP

ASN.1/Java Compiler Advanced Topics

Applies to: ASN.1/Java v8.7

ASN.1 Macros

The OSS macro processor is included as part of the OSS ASN.1 compiler and provides a series of useful functions:

  • Expands all macro notation.
  • Performs full syntax checking of ASN.1 source files.
  • Produces source listings (with all imported items expanded) and diagnostic messages.

When invoking the OSS macro expander/syntax checker, no preprocessing of the ASN.1 source is required.

Expansion of ASN.1 Macro Notation

The ASN.1 type that the macro instance returns (the type of the value that the macro assigns to the local value reference, VALUE) is used to determine how the macro is expanded. If a single assignment is made to VALUE in an instance of the macro, the type associated with that value is returned.

When the type returned by the macro instance is indeterminate (zero or more than one assignment to VALUE in the macro instance), a CHOICE type is generated. If no assignment is made to VALUE in the macro instance, the resulting CHOICE contains each possible type that the macro can return. If more than one assignment is made to VALUE in the macro instance, the resulting CHOICE contains the type associated with each VALUE to which an assignment was made.

When the type returned by the macro instance is completely indeterminate, an ANY type is generated. This occurs when the value assigned to VALUE is an argument that is present only in the macro's VALUE NOTATION, but the macro is used strictly as a type with no value specified.

Macro instances that have indeterminate return types are non-standard and we recommend that you do not use them. The compiler tolerates these types of macros only to support older versions; however, a warning message is issued when it encounters them.

Restrictions

  • When defining a macro by another macro, make sure the latter is defined. In the following example, OPERATION must be defined before it can be used in defining ABSTRACT-OPERATION:
    ABSTRACT-OPERATION MACRO ::= OPERATION
  • The character "[" is not supported for macros as a string.
  • When you specify arguments in a macro instance, make sure the macro is defined.

    In the following example, A is correctly defined since no argument is passed to ERROR. Also, C is correctly defined because ERROR is defined before being referenced by C. Note that B incorrectly defined, because arguments are passed to it, but ERROR is referenced by B before being defined:
    A ::= ERROR
    
    B ::= ERROR PARAMETER BOOLEAN
    
    ERROR MACRO ::= BEGIN
       TYPE NOTATION   ::= Parameter
       VALUE NOTATION  ::= value(VALUE CHOICE{
             localValue  INTEGER,
             globalValue OBJECT IDENTIFIER})
    
        Parameter       ::= "PARAMETER" NamedType | empty
        NamedType       ::= identifier type | type
    END
    
    C ::= ERROR PARAMETER BOOLEAN
    
  • Macro arguments and values that do not have an effect on the returned type are checked by the compiler for correct usage, but have no effect on the compiler output. The compiler treats such parameters and values as formal comments whose meaning is understood only by the user. As such, it validates their usage but does not attempt to interpret their meaning.

    For example, using the ERROR definition that is specified above in this section, you can create an instance of ERROR as follows:
    C ::= ERROR PARAMETER BOOLEAN

Note that, in the macro definition, the type of the value returned by ERROR is CHOICE {localValue INTEGER, globalValue OBJECT IDENTIFIER}; this type is independent of the parameters passed to ERROR. The compiler syntax-checks the parameters to ensure that if the PARAMETER occurs immediately after ERROR, it is followed by a valid ASN.1 type. These parameters are then ignored and have no further effect. In some instances, this behavior is contrary to the type/value compatibility rules in ASN.1.

Examples of Macros

The following examples are drawn from the ITU-T Recommendations X.208 and X.410.

Example 1

Macro whose return type is independent of the instance of the type notation and value notation:

ERROR MACRO ::=
BEGIN
     TYPE NOTATION  ::= "PARAMETER" NamedType | empty
     VALUE NOTATION ::= value(VALUE INTEGER)
     NamedType      ::= identifier type | type
END

The ERROR macro is used as follows:

ErrorRecord ::= SEQUENCE {
     rectype ERROR PARAMETER VisibleString,
     sector  INTEGER
}

Regardless of the parameter passed to the macro, the following definition is always implied because the type returned by the macro is always INTEGER:

ErrorRecord ::= SEQUENCE {
   rectype INTEGER,
   sector  INTEGER
}

Example 2

Macro whose return type is independent of the instance of the type notation and the value notation:

OPERATION MACRO ::= BEGIN
    TYPE NOTATION ::= "ARGUMENT" NamedType Result Errors | empty
    VALUE NOTATION ::= value(VALUE INTEGER)
    Result         ::= empty | "RESULT" NamedType
    Errors         ::= empty | "ERRORS" "{"ErrorNames"}"
    NamedType      ::= identifier type | type
    ErrorNames     ::= empty | IdentifierList
    IdentifierList ::= identifier | IdentifierList "," identifier
END

The OPERATION macro is used as follows:

cancel OPERATION
    ARGUMENT jobname IA5String
    RESULT jobCancelled NULL
    ERRORS {jobNotFound, unauthorizedCancel}
    ::= 1

Message ::= SEQUENCE {
    invokeID INTEGER,
             OPERATION,
    argument ANY
}

Regardless of the parameters passed to the macro, since the type that the macro returns is always INTEGER, the following code is always generated:

lookup INTEGER ::= 1

Message ::= SEQUENCE {
    invokeID INTEGER,
             INTEGER,
    argument ANY
}

Example 3

Macro whose return type is independent of the instance of the value notation, but depends on the instance of the type notation:

PAIR MACRO ::=
BEGIN
TYPE NOTATION ::=
          "TYPEX" "=" type(LocalType1)
          "TYPEY" "=" type(LocalType2)
VALUE NOTATION ::=
          "("
          "X" "=" value(LocalValue1 LocalType1)
          ","
          "Y" "=" value(LocalValue2 LocalType2)
          <VALUE SEQUENCE {LocalType1, LocalType2} ::=
                          {LocalValue1, LocalValue2}>
          ")"
END

The PAIR macro is used as follows:

AgeAndMarried ::= PAIR
     TYPEX = INTEGER
     TYPEY = BOOLEAN

serena AgeAndMarried ::= (X = 2, Y = FALSE)

The following code is generated. Note that the generated types are based on the macro parameters:

AgeAndMarried ::= SEQUENCE {
     INTEGER,
     BOOLEAN
}

serena AgeAndMarried ::= {2, FALSE}

Example 4

Macro whose return type depends on the instance of the type and the value notation (contains multiple assignments to VALUE):

BIND MACRO ::=
BEGIN
     TYPE NOTATION  ::= Argument  Result  Error
     VALUE NOTATION ::= Argument-value|Result-value|Error-value

     Argument ::= empty | "ARGUMENT" Name type(Argument-type)
     Result   ::= empty | "RESULT" Name type (Result-type)
     Error    ::= empty | "BIND-ERROR" Name type(Error-type)
     Name     ::= empty | identifier

     Argument-value ::= empty | "ARGUMENT"
         value(Arg-value Argument-type)
         <VALUE [16] EXPLICIT Argument-type ::= Arg-value>

     Result-value   ::= empty | "RESULT"
         value(Res-value Result-type)
         <VALUE [17] EXPLICIT Result-type   ::= Res-value>

     Error-value  ::= empty | "ERROR"
         value(Err-value Error-type)
         <VALUE [18] EXPLICIT Error-type    ::= Err-value>
END

The BIND macro is used as follows:

BindA ::= BIND
BindB ::= BIND RESULT INTEGER
b BIND ARGUMENT INTEGER ::= ARGUMENT 2

A warning message is issued for BindA and BindB, and the following code is generated:

BindA ::= CHOICE {
    [16] ANY,
    [17] ANY,
    [18] ANY
}

BindB ::= [17] INTEGER

b [16] INTEGER ::= 2

Backward Compatibility

The following table contains the -compat flags listed alphabetically and provides a description.
NOTE: OSS does not guarantee compatibility between different versions of the ASN.1 Tools released more than 10 years apart.

Name Description
badPerEncodingForExtensibleSizeConstr
Prior to version 4.2.0, the PER Aligned and PER Unaligned Coder encoded values of restricted character string, OCTET STRING and BIT STRING types with extensible size constraints satisfying X.691 annex B.3 example A15 without an extensibility bit. Since version 4.2.0, values of these types are encoded with an extensibility bit always set to zero.
For example, since version 4.2.0 for the type
T ::= IA5String (SIZE(1..20) | FROM("ABCD"), ...) 
the value
 t T ::= "ABCD" 
is encoded by the PER Aligned Coder with a zero extensibility bit:
00044142 4344
Previously the encoding did not contain an extensibility bit:
044142 4344
The -compatbadPerEncodingForExtensibleSizeConstr option disables the new behavior providing compatibility with previous versions.
JavaSharing
Type sharing as introduced in the 1.0 beta B version of the compiler might cause problems when your ASN.1 definition changes (if some shared types are removed from your definition). Therefore, the default behavior, beginning with version 1.1, is to disable type sharing. For compatibility with beta B and beta C, the -compat javasharing option has been introduced to restore the previous behavior.
OldInnerClassReference
Instructs the ASN.1 compiler for Java to generate references to nested classes inside artificial compiler-generated classes for macro types or types for information objects rather than to use the references inside the class that originated those artificial classes.
oldinfoobjectsets
Prevents the compiler from generating extra metadata in the information object set class. If you need interoperability with versions prior to 1.5 of the runtime, specify the -compat oldinfoobjectsets flag. A new constructor of the InfoObjectSet, which the generated code references, is not available in earlier versions of the runtime.
pdusForReferencedTypesOfRemovedFields
Previously, application of the ASN1.Remove directive to a SET/SEQUENCE field or to a CHOICE alternative could unexpectedly increase the size of the generated code because the referenced type was wrongly treated as a PDU. Thus, the Java class was generated for such a type, including the supporting code for encode and decode operations.
As a workaround, the global --<OSS.NOPDU>-- directive could be used along with OSS.PDU directives applied to all the required PDU types.
As of version 8.0, the compiler does not treat a named ASN.1 type as a PDU type if it is referenced only by fields or alternatives with the ASN.Remove compiler directive.
This flag restores the old behavior of the compiler.
v4.2reservedWords
Prevents the compiler from mangling enum and Position identifiers.
v6.0valueTruncation
Restores the previous behavior of the compiler to not truncate a value of a SEQUENCE OF/SET OF type.
v8.2ContentsConstraintsWithRecursiveTypeInsideConstrainedBy
Instructs the ASN.1 compiler to not generate PDU classes for types derived from contents constraints that are included inside recursively defined types when the recursion occurs within a nested user-defined constraint applied using an inner subtype constraint.
v8.2ImportedWithSuccessorForwardedReferences
Instructs the ASN.1 compiler to leave some forwarded references imported WITH SUCCESSORS as unresolved, which could result in either an error or ignoring some constraints (such as contents constraints) specified inside inner subtype constraints that are applied to a parameterized type whose right-hand side type includes an instance of another parameterized type.
v8.4ArtificialPDUsForRecursivesTypes
To restore the behavior of the ASN.1 compiler prior to version 8.4, this standalone flag instructs the ASN.1 compiler to create new artificial PDUs for complex recursive types that are defined through CONSTRAINED BY and are inside parameterized types.
v8.4ContentsConstraintInsideOpenTypeValue
To restore the behavior of the ASN.1 compiler prior to version 8.4, this standalone flag instructs the ASN.1 compiler to create a new artificial PDU for a type that has a contents constraint inside an open type value, even if the matching type exists in the information object set specified in the component relation constraint.
v8.4ForwardedNonParamReferencesImportedWithSuccessors
Restores the behavior of the ASN.1 compiler prior to version 8.4. This standalone flag instructs the ASN.1 compiler to leave some forwarded non-parameterized references, imported WITH SUCCESSORS, and used inside actual parameters with inner subtype constraints in instances of parameterized types as unresolved. This could result in warnings, also some unresolved types or errors in non-relaxed mode could be skipped.
v8.6PdusForTypesFromDEFAULTInsideInfoObjClass
Restores the behavior of the ASN.1 compiler prior to version 8.6. This flag instructs the ASN.1 compiler to ignore module names where information object class definitions are located when generating Java classes for PDU types used in the DEFAULT syntax applied to VariableTypeFields inside those classes. Note this compat flag could force the ASN.1 compiler to generate code that cannot be Java compiled.
v8.6TypesFromConstrainedBy
Restores the behavior of the ASN.1 compiler prior to version 8.6. This flag instructs the ASN.1 compiler to generate names that were generated by the previous version of the ASN.1 compiler for types defined in the CONSTRAINED BY syntax. Note this compat flag could restore an unexpected circular reference error for some syntaxes.

This documentation applies to the OSS® ASN.1 Tools for Java release 8.7 and later.

Copyright © 2024 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 Java 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 Java are available to you.