From c6c01899e81412edace1ac96d7eef1eb4cbfd655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 25 Jan 2017 07:02:54 +0100 Subject: Correct spelling of NBAP-PDU-Descriptions --- .../nbapsystem/NBAP-PDU-Descriptions.asn | 916 +++++++++++++++++++++ .../nbapsystem/NBAP-PDU-Discriptions.asn | 916 --------------------- lib/asn1/test/asn1_SUITE_data/test_records.erl | 2 +- lib/asn1/test/testNBAPsystem.erl | 14 +- 4 files changed, 924 insertions(+), 924 deletions(-) create mode 100644 lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Descriptions.asn delete mode 100644 lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn (limited to 'lib') diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Descriptions.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Descriptions.asn new file mode 100644 index 0000000000..12a4475422 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Descriptions.asn @@ -0,0 +1,916 @@ +-- ************************************************************** +-- +-- Elementary Procedure definitions +-- +-- ************************************************************** + +NBAP-PDU-Descriptions { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +umts-Access (20) modules (3) nbap (2) version1 (1) nbap-PDU-Descriptions (0) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Criticality, + ProcedureID, + MessageDiscriminator, + TransactionID +FROM NBAP-CommonDataTypes + + CommonTransportChannelSetupRequestFDD, + CommonTransportChannelSetupRequestTDD, + CommonTransportChannelSetupResponse, + CommonTransportChannelSetupFailure, + CommonTransportChannelReconfigurationRequestFDD, + CommonTransportChannelReconfigurationRequestTDD, + CommonTransportChannelReconfigurationResponse, + CommonTransportChannelReconfigurationFailure, + CommonTransportChannelDeletionRequest, + CommonTransportChannelDeletionResponse, + BlockResourceRequest, + BlockResourceResponse, + BlockResourceFailure, + UnblockResourceIndication, + AuditFailure, + AuditRequiredIndication, + AuditRequest, + AuditResponse, + CommonMeasurementInitiationRequest, + CommonMeasurementInitiationResponse, + CommonMeasurementInitiationFailure, + CommonMeasurementReport, + CommonMeasurementTerminationRequest, + CommonMeasurementFailureIndication, + CellSetupRequestFDD, + CellSetupRequestTDD, + CellSetupResponse, + CellSetupFailure, + CellReconfigurationRequestFDD, + CellReconfigurationRequestTDD, + CellReconfigurationResponse, + CellReconfigurationFailure, + CellDeletionRequest, + CellDeletionResponse, + InformationExchangeInitiationRequest, + InformationExchangeInitiationResponse, + InformationExchangeInitiationFailure, + InformationReport, + InformationExchangeTerminationRequest, + InformationExchangeFailureIndication, + BearerRearrangementIndication, + ResourceStatusIndication, + SystemInformationUpdateRequest, + SystemInformationUpdateResponse, + SystemInformationUpdateFailure, + ResetRequest, + ResetResponse, + RadioLinkActivationCommandFDD, + RadioLinkActivationCommandTDD, + RadioLinkPreemptionRequiredIndication, + RadioLinkSetupRequestFDD, + RadioLinkSetupRequestTDD, + RadioLinkSetupResponseFDD, + RadioLinkSetupResponseTDD, + RadioLinkSetupFailureFDD, + RadioLinkSetupFailureTDD, + RadioLinkAdditionRequestFDD, + RadioLinkAdditionRequestTDD, + RadioLinkAdditionResponseFDD, + RadioLinkAdditionResponseTDD, + RadioLinkAdditionFailureFDD, + RadioLinkAdditionFailureTDD, + RadioLinkParameterUpdateIndicationFDD, + RadioLinkParameterUpdateIndicationTDD, + RadioLinkReconfigurationPrepareFDD, + RadioLinkReconfigurationPrepareTDD, + RadioLinkReconfigurationReady, + RadioLinkReconfigurationFailure, + RadioLinkReconfigurationCommit, + RadioLinkReconfigurationCancel, + RadioLinkReconfigurationRequestFDD, + RadioLinkReconfigurationRequestTDD, + RadioLinkReconfigurationResponse, + RadioLinkDeletionRequest, + RadioLinkDeletionResponse, + DL-PowerControlRequest, + DL-PowerTimeslotControlRequest, + DedicatedMeasurementInitiationRequest, + DedicatedMeasurementInitiationResponse, + DedicatedMeasurementInitiationFailure, + DedicatedMeasurementReport, + DedicatedMeasurementTerminationRequest, + DedicatedMeasurementFailureIndication, + RadioLinkFailureIndication, + RadioLinkRestoreIndication, + CompressedModeCommand, + ErrorIndication, + PrivateMessage, + PhysicalSharedChannelReconfigurationRequestTDD, + PhysicalSharedChannelReconfigurationRequestFDD, + PhysicalSharedChannelReconfigurationResponse, + PhysicalSharedChannelReconfigurationFailure, + CellSynchronisationInitiationRequestTDD, + CellSynchronisationInitiationResponseTDD, + CellSynchronisationInitiationFailureTDD, + CellSynchronisationReconfigurationRequestTDD, + CellSynchronisationReconfigurationResponseTDD, + CellSynchronisationReconfigurationFailureTDD, + CellSynchronisationAdjustmentRequestTDD, + CellSynchronisationAdjustmentResponseTDD, + CellSynchronisationAdjustmentFailureTDD, + CellSynchronisationReportTDD, + CellSynchronisationTerminationRequestTDD, + CellSynchronisationFailureIndicationTDD +FROM NBAP-PDU-Contents + + id-audit, + id-auditRequired, + id-blockResource, + id-cellDeletion, + id-cellReconfiguration, + id-cellSetup, + id-cellSynchronisationInitiation, + id-cellSynchronisationReconfiguration, + id-cellSynchronisationReporting, + id-cellSynchronisationTermination, + id-cellSynchronisationFailure, + id-commonMeasurementFailure, + id-commonMeasurementInitiation, + id-commonMeasurementReport, + id-commonMeasurementTermination, + id-commonTransportChannelDelete, + id-commonTransportChannelReconfigure, + id-commonTransportChannelSetup, + id-compressedModeCommand, + id-dedicatedMeasurementFailure, + id-dedicatedMeasurementInitiation, + id-dedicatedMeasurementReport, + id-dedicatedMeasurementTermination, + id-downlinkPowerControl, + id-downlinkPowerTimeslotControl, + id-errorIndicationForDedicated, + id-errorIndicationForCommon, + id-informationExchangeFailure, + id-informationExchangeInitiation, + id-informationReporting, + id-informationExchangeTermination, + id-BearerRearrangement, + id-physicalSharedChannelReconfiguration, + id-privateMessageForDedicated, + id-privateMessageForCommon, + id-radioLinkActivation, + id-radioLinkAddition, + id-radioLinkDeletion, + id-radioLinkFailure, + id-radioLinkParameterUpdate, + id-radioLinkPreemption, + id-radioLinkRestoration, + id-radioLinkSetup, + id-reset, + id-resourceStatusIndication, + id-cellSynchronisationAdjustment, + id-synchronisedRadioLinkReconfigurationCancellation, + id-synchronisedRadioLinkReconfigurationCommit, + id-synchronisedRadioLinkReconfigurationPreparation, + id-systemInformationUpdate, + id-unblockResource, + id-unSynchronisedRadioLinkReconfiguration +FROM NBAP-Constants; + +-- ************************************************************** +-- +-- Interface Elementary Procedure Class +-- +-- ************************************************************** + +NBAP-ELEMENTARY-PROCEDURE ::= CLASS { + &InitiatingMessage , + &SuccessfulOutcome OPTIONAL, + &UnsuccessfulOutcome OPTIONAL, + &Outcome OPTIONAL, + &messageDiscriminator MessageDiscriminator, + &procedureID ProcedureID UNIQUE, + &criticality Criticality DEFAULT ignore +} + +WITH SYNTAX { + INITIATING MESSAGE &InitiatingMessage + [SUCCESSFUL OUTCOME &SuccessfulOutcome] + [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome] + [OUTCOME &Outcome] + MESSAGE DISCRIMINATOR &messageDiscriminator + PROCEDURE ID &procedureID + [CRITICALITY &criticality] +} + +-- ************************************************************** +-- +-- Interface PDU Definition +-- +-- ************************************************************** + +NBAP-PDU ::= CHOICE { + initiatingMessage InitiatingMessage, + succesfulOutcome SuccessfulOutcome, + unsuccesfulOutcome UnsuccessfulOutcome, + outcome Outcome, + ... +} + +InitiatingMessage ::= SEQUENCE { + procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), + criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + transactionID TransactionID, + value NBAP-ELEMENTARY-PROCEDURE.&InitiatingMessage({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) +} + +SuccessfulOutcome ::= SEQUENCE { + procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), + criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + transactionID TransactionID, + value NBAP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) +} + +UnsuccessfulOutcome ::= SEQUENCE { + procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), + criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + transactionID TransactionID, + value NBAP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) +} + +Outcome ::= SEQUENCE { + procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), + criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), + transactionID TransactionID, + value NBAP-ELEMENTARY-PROCEDURE.&Outcome ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) +} + +-- ************************************************************** +-- +-- Interface Elementary Procedure List +-- +-- ************************************************************** + +NBAP-ELEMENTARY-PROCEDURES NBAP-ELEMENTARY-PROCEDURE ::= { + NBAP-ELEMENTARY-PROCEDURES-CLASS-1 | + NBAP-ELEMENTARY-PROCEDURES-CLASS-2 , + ... +} + +NBAP-ELEMENTARY-PROCEDURES-CLASS-1 NBAP-ELEMENTARY-PROCEDURE ::= { + cellSetupFDD | + cellSetupTDD | + cellReconfigurationFDD | + cellReconfigurationTDD | + cellDeletion | + commonTransportChannelSetupFDD | + commonTransportChannelSetupTDD | + commonTransportChannelReconfigureFDD | + commonTransportChannelReconfigureTDD | + commonTransportChannelDelete | + audit | + blockResource | + radioLinkSetupFDD | + radioLinkSetupTDD | + systemInformationUpdate | + commonMeasurementInitiation | + radioLinkAdditionFDD | + radioLinkAdditionTDD | + radioLinkDeletion | + reset | + synchronisedRadioLinkReconfigurationPreparationFDD | + synchronisedRadioLinkReconfigurationPreparationTDD | + unSynchronisedRadioLinkReconfigurationFDD | + unSynchronisedRadioLinkReconfigurationTDD | + dedicatedMeasurementInitiation | + physicalSharedChannelReconfigurationTDD , + ..., + informationExchangeInitiation | + cellSynchronisationInitiationTDD | + cellSynchronisationReconfigurationTDD | + cellSynchronisationAdjustmentTDD | + physicalSharedChannelReconfigurationFDD +} + +NBAP-ELEMENTARY-PROCEDURES-CLASS-2 NBAP-ELEMENTARY-PROCEDURE ::= { + resourceStatusIndication | + auditRequired | + commonMeasurementReport | + commonMeasurementTermination | + commonMeasurementFailure | + synchronisedRadioLinkReconfigurationCommit | + synchronisedRadioLinkReconfigurationCancellation | + radioLinkFailure | + radioLinkPreemption | + radioLinkRestoration | + dedicatedMeasurementReport | + dedicatedMeasurementTermination | + dedicatedMeasurementFailure | + downlinkPowerControlFDD | + downlinkPowerTimeslotControl | + compressedModeCommand | + unblockResource | + errorIndicationForDedicated | + errorIndicationForCommon | + privateMessageForDedicated | + privateMessageForCommon , + ..., + informationReporting | + informationExchangeTermination | + informationExchangeFailure | + cellSynchronisationReportingTDD | + cellSynchronisationTerminationTDD | + cellSynchronisationFailureTDD | + bearerRearrangement | + radioLinkActivationFDD | + radioLinkActivationTDD | + radioLinkParameterUpdateFDD | + radioLinkParameterUpdateTDD +} + +-- ************************************************************** +-- +-- Interface Elementary Procedures +-- +-- ************************************************************** + +-- Class 1 + +-- *** CellSetup (FDD) *** +cellSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSetupRequestFDD + SUCCESSFUL OUTCOME CellSetupResponse + UNSUCCESSFUL OUTCOME CellSetupFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSetup, ddMode fdd } + CRITICALITY reject +} + +-- *** CellSetup (TDD) *** +cellSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSetupRequestTDD + SUCCESSFUL OUTCOME CellSetupResponse + UNSUCCESSFUL OUTCOME CellSetupFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSetup, ddMode tdd } + CRITICALITY reject +} + +-- *** CellReconfiguration(FDD) *** +cellReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellReconfigurationRequestFDD + SUCCESSFUL OUTCOME CellReconfigurationResponse + UNSUCCESSFUL OUTCOME CellReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellReconfiguration, ddMode fdd } + CRITICALITY reject +} + +-- *** CellReconfiguration(TDD) *** +cellReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellReconfigurationRequestTDD + SUCCESSFUL OUTCOME CellReconfigurationResponse + UNSUCCESSFUL OUTCOME CellReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellReconfiguration, ddMode tdd } + CRITICALITY reject +} + +-- *** CellDeletion *** +cellDeletion NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellDeletionRequest + SUCCESSFUL OUTCOME CellDeletionResponse + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellDeletion, ddMode common } + CRITICALITY reject +} + +-- *** CommonTransportChannelSetup (FDD) *** +commonTransportChannelSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonTransportChannelSetupRequestFDD + SUCCESSFUL OUTCOME CommonTransportChannelSetupResponse + UNSUCCESSFUL OUTCOME CommonTransportChannelSetupFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonTransportChannelSetup, ddMode fdd } + CRITICALITY reject +} + +-- *** CommonTransportChannelSetup (TDD) *** +commonTransportChannelSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonTransportChannelSetupRequestTDD + SUCCESSFUL OUTCOME CommonTransportChannelSetupResponse + UNSUCCESSFUL OUTCOME CommonTransportChannelSetupFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonTransportChannelSetup, ddMode tdd } + CRITICALITY reject +} + +-- *** CommonTransportChannelReconfigure (FDD) *** +commonTransportChannelReconfigureFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonTransportChannelReconfigurationRequestFDD + SUCCESSFUL OUTCOME CommonTransportChannelReconfigurationResponse + UNSUCCESSFUL OUTCOME CommonTransportChannelReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonTransportChannelReconfigure, ddMode fdd } + CRITICALITY reject +} + +-- *** CommonTransportChannelReconfigure (TDD) *** +commonTransportChannelReconfigureTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonTransportChannelReconfigurationRequestTDD + SUCCESSFUL OUTCOME CommonTransportChannelReconfigurationResponse + UNSUCCESSFUL OUTCOME CommonTransportChannelReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonTransportChannelReconfigure, ddMode tdd } + CRITICALITY reject +} + +-- *** CommonTransportChannelDelete *** +commonTransportChannelDelete NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonTransportChannelDeletionRequest + SUCCESSFUL OUTCOME CommonTransportChannelDeletionResponse + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonTransportChannelDelete, ddMode common } + CRITICALITY reject +} + +-- *** Audit *** +audit NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AuditRequest + SUCCESSFUL OUTCOME AuditResponse + UNSUCCESSFUL OUTCOME AuditFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-audit, ddMode common } + CRITICALITY reject +} + +-- *** BlockResourceRequest *** +blockResource NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE BlockResourceRequest + SUCCESSFUL OUTCOME BlockResourceResponse + UNSUCCESSFUL OUTCOME BlockResourceFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-blockResource, ddMode common } + CRITICALITY reject +} + +-- *** RadioLinkSetup (FDD) *** +radioLinkSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkSetupRequestFDD + SUCCESSFUL OUTCOME RadioLinkSetupResponseFDD + UNSUCCESSFUL OUTCOME RadioLinkSetupFailureFDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-radioLinkSetup, ddMode fdd } + CRITICALITY reject +} + +-- *** RadioLinkSetup (TDD) *** +radioLinkSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkSetupRequestTDD + SUCCESSFUL OUTCOME RadioLinkSetupResponseTDD + UNSUCCESSFUL OUTCOME RadioLinkSetupFailureTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-radioLinkSetup, ddMode tdd } + CRITICALITY reject +} + +-- *** SystemInformationUpdate *** +systemInformationUpdate NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE SystemInformationUpdateRequest + SUCCESSFUL OUTCOME SystemInformationUpdateResponse + UNSUCCESSFUL OUTCOME SystemInformationUpdateFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-systemInformationUpdate, ddMode common } + CRITICALITY reject +} + +-- *** Reset *** +reset NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResetRequest + SUCCESSFUL OUTCOME ResetResponse + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-reset, ddMode common } + CRITICALITY reject +} + +-- *** CommonMeasurementInitiation *** +commonMeasurementInitiation NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonMeasurementInitiationRequest + SUCCESSFUL OUTCOME CommonMeasurementInitiationResponse + UNSUCCESSFUL OUTCOME CommonMeasurementInitiationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonMeasurementInitiation, ddMode common } + CRITICALITY reject +} + +-- *** RadioLinkAddition (FDD) *** +radioLinkAdditionFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkAdditionRequestFDD + SUCCESSFUL OUTCOME RadioLinkAdditionResponseFDD + UNSUCCESSFUL OUTCOME RadioLinkAdditionFailureFDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkAddition, ddMode fdd } + CRITICALITY reject +} + +-- *** RadioLinkAddition (TDD) *** +radioLinkAdditionTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkAdditionRequestTDD + SUCCESSFUL OUTCOME RadioLinkAdditionResponseTDD + UNSUCCESSFUL OUTCOME RadioLinkAdditionFailureTDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkAddition, ddMode tdd } + CRITICALITY reject +} + +-- *** RadioLinkDeletion *** +radioLinkDeletion NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkDeletionRequest + SUCCESSFUL OUTCOME RadioLinkDeletionResponse + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkDeletion, ddMode common } + CRITICALITY reject +} + +-- *** SynchronisedRadioLinkReconfigurationPreparation (FDD) *** +synchronisedRadioLinkReconfigurationPreparationFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationPrepareFDD + SUCCESSFUL OUTCOME RadioLinkReconfigurationReady + UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationPreparation, ddMode fdd } + CRITICALITY reject +} + +-- *** SynchronisedRadioLinkReconfigurationPreparation (TDD) *** +synchronisedRadioLinkReconfigurationPreparationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationPrepareTDD + SUCCESSFUL OUTCOME RadioLinkReconfigurationReady + UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationPreparation, ddMode tdd } + CRITICALITY reject +} + +-- *** UnSynchronisedRadioLinkReconfiguration (FDD) *** +unSynchronisedRadioLinkReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationRequestFDD + SUCCESSFUL OUTCOME RadioLinkReconfigurationResponse + UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-unSynchronisedRadioLinkReconfiguration, ddMode fdd } + CRITICALITY reject +} + +-- *** UnSynchronisedRadioLinkReconfiguration (TDD) *** +unSynchronisedRadioLinkReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationRequestTDD + SUCCESSFUL OUTCOME RadioLinkReconfigurationResponse + UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-unSynchronisedRadioLinkReconfiguration, ddMode tdd } + CRITICALITY reject +} + +-- *** DedicatedMeasurementInitiation *** +dedicatedMeasurementInitiation NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DedicatedMeasurementInitiationRequest + SUCCESSFUL OUTCOME DedicatedMeasurementInitiationResponse + UNSUCCESSFUL OUTCOME DedicatedMeasurementInitiationFailure + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-dedicatedMeasurementInitiation, ddMode common } + CRITICALITY reject +} + +-- *** PhysicalSharedChannelReconfiguration (FDD) *** +physicalSharedChannelReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PhysicalSharedChannelReconfigurationRequestFDD + SUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationResponse + UNSUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-physicalSharedChannelReconfiguration, ddMode fdd } + CRITICALITY reject +} + +-- *** PhysicalSharedChannelReconfiguration (TDD) *** +physicalSharedChannelReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PhysicalSharedChannelReconfigurationRequestTDD + SUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationResponse + UNSUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-physicalSharedChannelReconfiguration, ddMode tdd } + CRITICALITY reject +} + +-- *** InformationExchangeInitiation *** +informationExchangeInitiation NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InformationExchangeInitiationRequest + SUCCESSFUL OUTCOME InformationExchangeInitiationResponse + UNSUCCESSFUL OUTCOME InformationExchangeInitiationFailure + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-informationExchangeInitiation, ddMode common } + CRITICALITY reject +} + +-- *** CellSynchronisationInitiation (TDD only) *** +cellSynchronisationInitiationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationInitiationRequestTDD + SUCCESSFUL OUTCOME CellSynchronisationInitiationResponseTDD + UNSUCCESSFUL OUTCOME CellSynchronisationInitiationFailureTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationInitiation, ddMode tdd } + CRITICALITY reject +} + +-- *** CellSynchronisationReconfiguration (TDD only) *** +cellSynchronisationReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationReconfigurationRequestTDD + SUCCESSFUL OUTCOME CellSynchronisationReconfigurationResponseTDD + UNSUCCESSFUL OUTCOME CellSynchronisationReconfigurationFailureTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationReconfiguration, ddMode tdd } + CRITICALITY reject +} + +-- *** CellSynchronisationAdjustment (TDD only) *** +cellSynchronisationAdjustmentTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationAdjustmentRequestTDD + SUCCESSFUL OUTCOME CellSynchronisationAdjustmentResponseTDD + UNSUCCESSFUL OUTCOME CellSynchronisationAdjustmentFailureTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationAdjustment, ddMode tdd } + CRITICALITY reject +} + +-- Class 2 + +-- *** ResourceStatusIndication *** +resourceStatusIndication NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResourceStatusIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-resourceStatusIndication, ddMode common } + CRITICALITY ignore +} + +-- *** AuditRequired *** +auditRequired NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AuditRequiredIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-auditRequired, ddMode common } + CRITICALITY ignore +} + +-- *** CommonMeasurementReport *** +commonMeasurementReport NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonMeasurementReport + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonMeasurementReport, ddMode common } + CRITICALITY ignore +} + +-- *** CommonMeasurementTermination *** +commonMeasurementTermination NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonMeasurementTerminationRequest + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonMeasurementTermination, ddMode common } + CRITICALITY ignore +} + +-- *** CommonMeasurementFailure *** +commonMeasurementFailure NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CommonMeasurementFailureIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-commonMeasurementFailure, ddMode common } + CRITICALITY ignore +} + +-- *** SynchronisedRadioLinkReconfigurationCommit *** +synchronisedRadioLinkReconfigurationCommit NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationCommit + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationCommit, ddMode common } + CRITICALITY ignore +} + +-- *** SynchronisedRadioReconfigurationCancellation *** +synchronisedRadioLinkReconfigurationCancellation NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkReconfigurationCancel + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationCancellation, ddMode common } + CRITICALITY ignore +} + +-- *** RadioLinkFailure *** +radioLinkFailure NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkFailureIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkFailure, ddMode common } + CRITICALITY ignore +} + +-- *** RadioLinkPreemption *** +radioLinkPreemption NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkPreemptionRequiredIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkPreemption, ddMode common } + CRITICALITY ignore +} + +-- *** RadioLinkRestoration *** +radioLinkRestoration NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkRestoreIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkRestoration, ddMode common } + CRITICALITY ignore +} + +-- *** DedicatedMeasurementReport *** +dedicatedMeasurementReport NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DedicatedMeasurementReport + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-dedicatedMeasurementReport, ddMode common } + CRITICALITY ignore +} + +-- *** DedicatedMeasurementTermination *** +dedicatedMeasurementTermination NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DedicatedMeasurementTerminationRequest + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-dedicatedMeasurementTermination, ddMode common } + CRITICALITY ignore +} + +-- *** DedicatedMeasurementFailure *** +dedicatedMeasurementFailure NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DedicatedMeasurementFailureIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-dedicatedMeasurementFailure, ddMode common } + CRITICALITY ignore +} + +-- *** DLPowerControl (FDD only) *** +downlinkPowerControlFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DL-PowerControlRequest + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-downlinkPowerControl, ddMode fdd } + CRITICALITY ignore +} + +-- *** DLPowerTimeslotControl (TDD only) *** +downlinkPowerTimeslotControl NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DL-PowerTimeslotControlRequest + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-downlinkPowerTimeslotControl, ddMode tdd } + CRITICALITY ignore +} + +-- *** CompressedModeCommand (FDD only) *** +compressedModeCommand NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CompressedModeCommand + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-compressedModeCommand, ddMode fdd } + CRITICALITY ignore +} + +-- *** UnblockResourceIndication *** +unblockResource NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UnblockResourceIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-unblockResource, ddMode common } + CRITICALITY ignore +} + +-- *** ErrorIndication for Dedicated procedures *** +errorIndicationForDedicated NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ErrorIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-errorIndicationForDedicated, ddMode common } + CRITICALITY ignore +} + +-- *** ErrorIndication for Common procedures *** +errorIndicationForCommon NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ErrorIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-errorIndicationForCommon, ddMode common } + CRITICALITY ignore +} + +-- *** CellSynchronisationReporting (TDD only) *** +cellSynchronisationReportingTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationReportTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationReporting, ddMode tdd } + CRITICALITY ignore +} + +-- *** CellSynchronisationTermination (TDD only) *** +cellSynchronisationTerminationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationTerminationRequestTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationTermination, ddMode tdd } + CRITICALITY ignore +} + +-- *** CellSynchronisationFailure (TDD only) *** +cellSynchronisationFailureTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellSynchronisationFailureIndicationTDD + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-cellSynchronisationFailure, ddMode tdd } + CRITICALITY ignore +} + +-- *** PrivateMessage for Dedicated procedures *** +privateMessageForDedicated NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PrivateMessage + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-privateMessageForDedicated, ddMode common } + CRITICALITY ignore +} + +-- *** PrivateMessage for Common procedures *** +privateMessageForCommon NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PrivateMessage + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-privateMessageForCommon, ddMode common } + CRITICALITY ignore +} + +-- *** InformationReporting *** +informationReporting NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InformationReport + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-informationReporting, ddMode common } + CRITICALITY ignore +} + +-- *** InformationExchangeTermination *** +informationExchangeTermination NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InformationExchangeTerminationRequest + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-informationExchangeTermination, ddMode common } + CRITICALITY ignore +} + +-- *** InformationExchangeFailure *** +informationExchangeFailure NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InformationExchangeFailureIndication + MESSAGE DISCRIMINATOR common + PROCEDURE ID { procedureCode id-informationExchangeFailure, ddMode common } + CRITICALITY ignore +} + +-- *** BearerRearrangement *** +bearerRearrangement NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE BearerRearrangementIndication + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-BearerRearrangement, ddMode common } + CRITICALITY ignore +} + +-- *** RadioLinkActivation (FDD) *** +radioLinkActivationFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkActivationCommandFDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkActivation, ddMode fdd } + CRITICALITY ignore +} + +-- *** RadioLinkActivation (TDD) *** +radioLinkActivationTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkActivationCommandTDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkActivation, ddMode tdd } + CRITICALITY ignore +} + +-- *** RadioLinkParameterUpdate (FDD) *** +radioLinkParameterUpdateFDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkParameterUpdateIndicationFDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkParameterUpdate, ddMode fdd } + CRITICALITY ignore +} + +-- *** RadioLinkParameterUpdate (TDD) *** +radioLinkParameterUpdateTDD NBAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RadioLinkParameterUpdateIndicationTDD + MESSAGE DISCRIMINATOR dedicated + PROCEDURE ID { procedureCode id-radioLinkParameterUpdate, ddMode tdd } + CRITICALITY ignore +} + +END + diff --git a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn b/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn deleted file mode 100644 index b9be9934e4..0000000000 --- a/lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Discriptions.asn +++ /dev/null @@ -1,916 +0,0 @@ --- ************************************************************** --- --- Elementary Procedure definitions --- --- ************************************************************** - -NBAP-PDU-Discriptions { -itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) -umts-Access (20) modules (3) nbap (2) version1 (1) nbap-PDU-Descriptions (0) } - -DEFINITIONS AUTOMATIC TAGS ::= - -BEGIN - --- ************************************************************** --- --- IE parameter types from other modules. --- --- ************************************************************** - -IMPORTS - Criticality, - ProcedureID, - MessageDiscriminator, - TransactionID -FROM NBAP-CommonDataTypes - - CommonTransportChannelSetupRequestFDD, - CommonTransportChannelSetupRequestTDD, - CommonTransportChannelSetupResponse, - CommonTransportChannelSetupFailure, - CommonTransportChannelReconfigurationRequestFDD, - CommonTransportChannelReconfigurationRequestTDD, - CommonTransportChannelReconfigurationResponse, - CommonTransportChannelReconfigurationFailure, - CommonTransportChannelDeletionRequest, - CommonTransportChannelDeletionResponse, - BlockResourceRequest, - BlockResourceResponse, - BlockResourceFailure, - UnblockResourceIndication, - AuditFailure, - AuditRequiredIndication, - AuditRequest, - AuditResponse, - CommonMeasurementInitiationRequest, - CommonMeasurementInitiationResponse, - CommonMeasurementInitiationFailure, - CommonMeasurementReport, - CommonMeasurementTerminationRequest, - CommonMeasurementFailureIndication, - CellSetupRequestFDD, - CellSetupRequestTDD, - CellSetupResponse, - CellSetupFailure, - CellReconfigurationRequestFDD, - CellReconfigurationRequestTDD, - CellReconfigurationResponse, - CellReconfigurationFailure, - CellDeletionRequest, - CellDeletionResponse, - InformationExchangeInitiationRequest, - InformationExchangeInitiationResponse, - InformationExchangeInitiationFailure, - InformationReport, - InformationExchangeTerminationRequest, - InformationExchangeFailureIndication, - BearerRearrangementIndication, - ResourceStatusIndication, - SystemInformationUpdateRequest, - SystemInformationUpdateResponse, - SystemInformationUpdateFailure, - ResetRequest, - ResetResponse, - RadioLinkActivationCommandFDD, - RadioLinkActivationCommandTDD, - RadioLinkPreemptionRequiredIndication, - RadioLinkSetupRequestFDD, - RadioLinkSetupRequestTDD, - RadioLinkSetupResponseFDD, - RadioLinkSetupResponseTDD, - RadioLinkSetupFailureFDD, - RadioLinkSetupFailureTDD, - RadioLinkAdditionRequestFDD, - RadioLinkAdditionRequestTDD, - RadioLinkAdditionResponseFDD, - RadioLinkAdditionResponseTDD, - RadioLinkAdditionFailureFDD, - RadioLinkAdditionFailureTDD, - RadioLinkParameterUpdateIndicationFDD, - RadioLinkParameterUpdateIndicationTDD, - RadioLinkReconfigurationPrepareFDD, - RadioLinkReconfigurationPrepareTDD, - RadioLinkReconfigurationReady, - RadioLinkReconfigurationFailure, - RadioLinkReconfigurationCommit, - RadioLinkReconfigurationCancel, - RadioLinkReconfigurationRequestFDD, - RadioLinkReconfigurationRequestTDD, - RadioLinkReconfigurationResponse, - RadioLinkDeletionRequest, - RadioLinkDeletionResponse, - DL-PowerControlRequest, - DL-PowerTimeslotControlRequest, - DedicatedMeasurementInitiationRequest, - DedicatedMeasurementInitiationResponse, - DedicatedMeasurementInitiationFailure, - DedicatedMeasurementReport, - DedicatedMeasurementTerminationRequest, - DedicatedMeasurementFailureIndication, - RadioLinkFailureIndication, - RadioLinkRestoreIndication, - CompressedModeCommand, - ErrorIndication, - PrivateMessage, - PhysicalSharedChannelReconfigurationRequestTDD, - PhysicalSharedChannelReconfigurationRequestFDD, - PhysicalSharedChannelReconfigurationResponse, - PhysicalSharedChannelReconfigurationFailure, - CellSynchronisationInitiationRequestTDD, - CellSynchronisationInitiationResponseTDD, - CellSynchronisationInitiationFailureTDD, - CellSynchronisationReconfigurationRequestTDD, - CellSynchronisationReconfigurationResponseTDD, - CellSynchronisationReconfigurationFailureTDD, - CellSynchronisationAdjustmentRequestTDD, - CellSynchronisationAdjustmentResponseTDD, - CellSynchronisationAdjustmentFailureTDD, - CellSynchronisationReportTDD, - CellSynchronisationTerminationRequestTDD, - CellSynchronisationFailureIndicationTDD -FROM NBAP-PDU-Contents - - id-audit, - id-auditRequired, - id-blockResource, - id-cellDeletion, - id-cellReconfiguration, - id-cellSetup, - id-cellSynchronisationInitiation, - id-cellSynchronisationReconfiguration, - id-cellSynchronisationReporting, - id-cellSynchronisationTermination, - id-cellSynchronisationFailure, - id-commonMeasurementFailure, - id-commonMeasurementInitiation, - id-commonMeasurementReport, - id-commonMeasurementTermination, - id-commonTransportChannelDelete, - id-commonTransportChannelReconfigure, - id-commonTransportChannelSetup, - id-compressedModeCommand, - id-dedicatedMeasurementFailure, - id-dedicatedMeasurementInitiation, - id-dedicatedMeasurementReport, - id-dedicatedMeasurementTermination, - id-downlinkPowerControl, - id-downlinkPowerTimeslotControl, - id-errorIndicationForDedicated, - id-errorIndicationForCommon, - id-informationExchangeFailure, - id-informationExchangeInitiation, - id-informationReporting, - id-informationExchangeTermination, - id-BearerRearrangement, - id-physicalSharedChannelReconfiguration, - id-privateMessageForDedicated, - id-privateMessageForCommon, - id-radioLinkActivation, - id-radioLinkAddition, - id-radioLinkDeletion, - id-radioLinkFailure, - id-radioLinkParameterUpdate, - id-radioLinkPreemption, - id-radioLinkRestoration, - id-radioLinkSetup, - id-reset, - id-resourceStatusIndication, - id-cellSynchronisationAdjustment, - id-synchronisedRadioLinkReconfigurationCancellation, - id-synchronisedRadioLinkReconfigurationCommit, - id-synchronisedRadioLinkReconfigurationPreparation, - id-systemInformationUpdate, - id-unblockResource, - id-unSynchronisedRadioLinkReconfiguration -FROM NBAP-Constants; - --- ************************************************************** --- --- Interface Elementary Procedure Class --- --- ************************************************************** - -NBAP-ELEMENTARY-PROCEDURE ::= CLASS { - &InitiatingMessage , - &SuccessfulOutcome OPTIONAL, - &UnsuccessfulOutcome OPTIONAL, - &Outcome OPTIONAL, - &messageDiscriminator MessageDiscriminator, - &procedureID ProcedureID UNIQUE, - &criticality Criticality DEFAULT ignore -} - -WITH SYNTAX { - INITIATING MESSAGE &InitiatingMessage - [SUCCESSFUL OUTCOME &SuccessfulOutcome] - [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome] - [OUTCOME &Outcome] - MESSAGE DISCRIMINATOR &messageDiscriminator - PROCEDURE ID &procedureID - [CRITICALITY &criticality] -} - --- ************************************************************** --- --- Interface PDU Definition --- --- ************************************************************** - -NBAP-PDU ::= CHOICE { - initiatingMessage InitiatingMessage, - succesfulOutcome SuccessfulOutcome, - unsuccesfulOutcome UnsuccessfulOutcome, - outcome Outcome, - ... -} - -InitiatingMessage ::= SEQUENCE { - procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), - criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - transactionID TransactionID, - value NBAP-ELEMENTARY-PROCEDURE.&InitiatingMessage({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) -} - -SuccessfulOutcome ::= SEQUENCE { - procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), - criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - transactionID TransactionID, - value NBAP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) -} - -UnsuccessfulOutcome ::= SEQUENCE { - procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), - criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - transactionID TransactionID, - value NBAP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) -} - -Outcome ::= SEQUENCE { - procedureID NBAP-ELEMENTARY-PROCEDURE.&procedureID ({NBAP-ELEMENTARY-PROCEDURES}), - criticality NBAP-ELEMENTARY-PROCEDURE.&criticality ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - messageDiscriminator NBAP-ELEMENTARY-PROCEDURE.&messageDiscriminator({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}), - transactionID TransactionID, - value NBAP-ELEMENTARY-PROCEDURE.&Outcome ({NBAP-ELEMENTARY-PROCEDURES}{@procedureID}) -} - --- ************************************************************** --- --- Interface Elementary Procedure List --- --- ************************************************************** - -NBAP-ELEMENTARY-PROCEDURES NBAP-ELEMENTARY-PROCEDURE ::= { - NBAP-ELEMENTARY-PROCEDURES-CLASS-1 | - NBAP-ELEMENTARY-PROCEDURES-CLASS-2 , - ... -} - -NBAP-ELEMENTARY-PROCEDURES-CLASS-1 NBAP-ELEMENTARY-PROCEDURE ::= { - cellSetupFDD | - cellSetupTDD | - cellReconfigurationFDD | - cellReconfigurationTDD | - cellDeletion | - commonTransportChannelSetupFDD | - commonTransportChannelSetupTDD | - commonTransportChannelReconfigureFDD | - commonTransportChannelReconfigureTDD | - commonTransportChannelDelete | - audit | - blockResource | - radioLinkSetupFDD | - radioLinkSetupTDD | - systemInformationUpdate | - commonMeasurementInitiation | - radioLinkAdditionFDD | - radioLinkAdditionTDD | - radioLinkDeletion | - reset | - synchronisedRadioLinkReconfigurationPreparationFDD | - synchronisedRadioLinkReconfigurationPreparationTDD | - unSynchronisedRadioLinkReconfigurationFDD | - unSynchronisedRadioLinkReconfigurationTDD | - dedicatedMeasurementInitiation | - physicalSharedChannelReconfigurationTDD , - ..., - informationExchangeInitiation | - cellSynchronisationInitiationTDD | - cellSynchronisationReconfigurationTDD | - cellSynchronisationAdjustmentTDD | - physicalSharedChannelReconfigurationFDD -} - -NBAP-ELEMENTARY-PROCEDURES-CLASS-2 NBAP-ELEMENTARY-PROCEDURE ::= { - resourceStatusIndication | - auditRequired | - commonMeasurementReport | - commonMeasurementTermination | - commonMeasurementFailure | - synchronisedRadioLinkReconfigurationCommit | - synchronisedRadioLinkReconfigurationCancellation | - radioLinkFailure | - radioLinkPreemption | - radioLinkRestoration | - dedicatedMeasurementReport | - dedicatedMeasurementTermination | - dedicatedMeasurementFailure | - downlinkPowerControlFDD | - downlinkPowerTimeslotControl | - compressedModeCommand | - unblockResource | - errorIndicationForDedicated | - errorIndicationForCommon | - privateMessageForDedicated | - privateMessageForCommon , - ..., - informationReporting | - informationExchangeTermination | - informationExchangeFailure | - cellSynchronisationReportingTDD | - cellSynchronisationTerminationTDD | - cellSynchronisationFailureTDD | - bearerRearrangement | - radioLinkActivationFDD | - radioLinkActivationTDD | - radioLinkParameterUpdateFDD | - radioLinkParameterUpdateTDD -} - --- ************************************************************** --- --- Interface Elementary Procedures --- --- ************************************************************** - --- Class 1 - --- *** CellSetup (FDD) *** -cellSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSetupRequestFDD - SUCCESSFUL OUTCOME CellSetupResponse - UNSUCCESSFUL OUTCOME CellSetupFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSetup, ddMode fdd } - CRITICALITY reject -} - --- *** CellSetup (TDD) *** -cellSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSetupRequestTDD - SUCCESSFUL OUTCOME CellSetupResponse - UNSUCCESSFUL OUTCOME CellSetupFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSetup, ddMode tdd } - CRITICALITY reject -} - --- *** CellReconfiguration(FDD) *** -cellReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellReconfigurationRequestFDD - SUCCESSFUL OUTCOME CellReconfigurationResponse - UNSUCCESSFUL OUTCOME CellReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellReconfiguration, ddMode fdd } - CRITICALITY reject -} - --- *** CellReconfiguration(TDD) *** -cellReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellReconfigurationRequestTDD - SUCCESSFUL OUTCOME CellReconfigurationResponse - UNSUCCESSFUL OUTCOME CellReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellReconfiguration, ddMode tdd } - CRITICALITY reject -} - --- *** CellDeletion *** -cellDeletion NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellDeletionRequest - SUCCESSFUL OUTCOME CellDeletionResponse - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellDeletion, ddMode common } - CRITICALITY reject -} - --- *** CommonTransportChannelSetup (FDD) *** -commonTransportChannelSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonTransportChannelSetupRequestFDD - SUCCESSFUL OUTCOME CommonTransportChannelSetupResponse - UNSUCCESSFUL OUTCOME CommonTransportChannelSetupFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonTransportChannelSetup, ddMode fdd } - CRITICALITY reject -} - --- *** CommonTransportChannelSetup (TDD) *** -commonTransportChannelSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonTransportChannelSetupRequestTDD - SUCCESSFUL OUTCOME CommonTransportChannelSetupResponse - UNSUCCESSFUL OUTCOME CommonTransportChannelSetupFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonTransportChannelSetup, ddMode tdd } - CRITICALITY reject -} - --- *** CommonTransportChannelReconfigure (FDD) *** -commonTransportChannelReconfigureFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonTransportChannelReconfigurationRequestFDD - SUCCESSFUL OUTCOME CommonTransportChannelReconfigurationResponse - UNSUCCESSFUL OUTCOME CommonTransportChannelReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonTransportChannelReconfigure, ddMode fdd } - CRITICALITY reject -} - --- *** CommonTransportChannelReconfigure (TDD) *** -commonTransportChannelReconfigureTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonTransportChannelReconfigurationRequestTDD - SUCCESSFUL OUTCOME CommonTransportChannelReconfigurationResponse - UNSUCCESSFUL OUTCOME CommonTransportChannelReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonTransportChannelReconfigure, ddMode tdd } - CRITICALITY reject -} - --- *** CommonTransportChannelDelete *** -commonTransportChannelDelete NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonTransportChannelDeletionRequest - SUCCESSFUL OUTCOME CommonTransportChannelDeletionResponse - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonTransportChannelDelete, ddMode common } - CRITICALITY reject -} - --- *** Audit *** -audit NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE AuditRequest - SUCCESSFUL OUTCOME AuditResponse - UNSUCCESSFUL OUTCOME AuditFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-audit, ddMode common } - CRITICALITY reject -} - --- *** BlockResourceRequest *** -blockResource NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE BlockResourceRequest - SUCCESSFUL OUTCOME BlockResourceResponse - UNSUCCESSFUL OUTCOME BlockResourceFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-blockResource, ddMode common } - CRITICALITY reject -} - --- *** RadioLinkSetup (FDD) *** -radioLinkSetupFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkSetupRequestFDD - SUCCESSFUL OUTCOME RadioLinkSetupResponseFDD - UNSUCCESSFUL OUTCOME RadioLinkSetupFailureFDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-radioLinkSetup, ddMode fdd } - CRITICALITY reject -} - --- *** RadioLinkSetup (TDD) *** -radioLinkSetupTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkSetupRequestTDD - SUCCESSFUL OUTCOME RadioLinkSetupResponseTDD - UNSUCCESSFUL OUTCOME RadioLinkSetupFailureTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-radioLinkSetup, ddMode tdd } - CRITICALITY reject -} - --- *** SystemInformationUpdate *** -systemInformationUpdate NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE SystemInformationUpdateRequest - SUCCESSFUL OUTCOME SystemInformationUpdateResponse - UNSUCCESSFUL OUTCOME SystemInformationUpdateFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-systemInformationUpdate, ddMode common } - CRITICALITY reject -} - --- *** Reset *** -reset NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE ResetRequest - SUCCESSFUL OUTCOME ResetResponse - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-reset, ddMode common } - CRITICALITY reject -} - --- *** CommonMeasurementInitiation *** -commonMeasurementInitiation NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonMeasurementInitiationRequest - SUCCESSFUL OUTCOME CommonMeasurementInitiationResponse - UNSUCCESSFUL OUTCOME CommonMeasurementInitiationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonMeasurementInitiation, ddMode common } - CRITICALITY reject -} - --- *** RadioLinkAddition (FDD) *** -radioLinkAdditionFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkAdditionRequestFDD - SUCCESSFUL OUTCOME RadioLinkAdditionResponseFDD - UNSUCCESSFUL OUTCOME RadioLinkAdditionFailureFDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkAddition, ddMode fdd } - CRITICALITY reject -} - --- *** RadioLinkAddition (TDD) *** -radioLinkAdditionTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkAdditionRequestTDD - SUCCESSFUL OUTCOME RadioLinkAdditionResponseTDD - UNSUCCESSFUL OUTCOME RadioLinkAdditionFailureTDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkAddition, ddMode tdd } - CRITICALITY reject -} - --- *** RadioLinkDeletion *** -radioLinkDeletion NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkDeletionRequest - SUCCESSFUL OUTCOME RadioLinkDeletionResponse - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkDeletion, ddMode common } - CRITICALITY reject -} - --- *** SynchronisedRadioLinkReconfigurationPreparation (FDD) *** -synchronisedRadioLinkReconfigurationPreparationFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationPrepareFDD - SUCCESSFUL OUTCOME RadioLinkReconfigurationReady - UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationPreparation, ddMode fdd } - CRITICALITY reject -} - --- *** SynchronisedRadioLinkReconfigurationPreparation (TDD) *** -synchronisedRadioLinkReconfigurationPreparationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationPrepareTDD - SUCCESSFUL OUTCOME RadioLinkReconfigurationReady - UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationPreparation, ddMode tdd } - CRITICALITY reject -} - --- *** UnSynchronisedRadioLinkReconfiguration (FDD) *** -unSynchronisedRadioLinkReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationRequestFDD - SUCCESSFUL OUTCOME RadioLinkReconfigurationResponse - UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-unSynchronisedRadioLinkReconfiguration, ddMode fdd } - CRITICALITY reject -} - --- *** UnSynchronisedRadioLinkReconfiguration (TDD) *** -unSynchronisedRadioLinkReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationRequestTDD - SUCCESSFUL OUTCOME RadioLinkReconfigurationResponse - UNSUCCESSFUL OUTCOME RadioLinkReconfigurationFailure - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-unSynchronisedRadioLinkReconfiguration, ddMode tdd } - CRITICALITY reject -} - --- *** DedicatedMeasurementInitiation *** -dedicatedMeasurementInitiation NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DedicatedMeasurementInitiationRequest - SUCCESSFUL OUTCOME DedicatedMeasurementInitiationResponse - UNSUCCESSFUL OUTCOME DedicatedMeasurementInitiationFailure - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-dedicatedMeasurementInitiation, ddMode common } - CRITICALITY reject -} - --- *** PhysicalSharedChannelReconfiguration (FDD) *** -physicalSharedChannelReconfigurationFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE PhysicalSharedChannelReconfigurationRequestFDD - SUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationResponse - UNSUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-physicalSharedChannelReconfiguration, ddMode fdd } - CRITICALITY reject -} - --- *** PhysicalSharedChannelReconfiguration (TDD) *** -physicalSharedChannelReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE PhysicalSharedChannelReconfigurationRequestTDD - SUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationResponse - UNSUCCESSFUL OUTCOME PhysicalSharedChannelReconfigurationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-physicalSharedChannelReconfiguration, ddMode tdd } - CRITICALITY reject -} - --- *** InformationExchangeInitiation *** -informationExchangeInitiation NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE InformationExchangeInitiationRequest - SUCCESSFUL OUTCOME InformationExchangeInitiationResponse - UNSUCCESSFUL OUTCOME InformationExchangeInitiationFailure - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-informationExchangeInitiation, ddMode common } - CRITICALITY reject -} - --- *** CellSynchronisationInitiation (TDD only) *** -cellSynchronisationInitiationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationInitiationRequestTDD - SUCCESSFUL OUTCOME CellSynchronisationInitiationResponseTDD - UNSUCCESSFUL OUTCOME CellSynchronisationInitiationFailureTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationInitiation, ddMode tdd } - CRITICALITY reject -} - --- *** CellSynchronisationReconfiguration (TDD only) *** -cellSynchronisationReconfigurationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationReconfigurationRequestTDD - SUCCESSFUL OUTCOME CellSynchronisationReconfigurationResponseTDD - UNSUCCESSFUL OUTCOME CellSynchronisationReconfigurationFailureTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationReconfiguration, ddMode tdd } - CRITICALITY reject -} - --- *** CellSynchronisationAdjustment (TDD only) *** -cellSynchronisationAdjustmentTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationAdjustmentRequestTDD - SUCCESSFUL OUTCOME CellSynchronisationAdjustmentResponseTDD - UNSUCCESSFUL OUTCOME CellSynchronisationAdjustmentFailureTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationAdjustment, ddMode tdd } - CRITICALITY reject -} - --- Class 2 - --- *** ResourceStatusIndication *** -resourceStatusIndication NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE ResourceStatusIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-resourceStatusIndication, ddMode common } - CRITICALITY ignore -} - --- *** AuditRequired *** -auditRequired NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE AuditRequiredIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-auditRequired, ddMode common } - CRITICALITY ignore -} - --- *** CommonMeasurementReport *** -commonMeasurementReport NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonMeasurementReport - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonMeasurementReport, ddMode common } - CRITICALITY ignore -} - --- *** CommonMeasurementTermination *** -commonMeasurementTermination NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonMeasurementTerminationRequest - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonMeasurementTermination, ddMode common } - CRITICALITY ignore -} - --- *** CommonMeasurementFailure *** -commonMeasurementFailure NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CommonMeasurementFailureIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-commonMeasurementFailure, ddMode common } - CRITICALITY ignore -} - --- *** SynchronisedRadioLinkReconfigurationCommit *** -synchronisedRadioLinkReconfigurationCommit NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationCommit - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationCommit, ddMode common } - CRITICALITY ignore -} - --- *** SynchronisedRadioReconfigurationCancellation *** -synchronisedRadioLinkReconfigurationCancellation NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkReconfigurationCancel - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-synchronisedRadioLinkReconfigurationCancellation, ddMode common } - CRITICALITY ignore -} - --- *** RadioLinkFailure *** -radioLinkFailure NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkFailureIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkFailure, ddMode common } - CRITICALITY ignore -} - --- *** RadioLinkPreemption *** -radioLinkPreemption NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkPreemptionRequiredIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkPreemption, ddMode common } - CRITICALITY ignore -} - --- *** RadioLinkRestoration *** -radioLinkRestoration NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkRestoreIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkRestoration, ddMode common } - CRITICALITY ignore -} - --- *** DedicatedMeasurementReport *** -dedicatedMeasurementReport NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DedicatedMeasurementReport - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-dedicatedMeasurementReport, ddMode common } - CRITICALITY ignore -} - --- *** DedicatedMeasurementTermination *** -dedicatedMeasurementTermination NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DedicatedMeasurementTerminationRequest - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-dedicatedMeasurementTermination, ddMode common } - CRITICALITY ignore -} - --- *** DedicatedMeasurementFailure *** -dedicatedMeasurementFailure NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DedicatedMeasurementFailureIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-dedicatedMeasurementFailure, ddMode common } - CRITICALITY ignore -} - --- *** DLPowerControl (FDD only) *** -downlinkPowerControlFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DL-PowerControlRequest - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-downlinkPowerControl, ddMode fdd } - CRITICALITY ignore -} - --- *** DLPowerTimeslotControl (TDD only) *** -downlinkPowerTimeslotControl NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE DL-PowerTimeslotControlRequest - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-downlinkPowerTimeslotControl, ddMode tdd } - CRITICALITY ignore -} - --- *** CompressedModeCommand (FDD only) *** -compressedModeCommand NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CompressedModeCommand - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-compressedModeCommand, ddMode fdd } - CRITICALITY ignore -} - --- *** UnblockResourceIndication *** -unblockResource NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE UnblockResourceIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-unblockResource, ddMode common } - CRITICALITY ignore -} - --- *** ErrorIndication for Dedicated procedures *** -errorIndicationForDedicated NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE ErrorIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-errorIndicationForDedicated, ddMode common } - CRITICALITY ignore -} - --- *** ErrorIndication for Common procedures *** -errorIndicationForCommon NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE ErrorIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-errorIndicationForCommon, ddMode common } - CRITICALITY ignore -} - --- *** CellSynchronisationReporting (TDD only) *** -cellSynchronisationReportingTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationReportTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationReporting, ddMode tdd } - CRITICALITY ignore -} - --- *** CellSynchronisationTermination (TDD only) *** -cellSynchronisationTerminationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationTerminationRequestTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationTermination, ddMode tdd } - CRITICALITY ignore -} - --- *** CellSynchronisationFailure (TDD only) *** -cellSynchronisationFailureTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE CellSynchronisationFailureIndicationTDD - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-cellSynchronisationFailure, ddMode tdd } - CRITICALITY ignore -} - --- *** PrivateMessage for Dedicated procedures *** -privateMessageForDedicated NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE PrivateMessage - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-privateMessageForDedicated, ddMode common } - CRITICALITY ignore -} - --- *** PrivateMessage for Common procedures *** -privateMessageForCommon NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE PrivateMessage - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-privateMessageForCommon, ddMode common } - CRITICALITY ignore -} - --- *** InformationReporting *** -informationReporting NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE InformationReport - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-informationReporting, ddMode common } - CRITICALITY ignore -} - --- *** InformationExchangeTermination *** -informationExchangeTermination NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE InformationExchangeTerminationRequest - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-informationExchangeTermination, ddMode common } - CRITICALITY ignore -} - --- *** InformationExchangeFailure *** -informationExchangeFailure NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE InformationExchangeFailureIndication - MESSAGE DISCRIMINATOR common - PROCEDURE ID { procedureCode id-informationExchangeFailure, ddMode common } - CRITICALITY ignore -} - --- *** BearerRearrangement *** -bearerRearrangement NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE BearerRearrangementIndication - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-BearerRearrangement, ddMode common } - CRITICALITY ignore -} - --- *** RadioLinkActivation (FDD) *** -radioLinkActivationFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkActivationCommandFDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkActivation, ddMode fdd } - CRITICALITY ignore -} - --- *** RadioLinkActivation (TDD) *** -radioLinkActivationTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkActivationCommandTDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkActivation, ddMode tdd } - CRITICALITY ignore -} - --- *** RadioLinkParameterUpdate (FDD) *** -radioLinkParameterUpdateFDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkParameterUpdateIndicationFDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkParameterUpdate, ddMode fdd } - CRITICALITY ignore -} - --- *** RadioLinkParameterUpdate (TDD) *** -radioLinkParameterUpdateTDD NBAP-ELEMENTARY-PROCEDURE ::= { - INITIATING MESSAGE RadioLinkParameterUpdateIndicationTDD - MESSAGE DISCRIMINATOR dedicated - PROCEDURE ID { procedureCode id-radioLinkParameterUpdate, ddMode tdd } - CRITICALITY ignore -} - -END - diff --git a/lib/asn1/test/asn1_SUITE_data/test_records.erl b/lib/asn1/test/asn1_SUITE_data/test_records.erl index 9fd07c1449..afb1c8c80b 100644 --- a/lib/asn1/test/asn1_SUITE_data/test_records.erl +++ b/lib/asn1/test/asn1_SUITE_data/test_records.erl @@ -25,7 +25,7 @@ -define(line,put(test_server_loc,{?MODULE,?LINE}),). --include("NBAP-PDU-Discriptions.hrl"). +-include("NBAP-PDU-Descriptions.hrl"). -include("NBAP-PDU-Contents.hrl"). -include("NBAP-Containers.hrl"). -include("NBAP-CommonDataTypes.hrl"). diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl index 1af283af42..8d61ca18ce 100644 --- a/lib/asn1/test/testNBAPsystem.erl +++ b/lib/asn1/test/testNBAPsystem.erl @@ -84,7 +84,7 @@ compile(Config, Options) -> M <- ["NBAP-CommonDataTypes.asn", "NBAP-IEs.asn", "NBAP-PDU-Contents.asn", - "NBAP-PDU-Discriptions.asn", + "NBAP-PDU-Descriptions.asn", "NBAP-Constants.asn", "NBAP-Containers.asn"]], asn1_test_lib:compile_all(Fs, Config, Options), @@ -98,16 +98,16 @@ test(_Erule,Config) -> ticket_5812(Config) -> Msg = v_5812(), - {ok,B2} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg), + {ok,B2} = 'NBAP-PDU-Descriptions':encode('NBAP-PDU', Msg), V = <<0,28,74,0,3,48,0,0,1,0,123,64,41,0,0,0,126,64,35,95,208,2,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,145,0,1,205,0,0,0,0,2,98,64,1,128>>, ok = compare(V,B2), - {ok,Msg2} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B2), + {ok,Msg2} = 'NBAP-PDU-Descriptions':decode('NBAP-PDU', B2), ok = check_record_names(Msg2,Config). enc_audit_req_msg() -> Msg = {initiatingMessage, audit_req_msg()}, - {ok,B} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg), - {ok,_Msg} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B), + {ok,B} = 'NBAP-PDU-Descriptions':encode('NBAP-PDU', Msg), + {ok,_Msg} = 'NBAP-PDU-Descriptions':decode('NBAP-PDU', B), {initiatingMessage, #'InitiatingMessage'{value=#'AuditRequest'{protocolIEs=[{_,114,ignore,_}], protocolExtensions = asn1_NOVALUE}}} = _Msg, @@ -116,8 +116,8 @@ enc_audit_req_msg() -> cell_setup_req_msg_test() -> Msg = {initiatingMessage, cell_setup_req_msg()}, - {ok,B} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg), - {ok,_Msg} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B), + {ok,B} = 'NBAP-PDU-Descriptions':encode('NBAP-PDU', Msg), + {ok,_Msg} = 'NBAP-PDU-Descriptions':decode('NBAP-PDU', B), io:format("Msg: ~P~n~n_Msg: ~P~n",[Msg,15,_Msg,15]), ok. -- cgit v1.2.3 From 13b6d01213c9ff39deafc3dd7672cc96dd6e8ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 25 Jan 2017 07:26:33 +0100 Subject: testMultipleLevels: Use asn1_test_lib:roundtrip() --- lib/asn1/test/testMultipleLevels.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/asn1/test/testMultipleLevels.erl b/lib/asn1/test/testMultipleLevels.erl index c610e59f3d..e9d83665aa 100644 --- a/lib/asn1/test/testMultipleLevels.erl +++ b/lib/asn1/test/testMultipleLevels.erl @@ -24,5 +24,7 @@ main(_) -> Data = {'Top',{short,"abc"},{long,"a long string follows here"}}, - {ok,B} = 'MultipleLevels':encode('Top', Data), - {ok,Data} = 'MultipleLevels':decode('Top', iolist_to_binary(B)). + roundtrip('Top', Data). + +roundtrip(T, V) -> + asn1_test_lib:roundtrip('MultipleLevels', T, V). -- cgit v1.2.3 From 90d2c1140409dec7f28c66922b69a16b7463139b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 25 Jan 2017 14:48:31 +0100 Subject: Refactor h323test.erl to simplify debugging --- lib/asn1/test/h323test.erl | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl index 935af0ba09..41a9159335 100644 --- a/lib/asn1/test/h323test.erl +++ b/lib/asn1/test/h323test.erl @@ -27,6 +27,8 @@ run(per) -> run(); run(_Rules) -> ok. run() -> + roundtrip('EndpointType', endpoint()), + roundtrip('Alerting-UUIE', alerting_uuie()), roundtrip('H323-UserInformation', alerting_val(), alerting_enc()), roundtrip('H323-UserInformation', connect_val(), connect_enc()), general_string(), @@ -36,18 +38,24 @@ alerting_val() -> {'H323-UserInformation', {'H323-UU-PDU', {alerting, - {'Alerting-UUIE', - {0,0,8,2250,0,2}, - {'EndpointType',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, - asn1_NOVALUE,asn1_NOVALUE, - {'TerminalInfo',asn1_NOVALUE}, - false,false}, - asn1_NOVALUE, - {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}, - asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}}, + alerting_uuie()}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, asn1_NOVALUE}. +endpoint() -> + {'EndpointType',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, + asn1_NOVALUE,asn1_NOVALUE, + {'TerminalInfo',asn1_NOVALUE}, + false,false}. + +alerting_uuie() -> + {'Alerting-UUIE', + {0,0,8,2250,0,2}, + endpoint(), + asn1_NOVALUE, + {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}, + asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}. + alerting_enc() -> "0380060008914a0002020120110000000000000000000000000000000000". @@ -82,6 +90,9 @@ general_string() -> UI = <<109,64,1,57>>, {ok, _V} = 'MULTIMEDIA-SYSTEM-CONTROL':decode(Type, UI). +roundtrip(T, V) -> + asn1_test_lib:roundtrip('H323-MESSAGES', T, V). + roundtrip(T, V, HexString) -> Enc = asn1_test_lib:hex_to_bin(HexString), Enc = asn1_test_lib:roundtrip_enc('H323-MESSAGES', T, V), -- cgit v1.2.3 From 63ac33729f3df5b7cb1789f78365777d0a6034ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 26 Jan 2017 07:40:30 +0100 Subject: Add additional tests of Extension Addition Groups --- lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 | 11 +++++++ lib/asn1/test/testSeqExtension.erl | 38 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'lib') diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 index 5fda19303a..e866ef2f4f 100644 --- a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 @@ -48,6 +48,17 @@ SeqExt6 ::= SEQUENCE [[ i6 [106] INTEGER, i7 [107] INTEGER ]] } +SeqExt7 ::= SEQUENCE +{ + -- The spaces between the ellipsis and the comma will prevent them + -- from being removed. + ... , + [[ a INTEGER (0..65535) OPTIONAL, + b OCTET STRING OPTIONAL, + c BOOLEAN + ]] +} + SeqExt1X ::= XSeqExt1 SeqExt2X ::= XSeqExt2 diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl index f7885cb002..be1d1c2490 100644 --- a/lib/asn1/test/testSeqExtension.erl +++ b/lib/asn1/test/testSeqExtension.erl @@ -31,6 +31,7 @@ -record('SeqExt4',{bool, int}). -record('SeqExt5',{name, shoesize}). -record('SeqExt6',{i1,i2,i3,i4,i5,i6,i7}). +-record('SeqExt7',{a=asn1_NOVALUE,b=asn1_NOVALUE,c}). -record('SuperSeq',{s1,s2,s3,s4,s5,s6,i}). main(Erule, DataDir, Opts) -> @@ -45,8 +46,35 @@ main(Erule, DataDir, Opts) -> roundtrip('SeqExt4', #'SeqExt4'{bool=true,int=12345}), roundtrip('SeqExt4', #'SeqExt4'{bool=false,int=123456}), + case Erule of + ber -> + %% BER currently does not handle Extension Addition Groups + %% correctly. + ok; + _ -> + v_roundtrip3('SeqExt5', #'SeqExt5'{name=asn1_NOVALUE, + shoesize=asn1_NOVALUE}, + Erule, #{per=>"00", + uper=>"00"}), + v_roundtrip3('SeqExt7', #'SeqExt7'{c=asn1_NOVALUE}, + Erule, #{per=>"00", + uper=>"00"}) + end, roundtrip('SeqExt5', #'SeqExt5'{name = <<"Arne">>,shoesize=47}), + v_roundtrip3('SeqExt7', #'SeqExt7'{c=false}, + Erule, #{per=>"80800100", + uper=>"80808000"}), + v_roundtrip3('SeqExt7', #'SeqExt7'{c=true}, + Erule, #{per=>"80800120", + uper=>"80809000"}), + v_roundtrip3('SeqExt7', #'SeqExt7'{a=777,b = <<16#AA>>,c=false}, + Erule, #{per=>"808006C0 030901AA 00", + uper=>"8082E061 20354000"}), + v_roundtrip3('SeqExt7', #'SeqExt7'{a=8888,c=false}, + Erule, #{per=>"80800480 22B800", + uper=>"8081C457 0000"}), + %% Encode a value with this version of the specification. BigInt = 128638468966, SuperSeq = #'SuperSeq'{s1=#'SeqExt1'{}, @@ -106,6 +134,7 @@ main(Erule, DataDir, Opts) -> v_roundtrip2(Erule, 'SeqExt130', list_to_tuple(['SeqExt130'| lists:duplicate(129, asn1_NOVALUE)++[199]])), + ok. roundtrip(Type, Value) -> @@ -118,6 +147,15 @@ v_roundtrip2(Erule, Type, Value) -> roundtrip2(Type, Value) -> asn1_test_lib:roundtrip_enc('SeqExtension2', Type, Value). +v_roundtrip3(Type, Value, Erule, Map) -> + case maps:find(Erule, Map) of + {ok,Hex} -> + Encoded = asn1_test_lib:hex_to_bin(Hex), + Encoded = asn1_test_lib:roundtrip_enc('SeqExtension', Type, Value); + error -> + asn1_test_lib:roundtrip('SeqExtension', Type, Value) + end. + v(ber, 'SeqExt66') -> "30049F41 017D"; v(per, 'SeqExt66') -> "C0420000 00000000 00004001 FA"; v(uper, 'SeqExt66') -> "D0800000 00000000 00101FA0"; -- cgit v1.2.3 From 3ca2800ee4ff086eec7fe51b5316cda4779414af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 13 Jan 2017 15:14:28 +0100 Subject: Break apart function with 6 arguments As a preparation for future changes, simplify gen_dec_constructed_imm_2/6 by breaking it apart to two functions. --- lib/asn1/src/asn1ct_constructed_per.erl | 53 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index a34b25182c..a3a0d4c3c2 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -306,34 +306,33 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) -> {DecObjInf,_,_} = ObjSetInfo, EmitComp = gen_dec_components_call(Erule, Typename, CompList, DecObjInf, Ext, length(Optionals)), - EmitRest = fun({AccTerm,AccBytes}) -> - gen_dec_constructed_imm_2(Erule, Typename, - CompList, - ObjSetInfo, - AccTerm, AccBytes) - end, - [EmitExt,EmitOpt|EmitComp++[{safe,EmitRest}]]. + EmitObjSets = gen_dec_objsets_fun(Erule, ObjSetInfo), + EmitPack = fun(_) -> + gen_dec_pack(Typename, CompList) + end, + RestGroup = {group,[{safe,EmitObjSets},{safe,EmitPack}]}, + [EmitExt,EmitOpt|EmitComp++[RestGroup]]. + +gen_dec_objsets_fun(Erule, ObjSetInfo) -> + fun({AccTerm,AccBytes}) -> + {_,_UniqueFName,ValueIndex} = ObjSetInfo, + case {AccTerm,AccBytes} of + {[],[]} -> + ok; + {_,[]} -> + ok; + {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} -> + ValueMatch = value_match(ValueIndex, Term), + _ = [begin + gen_dec_open_type(Erule, ValueMatch, ObjSet, + LeadingAttr, T), + emit([com,nl]) + end || T <- ListOfOpenTypes], + ok + end + end. -gen_dec_constructed_imm_2(Erule, Typename, CompList, - ObjSetInfo, AccTerm, AccBytes) -> - {_,_UniqueFName,ValueIndex} = ObjSetInfo, - case {AccTerm,AccBytes} of - {[],[]} -> - ok; - {_,[]} -> - ok; - {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} -> - ValueMatch = value_match(ValueIndex, Term), - _ = [begin - gen_dec_open_type(Erule, ValueMatch, ObjSet, - LeadingAttr, T), - emit([com,nl]) - end || T <- ListOfOpenTypes], - ok - end, - %% we don't return named lists any more Cnames = mkcnamelist(CompList), - demit({"Result = "}), %dbg - %% return value as record +gen_dec_pack(Typename, CompList) -> RecordName = record_name(Typename), case Typename of ['EXTERNAL'] -> -- cgit v1.2.3 From 75f9ee5823d57bfb60febc7371920a6858c895fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 13 Jan 2017 14:27:59 +0100 Subject: Clean up handling of textual order The to_encoding_order/1 function can be eliminated if we incorporate its functionality into textual_order/2. textual_order/2 has a workaround for TermList being longer than OrderList. Remove the workaround, because the code being generated would certainly be wrong (better let the compiler crash and receive a bug report if it happens). The workaround was not necessary to successfully compile the entire Erlang/OTP and to run the asn1 test suite. --- lib/asn1/src/asn1ct_constructed_per.erl | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index a3a0d4c3c2..e9cfc56fa5 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -350,7 +350,7 @@ gen_dec_pack(Typename, CompList) -> %% CompList is used here because we don't want %% ExtensionAdditionGroups to be wrapped in SEQUENCES when %% we are ordering the fields according to textual order - mkvlist(textual_order(to_encoding_order(CompList),asn1ct_name:all(term))), + mkvlist(textual_order(CompList, asn1ct_name:all(term))), emit("},") end, emit({{curr,bytes},"}"}). @@ -378,17 +378,16 @@ filter_ext_add_groups([H|T], Acc) -> filter_ext_add_groups(T, [H|Acc]); filter_ext_add_groups([], Acc) -> Acc. -textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) -> +textual_order([#'ComponentType'{textual_order=undefined}|_], TermList) -> TermList; -textual_order(CompList,TermList) when is_list(CompList) -> +textual_order(CompList, TermList) when is_list(CompList) -> OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList], - [Term||{_,Term}<- - lists:sort(lists:zip(OrderList, - lists:sublist(TermList,length(OrderList))))]; - %% sublist is just because Termlist can sometimes be longer than - %% OrderList, which it really shouldn't -textual_order({Root,Ext},TermList) -> - textual_order(Root ++ Ext,TermList). + Zipped = lists:sort(lists:zip(OrderList, TermList)), + [Term || {_,Term} <- Zipped]; +textual_order({Root,Ext}, TermList) -> + textual_order(Root ++ Ext, TermList); +textual_order({R1,Ext,R2}, TermList) -> + textual_order(R1 ++ R2 ++ Ext, TermList). to_textual_order({Root,Ext}) -> {to_textual_order(Root),Ext}; @@ -778,13 +777,6 @@ get_optionality_pos(TextPos,OptTable) -> no_num end. -to_encoding_order(Cs) when is_list(Cs) -> - Cs; -to_encoding_order(Cs = {_Root,_Ext}) -> - Cs; -to_encoding_order({R1,Ext,R2}) -> - {R1++R2,Ext}. - add_textual_order(Cs) when is_list(Cs) -> {NewCs,_} = add_textual_order1(Cs,1), NewCs; -- cgit v1.2.3 From 13d58883d9e8c992d4d07aff31aaf8df366f12b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Jan 2017 08:43:44 +0100 Subject: Refactor gen_encode_constructed_imm/3 Introduce helper functions to simplify and reduce the size of gen_encode_constructed_imm/3. --- lib/asn1/src/asn1ct_constructed_per.erl | 113 +++++++++++++++----------------- 1 file changed, 54 insertions(+), 59 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index e9cfc56fa5..61662e67df 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -51,24 +51,7 @@ gen_encode_constructed(Erule, Typename, #type{}=D) -> emit([".",nl]). gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> - {ExtAddGroup,TmpCompList,TableConsInfo} = - case D#type.def of - #'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} -> - {ExtAddGroup0,CL,TCI}; - #'SET'{tablecinf=TCI,components=CL} -> - {undefined,CL,TCI} - end, - - CompList = case ExtAddGroup of - undefined -> - TmpCompList; - _ when is_integer(ExtAddGroup) -> - %% This is a fake SEQUENCE representing an ExtensionAdditionGroup - %% Reset the textual order so we get the right - %% index of the components - [Comp#'ComponentType'{textual_order=undefined}|| - Comp<-TmpCompList] - end, + {CompList,TableConsInfo} = enc_complist(D), ExternalImm = case Typename of ['EXTERNAL'] -> @@ -94,44 +77,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> _ -> [] end, - {EncObj,ObjSetImm} = - case TableConsInfo of - #simpletableattributes{usedclassfield=Used, - uniqueclassfield=Unique} when Used /= Unique -> - {false,[]}; - %% ObjectSet, name of the object set in constraints - %% - %%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint - #simpletableattributes{objectsetname=ObjectSet, - c_name=AttrN, - c_index=N, - usedclassfield=UniqueFieldName, - uniqueclassfield=UniqueFieldName, - valueindex=ValueIndex0 - } -> %% N is index of attribute that determines constraint - {Module,ObjSetName} = ObjectSet, - #typedef{typespec=#'ObjectSet'{gen=Gen}} = - asn1_db:dbget(Module, ObjSetName), - case Gen of - true -> - ValueIndex = ValueIndex0 ++ [{N+1,top}], - Val = make_var(val), - {ObjSetImm0,Dst} = enc_dig_out_value(ValueIndex, Val), - {{AttrN,Dst},ObjSetImm0}; - false -> - {false,[]} - end; - _ -> - case D#type.tablecinf of - [{objfun,_}|_] -> - %% when the simpletableattributes was at an outer - %% level and the objfun has been passed through the - %% function call - {{"got objfun through args",{var,"ObjFun"}},[]}; - _ -> - {false,[]} - end - end, + {EncObj,ObjSetImm} = enc_table(Gen, TableConsInfo, D), ImmSetExt = case Ext of {ext,_Pos,NumExt2} when NumExt2 > 0 -> @@ -145,6 +91,55 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> ExternalImm ++ ExtImm ++ ObjSetImm ++ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody). +enc_complist(#type{def=Def}) -> + case Def of + #'SEQUENCE'{tablecinf=TCI,components=CL0,extaddgroup=ExtAddGroup} -> + case ExtAddGroup of + undefined -> + {CL0,TCI}; + _ when is_integer(ExtAddGroup) -> + %% This is a fake SEQUENCE representing an + %% ExtensionAdditionGroup. Renumber the textual + %% order so we get the right index of the + %% components. + CL = add_textual_order(CL0), + {CL,TCI} + end; + #'SET'{tablecinf=TCI,components=CL} -> + {CL,TCI} + end. + +enc_table(Gen, #simpletableattributes{objectsetname=ObjectSet, + c_name=AttrN, + c_index=N, + usedclassfield=UniqueFieldName, + uniqueclassfield=UniqueFieldName, + valueindex=ValueIndex0}, _) -> + {Module,ObjSetName} = ObjectSet, + #typedef{typespec=#'ObjectSet'{gen=MustGen}} = + asn1_db:dbget(Module, ObjSetName), + case MustGen of + true -> + ValueIndex = ValueIndex0 ++ [{N+1,top}], + Val = make_var(val), + {ObjSetImm,Dst} = enc_dig_out_value(Gen, ValueIndex, Val), + {{AttrN,Dst},ObjSetImm}; + false -> + {false,[]} + end; +enc_table(_Gen, #simpletableattributes{}, _) -> + {false,[]}; +enc_table(_Gen, _, #type{tablecinf=TCInf}) -> + case TCInf of + [{objfun,_}|_] -> + %% The simpletableattributes was at an outer + %% level and the objfun has been passed through the + %% function call. + {{"got objfun through args",{var,"ObjFun"}},[]}; + _ -> + {false,[]} + end. + gen_encode_extaddgroup(CompList) -> case extgroup_pos_and_length(CompList) of {extgrouppos,[]} -> @@ -1777,10 +1772,10 @@ value_match1(Value,[],Acc,Depth) -> value_match1(Value,[{VI,_}|VIs],Acc,Depth) -> value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1). -enc_dig_out_value([], Value) -> +enc_dig_out_value(_Gen, [], Value) -> {[],Value}; -enc_dig_out_value([{N,_}|T], Value) -> - {Imm0,Dst0} = enc_dig_out_value(T, Value), +enc_dig_out_value(Gen, [{N,_}|T], Value) -> + {Imm0,Dst0} = enc_dig_out_value(Gen, T, Value), {Imm,Dst} = asn1ct_imm:enc_element(N, Dst0), {Imm0++Imm,Dst}. -- cgit v1.2.3 From bfaf9c12ae3f84d71518697258734b0c9f5556fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Jan 2017 10:01:18 +0100 Subject: asn1ct_check: Number the components in INSTANCE OF asn1ct_check numbers all components in SEQUENCEs and SETs, except for the associated sequence for INSTANCE OF. Remove this exception so that the code generation pass can depend on SEQUENCEs being numbered. --- lib/asn1/src/asn1ct_check.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index f2c895bfaa..a01a22ddc4 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -4192,7 +4192,7 @@ iof_associated_type1(S,C) -> %% fieldname=[{typefieldreference,'Type'}], fieldname={'Type',[]}, type=Typefield_type}, - IOFComponents = + IOFComponents0 = [#'ComponentType'{name='type-id', typespec=#type{tag=C1TypeTag, def=ObjectIdentifier, @@ -4209,6 +4209,7 @@ iof_associated_type1(S,C) -> tablecinf=Comp2tablecinf}, prop=mandatory, tags=[{'CONTEXT',0}]}], + IOFComponents = textual_order(IOFComponents0), #'SEQUENCE'{tablecinf=TableCInf, components=simplify_comps(IOFComponents)}. -- cgit v1.2.3 From 5fa478d4550d8a55b3c89f8f6a7deef5b6fd9b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 17 Jan 2017 15:21:41 +0100 Subject: Simplify gen_enc_components_call() and friends --- lib/asn1/src/asn1ct_constructed_per.erl | 74 ++++++++++++++------------------- 1 file changed, 31 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 61662e67df..1782ca11b4 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -796,58 +796,47 @@ add_textual_order1(Cs,NumIn) -> end, NumIn,Cs). -gen_enc_components_call(Erule,TopType,{Root,ExtList}, DynamicEnc,Ext) -> - gen_enc_components_call(Erule,TopType,{Root,ExtList,[]}, DynamicEnc,Ext); -gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2}, DynamicEnc,Ext) -> - %% The type has extensionmarker - {Imm0,Rpos} = gen_enc_components_call1(Erule,TopType,Root++Root2,1, DynamicEnc,noext,[]), +gen_enc_components_call(Erule, TopType, {Root,ExtList}, DynamicEnc, Ext) -> + gen_enc_components_call(Erule, TopType, {Root,ExtList,[]}, DynamicEnc, Ext); +gen_enc_components_call(Erule, TopType, {R1,ExtList0,R2}=CL, DynamicEnc, Ext) -> + Root = R1 ++ R2, + Imm0 = gen_enc_components_call1(Erule, TopType, Root, DynamicEnc, noext), ExtImm = case Ext of {ext,_,ExtNum} when ExtNum > 0 -> [{var,"Extensions"}]; _ -> [] end, - %handle extensions {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL), - NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen), - {Imm1,_} = gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,DynamicEnc,Ext,[]), + ExtList1 = wrap_extensionAdditionGroups(ExtList0, ExtGroupPosLen), + ExtList = [mark_optional(C) || C <- ExtList1], + Imm1 = gen_enc_components_call1(Erule, TopType, ExtList, DynamicEnc, Ext), Imm0 ++ [ExtImm|Imm1]; -gen_enc_components_call(Erule,TopType, CompList, DynamicEnc, Ext) -> - %% The type has no extensionmarker - {Imm,_} = gen_enc_components_call1(Erule,TopType,CompList,1,DynamicEnc,Ext,[]), - Imm. - -gen_enc_components_call1(Erule,TopType, - [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest], - Tpos, - DynamicEnc, Ext, Acc) -> - - TermNo = - case C#'ComponentType'.textual_order of - undefined -> - Tpos; - CanonicalNum -> - CanonicalNum - end, +gen_enc_components_call(Erule, TopType, CompList, DynamicEnc, Ext) -> + %% No extension marker. + gen_enc_components_call1(Erule, TopType, CompList, DynamicEnc, Ext). + +mark_optional(#'ComponentType'{prop=Prop0}=C) -> + Prop = case Prop0 of + mandatory -> 'OPTIONAL'; + 'OPTIONAL'=Keep -> Keep; + {'DEFAULT',_}=Keep -> Keep + end, + C#'ComponentType'{prop=Prop}. + +gen_enc_components_call1(Erule, TopType, [C|Rest], DynamicEnc, Ext) -> + #'ComponentType'{name=Cname,typespec=Type, + prop=Prop,textual_order=TermNo} = C, Val = make_var(val), {Imm0,Element} = asn1ct_imm:enc_element(TermNo+1, Val), - Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext), - Category = case {Prop,Ext} of - {'OPTIONAL',_} -> - optional; - {{'DEFAULT',DefVal},_} -> - {default,DefVal}; - {_,{ext,ExtPos,_}} when Tpos >= ExtPos -> - optional; - {_,_} -> - mandatory - end, - Imm2 = case Category of + Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, + Element, DynamicEnc, Ext), + Imm2 = case Prop of mandatory -> Imm1; - optional -> + 'OPTIONAL' -> asn1ct_imm:enc_absent(Element, [asn1_NOVALUE], Imm1); - {default,Def} -> + {'DEFAULT',Def} -> DefValues = def_values(Type, Def), asn1ct_imm:enc_absent(Element, DefValues, Imm1) end, @@ -855,10 +844,9 @@ gen_enc_components_call1(Erule,TopType, [] -> []; _ -> Imm0 ++ Imm2 end, - gen_enc_components_call1(Erule, TopType, Rest, Tpos+1, DynamicEnc, Ext, [Imm|Acc]); -gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_, Acc) -> - ImmList = lists:reverse(Acc), - {ImmList,Pos}. + [Imm|gen_enc_components_call1(Erule, TopType, Rest, DynamicEnc, Ext)]; +gen_enc_components_call1(_Erule, _TopType, [], _, _) -> + []. def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) -> #typedef{typespec=T} = asn1_db:dbget(Mod, Type), -- cgit v1.2.3 From ce431409d0daba5630e36173dcb751f0ab65e5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 18 Jan 2017 15:33:56 +0100 Subject: Refactor code generation options Most options to the code generation pass are passed through the process dictionary. At the same time, an Erule or Erules argument is passed to most code generation functions. The Erule argument is only an atom indicating the encoding rules ('ber', 'per', or 'uper'). Introduce a new record #gen{} to contain code generation options and parameters. Pass it as the Erule argument (renaming it to Gen in functions that we will have to touch anyway). In this commit, eliminate the use of the variable 'encoding_options' in the process dictionary. --- lib/asn1/src/asn1_records.hrl | 10 + lib/asn1/src/asn1ct.erl | 146 +++++----- lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl | 39 ++- lib/asn1/src/asn1ct_constructed_per.erl | 52 ++-- lib/asn1/src/asn1ct_gen.erl | 359 ++++++++++++------------- lib/asn1/src/asn1ct_gen_per.erl | 12 +- 6 files changed, 305 insertions(+), 313 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl index af10c1771c..4b800f17c7 100644 --- a/lib/asn1/src/asn1_records.hrl +++ b/lib/asn1/src/asn1_records.hrl @@ -96,6 +96,16 @@ error_context %Top-level thingie (contains line numbers) }). +%% Code generation parameters and options. +-record(gen, + {erule=ber :: 'ber' | 'per', + der=false :: boolean(), + aligned=false :: boolean(), + rec_prefix="" :: string(), + macro_prefix="" :: string(), + options=[] :: [any()] + }). + %% state record used by back-end at partial decode %% active is set to 'yes' when a partial decode function is generated. %% prefix is set to 'dec-inc-' or 'dec-partial-' is for diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 4e030861f5..c5e32cdc96 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -838,33 +838,47 @@ generate({M,GenTOrV}, OutFile, EncodingRule, Options) -> debug_on(Options), setup_bit_string_format(Options), setup_legacy_erlang_types(Options), - put(encoding_options,Options), asn1ct_table:new(check_functions), + Gen = init_gen_record(EncodingRule, Options), + %% create decoding function names and taglists for partial decode - case (catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options)) of - {error, Reason} -> warning("Error in configuration file: ~n~p~n", - [Reason], Options, - "Error in configuration file"); - _ -> ok + try + specialized_decode_prepare(Gen, M) + catch + throw:{error, Reason} -> + warning("Error in configuration file: ~n~p~n", + [Reason], Options, + "Error in configuration file") end, - Result = - case (catch asn1ct_gen:pgen(OutFile,EncodingRule, - M#module.name,GenTOrV,Options)) of - {'EXIT',Reason2} -> - error("~p~n",[Reason2],Options), - {error,Reason2}; - _ -> - ok - end, + Res = case catch asn1ct_gen:pgen(OutFile, Gen, M#module.name, GenTOrV) of + {'EXIT',Reason2} -> + error("~p~n",[Reason2],Options), + {error,Reason2}; + _ -> + ok + end, debug_off(Options), - erase(encoding_options), cleanup_bit_string_format(), erase(tlv_format), % used in ber erase(class_default_type),% used in ber asn1ct_table:delete(check_functions), - Result. + Res. + +init_gen_record(EncodingRule, Options) -> + Erule = case EncodingRule of + uper -> per; + _ -> EncodingRule + end, + Der = proplists:get_bool(der, Options), + Aligned = EncodingRule =:= per, + RecPrefix = proplists:get_value(record_name_prefix, Options, ""), + MacroPrefix = proplists:get_value(macro_name_prefix, Options, ""), + #gen{erule=Erule,der=Der,aligned=Aligned, + rec_prefix=RecPrefix,macro_prefix=MacroPrefix, + options=Options}. + setup_legacy_erlang_types(Opts) -> F = case lists:member(legacy_erlang_types, Opts) of @@ -997,9 +1011,8 @@ input_file_type(File) -> end end; ".asn1config" -> - case read_config_file(File,asn1_module) of + case read_config_file_info(File, asn1_module) of {ok,Asn1Module} -> -% put(asn1_config_file,File), input_file_type(Asn1Module); Error -> Error @@ -1370,25 +1383,26 @@ prepare_bytes(Bytes) -> list_to_binary(Bytes). vsn() -> ?vsn. -specialized_decode_prepare(Erule,M,TsAndVs,Options) -> - case lists:member(asn1config,Options) of +specialized_decode_prepare(#gen{erule=ber,options=Options}=Gen, M) -> + case lists:member(asn1config, Options) of true -> - partial_decode_prepare(Erule,M,TsAndVs,Options); - _ -> + special_decode_prepare_1(Gen, M); + false -> ok - end. + end; +specialized_decode_prepare(_, _) -> + ok. + %% Reads the configuration file if it exists and stores information %% about partial decode and incomplete decode -partial_decode_prepare(ber,M,TsAndVs,Options) when is_tuple(TsAndVs) -> +special_decode_prepare_1(#gen{options=Options}=Gen, M) -> %% read configure file - - ModName = - case lists:keysearch(asn1config,1,Options) of - {value,{_,MName}} -> MName; - _ -> M#module.name - end, + ModName = case lists:keyfind(asn1config, 1, Options) of + {_,MName} -> MName; + false -> M#module.name + end, %% io:format("ModName: ~p~nM#module.name: ~p~n~n",[ModName,M#module.name]), - case read_config_file(ModName) of + case read_config_file(Gen, ModName) of no_config_file -> ok; CfgList -> @@ -1407,11 +1421,7 @@ partial_decode_prepare(ber,M,TsAndVs,Options) when is_tuple(TsAndVs) -> Part_inc_tlv_tags = tlv_tags(CommandList2), save_config(partial_incomplete_decode,Part_inc_tlv_tags), save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags) - end; -partial_decode_prepare(_,_,_,_) -> - ok. - - + end. %% create_partial_inc_decode_gen_info/2 %% @@ -1863,46 +1873,38 @@ tlv_tag1(<<0:1,PartialTag:7>>,Acc) -> tlv_tag1(<<1:1,PartialTag:7,Buffer/binary>>,Acc) -> tlv_tag1(Buffer,(Acc bsl 7) bor PartialTag). -%% reads the content from the configuration file and returns the -%% selected part choosen by InfoType. Assumes that the config file +%% Reads the content from the configuration file and returns the +%% selected part chosen by InfoType. Assumes that the config file %% content is an Erlang term. -read_config_file(ModuleName,InfoType) when is_atom(InfoType) -> - CfgList = read_config_file(ModuleName), - get_config_info(CfgList,InfoType). +read_config_file_info(ModuleName, InfoType) when is_atom(InfoType) -> + Name = ensure_ext(ModuleName, ".asn1config"), + CfgList = read_config_file0(Name, []), + get_config_info(CfgList, InfoType). +read_config_file(#gen{options=Options}, ModuleName) -> + Name = ensure_ext(ModuleName, ".asn1config"), + Includes = [I || {i,I} <- Options], + read_config_file0(Name, ["."|Includes]). -read_config_file(ModuleName) -> - case file:consult(lists:concat([ModuleName,'.asn1config'])) of +read_config_file0(Name, [D|Dirs]) -> + case file:consult(filename:join(D, Name)) of {ok,CfgList} -> CfgList; {error,enoent} -> - Options = get(encoding_options), - Includes = [I || {i,I} <- Options], - read_config_file1(ModuleName,Includes); + read_config_file0(Name, Dirs); {error,Reason} -> Error = "error reading asn1 config file: " ++ file:format_error(Reason), throw({error,Error}) - end. -read_config_file1(ModuleName,[]) -> - case filename:extension(ModuleName) of - ".asn1config" -> - no_config_file; - _ -> - read_config_file(lists:concat([ModuleName,".asn1config"])) end; -read_config_file1(ModuleName,[H|T]) -> -% File = filename:join([H,lists:concat([ModuleName,'.asn1config'])]), - File = filename:join([H,ModuleName]), - case file:consult(File) of - {ok,CfgList} -> - CfgList; - {error,enoent} -> - read_config_file1(ModuleName,T); - {error,Reason} -> - Error = "error reading asn1 config file: " ++ - file:format_error(Reason), - throw({error,Error}) +read_config_file0(_, []) -> + no_config_file. + +ensure_ext(ModuleName, Ext) -> + Name = filename:join([ModuleName]), + case filename:extension(Name) of + Ext -> Name; + _ -> Name ++ Ext end. get_config_info(CfgList,InfoType) -> @@ -2382,8 +2384,10 @@ format_error({write_error,File,Reason}) -> io_lib:format("writing output file ~s failed: ~s", [File,file:format_error(Reason)]). -is_error(S) when is_record(S, state) -> - is_error(S#state.options); +is_error(#state{options=Opts}) -> + is_error(Opts); +is_error(#gen{options=Opts}) -> + is_error(Opts); is_error(O) -> lists:member(errors, O) orelse is_verbose(O). @@ -2392,8 +2396,10 @@ is_warning(S) when is_record(S, state) -> is_warning(O) -> lists:member(warnings, O) orelse is_verbose(O). -is_verbose(S) when is_record(S, state) -> - is_verbose(S#state.options); +is_verbose(#state{options=Opts}) -> + is_verbose(Opts); +is_verbose(#gen{options=Opts}) -> + is_verbose(Opts); is_verbose(O) -> lists:member(verbose, O). diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl index 325bea5879..cc1196c5cb 100644 --- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl @@ -32,7 +32,7 @@ -include("asn1_records.hrl"). --import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/0]). +-import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/1]). -define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2). @@ -225,7 +225,7 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> _ -> {false,false} end, - RecordName = lists:concat([get_record_name_prefix(), + RecordName = lists:concat([get_record_name_prefix(Erules), asn1ct_gen:list2rname(Typename)]), case gen_dec_sequence_call(Erules,Typename,CompList2,Ext,DecObjInf) of no_terms -> % an empty sequence @@ -405,7 +405,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:new(tlv) end, - RecordName = lists:concat([get_record_name_prefix(), + RecordName = lists:concat([get_record_name_prefix(Erules), asn1ct_gen:list2rname(Typename)]), case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of no_terms -> % an empty sequence @@ -504,10 +504,8 @@ gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when is_record(D,type) -> emit([" || ",{curr,v}," <- ",{curr,tlv},"].",nl,nl,nl]). -gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont) - when is_record(Cont,type)-> - - {Objfun,Objfun_novar,EncObj} = +gen_encode_sof_components(Gen, Typename, SeqOrSetOf, #type{}=Cont) -> + {Objfun,Objfun_novar,EncObj} = case Cont#type.tablecinf of [{objfun,_}|_R] -> {", ObjFun",", _",{no_attr,"ObjFun"}}; @@ -517,20 +515,19 @@ gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont) emit(["'enc_",asn1ct_gen:list2name(Typename), "_components'([]",Objfun_novar,", AccBytes, AccLen) -> ",nl]), - case catch lists:member(der,get(encoding_options)) of - true when SeqOrSetOf=='SET OF'-> + case {Gen,SeqOrSetOf} of + {#gen{der=true},'SET OF'} -> asn1ct_func:need({ber,dynamicsort_SETOF,1}), emit([indent(3), "{dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]); - _ -> + {_,_} -> emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl]) end, emit(["'enc_",asn1ct_gen:list2name(Typename), "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]), TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def), - gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3, -% mandatory,"{EncBytes,EncLen} = ",EncObj), - mandatory,EncObj), + gen_enc_line(Gen, Typename, TypeNameSuffix, Cont, "H", 3, + mandatory, EncObj), emit([",",nl]), emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename), "_components'(T",Objfun,","]), @@ -1035,26 +1032,26 @@ gen_optormand_case('OPTIONAL', Erules, _TopType, _Cname, _Type, Element) -> emit([indent(9),"asn1_NOVALUE -> {", empty_lb(Erules),",0};",nl]), emit([indent(9),"_ ->",nl,indent(12)]); -gen_optormand_case({'DEFAULT',DefaultValue}, Erules, _TopType, +gen_optormand_case({'DEFAULT',DefaultValue}, Gen, _TopType, _Cname, Type, Element) -> CurrMod = get(currmod), - case catch lists:member(der,get(encoding_options)) of - true -> + case Gen of + #gen{erule=ber,der=true} -> asn1ct_gen_check:emit(Type, DefaultValue, Element); - _ -> + #gen{erule=ber,der=false} -> emit([" case ",Element," of",nl]), emit([indent(9),"asn1_DEFAULT -> {", - empty_lb(Erules), + empty_lb(Gen), ",0};",nl]), case DefaultValue of #'Externalvaluereference'{module=CurrMod, value=V} -> emit([indent(9),"?",{asis,V}," -> {", - empty_lb(Erules),",0};",nl]); + empty_lb(Gen),",0};",nl]); _ -> emit([indent(9),{asis, DefaultValue}," -> {", - empty_lb(Erules),",0};",nl]) + empty_lb(Gen),",0};",nl]) end, emit([indent(9),"_ ->",nl,indent(12)]) end. @@ -1429,7 +1426,7 @@ mkfuncname(TopType,Cname,WhatKind,Prefix,Suffix) -> {F, "?MODULE", F} end. -empty_lb(ber) -> +empty_lb(#gen{erule=ber}) -> "<<>>". value_match(Index,Value) when is_atom(Value) -> diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 1782ca11b4..4121146228 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -32,17 +32,26 @@ -include("asn1_records.hrl"). %-compile(export_all). --import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/0]). --import(asn1ct_func, [call/3]). +-import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/1]). + +-type type_name() :: any(). %% ENCODE GENERATOR FOR SEQUENCE TYPE ** ********** -gen_encode_set(Erules,TypeName,D) -> - gen_encode_constructed(Erules,TypeName,D). +-spec gen_encode_set(Gen, TypeName, #type{}) -> 'ok' when + Gen :: #gen{}, + TypeName :: type_name(). + +gen_encode_set(Gen, TypeName, D) -> + gen_encode_constructed(Gen, TypeName, D). -gen_encode_sequence(Erules,TypeName,D) -> - gen_encode_constructed(Erules,TypeName,D). +-spec gen_encode_sequence(Gen, TypeName, #type{}) -> 'ok' when + Gen :: #gen{}, + TypeName :: type_name(). + +gen_encode_sequence(Gen, TypeName, D) -> + gen_encode_constructed(Gen, TypeName, D). gen_encode_constructed(Erule, Typename, #type{}=D) -> asn1ct_name:start(), @@ -303,7 +312,7 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) -> DecObjInf, Ext, length(Optionals)), EmitObjSets = gen_dec_objsets_fun(Erule, ObjSetInfo), EmitPack = fun(_) -> - gen_dec_pack(Typename, CompList) + gen_dec_pack(Erule, Typename, CompList) end, RestGroup = {group,[{safe,EmitObjSets},{safe,EmitPack}]}, [EmitExt,EmitOpt|EmitComp++[RestGroup]]. @@ -327,8 +336,8 @@ gen_dec_objsets_fun(Erule, ObjSetInfo) -> end end. -gen_dec_pack(Typename, CompList) -> - RecordName = record_name(Typename), +gen_dec_pack(Gen, Typename, CompList) -> + RecordName = record_name(Gen, Typename), case Typename of ['EXTERNAL'] -> emit({" OldFormat={'",RecordName, @@ -356,10 +365,10 @@ gen_dec_pack(Typename, CompList) -> %% group. Such fake sequences never appear as a top type, and their %% name always start with "ExtAddGroup". -record_name(Typename0) -> +record_name(Gen, Typename0) -> [TopType|Typename1] = lists:reverse(Typename0), Typename = filter_ext_add_groups(Typename1, [TopType]), - lists:concat([get_record_name_prefix(), + lists:concat([get_record_name_prefix(Gen), asn1ct_gen:list2rname(Typename)]). filter_ext_add_groups([H|T], Acc) when is_atom(H) -> @@ -588,8 +597,7 @@ do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D) -> emit([",",nl, {asis,F},"(",Num,", ",Buf,ObjFun,", [])"]). -is_aligned(per) -> true; -is_aligned(uper) -> false. +is_aligned(#gen{erule=per,aligned=Aligned}) -> Aligned. gen_decode_length(Constraint, Erule) -> emit(["%% Length with constraint ",{asis,Constraint},nl]), @@ -1089,27 +1097,31 @@ gen_dec_components_call(Erule, TopType, {Root,ExtList}, DecInfObj, Ext, NumberOfOptionals) -> gen_dec_components_call(Erule,TopType,{Root,ExtList,[]}, DecInfObj,Ext,NumberOfOptionals); -gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2}, - DecInfObj,Ext,NumberOfOptionals) -> +gen_dec_components_call(Gen, TopType, {Root1,ExtList,Root2}=CL, + DecInfObj, Ext, NumberOfOptionals) -> %% The type has extensionmarker OptTable = create_optionality_table(Root1++Root2), Init = {ignore,fun(_) -> {[],[]} end}, {EmitRoot,Tpos} = - gen_dec_comp_calls(Root1++Root2, Erule, TopType, OptTable, + gen_dec_comp_calls(Root1++Root2, Gen, TopType, OptTable, DecInfObj, noext, NumberOfOptionals, 1, []), - EmitGetExt = gen_dec_get_extension(Erule), + EmitGetExt = gen_dec_get_extension(Gen), {extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL), NewExtList = wrap_extensionAdditionGroups(ExtList, ExtGroupPosLen), - {EmitExts,_} = gen_dec_comp_calls(NewExtList, Erule, TopType, OptTable, + {EmitExts,_} = gen_dec_comp_calls(NewExtList, Gen, TopType, OptTable, DecInfObj, Ext, NumberOfOptionals, Tpos, []), NumExtsToSkip = ext_length(ExtList), Finish = fun(St) -> emit([{next,bytes},"= "]), - call(Erule, skipextensions, - [{curr,bytes},NumExtsToSkip+1,"Extensions"]), + Mod = case Gen of + #gen{erule=per,aligned=false} -> uper; + #gen{erule=per,aligned=true} -> per + end, + asn1ct_func:call(Mod, skipextensions, + [{curr,bytes},NumExtsToSkip+1,"Extensions"]), asn1ct_name:new(bytes), St end, diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index bfaffa13bf..a54cb0765e 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -34,10 +34,10 @@ insert_once/2, ct_gen_module/1, index2suffix/1, - get_record_name_prefix/0, + get_record_name_prefix/1, conform_value/2, named_bitstring_value/2]). --export([pgen/5, +-export([pgen/4, mk_var/1, un_hyphen_var/1]). -export([gen_encode_constructed/4, @@ -45,23 +45,20 @@ -define(SUPPRESSION_FUNC, 'dialyzer-suppressions'). + %% pgen(Outfile, Erules, Module, TypeOrVal, Options) -%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module -%% .hrl file is only generated if necessary -%% Erules = per | ber -%% Module = atom() -%% TypeOrVal = {TypeList,ValueList} -%% TypeList = ValueList = [atom()] -%% Options = [Options] from asn1ct:compile() - -pgen(OutFile,Erules,Module,TypeOrVal,Options) -> - pgen_module(OutFile,Erules,Module,TypeOrVal,Options,true). - - -pgen_module(OutFile,Erules,Module, - TypeOrVal = {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets}, - Options,Indent) -> - N2nConvEnums = [CName|| {n2n,CName} <- get(encoding_options)], +%% Generate Erlang module (.erl) and (.hrl) file corresponding to +%% an ASN.1 module. The .hrl file is only generated if necessary. + +-spec pgen(Outfile, Gen, Module, Contents) -> 'ok' when + Outfile :: any(), + Gen :: #gen{}, + Module :: module(), + Contents :: tuple(). + +pgen(OutFile, #gen{options=Options}=Gen, Module, Contents) -> + {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = Contents, + N2nConvEnums = [CName|| {n2n,CName} <- Options], case N2nConvEnums -- Types of [] -> ok; @@ -70,29 +67,27 @@ pgen_module(OutFile,Erules,Module, UnmatchedTypes}) end, put(outfile,OutFile), - HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent), + HrlGenerated = pgen_hrl(Gen, Module, Contents), asn1ct_name:start(), ErlFile = lists:concat([OutFile,".erl"]), _ = open_output_file(ErlFile), asn1ct_func:start_link(), - gen_head(Erules,Module,HrlGenerated), - pgen_exports(Erules,Module,TypeOrVal), - pgen_dispatcher(Erules,Module,TypeOrVal), + gen_head(Gen, Module, HrlGenerated), + pgen_exports(Gen, Module, Contents), + pgen_dispatcher(Gen, Contents), pgen_info(), - pgen_typeorval(Erules,Module,N2nConvEnums,TypeOrVal), - pgen_partial_incomplete_decode(Erules), -% gen_vars(asn1_db:mod_to_vars(Module)), -% gen_tag_table(AllTypes), + pgen_typeorval(Gen, Module, N2nConvEnums, Contents), + pgen_partial_incomplete_decode(Gen), emit([nl, "%%%",nl, "%%% Run-time functions.",nl, "%%%",nl]), - dialyzer_suppressions(Erules), + dialyzer_suppressions(Gen), Fd = get(gen_file_out), asn1ct_func:generate(Fd), close_output_file(), _ = erase(outfile), - asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options). + asn1ct:verbose("--~p--~n", [{generated,ErlFile}], Gen). dialyzer_suppressions(Erules) -> emit([nl, @@ -181,10 +176,10 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) -> Rtmod:gen_objectset_code(Erules,TypeDef), pgen_objectsets(Rtmod,Erules,Module,T). -pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber -> - pgen_partial_inc_dec(Rtmod,Erule,Module), - pgen_partial_dec(Rtmod,Erule,Module); -pgen_partial_decode(_,_,_) -> +pgen_partial_decode(Rtmod, #gen{erule=ber}=Gen, Module) -> + pgen_partial_inc_dec(Rtmod, Gen, Module), + pgen_partial_dec(Rtmod, Gen, Module); +pgen_partial_decode(_, _, _) -> ok. pgen_partial_inc_dec(Rtmod,Erules,Module) -> @@ -225,7 +220,7 @@ pgen_partial_inc_dec1(Rtmod,Erules,Module,[P|Ps]) -> pgen_partial_inc_dec1(_,_,_,[]) -> ok. -gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber -> +gen_partial_inc_dec_refed_funcs(Rtmod, #gen{erule=ber}=Gen) -> case asn1ct:next_refed_func() of [] -> ok; @@ -233,19 +228,17 @@ gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber -> TypeDef = asn1_db:dbget(M,Name), asn1ct:update_gen_state(namelist,Pattern), asn1ct:set_current_sindex(Sindex), - Rtmod:gen_inc_decode(Erule,TypeDef), - gen_dec_part_inner_constr(Rtmod,Erule,TypeDef,[Name]), - gen_partial_inc_dec_refed_funcs(Rtmod,Erule); + Rtmod:gen_inc_decode(Gen, TypeDef), + gen_dec_part_inner_constr(Rtmod, Gen, TypeDef, [Name]), + gen_partial_inc_dec_refed_funcs(Rtmod, Gen); {Name,Sindex,Pattern,Type} -> TypeDef=#typedef{name=asn1ct_gen:list2name(Name),typespec=Type}, asn1ct:update_gen_state(namelist,Pattern), asn1ct:set_current_sindex(Sindex), - Rtmod:gen_inc_decode(Erule,TypeDef), - gen_dec_part_inner_constr(Rtmod,Erule,TypeDef,Name), - gen_partial_inc_dec_refed_funcs(Rtmod,Erule) - end; -gen_partial_inc_dec_refed_funcs(_,_) -> - ok. + Rtmod:gen_inc_decode(Gen, TypeDef), + gen_dec_part_inner_constr(Rtmod, Gen, TypeDef, Name), + gen_partial_inc_dec_refed_funcs(Rtmod, Gen) + end. pgen_partial_dec(_Rtmod,Erules,_Module) -> Type_pattern = asn1ct:get_gen_state_field(type_pattern), @@ -254,16 +247,16 @@ pgen_partial_dec(_Rtmod,Erules,_Module) -> pgen_partial_types(Erules,Type_pattern), ok. -pgen_partial_types(Erules,Type_pattern) -> - % until this functionality works on all back-ends - Options = get(encoding_options), - case lists:member(asn1config,Options) of +pgen_partial_types(#gen{options=Options}=Gen, TypePattern) -> + %% until this functionality works on all back-ends + case lists:member(asn1config, Options) of true -> - pgen_partial_types1(Erules,Type_pattern); - _ -> ok + pgen_partial_types1(Gen, TypePattern); + false -> + ok end. - + pgen_partial_types1(Erules,[{FuncName,[TopType|RestTypes]}|Rest]) -> % emit([FuncName,"(Bytes) ->",nl]), CurrMod = get(currmod), @@ -441,7 +434,8 @@ pgen_partial_incomplete_decode(Erule) -> _ -> ok end. -pgen_partial_incomplete_decode1(ber) -> + +pgen_partial_incomplete_decode1(#gen{erule=ber}) -> case asn1ct:read_config_data(partial_incomplete_decode) of undefined -> ok; @@ -451,7 +445,7 @@ pgen_partial_incomplete_decode1(ber) -> GeneratedFs= asn1ct:get_gen_state_field(gen_refed_funcs), % io:format("GeneratedFs :~n~p~n",[GeneratedFs]), gen_part_decode_funcs(GeneratedFs,0); -pgen_partial_incomplete_decode1(_) -> ok. +pgen_partial_incomplete_decode1(#gen{}) -> ok. emit_partial_incomplete_decode({FuncName,TopType,Pattern}) -> TypePattern = asn1ct:get_gen_state_field(inc_type_pattern), @@ -654,7 +648,8 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) -> gen_decode_constructed(Erules,Typename,InnerType,D#typedef.typespec). -pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> +pgen_exports(#gen{options=Options}=Gen, _Module, Contents) -> + {Types,Values,_,_,Objects,ObjectSets} = Contents, emit(["-export([encoding_rule/0,bit_string_format/0,",nl, " legacy_erlang_types/0]).",nl]), emit(["-export([",{asis,?SUPPRESSION_FUNC},"/1]).",nl]), @@ -662,21 +657,21 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> [] -> ok; _ -> emit({"-export([",nl}), - case Erules of - ber -> + case Gen of + #gen{erule=ber} -> gen_exports1(Types,"enc_",2); _ -> gen_exports1(Types,"enc_",1) end, emit({"-export([",nl}), - case Erules of - ber -> + case Gen of + #gen{erule=ber} -> gen_exports1(Types, "dec_", 2); _ -> gen_exports1(Types, "dec_", 1) end end, - case [X || {n2n,X} <- get(encoding_options)] of + case [X || {n2n,X} <- Options] of [] -> ok; A2nNames -> emit({"-export([",nl}), @@ -693,10 +688,10 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> case Objects of [] -> ok; _ -> - case erule(Erules) of - per -> - ok; - ber -> + case Gen of + #gen{erule=per} -> + ok; + #gen{erule=ber} -> emit({"-export([",nl}), gen_exports1(Objects,"enc_",3), emit({"-export([",nl}), @@ -706,10 +701,10 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> case ObjectSets of [] -> ok; _ -> - case erule(Erules) of - per -> - ok; - ber -> + case Gen of + #gen{erule=per} -> + ok; + #gen{erule=ber} -> emit({"-export([",nl}), gen_exports1(ObjectSets, "getenc_",1), emit({"-export([",nl}), @@ -735,16 +730,17 @@ gen_partial_inc_decode_exports() -> {_,undefined} -> ok; {Data,_} -> - gen_partial_inc_decode_exports(Data), + gen_partial_inc_decode_exports0(Data), emit(["-export([decode_part/2]).",nl]) end. -gen_partial_inc_decode_exports([]) -> + +gen_partial_inc_decode_exports0([]) -> ok; -gen_partial_inc_decode_exports([{Name,_,_}|Rest]) -> +gen_partial_inc_decode_exports0([{Name,_,_}|Rest]) -> emit(["-export([",Name,"/1"]), gen_partial_inc_decode_exports1(Rest); -gen_partial_inc_decode_exports([_|Rest]) -> - gen_partial_inc_decode_exports(Rest). +gen_partial_inc_decode_exports0([_|Rest]) -> + gen_partial_inc_decode_exports0(Rest). gen_partial_inc_decode_exports1([]) -> emit(["]).",nl]); @@ -773,27 +769,27 @@ gen_selected_decode_exports1([{FuncName,_}|Rest]) -> emit([",",nl," ",FuncName,"/1"]), gen_selected_decode_exports1(Rest). -pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) -> +pgen_dispatcher(Erules, {[],_Values,_,_,_Objects,_ObjectSets}) -> gen_info_functions(Erules); -pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) -> +pgen_dispatcher(Gen, {Types,_Values,_,_,_Objects,_ObjectSets}) -> emit(["-export([encode/2,decode/2]).",nl,nl]), - gen_info_functions(Erules), + gen_info_functions(Gen), - Options = get(encoding_options), + Options = Gen#gen.options, NoFinalPadding = lists:member(no_final_padding, Options), NoOkWrapper = proplists:get_bool(no_ok_wrapper, Options), - Call = case Erules of - per -> - asn1ct_func:need({Erules,complete,1}), + Call = case Gen of + #gen{erule=per,aligned=true} -> + asn1ct_func:need({per,complete,1}), "complete(encode_disp(Type, Data))"; - ber -> + #gen{erule=ber} -> "iolist_to_binary(element(1, encode_disp(Type, Data)))"; - uper when NoFinalPadding == true -> - asn1ct_func:need({Erules,complete_NFP,1}), + #gen{erule=per,aligned=false} when NoFinalPadding -> + asn1ct_func:need({uper,complete_NFP,1}), "complete_NFP(encode_disp(Type, Data))"; - uper -> - asn1ct_func:need({Erules,complete,1}), + #gen{erule=per,aligned=false} -> + asn1ct_func:need({uper,complete,1}), "complete(encode_disp(Type, Data))" end, @@ -809,36 +805,36 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) -> end, emit([nl,nl]), - Return_rest = proplists:get_bool(undec_rest, Options), - Data = case {Erules,Return_rest} of - {ber,true} -> "Data0"; - _ -> "Data" + ReturnRest = proplists:get_bool(undec_rest, Gen#gen.options), + Data = case Gen#gen.erule =:= ber andalso ReturnRest of + true -> "Data0"; + false -> "Data" end, emit(["decode(Type,",Data,") ->",nl]), DecWrap = - case {Erules,Return_rest} of - {ber,false} -> + case {Gen,ReturnRest} of + {#gen{erule=ber},false} -> asn1ct_func:need({ber,ber_decode_nif,1}), "element(1, ber_decode_nif(Data))"; - {ber,true} -> + {#gen{erule=ber},true} -> asn1ct_func:need({ber,ber_decode_nif,1}), emit(["{Data,Rest} = ber_decode_nif(Data0),",nl]), "Data"; - _ -> + {_,_} -> "Data" end, emit([case NoOkWrapper of false -> "try"; true -> "case" end, " decode_disp(Type, ",DecWrap,") of",nl]), - case erule(Erules) of - ber -> + case Gen of + #gen{erule=ber} -> emit([" Result ->",nl]); - per -> + #gen{erule=per} -> emit([" {Result,Rest} ->",nl]) end, - case Return_rest of + case ReturnRest of false -> result_line(NoOkWrapper, ["Result"]); true -> result_line(NoOkWrapper, ["Result","Rest"]) end, @@ -849,14 +845,14 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) -> emit([nl,"end.",nl,nl]) end, - gen_decode_partial_incomplete(Erules), + gen_decode_partial_incomplete(Gen), - case Erules of - ber -> + case Gen of + #gen{erule=ber} -> gen_dispatcher(Types,"encode_disp","enc_",""), gen_dispatcher(Types,"decode_disp","dec_",""), gen_partial_inc_dispatcher(); - _PerOrPer_bin -> + #gen{} -> gen_dispatcher(Types,"encode_disp","enc_",""), gen_dispatcher(Types,"decode_disp","dec_","") end, @@ -885,15 +881,20 @@ try_catch() -> " end",nl, "end."]. -gen_info_functions(Erules) -> +gen_info_functions(Gen) -> + Erule = case Gen of + #gen{erule=ber} -> ber; + #gen{erule=per,aligned=false} -> uper; + #gen{erule=per,aligned=true} -> per + end, emit(["encoding_rule() -> ", - {asis,Erules},".",nl,nl, + {asis,Erule},".",nl,nl, "bit_string_format() -> ", {asis,asn1ct:get_bit_string_format()},".",nl,nl, "legacy_erlang_types() -> ", {asis,asn1ct:use_legacy_types()},".",nl,nl]). -gen_decode_partial_incomplete(ber) -> +gen_decode_partial_incomplete(#gen{erule=ber}) -> case {asn1ct:read_config_data(partial_incomplete_decode), asn1ct:get_gen_state_field(inc_type_pattern)} of {undefined,_} -> @@ -931,7 +932,7 @@ gen_decode_partial_incomplete(ber) -> EmitCaseClauses(), emit([".",nl,nl]) end; -gen_decode_partial_incomplete(_Erule) -> +gen_decode_partial_incomplete(#gen{}) -> ok. gen_partial_inc_dispatcher() -> @@ -1092,22 +1093,22 @@ open_output_file(F) -> close_output_file() -> ok = file:close(erase(gen_file_out)). -pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) -> - put(currmod,Module), - {Types,Values,Ptypes,_,_,_} = TypeOrVal, +pgen_hrl(Gen, Module, Contents) -> + put(currmod, Module), + {Types,Values,Ptypes,_,_,_} = Contents, Ret = - case pgen_hrltypes(Erules,Module,Ptypes++Types,0) of + case pgen_hrltypes(Gen, Module, Ptypes++Types, 0) of 0 -> case Values of [] -> 0; _ -> open_hrl(get(outfile),get(currmod)), - pgen_macros(Erules,Module,Values), + pgen_macros(Gen, Module, Values), 1 end; X -> - pgen_macros(Erules,Module,Values), + pgen_macros(Gen, Module, Values), X end, case Ret of @@ -1119,62 +1120,59 @@ pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) -> close_output_file(), asn1ct:verbose("--~p--~n", [{generated,lists:concat([get(outfile),".hrl"])}], - Options), + Gen), Y end. pgen_macros(_,_,[]) -> true; -pgen_macros(Erules,Module,[H|T]) -> - Valuedef = asn1_db:dbget(Module,H), - gen_macro(Valuedef), - pgen_macros(Erules,Module,T). +pgen_macros(Gen, Module, [H|T]) -> + Valuedef = asn1_db:dbget(Module, H), + gen_macro(Gen, Valuedef), + pgen_macros(Gen, Module, T). pgen_hrltypes(_,_,[],NumRecords) -> NumRecords; -pgen_hrltypes(Erules,Module,[H|T],NumRecords) -> -% io:format("records = ~p~n",NumRecords), - Typedef = asn1_db:dbget(Module,H), - AddNumRecords = gen_record(Typedef,NumRecords), - pgen_hrltypes(Erules,Module,T,NumRecords+AddNumRecords). +pgen_hrltypes(Gen, Module, [H|T], NumRecords) -> + Typedef = asn1_db:dbget(Module, H), + AddNumRecords = gen_record(Gen, Typedef, NumRecords), + pgen_hrltypes(Gen, Module, T, NumRecords+AddNumRecords). %% Generates a macro for value Value defined in the ASN.1 module -gen_macro(Value) when is_record(Value,valuedef) -> - Prefix = get_macro_name_prefix(), - emit({"-define('",Prefix,Value#valuedef.name,"', ", - {asis,Value#valuedef.value},").",nl}). +gen_macro(Gen, #valuedef{name=Name,value=Value}) -> + Prefix = get_macro_name_prefix(Gen), + emit(["-define('",Prefix,Name,"', ",{asis,Value},").",nl]). %% Generate record functions ************** %% Generates an Erlang record for each named and unnamed SEQUENCE and SET in the ASN.1 %% module. If no SEQUENCE or SET is found there is no .hrl file generated -gen_record(Tdef,NumRecords) when is_record(Tdef,typedef) -> +gen_record(Gen, #typedef{}=Tdef, NumRecords) -> Name = [Tdef#typedef.name], Type = Tdef#typedef.typespec, - gen_record(type,Name,Type,NumRecords); - -gen_record(Tdef,NumRecords) when is_record(Tdef,ptypedef) -> + gen_record(Gen, type, Name, Type, NumRecords); +gen_record(Gen, #ptypedef{}=Tdef, NumRecords) -> Name = [Tdef#ptypedef.name], Type = Tdef#ptypedef.typespec, - gen_record(ptype,Name,Type,NumRecords). - -gen_record(TorPtype,Name,[#'ComponentType'{name=Cname,typespec=Type}|T],Num) -> - Num2 = gen_record(TorPtype,[Cname|Name],Type,Num), - gen_record(TorPtype,Name,T,Num2); -gen_record(TorPtype,Name,{Clist1,Clist2},Num) + gen_record(Gen, ptype, Name, Type, NumRecords). + +gen_record(Gen, TorPtype, Name, + [#'ComponentType'{name=Cname,typespec=Type}|T], Num) -> + Num2 = gen_record(Gen, TorPtype, [Cname|Name], Type, Num), + gen_record(Gen, TorPtype, Name, T, Num2); +gen_record(Gen, TorPtype, Name, {Clist1,Clist2}, Num) when is_list(Clist1), is_list(Clist2) -> - gen_record(TorPtype,Name,Clist1++Clist2,Num); -gen_record(TorPtype,Name,{Clist1,EClist,Clist2},Num) + gen_record(Gen, TorPtype, Name, Clist1++Clist2, Num); +gen_record(Gen, TorPtype, Name, {Clist1,EClist,Clist2}, Num) when is_list(Clist1), is_list(EClist), is_list(Clist2) -> - gen_record(TorPtype,Name,Clist1++EClist++Clist2,Num); -gen_record(TorPtype,Name,[_|T],Num) -> % skip EXTENSIONMARK - gen_record(TorPtype,Name,T,Num); -gen_record(_TorPtype,_Name,[],Num) -> + gen_record(Gen, TorPtype, Name, Clist1++EClist++Clist2, Num); +gen_record(Gen, TorPtype, Name, [_|T], Num) -> % skip EXTENSIONMARK + gen_record(Gen, TorPtype, Name, T, Num); +gen_record(_Gen, _TorPtype, _Name, [], Num) -> Num; - -gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) -> +gen_record(Gen, TorPtype, Name, #type{}=Type, Num) -> Def = Type#type.def, Rec = case Def of Seq when is_record(Seq,'SEQUENCE') -> @@ -1209,7 +1207,7 @@ gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) -> 0 -> open_hrl(get(outfile),get(currmod)); _ -> true end, - Prefix = get_record_name_prefix(), + Prefix = get_record_name_prefix(Gen), emit({"-record('",Prefix,list2name(Name),"',{",nl}), RootList = case CompList of _ when is_list(CompList) -> @@ -1260,33 +1258,28 @@ gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) -> emit({"}).",nl,nl}), CompList end, - gen_record(TorPtype,Name,NewCompList,Num+1); + gen_record(Gen, TorPtype, Name, NewCompList, Num+1); {inner,{'CHOICE', CompList}} -> - gen_record(TorPtype,Name,CompList,Num); + gen_record(Gen, TorPtype, Name, CompList, Num); {NewName,{_, CompList}} -> - gen_record(TorPtype,NewName,CompList,Num) + gen_record(Gen, TorPtype, NewName, CompList, Num) end; -gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now. +gen_record(_, _, _, _, NumRecords) -> % skip CLASS etc for now. NumRecords. - -gen_head(Erules,Mod,Hrl) -> - Options = get(encoding_options), - case Erules of - per -> - emit(["%% Generated by the Erlang ASN.1 PER-" - "compiler version, utilizing bit-syntax:", - asn1ct:vsn(),nl]); - ber -> - emit(["%% Generated by the Erlang ASN.1 BER_V2-" - "compiler version, utilizing bit-syntax:", - asn1ct:vsn(),nl]); - uper -> - emit(["%% Generated by the Erlang ASN.1 UNALIGNED" - " PER-compiler version, utilizing bit-syntax:", - asn1ct:vsn(),nl]) - end, - emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}), - emit({"-module('",Mod,"').",nl}), + +gen_head(#gen{options=Options}=Gen, Mod, Hrl) -> + Name = case Gen of + #gen{erule=per,aligned=false} -> + "PER (unaligned)"; + #gen{erule=per,aligned=true} -> + "PER (aligned)"; + #gen{erule=ber} -> + "BER" + end, + emit(["%% Generated by the Erlang ASN.1 ",Name, + "compiler. Version:",asn1ct:vsn(),nl, + "%% Purpose: encoder and decoder of the types in ",Mod,nl,nl, + "-module('",Mod,"').",nl]), put(currmod,Mod), emit({"-compile(nowarn_unused_vars).",nl}), emit({"-dialyzer(no_improper_lists).",nl}), @@ -1297,7 +1290,7 @@ gen_head(Erules,Mod,Hrl) -> emit(["-asn1_info([{vsn,'",asn1ct:vsn(),"'},",nl, " {module,'",Mod,"'},",nl, " {options,",io_lib:format("~p",[Options]),"}]).",nl,nl]). - + gen_hrlhead(Mod) -> emit({"%% Generated by the Erlang ASN.1 compiler version:",asn1ct:vsn(),nl}), @@ -1585,27 +1578,19 @@ constructed_suffix('SEQUENCE OF',_) -> constructed_suffix('SET OF',_) -> 'SETOF'. -erule(ber) -> ber; -erule(per) -> per; -erule(uper) -> per. - index2suffix(0) -> ""; index2suffix(N) -> lists:concat(["_",N]). -ct_gen_module(ber) -> +ct_gen_module(#gen{erule=ber}) -> asn1ct_gen_ber_bin_v2; -ct_gen_module(per) -> - asn1ct_gen_per; -ct_gen_module(uper) -> +ct_gen_module(#gen{erule=per}) -> asn1ct_gen_per. -ct_constructed_module(ber) -> +ct_constructed_module(#gen{erule=ber}) -> asn1ct_constructed_ber_bin_v2; -ct_constructed_module(per) -> - asn1ct_constructed_per; -ct_constructed_module(uper) -> +ct_constructed_module(#gen{erule=per}) -> asn1ct_constructed_per. get_constraint(C,Key) -> @@ -1617,19 +1602,9 @@ get_constraint(C,Key) -> {value,Cnstr} -> Cnstr end. - -get_record_name_prefix() -> - case lists:keysearch(record_name_prefix,1,get(encoding_options)) of - false -> - ""; - {value,{_,Prefix}} -> - Prefix - end. -get_macro_name_prefix() -> - case lists:keysearch(macro_name_prefix,1,get(encoding_options)) of - false -> - ""; - {value,{_,Prefix}} -> - Prefix - end. +get_record_name_prefix(#gen{rec_prefix=Prefix}) -> + Prefix. + +get_macro_name_prefix(#gen{macro_prefix=Prefix}) -> + Prefix. diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index aa7223904e..9671a566bf 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -113,11 +113,7 @@ gen_encode_prim(Erules, D) -> Value = {var,atom_to_list(asn1ct_gen:mk_var(asn1ct_name:curr(val)))}, gen_encode_prim(Erules, D, Value). -gen_encode_prim(Erules, #type{}=D, Value) -> - Aligned = case Erules of - uper -> false; - per -> true - end, +gen_encode_prim(#gen{erule=per,aligned=Aligned}, #type{}=D, Value) -> Imm = gen_encode_prim_imm(Value, D, Aligned), asn1ct_imm:enc_cg(Imm, Aligned). @@ -284,11 +280,7 @@ gen_dec_external(Ext, BytesVar) -> _ -> [{asis,Mod},":"] end,{asis,dec_func(Type)},"(",BytesVar,")"]). -gen_dec_imm(Erule, #type{def=Name,constraint=C}) -> - Aligned = case Erule of - uper -> false; - per -> true - end, +gen_dec_imm(#gen{erule=per,aligned=Aligned}, #type{def=Name,constraint=C}) -> gen_dec_imm_1(Name, C, Aligned). gen_dec_imm_1('ASN1_OPEN_TYPE', Constraint, Aligned) -> -- cgit v1.2.3 From d3182f64b8addb0aa2ea53f24ecdb8391bf4935f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 19 Jan 2017 14:11:54 +0100 Subject: Clean up filtering of options --- lib/asn1/src/asn1ct.erl | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index c5e32cdc96..0a68395b49 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1105,16 +1105,27 @@ translate_options([H|T]) -> translate_options([]) -> []. remove_asn_flags(Options) -> - [X || X <- Options, - X /= get_rule(Options), - X /= optimize, - X /= compact_bit_string, - X /= legacy_bit_string, - X /= legacy_erlang_types, - X /= debug, - X /= asn1config, - X /= record_name_prefix]. - + [X || X <- Options, not is_asn1_flag(X)]. + +is_asn1_flag(asn1config) -> true; +is_asn1_flag(ber) -> true; +is_asn1_flag(compact_bit_string) -> true; +is_asn1_flag(debug) -> true; +is_asn1_flag(der) -> true; +is_asn1_flag(legacy_bit_string) -> true; +is_asn1_flag({macro_name_prefix,_}) -> true; +is_asn1_flag({n2n,_}) -> true; +is_asn1_flag(noobj) -> true; +is_asn1_flag(no_ok_wrapper) -> true; +is_asn1_flag(optimize) -> true; +is_asn1_flag(per) -> true; +is_asn1_flag({record_name_prefix,_}) -> true; +is_asn1_flag(undec_rec) -> true; +is_asn1_flag(uper) -> true; +is_asn1_flag(verbose) -> true; +%% 'warnings_as_errors' is intentionally passed through to the compiler. +is_asn1_flag(_) -> false. + debug_on(Options) -> case lists:member(debug,Options) of true -> -- cgit v1.2.3 From a586ed43fc47bed6e3ff1d162ef0e1844de6ac50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 20 Jan 2017 10:27:08 +0100 Subject: Refactor encoding of optional values As a preparation for supporting maps in a future commit, refactor the functions for encoding optional values. --- lib/asn1/src/asn1ct_constructed_per.erl | 59 ++++++++++++++++++--------------- lib/asn1/src/asn1ct_imm.erl | 25 +++++--------- 2 files changed, 41 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 4121146228..15fc913773 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -59,7 +59,7 @@ gen_encode_constructed(Erule, Typename, #type{}=D) -> asn1ct_imm:enc_cg(Imm, is_aligned(Erule)), emit([".",nl]). -gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> +gen_encode_constructed_imm(Gen, Typename, #type{}=D) -> {CompList,TableConsInfo} = enc_complist(D), ExternalImm = case Typename of @@ -71,12 +71,10 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> _ -> [] end, - Aligned = is_aligned(Erule), - Value0 = make_var(val), Optionals = optionals(to_textual_order(CompList)), - ImmOptionals = [asn1ct_imm:per_enc_optional(Value0, Opt, Aligned) || - Opt <- Optionals], + ImmOptionals = enc_optionals(Gen, Optionals), Ext = extensible_enc(CompList), + Aligned = is_aligned(Gen), ExtImm = case Ext of {ext,ExtPos,NumExt} when NumExt > 0 -> gen_encode_extaddgroup(CompList), @@ -96,7 +94,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> _ -> [] end, - ImmBody = gen_enc_components_call(Erule, Typename, CompList, EncObj, Ext), + ImmBody = gen_enc_components_call(Gen, Typename, CompList, EncObj, Ext), ExternalImm ++ ExtImm ++ ObjSetImm ++ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody). @@ -149,6 +147,17 @@ enc_table(_Gen, _, #type{tablecinf=TCInf}) -> {false,[]} end. +enc_optionals(Gen, Optionals) -> + Var = make_var(val), + enc_optionals_1(Gen, Optionals, Var). + +enc_optionals_1(Gen, [{Pos,DefVals}|T], Var) -> + {Imm0,Element} = asn1ct_imm:enc_element(Pos+1, Var), + Imm = asn1ct_imm:per_enc_optional(Element, DefVals), + [Imm0++Imm|enc_optionals_1(Gen, T, Var)]; +enc_optionals_1(_, [], _) -> + []. + gen_encode_extaddgroup(CompList) -> case extgroup_pos_and_length(CompList) of {extgrouppos,[]} -> @@ -729,28 +738,26 @@ gen_dec_optionals(Optionals) -> {imm,Imm0,E}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Produce a list with positions (in the Value record) where -%% there are optional components, start with 2 because first element -%% is the record name - -optionals({L1,Ext,L2}) -> - Opt1 = optionals(L1,[],2), - ExtComps = length([C||C = #'ComponentType'{}<-Ext]), - Opt2 = optionals(L2,[],2+length(L1)+ExtComps), - Opt1 ++ Opt2; -optionals({L,_Ext}) -> optionals(L,[],2); -optionals(L) -> optionals(L,[],2). -optionals([#'ComponentType'{prop='OPTIONAL'}|Rest], Acc, Pos) -> - optionals(Rest, [Pos|Acc], Pos+1); -optionals([#'ComponentType'{typespec=T,prop={'DEFAULT',Val}}|Rest], - Acc, Pos) -> +optionals({Root1,Ext,Root2}) -> + Opt1 = optionals(Root1, 1), + ExtComps = length([C || C = #'ComponentType'{} <- Ext]), + Opt2 = optionals(Root2, 1 + length(Root1) + ExtComps), + Opt1 ++ Opt2; +optionals({L,_Ext}) -> + optionals(L, 1); +optionals(L) -> + optionals(L, 1). + +optionals([#'ComponentType'{prop='OPTIONAL'}|Rest], Pos) -> + [{Pos,[asn1_NOVALUE]}|optionals(Rest, Pos+1)]; +optionals([#'ComponentType'{typespec=T,prop={'DEFAULT',Val}}|Cs], Pos) -> Vals = def_values(T, Val), - optionals(Rest, [{Pos,Vals}|Acc], Pos+1); -optionals([#'ComponentType'{}|Rest], Acc, Pos) -> - optionals(Rest, Acc, Pos+1); -optionals([], Acc, _) -> - lists:reverse(Acc). + [{Pos,Vals}|optionals(Cs, Pos+1)]; +optionals([#'ComponentType'{}|Rest], Pos) -> + optionals(Rest, Pos+1); +optionals([], _) -> + []. %%%%%%%%%%%%%%%%%%%%%% %% create_optionality_table(Cs=[#'ComponentType'{textual_order=undefined}|_]) -> diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index 8b96242c56..741d54c321 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -37,7 +37,7 @@ per_enc_open_type/2, per_enc_restricted_string/3, per_enc_small_number/2]). --export([per_enc_extension_bit/2,per_enc_extensions/4,per_enc_optional/3]). +-export([per_enc_extension_bit/2,per_enc_extensions/4,per_enc_optional/2]). -export([per_enc_sof/5]). -export([enc_absent/3,enc_append/1,enc_element/2]). -export([enc_cg/2]). @@ -349,27 +349,18 @@ per_enc_extensions(Val0, Pos0, NumBits, Aligned) when NumBits > 0 -> ['_'|Length ++ PutBits]]}], {var,"Extensions"}}]. -per_enc_optional(Val0, {Pos,DefVals}, _Aligned) when is_integer(Pos), - is_list(DefVals) -> - {B,Val} = enc_element(Pos, Val0), +per_enc_optional(Val, DefVals) when is_list(DefVals) -> Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, - B++[{'cond', - [[{eq,Val,DefVal},Zero] || DefVal <- DefVals] ++ [['_',One]]}]; -per_enc_optional(Val0, {Pos,{call,M,F,A}}, _Aligned) when is_integer(Pos) -> - {B,Val} = enc_element(Pos, Val0), + [{'cond', + [[{eq,Val,DefVal},Zero] || DefVal <- DefVals] ++ [['_',One]]}]; +per_enc_optional(Val, {call,M,F,A}) -> {[],[[],Tmp]} = mk_vars([], [tmp]), Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, - B++[{call,M,F,[Val|A],Tmp}, - {'cond', - [[{eq,Tmp,true},Zero],['_',One]]}]; -per_enc_optional(Val0, Pos, _Aligned) when is_integer(Pos) -> - {B,Val} = enc_element(Pos, Val0), - Zero = {put_bits,0,1,[1]}, - One = {put_bits,1,1,[1]}, - B++[{'cond',[[{eq,Val,asn1_NOVALUE},Zero], - ['_',One]]}]. + [{call,M,F,[Val|A],Tmp}, + {'cond', + [[{eq,Tmp,true},Zero],['_',One]]}]. per_enc_sof(Val0, Constraint, ElementVar, ElementImm, Aligned) -> {B,[Val,Len]} = mk_vars(Val0, [len]), -- cgit v1.2.3 From 48137fa5034202e0fc4c5fbc0faf9bbb8bc2bb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 24 Jan 2017 14:18:02 +0100 Subject: Refactor decoding as a preparation for handling maps --- lib/asn1/src/asn1ct_constructed_per.erl | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 15fc913773..e817cf8677 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -326,7 +326,7 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) -> RestGroup = {group,[{safe,EmitObjSets},{safe,EmitPack}]}, [EmitExt,EmitOpt|EmitComp++[RestGroup]]. -gen_dec_objsets_fun(Erule, ObjSetInfo) -> +gen_dec_objsets_fun(Gen, ObjSetInfo) -> fun({AccTerm,AccBytes}) -> {_,_UniqueFName,ValueIndex} = ObjSetInfo, case {AccTerm,AccBytes} of @@ -335,9 +335,9 @@ gen_dec_objsets_fun(Erule, ObjSetInfo) -> {_,[]} -> ok; {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} -> - ValueMatch = value_match(ValueIndex, Term), + ValueMatch = value_match(Gen, ValueIndex, Term), _ = [begin - gen_dec_open_type(Erule, ValueMatch, ObjSet, + gen_dec_open_type(Gen, ValueMatch, ObjSet, LeadingAttr, T), emit([com,nl]) end || T <- ListOfOpenTypes], @@ -1454,29 +1454,29 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp, Prop}],PrevSt} end end; -gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) -> - case gen_dec_line_other(Erule, Atype, TopType, Comp) of +gen_dec_line_special(Gen, Atype, TopType, Comp, DecInfObj) -> + case gen_dec_line_other(Gen, Atype, TopType, Comp) of Fun when is_function(Fun, 1) -> fun({BytesVar,PrevSt}) -> Fun(BytesVar), - gen_dec_line_dec_inf(Comp, DecInfObj), + gen_dec_line_dec_inf(Gen,Comp, DecInfObj), {[],PrevSt} end; Imm0 -> {imm,Imm0, fun(Imm, {BytesVar,PrevSt}) -> asn1ct_imm:dec_code_gen(Imm, BytesVar), - gen_dec_line_dec_inf(Comp, DecInfObj), + gen_dec_line_dec_inf(Gen, Comp, DecInfObj), {[],PrevSt} end} end. -gen_dec_line_dec_inf(Comp, DecInfObj) -> +gen_dec_line_dec_inf(Gen, Comp, DecInfObj) -> #'ComponentType'{name=Cname} = Comp, case DecInfObj of {Cname,{_,_OSet,_UniqueFName,ValIndex}} -> Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)), - ValueMatch = value_match(ValIndex,Term), + ValueMatch = value_match(Gen, ValIndex,Term), emit([",",nl, "ObjFun = ",ValueMatch]); _ -> @@ -1768,16 +1768,11 @@ wrap_extensionAdditionGroups([H|T],ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupN wrap_extensionAdditionGroups([],_,Acc,_,_) -> lists:reverse(Acc). -value_match(Index,Value) when is_atom(Value) -> - value_match(Index,atom_to_list(Value)); -value_match([],Value) -> +value_match(_Gen, [], Value) -> Value; -value_match([{VI,_}|VIs],Value) -> - value_match1(Value,VIs,lists:concat(["element(",VI,","]),1). -value_match1(Value,[],Acc,Depth) -> - Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")")); -value_match1(Value,[{VI,_}|VIs],Acc,Depth) -> - value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1). +value_match(Gen, [{VI,_}|VIs], Value0) -> + Value = value_match(Gen, VIs, Value0), + lists:concat(["element(",VI,", ",Value,")"]). enc_dig_out_value(_Gen, [], Value) -> {[],Value}; -- cgit v1.2.3 From 8a7f914affce3102e4889c2973ea2d2e99ad633d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 16 Jan 2017 16:47:58 +0100 Subject: Teach the ASN.1 compiler the 'maps' option When the 'maps' option is given, the SEQUENCE and SET types are represented as maps instead of as records. Optional and default values must be not be given as asn1_NOVALUE or asn1_DEFAULT in a map passed to the M:encode/2 function; they must be omitted from the map. Similarly, when decoding missing values will be omitted from the map. No .hrl files will be generated when the 'maps' options is used. That means values in an ASN.1 module must be retrieved by calling the appropriate function in generated module. Since we one day hope to get rid of the options 'compact_bit_string', 'legacy_bit_string', and 'legacy_erlang_types', we will not allow them to be combined with the 'maps' option. --- lib/asn1/doc/src/asn1_getting_started.xml | 77 +++- lib/asn1/doc/src/asn1ct.xml | 17 +- lib/asn1/src/asn1_db.erl | 26 +- lib/asn1/src/asn1_records.hrl | 2 + lib/asn1/src/asn1ct.erl | 43 +- lib/asn1/src/asn1ct_check.erl | 26 +- lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl | 273 ++++++++----- lib/asn1/src/asn1ct_constructed_per.erl | 544 +++++++++++++++++-------- lib/asn1/src/asn1ct_eval_ext.funcs | 1 + lib/asn1/src/asn1ct_gen.erl | 18 +- lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 12 +- lib/asn1/src/asn1ct_gen_check.erl | 191 ++++++--- lib/asn1/src/asn1ct_imm.erl | 41 +- lib/asn1/src/asn1ct_value.erl | 24 +- lib/asn1/src/asn1rtt_ext.erl | 62 ++- lib/asn1/test/Makefile | 1 + lib/asn1/test/asn1_SUITE.erl | 76 +++- lib/asn1/test/asn1_SUITE_data/Maps.asn1 | 17 + lib/asn1/test/asn1_test_lib.erl | 105 ++++- lib/asn1/test/testContextSwitchingTypes.erl | 1 + lib/asn1/test/testInfObj.erl | 1 + lib/asn1/test/testMaps.erl | 50 +++ lib/asn1/test/testRfcs.erl | 50 ++- lib/asn1/test/testTCAP.erl | 1 + lib/asn1/test/testTimer.erl | 131 ++++-- lib/asn1/test/testUniqueObjectSets.erl | 1 + lib/asn1/test/test_compile_options.erl | 28 +- 27 files changed, 1349 insertions(+), 470 deletions(-) create mode 100644 lib/asn1/test/asn1_SUITE_data/Maps.asn1 create mode 100644 lib/asn1/test/testMaps.erl (limited to 'lib') diff --git a/lib/asn1/doc/src/asn1_getting_started.xml b/lib/asn1/doc/src/asn1_getting_started.xml index d40b294c39..d2b73d63c3 100644 --- a/lib/asn1/doc/src/asn1_getting_started.xml +++ b/lib/asn1/doc/src/asn1_getting_started.xml @@ -187,6 +187,14 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn

DER encoding rule. Only when using option -ber.

+ +maps + +

Use maps instead of records to represent the SEQUENCE and + SET types. No .hrl files will be generated. + See the Section + Map representation for SEQUENCE and SET + for more information.

+
+asn1config

This functionality works together with option @@ -766,8 +774,11 @@ Pdu ::= SEQUENCE { b REAL, c OBJECT IDENTIFIER, d NULL } -

This is a 4-component structure called Pdu. The record format - is the major format for representation of SEQUENCE in Erlang. +

This is a 4-component structure called Pdu. By default, + a SEQUENCE is represented by a record in Erlang. + It can also be represented as a map; see + + Map representation for SEQUENCE and SET. For each SEQUENCE and SET in an ASN.1 module an Erlang record declaration is generated. For Pdu, a record like the following is defined:

@@ -877,6 +888,48 @@ SExt ::= SEQUENCE { component, if present, otherwise the value asn1_NOVALUE.

+
+ + Map representation for SEQUENCE and SET +

If the ASN.1 module has been compiled with option maps, + the types SEQUENCE and SET are represented as maps.

+

In the following example, this ASN.1 specification is used:

+
+File DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+Seq1 ::= SEQUENCE {
+    a INTEGER DEFAULT 42,
+    b BOOLEAN OPTIONAL,
+    c IA5String
+}
+END   
+ +

Optional fields are to be omitted from the map if they have + no value:

+ +
+1> asn1ct:compile('File', [per,maps]).
+ok
+2> {ok,E} = 'File':encode('Seq1', #{a=>0,c=>"string"}).
+{ok,<<128,1,0,6,115,116,114,105,110,103>>} 
+ +

When decoding, optional fields will be omitted from the map:

+ +
+3> 'File':decode('Seq1', E).
+{ok,#{a => 0,c => "string"}}   
+ +

Default values can be omitted from the map:

+
+4> {ok,E2} = 'File':encode('Seq1', #{c=>"string"}).
+{ok,<<0,6,115,116,114,105,110,103>>}
+5> 'File':decode('Seq1', E2).
+{ok,#{a => 42,c => "string"}}   
+ +

It is not allowed to use the atoms asn1_VALUE and + asn1_DEFAULT with maps.

+
+
CHOICE @@ -1004,11 +1057,16 @@ T ::= CHOICE {
Naming of Records in .hrl Files +

When the option maps is given, no .hrl files + will be generated. The rest of this section describes the behavior + of the compiler when maps is not used.

+

When an ASN.1 specification is compiled, all defined types of type - SET or SEQUENCE result in a corresponding record in the - generated .hrl file. This is because the values for - SET and SEQUENCE are represented as records as - mentioned earlier.

+ SET or SEQUENCE result in a corresponding record in the + generated .hrl file. This is because the values for + SET and SEQUENCE are represented as records + by default.

+

Some special cases of this functionality are presented in the next section.

@@ -1144,9 +1202,10 @@ SS ::= SET {

This example shows that a function is generated by the compiler that returns a valid Erlang representation of the value, although the value is of a complex type.

-

Furthermore, a macro is generated for each value in the .hrl - file. So, the defined value tt can also be extracted by - ?tt in application code.

+

Furthermore, if the option maps is not used, + a macro is generated for each value in the .hrl + file. So, the defined value tt can also be extracted by + ?tt in application code.

diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index ebe1ce44dc..859d6a50bb 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -170,11 +170,24 @@ File3.asn as for ber.

+ maps + +

This option changes the representation of the types + SEQUENCE and SET to use maps (instead of + records). This option also suppresses the generation of + .hrl files.

+

For details, see Section + + Map representation for SEQUENCE and SET + in the User's Guide. +

+
compact_bit_string

The BIT STRING type is decoded to "compact notation". This option is not recommended for new code. + This option cannot be combined with the option maps.

For details, see Section @@ -188,6 +201,7 @@ File3.asn The BIT STRING type is decoded to the legacy format, that is, a list of zeroes and ones. This option is not recommended for new code. + This option cannot be combined with the option maps.

For details, see Section BIT STRING @@ -202,7 +216,8 @@ File3.asn marker="asn1_getting_started#BIT STRING">BIT STRING and Section OCTET STRING in the User's Guide.

-

This option is not recommended for new code.

+

This option is not recommended for new code. + This option cannot be combined with the option maps.

{n2n, EnumTypeName} diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl index 869ea310aa..a3e45ca915 100644 --- a/lib/asn1/src/asn1_db.erl +++ b/lib/asn1/src/asn1_db.erl @@ -20,7 +20,7 @@ %% -module(asn1_db). --export([dbstart/1,dbnew/2,dbload/1,dbload/3,dbsave/2,dbput/2, +-export([dbstart/1,dbnew/3,dbload/1,dbload/4,dbsave/2,dbput/2, dbput/3,dbget/2]). -export([dbstop/0]). @@ -37,13 +37,13 @@ dbstart(Includes0) -> put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)), ok. -dbload(Module, Erule, Mtime) -> - req({load, Module, Erule, Mtime}). +dbload(Module, Erule, Maps, Mtime) -> + req({load, Module, {Erule,Maps}, Mtime}). dbload(Module) -> req({load, Module, any, {{0,0,0},{0,0,0}}}). -dbnew(Module, Erule) -> req({new, Module, Erule}). +dbnew(Module, Erule, Maps) -> req({new, Module, {Erule,Maps}}). dbsave(OutFile, Module) -> cast({save, OutFile, Module}). dbput(Module, K, V) -> cast({set, Module, K, V}). dbput(Module, Kvs) -> cast({set, Module, Kvs}). @@ -110,19 +110,19 @@ loop(#state{parent = Parent, monitor = MRef, table = Table, ok = ets:tab2file(Mtab, TempFile), ok = file:rename(TempFile, OutFile), loop(State); - {From, {new, Mod, Erule}} -> + {From, {new, Mod, EruleMaps}} -> [] = ets:lookup(Table, Mod), %Assertion. ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []), ets:insert(Table, {Mod, ModTableId}), - ets:insert(ModTableId, {?MAGIC_KEY, info(Erule)}), + ets:insert(ModTableId, {?MAGIC_KEY, info(EruleMaps)}), reply(From, ok), loop(State); - {From, {load, Mod, Erule, Mtime}} -> + {From, {load, Mod, EruleMaps, Mtime}} -> case ets:member(Table, Mod) of true -> reply(From, ok); false -> - case load_table(Mod, Erule, Mtime, Includes) of + case load_table(Mod, EruleMaps, Mtime, Includes) of {ok, ModTableId} -> ets:insert(Table, {Mod, ModTableId}), reply(From, ok); @@ -151,20 +151,20 @@ lookup(Tab, K) -> [{K,V}] -> V end. -info(Erule) -> - {asn1ct:vsn(),Erule}. +info(EruleMaps) -> + {asn1ct:vsn(),EruleMaps}. -load_table(Mod, Erule, Mtime, Includes) -> +load_table(Mod, EruleMaps, Mtime, Includes) -> Base = lists:concat([Mod, ".asn1db"]), case path_find(Includes, Mtime, Base) of error -> error; - {ok,ModTab} when Erule =:= any -> + {ok,ModTab} when EruleMaps =:= any -> {ok,ModTab}; {ok,ModTab} -> Vsn = asn1ct:vsn(), case ets:lookup(ModTab, ?MAGIC_KEY) of - [{_,{Vsn,Erule}}] -> + [{_,{Vsn,EruleMaps}}] -> %% Correct version and encoding rule. {ok,ModTab}; _ -> diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl index 4b800f17c7..d3d76f9566 100644 --- a/lib/asn1/src/asn1_records.hrl +++ b/lib/asn1/src/asn1_records.hrl @@ -28,6 +28,7 @@ -define('COMPLETE_ENCODE',1). -define('TLV_DECODE',2). +-define(MISSING_IN_MAP, asn1__MISSING_IN_MAP). -record(module,{pos,name,defid,tagdefault='EXPLICIT',exports={exports,[]},imports={imports,[]}, extensiondefault=empty,typeorval}). @@ -103,6 +104,7 @@ aligned=false :: boolean(), rec_prefix="" :: string(), macro_prefix="" :: string(), + pack=record :: 'record' | 'map', options=[] :: [any()] }). diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 0a68395b49..d27f8897af 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -193,7 +193,7 @@ check_pass(#st{code=M,file=File,includes=Includes, erule=Erule,dbfile=DbFile,opts=Opts, inputmodules=InputModules}=St) -> start(Includes), - case asn1ct_check:storeindb(#state{erule=Erule}, M) of + case asn1ct_check:storeindb(#state{erule=Erule,options=Opts}, M) of ok -> Module = asn1_db:dbget(M#module.name, 'MODULE'), State = #state{mname=Module#module.name, @@ -216,8 +216,8 @@ check_pass(#st{code=M,file=File,includes=Includes, {error,St#st{error=Reason}} end. -save_pass(#st{code=M,erule=Erule}=St) -> - ok = asn1ct_check:storeindb(#state{erule=Erule}, M), +save_pass(#st{code=M,erule=Erule,opts=Opts}=St) -> + ok = asn1ct_check:storeindb(#state{erule=Erule,options=Opts}, M), {ok,St}. parse_listing(#st{code=Code,outfile=OutFile0}=St) -> @@ -842,6 +842,8 @@ generate({M,GenTOrV}, OutFile, EncodingRule, Options) -> Gen = init_gen_record(EncodingRule, Options), + check_maps_option(Gen), + %% create decoding function names and taglists for partial decode try specialized_decode_prepare(Gen, M) @@ -875,9 +877,13 @@ init_gen_record(EncodingRule, Options) -> Aligned = EncodingRule =:= per, RecPrefix = proplists:get_value(record_name_prefix, Options, ""), MacroPrefix = proplists:get_value(macro_name_prefix, Options, ""), + Pack = case proplists:get_value(maps, Options, false) of + true -> map; + false -> record + end, #gen{erule=Erule,der=Der,aligned=Aligned, rec_prefix=RecPrefix,macro_prefix=MacroPrefix, - options=Options}. + pack=Pack,options=Options}. setup_legacy_erlang_types(Opts) -> @@ -924,6 +930,26 @@ cleanup_bit_string_format() -> get_bit_string_format() -> get(bit_string_format). +check_maps_option(#gen{pack=map}) -> + case get_bit_string_format() of + bitstring -> + ok; + _ -> + Message1 = "The 'maps' option must not be combined with " + "'compact_bit_string' or 'legacy_bit_string'", + exit({error,{asn1,Message1}}) + end, + case use_legacy_types() of + false -> + ok; + true -> + Message2 = "The 'maps' option must not be combined with " + "'legacy_erlang_types'", + exit({error,{asn1,Message2}}) + end; +check_maps_option(#gen{}) -> + ok. + %% parse_and_save parses an asn1 spec and saves the unchecked parse %% tree in a data base file. @@ -933,22 +959,27 @@ parse_and_save(Module,S) -> SourceDir = S#state.sourcedir, Includes = [I || {i,I} <- Options], Erule = S#state.erule, + Maps = lists:member(maps, Options), case get_input_file(Module, [SourceDir|Includes]) of %% search for asn1 source {file,SuffixedASN1source} -> Mtime = filelib:last_modified(SuffixedASN1source), - case asn1_db:dbload(Module, Erule, Mtime) of + case asn1_db:dbload(Module, Erule, Maps, Mtime) of ok -> ok; error -> parse_and_save1(S, SuffixedASN1source, Options) end; - Err -> + Err when not Maps -> case asn1_db:dbload(Module) of ok -> + %% FIXME: This should be an error. warning("could not do a consistency check of the ~p file: no asn1 source file was found.~n", [lists:concat([Module,".asn1db"])],Options); error -> ok end, + {error,{asn1,input_file_error,Err}}; + Err -> + %% Always fail directly when the 'maps' option is used. {error,{asn1,input_file_error,Err}} end. diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index a01a22ddc4..321f4147f5 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -2239,12 +2239,18 @@ normalized_record(SorS,S,Value,Components,NameList) -> case is_record_normalized(S,NewName,Value,length(Components)) of true -> Value; - _ -> + false -> NoComps = length(Components), ListOfVals = normalize_seq_or_set(SorS,S,Value,Components,NameList,[]), - NoComps = length(ListOfVals), %% Assert - list_to_tuple([NewName|ListOfVals]) + NoComps = length(ListOfVals), %Assertion. + case use_maps(S) of + false -> + list_to_tuple([NewName|ListOfVals]); + true -> + create_map_value(Components, ListOfVals) + end end. + is_record_normalized(S,Name,V = #'Externalvaluereference'{},NumComps) -> case get_referenced_type(S,V) of {_M,#valuedef{type=_T1,value=V2}} -> @@ -2253,9 +2259,20 @@ is_record_normalized(S,Name,V = #'Externalvaluereference'{},NumComps) -> end; is_record_normalized(_S,Name,Value,NumComps) when is_tuple(Value) -> (tuple_size(Value) =:= (NumComps + 1)) andalso (element(1, Value) =:= Name); +is_record_normalized(_S, _Name, Value, _NumComps) when is_map(Value) -> + true; is_record_normalized(_,_,_,_) -> false. +use_maps(#state{options=Opts}) -> + lists:member(maps, Opts). + +create_map_value(Components, ListOfVals) -> + Zipped = lists:zip(Components, ListOfVals), + L = [{Name,V} || {#'ComponentType'{name=Name},V} <- Zipped, + V =/= asn1_NOVALUE], + maps:from_list(L). + normalize_seq_or_set(SorS, S, [{#seqtag{val=Cname},V}|Vs], [#'ComponentType'{name=Cname,typespec=TS}|Cs], @@ -5674,7 +5691,8 @@ storeindb(S0, #module{name=ModName,typeorval=TVlist0}=M) -> storeindb_1(S, #module{name=ModName}=M, TVlist0, TVlist) -> NewM = M#module{typeorval=findtypes_and_values(TVlist0)}, - asn1_db:dbnew(ModName, S#state.erule), + Maps = lists:member(maps, S#state.options), + asn1_db:dbnew(ModName, S#state.erule, Maps), asn1_db:dbput(ModName, 'MODULE', NewM), asn1_db:dbput(ModName, TVlist), include_default_class(S, NewM#module.name), diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl index cc1196c5cb..16af09bca9 100644 --- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl @@ -57,7 +57,7 @@ %%=============================================================================== %%=============================================================================== -gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> +gen_encode_sequence(Gen, Typename, #type{}=D) -> asn1ct_name:start(), asn1ct_name:new(term), asn1ct_name:new(bytes), @@ -67,8 +67,12 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> ValName = case Typename of ['EXTERNAL'] -> + Tr = case Gen of + #gen{pack=record} -> transform_to_EXTERNAL1990; + #gen{pack=map} -> transform_to_EXTERNAL1990_maps + end, emit([indent(4),"NewVal = ", - {call,ext,transform_to_EXTERNAL1990,["Val"]}, + {call,ext,Tr,["Val"]}, com,nl]), "NewVal"; _ -> @@ -90,18 +94,9 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> {Rl,El} -> Rl ++ El; _ -> CompList end, - -%% don't match recordname for now, because of compatibility reasons -%% emit(["{'",asn1ct_gen:list2rname(Typename),"'"]), - emit(["{_"]), - case length(CompList1) of - 0 -> - true; - CompListLen -> - emit([","]), - mkcindexlist([Tc || Tc <- lists:seq(1,CompListLen)]) - end, - emit(["} = ",ValName,",",nl]), + + enc_match_input(Gen, ValName, CompList1), + EncObj = case TableConsInfo of #simpletableattributes{usedclassfield=Used, @@ -125,7 +120,7 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> emit([ObjectEncode," = ",nl, " ",{asis,ObjSetMod},":'getenc_",ObjSetName, "'("]), - ValueMatch = value_match(ValueIndex, + ValueMatch = value_match(Gen, ValueIndex, lists:concat(["Cindex",N])), emit([indent(35),ValueMatch,"),",nl]), {AttrN,ObjectEncode}; @@ -144,7 +139,7 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> end end, - gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj), + gen_enc_sequence_call(Gen, Typename, CompList1, 1, Ext, EncObj), emit([nl," BytesSoFar = "]), case SeqOrSet of @@ -168,7 +163,36 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) -> call(encode_tags, ["TagIn","BytesSoFar","LenSoFar"]), emit([".",nl]). -gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> +enc_match_input(#gen{pack=record}, ValName, CompList) -> + Len = length(CompList), + Vars = [lists:concat(["Cindex",N]) || N <- lists:seq(1, Len)], + RecordName = "_", + emit(["{",lists:join(",", [RecordName|Vars]),"} = ",ValName,com,nl]); +enc_match_input(#gen{pack=map}, ValName, CompList) -> + Len = length(CompList), + Vars = [lists:concat(["Cindex",N]) || N <- lists:seq(1, Len)], + Zipped = lists:zip(CompList, Vars), + M = [[{asis,Name},":=",Var] || + {#'ComponentType'{prop=mandatory,name=Name},Var} <- Zipped], + case M of + [] -> + ok; + [_|_] -> + emit(["#{",lists:join(",", M),"} = ",ValName,com,nl]) + end, + Os0 = [{Name,Var} || + {#'ComponentType'{prop=Prop,name=Name},Var} <- Zipped, + Prop =/= mandatory], + F = fun({Name,Var}) -> + [Var," = case ",ValName," of\n" + " #{",{asis,Name},":=",Var,"_0} -> ", + Var,"_0;\n" + " _ -> ",atom_to_list(?MISSING_IN_MAP),"\n" + "end"] + end, + emit(lists:join(",\n", [F(E) || E <- Os0]++[[]])). + +gen_decode_sequence(Gen, Typename, #type{}=D) -> asn1ct_name:start(), asn1ct_name:new(tag), #'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def, @@ -225,15 +249,20 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> _ -> {false,false} end, - RecordName = lists:concat([get_record_name_prefix(Erules), - asn1ct_gen:list2rname(Typename)]), - case gen_dec_sequence_call(Erules,Typename,CompList2,Ext,DecObjInf) of - no_terms -> % an empty sequence - emit([nl,nl]), - demit(["Result = "]), %dbg - %% return value as record + RecordName0 = lists:concat([get_record_name_prefix(Gen), + asn1ct_gen:list2rname(Typename)]), + RecordName = list_to_atom(RecordName0), + case gen_dec_sequence_call(Gen, Typename, CompList2, Ext, DecObjInf) of + no_terms -> % an empty sequence asn1ct_name:new(rb), - emit([" {'",RecordName,"'}.",nl,nl]); + case Gen of + #gen{pack=record} -> + emit([nl,nl, + " {'",RecordName,"'}.",nl,nl]); + #gen{pack=map} -> + emit([nl,nl, + " #{}.",nl,nl]) + end; {LeadingAttrTerm,PostponedDecArgs} -> emit([nl]), case {LeadingAttrTerm,PostponedDecArgs} of @@ -243,7 +272,7 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> ok; {[{ObjSetRef,LeadingAttr,Term}],PostponedDecArgs} -> DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])), - ValueMatch = value_match(ValueIndex,Term), + ValueMatch = value_match(Gen, ValueIndex,Term), {ObjSetMod,ObjSetName} = ObjSetRef, emit([DecObj," =",nl, " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(", @@ -263,22 +292,64 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) -> "end,",nl]) end, asn1ct_name:new(rb), - case Typename of - ['EXTERNAL'] -> - emit([" OldFormat={'",RecordName, - "', "]), - mkvlist(asn1ct_name:all(term)), - emit(["},",nl]), - emit([" ", - {call,ext,transform_to_EXTERNAL1994, - ["OldFormat"]},".",nl]); - _ -> - emit([" {'",RecordName,"', "]), - mkvlist(asn1ct_name:all(term)), - emit(["}.",nl,nl]) - end + gen_dec_pack(Gen, RecordName, Typename, CompList), + emit([".",nl]) end. +gen_dec_pack(Gen, RecordName, Typename, CompList) -> + case Typename of + ['EXTERNAL'] -> + dec_external(Gen, RecordName); + _ -> + asn1ct_name:new(res), + gen_dec_do_pack(Gen, RecordName, CompList), + emit([com,nl, + {curr,res}]) + end. + +dec_external(#gen{pack=record}, RecordName) -> + All = [{var,Term} || Term <- asn1ct_name:all(term)], + Record = [{asis,RecordName}|All], + emit(["OldFormat={",lists:join(",", Record),"},",nl, + {call,ext,transform_to_EXTERNAL1994, + ["OldFormat"]}]); +dec_external(#gen{pack=map}, _RecordName) -> + Vars = asn1ct_name:all(term), + Names = ['direct-reference','indirect-reference', + 'data-value-descriptor',encoding], + Zipped = lists:zip(Names, Vars), + MapInit = lists:join(",", [["'",N,"'=>",{var,V}] || {N,V} <- Zipped]), + emit(["OldFormat = #{",MapInit,"}",com,nl, + "ASN11994Format =",nl, + {call,ext,transform_to_EXTERNAL1994_maps, + ["OldFormat"]}]). + +gen_dec_do_pack(#gen{pack=record}, RecordName, _CompList) -> + All = asn1ct_name:all(term), + L = [{asis,RecordName}|[{var,Var} || Var <- All]], + emit([{curr,res}," = {",lists:join(",", L),"}"]); +gen_dec_do_pack(#gen{pack=map}, _, CompList) -> + Zipped = lists:zip(CompList, asn1ct_name:all(term)), + PF = fun({#'ComponentType'{prop='OPTIONAL'},_}) -> false; + ({_,_}) -> true + end, + {Mandatory,Optional} = lists:partition(PF, Zipped), + L = [[{asis,Name},"=>",{var,Var}] || + {#'ComponentType'{name=Name},Var} <- Mandatory], + emit([{curr,res}," = #{",lists:join(",", L),"}"]), + gen_dec_map_optional(Optional). + +gen_dec_map_optional([{#'ComponentType'{name=Name},Var}|T]) -> + asn1ct_name:new(res), + emit([com,nl, + {curr,res}," = case ",{var,Var}," of",nl, + " asn1_NOVALUE -> ",{prev,res},";",nl, + " _ -> ",{prev,res},"#{",{asis,Name},"=>",{var,Var},"}",nl, + "end"]), + gen_dec_map_optional(T); +gen_dec_map_optional([]) -> + ok. + gen_dec_postponed_decs(_,[]) -> emit(nl); gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term, @@ -327,7 +398,7 @@ emit_opt_or_mand_check(Value,TmpTerm) -> gen_encode_set(Erules,Typename,D) when is_record(D,type) -> gen_encode_sequence(Erules,Typename,D). -gen_decode_set(Erules,Typename,D) when is_record(D,type) -> +gen_decode_set(Gen, Typename, #type{}=D) -> asn1ct_name:start(), %% asn1ct_name:new(term), asn1ct_name:new(tag), @@ -393,7 +464,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> _ -> emit(["SetFun = fun(FunTlv) ->", nl]), emit(["case FunTlv of ",nl]), - NextNum = gen_dec_set_cases(Erules,Typename,CompList,1), + NextNum = gen_dec_set_cases(Gen, Typename, CompList, 1), emit([indent(6), {curr,else}," -> ",nl, indent(9),"{",NextNum,", ",{curr,else},"}",nl]), emit([indent(3),"end",nl]), @@ -405,14 +476,17 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:new(tlv) end, - RecordName = lists:concat([get_record_name_prefix(Erules), - asn1ct_gen:list2rname(Typename)]), - case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of - no_terms -> % an empty sequence - emit([nl,nl]), - demit(["Result = "]), %dbg - %% return value as record - emit([" {'",RecordName,"'}.",nl]); + RecordName0 = lists:concat([get_record_name_prefix(Gen), + asn1ct_gen:list2rname(Typename)]), + RecordName = list_to_atom(RecordName0), + case gen_dec_sequence_call(Gen, Typename, CompList, Ext, DecObjInf) of + no_terms -> % an empty SET + case Gen of + #gen{pack=record} -> + emit([nl,nl," {'",RecordName,"'}.",nl,nl]); + #gen{pack=map} -> + emit([nl,nl," #{}.",nl,nl]) + end; {LeadingAttrTerm,PostponedDecArgs} -> emit([nl]), case {LeadingAttrTerm,PostponedDecArgs} of @@ -422,7 +496,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> ok; {[{ObjSetRef,LeadingAttr,Term}],PostponedDecArgs} -> DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])), - ValueMatch = value_match(ValueIndex,Term), + ValueMatch = value_match(Gen, ValueIndex, Term), {ObjSetMod,ObjSetName} = ObjSetRef, emit([DecObj," =",nl, " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(", @@ -441,9 +515,8 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) -> "}}}) % extra fields not allowed",nl, "end,",nl]) end, - emit([" {'",RecordName,"', "]), - mkvlist(asn1ct_name:all(term)), - emit(["}.",nl]) + gen_dec_pack(Gen, RecordName, Typename, CompList), + emit([".",nl]) end. @@ -1025,35 +1098,44 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj) emit([nl,indent(7),"end"]) end. -gen_optormand_case(mandatory, _Erules, _TopType, _Cname, _Type, _Element) -> +gen_optormand_case(mandatory, _Gen, _TopType, _Cname, _Type, _Element) -> ok; -gen_optormand_case('OPTIONAL', Erules, _TopType, _Cname, _Type, Element) -> +gen_optormand_case('OPTIONAL', Gen, _TopType, _Cname, _Type, Element) -> emit([" case ",Element," of",nl]), - emit([indent(9),"asn1_NOVALUE -> {", - empty_lb(Erules),",0};",nl]), + Missing = case Gen of + #gen{pack=record} -> asn1_NOVALUE; + #gen{pack=map} -> ?MISSING_IN_MAP + end, + emit([indent(9),Missing," -> {", + empty_lb(Gen),",0};",nl]), emit([indent(9),"_ ->",nl,indent(12)]); gen_optormand_case({'DEFAULT',DefaultValue}, Gen, _TopType, _Cname, Type, Element) -> CurrMod = get(currmod), case Gen of #gen{erule=ber,der=true} -> - asn1ct_gen_check:emit(Type, DefaultValue, Element); - #gen{erule=ber,der=false} -> - emit([" case ",Element," of",nl]), - emit([indent(9),"asn1_DEFAULT -> {", - empty_lb(Gen), - ",0};",nl]), - case DefaultValue of - #'Externalvaluereference'{module=CurrMod, - value=V} -> - emit([indent(9),"?",{asis,V}," -> {", - empty_lb(Gen),",0};",nl]); - _ -> - emit([indent(9),{asis, - DefaultValue}," -> {", - empty_lb(Gen),",0};",nl]) - end, - emit([indent(9),"_ ->",nl,indent(12)]) + asn1ct_gen_check:emit(Gen, Type, DefaultValue, Element); + #gen{erule=ber,der=false,pack=Pack} -> + Ind9 = indent(9), + DefMarker = case Pack of + record -> asn1_DEFAULT; + map -> ?MISSING_IN_MAP + end, + emit([" case ",Element," of",nl, + Ind9,{asis,DefMarker}," ->",nl, + Ind9,indent(3),"{",empty_lb(Gen),",0};",nl, + Ind9,"_ when ",Element," =:= "]), + Dv = case DefaultValue of + #'Externalvaluereference'{module=CurrMod, + value=V} -> + ["?",{asis,V}]; + _ -> + [{asis,DefaultValue}] + end, + emit(Dv++[" ->",nl, + Ind9,indent(3),"{",empty_lb(Gen),",0};",nl, + Ind9,"_ ->",nl, + indent(12)]) end. %% Use for SEQUENCE OF and CHOICE. @@ -1204,7 +1286,7 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC (Type#type.def)#'ObjectClassFieldType'.fieldname, [{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)), asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}]; -gen_dec_call(InnerType, _Erules, TopType, Cname, Type, BytesVar, +gen_dec_call(InnerType, Gen, TopType, Cname, Type, BytesVar, Tag, _PrimOptOrMand, _OptOrMand, DecObjInf,_) -> WhatKind = asn1ct_gen:type(InnerType), gen_dec_call1(WhatKind, InnerType, TopType, Cname, @@ -1212,7 +1294,7 @@ gen_dec_call(InnerType, _Erules, TopType, Cname, Type, BytesVar, case DecObjInf of {Cname,{_,OSet,_UniqueFName,ValIndex}} -> Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)), - ValueMatch = value_match(ValIndex,Term), + ValueMatch = value_match(Gen, ValIndex, Term), {ObjSetMod,ObjSetName} = OSet, emit([",",nl,"ObjFun = ",{asis,ObjSetMod},":'getdec_",ObjSetName, "'(",ValueMatch,")"]); @@ -1337,19 +1419,6 @@ gen_dec_call1(WhatKind, _, TopType, Cname, Type, BytesVar, Tag) -> indent(N) -> lists:duplicate(N,32). % 32 = space -mkcindexlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ " - emit(["Cindex",H,Sep]), - mkcindexlist([T1|T], Sep); -mkcindexlist([H|T], Sep) -> - emit(["Cindex",H]), - mkcindexlist(T, Sep); -mkcindexlist([], _) -> - true. - -mkcindexlist(L) -> - mkcindexlist(L,", "). - - mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ " emit([{var,H},Sep]), mkvlist([T1|T], Sep); @@ -1429,16 +1498,22 @@ mkfuncname(TopType,Cname,WhatKind,Prefix,Suffix) -> empty_lb(#gen{erule=ber}) -> "<<>>". -value_match(Index,Value) when is_atom(Value) -> - value_match(Index,atom_to_list(Value)); -value_match([],Value) -> +value_match(#gen{pack=record}, VIs, Value) -> + value_match_rec(VIs, Value); +value_match(#gen{pack=map}, VIs, Value) -> + value_match_map(VIs, Value). + +value_match_rec([], Value) -> + Value; +value_match_rec([{VI,_}|VIs], Value0) -> + Value = value_match_rec(VIs, Value0), + lists:concat(["element(",VI,", ",Value,")"]). + +value_match_map([], Value) -> Value; -value_match([{VI,_}|VIs],Value) -> - value_match1(Value,VIs,lists:concat(["element(",VI,","]),1). -value_match1(Value,[],Acc,Depth) -> - Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")")); -value_match1(Value,[{VI,_}|VIs],Acc,Depth) -> - value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1). +value_match_map([{_,Name}|VIs], Value0) -> + Value = value_match_map(VIs, Value0), + lists:concat(["maps:get(",Name,", ",Value,")"]). call(F, Args) -> asn1ct_func:call(ber, F, Args). diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index e817cf8677..b7579c8065 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -36,6 +36,7 @@ -type type_name() :: any(). + %% ENCODE GENERATOR FOR SEQUENCE TYPE ** ********** @@ -61,29 +62,20 @@ gen_encode_constructed(Erule, Typename, #type{}=D) -> gen_encode_constructed_imm(Gen, Typename, #type{}=D) -> {CompList,TableConsInfo} = enc_complist(D), - ExternalImm = - case Typename of - ['EXTERNAL'] -> - Next = asn1ct_gen:mk_var(asn1ct_name:next(val)), - Curr = asn1ct_gen:mk_var(asn1ct_name:curr(val)), - asn1ct_name:new(val), - [{call,ext,transform_to_EXTERNAL1990,[{var,Curr}],{var,Next}}]; - _ -> - [] - end, + ExternalImm = external_imm(Gen, Typename), Optionals = optionals(to_textual_order(CompList)), ImmOptionals = enc_optionals(Gen, Optionals), Ext = extensible_enc(CompList), Aligned = is_aligned(Gen), ExtImm = case Ext of {ext,ExtPos,NumExt} when NumExt > 0 -> - gen_encode_extaddgroup(CompList), + gen_encode_extaddgroup(Gen, CompList), Value = make_var(val), - asn1ct_imm:per_enc_extensions(Value, ExtPos, - NumExt, Aligned); + enc_extensions(Gen, Value, ExtPos, NumExt, Aligned); _ -> [] end, + MatchImm = enc_map_match(Gen, CompList), {EncObj,ObjSetImm} = enc_table(Gen, TableConsInfo, D), ImmSetExt = case Ext of @@ -95,9 +87,29 @@ gen_encode_constructed_imm(Gen, Typename, #type{}=D) -> [] end, ImmBody = gen_enc_components_call(Gen, Typename, CompList, EncObj, Ext), - ExternalImm ++ ExtImm ++ ObjSetImm ++ + ExternalImm ++ MatchImm ++ ExtImm ++ ObjSetImm ++ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody). +external_imm(Gen, ['EXTERNAL']) -> + Next = asn1ct_gen:mk_var(asn1ct_name:next(val)), + Curr = asn1ct_gen:mk_var(asn1ct_name:curr(val)), + asn1ct_name:new(val), + F = case Gen of + #gen{pack=record} -> transform_to_EXTERNAL1990; + #gen{pack=map} -> transform_to_EXTERNAL1990_maps + end, + [{call,ext,F,[{var,Curr}],{var,Next}}]; +external_imm(_, _) -> + []. + +enc_extensions(#gen{pack=record}, Value, ExtPos, NumExt, Aligned) -> + asn1ct_imm:per_enc_extensions(Value, ExtPos, NumExt, Aligned); +enc_extensions(#gen{pack=map}, Value, ExtPos, NumExt, Aligned) -> + Vars = [{var,lists:concat(["Input@",Pos])} || + Pos <- lists:seq(ExtPos, ExtPos+NumExt-1)], + Undefined = atom_to_list(?MISSING_IN_MAP), + asn1ct_imm:per_enc_extensions_map(Value, Vars, Undefined, Aligned). + enc_complist(#type{def=Def}) -> case Def of #'SEQUENCE'{tablecinf=TCI,components=CL0,extaddgroup=ExtAddGroup} -> @@ -127,7 +139,7 @@ enc_table(Gen, #simpletableattributes{objectsetname=ObjectSet, asn1_db:dbget(Module, ObjSetName), case MustGen of true -> - ValueIndex = ValueIndex0 ++ [{N+1,top}], + ValueIndex = ValueIndex0 ++ [{N+1,'ASN1_top'}], Val = make_var(val), {ObjSetImm,Dst} = enc_dig_out_value(Gen, ValueIndex, Val), {{AttrN,Dst},ObjSetImm}; @@ -151,41 +163,118 @@ enc_optionals(Gen, Optionals) -> Var = make_var(val), enc_optionals_1(Gen, Optionals, Var). -enc_optionals_1(Gen, [{Pos,DefVals}|T], Var) -> +enc_optionals_1(#gen{pack=record}=Gen, [{Pos,DefVals}|T], Var) -> {Imm0,Element} = asn1ct_imm:enc_element(Pos+1, Var), Imm = asn1ct_imm:per_enc_optional(Element, DefVals), [Imm0++Imm|enc_optionals_1(Gen, T, Var)]; +enc_optionals_1(#gen{pack=map}=Gen, [{Pos,DefVals0}|T], V) -> + Var = {var,lists:concat(["Input@",Pos])}, + DefVals = translate_missing_value(Gen, DefVals0), + Imm = asn1ct_imm:per_enc_optional(Var, DefVals), + [Imm|enc_optionals_1(Gen, T, V)]; enc_optionals_1(_, [], _) -> []. -gen_encode_extaddgroup(CompList) -> +enc_map_match(#gen{pack=record}, _Cs) -> + []; +enc_map_match(#gen{pack=map}, Cs0) -> + Var0 = "Input", + Cs = enc_flatten_components(Cs0), + M = [[quote_atom(Name),":=",lists:concat([Var0,"@",Order])] || + #'ComponentType'{prop=mandatory,name=Name, + textual_order=Order} <- Cs], + Mand = case M of + [] -> + []; + [_|_] -> + Patt = {expr,lists:flatten(["#{",lists:join(",", M),"}"])}, + [{assign,Patt,{var,asn1ct_name:curr(val)}}] + end, + + Os0 = [{Name,Order} || + #'ComponentType'{prop=Prop,name=Name, + textual_order=Order} <- Cs, + Prop =/= mandatory], + {var,Val} = make_var(val), + F = fun({Name,Order}) -> + Var = lists:concat([Var0,"@",Order]), + P0 = ["case ",Val," of\n" + " #{",quote_atom(Name),":=",Var,"_0} -> ", + Var,"_0;\n" + " _ -> ",atom_to_list(?MISSING_IN_MAP),"\n" + "end"], + P = lists:flatten(P0), + {assign,{var,Var},P} + end, + Os = [F(O) || O <- Os0], + Mand ++ Os. + +enc_flatten_components({Root1,Ext0,Root2}=CL) -> + {_,Gs} = extgroup_pos_and_length(CL), + Ext = wrap_extensionAdditionGroups(Ext0, Gs), + Root1 ++ Root2 ++ [mark_optional(C) || C <- Ext]; +enc_flatten_components({Root,Ext}) -> + enc_flatten_components({Root,Ext,[]}); +enc_flatten_components(Cs) -> + Cs. + +gen_encode_extaddgroup(#gen{pack=record}, CompList) -> case extgroup_pos_and_length(CompList) of {extgrouppos,[]} -> ok; {extgrouppos,ExtGroupPosLenList} -> - _ = [do_gen_encode_extaddgroup(G) || G <- ExtGroupPosLenList], + _ = [gen_encode_eag_record(G) || + G <- ExtGroupPosLenList], ok - end. + end; +gen_encode_extaddgroup(#gen{pack=map}, Cs0) -> + Cs = enc_flatten_components(Cs0), + gen_encode_eag_map(Cs). + +gen_encode_eag_map([#'ComponentType'{name=Group,typespec=Type}|Cs]) -> + case Type of + #type{def=#'SEQUENCE'{extaddgroup=G,components=GCs0}} + when is_integer(G) -> + Ns = [N || #'ComponentType'{name=N,prop=mandatory} <- GCs0], + test_for_mandatory(Ns, Group), + gen_encode_eag_map(Cs); + _ -> + gen_encode_eag_map(Cs) + end; +gen_encode_eag_map([]) -> + ok. -do_gen_encode_extaddgroup({ActualGroupPos,GroupVirtualPos,GroupLen}) -> +test_for_mandatory([Mand|_], Group) -> + emit([{next,val}," = case ",{curr,val}," of",nl, + "#{",quote_atom(Mand),":=_} -> ", + {curr,val},"#{",{asis,Group},"=>",{curr,val},"};",nl, + "#{} -> ",{curr,val},nl, + "end,",nl]), + asn1ct_name:new(val); +test_for_mandatory([], _) -> + ok. + +gen_encode_eag_record({ActualPos,VirtualPos,Len}) -> Val = asn1ct_gen:mk_var(asn1ct_name:curr(val)), - Elements = make_elements(GroupVirtualPos+1, - Val, - lists:seq(1, GroupLen)), - Expr = any_non_value(GroupVirtualPos+1, Val, GroupLen, ""), + Elements = get_input_vars(Val, VirtualPos, Len), + Expr = any_non_value(Val, VirtualPos, Len), emit([{next,val}," = case ",Expr," of",nl, - "false -> setelement(",{asis,ActualGroupPos+1},", ", + "false -> setelement(",{asis,ActualPos+1},", ", {curr,val},", asn1_NOVALUE);",nl, - "true -> setelement(",{asis,ActualGroupPos+1},", ", + "true -> setelement(",{asis,ActualPos+1},", ", {curr,val},", {extaddgroup,", Elements,"})",nl, "end,",nl]), asn1ct_name:new(val). -any_non_value(_, _, 0, _) -> +any_non_value(Val, Pos, N) -> + L = any_non_value_1(Val, Pos, N), + lists:join(" orelse ", L). + +any_non_value_1(_, _, 0) -> []; -any_non_value(Pos, Val, N, Sep) -> - Sep ++ [make_element(Pos, Val)," =/= asn1_NOVALUE"] ++ - any_non_value(Pos+1, Val, N-1, [" orelse",nl]). +any_non_value_1(Val, Pos, N) -> + Var = get_input_var(Val, Pos), + [Var ++ " =/= asn1_NOVALUE"|any_non_value_1(Val, Pos+1, N-1)]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% generate decode function for SEQUENCE and SET @@ -346,27 +435,78 @@ gen_dec_objsets_fun(Gen, ObjSetInfo) -> end. gen_dec_pack(Gen, Typename, CompList) -> - RecordName = record_name(Gen, Typename), case Typename of ['EXTERNAL'] -> - emit({" OldFormat={'",RecordName, - "'"}), - mkvlist(asn1ct_name:all(term)), - emit({"},",nl}), - emit([" ASN11994Format =",nl, - " ", - {call,ext,transform_to_EXTERNAL1994, - ["OldFormat"]},com,nl]), - emit(" {ASN11994Format,"); + dec_external(Gen, Typename); _ -> - emit(["{{'",RecordName,"'"]), - %% CompList is used here because we don't want - %% ExtensionAdditionGroups to be wrapped in SEQUENCES when - %% we are ordering the fields according to textual order - mkvlist(textual_order(CompList, asn1ct_name:all(term))), - emit("},") - end, - emit({{curr,bytes},"}"}). + asn1ct_name:new(res), + gen_dec_do_pack(Gen, Typename, CompList), + emit([com,nl, + "{",{curr,res},",",{curr,bytes},"}"]) + end. + +dec_external(#gen{pack=record}=Gen, Typename) -> + RecordName = list_to_atom(record_name(Gen, Typename)), + All = [{var,Term} || Term <- asn1ct_name:all(term)], + Record = [{asis,RecordName}|All], + emit(["OldFormat={",lists:join(",", Record),"},",nl, + "ASN11994Format =",nl, + {call,ext,transform_to_EXTERNAL1994, + ["OldFormat"]},com,nl, + "{ASN11994Format,",{curr,bytes},"}"]); +dec_external(#gen{pack=map}, _Typename) -> + Vars = asn1ct_name:all(term), + Names = ['direct-reference','indirect-reference', + 'data-value-descriptor',encoding], + Zipped = lists:zip(Names, Vars), + MapInit = lists:join(",", [["'",N,"'=>",{var,V}] || {N,V} <- Zipped]), + emit(["OldFormat = #{",MapInit,"}",com,nl, + "ASN11994Format =",nl, + {call,ext,transform_to_EXTERNAL1994_maps, + ["OldFormat"]},com,nl, + "{ASN11994Format,",{curr,bytes},"}"]). + +gen_dec_do_pack(#gen{pack=record}=Gen, TypeName, CompList) -> + Zipped0 = zip_components(CompList, asn1ct_name:all(term)), + Zipped = textual_order(Zipped0), + RecordName = ["'",record_name(Gen, TypeName),"'"], + L = [RecordName|[{var,Var} || {_,Var} <- Zipped]], + emit([{curr,res}," = {",lists:join(",", L),"}"]); +gen_dec_do_pack(#gen{pack=map}, _, CompList0) -> + CompList = enc_flatten_components(CompList0), + Zipped0 = zip_components(CompList, asn1ct_name:all(term)), + Zipped = textual_order(Zipped0), + PF = fun({#'ComponentType'{prop='OPTIONAL'},_}) -> false; + ({_,_}) -> true + end, + {Mandatory,Optional} = lists:partition(PF, Zipped), + L = [[{asis,Name},"=>",{var,Var}] || + {#'ComponentType'{name=Name},Var} <- Mandatory], + emit([{curr,res}," = #{",lists:join(",", L),"}"]), + gen_dec_map_optional(Optional), + gen_dec_merge_maps(asn1ct_name:all(map)). + +gen_dec_map_optional([{#'ComponentType'{name=Name},Var}|T]) -> + asn1ct_name:new(res), + emit([com,nl, + {curr,res}," = case ",{var,Var}," of",nl, + " asn1_NOVALUE -> ",{prev,res},";",nl, + " _ -> ",{prev,res},"#{",{asis,Name},"=>",{var,Var},"}",nl, + "end"]), + gen_dec_map_optional(T); +gen_dec_map_optional([]) -> + ok. + +gen_dec_merge_maps([M|Ms]) -> + asn1ct_name:new(res), + emit([com,nl, + {curr,res}," = maps:merge(",{prev,res},", ",{var,M},")"]), + gen_dec_merge_maps(Ms); +gen_dec_merge_maps([]) -> + ok. + +quote_atom(A) when is_atom(A) -> + io_lib:format("~p", [A]). %% record_name([TypeName]) -> RecordNameString %% Construct a record name for the constructed type, ignoring any @@ -391,16 +531,26 @@ filter_ext_add_groups([H|T], Acc) -> filter_ext_add_groups(T, [H|Acc]); filter_ext_add_groups([], Acc) -> Acc. -textual_order([#'ComponentType'{textual_order=undefined}|_], TermList) -> - TermList; -textual_order(CompList, TermList) when is_list(CompList) -> - OrderList = [Ix||#'ComponentType'{textual_order=Ix} <- CompList], - Zipped = lists:sort(lists:zip(OrderList, TermList)), - [Term || {_,Term} <- Zipped]; -textual_order({Root,Ext}, TermList) -> - textual_order(Root ++ Ext, TermList); -textual_order({R1,Ext,R2}, TermList) -> - textual_order(R1 ++ R2 ++ Ext, TermList). +zip_components({Root,Ext}, Vars) -> + zip_components({Root,Ext,[]}, Vars); +zip_components({R1,Ext0,R2}, Vars) -> + Ext = [mark_optional(C) || C <- Ext0], + zip_components(R1++R2++Ext, Vars); +zip_components(Cs, Vars) when is_list(Cs) -> + zip_components_1(Cs, Vars). + +zip_components_1([#'ComponentType'{}=C|Cs], [V|Vs]) -> + [{C,V}|zip_components_1(Cs, Vs)]; +zip_components_1([_|Cs], Vs) -> + zip_components_1(Cs, Vs); +zip_components_1([], []) -> + []. + +textual_order([{#'ComponentType'{textual_order=undefined},_}|_]=L) -> + L; +textual_order(L0) -> + L = [{Ix,P} || {#'ComponentType'{textual_order=Ix},_}=P <- L0], + [C || {_,C} <- lists:sort(L)]. to_textual_order({Root,Ext}) -> {to_textual_order(Root),Ext}; @@ -469,7 +619,7 @@ dec_objset_default(N, _, _, true) -> end]). dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) -> - emit([{asis,N},"(Bytes, ",{asis,Id},") ->",nl]), + emit([{asis,N},"(Bytes, Id) when Id =:= ",{asis,Id}," ->",nl]), dec_objset_2(Erule, Obj, RestFields, Typename). dec_objset_2(Erule, Obj, RestFields0, Typename) -> @@ -650,22 +800,7 @@ gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% General and special help functions (not exported) - -mkvlist([H|T]) -> - emit(","), - mkvlist2([H|T]); -mkvlist([]) -> - true. -mkvlist2([H,T1|T]) -> - emit({{var,H},","}), - mkvlist2([T1|T]); -mkvlist2([H|T]) -> - emit({{var,H}}), - mkvlist2(T); -mkvlist2([]) -> - true. - +%% General and special help functions (not exported) extensible_dec(CompList) when is_list(CompList) -> noext; @@ -837,32 +972,52 @@ mark_optional(#'ComponentType'{prop=Prop0}=C) -> 'OPTIONAL'=Keep -> Keep; {'DEFAULT',_}=Keep -> Keep end, - C#'ComponentType'{prop=Prop}. + C#'ComponentType'{prop=Prop}; +mark_optional(Other) -> + Other. -gen_enc_components_call1(Erule, TopType, [C|Rest], DynamicEnc, Ext) -> +gen_enc_components_call1(Gen, TopType, [C|Rest], DynamicEnc, Ext) -> #'ComponentType'{name=Cname,typespec=Type, - prop=Prop,textual_order=TermNo} = C, - Val = make_var(val), - {Imm0,Element} = asn1ct_imm:enc_element(TermNo+1, Val), - Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, + prop=Prop,textual_order=Num} = C, + {Imm0,Element} = enc_fetch_field(Gen, Num, Prop), + Imm1 = gen_enc_line_imm(Gen, TopType, Cname, Type, Element, DynamicEnc, Ext), Imm2 = case Prop of mandatory -> Imm1; 'OPTIONAL' -> - asn1ct_imm:enc_absent(Element, [asn1_NOVALUE], Imm1); + enc_absent(Gen, Element, [asn1_NOVALUE], Imm1); {'DEFAULT',Def} -> DefValues = def_values(Type, Def), - asn1ct_imm:enc_absent(Element, DefValues, Imm1) + enc_absent(Gen, Element, DefValues, Imm1) end, Imm = case Imm2 of [] -> []; _ -> Imm0 ++ Imm2 end, - [Imm|gen_enc_components_call1(Erule, TopType, Rest, DynamicEnc, Ext)]; -gen_enc_components_call1(_Erule, _TopType, [], _, _) -> + [Imm|gen_enc_components_call1(Gen, TopType, Rest, DynamicEnc, Ext)]; +gen_enc_components_call1(_Gen, _TopType, [], _, _) -> []. +enc_absent(Gen, Var, Absent0, Imm) -> + Absent = translate_missing_value(Gen, Absent0), + asn1ct_imm:enc_absent(Var, Absent, Imm). + +translate_missing_value(#gen{pack=record}, Optionals) -> + Optionals; +translate_missing_value(#gen{pack=map}, Optionals) -> + case Optionals of + [asn1_NOVALUE|T] -> [?MISSING_IN_MAP|T]; + [asn1_DEFAULT|T] -> [?MISSING_IN_MAP|T]; + {call,_,_,_} -> Optionals + end. + +enc_fetch_field(#gen{pack=record}, Num, _Prop) -> + Val = make_var(val), + asn1ct_imm:enc_element(Num+1, Val); +enc_fetch_field(#gen{pack=map}, Num, _) -> + {[],{var,lists:concat(["Input@",Num])}}. + def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) -> #typedef{typespec=T} = asn1_db:dbget(Mod, Type), def_values(T, Def); @@ -1171,7 +1326,7 @@ gen_dec_comp_calls([C|Cs], Erule, TopType, OptTable, DecInfObj, gen_dec_comp_calls([], _, _, _, _, _, _, Tpos, Acc) -> {lists:append(lists:reverse(Acc)),Tpos}. -gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj, +gen_dec_comp_call(Comp, Gen, TopType, Tpos, OptTable, DecInfObj, Ext, NumberOfOptionals) -> #'ComponentType'{typespec=Type,prop=Prop,textual_order=TextPos} = Comp, Pos = case Ext of @@ -1212,15 +1367,9 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj, _ -> case Type of #type{def=#'SEQUENCE'{ - extaddgroup=Number1, - components=ExtGroupCompList1}} when is_integer(Number1)-> - fun(St) -> - emit(["{{_,"]), - emit_extaddgroupTerms(term,ExtGroupCompList1), - emit(["}"]), - emit([",",{next,bytes},"} = "]), - St - end; + extaddgroup=GroupNum, + components=CompList}} when is_integer(GroupNum)-> + dec_match_extadd_fun(Gen, CompList); _ -> fun(St) -> asn1ct_name:new(term), @@ -1230,9 +1379,9 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj, end end end, - {Pre,Post} = comp_call_pre_post(Ext, Prop, Pos, Type, TextPos, + {Pre,Post} = comp_call_pre_post(Gen, Ext, Prop, Pos, Type, TextPos, OptTable, NumberOfOptionals, Ext), - Lines = gen_dec_seq_line_imm(Erule, TopType, Comp, Tpos, DecInfObj, Ext), + Lines = gen_dec_seq_line_imm(Gen, TopType, Comp, Tpos, DecInfObj, Ext), AdvBuffer = {ignore,fun(St) -> asn1ct_name:new(bytes), St @@ -1240,9 +1389,24 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj, [{group,[{safe,Comment},{safe,Preamble}] ++ Pre ++ Lines ++ Post ++ [{safe,AdvBuffer}]}]. -comp_call_pre_post(noext, mandatory, _, _, _, _, _, _) -> +dec_match_extadd_fun(#gen{pack=record}, CompList) -> + fun(St) -> + emit(["{{_,"]), + emit_extaddgroupTerms(term, CompList), + emit(["}"]), + emit([",",{next,bytes},"} = "]), + St + end; +dec_match_extadd_fun(#gen{pack=map}, _CompList) -> + fun(St) -> + asn1ct_name:new(map), + emit(["{",{curr,map},",",{next,bytes},"} = "]), + St + end. + +comp_call_pre_post(_Gen, noext, mandatory, _, _, _, _, _, _) -> {[],[]}; -comp_call_pre_post(noext, Prop, _, Type, TextPos, +comp_call_pre_post(_Gen, noext, Prop, _, Type, TextPos, OptTable, NumOptionals, Ext) -> %% OPTIONAL or DEFAULT OptPos = get_optionality_pos(TextPos, OptTable), @@ -1266,32 +1430,53 @@ comp_call_pre_post(noext, Prop, _, Type, TextPos, "end"]), St end]}; -comp_call_pre_post({ext,_,_}, Prop, Pos, Type, _, _, _, Ext) -> +comp_call_pre_post(Gen, {ext,_,_}, Prop, Pos, Type, _, _, _, Ext) -> %% Extension {[fun(St) -> emit(["case Extensions of",nl, " <<_:",Pos-1,",1:1,_/bitstring>> ->",nl]), St end], - [fun(St) -> - emit([";",nl, - "_ ->",nl, - "{"]), - case Type of - #type{def=#'SEQUENCE'{ - extaddgroup=Number2, - components=ExtGroupCompList2}} - when is_integer(Number2)-> - emit("{extAddGroup,"), - gen_dec_extaddGroup_no_val(Ext, Type, ExtGroupCompList2), - emit("}"); - _ -> - gen_dec_component_no_val(Ext, Type, Prop) - end, - emit([",",{curr,bytes},"}",nl, - "end"]), - St - end]}. + [extadd_group_fun(Gen, Prop, Type, Ext)]}. + +extadd_group_fun(#gen{pack=record}, Prop, Type, Ext) -> + fun(St) -> + emit([";",nl, + "_ ->",nl, + "{"]), + case Type of + #type{def=#'SEQUENCE'{ + extaddgroup=Number2, + components=ExtGroupCompList2}} + when is_integer(Number2)-> + emit("{extAddGroup,"), + gen_dec_extaddGroup_no_val(Ext, Type, ExtGroupCompList2), + emit("}"); + _ -> + gen_dec_component_no_val(Ext, Type, Prop) + end, + emit([",",{curr,bytes},"}",nl, + "end"]), + St + end; +extadd_group_fun(#gen{pack=map}, Prop, Type, Ext) -> + fun(St) -> + emit([";",nl, + "_ ->",nl, + "{"]), + case Type of + #type{def=#'SEQUENCE'{ + extaddgroup=Number2, + components=Comp}} + when is_integer(Number2)-> + dec_map_extaddgroup_no_val(Ext, Type, Comp); + _ -> + gen_dec_component_no_val(Ext, Type, Prop) + end, + emit([",",{curr,bytes},"}",nl, + "end"]), + St + end. is_mandatory_predef_tab_c(noext, mandatory, {"got objfun through args","ObjFun"}) -> @@ -1318,7 +1503,20 @@ gen_dec_component_no_val(_, _, 'OPTIONAL') -> emit({"asn1_NOVALUE"}); gen_dec_component_no_val({ext,_,_}, _, mandatory) -> emit({"asn1_NOVALUE"}). - + +dec_map_extaddgroup_no_val(Ext, Type, Comp) -> + L0 = [dec_map_extaddgroup_no_val_1(N, P, Ext, Type) || + #'ComponentType'{name=N,prop=P} <- Comp], + L = [E || E <- L0, E =/= []], + emit(["#{",lists:join(",", L),"}"]). + +dec_map_extaddgroup_no_val_1(Name, {'DEFAULT',DefVal0}, _Ext, Type) -> + DefVal = asn1ct_gen:conform_value(Type, DefVal0), + [Name,"=>",{asis,DefVal}]; +dec_map_extaddgroup_no_val_1(_Name, 'OPTIONAL', _, _) -> + []; +dec_map_extaddgroup_no_val_1(_Name, mandatory, {ext,_,_}, _) -> + []. gen_dec_choice_line(Erule, TopType, Comp, Pre) -> Imm0 = gen_dec_line_imm(Erule, TopType, Comp, false, Pre), @@ -1698,20 +1896,17 @@ gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) -> gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre); gen_dec_choice2(_, _, [], _, _, _) -> ok. -make_elements(I,Val,ExtCnames) -> - make_elements(I,Val,ExtCnames,[]). +get_input_vars(Val, I, N) -> + L = get_input_vars_1(Val, I, N), + lists:join(",", L). -make_elements(I,Val,[_ExtCname],Acc)-> % the last one, no comma needed - Element = make_element(I, Val), - make_elements(I+1,Val,[],[Element|Acc]); -make_elements(I,Val,[_ExtCname|Rest],Acc)-> - Element = make_element(I, Val), - make_elements(I+1,Val,Rest,[", ",Element|Acc]); -make_elements(_I,_,[],Acc) -> - lists:reverse(Acc). +get_input_vars_1(_Val, _I, 0) -> + []; +get_input_vars_1(Val, I, N) -> + [get_input_var(Val, I)|get_input_vars_1(Val, I+1, N-1)]. -make_element(I, Val) -> - lists:flatten(io_lib:format("element(~w, ~s)", [I,Val])). +get_input_var(Val, I) -> + lists:flatten(io_lib:format("element(~w, ~s)", [I+1,Val])). emit_extaddgroupTerms(VarSeries,[_]) -> asn1ct_name:new(VarSeries), @@ -1728,57 +1923,66 @@ flat_complist({Rl1,El,Rl2}) -> Rl1 ++ El ++ Rl2; flat_complist({Rl,El}) -> Rl ++ El; flat_complist(CompList) -> CompList. -%%wrap_compList({Root1,Ext,Root2}) -> -%% {Root1,wrap_extensionAdditionGroups(Ext),Root2}; -%%wrap_compList({Root1,Ext}) -> -%% {Root1,wrap_extensionAdditionGroups(Ext)}; -%%wrap_compList(CompList) -> -%% CompList. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Will convert all componentTypes following 'ExtensionAdditionGroup' +%% Convert all componentTypes following 'ExtensionAdditionGroup' %% up to the matching 'ExtensionAdditionGroupEnd' into one componentType -%% of type SEQUENCE with the componentTypes as components +%% of type SEQUENCE with the componentTypes as components. %% -wrap_extensionAdditionGroups(ExtCompList,ExtGroupPosLen) -> - wrap_extensionAdditionGroups(ExtCompList,ExtGroupPosLen,[],0,0). +wrap_extensionAdditionGroups(ExtCompList, ExtGroupPosLen) -> + wrap_eags(ExtCompList, ExtGroupPosLen, 0, 0). -wrap_extensionAdditionGroups([{'ExtensionAdditionGroup',_Number}|Rest], - [{ActualPos,_,_}|ExtGroupPosLenRest],Acc,_ExtAddGroupDiff,ExtGroupNum) -> - {ExtGroupCompList,['ExtensionAdditionGroupEnd'|Rest2]} = +wrap_eags([{'ExtensionAdditionGroup',_Number}|T0], + [{ActualPos,_,_}|Gs], _ExtAddGroupDiff, ExtGroupNum) -> + {ExtGroupCompList,['ExtensionAdditionGroupEnd'|T]} = lists:splitwith(fun(#'ComponentType'{}) -> true; (_) -> false - end, - Rest), - wrap_extensionAdditionGroups(Rest2,ExtGroupPosLenRest, - [#'ComponentType'{ - name=list_to_atom("ExtAddGroup"++ - integer_to_list(ExtGroupNum+1)), - typespec=#type{def=#'SEQUENCE'{ - extaddgroup=ExtGroupNum+1, - components=ExtGroupCompList}}, - textual_order = ActualPos, - prop='OPTIONAL'}|Acc],length(ExtGroupCompList)-1, - ExtGroupNum+1); -wrap_extensionAdditionGroups([H=#'ComponentType'{textual_order=Tord}|T], - ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupNum) when is_integer(Tord) -> - wrap_extensionAdditionGroups(T,ExtAddGrpLenPos,[H#'ComponentType'{ - textual_order=Tord - ExtAddGroupDiff}|Acc],ExtAddGroupDiff,ExtGroupNum); -wrap_extensionAdditionGroups([H|T],ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupNum) -> - wrap_extensionAdditionGroups(T,ExtAddGrpLenPos,[H|Acc],ExtAddGroupDiff,ExtGroupNum); -wrap_extensionAdditionGroups([],_,Acc,_,_) -> - lists:reverse(Acc). - -value_match(_Gen, [], Value) -> + end, T0), + Name = list_to_atom(lists:concat(["ExtAddGroup",ExtGroupNum+1])), + Seq = #type{def=#'SEQUENCE'{extaddgroup=ExtGroupNum+1, + components=ExtGroupCompList}}, + Comp = #'ComponentType'{name=Name, + typespec=Seq, + textual_order=ActualPos, + prop='OPTIONAL'}, + [Comp|wrap_eags(T, Gs, length(ExtGroupCompList)-1, ExtGroupNum+1)]; +wrap_eags([#'ComponentType'{textual_order=Tord}=H|T], + ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum) + when is_integer(Tord) -> + Comp = H#'ComponentType'{textual_order=Tord - ExtAddGroupDiff}, + [Comp|wrap_eags(T, ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum)]; +wrap_eags([H|T], ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum) -> + [H|wrap_eags(T, ExtAddGrpLenPos, ExtAddGroupDiff, ExtGroupNum)]; +wrap_eags([], _, _, _) -> + []. + +value_match(#gen{pack=record}, VIs, Value) -> + value_match_rec(VIs, Value); +value_match(#gen{pack=map}, VIs, Value) -> + value_match_map(VIs, Value). + +value_match_rec([], Value) -> Value; -value_match(Gen, [{VI,_}|VIs], Value0) -> - Value = value_match(Gen, VIs, Value0), +value_match_rec([{VI,_}|VIs], Value0) -> + Value = value_match_rec(VIs, Value0), lists:concat(["element(",VI,", ",Value,")"]). +value_match_map([], Value) -> + Value; +value_match_map([{_,Name}|VIs], Value0) -> + Value = value_match_map(VIs, Value0), + lists:concat(["maps:get(",Name,", ",Value,")"]). + enc_dig_out_value(_Gen, [], Value) -> {[],Value}; -enc_dig_out_value(Gen, [{N,_}|T], Value) -> +enc_dig_out_value(#gen{pack=record}=Gen, [{N,_}|T], Value) -> {Imm0,Dst0} = enc_dig_out_value(Gen, T, Value), {Imm,Dst} = asn1ct_imm:enc_element(N, Dst0), + {Imm0++Imm,Dst}; +enc_dig_out_value(#gen{pack=map}, [{N,'ASN1_top'}], _Value) -> + {[],{var,lists:concat(["Input@",N-1])}}; +enc_dig_out_value(#gen{pack=map}=Gen, [{_,Name}|T], Value) -> + {Imm0,Dst0} = enc_dig_out_value(Gen, T, Value), + {Imm,Dst} = asn1ct_imm:enc_maps_get(Name, Dst0), {Imm0++Imm,Dst}. make_var(Base) -> diff --git a/lib/asn1/src/asn1ct_eval_ext.funcs b/lib/asn1/src/asn1ct_eval_ext.funcs index 5761901f89..01c67e7b5a 100644 --- a/lib/asn1/src/asn1ct_eval_ext.funcs +++ b/lib/asn1/src/asn1ct_eval_ext.funcs @@ -1 +1,2 @@ {ext,transform_to_EXTERNAL1994,1}. +{ext,transform_to_EXTERNAL1994_maps,1}. diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index a54cb0765e..4fa830d7d9 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -67,6 +67,7 @@ pgen(OutFile, #gen{options=Options}=Gen, Module, Contents) -> UnmatchedTypes}) end, put(outfile,OutFile), + put(currmod, Module), HrlGenerated = pgen_hrl(Gen, Module, Contents), asn1ct_name:start(), ErlFile = lists:concat([OutFile,".erl"]), @@ -650,7 +651,7 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) -> pgen_exports(#gen{options=Options}=Gen, _Module, Contents) -> {Types,Values,_,_,Objects,ObjectSets} = Contents, - emit(["-export([encoding_rule/0,bit_string_format/0,",nl, + emit(["-export([encoding_rule/0,maps/0,bit_string_format/0,",nl, " legacy_erlang_types/0]).",nl]), emit(["-export([",{asis,?SUPPRESSION_FUNC},"/1]).",nl]), case Types of @@ -887,8 +888,14 @@ gen_info_functions(Gen) -> #gen{erule=per,aligned=false} -> uper; #gen{erule=per,aligned=true} -> per end, + Maps = case Gen of + #gen{pack=record} -> false; + #gen{pack=map} -> true + end, emit(["encoding_rule() -> ", {asis,Erule},".",nl,nl, + "maps() -> ", + {asis,Maps},".",nl,nl, "bit_string_format() -> ", {asis,asn1ct:get_bit_string_format()},".",nl,nl, "legacy_erlang_types() -> ", @@ -1093,8 +1100,7 @@ open_output_file(F) -> close_output_file() -> ok = file:close(erase(gen_file_out)). -pgen_hrl(Gen, Module, Contents) -> - put(currmod, Module), +pgen_hrl(#gen{pack=record}=Gen, Module, Contents) -> {Types,Values,Ptypes,_,_,_} = Contents, Ret = case pgen_hrltypes(Gen, Module, Ptypes++Types, 0) of @@ -1103,7 +1109,7 @@ pgen_hrl(Gen, Module, Contents) -> [] -> 0; _ -> - open_hrl(get(outfile),get(currmod)), + open_hrl(get(outfile), Module), pgen_macros(Gen, Module, Values), 1 end; @@ -1122,7 +1128,9 @@ pgen_hrl(Gen, Module, Contents) -> [{generated,lists:concat([get(outfile),".hrl"])}], Gen), Y - end. + end; +pgen_hrl(#gen{pack=map}, _, _) -> + 0. pgen_macros(_,_,[]) -> true; diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index b884d14b0d..6c6d4193f3 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -1200,11 +1200,13 @@ gen_objset_enc(Erules, ObjSetName, UniqueName, {no_mod,no_name} -> gen_inlined_enc_funs(Fields, ClFields, ObjSetName, Val, NthObj); {CurrMod,Name} -> - emit(["'getenc_",ObjSetName,"'(",{asis,Val},") ->",nl, + emit(["'getenc_",ObjSetName,"'(Id) when Id =:= ", + {asis,Val}," ->",nl, " fun 'enc_",Name,"'/3;",nl]), {[],NthObj}; {ModuleName,Name} -> - emit(["'getenc_",ObjSetName,"'(",{asis,Val},") ->",nl]), + emit(["'getenc_",ObjSetName,"'(Id) when Id =:= ", + {asis,Val}," ->",nl]), emit_ext_fun(enc,ModuleName,Name), emit([";",nl]), {[],NthObj}; @@ -1382,11 +1384,13 @@ gen_objset_dec(Erules, ObjSName, UniqueName, [{ObjName,Val,Fields}|T], {no_mod,no_name} -> gen_inlined_dec_funs(Fields,ClFields,ObjSName,Val,NthObj); {CurrMod,Name} -> - emit(["'getdec_",ObjSName,"'(",{asis,Val},") ->",nl, + emit(["'getdec_",ObjSName,"'(Id) when Id =:= ", + {asis,Val}," ->",nl, " fun 'dec_",Name,"'/3;", nl]), NthObj; {ModuleName,Name} -> - emit(["'getdec_",ObjSName,"'(",{asis,Val},") ->",nl]), + emit(["'getdec_",ObjSName,"'(Id) when Id =:= ", + {asis,Val}," ->",nl]), emit_ext_fun(dec,ModuleName,Name), emit([";",nl]), NthObj; diff --git a/lib/asn1/src/asn1ct_gen_check.erl b/lib/asn1/src/asn1ct_gen_check.erl index abe77dd0cb..ccc62a3ce3 100644 --- a/lib/asn1/src/asn1ct_gen_check.erl +++ b/lib/asn1/src/asn1ct_gen_check.erl @@ -21,45 +21,51 @@ %% -module(asn1ct_gen_check). --export([emit/3]). +-export([emit/4]). -import(asn1ct_gen, [emit/1]). -include("asn1_records.hrl"). -emit(Type, Default, Value) -> +emit(Gen, Type, Default, Value) -> Key = {Type,Default}, - Gen = fun(Fd, Name) -> - file:write(Fd, gen(Name, Type, Default)) - end, + DoGen = fun(Fd, Name) -> + file:write(Fd, gen(Gen, Name, Type, Default)) + end, emit(" case "), - asn1ct_func:call_gen("is_default_", Key, Gen, [Value]), + asn1ct_func:call_gen("is_default_", Key, DoGen, [Value]), emit([" of",nl, "true -> {[],0};",nl, "false ->",nl]). -gen(Name, #type{def=T}, Default) -> +gen(#gen{pack=Pack}=Gen, Name, #type{def=T}, Default) -> + DefMarker = case Pack of + record -> "asn1_DEFAULT"; + map -> atom_to_list(?MISSING_IN_MAP) + end, NameStr = atom_to_list(Name), - [NameStr,"(asn1_DEFAULT) ->\n", - "true;\n"|case do_gen(T, Default) of - {literal,Literal} -> - [NameStr,"(",term2str(Literal),") ->\n","true;\n", - NameStr,"(_) ->\n","false.\n\n"]; - {exception,Func,Args} -> - [NameStr,"(Value) ->\n", - "try ",Func,"(Value",arg2str(Args),") of\n", - "_ -> true\n" - "catch throw:false -> false\n" - "end.\n\n"] - end]. + [NameStr,"(",DefMarker,") ->\n", + "true;\n"| + case do_gen(Gen, T, Default) of + {literal,Literal} -> + [NameStr,"(Def) when Def =:= ",term2str(Literal)," ->\n", + "true;\n", + NameStr,"(_) ->\n","false.\n\n"]; + {exception,Func,Args} -> + [NameStr,"(Value) ->\n", + "try ",Func,"(Value",arg2str(Args),") of\n", + "_ -> true\n" + "catch throw:false -> false\n" + "end.\n\n"] + end]. -do_gen(_, asn1_NOVALUE) -> +do_gen(_Gen, _, asn1_NOVALUE) -> {literal,asn1_NOVALUE}; -do_gen(#'Externaltypereference'{module=M,type=T}, Default) -> +do_gen(Gen, #'Externaltypereference'{module=M,type=T}, Default) -> #typedef{typespec=#type{def=Td}} = asn1_db:dbget(M, T), - do_gen(Td, Default); -do_gen('BOOLEAN', Default) -> + do_gen(Gen, Td, Default); +do_gen(_Gen, 'BOOLEAN', Default) -> {literal,Default}; -do_gen({'BIT STRING',[]}, Default) -> +do_gen(_Gen, {'BIT STRING',[]}, Default) -> true = is_bitstring(Default), %Assertion. case asn1ct:use_legacy_types() of false -> @@ -67,17 +73,17 @@ do_gen({'BIT STRING',[]}, Default) -> true -> {exception,need(check_legacy_bitstring, 2),[Default]} end; -do_gen({'BIT STRING',[_|_]=NBL}, Default) -> +do_gen(_Gen, {'BIT STRING',[_|_]=NBL}, Default) -> do_named_bitstring(NBL, Default); -do_gen({'ENUMERATED',_}, Default) -> +do_gen(_Gen, {'ENUMERATED',_}, Default) -> {literal,Default}; -do_gen('INTEGER', Default) -> +do_gen(_Gen, 'INTEGER', Default) -> {literal,Default}; -do_gen({'INTEGER',NNL}, Default) -> +do_gen(_Gen, {'INTEGER',NNL}, Default) -> {exception,need(check_int, 3),[Default,NNL]}; -do_gen('NULL', Default) -> +do_gen(_Gen, 'NULL', Default) -> {literal,Default}; -do_gen('OCTET STRING', Default) -> +do_gen(_Gen, 'OCTET STRING', Default) -> true = is_binary(Default), %Assertion. case asn1ct:use_legacy_types() of false -> @@ -85,34 +91,34 @@ do_gen('OCTET STRING', Default) -> true -> {exception,need(check_octetstring, 2),[Default]} end; -do_gen('OBJECT IDENTIFIER', Default0) -> +do_gen(_Gen, 'OBJECT IDENTIFIER', Default0) -> Default = pre_process_oid(Default0), {exception,need(check_objectidentifier, 2),[Default]}; -do_gen({'CHOICE',Cs}, Default) -> +do_gen(Gen, {'CHOICE',Cs}, Default) -> {Tag,Value} = Default, [Type] = [Type || #'ComponentType'{name=T,typespec=Type} <- Cs, T =:= Tag], - case do_gen(Type#type.def, Value) of + case do_gen(Gen, Type#type.def, Value) of {literal,Lit} -> {literal,{Tag,Lit}}; {exception,Func0,Args} -> Key = {Tag,Func0,Args}, - Gen = fun(Fd, Name) -> - S = gen_choice(Name, Tag, Func0, Args), - ok = file:write(Fd, S) + DoGen = fun(Fd, Name) -> + S = gen_choice(Name, Tag, Func0, Args), + ok = file:write(Fd, S) end, - Func = asn1ct_func:call_gen("is_default_choice", Key, Gen), + Func = asn1ct_func:call_gen("is_default_choice", Key, DoGen), {exception,atom_to_list(Func),[]} end; -do_gen(#'SEQUENCE'{components=Cs}, Default) -> - do_seq_set(Cs, Default); -do_gen({'SEQUENCE OF',Type}, Default) -> - do_sof(Type, Default); -do_gen(#'SET'{components=Cs}, Default) -> - do_seq_set(Cs, Default); -do_gen({'SET OF',Type}, Default) -> - do_sof(Type, Default); -do_gen(Type, Default) -> +do_gen(Gen, #'SEQUENCE'{components=Cs}, Default) -> + do_seq_set(Gen, Cs, Default); +do_gen(Gen, {'SEQUENCE OF',Type}, Default) -> + do_sof(Gen, Type, Default); +do_gen(Gen, #'SET'{components=Cs}, Default) -> + do_seq_set(Gen, Cs, Default); +do_gen(Gen, {'SET OF',Type}, Default) -> + do_sof(Gen, Type, Default); +do_gen(_Gen, Type, Default) -> case asn1ct_gen:unify_if_string(Type) of restrictedstring -> {exception,need(check_restrictedstring, 2),[Default]}; @@ -136,39 +142,58 @@ do_named_bitstring(_, Default) when is_bitstring(Default) -> end, {exception,need(Func, 3),[Default,bit_size(Default)]}. -do_seq_set(Cs0, Default) -> +do_seq_set(#gen{pack=record}=Gen, Cs0, Default) -> Tag = element(1, Default), Cs1 = [T || #'ComponentType'{typespec=T} <- Cs0], - Cs = components(Cs1, tl(tuple_to_list(Default))), + Cs = components(Gen, Cs1, tl(tuple_to_list(Default))), case are_all_literals(Cs) of true -> Literal = list_to_tuple([Tag|[L || {literal,L} <- Cs]]), {literal,Literal}; false -> Key = {Cs,Default}, - Gen = fun(Fd, Name) -> - S = gen_components(Name, Tag, Cs), - ok = file:write(Fd, S) - end, - Func = asn1ct_func:call_gen("is_default_cs_", Key, Gen), + DoGen = fun(Fd, Name) -> + S = gen_components(Name, Tag, Cs), + ok = file:write(Fd, S) + end, + Func = asn1ct_func:call_gen("is_default_cs_", Key, DoGen), + {exception,atom_to_list(Func),[]} + end; +do_seq_set(#gen{pack=map}=Gen, Cs0, Default) -> + Cs1 = [{N,T} || #'ComponentType'{name=N,typespec=T} <- Cs0], + Cs = map_components(Gen, Cs1, Default), + AllLiterals = lists:all(fun({_,{literal,_}}) -> true; + ({_,_}) -> false + end, Cs), + case AllLiterals of + true -> + L = [{Name,Lit} || {Name,{literal,Lit}} <- Cs], + {literal,maps:from_list(L)}; + false -> + Key = {Cs,Default}, + DoGen = fun(Fd, Name) -> + S = gen_map_components(Name, Cs), + ok = file:write(Fd, S) + end, + Func = asn1ct_func:call_gen("is_default_cs_", Key, DoGen), {exception,atom_to_list(Func),[]} end. -do_sof(Type, Default0) -> +do_sof(Gen, Type, Default0) -> Default = lists:sort(Default0), Cs0 = lists:duplicate(length(Default), Type), - Cs = components(Cs0, Default), + Cs = components(Gen, Cs0, Default), case are_all_literals(Cs) of true -> Literal = [Lit || {literal,Lit} <- Cs], {exception,need(check_literal_sof, 2),[Literal]}; false -> Key = Cs, - Gen = fun(Fd, Name) -> - S = gen_sof(Name, Cs), - ok = file:write(Fd, S) + DoGen = fun(Fd, Name) -> + S = gen_sof(Name, Cs), + ok = file:write(Fd, S) end, - Func = asn1ct_func:call_gen("is_default_sof", Key, Gen), + Func = asn1ct_func:call_gen("is_default_sof", Key, DoGen), {exception,atom_to_list(Func),[]} end. @@ -199,6 +224,39 @@ gen_cs_2([], _) -> "throw(false)\n" "end.\n"]. +gen_map_components(Name, Cs) -> + [atom_to_list(Name),"(Value) ->\n", + "case Value of\n", + "#{"|gen_map_cs_1(Cs, 1, "", [])]. + +gen_map_cs_1([{Name,{literal,Lit}}|T], I, Sep, Acc) -> + Var = "E"++integer_to_list(I), + G = Var ++ " =:= " ++ term2str(Lit), + [Sep,term2str(Name),":=",Var| + gen_map_cs_1(T, I+1, ",\n", [{guard,G}|Acc])]; +gen_map_cs_1([{Name,Exc}|T], I, Sep, Acc) -> + Var = "E"++integer_to_list(I), + [Sep,term2str(Name),":=",Var| + gen_map_cs_1(T, I+1, ",\n", [{exc,{Var,Exc}}|Acc])]; +gen_map_cs_1([], _, _, Acc) -> + G = lists:join(", ", [S || {guard,S} <- Acc]), + Exc = [E || {exc,E} <- Acc], + Body = gen_map_cs_2(Exc, ""), + case G of + [] -> + ["} ->\n"|Body]; + [_|_] -> + ["} when ",G," ->\n"|Body] + end. + +gen_map_cs_2([{Var,{exception,Func,Args}}|T], Sep) -> + [Sep,Func,"(",Var,arg2str(Args),")"|gen_map_cs_2(T, ",\n")]; +gen_map_cs_2([], _) -> + [";\n", + "_ ->\n" + "throw(false)\n" + "end.\n"]. + gen_sof(Name, Cs) -> [atom_to_list(Name),"(Value) ->\n", "case length(Value) of\n", @@ -221,9 +279,18 @@ gen_sof_1([{exception,Func,Args}|Cs], I) -> gen_sof_1([], _) -> ".\n". -components([#type{def=Def}|Ts], [V|Vs]) -> - [do_gen(Def, V)|components(Ts, Vs)]; -components([], []) -> []. +components(Gen, [#type{def=Def}|Ts], [V|Vs]) -> + [do_gen(Gen, Def, V)|components(Gen, Ts, Vs)]; +components(_Gen, [], []) -> []. + +map_components(Gen, [{Name,#type{def=Def}}|Ts], Value) -> + case maps:find(Name, Value) of + {ok,V} -> + [{Name,do_gen(Gen, Def, V)}|map_components(Gen, Ts, Value)]; + error -> + map_components(Gen, Ts, Value) + end; +map_components(_Gen, [], _Value) -> []. gen_choice(Name, Tag, Func, Args) -> NameStr = atom_to_list(Name), diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index 741d54c321..2ab848652e 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -37,9 +37,11 @@ per_enc_open_type/2, per_enc_restricted_string/3, per_enc_small_number/2]). --export([per_enc_extension_bit/2,per_enc_extensions/4,per_enc_optional/2]). +-export([per_enc_extension_bit/2,per_enc_extensions/4, + per_enc_extensions_map/4, + per_enc_optional/2]). -export([per_enc_sof/5]). --export([enc_absent/3,enc_append/1,enc_element/2]). +-export([enc_absent/3,enc_append/1,enc_element/2,enc_maps_get/2]). -export([enc_cg/2]). -export([optimize_alignment/1,optimize_alignment/2, dec_slim_cg/2,dec_code_gen/2]). @@ -349,6 +351,20 @@ per_enc_extensions(Val0, Pos0, NumBits, Aligned) when NumBits > 0 -> ['_'|Length ++ PutBits]]}], {var,"Extensions"}}]. +per_enc_extensions_map(Val0, Vars, Undefined, Aligned) -> + NumBits = length(Vars), + {B,[_Val,Bitmap]} = mk_vars(Val0, [bitmap]), + Length = per_enc_small_length(NumBits, Aligned), + PutBits = case NumBits of + 1 -> [{put_bits,1,1,[1]}]; + _ -> [{put_bits,Bitmap,NumBits,[1]}] + end, + BitmapExpr = extensions_bitmap(Vars, Undefined), + B++[{assign,Bitmap,BitmapExpr}, + {list,[{'cond',[[{eq,Bitmap,0}], + ['_'|Length ++ PutBits]]}], + {var,"Extensions"}}]. + per_enc_optional(Val, DefVals) when is_list(DefVals) -> Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, @@ -414,6 +430,13 @@ enc_element(N, Val0) -> {[],[Val,Dst]} = mk_vars(Val0, [element]), {[{call,erlang,element,[N,Val],Dst}],Dst}. +enc_maps_get(N, Val0) -> + {[],[Val,Dst0]} = mk_vars(Val0, [element]), + {var,Dst} = Dst0, + DstExpr = {expr,lists:concat(["#{",N,":=",Dst,"}"])}, + {var,SrcVar} = Val, + {[{assign,DstExpr,SrcVar}],Dst0}. + enc_cg(Imm0, false) -> Imm1 = enc_cse(Imm0), Imm2 = enc_pre_cg(Imm1), @@ -1231,6 +1254,20 @@ enc_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) -> enc_length(Len, Sv, _Aligned) when is_integer(Sv) -> [{'cond',[[{eq,Len,Sv}]]}]. +extensions_bitmap(Vs, Undefined) -> + Highest = 1 bsl (length(Vs)-1), + Cs = extensions_bitmap_1(Vs, Undefined, Highest), + lists:flatten(lists:join(" bor ", Cs)). + +extensions_bitmap_1([{var,V}|Vs], Undefined, Power) -> + S = ["case ",V," of\n", + " ",Undefined," -> 0;\n" + " _ -> ",integer_to_list(Power),"\n" + "end"], + [S|extensions_bitmap_1(Vs, Undefined, Power bsr 1)]; +extensions_bitmap_1([], _, _) -> + []. + put_bits_binary(Bin, _Unit, Aligned) when is_binary(Bin) -> Sz = byte_size(Bin), <> = Bin, diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index b3d41dd9f3..8bd99d995b 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -64,7 +64,11 @@ from_type(M,Typename,Type) when is_record(Type,type) -> end; {constructed,bif} when Typename == ['EXTERNAL'] -> Val=from_type_constructed(M,Typename,InnerType,Type), - asn1ct_eval_ext:transform_to_EXTERNAL1994(Val); + T = case M:maps() of + false -> transform_to_EXTERNAL1994; + true -> transform_to_EXTERNAL1994_maps + end, + asn1ct_eval_ext:T(Val); {constructed,bif} -> from_type_constructed(M,Typename,InnerType,Type) end; @@ -118,11 +122,13 @@ get_sequence(M,Typename,Type) -> #'SEQUENCE'{components=Cl} -> {'SEQUENCE',Cl}; #'SET'{components=Cl} -> {'SET',to_textual_order(Cl)} end, - case get_components(M,Typename,CompList) of - [] -> - {list_to_atom(asn1ct_gen:list2rname(Typename))}; - C -> - list_to_tuple([list_to_atom(asn1ct_gen:list2rname(Typename))|C]) + Cs = get_components(M, Typename, CompList), + case M:maps() of + false -> + RecordTag = list_to_atom(asn1ct_gen:list2rname(Typename)), + list_to_tuple([RecordTag|[Val || {_,Val} <- Cs]]); + true -> + maps:from_list(Cs) end. get_components(M,Typename,{Root,Ext}) -> @@ -130,9 +136,9 @@ get_components(M,Typename,{Root,Ext}) -> %% Should enhance this *** HERE *** with proper handling of extensions -get_components(M,Typename,[H|T]) -> - [from_type(M,Typename,H)| - get_components(M,Typename,T)]; +get_components(M, Typename, [H|T]) -> + #'ComponentType'{name=Name} = H, + [{Name,from_type(M, Typename, H)}|get_components(M, Typename, T)]; get_components(_,_,[]) -> []. diff --git a/lib/asn1/src/asn1rtt_ext.erl b/lib/asn1/src/asn1rtt_ext.erl index 3bf01823db..161b2db691 100644 --- a/lib/asn1/src/asn1rtt_ext.erl +++ b/lib/asn1/src/asn1rtt_ext.erl @@ -19,7 +19,8 @@ %% -module(asn1rtt_ext). --export([transform_to_EXTERNAL1990/1,transform_to_EXTERNAL1994/1]). +-export([transform_to_EXTERNAL1990/1,transform_to_EXTERNAL1990_maps/1, + transform_to_EXTERNAL1994/1,transform_to_EXTERNAL1994_maps/1]). transform_to_EXTERNAL1990({_,_,_,_}=Val) -> transform_to_EXTERNAL1990(tuple_to_list(Val), []); @@ -51,6 +52,30 @@ transform_to_EXTERNAL1990([Data_value], Acc) list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])). +transform_to_EXTERNAL1990_maps(#{identification:=Id,'data-value':=Value}=V) -> + M0 = case Id of + {syntax,DRef} -> + #{'direct-reference'=>DRef}; + {'presentation-context-id',IndRef} -> + #{'indirect-reference'=>IndRef}; + {'context-negotiation', + #{'presentation-context-id':=IndRef, + 'transfer-syntax':=DRef}} -> + #{'direct-reference'=>DRef, + 'indirect-reference'=>IndRef} + end, + M = case V of + #{'data-value-descriptor':=Dvd} -> + M0#{'data-value-descriptor'=>Dvd}; + #{} -> + M0 + end, + M#{encoding=>{'octet-aligned',Value}}; +transform_to_EXTERNAL1990_maps(#{encoding:=_}=V) -> + %% Already in the EXTERNAL 1990 format. + V. + + transform_to_EXTERNAL1994({'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}=V) -> Identification = case {DRef,IndRef} of @@ -71,3 +96,38 @@ transform_to_EXTERNAL1994({'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}=V) -> %% information. V end. + +transform_to_EXTERNAL1994_maps(V0) -> + Identification = + case V0 of + #{'direct-reference':=DRef, + 'indirect-reference':=asn1_NOVALUE} -> + {syntax,DRef}; + #{'direct-reference':=asn1_NOVALUE, + 'indirect-reference':=IndRef} -> + {'presentation-context-id',IndRef}; + #{'direct-reference':=DRef, + 'indirect-reference':=IndRef} -> + {'context-negotiation', + #{'transfer-syntax'=>DRef, + 'presentation-context-id'=>IndRef}} + end, + case V0 of + #{encoding:={'octet-aligned',Val}} + when is_list(Val); is_binary(Val) -> + %% Transform to the EXTERNAL 1994 definition. + V = #{identification=>Identification, + 'data-value'=>Val}, + case V0 of + #{'data-value-descriptor':=asn1_NOVALUE} -> + V; + #{'data-value-descriptor':=Dvd} -> + V#{'data-value-descriptor'=>Dvd} + end; + _ -> + %% Keep the EXTERNAL 1990 definition to avoid losing + %% information. + V = [{K,V} || {K,V} <- maps:to_list(V0), + V =/= asn1_NOVALUE], + maps:from_list(V) + end. diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile index 40575e8a2f..d346bb9e12 100644 --- a/lib/asn1/test/Makefile +++ b/lib/asn1/test/Makefile @@ -82,6 +82,7 @@ MODULES= \ testInfObjExtract \ testParameterizedInfObj \ testFragmented \ + testMaps \ testMergeCompile \ testMultipleLevels \ testDeepTConstr \ diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index b6430134ab..6769a38b12 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -21,6 +21,9 @@ -module(asn1_SUITE). +%% Suppress compilation of an addititional module compiled for maps. +-define(NO_MAPS_MODULE, asn1_test_lib_no_maps). + -define(only_ber(Func), if Rule =:= ber -> Func; true -> ok @@ -102,6 +105,7 @@ groups() -> testMultipleLevels, testOpt, testSeqDefault, + testMaps, % Uses 'External' {group, [], [testExternal, testSeqExtension]}, @@ -176,8 +180,11 @@ groups() -> {performance, [], [testTimer_ber, + testTimer_ber_maps, testTimer_per, - testTimer_uper]}]. + testTimer_per_maps, + testTimer_uper, + testTimer_uper_maps]}]. %%------------------------------------------------------------------------------ %% Init/end @@ -441,6 +448,16 @@ testDEFAULT(Config, Rule, Opts) -> testDef:main(Rule), testSeqSetDefaultVal:main(Rule, Opts). +testMaps(Config) -> + test(Config, fun testMaps/3, + [{ber,[maps,no_ok_wrapper]}, + {ber,[maps,der,no_ok_wrapper]}, + {per,[maps,no_ok_wrapper]}, + {uper,[maps,no_ok_wrapper]}]). +testMaps(Config, Rule, Opts) -> + asn1_test_lib:compile_all(['Maps'], Config, [Rule|Opts]), + testMaps:main(Rule). + testOpt(Config) -> test(Config, fun testOpt/3). testOpt(Config, Rule, Opts) -> asn1_test_lib:compile("Opt", Config, [Rule|Opts]), @@ -614,12 +631,12 @@ parse(Config) -> [asn1_test_lib:compile(M, Config, [abs]) || M <- test_modules()]. per(Config) -> - test(Config, fun per/3, [per,uper]). + test(Config, fun per/3, [per,uper,{per,[maps]},{uper,[maps]}]). per(Config, Rule, Opts) -> [module_test(M, Config, Rule, Opts) || M <- per_modules()]. ber_other(Config) -> - test(Config, fun ber_other/3, [ber]). + test(Config, fun ber_other/3, [ber,{ber,[maps]}]). ber_other(Config, Rule, Opts) -> [module_test(M, Config, Rule, Opts) || M <- ber_modules()]. @@ -628,7 +645,7 @@ der(Config) -> asn1_test_lib:compile_all(ber_modules(), Config, [der]). module_test(M0, Config, Rule, Opts) -> - asn1_test_lib:compile(M0, Config, [Rule|Opts]), + asn1_test_lib:compile(M0, Config, [Rule,?NO_MAPS_MODULE|Opts]), case list_to_atom(M0) of 'LDAP' -> %% Because of the recursive definition of 'Filter' in @@ -995,7 +1012,9 @@ testS1AP(Config, Rule, Opts) -> testRfcs() -> [{timetrap,{minutes,90}}]. -testRfcs(Config) -> test(Config, fun testRfcs/3, [{ber,[der]}]). +testRfcs(Config) -> test(Config, fun testRfcs/3, + [{ber,[der,?NO_MAPS_MODULE]}, + {ber,[der,maps]}]). testRfcs(Config, Rule, Opts) -> case erlang:system_info(system_architecture) of "sparc-sun-solaris2.10" -> @@ -1010,7 +1029,8 @@ test_compile_options(Config) -> ok = test_compile_options:path(Config), ok = test_compile_options:noobj(Config), ok = test_compile_options:record_name_prefix(Config), - ok = test_compile_options:verbose(Config). + ok = test_compile_options:verbose(Config), + ok = test_compile_options:maps(Config). testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3). testDoubleEllipses(Config, Rule, Opts) -> @@ -1069,7 +1089,7 @@ test_x691(Config, Rule, Opts) -> ok. ticket_6143(Config) -> - ok = test_compile_options:ticket_6143(Config). + asn1_test_lib:compile("AA1", Config, [?NO_MAPS_MODULE]). testExtensionAdditionGroup(Config) -> test(Config, fun testExtensionAdditionGroup/3). @@ -1157,20 +1177,33 @@ END ok = asn1ct:compile(File, [{outdir, PrivDir}]). -timer_compile(Config, Rule) -> - asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"], - Config, [no_ok_wrapper,Rule]). +timer_compile(Config, Opts0) -> + Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES"], + Opts = [no_ok_wrapper,?NO_MAPS_MODULE|Opts0], + asn1_test_lib:compile_all(Files, Config, Opts). testTimer_ber(Config) -> - timer_compile(Config, ber), + timer_compile(Config, [ber]), testTimer:go(). testTimer_per(Config) -> - timer_compile(Config, per), + timer_compile(Config, [per]), testTimer:go(). testTimer_uper(Config) -> - timer_compile(Config, uper), + timer_compile(Config, [uper]), + testTimer:go(). + +testTimer_ber_maps(Config) -> + timer_compile(Config, [ber,maps]), + testTimer:go(). + +testTimer_per_maps(Config) -> + timer_compile(Config, [per,maps]), + testTimer:go(). + +testTimer_uper_maps(Config) -> + timer_compile(Config, [uper,maps]), testTimer:go(). %% Test of multiple-line comment, OTP-8043 @@ -1179,9 +1212,11 @@ testComment(Config) -> asn1_test_lib:roundtrip('Comment', 'Seq', {'Seq',12,true}). testName2Number(Config) -> - N2NOptions = [{n2n,Type} || Type <- ['CauseMisc', 'CauseProtocol', - 'CauseRadioNetwork', - 'CauseTransport','CauseNas']], + N2NOptions0 = [{n2n,Type} || + Type <- ['CauseMisc', 'CauseProtocol', + 'CauseRadioNetwork', + 'CauseTransport','CauseNas']], + N2NOptions = [?NO_MAPS_MODULE|N2NOptions0], asn1_test_lib:compile("S1AP-IEs", Config, N2NOptions), 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'), @@ -1191,8 +1226,9 @@ testName2Number(Config) -> %% Test that n2n option generates name2num and num2name functions supporting %% values not within the extension root if the enumeration type has an %% extension marker. - N2NOptionsExt = [{n2n, 'NoExt'}, {n2n, 'Ext'}, {n2n, 'Ext2'}], + N2NOptionsExt = [?NO_MAPS_MODULE,{n2n,'NoExt'},{n2n,'Ext'},{n2n,'Ext2'}], asn1_test_lib:compile("EnumN2N", Config, N2NOptionsExt), + %% Previously, name2num and num2name was not generated if the type didn't %% have an extension marker: 0 = 'EnumN2N':name2num_NoExt('blue'), @@ -1210,9 +1246,11 @@ testName2Number(Config) -> ok. ticket_7407(Config) -> - asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper]), + Opts = [uper,?NO_MAPS_MODULE], + asn1_test_lib:compile("EUTRA-extract-7407", Config, Opts), ticket_7407_code(true), - asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper,no_final_padding]), + asn1_test_lib:compile("EUTRA-extract-7407", Config, + [no_final_padding|Opts]), ticket_7407_code(false). ticket_7407_code(FinalPadding) -> diff --git a/lib/asn1/test/asn1_SUITE_data/Maps.asn1 b/lib/asn1/test/asn1_SUITE_data/Maps.asn1 new file mode 100644 index 0000000000..fd5f373e45 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/Maps.asn1 @@ -0,0 +1,17 @@ +Maps DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + +XY ::= SEQUENCE { x INTEGER DEFAULT 0, y INTEGER DEFAULT 0 } + +xy1 XY ::= { x 42, y 17 } +xy2 XY ::= { } +xy3 XY ::= { y 999 } + +S ::= SEQUENCE { + xy XY DEFAULT { x 100, y 100 }, + os OCTET STRING OPTIONAL +} + +s1 S ::= {} + +END diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl index dc614db4f2..a79958d229 100644 --- a/lib/asn1/test/asn1_test_lib.erl +++ b/lib/asn1/test/asn1_test_lib.erl @@ -25,7 +25,8 @@ hex_to_bin/1, match_value/2, parallel/0, - roundtrip/3,roundtrip/4,roundtrip_enc/3,roundtrip_enc/4]). + roundtrip/3,roundtrip/4,roundtrip_enc/3,roundtrip_enc/4, + map_roundtrip/3]). -include_lib("common_test/include/ct.hrl"). @@ -94,15 +95,58 @@ module(F0) -> list_to_atom(F). %% filename:join(CaseDir, F ++ ".beam"). -compile_file(File, Options) -> +compile_file(File, Options0) -> + Options = [warnings_as_errors|Options0], try - ok = asn1ct:compile(File, [warnings_as_errors|Options]) + ok = asn1ct:compile(File, Options), + ok = compile_maps(File, Options) catch _:Reason -> ct:print("Failed to compile ~s\n~p", [File,Reason]), error end. +compile_maps(File, Options) -> + unload_map_mod(File), + Incompat = [abs,compact_bit_string,legacy_bit_string, + legacy_erlang_types,maps,asn1_test_lib_no_maps], + case lists:any(fun(E) -> lists:member(E, Incompat) end, Options) of + true -> + ok; + false -> + compile_maps_1(File, Options) + end. + +compile_maps_1(File, Options) -> + ok = asn1ct:compile(File, [maps,no_ok_wrapper,noobj|Options]), + OutDir = proplists:get_value(outdir, Options), + Base0 = filename:rootname(filename:basename(File)), + Base = case filename:extension(Base0) of + ".set" -> + filename:rootname(Base0); + _ -> + Base0 + end, + ErlBase = Base ++ ".erl", + ErlFile = filename:join(OutDir, ErlBase), + {ok,Erl0} = file:read_file(ErlFile), + Erl = re:replace(Erl0, <<"-module\\('">>, "&maps_"), + MapsErlFile = filename:join(OutDir, "maps_" ++ ErlBase), + ok = file:write_file(MapsErlFile, Erl), + {ok,_} = compile:file(MapsErlFile, [report,{outdir,OutDir},{i,OutDir}]), + ok. + +unload_map_mod(File0) -> + File1 = filename:basename(File0), + File2 = filename:rootname(File1, ".asn"), + File3 = filename:rootname(File2, ".asn1"), + File4 = filename:rootname(File3, ".py"), + File = filename:rootname(File4, ".set"), + MapMod = list_to_atom("maps_"++File), + code:delete(MapMod), + code:purge(MapMod), + ok. + compile_erlang(Mod, Config, Options) -> DataDir = proplists:get_value(data_dir, Config), CaseDir = proplists:get_value(case_dir, Config), @@ -147,24 +191,60 @@ roundtrip(Mod, Type, Value) -> roundtrip(Mod, Type, Value, Value). roundtrip(Mod, Type, Value, ExpectedValue) -> - {ok,Encoded} = Mod:encode(Type, Value), - {ok,ExpectedValue} = Mod:decode(Type, Encoded), - test_ber_indefinite(Mod, Type, Encoded, ExpectedValue), - ok. + roundtrip_enc(Mod, Type, Value, ExpectedValue). roundtrip_enc(Mod, Type, Value) -> roundtrip_enc(Mod, Type, Value, Value). roundtrip_enc(Mod, Type, Value, ExpectedValue) -> - {ok,Encoded} = Mod:encode(Type, Value), - {ok,ExpectedValue} = Mod:decode(Type, Encoded), + case Mod:encode(Type, Value) of + {ok,Encoded} -> + {ok,ExpectedValue} = Mod:decode(Type, Encoded); + Encoded when is_binary(Encoded) -> + ExpectedValue = Mod:decode(Type, Encoded) + end, + map_roundtrip(Mod, Type, Encoded), test_ber_indefinite(Mod, Type, Encoded, ExpectedValue), Encoded. +map_roundtrip(Mod, Type, Encoded) -> + MapMod = list_to_atom("maps_"++atom_to_list(Mod)), + try MapMod:maps() of + true -> + map_roundtrip_1(MapMod, Type, Encoded) + catch + error:undef -> + ok + end. + %%% %%% Internal functions. %%% +map_roundtrip_1(Mod, Type, Encoded) -> + Decoded = Mod:decode(Type, Encoded), + case Mod:encode(Type, Decoded) of + Encoded -> + ok; + OtherEncoding -> + case is_named_bitstring(Decoded) of + true -> + %% In BER, named BIT STRINGs with different number of + %% trailing zeroes decode to the same value. + ok; + false -> + error({encode_mismatch,Decoded,Encoded,OtherEncoding}) + end + end, + ok. + +is_named_bitstring([H|T]) -> + is_atom(H) andalso is_named_bitstring(T); +is_named_bitstring([]) -> + true; +is_named_bitstring(_) -> + false. + hex2num(C) when $0 =< C, C =< $9 -> C - $0; hex2num(C) when $A =< C, C =< $F -> C - $A + 10; hex2num(C) when $a =< C, C =< $f -> C - $a + 10. @@ -179,7 +259,12 @@ test_ber_indefinite(Mod, Type, Encoded, ExpectedValue) -> case Mod:encoding_rule() of ber -> Indefinite = iolist_to_binary(ber_indefinite(Encoded)), - {ok,ExpectedValue} = Mod:decode(Type, Indefinite); + case Mod:decode(Type, Indefinite) of + {ok,ExpectedValue} -> + ok; + ExpectedValue -> + ok + end; _ -> ok end. diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl index 10012908a9..5688d8afd6 100644 --- a/lib/asn1/test/testContextSwitchingTypes.erl +++ b/lib/asn1/test/testContextSwitchingTypes.erl @@ -90,5 +90,6 @@ check_object_identifier(Tuple) when is_tuple(Tuple) -> enc_dec(T, V0) -> M = 'ContextSwitchingTypes', {ok,Enc} = M:encode(T, V0), + asn1_test_lib:map_roundtrip(M, T, Enc), {ok,V} = M:decode(T, Enc), V. diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl index 5a9f47d865..c519c70cdf 100644 --- a/lib/asn1/test/testInfObj.erl +++ b/lib/asn1/test/testInfObj.erl @@ -197,5 +197,6 @@ roundtrip(M, T, V) -> enc_dec(M, T, V0) -> {ok,Enc} = M:encode(T, V0), + asn1_test_lib:map_roundtrip(M, T, Enc), {ok,V} = M:decode(T, Enc), V. diff --git a/lib/asn1/test/testMaps.erl b/lib/asn1/test/testMaps.erl new file mode 100644 index 0000000000..45dd2255ba --- /dev/null +++ b/lib/asn1/test/testMaps.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(testMaps). + +-export([main/1]). + +main(_) -> + M = 'Maps', + true = M:maps(), + + true = M:xy1() =:= #{x=>42,y=>17}, + true = M:xy2() =:= #{x=>0,y=>0}, + true = M:xy3() =:= #{x=>0,y=>999}, + true = M:s1() =:= #{xy=>#{x=>100,y=>100}}, + + roundtrip('XY', M:xy1()), + roundtrip('XY', M:xy2()), + roundtrip('XY', M:xy3()), + roundtrip('XY', #{}, #{x=>0,y=>0}), + + roundtrip('S', M:s1()), + roundtrip('S', #{}, #{xy=>#{x=>100,y=>100}}), + roundtrip('S', #{os=><<1,2,3>>}, #{xy=>#{x=>100,y=>100}, + os=><<1,2,3>>}), + + ok. + +roundtrip(Type, Value) -> + roundtrip(Type, Value, Value). + +roundtrip(Type, Value, Expected) -> + asn1_test_lib:roundtrip('Maps', Type, Value, Expected). diff --git a/lib/asn1/test/testRfcs.erl b/lib/asn1/test/testRfcs.erl index da7333ef98..20176e35eb 100644 --- a/lib/asn1/test/testRfcs.erl +++ b/lib/asn1/test/testRfcs.erl @@ -35,22 +35,27 @@ compile(Config, Erules, Options0) -> asn1_test_lib:compile_all(Specs, Config, [Erules,{i,CaseDir}|Options]). test() -> - {1,3,6,1,5,5,7,48,1,2} = - IdPkixOcspNonce = - 'OCSP-2009':'id-pkix-ocsp-nonce'(), - roundtrip('OCSP-2009', 'OCSPRequest', - {'OCSPRequest', - {'TBSRequest', - 0, - {rfc822Name,"name string"}, - [{'Request', - {'CertID',{'_',{2,9,3,4,5},asn1_NOVALUE}, - <<"POTATOHASH">>,<<"HASHBROWN">>,42}, - [{'_',IdPkixOcspNonce,true,<<34,159,16,57,199>>}]}], - asn1_NOVALUE}, - asn1_NOVALUE}), - otp_7759(), - ok. + M = 'OCSP-2009', + case M:maps() of + false -> + {1,3,6,1,5,5,7,48,1,2} = + IdPkixOcspNonce = + 'OCSP-2009':'id-pkix-ocsp-nonce'(), + roundtrip('OCSP-2009', 'OCSPRequest', + {'OCSPRequest', + {'TBSRequest', + 0, + {rfc822Name,"name string"}, + [{'Request', + {'CertID',{'_',{2,9,3,4,5},asn1_NOVALUE}, + <<"POTATOHASH">>,<<"HASHBROWN">>,42}, + [{'_',IdPkixOcspNonce,true,<<34,159,16,57,199>>}]}], + asn1_NOVALUE}, + asn1_NOVALUE}), + otp_7759(records); + true -> + otp_7759(maps) + end. roundtrip(Module, Type, Value0) -> Enc = Module:encode(Type, Value0), @@ -58,7 +63,7 @@ roundtrip(Module, Type, Value0) -> asn1_test_lib:match_value(Value0, Value1), ok. -otp_7759() -> +otp_7759(Pack) -> %% The release note for asn-1.6.6 says: %% Decode of an open_type when the value was empty tagged %% type encoded with indefinite length failed. @@ -66,10 +71,15 @@ otp_7759() -> Encoded = encoded_msg(), ContentInfo = Mod:decode('ContentInfo', Encoded), io:format("~p\n", [ContentInfo]), - {'ContentInfo',_Id,PKCS7_content} = ContentInfo, - X = Mod:decode('SignedData', PKCS7_content), + Content = case ContentInfo of + {'ContentInfo',_Id,Content0} when Pack =:= records -> + Content0; + #{'content-type':=_,'pkcs7-content':=Content0} + when Pack =:= maps -> + Content0 + end, + X = Mod:decode('SignedData', Content), io:format("~p\n", [X]), - io:nl(), ok. encoded_msg() -> diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl index 422ae1f0fc..a6f0f9fad7 100644 --- a/lib/asn1/test/testTCAP.erl +++ b/lib/asn1/test/testTCAP.erl @@ -92,5 +92,6 @@ test_asn1config() -> enc_dec(T, V0) -> M = 'TCAPPackage', {ok,Enc} = M:encode(T, V0), + asn1_test_lib:map_roundtrip(M, T, Enc), {ok,V} = M:decode(T, Enc), V. diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl index bd8da85735..3edeb1b712 100644 --- a/lib/asn1/test/testTimer.erl +++ b/lib/asn1/test/testTimer.erl @@ -25,7 +25,42 @@ -define(times, 5000). -val() -> +go() -> + Module = 'H323-MESSAGES', + Type = 'H323-UserInformation', + Value = case Module:maps() of + false -> val_records(); + true -> val_maps() + end, + Bytes = Module:encode(Type, Value), + Value = Module:decode(Type, Bytes), + + {ValWr,done} = timer:tc(fun() -> encode(?times, Module, Type, Value) end), + io:format("ASN.1 encoding: ~p micro~n", [ValWr / ?times]), + + done = decode(2, Module, Type, Bytes), + + {ValRead,done} = timer:tc(fun() -> decode(?times, Module, Type, Bytes) end), + io:format("ASN.1 decoding: ~p micro~n", [ValRead /?times]), + + Comment = "encode: "++integer_to_list(round(ValWr/?times)) ++ + " micro, decode: "++integer_to_list(round(ValRead /?times)) ++ + " micro. [" ++ atom_to_list(Module:encoding_rule()) ++ "]", + {comment,Comment}. + +encode(0, _Module,_Type,_Value) -> + done; +encode(N, Module,Type,Value) -> + Module:encode(Type, Value), + encode(N-1, Module, Type, Value). + +decode(0, _Module, _Type, _Value) -> + done; +decode(N, Module, Type, Value) -> + Module:decode(Type, Value), + decode(N-1, Module, Type, Value). + +val_records() -> {'H323-UserInformation',{'H323-UU-PDU', {callProceeding, {'CallProceeding-UUIE', @@ -126,34 +161,66 @@ val() -> {'H323-UserInformation_user-data',24,<<"O">>}}. -go() -> - Module = 'H323-MESSAGES', - Type = 'H323-UserInformation', - Value = val(), - Bytes = Module:encode(Type, Value), - Value = Module:decode(Type, Bytes), - - {ValWr,done} = timer:tc(fun() -> encode(?times, Module, Type, Value) end), - io:format("ASN.1 encoding: ~p micro~n", [ValWr / ?times]), - - done = decode(2, Module, Type, Bytes), - - {ValRead,done} = timer:tc(fun() -> decode(?times, Module, Type, Bytes) end), - io:format("ASN.1 decoding: ~p micro~n", [ValRead /?times]), - - Comment = "encode: "++integer_to_list(round(ValWr/?times)) ++ - " micro, decode: "++integer_to_list(round(ValRead /?times)) ++ - " micro. [" ++ atom_to_list(Module:encoding_rule()) ++ "]", - {comment,Comment}. - -encode(0, _Module,_Type,_Value) -> - done; -encode(N, Module,Type,Value) -> - Module:encode(Type, Value), - encode(N-1, Module, Type, Value). - -decode(0, _Module, _Type, _Value) -> - done; -decode(N, Module, Type, Value) -> - Module:decode(Type, Value), - decode(N-1, Module, Type, Value). +val_maps() -> +#{'h323-uu-pdu' => #{h245Control => [], + h245Tunneling => true, + 'h323-message-body' => {callProceeding,#{callIdentifier => #{guid => <<"OCTET STRINGOCTE">>}, + cryptoTokens => [{cryptoGKPwdEncr,#{algorithmOID => {1,18,467,467}, + encryptedData => <<"OC">>, + paramS => #{iv8 => <<"OCTET ST">>, + ranInt => -7477016}}}, + {cryptoGKPwdEncr,#{algorithmOID => {1,19,486,486}, + encryptedData => <<>>, + paramS => #{iv8 => <<"OCTET ST">>, + ranInt => -2404513}}}], + destinationInfo => #{gatekeeper => #{nonStandardData => #{data => <<"O">>, + nonStandardIdentifier => {object,{0,10,260}}}}, + gateway => #{nonStandardData => #{data => <<"O">>, + nonStandardIdentifier => {object,{0,13,326}}}, + protocol => [{h320,#{dataRatesSupported => [#{channelMultiplier => 78, + channelRate => 1290470518, + nonStandardData => #{data => <<"O">>, + nonStandardIdentifier => {object,{0,11,295}}}}], + nonStandardData => #{data => <<"O">>, + nonStandardIdentifier => {object,{0,11,282}}}, + supportedPrefixes => [#{nonStandardData => #{data => <<"O">>, + nonStandardIdentifier => {object,{0,12,312}}}, + prefix => {'h323-ID',"BM"}}]}}]}, + mc => true, + mcu => #{nonStandardData => #{data => <<"OC">>, + nonStandardIdentifier => {object,{1,13,340,340}}}}, + nonStandardData => #{data => <<"O">>,nonStandardIdentifier => {object,{0,9,237}}}, + terminal => #{nonStandardData => #{data => <<"OC">>, + nonStandardIdentifier => {object,{1,14,353,354}}}}, + undefinedNode => true, + vendor => #{productId => <<"OC">>, + vendor => #{manufacturerCode => 16282, + t35CountryCode => 62, + t35Extension => 63}, + versionId => <<"OC">>}}, + fastStart => [], + h245Address => {ipxAddress,#{netnum => <<"OCTE">>, + node => <<"OCTET ">>, + port => <<"OC">>}}, + h245SecurityMode => {noSecurity,'NULL'}, + protocolIdentifier => {0,8,222}, + tokens => [#{certificate => #{certificate => <<"OC">>,type => {1,16,405,406}}, + challenge => <<"OCTET STR">>, + dhkey => #{generator => <<1:1>>,halfkey => <<1:1>>,modSize => <<1:1>>}, + generalID => "BMP", + nonStandard => #{data => <<"OC">>,nonStandardIdentifier => {1,16,414,415}}, + password => "BM", + random => -26430296, + timeStamp => 1667517741}, + #{certificate => #{certificate => <<"OC">>,type => {1,17,442,443}}, + challenge => <<"OCTET STRI">>, + dhkey => #{generator => <<1:1>>,halfkey => <<1:1>>,modSize => <<1:1>>}, + generalID => "BMP", + nonStandard => #{data => <<"OC">>,nonStandardIdentifier => {1,18,452,452}}, + password => "BMP", + random => -16356110, + timeStamp => 1817656756}]}}, + h4501SupplementaryService => [], + nonStandardControl => [], + nonStandardData => #{data => <<>>,nonStandardIdentifier => {object,{0,3,84}}}}, + 'user-data' => #{'protocol-discriminator' => 24,'user-information' => <<"O">>}}. diff --git a/lib/asn1/test/testUniqueObjectSets.erl b/lib/asn1/test/testUniqueObjectSets.erl index 4d3ec94391..30cbceb577 100644 --- a/lib/asn1/test/testUniqueObjectSets.erl +++ b/lib/asn1/test/testUniqueObjectSets.erl @@ -27,6 +27,7 @@ seq_roundtrip(I, D0) -> M = 'UniqueObjectSets', try {ok,Enc} = M:encode('Seq', {'Seq',I,D0}), + asn1_test_lib:map_roundtrip(M, 'Seq', Enc), {ok,{'Seq',I,D}} = M:decode('Seq', Enc), D catch C:E -> diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index ac74470537..c15e61550c 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -24,8 +24,8 @@ -include_lib("common_test/include/ct.hrl"). --export([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1, - record_name_prefix/1,verbose/1]). +-export([wrong_path/1,comp/2,path/1,noobj/1, + record_name_prefix/1,verbose/1,maps/1]). %% OTP-5689 wrong_path(Config) -> @@ -64,8 +64,6 @@ path(Config) -> file:set_cwd(CWD), ok. -ticket_6143(Config) -> asn1_test_lib:compile("AA1", Config, []). - noobj(Config) -> DataDir = proplists:get_value(data_dir,Config), OutDir = proplists:get_value(priv_dir,Config), @@ -130,6 +128,28 @@ verbose(Config) when is_list(Config) -> [] = test_server:capture_get(), ok. +maps(Config) -> + DataDir = proplists:get_value(data_dir, Config), + OutDir = proplists:get_value(case_dir, Config), + InFile = filename:join(DataDir, "P-Record"), + + do_maps(ber, InFile, OutDir), + do_maps(per, InFile, OutDir), + do_maps(uper, InFile, OutDir). + +do_maps(Erule, InFile, OutDir) -> + Opts = [Erule,maps,{outdir,OutDir}], + ok = asn1ct:compile(InFile, Opts), + + %% Make sure that no .hrl files are generated. + [] = filelib:wildcard(filename:join(OutDir, "*.hrl")), + + %% Remove all generated files. + All = filelib:wildcard(filename:join(OutDir, "*")), + _ = [file:delete(N) || N <- All], + + ok. + outfiles_check(OutDir) -> outfiles_check(OutDir,outfiles1()). -- cgit v1.2.3