aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/text
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/src/text')
-rw-r--r--lib/megaco/src/text/Makefile148
-rw-r--r--lib/megaco/src/text/depend.mk187
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder.erl560
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_prev3a.erl297
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_prev3b.erl432
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_prev3c.erl455
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_v1.erl407
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_v2.erl413
-rw-r--r--lib/megaco/src/text/megaco_compact_text_encoder_v3.erl455
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder.erl613
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_prev3a.erl303
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_prev3b.erl437
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_prev3c.erl483
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_v1.erl407
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_v2.erl430
-rw-r--r--lib/megaco/src/text/megaco_pretty_text_encoder_v3.erl462
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3a.hrl2945
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3b.hrl2966
-rw-r--r--lib/megaco/src/text/megaco_text_gen_prev3c.hrl3443
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v1.hrl2404
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v2.hrl2794
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v3.hrl3457
-rw-r--r--lib/megaco/src/text/megaco_text_mini_decoder.erl88
-rw-r--r--lib/megaco/src/text/megaco_text_mini_parser.hrl1246
-rw-r--r--lib/megaco/src/text/megaco_text_mini_parser.yrl398
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3a.hrl1670
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3a.yrl1591
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3b.hrl1717
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3b.yrl1601
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3c.hrl1980
-rw-r--r--lib/megaco/src/text/megaco_text_parser_prev3c.yrl1673
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v1.hrl1410
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v1.yrl1364
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v2.hrl1643
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v2.yrl1538
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v3.hrl2002
-rw-r--r--lib/megaco/src/text/megaco_text_parser_v3.yrl1680
-rw-r--r--lib/megaco/src/text/megaco_text_scanner.erl869
-rw-r--r--lib/megaco/src/text/megaco_text_tokens.hrl475
-rw-r--r--lib/megaco/src/text/modules.mk65
40 files changed, 47508 insertions, 0 deletions
diff --git a/lib/megaco/src/text/Makefile b/lib/megaco/src/text/Makefile
new file mode 100644
index 0000000000..b2e8e762dd
--- /dev/null
+++ b/lib/megaco/src/text/Makefile
@@ -0,0 +1,148 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+include $(ERL_TOP)/make/target.mk
+
+EBIN = ../../ebin
+MEGACO_INCLUDEDIR = ../../include
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(MEGACO_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = \
+ $(MODULES:%=%.erl) \
+ $(INTERNAL_YRL_FILES:%.yrl=%.erl)
+
+ERL_TARGET_FILES = \
+ $(INTERNAL_YRL_FILES:%.yrl=%.erl)
+
+BEAM_TARGET_FILES = \
+ $(INTERNAL_YRL_FILES:%.yrl=$(EBIN)/%.$(EMULATOR)) \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+TARGET_FILES = $(ERL_TARGET_FILES) $(BEAM_TARGET_FILES)
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+include ../app/megaco.mk
+
+ERL_COMPILE_FLAGS += \
+ $(MEGACO_ERL_COMPILE_FLAGS) \
+ -I../../include
+
+# YRL_FLAGS += -pa /clearcase/otp/tools/parsetools/ebin
+
+ifeq ($(YRL_VERBOSE),true)
+YRL_FLAGS += -v
+endif
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+info:
+ @echo "MODULES = $(MODULES)"
+ @echo ""
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo ""
+ @echo "ERL_TARGET_FILES = $(ERL_TARGET_FILES)"
+ @echo ""
+ @echo "BEAM_TARGET_FILES = $(BEAM_TARGET_FILES)"
+ @echo ""
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+ @echo "INTERNAL_YRL_FILES = $(INTERNAL_YRL_FILES)"
+ @echo ""
+ @echo "INTERNAL_HRL_FILES = $(INTERNAL_HRL_FILES)"
+ @echo ""
+
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+parser: parser_v1 parser_v2 parser_prev3a parser_prev3b
+
+parser_v1: megaco_text_parser_v1.$(EMULATOR)
+
+parser_v2: megaco_text_parser_v2.$(EMULATOR)
+
+parser_prev3a: megaco_text_parser_prev3a.$(EMULATOR)
+
+parser_prev3b: megaco_text_parser_prev3b.$(EMULATOR)
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(BEAM_TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/text
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_YRL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/text
+
+
+release_docs_spec:
+
+
+# ----------------------------------------------------
+# Include dependencies
+# ----------------------------------------------------
+
+include depend.mk
+
diff --git a/lib/megaco/src/text/depend.mk b/lib/megaco/src/text/depend.mk
new file mode 100644
index 0000000000..62d0811692
--- /dev/null
+++ b/lib/megaco/src/text/depend.mk
@@ -0,0 +1,187 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+megaco_text_parser_v1.erl: \
+ megaco_text_parser_v1.yrl \
+ megaco_text_parser_v1.hrl
+megaco_text_parser_v2.erl: \
+ megaco_text_parser_v2.yrl \
+ megaco_text_parser_v2.hrl
+megaco_text_parser_v3.erl: \
+ megaco_text_parser_v3.yrl \
+ megaco_text_parser_v3.hrl
+megaco_text_parser_prev3a.erl: \
+ megaco_text_parser_prev3a.yrl \
+ megaco_text_parser_prev3a.hrl
+megaco_text_parser_prev3b.erl: \
+ megaco_text_parser_prev3b.yrl \
+ megaco_text_parser_prev3b.hrl
+megaco_text_parser_prev3c.erl: \
+ megaco_text_parser_prev3c.yrl \
+ megaco_text_parser_prev3c.hrl
+
+megaco_text_mini_parser.erl: \
+ megaco_text_mini_parser.yrl \
+ megaco_text_mini_parser.hrl
+
+$(EBIN)/megaco_compact_text_encoder.$(EMULATOR): \
+ megaco_compact_text_encoder.erl
+
+$(EBIN)/megaco_compact_text_encoder.$(EMULATOR): \
+ megaco_compact_text_encoder.erl
+
+$(EBIN)/megaco_compact_text_encoder_v1.$(EMULATOR): \
+ megaco_compact_text_encoder_v1.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v1.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v1.hrl
+
+$(EBIN)/megaco_compact_text_encoder_v2.$(EMULATOR): \
+ megaco_compact_text_encoder_v2.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v2.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v2.hrl
+
+$(EBIN)/megaco_compact_text_encoder_v3.$(EMULATOR): \
+ megaco_compact_text_encoder_v3.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v3.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v3.hrl
+
+$(EBIN)/megaco_compact_text_encoder_prev3a.$(EMULATOR): \
+ megaco_compact_text_encoder_prev3a.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3a.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3a.hrl
+
+$(EBIN)/megaco_compact_text_encoder_prev3b.$(EMULATOR): \
+ megaco_compact_text_encoder_prev3b.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3b.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3b.hrl
+
+$(EBIN)/megaco_compact_text_encoder_prev3c.$(EMULATOR): \
+ megaco_compact_text_encoder_prev3c.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3c.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3c.hrl
+
+$(EBIN)/megaco_pretty_text_encoder.$(EMULATOR): \
+ megaco_pretty_text_encoder.erl
+
+$(EBIN)/megaco_pretty_text_encoder_v1.$(EMULATOR): \
+ megaco_pretty_text_encoder_v1.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v1.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v1.hrl
+
+$(EBIN)/megaco_pretty_text_encoder_v2.$(EMULATOR): \
+ megaco_pretty_text_encoder_v2.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v2.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v2.hrl
+
+$(EBIN)/megaco_pretty_text_encoder_v3.$(EMULATOR): \
+ megaco_pretty_text_encoder_v3.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v3.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_v3.hrl
+
+$(EBIN)/megaco_pretty_text_encoder_prev3a.$(EMULATOR): \
+ megaco_pretty_text_encoder_prev3a.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3a.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3a.hrl
+
+$(EBIN)/megaco_pretty_text_encoder_prev3b.$(EMULATOR): \
+ megaco_pretty_text_encoder_prev3b.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3b.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3b.hrl
+
+$(EBIN)/megaco_pretty_text_encoder_prev3c.$(EMULATOR): \
+ megaco_pretty_text_encoder_prev3c.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3c.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_gen_prev3c.hrl
+
+$(EBIN)/megaco_text_parser_v1.$(EMULATOR): \
+ megaco_text_parser_v1.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v1.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_v1.hrl
+
+$(EBIN)/megaco_text_parser_v2.$(EMULATOR): \
+ megaco_text_parser_v2.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v2.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_v2.hrl
+
+$(EBIN)/megaco_text_parser_v3.$(EMULATOR): \
+ megaco_text_parser_v3.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_v3.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_v3.hrl
+
+$(EBIN)/megaco_text_parser_prev3a.$(EMULATOR): \
+ megaco_text_parser_prev3a.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3a.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_prev3a.hrl
+
+$(EBIN)/megaco_text_parser_prev3b.$(EMULATOR): \
+ megaco_text_parser_prev3b.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3b.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_prev3b.hrl
+
+$(EBIN)/megaco_text_parser_prev3c.$(EMULATOR): \
+ megaco_text_parser_prev3c.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ $(MEGACO_INCLUDEDIR)/megaco_message_prev3c.hrl \
+ megaco_text_tokens.hrl \
+ megaco_text_parser_prev3c.hrl
+
+$(EBIN)/megaco_text_scanner.$(EMULATOR): megaco_text_scanner.erl \
+ $(MEGACO_INCLUDEDIR)/megaco.hrl \
+ ../engine/megaco_message_internal.hrl \
+ megaco_text_tokens.hrl
+
+$(EBIN)/megaco_text_mini_decoder.$(EMULATOR): \
+ megaco_text_mini_decoder.erl \
+ ../engine/megaco_message_internal.hrl \
+ megaco_text_tokens.hrl
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder.erl b/lib/megaco/src/text/megaco_compact_text_encoder.erl
new file mode 100644
index 0000000000..f5195bda14
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder.erl
@@ -0,0 +1,560 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder).
+
+-behaviour(megaco_encoder).
+
+-export([encode_message/3, decode_message/3,
+ decode_mini_message/3,
+
+ version_of/2,
+
+ encode_transaction/3,
+ encode_action_requests/3,
+ encode_action_request/3,
+ encode_command_request/3,
+ encode_action_reply/3]).
+
+-export([token_tag2string/1, token_tag2string/2]).
+
+%% Backward compatible funcs:
+-export([encode_message/2, decode_message/2]).
+
+
+-include_lib("megaco/src/engine/megaco_message_internal.hrl").
+
+-define(V1_PARSE_MOD, megaco_text_parser_v1).
+-define(V2_PARSE_MOD, megaco_text_parser_v2).
+-define(V3_PARSE_MOD, megaco_text_parser_v3).
+-define(PREV3A_PARSE_MOD, megaco_text_parser_prev3a).
+-define(PREV3B_PARSE_MOD, megaco_text_parser_prev3b).
+-define(PREV3C_PARSE_MOD, megaco_text_parser_prev3c).
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EncodingConfig,
+ #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) ->
+ encode_message(EncodingConfig, V, MegaMsg).
+
+encode_message([{version3,_}|EC], 1, MegaMsg) ->
+ megaco_compact_text_encoder_v1:encode_message(EC, MegaMsg);
+encode_message(EC, 1, MegaMsg) ->
+ megaco_compact_text_encoder_v1:encode_message(EC, MegaMsg);
+encode_message([{version3,_}|EC], 2, MegaMsg) ->
+ megaco_compact_text_encoder_v2:encode_message(EC, MegaMsg);
+encode_message(EC, 2, MegaMsg) ->
+ megaco_compact_text_encoder_v2:encode_message(EC, MegaMsg);
+encode_message([{version3,v3}|EC], 3, MegaMsg) ->
+ megaco_compact_text_encoder_v3:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3c}|EC], 3, MegaMsg) ->
+ megaco_compact_text_encoder_prev3c:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3b}|EC], 3, MegaMsg) ->
+ megaco_compact_text_encoder_prev3b:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3a}|EC], 3, MegaMsg) ->
+ megaco_compact_text_encoder_prev3a:encode_message(EC, MegaMsg);
+encode_message(EC, 3, MegaMsg) ->
+ megaco_compact_text_encoder_v3:encode_message(EC, MegaMsg);
+encode_message(_EC, V, _MegaMsg) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%----------------------------------------------------------------------
+
+version_of(_EC, Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, _Tokens, V, _LastLine} ->
+ {ok, V};
+ {error, Reason, Line} ->
+ {error, {decode_failed, Reason, Line}}
+ end.
+
+decode_message(EC, Bin) ->
+ %% d("decode_message -> entry with"
+ %% "~n EC: ~p", [EC]),
+ decode_message(EC, dynamic, Bin).
+
+decode_message([], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message([]) -> entry"),
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,v3}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(v3) -> entry"),
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3c}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3c) -> entry"),
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3b}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3b) -> entry"),
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3a}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3a) -> entry"),
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{flex, Port}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(flex) -> entry"),
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,v3},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(v3,flex) -> entry"),
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3c},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3c,flex) -> entry"),
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} ->
+ scan_error(Reason, Line, Bin)
+ end;
+decode_message([{version3,prev3b},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3b,flex) -> entry"),
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3a},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ %% d("decode_message(prev3a,flex) -> entry"),
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message(EC, _, Bin) when is_binary(Bin) ->
+ {error, {bad_encoding_config, EC}};
+decode_message(_EC, _, _BadBin) ->
+ {error, bad_binary}.
+
+
+do_decode_message(ParseMod, Tokens, Bin) ->
+%% d("do_decode_message -> entry with"
+%% "~n ParseMod: ~p"
+%% "~n Tokens: ~p", [ParseMod, Tokens]),
+ case (catch ParseMod:parse(Tokens)) of
+ {ok, MegacoMessage} ->
+%% d("do_decode_message -> "
+%% "~n MegacoMessage: ~p", [MegacoMessage]),
+ {ok, MegacoMessage};
+ {error, Reason} ->
+ parse_error(Reason, Tokens, Bin);
+
+ %% OTP-4007
+ {'EXIT', Reason} ->
+ parse_error(Reason, Tokens, Bin)
+ end.
+
+
+decode_mini_message(EC, _, Bin) when is_binary(Bin) ->
+ megaco_text_mini_decoder:decode_message(EC, Bin).
+
+
+scan_error(Reason, Line, Bin) ->
+ scan_error(Reason, Line, [], Bin).
+
+scan_error("bad_property_parm: " ++ Reason, _Line, _Tokens, _Bin) ->
+ {error, {bad_property_parm, Reason}};
+scan_error(Reason, Line, Tokens, Bin) ->
+ %% io:format("scanner error: "
+ %% "~n Reason: ~p"
+ %% "~n Line: ~p"
+ %% "~n Tokens: ~p"
+ %% "~n Bin: ~p"
+ %% "~n", [Reason, Line, Tokens, Bin]),
+ {error, [{reason, Reason, Line}, {token, Tokens}, {chars, Bin}]}.
+
+parse_error(Reason, Tokens, Chars) ->
+ %% io:format("parser error -> entry with"
+ %% "~n Reason: ~p"
+ %% "~n Tokens: ~p"
+ %% "~n", [Reason, Tokens]),
+ case Reason of
+ {Line, Mod, [Prefix, [$[, TokenStringRaw, $]]]} when
+ is_integer(Line) andalso
+ is_atom(Mod) andalso
+ is_list(Prefix) andalso
+ is_list(TokenStringRaw) ->
+ TokenString = [l2i(X) || X <- TokenStringRaw, is_list(X)],
+ ReasonStr = Prefix ++ TokenString,
+ {error, [{reason, ReasonStr, Line}, {tokens, Tokens}, {chars, Chars}, {module, Mod}]};
+ _ ->
+ {error, [{reason, Reason}, {token, Tokens}, {chars, Chars}]}
+ end.
+
+
+l2i(L) when is_list(L) ->
+ case (catch list_to_integer(L)) of
+ I when is_integer(I) ->
+ I;
+ _ ->
+ L
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction([{version3,_}|EC], 1, Trans) ->
+ megaco_compact_text_encoder_v1:encode_transaction(EC, Trans);
+encode_transaction(EC, 1, Trans) ->
+ megaco_compact_text_encoder_v1:encode_transaction(EC, Trans);
+encode_transaction([{version3,_}|EC], 2, Trans) ->
+ megaco_compact_text_encoder_v2:encode_transaction(EC, Trans);
+encode_transaction(EC, 2, Trans) ->
+ megaco_compact_text_encoder_v2:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3c}|EC], 3, Trans) ->
+ megaco_compact_text_encoder_prev3c:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3b}|EC], 3, Trans) ->
+ megaco_compact_text_encoder_prev3b:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3a}|EC], 3, Trans) ->
+ megaco_compact_text_encoder_prev3a:encode_transaction(EC, Trans);
+encode_transaction([{version3,v3}|EC], 3, Trans) ->
+ megaco_compact_text_encoder_v3:encode_transaction(EC, Trans);
+encode_transaction(EC, 3, Trans) ->
+ megaco_compact_text_encoder_v3:encode_transaction(EC, Trans);
+encode_transaction(_EC, V, _Trans) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests([{version3,_}|EC], 1, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v1:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 1, ActReqs) when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v1:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,_}|EC], 2, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v2:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 2, ActReqs) when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v2:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3c}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_prev3c:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3b}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_prev3b:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3a}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_prev3a:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,v3}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v3:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) ->
+ megaco_compact_text_encoder_v3:encode_action_requests(EC, ActReqs);
+encode_action_requests(_EC, V, _ActReqs) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request([{version3,_}|EC], 1, ActReq) ->
+ megaco_compact_text_encoder_v1:encode_action_request(EC, ActReq);
+encode_action_request(EC, 1, ActReq) ->
+ megaco_compact_text_encoder_v1:encode_action_request(EC, ActReq);
+encode_action_request([{version3,_}|EC], 2, ActReq) ->
+ megaco_compact_text_encoder_v2:encode_action_request(EC, ActReq);
+encode_action_request(EC, 2, ActReq) ->
+ megaco_compact_text_encoder_v2:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3c}|EC], 3, ActReq) ->
+ megaco_compact_text_encoder_prev3c:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3b}|EC], 3, ActReq) ->
+ megaco_compact_text_encoder_prev3b:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3a}|EC], 3, ActReq) ->
+ megaco_compact_text_encoder_prev3a:encode_action_request(EC, ActReq);
+encode_action_request([{version3,v3}|EC], 3, ActReq) ->
+ megaco_compact_text_encoder_v3:encode_action_request(EC, ActReq);
+encode_action_request(EC, 3, ActReq) ->
+ megaco_compact_text_encoder_v3:encode_action_request(EC, ActReq);
+encode_action_request(_EC, V, _ActReq) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request([{version3,_}|EC], 1, CmdReq) ->
+ megaco_compact_text_encoder_v1:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 1, CmdReq) ->
+ megaco_compact_text_encoder_v1:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,_}|EC], 2, CmdReq) ->
+ megaco_compact_text_encoder_v2:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 2, CmdReq) ->
+ megaco_compact_text_encoder_v2:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3c}|EC], 3, CmdReq) ->
+ megaco_compact_text_encoder_prev3c:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3b}|EC], 3, CmdReq) ->
+ megaco_compact_text_encoder_prev3b:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3a}|EC], 3, CmdReq) ->
+ megaco_compact_text_encoder_prev3a:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,v3}|EC], 3, CmdReq) ->
+ megaco_compact_text_encoder_v3:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 3, CmdReq) ->
+ megaco_compact_text_encoder_v3:encode_command_request(EC, CmdReq);
+encode_command_request(_EC, V, _CmdReq) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply([{version3,_}|EC], 1, ActRep) ->
+ megaco_compact_text_encoder_v1:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 1, ActRep) ->
+ megaco_compact_text_encoder_v1:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,_}|EC], 2, ActRep) ->
+ megaco_compact_text_encoder_v2:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 2, ActRep) ->
+ megaco_compact_text_encoder_v2:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3c}|EC], 3, ActRep) ->
+ megaco_compact_text_encoder_prev3c:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3b}|EC], 3, ActRep) ->
+ megaco_compact_text_encoder_prev3b:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3a}|EC], 3, ActRep) ->
+ megaco_compact_text_encoder_prev3a:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,v3}|EC], 3, ActRep) ->
+ megaco_compact_text_encoder_v3:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 3, ActRep) ->
+ megaco_compact_text_encoder_v3:encode_action_reply(EC, ActRep);
+encode_action_reply(_EC, V, _ActRep) ->
+ {error, {bad_version, V}}.
+
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+-define(TT2S_BEST_VERSION, v3).
+
+token_tag2string(Tag) ->
+ token_tag2string(Tag, ?TT2S_BEST_VERSION).
+
+token_tag2string(Tag, 1) ->
+ token_tag2string(Tag, v1);
+token_tag2string(Tag, v1) ->
+ megaco_compact_text_encoder_v1:token_tag2string(Tag);
+token_tag2string(Tag, 2) ->
+ token_tag2string(Tag, v2);
+token_tag2string(Tag, v2) ->
+ megaco_compact_text_encoder_v2:token_tag2string(Tag);
+token_tag2string(Tag, 3) ->
+ token_tag2string(Tag, v3);
+token_tag2string(Tag, v3) ->
+ megaco_compact_text_encoder_v3:token_tag2string(Tag);
+token_tag2string(Tag, prev3b) ->
+ megaco_compact_text_encoder_prev3b:token_tag2string(Tag);
+token_tag2string(Tag, prev3c) ->
+ megaco_compact_text_encoder_prev3c:token_tag2string(Tag);
+token_tag2string(Tag, _Vsn) ->
+ token_tag2string(Tag, ?TT2S_BEST_VERSION).
+
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE|A]);
+%% d(_, _, _) ->
+%% ok.
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_prev3a.erl b/lib/megaco/src/text/megaco_compact_text_encoder_prev3a.erl
new file mode 100644
index 0000000000..a45d35cc43
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_prev3a.erl
@@ -0,0 +1,297 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_prev3a).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3a.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(LSBRKT_INDENT(_State), [?LsbrktToken]).
+-define(RSBRKT_INDENT(_State), [?RsbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothToken , ?CompactBothToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(ContextAttrToken , ?CompactContextAttrToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DirectionToken , ?CompactDirectionToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(EmergencyOffToken , ?CompactEmergencyOffToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(ExternalToken , ?CompactExternalToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(IEPSToken , ?CompactIEPSToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InternalToken , ?CompactInternalToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(Nx64kToken , ?CompactNx64kToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(RequestIDToken , ?CompactRequestIDToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?CompactServiceChangeIncompleteToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3a.hrl").
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_prev3b.erl b/lib/megaco/src/text/megaco_compact_text_encoder_prev3b.erl
new file mode 100644
index 0000000000..63f76040ce
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_prev3b.erl
@@ -0,0 +1,432 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_prev3b).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3b.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(both) -> ?CompactBothToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAttrToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+%% token_tag2string(X) -> ?CompactContextListToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDirectionToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+%% token_tag2string(X) -> ?CompactEmergencyOffToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+token_tag2string(external) -> ?CompactExternalToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+token_tag2string(iepsCallind) -> ?CompactIEPSToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(internal) -> ?CompactInternalToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+%% token_tag2string(X) -> ?CompactNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+%% token_tag2string(X) -> ?CompactRequestIDToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?CompactServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(LSBRKT_INDENT(_State), [?LsbrktToken]).
+-define(RSBRKT_INDENT(_State), [?RsbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothToken , ?CompactBothToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(ContextAttrToken , ?CompactContextAttrToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DirectionToken , ?CompactDirectionToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(EmergencyOffToken , ?CompactEmergencyOffToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(ExternalToken , ?CompactExternalToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(IEPSToken , ?CompactIEPSToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InternalToken , ?CompactInternalToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(Nx64kToken , ?CompactNx64kToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(RequestIDToken , ?CompactRequestIDToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?CompactServiceChangeIncompleteToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3b.hrl").
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_prev3c.erl b/lib/megaco/src/text/megaco_compact_text_encoder_prev3c.erl
new file mode 100644
index 0000000000..10d7b7e732
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_prev3c.erl
@@ -0,0 +1,455 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_prev3c).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3c.hrl").
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+%% token_tag2string(X) -> ?CompactAndAUDITSelectToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(both) -> ?CompactBothToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+%% token_tag2string(X) -> ?CompactContextAttrToken;
+%% token_tag2string(X) -> ?CompactContextListToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDirectionToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+%% token_tag2string(X) -> ?CompactEmergencyOffToken;
+%% token_tag2string(X) -> ?CompactEmergencyValueToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+token_tag2string(external) -> ?CompactExternalToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+token_tag2string(iepsCallind) -> ?CompactIEPSToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(internal) -> ?CompactInternalToken;
+%% token_tag2string(X) -> ?CompactIntsigDelayToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(iteration) -> ?CompactIterationToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+%% token_tag2string(X) -> ?CompactNeverNotifyToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+%% token_tag2string(X) -> ?CompactNotifyImmediateToken;
+%% token_tag2string(X) -> ?CompactNotifyRegulatedToken;
+%% token_tag2string(X) -> ?CompactNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onewayboth) -> ?CompactOnewayBothToken;
+token_tag2string(onewayexternal) -> ?CompactOnewayExternalToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+%% token_tag2string(X) -> ?CompactOrAUDITselectToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+token_tag2string(resetEventsDescriptor) -> ?CompactResetEventsDescriptorToken;
+%% token_tag2string(X) -> ?CompactRequestIDToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?CompactServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(LSBRKT_INDENT(_State), [?LsbrktToken]).
+-define(RSBRKT_INDENT(_State), [?RsbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AndAUDITSelectToken , ?CompactAndAUDITSelectToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothToken , ?CompactBothToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(ContextAttrToken , ?CompactContextAttrToken).
+-define(ContextListToken , ?CompactContextListToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DirectionToken , ?CompactDirectionToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(EmergencyOffToken , ?CompactEmergencyOffToken).
+-define(EmergencyValueToken , ?CompactEmergencyValueToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(ExternalToken , ?CompactExternalToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(IEPSToken , ?CompactIEPSToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InternalToken , ?CompactInternalToken).
+-define(IntsigDelayToken , ?CompactIntsigDelayToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IterationToken , ?CompactIterationToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+%% -define(MessageSegmentToken , ?CompactMessageSegmentToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NeverNotifyToken , ?CompactNeverNotifyToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(NotifyImmediateToken , ?CompactNotifyImmediateToken).
+-define(NotifyRegulatedToken , ?CompactNotifyRegulatedToken).
+-define(Nx64kToken , ?CompactNx64kToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnewayBothToken , ?CompactOnewayBothToken).
+-define(OnewayExternalToken , ?CompactOnewayExternalToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OrAUDITselectToken , ?CompactOrAUDITselectToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResetEventsDescriptorToken , ?CompactResetEventsDescriptorToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(RequestIDToken , ?CompactRequestIDToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+%% -define(SegmentationCompleteToken , ?CompactSegmentationCompleteToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?CompactServiceChangeIncompleteToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3c.hrl").
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_v1.erl b/lib/megaco/src/text/megaco_compact_text_encoder_v1.erl
new file mode 100644
index 0000000000..c1b454dc0f
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_v1.erl
@@ -0,0 +1,407 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_v1).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v1.hrl").
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_v2.erl b/lib/megaco/src/text/megaco_compact_text_encoder_v2.erl
new file mode 100644
index 0000000000..ac0877da2f
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_v2.erl
@@ -0,0 +1,413 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_v2).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v2.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+%% token_tag2string(X) -> ?CompactEmergencyOffToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+%% token_tag2string(X) -> ?CompactNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(EmergencyOffToken , ?CompactEmergencyOffToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(Nx64kToken , ?CompactNx64kToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v2.hrl").
+
diff --git a/lib/megaco/src/text/megaco_compact_text_encoder_v3.erl b/lib/megaco/src/text/megaco_compact_text_encoder_v3.erl
new file mode 100644
index 0000000000..5dd239222b
--- /dev/null
+++ b/lib/megaco/src/text/megaco_compact_text_encoder_v3.erl
@@ -0,0 +1,455 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode COMPACT Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_compact_text_encoder_v3).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v3.hrl").
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+%% token_tag2string(X) -> ?CompactAndAUDITSelectToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(both) -> ?CompactBothToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+%% token_tag2string(X) -> ?CompactContextAttrToken;
+%% token_tag2string(X) -> ?CompactContextListToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDirectionToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+%% token_tag2string(X) -> ?CompactEmergencyOffToken;
+%% token_tag2string(X) -> ?CompactEmergencyValueToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+token_tag2string(external) -> ?CompactExternalToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+token_tag2string(iepsCallind) -> ?CompactIEPSToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(internal) -> ?CompactInternalToken;
+%% token_tag2string(X) -> ?CompactIntsigDelayToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(iteration) -> ?CompactIterationToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+%% token_tag2string(X) -> ?CompactNeverNotifyToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+%% token_tag2string(X) -> ?CompactNotifyImmediateToken;
+%% token_tag2string(X) -> ?CompactNotifyRegulatedToken;
+%% token_tag2string(X) -> ?CompactNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onewayboth) -> ?CompactOnewayBothToken;
+token_tag2string(onewayexternal) -> ?CompactOnewayExternalToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+%% token_tag2string(X) -> ?CompactOrAUDITselectToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+token_tag2string(resetEventsDescriptor) -> ?CompactResetEventsDescriptorToken;
+%% token_tag2string(X) -> ?CompactRequestIDToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?CompactServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?EqualToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?LbrktToken]).
+-define(RBRKT, [?RbrktToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), State).
+-define(INDENT(State), State).
+-define(LBRKT_INDENT(_State), [?LbrktToken]).
+-define(RBRKT_INDENT(_State), [?RbrktToken]).
+-define(LSBRKT_INDENT(_State), [?LsbrktToken]).
+-define(RSBRKT_INDENT(_State), [?RsbrktToken]).
+-define(COMMA_INDENT(_State), [?CommaToken]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?CompactAddToken).
+-define(AndAUDITSelectToken , ?CompactAndAUDITSelectToken).
+-define(AuditToken , ?CompactAuditToken).
+-define(AuditCapToken , ?CompactAuditCapToken).
+-define(AuditValueToken , ?CompactAuditValueToken).
+-define(AuthToken , ?CompactAuthToken).
+-define(BothToken , ?CompactBothToken).
+-define(BothwayToken , ?CompactBothwayToken).
+-define(BriefToken , ?CompactBriefToken).
+-define(BufferToken , ?CompactBufferToken).
+-define(CtxToken , ?CompactCtxToken).
+-define(ContextAuditToken , ?CompactContextAuditToken).
+-define(ContextAttrToken , ?CompactContextAttrToken).
+-define(ContextListToken , ?CompactContextListToken).
+-define(DigitMapToken , ?CompactDigitMapToken).
+-define(DirectionToken , ?CompactDirectionToken).
+-define(DiscardToken , ?CompactDiscardToken).
+-define(DisconnectedToken , ?CompactDisconnectedToken).
+-define(DelayToken , ?CompactDelayToken).
+-define(DeleteToken , ?CompactDeleteToken).
+-define(DurationToken , ?CompactDurationToken).
+-define(EmbedToken , ?CompactEmbedToken).
+-define(EmergencyToken , ?CompactEmergencyToken).
+-define(EmergencyOffToken , ?CompactEmergencyOffToken).
+-define(EmergencyValueToken , ?CompactEmergencyValueToken).
+-define(ErrorToken , ?CompactErrorToken).
+-define(EventBufferToken , ?CompactEventBufferToken).
+-define(EventsToken , ?CompactEventsToken).
+-define(ExternalToken , ?CompactExternalToken).
+-define(FailoverToken , ?CompactFailoverToken).
+-define(ForcedToken , ?CompactForcedToken).
+-define(GracefulToken , ?CompactGracefulToken).
+-define(H221Token , ?CompactH221Token).
+-define(H223Token , ?CompactH223Token).
+-define(H226Token , ?CompactH226Token).
+-define(HandOffToken , ?CompactHandOffToken).
+-define(IEPSToken , ?CompactIEPSToken).
+-define(ImmAckRequiredToken , ?CompactImmAckRequiredToken).
+-define(InactiveToken , ?CompactInactiveToken).
+-define(InternalToken , ?CompactInternalToken).
+-define(IntsigDelayToken , ?CompactIntsigDelayToken).
+-define(IsolateToken , ?CompactIsolateToken).
+-define(InSvcToken , ?CompactInSvcToken).
+-define(InterruptByEventToken , ?CompactInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?CompactInterruptByNewSignalsDescrToken).
+-define(IterationToken , ?CompactIterationToken).
+-define(KeepActiveToken , ?CompactKeepActiveToken).
+-define(LocalToken , ?CompactLocalToken).
+-define(LocalControlToken , ?CompactLocalControlToken).
+-define(LockStepToken , ?CompactLockStepToken).
+-define(LoopbackToken , ?CompactLoopbackToken).
+-define(MediaToken , ?CompactMediaToken).
+-define(MegacopToken , ?CompactMegacopToken).
+-define(MessageSegmentToken , ?CompactMessageSegmentToken).
+-define(MethodToken , ?CompactMethodToken).
+-define(MgcIdToken , ?CompactMgcIdToken).
+-define(ModeToken , ?CompactModeToken).
+-define(ModifyToken , ?CompactModifyToken).
+-define(ModemToken , ?CompactModemToken).
+-define(MoveToken , ?CompactMoveToken).
+-define(MtpToken , ?CompactMtpToken).
+-define(MuxToken , ?CompactMuxToken).
+-define(NeverNotifyToken , ?CompactNeverNotifyToken).
+-define(NotifyToken , ?CompactNotifyToken).
+-define(NotifyCompletionToken , ?CompactNotifyCompletionToken).
+-define(NotifyImmediateToken , ?CompactNotifyImmediateToken).
+-define(NotifyRegulatedToken , ?CompactNotifyRegulatedToken).
+-define(Nx64kToken , ?CompactNx64kToken).
+-define(ObservedEventsToken , ?CompactObservedEventsToken).
+-define(OffToken , ?CompactOffToken).
+-define(OnewayToken , ?CompactOnewayToken).
+-define(OnewayBothToken , ?CompactOnewayBothToken).
+-define(OnewayExternalToken , ?CompactOnewayExternalToken).
+-define(OnOffToken , ?CompactOnOffToken).
+-define(OnToken , ?CompactOnToken).
+-define(OrAUDITselectToken , ?CompactOrAUDITselectToken).
+-define(OtherReasonToken , ?CompactOtherReasonToken).
+-define(OutOfSvcToken , ?CompactOutOfSvcToken).
+-define(PackagesToken , ?CompactPackagesToken).
+-define(PendingToken , ?CompactPendingToken).
+-define(PriorityToken , ?CompactPriorityToken).
+-define(ProfileToken , ?CompactProfileToken).
+-define(ReasonToken , ?CompactReasonToken).
+-define(RecvonlyToken , ?CompactRecvonlyToken).
+-define(ReplyToken , ?CompactReplyToken).
+-define(ResetEventsDescriptorToken , ?CompactResetEventsDescriptorToken).
+-define(ResponseAckToken , ?CompactResponseAckToken).
+-define(RestartToken , ?CompactRestartToken).
+-define(RemoteToken , ?CompactRemoteToken).
+-define(RequestIDToken , ?CompactRequestIDToken).
+-define(ReservedGroupToken , ?CompactReservedGroupToken).
+-define(ReservedValueToken , ?CompactReservedValueToken).
+-define(SegmentationCompleteToken , ?CompactSegmentationCompleteToken).
+-define(SendonlyToken , ?CompactSendonlyToken).
+-define(SendrecvToken , ?CompactSendrecvToken).
+-define(ServicesToken , ?CompactServicesToken).
+-define(ServiceStatesToken , ?CompactServiceStatesToken).
+-define(ServiceChangeToken , ?CompactServiceChangeToken).
+-define(ServiceChangeAddressToken , ?CompactServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?CompactServiceChangeIncompleteToken).
+-define(SignalListToken , ?CompactSignalListToken).
+-define(SignalsToken , ?CompactSignalsToken).
+-define(SignalTypeToken , ?CompactSignalTypeToken).
+-define(StatsToken , ?CompactStatsToken).
+-define(StreamToken , ?CompactStreamToken).
+-define(SubtractToken , ?CompactSubtractToken).
+-define(SynchISDNToken , ?CompactSynchISDNToken).
+-define(TerminationStateToken , ?CompactTerminationStateToken).
+-define(TestToken , ?CompactTestToken).
+-define(TimeOutToken , ?CompactTimeOutToken).
+-define(TopologyToken , ?CompactTopologyToken).
+-define(TransToken , ?CompactTransToken).
+-define(V18Token , ?CompactV18Token).
+-define(V22Token , ?CompactV22Token).
+-define(V22bisToken , ?CompactV22bisToken).
+-define(V32Token , ?CompactV32Token).
+-define(V32bisToken , ?CompactV32bisToken).
+-define(V34Token , ?CompactV34Token).
+-define(V76Token , ?CompactV76Token).
+-define(V90Token , ?CompactV90Token).
+-define(V91Token , ?CompactV91Token).
+-define(VersionToken , ?CompactVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v3.hrl").
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder.erl b/lib/megaco/src/text/megaco_pretty_text_encoder.erl
new file mode 100644
index 0000000000..6a9a7df041
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder.erl
@@ -0,0 +1,613 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder).
+
+-behaviour(megaco_encoder).
+
+-export([encode_message/3, decode_message/3,
+ decode_mini_message/3,
+
+ version_of/2,
+
+ encode_transaction/3,
+ encode_action_requests/3,
+ encode_action_request/3,
+ encode_command_request/3,
+ encode_action_reply/3]).
+
+%% Backward compatible funcs:
+-export([encode_message/2, decode_message/2,
+
+ encode_transaction/1,
+ encode_command_request/1,
+ encode_action_reply/1]).
+
+%% Do we need these here?
+-export([trim_quoted_string/1,
+ term_to_compact_string/1,
+ term_to_pretty_string/1]).
+
+-export([token_tag2string/1, token_tag2string/2]).
+
+
+-include("megaco_text_tokens.hrl").
+-include_lib("megaco/src/engine/megaco_message_internal.hrl").
+
+-define(V1_PARSE_MOD, megaco_text_parser_v1).
+-define(V2_PARSE_MOD, megaco_text_parser_v2).
+-define(V3_PARSE_MOD, megaco_text_parser_v3).
+-define(PREV3A_PARSE_MOD, megaco_text_parser_prev3a).
+-define(PREV3B_PARSE_MOD, megaco_text_parser_prev3b).
+-define(PREV3C_PARSE_MOD, megaco_text_parser_prev3c).
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EncodingConfig,
+ #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) ->
+ encode_message(EncodingConfig, V, MegaMsg).
+
+
+encode_message([{version3,_}|EC], 1, MegaMsg) ->
+ megaco_pretty_text_encoder_v1:encode_message(EC, MegaMsg);
+encode_message(EC, 1, MegaMsg) ->
+ megaco_pretty_text_encoder_v1:encode_message(EC, MegaMsg);
+encode_message([{version3,_}|EC], 2, MegaMsg) ->
+ megaco_pretty_text_encoder_v2:encode_message(EC, MegaMsg);
+encode_message(EC, 2, MegaMsg) ->
+ megaco_pretty_text_encoder_v2:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3c}|EC], 3, MegaMsg) ->
+ megaco_pretty_text_encoder_prev3c:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3b}|EC], 3, MegaMsg) ->
+ megaco_pretty_text_encoder_prev3b:encode_message(EC, MegaMsg);
+encode_message([{version3,prev3a}|EC], 3, MegaMsg) ->
+ megaco_pretty_text_encoder_prev3a:encode_message(EC, MegaMsg);
+encode_message([{version3,v3}|EC], 3, MegaMsg) ->
+ megaco_pretty_text_encoder_v3:encode_message(EC, MegaMsg);
+encode_message(EC, 3, MegaMsg) ->
+ megaco_pretty_text_encoder_v3:encode_message(EC, MegaMsg);
+encode_message(_EC, V, _MegaMsg) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%----------------------------------------------------------------------
+
+version_of(_EC, Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, _Tokens, V, _LastLine} ->
+ {ok, V};
+ {error, Reason, Line} ->
+ {error, {decode_failed, Reason, Line}}
+ end.
+
+
+decode_message(EC, Bin) ->
+ decode_message(EC, dynamic, Bin).
+
+decode_message([], _, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,v3}], _, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3c}], _, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} ->
+ scan_error(Reason, Line, Bin)
+ end;
+decode_message([{version3,prev3b}], _, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3a}], _, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ {error, Reason, Tokens, Line} ->
+ scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{flex, Port}], _, Bin) when is_binary(Bin) ->
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,v3},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?V3_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3c},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3C_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3b},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3B_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message([{version3,prev3a},{flex, Port}], _, Bin) when is_binary(Bin) ->
+ case megaco_flex_scanner:scan(Bin, Port) of
+ {ok, Tokens, 1, _LastLine} ->
+ do_decode_message(?V1_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 2, _LastLine} ->
+ do_decode_message(?V2_PARSE_MOD, Tokens, Bin);
+
+ {ok, Tokens, 3, _LastLine} ->
+ do_decode_message(?PREV3A_PARSE_MOD, Tokens, Bin);
+
+ {ok, _Tokens, V, _LastLine} ->
+ {error, {unsupported_version, V}};
+
+ %% {error, Reason, Tokens, Line} ->
+ %% scan_error(Reason, Line, Tokens, Bin);
+
+ {error, Reason, Line} -> %% OTP-4007
+ scan_error(Reason, Line, Bin) %% OTP-4007
+ end;
+decode_message(EC, _, Bin) when is_binary(Bin) ->
+ {error, {bad_encoding_config, EC}};
+decode_message(_EC, _, _BadBin) ->
+ {error, bad_binary}.
+
+
+do_decode_message(ParseMod, Tokens, Bin) ->
+ case (catch ParseMod:parse(Tokens)) of
+ {ok, MegacoMessage} ->
+ {ok, MegacoMessage};
+ {error, Reason} ->
+ parse_error(Reason, Tokens, Bin);
+
+ %% OTP-4007
+ {'EXIT', Reason} ->
+ parse_error(Reason, Tokens, Bin)
+ end.
+
+
+decode_mini_message(EC, _, Bin) when is_binary(Bin) ->
+ megaco_text_mini_decoder:decode_message(EC, Bin).
+
+
+scan_error(Reason, Line, Bin) ->
+ scan_error(Reason, Line, [], Bin).
+
+scan_error("bad_property_parm: " ++ Reason, _Line, _Tokens, _Bin) ->
+ {error, {bad_property_parm, Reason}};
+scan_error(Reason, Line, Tokens, Bin) ->
+ %% io:format("scanner error: "
+ %% "~n Reason: ~p"
+ %% "~n Line: ~p"
+ %% "~n Tokens: ~p"
+ %% "~n Bin: ~p"
+ %% "~n", [Reason, Line, Tokens, Bin]),
+ {error, [{reason, Reason, Line}, {token, Tokens}, {chars, Bin}]}.
+
+parse_error(Reason, Tokens, Chars) ->
+%% io:format("parse_error -> entry with"
+%% "~n Reason: ~p"
+%% "~n Tokens: ~p"
+%% "~n Chars: ~p"
+%% "~n", [Reason, Tokens, Chars]),
+ case Reason of
+ {Line, Mod, [Prefix, [$[, TokenStringRaw, $]]]} when
+ is_integer(Line) andalso
+ is_atom(Mod) andalso
+ is_list(Prefix) andalso
+ is_list(TokenStringRaw) ->
+ TokenString = [l2i(X) || X <- TokenStringRaw, is_list(X)],
+ ReasonStr = Prefix ++ TokenString,
+ {error, [{reason, ReasonStr, Line}, {tokens, Tokens}, {chars, Chars}, {module, Mod}]};
+ _ ->
+ {error, [{reason, Reason}, {token, Tokens}, {chars, Chars}]}
+ end.
+
+
+l2i(L) when is_list(L) ->
+ case (catch list_to_integer(L)) of
+ I when is_integer(I) ->
+ I;
+ _ ->
+ L
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a binary
+%% Return {ok, Bin} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(Trans) ->
+ encode_transaction([], 1, Trans).
+
+encode_transaction([{version3,_}|EC], 1, Trans) ->
+ megaco_pretty_text_encoder_v1:encode_transaction(EC, Trans);
+encode_transaction(EC, 1, Trans) ->
+ megaco_pretty_text_encoder_v1:encode_transaction(EC, Trans);
+encode_transaction([{version3,_}|EC], 2, Trans) ->
+ megaco_pretty_text_encoder_v2:encode_transaction(EC, Trans);
+encode_transaction(EC, 2, Trans) ->
+ megaco_pretty_text_encoder_v2:encode_transaction(EC, Trans);
+encode_transaction([{version3,v3}|EC], 3, Trans) ->
+ megaco_pretty_text_encoder_v3:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3c}|EC], 3, Trans) ->
+ megaco_pretty_text_encoder_prev3c:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3b}|EC], 3, Trans) ->
+ megaco_pretty_text_encoder_prev3b:encode_transaction(EC, Trans);
+encode_transaction([{version3,prev3a}|EC], 3, Trans) ->
+ megaco_pretty_text_encoder_prev3a:encode_transaction(EC, Trans);
+encode_transaction(EC, 3, Trans) ->
+ megaco_pretty_text_encoder_v3:encode_transaction(EC, Trans);
+encode_transaction(_EC, V, _Trans) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests([{version3,_}|EC], 1, ActReqs) when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v1:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 1, ActReqs) when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v1:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,_}|EC], 2, ActReqs) when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v2:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 2, ActReqs) when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v2:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,v3}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v3:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3c}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_prev3c:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3b}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_prev3b:encode_action_requests(EC, ActReqs);
+encode_action_requests([{version3,prev3a}|EC], 3, ActReqs)
+ when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_prev3a:encode_action_requests(EC, ActReqs);
+encode_action_requests(EC, 3, ActReqs) when is_list(ActReqs) ->
+ megaco_pretty_text_encoder_v3:encode_action_requests(EC, ActReqs);
+encode_action_requests(_EC, V, _ActReqs) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request([{version3,_}|EC], 1, ActReq) ->
+ megaco_pretty_text_encoder_v1:encode_action_request(EC, ActReq);
+encode_action_request(EC, 1, ActReq) ->
+ megaco_pretty_text_encoder_v1:encode_action_request(EC, ActReq);
+encode_action_request([{version3,_}|EC], 2, ActReq) ->
+ megaco_pretty_text_encoder_v2:encode_action_request(EC, ActReq);
+encode_action_request(EC, 2, ActReq) ->
+ megaco_pretty_text_encoder_v2:encode_action_request(EC, ActReq);
+encode_action_request([{version3,v3}|EC], 3, ActReq) ->
+ megaco_pretty_text_encoder_v3:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3c}|EC], 3, ActReq) ->
+ megaco_pretty_text_encoder_prev3c:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3b}|EC], 3, ActReq) ->
+ megaco_pretty_text_encoder_prev3b:encode_action_request(EC, ActReq);
+encode_action_request([{version3,prev3a}|EC], 3, ActReq) ->
+ megaco_pretty_text_encoder_prev3a:encode_action_request(EC, ActReq);
+encode_action_request(EC, 3, ActReq) ->
+ megaco_pretty_text_encoder_v3:encode_action_request(EC, ActReq);
+encode_action_request(_EC, V, _ActReq) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(CmdReq) ->
+ encode_command_request([], 1, CmdReq).
+
+encode_command_request([{version3,_}|EC], 1, CmdReq) ->
+ megaco_pretty_text_encoder_v1:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 1, CmdReq) ->
+ megaco_pretty_text_encoder_v1:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,_}|EC], 2, CmdReq) ->
+ megaco_pretty_text_encoder_v2:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 2, CmdReq) ->
+ megaco_pretty_text_encoder_v2:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,v3}|EC], 3, CmdReq) ->
+ megaco_pretty_text_encoder_v3:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3c}|EC], 3, CmdReq) ->
+ megaco_pretty_text_encoder_prev3c:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3b}|EC], 3, CmdReq) ->
+ megaco_pretty_text_encoder_prev3b:encode_command_request(EC, CmdReq);
+encode_command_request([{version3,prev3a}|EC], 3, CmdReq) ->
+ megaco_pretty_text_encoder_prev3a:encode_command_request(EC, CmdReq);
+encode_command_request(EC, 3, CmdReq) ->
+ megaco_pretty_text_encoder_v3:encode_command_request(EC, CmdReq);
+encode_command_request(_EC, V, _CmdReq) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(ActRep) ->
+%% io:format("~p:encode_action_reply -> entry with"
+%% "~n ActRep: ~p"
+%% "~n", [?MODULE, ActRep]),
+ encode_action_reply([], 1, ActRep).
+
+encode_action_reply([{version3,_}|EC], 1, ActRep) ->
+ megaco_pretty_text_encoder_v1:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 1, ActRep) ->
+ megaco_pretty_text_encoder_v1:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,_}|EC], 2, ActRep) ->
+ megaco_pretty_text_encoder_v2:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 2, ActRep) ->
+ megaco_pretty_text_encoder_v2:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,v3}|EC], 3, ActRep) ->
+ megaco_pretty_text_encoder_v3:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3c}|EC], 3, ActRep) ->
+ megaco_pretty_text_encoder_prev3c:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3b}|EC], 3, ActRep) ->
+ megaco_pretty_text_encoder_prev3b:encode_action_reply(EC, ActRep);
+encode_action_reply([{version3,prev3a}|EC], 3, ActRep) ->
+ megaco_pretty_text_encoder_prev3a:encode_action_reply(EC, ActRep);
+encode_action_reply(EC, 3, ActRep) ->
+ megaco_pretty_text_encoder_v3:encode_action_reply(EC, ActRep);
+encode_action_reply(_EC, V, _ActRep) ->
+ {error, {bad_version, V}}.
+
+
+%%----------------------------------------------------------------------
+term_to_compact_string(Term) ->
+ case catch io_lib:format("~s", [Term]) of
+ {'EXIT', _} -> lists:flatten(io_lib:format("~w", [Term]));
+ GoodString -> lists:flatten(GoodString)
+ end.
+
+%%----------------------------------------------------------------------
+term_to_pretty_string(Term) ->
+ case catch io_lib:format("~s", [Term]) of
+ {'EXIT', _} -> lists:flatten(io_lib:format("~p", [Term]));
+ GoodString -> lists:flatten(GoodString)
+ end.
+
+%%----------------------------------------------------------------------
+trim_quoted_string([H | T]) ->
+ case ?classify_char(H) of
+ safe_char -> [H | trim_quoted_string(T)];
+ rest_char -> [H | trim_quoted_string(T)];
+ white_space -> [H | trim_quoted_string(T)];
+ _BadChar -> [$? | trim_quoted_string(T)]
+ end;
+trim_quoted_string([]) ->
+ [].
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+-define(TT2S_BEST_VERSION, v3).
+
+token_tag2string(Tag) ->
+ token_tag2string(Tag, ?TT2S_BEST_VERSION).
+
+token_tag2string(Tag, 1) ->
+ token_tag2string(Tag, v1);
+token_tag2string(Tag, v1) ->
+ megaco_pretty_text_encoder_v1:token_tag2string(Tag);
+token_tag2string(Tag, 2) ->
+ token_tag2string(Tag, v2);
+token_tag2string(Tag, v2) ->
+ megaco_pretty_text_encoder_v2:token_tag2string(Tag);
+token_tag2string(Tag, 3) ->
+ token_tag2string(Tag, v3);
+token_tag2string(Tag, v3) ->
+ megaco_pretty_text_encoder_v3:token_tag2string(Tag);
+token_tag2string(Tag, prev3b) ->
+ megaco_pretty_text_encoder_prev3b:token_tag2string(Tag);
+token_tag2string(Tag, prev3c) ->
+ megaco_pretty_text_encoder_prev3c:token_tag2string(Tag);
+token_tag2string(Tag, _Vsn) ->
+ token_tag2string(Tag, ?TT2S_BEST_VERSION).
+
+
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% %% d(get(dbg), F, A).
+%% d(true, F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE|A]);
+%% d(_, _, _) ->
+%% ok.
+
+%% p(F, A) ->
+%% io:format("*** [~s] ***"
+%% "~n " ++ F ++ "~n", [formated_timestamp() | A]),
+%% sleep(5000),
+%% ok.
+
+%% sleep(X) -> receive after X -> ok end.
+
+%% formated_timestamp() ->
+%% format_timestamp(now()).
+
+%% format_timestamp({_N1, _N2, N3} = Now) ->
+%% {Date, Time} = calendar:now_to_datetime(Now),
+%% {YYYY,MM,DD} = Date,
+%% {Hour,Min,Sec} = Time,
+%% FormatDate =
+%% io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
+%% [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
+%% lists:flatten(FormatDate).
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_prev3a.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3a.erl
new file mode 100644
index 0000000000..6f42bf963c
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3a.erl
@@ -0,0 +1,303 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_prev3a).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3a.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%
+%% See megaco_pretty_text_encoder:decode_message/2
+%%
+%%----------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?SpToken, ?LsbrktToken, ?SpToken]).
+-define(RSBRKT, [?SpToken, ?RsbrktToken, ?SpToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(LSBRKT_INDENT(State), [?SpToken, ?LsbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RSBRKT_INDENT(State), [?INDENT(State), ?RsbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothToken , ?PrettyBothToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(ContextAttrToken , ?PrettyContextAttrToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DirectionToken , ?PrettyDirectionToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(EmergencyOffToken , ?PrettyEmergencyOffToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(ExternalToken , ?PrettyExternalToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(IEPSToken , ?PrettyIEPSToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(InternalToken , ?PrettyInternalToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(RequestIDToken , ?PrettyRequestIDToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?PrettyServiceChangeIncompleteToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3a.hrl").
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_prev3b.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3b.erl
new file mode 100644
index 0000000000..44bdc4690d
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3b.erl
@@ -0,0 +1,437 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_prev3b).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3b.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%
+%% See megaco_pretty_text_encoder:decode_message/2
+%%
+%%----------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?PrettyAddToken;
+token_tag2string(addReply) -> ?PrettyAddToken;
+token_tag2string(auditDescriptor) -> ?PrettyAuditToken;
+token_tag2string(auditCapRequest) -> ?PrettyAuditCapToken;
+token_tag2string(auditCapReply) -> ?PrettyAuditCapToken;
+token_tag2string(auditValueRequest) -> ?PrettyAuditValueToken;
+token_tag2string(auditValueReply) -> ?PrettyAuditValueToken;
+%% token_tag2string(X) -> ?PrettyAuthToken;
+token_tag2string(both) -> ?PrettyBothToken;
+token_tag2string(bothway) -> ?PrettyBothwayToken;
+token_tag2string(brief) -> ?PrettyBriefToken;
+%% token_tag2string(X) -> ?PrettyBufferToken;
+%% token_tag2string(X) -> ?PrettyCtxToken;
+%% token_tag2string(X) -> ?PrettyContextAttrToken;
+%% token_tag2string(X) -> ?PrettyContextAuditToken;
+%% token_tag2string(X) -> ?PrettyContextListToken;
+token_tag2string(digitMapDescriptor) -> ?PrettyDigitMapToken;
+token_tag2string(digitMapToken) -> ?PrettyDigitMapToken;
+%% token_tag2string(X) -> ?PrettyDirectionToken;
+%% token_tag2string(X) -> ?PrettyDiscardToken;
+%% token_tag2string(X) -> ?PrettyDisconnectedToken;
+%% token_tag2string(X) -> ?PrettyDelayToken;
+token_tag2string(duration) -> ?PrettyDurationToken;
+%% token_tag2string(X) -> ?PrettyEmbedToken;
+token_tag2string(emergencyAudit) -> ?PrettyEmergencyToken;
+%% token_tag2string(X) -> ?PrettyEmergencyOffToken;
+token_tag2string(errorDescriptor) -> ?PrettyErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?PrettyEventBufferToken;
+token_tag2string(eventBufferToken) -> ?PrettyEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?PrettyEventsToken;
+token_tag2string(eventsToken) -> ?PrettyEventsToken;
+token_tag2string(external) -> ?PrettyExternalToken;
+%% token_tag2string(X) -> ?PrettyFailoverToken;
+%% token_tag2string(X) -> ?PrettyForcedToken;
+%% token_tag2string(X) -> ?PrettyGracefulToken;
+%% token_tag2string(X) -> ?PrettyH221Token;
+%% token_tag2string(X) -> ?PrettyH223Token;
+%% token_tag2string(X) -> ?PrettyH226Token;
+%% token_tag2string(X) -> ?PrettyHandOffToken;
+token_tag2string(iepsCallind) -> ?PrettyIEPSToken;
+%% token_tag2string(X) -> ?PrettyImmAckRequiredToken;
+token_tag2string(inactive) -> ?PrettyInactiveToken;
+token_tag2string(internal) -> ?PrettyInternalToken;
+token_tag2string(onInterruptByEvent) -> ?PrettyInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?PrettyInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?PrettyIsolateToken;
+token_tag2string(inSvc) -> ?PrettyInSvcToken;
+token_tag2string(keepActive) -> ?PrettyKeepActiveToken;
+token_tag2string(localDescriptor) -> ?PrettyLocalToken;
+token_tag2string(localControlDescriptor) -> ?PrettyLocalControlToken;
+token_tag2string(lockStep) -> ?PrettyLockStepToken;
+token_tag2string(loopBack) -> ?PrettyLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?PrettyMediaToken;
+token_tag2string(mediaToken) -> ?PrettyMediaToken;
+%% token_tag2string(X) -> ?PrettyMegacopToken;
+%% token_tag2string(X) -> ?PrettyMethodToken;
+%% token_tag2string(X) -> ?PrettyMgcIdToken;
+%% token_tag2string(X) -> ?PrettyModeToken;
+token_tag2string(modReq) -> ?PrettyModifyToken;
+token_tag2string(modReply) -> ?PrettyModifyToken;
+token_tag2string(modemDescriptor) -> ?PrettyModemToken;
+token_tag2string(modemToken) -> ?PrettyModemToken;
+token_tag2string(moveReq) -> ?PrettyMoveToken;
+token_tag2string(moveReply) -> ?PrettyMoveToken;
+%% token_tag2string(X) -> ?PrettyMtpToken;
+token_tag2string(muxDescriptor) -> ?PrettyMuxToken;
+token_tag2string(muxToken) -> ?PrettyMuxToken;
+token_tag2string(notifyReq) -> ?PrettyNotifyToken;
+%% token_tag2string(X) -> ?PrettyNotifyCompletionToken;
+%% token_tag2string(X) -> ?PrettyNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?PrettyObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?PrettyObservedEventsToken;
+token_tag2string(false) -> ?PrettyOffToken;
+token_tag2string(off) -> ?PrettyOffToken;
+token_tag2string(oneway) -> ?PrettyOnewayToken;
+token_tag2string(onOff) -> ?PrettyOnOffToken;
+token_tag2string(true) -> ?PrettyOnToken;
+token_tag2string(otherReason) -> ?PrettyOtherReasonToken;
+token_tag2string(outOfSvc) -> ?PrettyOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?PrettyPackagesToken;
+token_tag2string(packagesToken) -> ?PrettyPackagesToken;
+%% token_tag2string(X) -> ?PrettyPendingToken;
+token_tag2string(priorityAudit) -> ?PrettyPriorityToken;
+%% token_tag2string(X) -> ?PrettyProfileToken;
+%% token_tag2string(X) -> ?PrettyReasonToken;
+token_tag2string(recvOnly) -> ?PrettyRecvonlyToken;
+%% token_tag2string(X) -> ?PrettyReplyToken;
+%% token_tag2string(X) -> ?PrettyRequestIDToken;
+%% token_tag2string(X) -> ?PrettyResponseAckToken;
+%% token_tag2string(X) -> ?PrettyRestartToken;
+token_tag2string(remoteDescriptor) -> ?PrettyRemoteToken;
+%% token_tag2string(X) -> ?PrettyReservedGroupToken;
+%% token_tag2string(X) -> ?PrettyReservedValueToken;
+token_tag2string(sendOnly) -> ?PrettySendonlyToken;
+token_tag2string(sendRecv) -> ?PrettySendrecvToken;
+%% token_tag2string(X) -> ?PrettyServicesToken;
+%% token_tag2string(X) -> ?PrettyServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?PrettyServiceChangeToken;
+%% token_tag2string(X) -> ?PrettyServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?PrettyServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?PrettySignalListToken;
+token_tag2string(signalsDescriptor) -> ?PrettySignalsToken;
+token_tag2string(signalsToken) -> ?PrettySignalsToken;
+%% token_tag2string(X) -> ?PrettySignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?PrettyStatsToken;
+token_tag2string(statsToken) -> ?PrettyStatsToken;
+%% token_tag2string(X) -> ?PrettyStreamToken;
+token_tag2string(subtractReq) -> ?PrettySubtractToken;
+token_tag2string(subtractReply) -> ?PrettySubtractToken;
+%% token_tag2string(X) -> ?PrettySynchISDNToken;
+%% token_tag2string(X) -> ?PrettyTerminationStateToken;
+token_tag2string(test) -> ?PrettyTestToken;
+token_tag2string(timeOut) -> ?PrettyTimeOutToken;
+token_tag2string(onTimeOut) -> ?PrettyTimeOutToken;
+token_tag2string(topologyAudit) -> ?PrettyTopologyToken;
+%% token_tag2string(X) -> ?PrettyTransToken;
+%% token_tag2string(X) -> ?PrettyV18Token;
+%% token_tag2string(X) -> ?PrettyV22Token;
+%% token_tag2string(X) -> ?PrettyV22bisToken;
+%% token_tag2string(X) -> ?PrettyV32Token;
+%% token_tag2string(X) -> ?PrettyV32bisToken;
+%% token_tag2string(X) -> ?PrettyV34Token;
+%% token_tag2string(X) -> ?PrettyV76Token;
+%% token_tag2string(X) -> ?PrettyV90Token;
+%% token_tag2string(X) -> ?PrettyV91Token;
+%% token_tag2string(X) -> ?PrettyVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?SpToken, ?LsbrktToken, ?SpToken]).
+-define(RSBRKT, [?SpToken, ?RsbrktToken, ?SpToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(LSBRKT_INDENT(State), [?SpToken, ?LsbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RSBRKT_INDENT(State), [?INDENT(State), ?RsbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothToken , ?PrettyBothToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(ContextAttrToken , ?PrettyContextAttrToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DirectionToken , ?PrettyDirectionToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(EmergencyOffToken , ?PrettyEmergencyOffToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(ExternalToken , ?PrettyExternalToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(IEPSToken , ?PrettyIEPSToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(InternalToken , ?PrettyInternalToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(RequestIDToken , ?PrettyRequestIDToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?PrettyServiceChangeIncompleteToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3b.hrl").
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_prev3c.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3c.erl
new file mode 100644
index 0000000000..1511056f00
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_prev3c.erl
@@ -0,0 +1,483 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_prev3c).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-export([test/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3c.hrl").
+-include("megaco_text_tokens.hrl").
+
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%
+%% See megaco_pretty_text_encoder:decode_message/2
+%%
+%%----------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?PrettyAddToken;
+token_tag2string(addReply) -> ?PrettyAddToken;
+%% token_tag2string(X) -> ?PrettyAndAUDITSelectToken;
+token_tag2string(auditDescriptor) -> ?PrettyAuditToken;
+token_tag2string(auditCapRequest) -> ?PrettyAuditCapToken;
+token_tag2string(auditCapReply) -> ?PrettyAuditCapToken;
+token_tag2string(auditValueRequest) -> ?PrettyAuditValueToken;
+token_tag2string(auditValueReply) -> ?PrettyAuditValueToken;
+%% token_tag2string(X) -> ?PrettyAuthToken;
+token_tag2string(both) -> ?PrettyBothToken;
+token_tag2string(bothway) -> ?PrettyBothwayToken;
+token_tag2string(brief) -> ?PrettyBriefToken;
+%% token_tag2string(X) -> ?PrettyBufferToken;
+%% token_tag2string(X) -> ?PrettyCtxToken;
+%% token_tag2string(X) -> ?PrettyContextAuditToken;
+%% token_tag2string(X) -> ?PrettyContextAttrToken;
+%% token_tag2string(X) -> ?PrettyContextListToken;
+token_tag2string(digitMapDescriptor) -> ?PrettyDigitMapToken;
+token_tag2string(digitMapToken) -> ?PrettyDigitMapToken;
+%% token_tag2string(X) -> ?PrettyDirectionToken;
+%% token_tag2string(X) -> ?PrettyDiscardToken;
+%% token_tag2string(X) -> ?PrettyDisconnectedToken;
+%% token_tag2string(X) -> ?PrettyDelayToken;
+token_tag2string(duration) -> ?PrettyDurationToken;
+%% token_tag2string(X) -> ?PrettyEmbedToken;
+token_tag2string(emergencyAudit) -> ?PrettyEmergencyToken;
+%% token_tag2string(X) -> ?PrettyEmergencyOffToken;
+%% token_tag2string(X) -> ?PrettyEmergencyValueToken;
+token_tag2string(errorDescriptor) -> ?PrettyErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?PrettyEventBufferToken;
+token_tag2string(eventBufferToken) -> ?PrettyEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?PrettyEventsToken;
+token_tag2string(eventsToken) -> ?PrettyEventsToken;
+token_tag2string(external) -> ?PrettyExternalToken;
+%% token_tag2string(X) -> ?PrettyFailoverToken;
+%% token_tag2string(X) -> ?PrettyForcedToken;
+%% token_tag2string(X) -> ?PrettyGracefulToken;
+%% token_tag2string(X) -> ?PrettyH221Token;
+%% token_tag2string(X) -> ?PrettyH223Token;
+%% token_tag2string(X) -> ?PrettyH226Token;
+%% token_tag2string(X) -> ?PrettyHandOffToken;
+token_tag2string(iepsCallind) -> ?PrettyIEPSToken;
+%% token_tag2string(X) -> ?PrettyImmAckRequiredToken;
+token_tag2string(inactive) -> ?PrettyInactiveToken;
+token_tag2string(internal) -> ?PrettyInternalToken;
+%% token_tag2string(X) -> ?PrettyIntsigDelayToken;
+token_tag2string(onInterruptByEvent) -> ?PrettyInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?PrettyInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?PrettyIsolateToken;
+token_tag2string(inSvc) -> ?PrettyInSvcToken;
+token_tag2string(iteration) -> ?PrettyIterationToken;
+token_tag2string(keepActive) -> ?PrettyKeepActiveToken;
+token_tag2string(localDescriptor) -> ?PrettyLocalToken;
+token_tag2string(localControlDescriptor) -> ?PrettyLocalControlToken;
+token_tag2string(lockStep) -> ?PrettyLockStepToken;
+token_tag2string(loopBack) -> ?PrettyLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?PrettyMediaToken;
+token_tag2string(mediaToken) -> ?PrettyMediaToken;
+%% token_tag2string(X) -> ?PrettyMegacopToken;
+%% token_tag2string(X) -> ?PrettyMethodToken;
+%% token_tag2string(X) -> ?PrettyMgcIdToken;
+%% token_tag2string(X) -> ?PrettyModeToken;
+token_tag2string(modReq) -> ?PrettyModifyToken;
+token_tag2string(modReply) -> ?PrettyModifyToken;
+token_tag2string(modemDescriptor) -> ?PrettyModemToken;
+token_tag2string(modemToken) -> ?PrettyModemToken;
+token_tag2string(moveReq) -> ?PrettyMoveToken;
+token_tag2string(moveReply) -> ?PrettyMoveToken;
+%% token_tag2string(X) -> ?PrettyMtpToken;
+token_tag2string(muxDescriptor) -> ?PrettyMuxToken;
+token_tag2string(muxToken) -> ?PrettyMuxToken;
+%% token_tag2string(X) -> ?PrettyNeverNotifyToken;
+token_tag2string(notifyReq) -> ?PrettyNotifyToken;
+%% token_tag2string(X) -> ?PrettyNotifyCompletionToken;
+%% token_tag2string(X) -> ?PrettyNotifyImmediateToken;
+%% token_tag2string(X) -> ?PrettyNotifyRegulatedToken;
+%% token_tag2string(X) -> ?PrettyNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?PrettyObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?PrettyObservedEventsToken;
+token_tag2string(false) -> ?PrettyOffToken;
+token_tag2string(off) -> ?PrettyOffToken;
+token_tag2string(oneway) -> ?PrettyOnewayToken;
+token_tag2string(onewayboth) -> ?PrettyOnewayBothToken;
+token_tag2string(onewayexternal) -> ?PrettyOnewayExternalToken;
+token_tag2string(onOff) -> ?PrettyOnOffToken;
+%% token_tag2string(X) -> ?PrettyOrAUDITselectToken;
+token_tag2string(true) -> ?PrettyOnToken;
+token_tag2string(otherReason) -> ?PrettyOtherReasonToken;
+token_tag2string(outOfSvc) -> ?PrettyOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?PrettyPackagesToken;
+token_tag2string(packagesToken) -> ?PrettyPackagesToken;
+%% token_tag2string(X) -> ?PrettyPendingToken;
+token_tag2string(priorityAudit) -> ?PrettyPriorityToken;
+%% token_tag2string(X) -> ?PrettyProfileToken;
+%% token_tag2string(X) -> ?PrettyReasonToken;
+token_tag2string(recvOnly) -> ?PrettyRecvonlyToken;
+%% token_tag2string(X) -> ?PrettyReplyToken;
+token_tag2string(resetEventsDescriptor) -> ?PrettyResetEventsDescriptorToken;
+%% token_tag2string(X) -> ?PrettyRequestIDToken;
+%% token_tag2string(X) -> ?PrettyResponseAckToken;
+%% token_tag2string(X) -> ?PrettyRestartToken;
+token_tag2string(remoteDescriptor) -> ?PrettyRemoteToken;
+%% token_tag2string(X) -> ?PrettyReservedGroupToken;
+%% token_tag2string(X) -> ?PrettyReservedValueToken;
+token_tag2string(sendOnly) -> ?PrettySendonlyToken;
+token_tag2string(sendRecv) -> ?PrettySendrecvToken;
+%% token_tag2string(X) -> ?PrettyServicesToken;
+%% token_tag2string(X) -> ?PrettyServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?PrettyServiceChangeToken;
+%% token_tag2string(X) -> ?PrettyServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?PrettyServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?PrettySignalListToken;
+token_tag2string(signalsDescriptor) -> ?PrettySignalsToken;
+token_tag2string(signalsToken) -> ?PrettySignalsToken;
+%% token_tag2string(X) -> ?PrettySignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?PrettyStatsToken;
+token_tag2string(statsToken) -> ?PrettyStatsToken;
+%% token_tag2string(X) -> ?PrettyStreamToken;
+token_tag2string(subtractReq) -> ?PrettySubtractToken;
+token_tag2string(subtractReply) -> ?PrettySubtractToken;
+%% token_tag2string(X) -> ?PrettySynchISDNToken;
+%% token_tag2string(X) -> ?PrettyTerminationStateToken;
+token_tag2string(test) -> ?PrettyTestToken;
+token_tag2string(timeOut) -> ?PrettyTimeOutToken;
+token_tag2string(onTimeOut) -> ?PrettyTimeOutToken;
+token_tag2string(topologyAudit) -> ?PrettyTopologyToken;
+%% token_tag2string(X) -> ?PrettyTransToken;
+%% token_tag2string(X) -> ?PrettyV18Token;
+%% token_tag2string(X) -> ?PrettyV22Token;
+%% token_tag2string(X) -> ?PrettyV22bisToken;
+%% token_tag2string(X) -> ?PrettyV32Token;
+%% token_tag2string(X) -> ?PrettyV32bisToken;
+%% token_tag2string(X) -> ?PrettyV34Token;
+%% token_tag2string(X) -> ?PrettyV76Token;
+%% token_tag2string(X) -> ?PrettyV90Token;
+%% token_tag2string(X) -> ?PrettyV91Token;
+%% token_tag2string(X) -> ?PrettyVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?SpToken, ?LsbrktToken, ?SpToken]).
+-define(RSBRKT, [?SpToken, ?RsbrktToken, ?SpToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(LSBRKT_INDENT(State), [?SpToken, ?LsbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RSBRKT_INDENT(State), [?INDENT(State), ?RsbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AndAUDITSelectToken , ?PrettytAndAUDITSelectToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothToken , ?PrettyBothToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(ContextAttrToken , ?PrettyContextAttrToken).
+-define(ContextListToken , ?PrettyContextListToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DirectionToken , ?PrettyDirectionToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(EmergencyOffToken , ?PrettyEmergencyOffToken).
+-define(EmergencyValueToken , ?PrettyEmergencyValueToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(ExternalToken , ?PrettyExternalToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(IEPSToken , ?PrettyIEPSToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(InternalToken , ?PrettyInternalToken).
+-define(IntsigDelayToken , ?PrettyIntsigDelayToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(IterationToken , ?PrettyIterationToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+%% -define(MessageSegmentToken , ?PrettyMessageSegmentToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NeverNotifyToken , ?PrettyNeverNotifyToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(NotifyImmediateToken , ?PrettyNotifyImmediateToken).
+-define(NotifyRegulatedToken , ?PrettyNotifyRegulatedToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnewayBothToken , ?PrettyOnewayBothToken).
+-define(OnewayExternalToken , ?PrettyOnewayExternalToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OrAUDITselectToken , ?PrettyOrAUDITselectToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(ResetEventsDescriptorToken , ?PrettyResetEventsDescriptorToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(RequestIDToken , ?PrettyRequestIDToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+%% -define(SegmentationCompleteToken , ?PrettySegmentationCompleteToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?PrettyServiceChangeIncompleteToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_prev3c.hrl").
+
+%% start() ->
+%% Fun = fun() ->
+%% Val = lists:flatten([$", $e, $r, $i, $c, $s, $s, $o, $n, $"]),
+%% %% Val = [$e, $r, $i, $c, $s, $s, $o, $n],
+%% PP = {'PropertyParm',"ipdc/realm",[Val],asn1_NOVALUE},
+%% enc_PropertyParm(PP, [])
+%% end,
+%% test(Fun).
+
+%% start() ->
+%% Fun = fun() ->
+%% PP = {'PropertyParm',"ipdc/realm",["ericsson"],asn1_NOVALUE},
+%% enc_PropertyParm(PP, [])
+%% end,
+%% test(Fun).
+
+test(Fun) when is_function(Fun) ->
+ Fun().
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_v1.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_v1.erl
new file mode 100644
index 0000000000..6f65bc7337
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_v1.erl
@@ -0,0 +1,407 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_v1).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EC, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EC}};
+encode_message(_EC, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?PrettyAddToken;
+token_tag2string(addReply) -> ?PrettyAddToken;
+token_tag2string(auditDescriptor) -> ?PrettyAuditToken;
+token_tag2string(auditCapRequest) -> ?PrettyAuditCapToken;
+token_tag2string(auditCapReply) -> ?PrettyAuditCapToken;
+token_tag2string(auditValueRequest) -> ?PrettyAuditValueToken;
+token_tag2string(auditValueReply) -> ?PrettyAuditValueToken;
+%% token_tag2string(X) -> ?PrettyAuthToken;
+token_tag2string(bothway) -> ?PrettyBothwayToken;
+token_tag2string(brief) -> ?PrettyBriefToken;
+%% token_tag2string(X) -> ?PrettyBufferToken;
+%% token_tag2string(X) -> ?PrettyCtxToken;
+%% token_tag2string(X) -> ?PrettyContextAuditToken;
+token_tag2string(digitMapDescriptor) -> ?PrettyDigitMapToken;
+token_tag2string(digitMapToken) -> ?PrettyDigitMapToken;
+%% token_tag2string(X) -> ?PrettyDiscardToken;
+%% token_tag2string(X) -> ?PrettyDisconnectedToken;
+%% token_tag2string(X) -> ?PrettyDelayToken;
+token_tag2string(duration) -> ?PrettyDurationToken;
+%% token_tag2string(X) -> ?PrettyEmbedToken;
+token_tag2string(emergencyAudit) -> ?PrettyEmergencyToken;
+token_tag2string(errorDescriptor) -> ?PrettyErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?PrettyEventBufferToken;
+token_tag2string(eventBufferToken) -> ?PrettyEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?PrettyEventsToken;
+token_tag2string(eventsToken) -> ?PrettyEventsToken;
+%% token_tag2string(X) -> ?PrettyFailoverToken;
+%% token_tag2string(X) -> ?PrettyForcedToken;
+%% token_tag2string(X) -> ?PrettyGracefulToken;
+%% token_tag2string(X) -> ?PrettyH221Token;
+%% token_tag2string(X) -> ?PrettyH223Token;
+%% token_tag2string(X) -> ?PrettyH226Token;
+%% token_tag2string(X) -> ?PrettyHandOffToken;
+%% token_tag2string(X) -> ?PrettyImmAckRequiredToken;
+token_tag2string(inactive) -> ?PrettyInactiveToken;
+token_tag2string(onInterruptByEvent) -> ?PrettyInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?PrettyInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?PrettyIsolateToken;
+token_tag2string(inSvc) -> ?PrettyInSvcToken;
+token_tag2string(keepActive) -> ?PrettyKeepActiveToken;
+token_tag2string(localDescriptor) -> ?PrettyLocalToken;
+token_tag2string(localControlDescriptor) -> ?PrettyLocalControlToken;
+token_tag2string(lockStep) -> ?PrettyLockStepToken;
+token_tag2string(loopBack) -> ?PrettyLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?PrettyMediaToken;
+token_tag2string(mediaToken) -> ?PrettyMediaToken;
+%% token_tag2string(X) -> ?PrettyMegacopToken;
+%% token_tag2string(X) -> ?PrettyMethodToken;
+%% token_tag2string(X) -> ?PrettyMgcIdToken;
+%% token_tag2string(X) -> ?PrettyModeToken;
+token_tag2string(modReq) -> ?PrettyModifyToken;
+token_tag2string(modReply) -> ?PrettyModifyToken;
+token_tag2string(modemDescriptor) -> ?PrettyModemToken;
+token_tag2string(modemToken) -> ?PrettyModemToken;
+token_tag2string(moveReq) -> ?PrettyMoveToken;
+token_tag2string(moveReply) -> ?PrettyMoveToken;
+%% token_tag2string(X) -> ?PrettyMtpToken;
+token_tag2string(muxDescriptor) -> ?PrettyMuxToken;
+token_tag2string(muxToken) -> ?PrettyMuxToken;
+token_tag2string(notifyReq) -> ?PrettyNotifyToken;
+%% token_tag2string(X) -> ?PrettyNotifyCompletionToken;
+token_tag2string(observedEventsDescriptor) -> ?PrettyObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?PrettyObservedEventsToken;
+token_tag2string(false) -> ?PrettyOffToken;
+token_tag2string(off) -> ?PrettyOffToken;
+token_tag2string(oneway) -> ?PrettyOnewayToken;
+token_tag2string(onOff) -> ?PrettyOnOffToken;
+token_tag2string(true) -> ?PrettyOnToken;
+token_tag2string(otherReason) -> ?PrettyOtherReasonToken;
+token_tag2string(outOfSvc) -> ?PrettyOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?PrettyPackagesToken;
+token_tag2string(packagesToken) -> ?PrettyPackagesToken;
+%% token_tag2string(X) -> ?PrettyPendingToken;
+token_tag2string(priorityAudit) -> ?PrettyPriorityToken;
+%% token_tag2string(X) -> ?PrettyProfileToken;
+%% token_tag2string(X) -> ?PrettyReasonToken;
+token_tag2string(recvOnly) -> ?PrettyRecvonlyToken;
+%% token_tag2string(X) -> ?PrettyReplyToken;
+%% token_tag2string(X) -> ?PrettyResponseAckToken;
+%% token_tag2string(X) -> ?PrettyRestartToken;
+token_tag2string(remoteDescriptor) -> ?PrettyRemoteToken;
+%% token_tag2string(X) -> ?PrettyReservedGroupToken;
+%% token_tag2string(X) -> ?PrettyReservedValueToken;
+token_tag2string(sendOnly) -> ?PrettySendonlyToken;
+token_tag2string(sendRecv) -> ?PrettySendrecvToken;
+%% token_tag2string(X) -> ?PrettyServicesToken;
+%% token_tag2string(X) -> ?PrettyServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?PrettyServiceChangeToken;
+%% token_tag2string(X) -> ?PrettyServiceChangeAddressToken;
+%% token_tag2string(X) -> ?PrettySignalListToken;
+token_tag2string(signalsDescriptor) -> ?PrettySignalsToken;
+token_tag2string(signalsToken) -> ?PrettySignalsToken;
+%% token_tag2string(X) -> ?PrettySignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?PrettyStatsToken;
+token_tag2string(statsToken) -> ?PrettyStatsToken;
+%% token_tag2string(X) -> ?PrettyStreamToken;
+token_tag2string(subtractReq) -> ?PrettySubtractToken;
+token_tag2string(subtractReply) -> ?PrettySubtractToken;
+%% token_tag2string(X) -> ?PrettySynchISDNToken;
+%% token_tag2string(X) -> ?PrettyTerminationStateToken;
+token_tag2string(test) -> ?PrettyTestToken;
+token_tag2string(timeOut) -> ?PrettyTimeOutToken;
+token_tag2string(onTimeOut) -> ?PrettyTimeOutToken;
+token_tag2string(topologyAudit) -> ?PrettyTopologyToken;
+%% token_tag2string(X) -> ?PrettyTransToken;
+%% token_tag2string(X) -> ?PrettyV18Token;
+%% token_tag2string(X) -> ?PrettyV22Token;
+%% token_tag2string(X) -> ?PrettyV22bisToken;
+%% token_tag2string(X) -> ?PrettyV32Token;
+%% token_tag2string(X) -> ?PrettyV32bisToken;
+%% token_tag2string(X) -> ?PrettyV34Token;
+%% token_tag2string(X) -> ?PrettyV76Token;
+%% token_tag2string(X) -> ?PrettyV90Token;
+%% token_tag2string(X) -> ?PrettyV91Token;
+%% token_tag2string(X) -> ?PrettyVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v1.hrl").
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_v2.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_v2.erl
new file mode 100644
index 0000000000..37c067b937
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_v2.erl
@@ -0,0 +1,430 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_v2).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+-export([test/1]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v2.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%
+%% See megaco_pretty_text_encoder:decode_message/2
+%%
+%%----------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?PrettyAddToken;
+token_tag2string(addReply) -> ?PrettyAddToken;
+token_tag2string(auditDescriptor) -> ?PrettyAuditToken;
+token_tag2string(auditCapRequest) -> ?PrettyAuditCapToken;
+token_tag2string(auditCapReply) -> ?PrettyAuditCapToken;
+token_tag2string(auditValueRequest) -> ?PrettyAuditValueToken;
+token_tag2string(auditValueReply) -> ?PrettyAuditValueToken;
+%% token_tag2string(X) -> ?PrettyAuthToken;
+token_tag2string(bothway) -> ?PrettyBothwayToken;
+token_tag2string(brief) -> ?PrettyBriefToken;
+%% token_tag2string(X) -> ?PrettyBufferToken;
+%% token_tag2string(X) -> ?PrettyCtxToken;
+%% token_tag2string(X) -> ?PrettyContextAuditToken;
+token_tag2string(digitMapDescriptor) -> ?PrettyDigitMapToken;
+token_tag2string(digitMapToken) -> ?PrettyDigitMapToken;
+%% token_tag2string(X) -> ?PrettyDiscardToken;
+%% token_tag2string(X) -> ?PrettyDisconnectedToken;
+%% token_tag2string(X) -> ?PrettyDelayToken;
+token_tag2string(duration) -> ?PrettyDurationToken;
+%% token_tag2string(X) -> ?PrettyEmbedToken;
+token_tag2string(emergencyAudit) -> ?PrettyEmergencyToken;
+%% token_tag2string(X) -> ?PrettyEmergencyOffToken;
+token_tag2string(errorDescriptor) -> ?PrettyErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?PrettyEventBufferToken;
+token_tag2string(eventBufferToken) -> ?PrettyEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?PrettyEventsToken;
+token_tag2string(eventsToken) -> ?PrettyEventsToken;
+%% token_tag2string(X) -> ?PrettyFailoverToken;
+%% token_tag2string(X) -> ?PrettyForcedToken;
+%% token_tag2string(X) -> ?PrettyGracefulToken;
+%% token_tag2string(X) -> ?PrettyH221Token;
+%% token_tag2string(X) -> ?PrettyH223Token;
+%% token_tag2string(X) -> ?PrettyH226Token;
+%% token_tag2string(X) -> ?PrettyHandOffToken;
+%% token_tag2string(X) -> ?PrettyImmAckRequiredToken;
+token_tag2string(inactive) -> ?PrettyInactiveToken;
+token_tag2string(onInterruptByEvent) -> ?PrettyInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?PrettyInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?PrettyIsolateToken;
+token_tag2string(inSvc) -> ?PrettyInSvcToken;
+token_tag2string(keepActive) -> ?PrettyKeepActiveToken;
+token_tag2string(localDescriptor) -> ?PrettyLocalToken;
+token_tag2string(localControlDescriptor) -> ?PrettyLocalControlToken;
+token_tag2string(lockStep) -> ?PrettyLockStepToken;
+token_tag2string(loopBack) -> ?PrettyLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?PrettyMediaToken;
+token_tag2string(mediaToken) -> ?PrettyMediaToken;
+%% token_tag2string(X) -> ?PrettyMegacopToken;
+%% token_tag2string(X) -> ?PrettyMethodToken;
+%% token_tag2string(X) -> ?PrettyMgcIdToken;
+%% token_tag2string(X) -> ?PrettyModeToken;
+token_tag2string(modReq) -> ?PrettyModifyToken;
+token_tag2string(modReply) -> ?PrettyModifyToken;
+token_tag2string(modemDescriptor) -> ?PrettyModemToken;
+token_tag2string(modemToken) -> ?PrettyModemToken;
+token_tag2string(moveReq) -> ?PrettyMoveToken;
+token_tag2string(moveReply) -> ?PrettyMoveToken;
+%% token_tag2string(X) -> ?PrettyMtpToken;
+token_tag2string(muxDescriptor) -> ?PrettyMuxToken;
+token_tag2string(muxToken) -> ?PrettyMuxToken;
+token_tag2string(notifyReq) -> ?PrettyNotifyToken;
+%% token_tag2string(X) -> ?PrettyNotifyCompletionToken;
+%% token_tag2string(X) -> ?PrettyNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?PrettyObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?PrettyObservedEventsToken;
+token_tag2string(false) -> ?PrettyOffToken;
+token_tag2string(off) -> ?PrettyOffToken;
+token_tag2string(oneway) -> ?PrettyOnewayToken;
+token_tag2string(onOff) -> ?PrettyOnOffToken;
+token_tag2string(true) -> ?PrettyOnToken;
+token_tag2string(otherReason) -> ?PrettyOtherReasonToken;
+token_tag2string(outOfSvc) -> ?PrettyOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?PrettyPackagesToken;
+token_tag2string(packagesToken) -> ?PrettyPackagesToken;
+%% token_tag2string(X) -> ?PrettyPendingToken;
+token_tag2string(priorityAudit) -> ?PrettyPriorityToken;
+%% token_tag2string(X) -> ?PrettyProfileToken;
+%% token_tag2string(X) -> ?PrettyReasonToken;
+token_tag2string(recvOnly) -> ?PrettyRecvonlyToken;
+%% token_tag2string(X) -> ?PrettyReplyToken;
+%% token_tag2string(X) -> ?PrettyResponseAckToken;
+%% token_tag2string(X) -> ?PrettyRestartToken;
+token_tag2string(remoteDescriptor) -> ?PrettyRemoteToken;
+%% token_tag2string(X) -> ?PrettyReservedGroupToken;
+%% token_tag2string(X) -> ?PrettyReservedValueToken;
+token_tag2string(sendOnly) -> ?PrettySendonlyToken;
+token_tag2string(sendRecv) -> ?PrettySendrecvToken;
+%% token_tag2string(X) -> ?PrettyServicesToken;
+%% token_tag2string(X) -> ?PrettyServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?PrettyServiceChangeToken;
+%% token_tag2string(X) -> ?PrettyServiceChangeAddressToken;
+%% token_tag2string(X) -> ?PrettySignalListToken;
+token_tag2string(signalsDescriptor) -> ?PrettySignalsToken;
+token_tag2string(signalsToken) -> ?PrettySignalsToken;
+%% token_tag2string(X) -> ?PrettySignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?PrettyStatsToken;
+token_tag2string(statsToken) -> ?PrettyStatsToken;
+%% token_tag2string(X) -> ?PrettyStreamToken;
+token_tag2string(subtractReq) -> ?PrettySubtractToken;
+token_tag2string(subtractReply) -> ?PrettySubtractToken;
+%% token_tag2string(X) -> ?PrettySynchISDNToken;
+%% token_tag2string(X) -> ?PrettyTerminationStateToken;
+token_tag2string(test) -> ?PrettyTestToken;
+token_tag2string(timeOut) -> ?PrettyTimeOutToken;
+token_tag2string(onTimeOut) -> ?PrettyTimeOutToken;
+token_tag2string(topologyAudit) -> ?PrettyTopologyToken;
+%% token_tag2string(X) -> ?PrettyTransToken;
+%% token_tag2string(X) -> ?PrettyV18Token;
+%% token_tag2string(X) -> ?PrettyV22Token;
+%% token_tag2string(X) -> ?PrettyV22bisToken;
+%% token_tag2string(X) -> ?PrettyV32Token;
+%% token_tag2string(X) -> ?PrettyV32bisToken;
+%% token_tag2string(X) -> ?PrettyV34Token;
+%% token_tag2string(X) -> ?PrettyV76Token;
+%% token_tag2string(X) -> ?PrettyV90Token;
+%% token_tag2string(X) -> ?PrettyV91Token;
+%% token_tag2string(X) -> ?PrettyVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?LsbrktToken]).
+-define(RSBRKT, [?RsbrktToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(EmergencyOffToken , ?PrettyEmergencyOffToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v2.hrl").
+
+%% start() ->
+%% Fun = fun() ->
+%% PP = {'PropertyParm',"ipdc/realm",["ericsson"],asn1_NOVALUE},
+%% enc_PropertyParm(PP, [])
+%% end,
+%% test(Fun).
+
+test(Fun) when is_function(Fun) ->
+ Fun().
+
diff --git a/lib/megaco/src/text/megaco_pretty_text_encoder_v3.erl b/lib/megaco/src/text/megaco_pretty_text_encoder_v3.erl
new file mode 100644
index 0000000000..833b6ea00f
--- /dev/null
+++ b/lib/megaco/src/text/megaco_pretty_text_encoder_v3.erl
@@ -0,0 +1,462 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_pretty_text_encoder_v3).
+
+-export([encode_message/2,
+ encode_transaction/2,
+ encode_action_requests/2,
+ encode_action_request/2,
+ encode_command_request/2,
+ encode_action_reply/2]).
+
+-export([token_tag2string/1]).
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v3.hrl").
+-include("megaco_text_tokens.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message(EC, MegaMsg)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch enc_MegacoMessage(MegaMsg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end;
+encode_message(EncodingConfig, MegaMsg)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EncodingConfig}};
+encode_message(_EncodingConfig, _MegaMsg) ->
+ {error, bad_megaco_message}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%
+%% See megaco_pretty_text_encoder:decode_message/2
+%%
+%%----------------------------------------------------------------------
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_transaction(_EC, Trans) ->
+ case (catch enc_Transaction(Trans)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests(_EC, ActReqs) when is_list(ActReqs) ->
+ case (catch enc_ActionRequests(ActReqs)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request(_EC, ActReq)
+ when is_record(ActReq, 'ActionRequest') ->
+ case (catch enc_ActionRequest(ActReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a CommandRequest record into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_command_request(_EC, CmdReq)
+ when is_record(CmdReq, 'CommandRequest') ->
+ case (catch enc_CommandRequest(CmdReq)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+%%----------------------------------------------------------------------
+%% Convert a action reply into a deep io list
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply(_EC, ActRep)
+ when is_record(ActRep, 'ActionReply') ->
+ case (catch enc_ActionReply(ActRep)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Bin when is_binary(Bin) ->
+ {ok, Bin};
+ DeepIoList ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% A utility function to pretty print the tags found in a megaco message
+%%----------------------------------------------------------------------
+
+token_tag2string(addReq) -> ?CompactAddToken;
+token_tag2string(addReply) -> ?CompactAddToken;
+%% token_tag2string(X) -> ?CompactAndAUDITSelectToken;
+token_tag2string(auditDescriptor) -> ?CompactAuditToken;
+token_tag2string(auditCapRequest) -> ?CompactAuditCapToken;
+token_tag2string(auditCapReply) -> ?CompactAuditCapToken;
+token_tag2string(auditValueRequest) -> ?CompactAuditValueToken;
+token_tag2string(auditValueReply) -> ?CompactAuditValueToken;
+%% token_tag2string(X) -> ?CompactAuthToken;
+token_tag2string(both) -> ?CompactBothToken;
+token_tag2string(bothway) -> ?CompactBothwayToken;
+token_tag2string(brief) -> ?CompactBriefToken;
+%% token_tag2string(X) -> ?CompactBufferToken;
+%% token_tag2string(X) -> ?CompactCtxToken;
+%% token_tag2string(X) -> ?CompactContextAuditToken;
+%% token_tag2string(X) -> ?CompactContextAttrToken;
+%% token_tag2string(X) -> ?CompactContextListToken;
+token_tag2string(digitMapDescriptor) -> ?CompactDigitMapToken;
+token_tag2string(digitMapToken) -> ?CompactDigitMapToken;
+%% token_tag2string(X) -> ?CompactDirectionToken;
+%% token_tag2string(X) -> ?CompactDiscardToken;
+%% token_tag2string(X) -> ?CompactDisconnectedToken;
+%% token_tag2string(X) -> ?CompactDelayToken;
+token_tag2string(duration) -> ?CompactDurationToken;
+%% token_tag2string(X) -> ?CompactEmbedToken;
+token_tag2string(emergencyAudit) -> ?CompactEmergencyToken;
+%% token_tag2string(X) -> ?CompactEmergencyOffToken;
+%% token_tag2string(X) -> ?CompactEmergencyValueToken;
+token_tag2string(errorDescriptor) -> ?CompactErrorToken;
+token_tag2string(eventBufferDescriptor) -> ?CompactEventBufferToken;
+token_tag2string(eventBufferToken) -> ?CompactEventBufferToken;
+token_tag2string(eventsDescriptor) -> ?CompactEventsToken;
+token_tag2string(eventsToken) -> ?CompactEventsToken;
+token_tag2string(external) -> ?CompactExternalToken;
+%% token_tag2string(X) -> ?CompactFailoverToken;
+%% token_tag2string(X) -> ?CompactForcedToken;
+%% token_tag2string(X) -> ?CompactGracefulToken;
+%% token_tag2string(X) -> ?CompactH221Token;
+%% token_tag2string(X) -> ?CompactH223Token;
+%% token_tag2string(X) -> ?CompactH226Token;
+%% token_tag2string(X) -> ?CompactHandOffToken;
+token_tag2string(iepsCallind) -> ?CompactIEPSToken;
+%% token_tag2string(X) -> ?CompactImmAckRequiredToken;
+token_tag2string(inactive) -> ?CompactInactiveToken;
+token_tag2string(internal) -> ?CompactInternalToken;
+%% token_tag2string(X) -> ?CompactIntsigDelayToken;
+token_tag2string(onInterruptByEvent) -> ?CompactInterruptByEventToken;
+token_tag2string(onInterruptByNewSignalDescr) -> ?CompactInterruptByNewSignalsDescrToken;
+token_tag2string(isolate) -> ?CompactIsolateToken;
+token_tag2string(inSvc) -> ?CompactInSvcToken;
+token_tag2string(iteration) -> ?CompactIterationToken;
+token_tag2string(keepActive) -> ?CompactKeepActiveToken;
+token_tag2string(localDescriptor) -> ?CompactLocalToken;
+token_tag2string(localControlDescriptor) -> ?CompactLocalControlToken;
+token_tag2string(lockStep) -> ?CompactLockStepToken;
+token_tag2string(loopBack) -> ?CompactLoopbackToken;
+token_tag2string(mediaDescriptor) -> ?CompactMediaToken;
+token_tag2string(mediaToken) -> ?CompactMediaToken;
+%% token_tag2string(X) -> ?CompactMegacopToken;
+%% token_tag2string(X) -> ?CompactMethodToken;
+%% token_tag2string(X) -> ?CompactMgcIdToken;
+%% token_tag2string(X) -> ?CompactModeToken;
+token_tag2string(modReq) -> ?CompactModifyToken;
+token_tag2string(modReply) -> ?CompactModifyToken;
+token_tag2string(modemDescriptor) -> ?CompactModemToken;
+token_tag2string(modemToken) -> ?CompactModemToken;
+token_tag2string(moveReq) -> ?CompactMoveToken;
+token_tag2string(moveReply) -> ?CompactMoveToken;
+%% token_tag2string(X) -> ?CompactMtpToken;
+token_tag2string(muxDescriptor) -> ?CompactMuxToken;
+token_tag2string(muxToken) -> ?CompactMuxToken;
+%% token_tag2string(X) -> ?CompactNeverNotifyToken;
+token_tag2string(notifyReq) -> ?CompactNotifyToken;
+%% token_tag2string(X) -> ?CompactNotifyCompletionToken;
+%% token_tag2string(X) -> ?CompactNotifyImmediateToken;
+%% token_tag2string(X) -> ?CompactNotifyRegulatedToken;
+%% token_tag2string(X) -> ?CompactNx64kToken;
+token_tag2string(observedEventsDescriptor) -> ?CompactObservedEventsToken;
+token_tag2string(observedEventsToken) -> ?CompactObservedEventsToken;
+token_tag2string(false) -> ?CompactOffToken;
+token_tag2string(off) -> ?CompactOffToken;
+token_tag2string(oneway) -> ?CompactOnewayToken;
+token_tag2string(onewayboth) -> ?CompactOnewayBothToken;
+token_tag2string(onewayexternal) -> ?CompactOnewayExternalToken;
+token_tag2string(onOff) -> ?CompactOnOffToken;
+%% token_tag2string(X) -> ?CompactOrAUDITselectToken;
+token_tag2string(true) -> ?CompactOnToken;
+token_tag2string(otherReason) -> ?CompactOtherReasonToken;
+token_tag2string(outOfSvc) -> ?CompactOutOfSvcToken;
+token_tag2string(packagesDescriptor) -> ?CompactPackagesToken;
+token_tag2string(packagesToken) -> ?CompactPackagesToken;
+%% token_tag2string(X) -> ?CompactPendingToken;
+token_tag2string(priorityAudit) -> ?CompactPriorityToken;
+%% token_tag2string(X) -> ?CompactProfileToken;
+%% token_tag2string(X) -> ?CompactReasonToken;
+token_tag2string(recvOnly) -> ?CompactRecvonlyToken;
+%% token_tag2string(X) -> ?CompactReplyToken;
+token_tag2string(resetEventsDescriptor) -> ?CompactResetEventsDescriptorToken;
+%% token_tag2string(X) -> ?CompactRequestIDToken;
+%% token_tag2string(X) -> ?CompactResponseAckToken;
+%% token_tag2string(X) -> ?CompactRestartToken;
+token_tag2string(remoteDescriptor) -> ?CompactRemoteToken;
+%% token_tag2string(X) -> ?CompactReservedGroupToken;
+%% token_tag2string(X) -> ?CompactReservedValueToken;
+token_tag2string(sendOnly) -> ?CompactSendonlyToken;
+token_tag2string(sendRecv) -> ?CompactSendrecvToken;
+%% token_tag2string(X) -> ?CompactServicesToken;
+%% token_tag2string(X) -> ?CompactServiceStatesToken;
+token_tag2string(serviceChangeReq) -> ?CompactServiceChangeToken;
+%% token_tag2string(X) -> ?CompactServiceChangeAddressToken;
+token_tag2string(incomplete) -> ?CompactServiceChangeIncompleteToken;
+%% token_tag2string(X) -> ?CompactSignalListToken;
+token_tag2string(signalsDescriptor) -> ?CompactSignalsToken;
+token_tag2string(signalsToken) -> ?CompactSignalsToken;
+%% token_tag2string(X) -> ?CompactSignalTypeToken;
+token_tag2string(statisticsDescriptor) -> ?CompactStatsToken;
+token_tag2string(statsToken) -> ?CompactStatsToken;
+%% token_tag2string(X) -> ?CompactStreamToken;
+token_tag2string(subtractReq) -> ?CompactSubtractToken;
+token_tag2string(subtractReply) -> ?CompactSubtractToken;
+%% token_tag2string(X) -> ?CompactSynchISDNToken;
+%% token_tag2string(X) -> ?CompactTerminationStateToken;
+token_tag2string(test) -> ?CompactTestToken;
+token_tag2string(timeOut) -> ?CompactTimeOutToken;
+token_tag2string(onTimeOut) -> ?CompactTimeOutToken;
+token_tag2string(topologyAudit) -> ?CompactTopologyToken;
+%% token_tag2string(X) -> ?CompactTransToken;
+%% token_tag2string(X) -> ?CompactV18Token;
+%% token_tag2string(X) -> ?CompactV22Token;
+%% token_tag2string(X) -> ?CompactV22bisToken;
+%% token_tag2string(X) -> ?CompactV32Token;
+%% token_tag2string(X) -> ?CompactV32bisToken;
+%% token_tag2string(X) -> ?CompactV34Token;
+%% token_tag2string(X) -> ?CompactV76Token;
+%% token_tag2string(X) -> ?CompactV90Token;
+%% token_tag2string(X) -> ?CompactV91Token;
+%% token_tag2string(X) -> ?CompactVersionToken;
+token_tag2string(_) -> [].
+
+
+%%----------------------------------------------------------------------
+%% Define various macros used by the actual generator code
+%%----------------------------------------------------------------------
+
+-define(EQUAL, [?SpToken, ?EqualToken, ?SpToken]).
+-define(COLON, [?ColonToken]).
+-define(LBRKT, [?SpToken, ?LbrktToken, ?SpToken]).
+-define(RBRKT, [?SpToken, ?RbrktToken, ?SpToken]).
+-define(LSBRKT, [?SpToken, ?LsbrktToken, ?SpToken]).
+-define(RSBRKT, [?SpToken, ?RsbrktToken, ?SpToken]).
+-define(COMMA, [?CommaToken, ?SpToken]).
+-define(DOT, [?DotToken]).
+-define(SLASH, [?SlashToken]).
+-define(DQUOTE, [?DoubleQuoteToken]).
+-define(SP, [?SpToken]).
+-define(HTAB, [?HtabToken]).
+-define(CR, [?CrToken]).
+-define(LF, [?LfToken]).
+-define(LWSP, []).
+-define(EOL, ?LF).
+-define(WSP, ?SP).
+-define(SEP, ?WSP).
+
+-define(INIT_INDENT, []).
+-define(INC_INDENT(State), [?HtabToken | State]).
+-define(INDENT(State), [?LfToken | State]).
+-define(LBRKT_INDENT(State), [?SpToken, ?LbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RBRKT_INDENT(State), [?INDENT(State), ?RbrktToken]).
+-define(LSBRKT_INDENT(State), [?SpToken, ?LsbrktToken, ?INDENT(?INC_INDENT(State))]).
+-define(RSBRKT_INDENT(State), [?INDENT(State), ?RsbrktToken]).
+-define(COMMA_INDENT(State), [?CommaToken, ?INDENT(State)]).
+-define(SEP_INDENT(_State), [?LfToken]).
+
+%%----------------------------------------------------------------------
+%% Define token macros
+%%----------------------------------------------------------------------
+
+-define(AddToken , ?PrettyAddToken).
+-define(AndAUDITSelectToken , ?PrettytAndAUDITSelectToken).
+-define(AuditToken , ?PrettyAuditToken).
+-define(AuditCapToken , ?PrettyAuditCapToken).
+-define(AuditValueToken , ?PrettyAuditValueToken).
+-define(AuthToken , ?PrettyAuthToken).
+-define(BothToken , ?PrettyBothToken).
+-define(BothwayToken , ?PrettyBothwayToken).
+-define(BriefToken , ?PrettyBriefToken).
+-define(BufferToken , ?PrettyBufferToken).
+-define(CtxToken , ?PrettyCtxToken).
+-define(ContextAuditToken , ?PrettyContextAuditToken).
+-define(ContextAttrToken , ?PrettyContextAttrToken).
+-define(ContextListToken , ?PrettyContextListToken).
+-define(DigitMapToken , ?PrettyDigitMapToken).
+-define(DirectionToken , ?PrettyDirectionToken).
+-define(DiscardToken , ?PrettyDiscardToken).
+-define(DisconnectedToken , ?PrettyDisconnectedToken).
+-define(DelayToken , ?PrettyDelayToken).
+-define(DeleteToken , ?PrettyDeleteToken).
+-define(DurationToken , ?PrettyDurationToken).
+-define(EmbedToken , ?PrettyEmbedToken).
+-define(EmergencyToken , ?PrettyEmergencyToken).
+-define(EmergencyOffToken , ?PrettyEmergencyOffToken).
+-define(EmergencyValueToken , ?PrettyEmergencyValueToken).
+-define(ErrorToken , ?PrettyErrorToken).
+-define(EventBufferToken , ?PrettyEventBufferToken).
+-define(EventsToken , ?PrettyEventsToken).
+-define(ExternalToken , ?PrettyExternalToken).
+-define(FailoverToken , ?PrettyFailoverToken).
+-define(ForcedToken , ?PrettyForcedToken).
+-define(GracefulToken , ?PrettyGracefulToken).
+-define(H221Token , ?PrettyH221Token).
+-define(H223Token , ?PrettyH223Token).
+-define(H226Token , ?PrettyH226Token).
+-define(HandOffToken , ?PrettyHandOffToken).
+-define(IEPSToken , ?PrettyIEPSToken).
+-define(ImmAckRequiredToken , ?PrettyImmAckRequiredToken).
+-define(InactiveToken , ?PrettyInactiveToken).
+-define(InternalToken , ?PrettyInternalToken).
+-define(IntsigDelayToken , ?PrettyIntsigDelayToken).
+-define(IsolateToken , ?PrettyIsolateToken).
+-define(InSvcToken , ?PrettyInSvcToken).
+-define(InterruptByEventToken , ?PrettyInterruptByEventToken).
+-define(InterruptByNewSignalsDescrToken, ?PrettyInterruptByNewSignalsDescrToken).
+-define(IterationToken , ?PrettyIterationToken).
+-define(KeepActiveToken , ?PrettyKeepActiveToken).
+-define(LocalToken , ?PrettyLocalToken).
+-define(LocalControlToken , ?PrettyLocalControlToken).
+-define(LockStepToken , ?PrettyLockStepToken).
+-define(LoopbackToken , ?PrettyLoopbackToken).
+-define(MediaToken , ?PrettyMediaToken).
+-define(MegacopToken , ?PrettyMegacopToken).
+-define(MessageSegmentToken , ?PrettyMessageSegmentToken).
+-define(MethodToken , ?PrettyMethodToken).
+-define(MgcIdToken , ?PrettyMgcIdToken).
+-define(ModeToken , ?PrettyModeToken).
+-define(ModifyToken , ?PrettyModifyToken).
+-define(ModemToken , ?PrettyModemToken).
+-define(MoveToken , ?PrettyMoveToken).
+-define(MtpToken , ?PrettyMtpToken).
+-define(MuxToken , ?PrettyMuxToken).
+-define(NeverNotifyToken , ?PrettyNeverNotifyToken).
+-define(NotifyToken , ?PrettyNotifyToken).
+-define(NotifyCompletionToken , ?PrettyNotifyCompletionToken).
+-define(NotifyImmediateToken , ?PrettyNotifyImmediateToken).
+-define(NotifyRegulatedToken , ?PrettyNotifyRegulatedToken).
+-define(Nx64kToken , ?PrettyNx64kToken).
+-define(ObservedEventsToken , ?PrettyObservedEventsToken).
+-define(OffToken , ?PrettyOffToken).
+-define(OnewayToken , ?PrettyOnewayToken).
+-define(OnewayBothToken , ?PrettyOnewayBothToken).
+-define(OnewayExternalToken , ?PrettyOnewayExternalToken).
+-define(OnOffToken , ?PrettyOnOffToken).
+-define(OnToken , ?PrettyOnToken).
+-define(OrAUDITselectToken , ?PrettyOrAUDITselectToken).
+-define(OtherReasonToken , ?PrettyOtherReasonToken).
+-define(OutOfSvcToken , ?PrettyOutOfSvcToken).
+-define(PackagesToken , ?PrettyPackagesToken).
+-define(PendingToken , ?PrettyPendingToken).
+-define(PriorityToken , ?PrettyPriorityToken).
+-define(ProfileToken , ?PrettyProfileToken).
+-define(ReasonToken , ?PrettyReasonToken).
+-define(RecvonlyToken , ?PrettyRecvonlyToken).
+-define(ReplyToken , ?PrettyReplyToken).
+-define(ResetEventsDescriptorToken , ?PrettyResetEventsDescriptorToken).
+-define(ResponseAckToken , ?PrettyResponseAckToken).
+-define(RestartToken , ?PrettyRestartToken).
+-define(RemoteToken , ?PrettyRemoteToken).
+-define(RequestIDToken , ?PrettyRequestIDToken).
+-define(ReservedGroupToken , ?PrettyReservedGroupToken).
+-define(ReservedValueToken , ?PrettyReservedValueToken).
+-define(SegmentationCompleteToken , ?PrettySegmentationCompleteToken).
+-define(SendonlyToken , ?PrettySendonlyToken).
+-define(SendrecvToken , ?PrettySendrecvToken).
+-define(ServicesToken , ?PrettyServicesToken).
+-define(ServiceStatesToken , ?PrettyServiceStatesToken).
+-define(ServiceChangeToken , ?PrettyServiceChangeToken).
+-define(ServiceChangeAddressToken , ?PrettyServiceChangeAddressToken).
+-define(ServiceChangeIncompleteToken , ?PrettyServiceChangeIncompleteToken).
+-define(SignalListToken , ?PrettySignalListToken).
+-define(SignalsToken , ?PrettySignalsToken).
+-define(SignalTypeToken , ?PrettySignalTypeToken).
+-define(StatsToken , ?PrettyStatsToken).
+-define(StreamToken , ?PrettyStreamToken).
+-define(SubtractToken , ?PrettySubtractToken).
+-define(SynchISDNToken , ?PrettySynchISDNToken).
+-define(TerminationStateToken , ?PrettyTerminationStateToken).
+-define(TestToken , ?PrettyTestToken).
+-define(TimeOutToken , ?PrettyTimeOutToken).
+-define(TopologyToken , ?PrettyTopologyToken).
+-define(TransToken , ?PrettyTransToken).
+-define(V18Token , ?PrettyV18Token).
+-define(V22Token , ?PrettyV22Token).
+-define(V22bisToken , ?PrettyV22bisToken).
+-define(V32Token , ?PrettyV32Token).
+-define(V32bisToken , ?PrettyV32bisToken).
+-define(V34Token , ?PrettyV34Token).
+-define(V76Token , ?PrettyV76Token).
+-define(V90Token , ?PrettyV90Token).
+-define(V91Token , ?PrettyV91Token).
+-define(VersionToken , ?PrettyVersionToken).
+
+%%----------------------------------------------------------------------
+%% Include the generator code
+%%----------------------------------------------------------------------
+
+-include("megaco_text_gen_v3.hrl").
+
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3a.hrl b/lib/megaco/src/text/megaco_text_gen_prev3a.hrl
new file mode 100644
index 0000000000..b1ddb10a4e
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_prev3a.hrl
@@ -0,0 +1,2945 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V2 Megaco/H.248 text messages from internal form
+%% The following was changed:
+%% - MuxType (Nx64kToken)
+%% - auditItem (terminationAudit)
+%% - serviceChangeParm (auditItem)
+%%
+%% The following was added:
+%% - All IndAud stuff
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ %% These fields are actually not
+ %% supported in this implementation,
+ %% but because the messanger module
+ %% cannot see any diff between the
+ %% various v3 implementations...
+ segmentNumber = asn1_NOVALUE,
+ segmentationComplete = asn1_NOVALUE},
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = asn1_NOVALUE,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = CtxAAR,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {[CtxAAR], fun enc_ContextAttrAuditRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+% d("enc_ActionReply -> entry with"
+% "~n Id: ~p"
+% "~n ED: ~p"
+% "~n CtxRep: ~p"
+% "~n CmdRep: ~p", [Id, ED, CtxRep, CmdRep]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, [], State)
+ when CtxRep =/= asn1_NOVALUE ->
+% d("do_enc_ActionReply -> entry with"
+% "~n CtxRep: ~p", [CtxRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when CtxRep =/= asn1_NOVALUE, CmdRep =/= [] ->
+% d("do_enc_ActionReply -> entry with"
+% "~n CtxRep: ~p"
+% "~n CmdRep: ~p", [CtxRep, CmdRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, asn1_NOVALUE, CmdRep, State)
+ when CmdRep =/= [] ->
+% d("do_enc_ActionReply -> entry with"
+% "~n CmdRep: ~p", [CmdRep]),
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, [], State)
+ when (ED =/= asn1_NOVALUE) andalso (CtxRep =/= asn1_NOVALUE) ->
+% d("do_enc_ActionReply -> entry with"
+% "~n ED: ~p"
+% "~n CtxRep: ~p", [ED, CtxRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso (CmdRep =/= []) ->
+% d("do_enc_ActionReply -> entry with"
+% "~n ED: ~p"
+% "~n CmdRep: ~p", [ED, CmdRep]),
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso
+ (CtxRep =/= asn1_NOVALUE) andalso
+ (CmdRep =/= []) ->
+% d("do_enc_ActionReply -> entry with"
+% "~n ED: ~p"
+% "~n CtxRep: ~p"
+% "~n CmdRep: ~p", [ED, CtxRep, CmdRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when ED =/= asn1_NOVALUE ->
+% d("do_enc_ActionReply -> entry with"
+% "~n ED: ~p", [ED]),
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+enc_ContextRequest_priority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_priority(Val, _State) ->
+ {[Val], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextRequest_emergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_emergency(true, _State) ->
+ {[?EmergencyToken], fun(Elem, _) -> Elem end};
+enc_ContextRequest_emergency(false, _State) ->
+ {[?EmergencyOffToken], fun(Elem, _) -> Elem end}.
+
+enc_ContextRequest_topologyReq(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ asn1_NOVALUE}, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ List}, _State) ->
+ {List, fun enc_TopologyRequest/2};
+enc_ContextRequest_topologyReq(List, _State) ->
+ {[List], fun enc_TopologyRequest/2}.
+
+enc_ContextRequest_iepsCallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_iepsCallind(false, _State) ->
+ {[], dummy};
+% enc_ContextRequest_iepsCallind(false, _State) ->
+% {[?IEPS_XXXX_Token], fun(Elem, _) -> Elem end};
+enc_ContextRequest_iepsCallind(true, _State) ->
+ {[?IEPSToken], fun(Elem, _) -> Elem end}.
+
+enc_ContextRequest_contextProp(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp([PP], _State) ->
+ {[PP], fun enc_PropertyParm/2};
+enc_ContextRequest_contextProp(PPs, _State) when is_list(PPs) ->
+ error({at_most_one_contextProp, PPs}).
+
+enc_ContextRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = [],
+ iepsCallind = asn1_NOVALUE,
+ contextProp = []}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = Prio,
+ emergency = Em,
+ topologyReq = TR,
+ iepsCallind = Ieps,
+ contextProp = CP}, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ enc_list([enc_ContextRequest_priority(Prio, State),
+ enc_ContextRequest_emergency(Em, State),
+ enc_ContextRequest_topologyReq(TR, State),
+ enc_ContextRequest_iepsCallind(Ieps, State),
+ enc_ContextRequest_contextProp(CP, State)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextPropAud = []}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(CAAR, State) ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudContextAttrDescriptor(CAAR, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudContextAttrDescriptor(
+ #'ContextAttrAuditRequest'{topology = Top,
+ emergency = Em,
+ priority = Prio,
+ iepsCallind = Ieps,
+ contextPropAud = CPA}, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+ {[Em], fun('NULL', _) -> ?EmergencyToken end},
+ {[Prio], fun('NULL', _) -> ?PriorityToken end},
+ {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+ {CPA, fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+% d("enc_Command -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+% d("enc_CommandReply -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}],?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir}, State) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(Dir, State)
+ ].
+
+enc_TopologyDirection(bothway, _State) ->
+ ?BothwayToken;
+enc_TopologyDirection(isolate, _State) ->
+ ?IsolateToken;
+enc_TopologyDirection(oneway, _State) ->
+ ?OnewayToken;
+enc_TopologyDirection(Top, _State) ->
+ error({illegal_TopologyDirection, Top}).
+
+enc_AmmRequest(Val, State)
+ when is_record(Val, 'AmmRequest') ->
+% d("enc_AmmRequest -> entry with"
+% "~n Val: ~p", [Val]),
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'AmmRequest'.terminationID, State),
+ enc_opt_brackets(
+ enc_list([{Val#'AmmRequest'.descriptors, fun enc_ammDescriptor/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+% d("enc_ammDescriptor -> entry with"
+% "~n Tag: ~p"
+% "~n Desc: ~p", [Tag, Desc]),
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ statisticsDescriptor -> enc_StatisticsDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = asn1_NOVALUE}, State) ->
+% d("enc_AmmsReply(asn1_NOVALUE) -> entry with"
+% "~n ID: ~p", [ID]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = []}, State) ->
+% d("enc_AmmsReply([]) -> entry with"
+% "~n ID: ~p", [ID]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = Res}, State) ->
+% d("enc_AmmsReply -> entry with"
+% "~n ID: ~p"
+% "~n Res: ~p", [ID, Res]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(Val, State)
+ when is_record(Val, 'SubtractRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'SubtractRequest'.terminationID, State),
+ case Val#'SubtractRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_AuditRequest(Val, State)
+ when is_record(Val, 'AuditRequest') ->
+% d("enc_AuditRequest -> entry with"
+% "~n Val: ~p", [Val]),
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1([Val#'AuditRequest'.terminationID], State),
+ case Val#'AuditRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDListN(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor(asn1_NOVALUE) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor([]) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n List: ~p", [List]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n Prop: ~p", [Prop]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n List: ~p"
+% "~n Prop: ~p", [List, Prop]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+% d("enc_auditPropertyToken -> entry with",
+% "~n Param: ~p", [Param]),
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+%% The ASN.1 does not limit to just one of termStateDescr or streams,
+%% but the ABNF seams to do that...
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Streams}, State) ->
+% d("enc_IndAudMediaDescriptor -> entry with",
+% "~n Streams: ~p", [Streams]),
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = asn1_NOVALUE},
+ State) ->
+% d("enc_IndAudMediaDescriptor -> entry with",
+% "~n TSD: ~p", [TSD]),
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({Tag, Val}, State) ->
+% d("enc_IndAudMediaDescriptor_streams -> entry with",
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ oneStream ->
+ enc_IndAudStreamParms(Val, State);
+ multiStream ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+ _ ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag})
+ end.
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL'}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE}, State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% In text, localDescriptor and remoteDescriptor are not allowed!!
+enc_IndAudStreamParms(
+ #'IndAudStreamParms'{localControlDescriptor = LCD,
+ localDescriptor = asn1_NOVALUE,
+ remoteDescriptor = asn1_NOVALUE,
+ statisticsDescriptor = SD}, State) ->
+% d("enc_IndAudStreamParms -> entry with"
+% "~n LCD: ~p"
+% "~n SD: ~p", [LCD, SD]),
+ [
+ enc_list([{[LCD], fun enc_IndAudLocalControlDescriptor/2},
+ {[SD], fun enc_IndAudStatisticsDescriptor/2}],
+ ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(Val, State)
+ when is_record(Val, 'IndAudLocalControlDescriptor') ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'IndAudLocalControlDescriptor'.streamMode],
+ fun('NULL', _) -> ?ModeToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveValue],
+ fun('NULL', _) -> ?ReservedValueToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveGroup],
+ fun('NULL', _) -> ?ReservedGroupToken end},
+ {Val#'IndAudLocalControlDescriptor'.propertyParms,
+ fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = PkgdName}, State) ->
+ enc_PkgdName(PkgdName, State).
+
+enc_IndAudMediaDescriptor_multiStream([Val], State) ->
+% d("enc_IndAudMediaDescriptor_multiStream -> entry with"
+% "~n Val: ~p", [Val]),
+ [
+ enc_IndAudStreamDescriptor(Val, ?INC_INDENT(State))
+ ];
+enc_IndAudMediaDescriptor_multiStream(Vals, _State) when is_list(Vals) ->
+ error({invalid_IndAudMediaDescriptor_multiStream_length, Vals});
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+% d("enc_IndAudStreamDescriptor -> entry with"
+% "~n SID: ~p"
+% "~n Parms: ~p", [SID, Parms]),
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventBufferDescriptor') ->
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID} = Val,
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventsDescriptor') ->
+ #'IndAudEventsDescriptor'{requestID = ReqID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE} = Val,
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(ReqID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = Parm},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(Parm, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+% d("enc_IndAudStatisticsDescriptor -> entry with"
+% "~n Name: ~p", [Name]),
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit',Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([], _State) ->
+ [];
+enc_TerminationAudit([Mand | Opt], State) ->
+% d("enc_TerminationAudit -> entry with"
+% "~n Mand: ~p", [Mand]),
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+% d("enc_AuditReturnParameter -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+ enc_list([{List, fun enc_auditReturnItem/2}], ?INC_INDENT(State)).
+
+
+enc_NotifyRequest(Val, State)
+ when is_record(Val, 'NotifyRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'NotifyRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ %% BUGBUG: Mismatch between ASN.1 and ABNF
+ %% BUGBUG: The following ought to be a 'choice'
+ case Val#'NotifyRequest'.errorDescriptor of
+ asn1_NOVALUE ->
+ OED = Val#'NotifyRequest'.observedEventsDescriptor,
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State));
+ ErrorDescr ->
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State))
+ end,
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(Val, State)
+ when is_record(Val, 'NotifyReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ case Val#'NotifyReply'.terminationID of
+ asn1_NOVALUE ->
+ error(asn1_not_compliant_with_abnf);
+ TermId ->
+ enc_TerminationIDList1(TermId, State)
+ end,
+ case Val#'NotifyReply'.errorDescriptor of
+ asn1_NOVALUE ->
+ [];
+ ErrorDescr ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_ObservedEventsDescriptor(Val, State)
+ when is_record(Val, 'ObservedEventsDescriptor') ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(Val#'ObservedEventsDescriptor'.requestId, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEventsDescriptors(Val#'ObservedEventsDescriptor'.observedEventLst, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEventsDescriptors([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(Val, State)
+ when is_record(Val, 'ObservedEvent') ->
+ [
+ case Val#'ObservedEvent'.timeNotation of
+ asn1_NOVALUE ->
+ [];
+ TimeStamp ->
+ [
+ enc_TimeNotation(TimeStamp, State),
+ ?LWSP,
+ ?COLON
+ ]
+ end,
+ ?LWSP,
+ enc_EventName(Val#'ObservedEvent'.eventName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'ObservedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'ObservedEvent'.eventParList, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName',Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(Val, State)
+ when is_record(Val, 'ServiceChangeRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Val#'ServiceChangeRequest'.serviceChangeParms,
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(Val, State)
+ when is_record(Val, 'ServiceChangeReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeReply'.terminationID, State),
+ enc_ServiceChangeResult(Val#'ServiceChangeReply'.serviceChangeResult, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult',Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({Tag, Val}, State) ->
+ case Tag of
+ errorDescriptor ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ serviceChangeResParms ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+ _ ->
+ error({invalid_ServiceChangeResult_tag, Tag})
+ end.
+
+%% Required length of termination ID list is 1
+enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList1(Val, State);
+enc_TerminationIDList1([Singleton], State) ->
+ enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDListN({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDListN(Val, State);
+enc_TerminationIDListN([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDListN(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(Val, State)
+ when is_record(Val, 'MediaDescriptor') ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'MediaDescriptor'.termStateDescr],
+ fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Val#'MediaDescriptor'.streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2},
+ {[Val#'StreamParms'.statisticsDescriptor],
+ fun enc_StatisticsDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name == "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EQUAL,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EQUAL,
+ ?LSBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RSBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDListN(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(Val, State)
+ when is_record(Val, 'EventsDescriptor') ->
+ #'EventsDescriptor'{requestID = RequestId,
+ eventList = Events} = Val,
+ if
+ RequestId == asn1_NOVALUE, Events == [] ->
+ [
+ ?EventsToken
+ ];
+
+ RequestId /= asn1_NOVALUE, Events /= [] ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RequestId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Events, fun enc_RequestedEvent/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end.
+
+enc_RequestedEvent(Val, State)
+ when is_record(Val, 'RequestedEvent') ->
+ PkgdName = ?META_ENC(event, Val#'RequestedEvent'.pkgdName),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'RequestedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'RequestedEvent'.evParList, fun enc_eventOther/2} |
+ decompose_requestedActions(Val#'RequestedEvent'.eventAction)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of KeepActiveToken , eventDM and eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (KA =/= true) andalso
+ (SD =/= asn1_NOVALUE) andalso
+ (SD =/= []) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD}) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ].
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso is_list(Evs) andalso (Evs =/= []) ->
+ %% d("enc_embedFirst -> entry with"
+ %% "~n RID: ~p"
+ %% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+ %% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ evParList = EPL,
+ eventAction = EA}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list(
+ [{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(Val)
+ when is_record(Val, 'SecondRequestedActions') ->
+ [
+ {[Val#'SecondRequestedActions'.keepActive],
+ fun enc_keepActive/2},
+ {[Val#'SecondRequestedActions'.eventDM],
+ fun enc_EventDM/2},
+ {[Val#'SecondRequestedActions'.signalsDescriptor],
+ fun enc_embeddedSignalsDescriptor/2}
+ ].
+
+enc_embeddedSignalsDescriptor(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EventSpecs, State)
+ when is_list(EventSpecs) andalso (length(EventSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EventSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EventSpecs, _State) ->
+ error({bad_eventSpecs, EventSpecs}).
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = Name,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(Name, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(List, State) when is_list(List) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(Val, State)
+ when is_record(Val, 'Signal') ->
+ [
+ enc_SignalName(Val#'Signal'.signalName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'Signal'.streamID], fun enc_sigStream/2},
+ {[Val#'Signal'.sigType], fun enc_sigSignalType/2},
+ {[Val#'Signal'.duration], fun enc_sigDuration/2},
+ {[Val#'Signal'.notifyCompletion], fun enc_notifyCompletion/2},
+ {[Val#'Signal'.keepActive], fun enc_keepActive/2},
+ {Val#'Signal'.sigParList, fun enc_sigOther/2},
+ {[Val#'Signal'.direction], fun enc_SignalDirection/2},
+ {[Val#'Signal'.requestID], fun enc_sigRequestID/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_SignalDirection({'SignalDirection', Val}, State) ->
+ enc_SignalDirection(Val, State);
+enc_SignalDirection(Val, _State) ->
+ [
+ ?DirectionToken,
+ ?EQUAL,
+ case Val of
+ internal -> ?InternalToken;
+ external -> ?ExternalToken;
+ both -> ?BothToken
+ end
+ ].
+
+enc_sigRequestID(Val, State) ->
+ [
+ ?RequestIDToken,
+ ?EQUAL,
+ enc_RequestID(Val, State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = [],
+ durationTimer = asn1_NOVALUE}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2},
+ {[Val#'ServiceChangeParm'.serviceChangeIncompleteFlag],
+ fun('NULL', _) -> ?ServiceChangeIncompleteToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken
+ end
+ %% BUGBUG: extension
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invalid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
+
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3b.hrl b/lib/megaco/src/text/megaco_text_gen_prev3b.hrl
new file mode 100644
index 0000000000..8a4af877dc
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_prev3b.hrl
@@ -0,0 +1,2966 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V2 Megaco/H.248 text messages from internal form
+%% The following was changed:
+%% - MuxType (Nx64kToken)
+%% - auditItem (terminationAudit)
+%% - serviceChangeParm (auditItem)
+%%
+%% The following was added:
+%% - All IndAud stuff
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ %% These fields are actually not
+ %% supported in this implementation,
+ %% but because the messanger module
+ %% cannot see any diff between the
+ %% various v3 implementations...
+ segmentNumber = asn1_NOVALUE,
+ segmentationComplete = asn1_NOVALUE},
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = asn1_NOVALUE,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = CtxAAR,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {[CtxAAR], fun enc_ContextAttrAuditRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+%% d("enc_ActionReply -> entry with"
+%% "~n Id: ~p"
+%% "~n ED: ~p"
+%% "~n CtxRep: ~p"
+%% "~n CmdRep: ~p", [Id, ED, CtxRep, CmdRep]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, [], State)
+ when (CtxRep =/= asn1_NOVALUE) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n CtxRep: ~p", [CtxRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) andalso (CmdRep =/= []) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n CtxRep: ~p"
+%% "~n CmdRep: ~p", [CtxRep, CmdRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, asn1_NOVALUE, CmdRep, State)
+ when (CmdRep =/= []) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n CmdRep: ~p", [CmdRep]),
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, [], State)
+ when (ED =/= asn1_NOVALUE) andalso (CtxRep =/= asn1_NOVALUE) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n ED: ~p"
+%% "~n CtxRep: ~p", [ED, CtxRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso (CmdRep =/= []) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n ED: ~p"
+%% "~n CmdRep: ~p", [ED, CmdRep]),
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso
+ (CtxRep =/= asn1_NOVALUE) andalso
+ (CmdRep =/= []) ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n ED: ~p"
+%% "~n CtxRep: ~p"
+%% "~n CmdRep: ~p", [ED, CtxRep, CmdRep]),
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when ED =/= asn1_NOVALUE ->
+%% d("do_enc_ActionReply -> entry with"
+%% "~n ED: ~p", [ED]),
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+enc_ContextRequest_priority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_priority(Val, _State) ->
+ {[Val], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextRequest_emergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_emergency(true, _State) ->
+ {[?EmergencyToken], fun(Elem, _) -> Elem end};
+enc_ContextRequest_emergency(false, _State) ->
+ {[?EmergencyOffToken], fun(Elem, _) -> Elem end}.
+
+enc_ContextRequest_topologyReq(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ asn1_NOVALUE}, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ List}, _State) ->
+ {List, fun enc_TopologyRequest/2};
+enc_ContextRequest_topologyReq(List, _State) ->
+ {[List], fun enc_TopologyRequest/2}.
+
+enc_ContextRequest_iepscallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_iepscallind(Bool, _State) ->
+ {[Bool], fun enc_iepsValue/2}.
+
+enc_ContextRequest_contextProp(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp(Props, _State) ->
+ {[Props], fun(Elem, S) -> enc_contextAttrDescriptor(Elem, contextProps, S) end}.
+
+enc_contextAttrDescriptor([Mand|Opt], contextProps, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ [enc_PropertyParm(Mand, State) |
+ [[?COMMA_INDENT(State), enc_PropertyParm(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = [],
+ iepscallind = asn1_NOVALUE,
+ contextProp = []}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = Prio,
+ emergency = Em,
+ topologyReq = TR,
+ iepscallind = Ieps,
+ contextProp = CP}, State) ->
+ [
+ enc_list([enc_ContextRequest_priority(Prio, State),
+ enc_ContextRequest_emergency(Em, State),
+ enc_ContextRequest_topologyReq(TR, State),
+ enc_ContextRequest_iepscallind(Ieps, State),
+ enc_ContextRequest_contextProp(CP, State)],
+ State)
+ ].
+
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = []}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(CAAR, State) ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudContextAttrDescriptor(CAAR, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudContextAttrDescriptor(
+ #'ContextAttrAuditRequest'{topology = Top,
+ emergency = Em,
+ priority = Prio,
+ iepscallind = Ieps,
+ contextPropAud = CPA}, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+ {[Em], fun('NULL', _) -> ?EmergencyToken end},
+ {[Prio], fun('NULL', _) -> ?PriorityToken end},
+ {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+ {CPA, fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+% d("enc_Command -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+%% d("enc_CommandReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}],?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir}, State) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(Dir, State)
+ ].
+
+enc_TopologyDirection(bothway, _State) ->
+ ?BothwayToken;
+enc_TopologyDirection(isolate, _State) ->
+ ?IsolateToken;
+enc_TopologyDirection(oneway, _State) ->
+ ?OnewayToken;
+enc_TopologyDirection(Top, _State) ->
+ error({illegal_TopologyDirection, Top}).
+
+enc_iepsValue(Val, _State) ->
+ [
+ ?IEPSToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+
+
+enc_AmmRequest(Val, State)
+ when is_record(Val, 'AmmRequest') ->
+% d("enc_AmmRequest -> entry with"
+% "~n Val: ~p", [Val]),
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'AmmRequest'.terminationID, State),
+ enc_opt_brackets(
+ enc_list([{Val#'AmmRequest'.descriptors, fun enc_ammDescriptor/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+% d("enc_ammDescriptor -> entry with"
+% "~n Tag: ~p"
+% "~n Desc: ~p", [Tag, Desc]),
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ statisticsDescriptor -> enc_StatisticsDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = asn1_NOVALUE}, State) ->
+% d("enc_AmmsReply(asn1_NOVALUE) -> entry with"
+% "~n ID: ~p", [ID]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = []}, State) ->
+% d("enc_AmmsReply([]) -> entry with"
+% "~n ID: ~p", [ID]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = Res}, State) ->
+% d("enc_AmmsReply -> entry with"
+% "~n ID: ~p"
+% "~n Res: ~p", [ID, Res]),
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(Val, State)
+ when is_record(Val, 'SubtractRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'SubtractRequest'.terminationID, State),
+ case Val#'SubtractRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_AuditRequest(Val, State)
+ when is_record(Val, 'AuditRequest') ->
+ %% d("enc_AuditRequest -> entry with"
+ %% "~n Val: ~p", [Val]),
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1([Val#'AuditRequest'.terminationID], State),
+ case Val#'AuditRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+%% d("enc_AuditReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ contextAuditResult ->
+ %% d("enc_AuditReply -> contextAuditResult"),
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDListN(Val, State)
+ ];
+ error ->
+ %% d("enc_AuditReply -> error"),
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ %% d("enc_AuditReply -> auditResult"),
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor(asn1_NOVALUE) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor([]) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n List: ~p", [List]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n Prop: ~p", [Prop]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+% d("enc_AuditDescriptor -> entry with",
+% "~n List: ~p"
+% "~n Prop: ~p", [List, Prop]),
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+% d("enc_auditPropertyToken -> entry with",
+% "~n Param: ~p", [Param]),
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+%% The ASN.1 does not limit to just one of termStateDescr or streams,
+%% but the ABNF seams to do that...
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Streams}, State) ->
+% d("enc_IndAudMediaDescriptor -> entry with",
+% "~n Streams: ~p", [Streams]),
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = asn1_NOVALUE},
+ State) ->
+% d("enc_IndAudMediaDescriptor -> entry with",
+% "~n TSD: ~p", [TSD]),
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({Tag, Val}, State) ->
+% d("enc_IndAudMediaDescriptor_streams -> entry with",
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ oneStream ->
+ enc_IndAudStreamParms(Val, State);
+ multiStream ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+ _ ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag})
+ end.
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL'}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE}, State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% In text, localDescriptor and remoteDescriptor are not allowed!!
+enc_IndAudStreamParms(
+ #'IndAudStreamParms'{localControlDescriptor = LCD,
+ localDescriptor = asn1_NOVALUE,
+ remoteDescriptor = asn1_NOVALUE,
+ statisticsDescriptor = SD}, State) ->
+% d("enc_IndAudStreamParms -> entry with"
+% "~n LCD: ~p"
+% "~n SD: ~p", [LCD, SD]),
+ [
+ enc_list([{[LCD], fun enc_IndAudLocalControlDescriptor/2},
+ {[SD], fun enc_IndAudStatisticsDescriptor/2}],
+ ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(Val, State)
+ when is_record(Val, 'IndAudLocalControlDescriptor') ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'IndAudLocalControlDescriptor'.streamMode],
+ fun('NULL', _) -> ?ModeToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveValue],
+ fun('NULL', _) -> ?ReservedValueToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveGroup],
+ fun('NULL', _) -> ?ReservedGroupToken end},
+ {Val#'IndAudLocalControlDescriptor'.propertyParms,
+ fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = PkgdName}, State) ->
+ enc_PkgdName(PkgdName, State).
+
+enc_IndAudMediaDescriptor_multiStream([Val], State) ->
+ %% d("enc_IndAudMediaDescriptor_multiStream -> entry with"
+ %% "~n Val: ~p", [Val]),
+ [
+ enc_IndAudStreamDescriptor(Val, ?INC_INDENT(State))
+ ];
+enc_IndAudMediaDescriptor_multiStream(Vals, State) when is_list(Vals) ->
+%% d("enc_IndAudMediaDescriptor_multiStream -> entry with"
+%% "~n Vals: ~p", [Vals]),
+ [
+ enc_list([{Vals, fun enc_IndAudStreamDescriptor/2}], State)
+ ];
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+%% d("enc_IndAudStreamDescriptor -> entry with"
+%% "~n SID: ~p"
+%% "~n Parms: ~p", [SID, Parms]),
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventBufferDescriptor') ->
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID} = Val,
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventsDescriptor') ->
+ #'IndAudEventsDescriptor'{requestID = ReqID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE} = Val,
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(ReqID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = Parm},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(Parm, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+% d("enc_IndAudStatisticsDescriptor -> entry with"
+% "~n Name: ~p", [Name]),
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit',Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([], _State) ->
+ [];
+enc_TerminationAudit([Mand | Opt], State) ->
+% d("enc_TerminationAudit -> entry with"
+% "~n Mand: ~p", [Mand]),
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+% d("enc_AuditReturnParameter -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+ enc_list([{List, fun enc_auditReturnItem/2}], ?INC_INDENT(State)).
+
+
+enc_NotifyRequest(Val, State)
+ when is_record(Val, 'NotifyRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'NotifyRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ %% BUGBUG: Mismatch between ASN.1 and ABNF
+ %% BUGBUG: The following ought to be a 'choice'
+ case Val#'NotifyRequest'.errorDescriptor of
+ asn1_NOVALUE ->
+ OED = Val#'NotifyRequest'.observedEventsDescriptor,
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State));
+ ErrorDescr ->
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State))
+ end,
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(Val, State)
+ when is_record(Val, 'NotifyReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ case Val#'NotifyReply'.terminationID of
+ asn1_NOVALUE ->
+ error(asn1_not_compliant_with_abnf);
+ TermId ->
+ enc_TerminationIDList1(TermId, State)
+ end,
+ case Val#'NotifyReply'.errorDescriptor of
+ asn1_NOVALUE ->
+ [];
+ ErrorDescr ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_ObservedEventsDescriptor(Val, State)
+ when is_record(Val, 'ObservedEventsDescriptor') ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(Val#'ObservedEventsDescriptor'.requestId, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEventsDescriptors(Val#'ObservedEventsDescriptor'.observedEventLst, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEventsDescriptors([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(Val, State)
+ when is_record(Val, 'ObservedEvent') ->
+ [
+ case Val#'ObservedEvent'.timeNotation of
+ asn1_NOVALUE ->
+ [];
+ TimeStamp ->
+ [
+ enc_TimeNotation(TimeStamp, State),
+ ?LWSP,
+ ?COLON
+ ]
+ end,
+ ?LWSP,
+ enc_EventName(Val#'ObservedEvent'.eventName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'ObservedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'ObservedEvent'.eventParList, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName',Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(Val, State)
+ when is_record(Val, 'ServiceChangeRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Val#'ServiceChangeRequest'.serviceChangeParms,
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(Val, State)
+ when is_record(Val, 'ServiceChangeReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeReply'.terminationID, State),
+ enc_ServiceChangeResult(Val#'ServiceChangeReply'.serviceChangeResult, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult',Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({Tag, Val}, State) ->
+ case Tag of
+ errorDescriptor ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ serviceChangeResParms ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+ _ ->
+ error({invalid_ServiceChangeResult_tag, Tag})
+ end.
+
+%% Required length of termination ID list is 1
+enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList1(Val, State);
+enc_TerminationIDList1([Singleton], State) ->
+ enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDListN({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDListN(Val, State);
+enc_TerminationIDListN([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDListN(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(Val, State)
+ when is_record(Val, 'MediaDescriptor') ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'MediaDescriptor'.termStateDescr],
+ fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Val#'MediaDescriptor'.streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2},
+ {[Val#'StreamParms'.statisticsDescriptor],
+ fun enc_StatisticsDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name =:= "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EQUAL,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EQUAL,
+ ?LSBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RSBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDListN(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(Val, State)
+ when is_record(Val, 'EventsDescriptor') ->
+ #'EventsDescriptor'{requestID = RequestId,
+ eventList = Events} = Val,
+ if
+ RequestId == asn1_NOVALUE, Events == [] ->
+ [
+ ?EventsToken
+ ];
+
+ RequestId /= asn1_NOVALUE, Events /= [] ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RequestId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Events, fun enc_RequestedEvent/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end.
+
+enc_RequestedEvent(Val, State)
+ when is_record(Val, 'RequestedEvent') ->
+ PkgdName = ?META_ENC(event, Val#'RequestedEvent'.pkgdName),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'RequestedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'RequestedEvent'.evParList, fun enc_eventOther/2} |
+ decompose_requestedActions(Val#'RequestedEvent'.eventAction)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of KeepActiveToken , eventDM and eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (KA =/= true) andalso
+ (SD =/= asn1_NOVALUE) andalso
+ (SD =/= []) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD}) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ].
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso is_list(Evs) andalso (Evs =/= []) ->
+ %% d("enc_embedFirst -> entry with"
+ %% "~n RID: ~p"
+ %% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+ %% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ evParList = EPL,
+ eventAction = EA}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list(
+ [{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(Val)
+ when is_record(Val, 'SecondRequestedActions') ->
+ [
+ {[Val#'SecondRequestedActions'.keepActive],
+ fun enc_keepActive/2},
+ {[Val#'SecondRequestedActions'.eventDM],
+ fun enc_EventDM/2},
+ {[Val#'SecondRequestedActions'.signalsDescriptor],
+ fun enc_embeddedSignalsDescriptor/2}
+ ].
+
+enc_embeddedSignalsDescriptor(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EventSpecs, State)
+ when is_list(EventSpecs) andalso (length(EventSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EventSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = Name,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(Name, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(List, State) when is_list(List) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(Val, State)
+ when is_record(Val, 'Signal') ->
+ [
+ enc_SignalName(Val#'Signal'.signalName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'Signal'.streamID], fun enc_sigStream/2},
+ {[Val#'Signal'.sigType], fun enc_sigSignalType/2},
+ {[Val#'Signal'.duration], fun enc_sigDuration/2},
+ {[Val#'Signal'.notifyCompletion], fun enc_notifyCompletion/2},
+ {[Val#'Signal'.keepActive], fun enc_keepActive/2},
+ {Val#'Signal'.sigParList, fun enc_sigOther/2},
+ {[Val#'Signal'.direction], fun enc_SignalDirection/2},
+ {[Val#'Signal'.requestID], fun enc_sigRequestID/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_SignalDirection({'SignalDirection', Val}, State) ->
+ enc_SignalDirection(Val, State);
+enc_SignalDirection(Val, _State) ->
+ [
+ ?DirectionToken,
+ ?EQUAL,
+ case Val of
+ internal -> ?InternalToken;
+ external -> ?ExternalToken;
+ both -> ?BothToken
+ end
+ ].
+
+enc_sigRequestID(Val, State) ->
+ [
+ ?RequestIDToken,
+ ?EQUAL,
+ enc_RequestID(Val, State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = [],
+ durationTimer = asn1_NOVALUE}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2},
+ {[Val#'ServiceChangeParm'.serviceChangeIncompleteFlag],
+ fun('NULL', _) -> ?ServiceChangeIncompleteToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken
+ end
+ %% BUGBUG: extension
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invalid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% d(get(dbg), F, A).
+%%
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+%%
+
diff --git a/lib/megaco/src/text/megaco_text_gen_prev3c.hrl b/lib/megaco/src/text/megaco_text_gen_prev3c.hrl
new file mode 100644
index 0000000000..11db906846
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_prev3c.hrl
@@ -0,0 +1,3443 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V3 Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+%% segmentReply ->
+%% enc_SegmentReply(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res%% ,
+%% segmentationNumber = SegNo,
+%% segmentationComplete = SegCompl
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ %% These fields are actually not
+ %% supported in this implementation,
+ %% but because the messanger module
+ %% cannot see any diff between the
+ %% various v3 implementations...
+ segmentNumber = asn1_NOVALUE,
+ segmentationComplete = asn1_NOVALUE
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = asn1_NOVALUE,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = CtxAAR,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {[CtxAAR], fun enc_ContextAttrAuditRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = asn1_NOVALUE,
+ contextReply = asn1_NOVALUE,
+ commandReply = []},
+ State) ->
+%% d("enc_ActionReply -> entry with"
+%% "~n Id: ~p", [Id]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State)
+ ];
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+%% d("enc_ActionReply -> entry with"
+%% "~n Id: ~p"
+%% "~n ED: ~p"
+%% "~n CtxRep: ~p"
+%% "~n CmdRep: ~p", [Id, ED, CtxRep, CmdRep]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, [], State)
+ when (CtxRep =/= asn1_NOVALUE) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) andalso (CmdRep =/= []) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, asn1_NOVALUE, CmdRep, State)
+ when (CmdRep =/= []) ->
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, [], State)
+ when (ED =/= asn1_NOVALUE) andalso (CtxRep =/= asn1_NOVALUE) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso (CmdRep =/= []) ->
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) andalso
+ (CtxRep =/= asn1_NOVALUE) andalso
+ (CmdRep =/= []) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when (ED =/= asn1_NOVALUE) ->
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+enc_ContextRequest_priority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_priority(Val, _State) ->
+ {[Val], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextRequest_emergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_emergency(true, _State) ->
+ {[?EmergencyToken], fun(Elem, _) -> Elem end};
+enc_ContextRequest_emergency(false, _State) ->
+ {[?EmergencyOffToken], fun(Elem, _) -> Elem end}.
+
+enc_ContextRequest_topologyReq(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ asn1_NOVALUE}, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ List}, _State) ->
+ {List, fun enc_TopologyRequest/2};
+enc_ContextRequest_topologyReq(List, _State) ->
+ {[List], fun enc_TopologyRequest/2}.
+
+enc_ContextRequest_iepscallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_iepscallind(Bool, _State) ->
+ {[Bool], fun enc_iepsValue/2}.
+
+enc_ContextRequest_contextProp(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp(Props, _State) ->
+ {[Props], fun(Elem, S) -> enc_contextAttrDescriptor(Elem, contextProps, S) end}.
+
+enc_ContextRequest_contextList(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextList([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextList(Props, _State) ->
+ {[Props], fun(Elem, S) ->
+ enc_contextAttrDescriptor(Elem, contextList, S)
+ end}.
+
+enc_contextAttrDescriptor([Mand|Opt], contextProps, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ [enc_PropertyParm(Mand, State) |
+ [[?COMMA_INDENT(State), enc_PropertyParm(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ];
+enc_contextAttrDescriptor(CtxIdList, contextList, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ enc_contextIdList(CtxIdList, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_contextIdList([Mand|Opt], State) ->
+ State2 = ?INC_INDENT(State),
+ [
+ ?ContextListToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ [enc_ContextID(Mand, State2) |
+ [[?COMMA_INDENT(State2), enc_ContextID(Val, State2)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE,
+ contextList = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = [],
+ iepscallind = asn1_NOVALUE,
+ contextProp = [],
+ contextList = []}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = Prio,
+ emergency = Em,
+ topologyReq = TR,
+ iepscallind = Ieps,
+ contextProp = CP,
+ contextList = CL}, State) ->
+ [
+ enc_list([enc_ContextRequest_priority(Prio, State),
+ enc_ContextRequest_emergency(Em, State),
+ enc_ContextRequest_topologyReq(TR, State),
+ enc_ContextRequest_iepscallind(Ieps, State),
+ enc_ContextRequest_contextProp(CP, State),
+ enc_ContextRequest_contextList(CL, State)],
+ State)
+ ].
+
+
+%% -- contextAudit --
+%% contextAudit = ContextAuditToken LBRKT
+%% (contextAuditProperties *(COMMA contextAuditProperties)) /
+%% indAudcontextAttrDesscriptor
+%% RBRKT
+%% contextAuditProperties =
+%% (TopologyToken / EmergencyToken / PriorityToken /
+%% IEPSToken / pkgdName / contextAuditSelect)
+%% contextAuditSelect =
+%% priority / emergencyValue / iepsValue /
+%% contextAttrDescriptor / auditSelectLogic
+%% indAudcontextAttrDesscriptor =
+%% ContextAttrToken LBRKT
+%% (contextAuditProperties *(COMMA contextAuditProperties))
+%% RBRKT
+%%
+%% This could actually either be
+%% a) a list of contextAuditProperties:
+%% contextAuditProperties *(COMMA contextAuditProperties)
+%% b) a indAudcontextAttrDescriptor
+%% But since b) actually has the same content as a) with
+%% the extra ContextAttrToken, there does not seem to be any
+%% reason for using it.
+enc_ContextAttrAuditRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE,
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = [],
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = Top,
+ emergency = Em,
+ priority = Prio,
+ iepscallind = Ieps,
+ contextPropAud = CPA,
+ selectpriority = SPrio,
+ selectemergency = SEm,
+ selectiepscallind = SIeps,
+ selectLogic = SL}, State) ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+ {[Em], fun('NULL', _) -> ?EmergencyToken end},
+ {[Prio], fun('NULL', _) -> ?PriorityToken end},
+ {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+ {CPA, fun enc_IndAudPropertyParm/2},
+ enc_ContextAttrAuditRequest_selectpriority(SPrio, State),
+ enc_ContextAttrAuditRequest_selectemergency(SEm, State),
+ enc_ContextAttrAuditRequest_selectiepscallind(SIeps, State),
+ enc_ContextAttrAuditRequest_selectLogic(SL, State)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectpriority(SPrio, _State) ->
+ {[SPrio], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectemergency(SEm, _State) ->
+ {[SEm], fun(X,S) -> enc_emergencyValue(X, S) end}.
+
+enc_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectiepscallind(SEm, _State) ->
+ {[SEm], fun(X,S) -> enc_iepsValue(X, S) end}.
+
+enc_ContextAttrAuditRequest_selectLogic(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectLogic({andAUDITSelect, 'NULL'}, _State) ->
+ {[], dummy}; % This is default so, there is no reason to add it
+enc_ContextAttrAuditRequest_selectLogic({orAUDITSelect, 'NULL'}, _State) ->
+ {[?OrAUDITselectToken], fun(Elem, _) -> Elem end}.
+
+enc_emergencyValue(true, _) ->
+ [?EmergencyValueToken,?EQUAL,?EmergencyToken];
+enc_emergencyValue(_, _) ->
+ [?EmergencyValueToken,?EQUAL,?EmergencyOffToken].
+
+
+%% enc_IndAudContextAttrDescriptor(
+%% #'ContextAttrAuditRequest'{topology = Top,
+%% emergency = Em,
+%% priority = Prio,
+%% iepscallind = Ieps,
+%% contextPropAud = CPA,
+%% selectpriority = SelPrio,
+%% selectemergency = SelEm,
+%% selectiepscallind = SelIeps,
+%% selectLogic = SelLog}, State) ->
+%% [
+%% ?ContextAttrToken,
+%% ?LBRKT_INDENT(State),
+%% enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+%% {[Em], fun('NULL', _) -> ?EmergencyToken end},
+%% {[Prio], fun('NULL', _) -> ?PriorityToken end},
+%% {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+%% {CPA, fun enc_IndAudPropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% ?RBRKT_INDENT(State)
+%% ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+%% d("enc_Command -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+%% d("enc_CommandReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = asn1_NOVALUE, % OPTIONAL
+ topologyDirectionExtension = asn1_NOVALUE % OPTIONAL
+ }, State) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = SID, % OPTIONAL
+ topologyDirectionExtension = asn1_NOVALUE}, % OPTIONAL
+ State) when (SID =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_StreamID(SID, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = asn1_NOVALUE, % OPTIONAL
+ topologyDirectionExtension = TDE}, % OPTIONAL
+ State) when (TDE =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirectionExtension(TDE, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = SID, % OPTIONAL
+ topologyDirectionExtension = TDE}, % OPTIONAL
+ State) when (SID =/= asn1_NOVALUE) andalso (TDE =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_StreamID(SID, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirectionExtension(TDE, State)
+ ].
+
+enc_TopologyDirection(bothway, _State) ->
+ ?BothwayToken;
+enc_TopologyDirection(isolate, _State) ->
+ ?IsolateToken;
+enc_TopologyDirection(oneway, _State) ->
+ ?OnewayToken.
+
+enc_TopologyDirectionExtension(onewayexternal, _State) ->
+ ?OnewayExternalToken;
+enc_TopologyDirectionExtension(onewayboth, _State) ->
+ ?OnewayBothToken.
+
+enc_iepsValue(Val, _State) ->
+ [
+ ?IEPSToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+
+
+enc_AmmRequest(#'AmmRequest'{terminationID = TIDs,
+ descriptors = Ds}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ enc_opt_brackets(
+ enc_list([{Ds, fun enc_ammDescriptor/2}], ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ statisticsDescriptor -> enc_StatisticsDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = []}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(#'SubtractRequest'{terminationID = TIDs,
+ auditDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_SubtractRequest(#'SubtractRequest'{terminationID = TIDs,
+ auditDescriptor = AD},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = [TID|_] = TIDList},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = TIDList},
+ _State) ->
+ error({invalid_terminationID, TID, TIDList});
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList([TID], State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = [TID|_] = TIDList},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDList, State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = _AD,
+ terminationIDList = TIDList},
+ _State) ->
+ error({invalid_terminationID, TID, TIDList}).
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+%% d("enc_AuditReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDList(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ auditResultTermList ->
+ enc_TermListAuditResult(Val, State);
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+%% This is actually the same as AuditResult with the exception
+%% that instead of terminationID we have terminationIDList.
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p", [TIDList]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = []}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p", [TIDList]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = TAR}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p"
+%% "~n TAR: ~p", [TIDList, TAR]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State),
+ case lists:flatten(enc_TerminationAudit(TAR, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor(asn1_NOVALUE) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor([]) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = asn1_NOVALUE}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({oneStream, Val}, State) ->
+ enc_IndAudStreamParms(Val, State);
+enc_IndAudMediaDescriptor_streams({multiStream, Val}, State) ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+enc_IndAudMediaDescriptor_streams({Tag, _Val}, _State) ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag}).
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL',
+ serviceStateSel = asn1_NOVALUE},
+ _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = SSS},
+ State) when (SSS =/= asn1_NOVALUE) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_serviceState(SSS, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = asn1_NOVALUE},
+ _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = asn1_NOVALUE},
+ State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudStreamParms(
+ #'IndAudStreamParms'{localControlDescriptor = LCD,
+ localDescriptor = LD,
+ remoteDescriptor = RD,
+ statisticsDescriptor = SD}, State) ->
+ [
+ enc_list([{[LCD], fun enc_IndAudLocalControlDescriptor/2},
+ {[LD], fun enc_remoteDescriptor/2},
+ {[RD], fun enc_localDescriptor/2},
+ {[SD], fun enc_IndAudStatisticsDescriptor/2}],
+ ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(
+ #'IndAudLocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PP,
+ streamModeSel = asn1_NOVALUE}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun('NULL', _) -> ?ModeToken end},
+ {[RV], fun('NULL', _) -> ?ReservedValueToken end},
+ {[RG], fun('NULL', _) -> ?ReservedGroupToken end},
+ {PP, fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudLocalControlDescriptor(
+ #'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PP,
+ streamModeSel = SMS}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[RV], fun('NULL', _) -> ?ReservedValueToken end},
+ {[RG], fun('NULL', _) -> ?ReservedGroupToken end},
+ { PP, fun enc_IndAudPropertyParm/2},
+ {[SMS], fun enc_StreamMode/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name, propertyParms = PP},
+ State) ->
+ [
+ enc_list([{[Name], fun enc_PkgdName/2},
+ {[PP], fun enc_PropertyParm/2}], State)
+ ].
+
+enc_IndAudMediaDescriptor_multiStream(Val, State) when is_list(Val) ->
+ [
+ enc_list([{Val, fun enc_IndAudStreamDescriptor/2}], State)
+ ];
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID}, State) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventStream, ID}, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(
+ #'IndAudEventsDescriptor'{requestID = asn1_NOVALUE,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ ?EventsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventsDescriptor(
+ #'IndAudEventsDescriptor'{requestID = RID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(asn1_NOVALUE, _State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(_State),
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE,
+ signalRequestID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ];
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = SID,
+ signalRequestID = SRID}, State) ->
+ [
+ enc_SignalName(SignalName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_StreamID/2},
+ {[SRID], fun enc_sigRequestID/2}],
+ State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = asn1_NOVALUE},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State)
+ ];
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = SL},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(SL, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit', Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([Mand | Opt], State) ->
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+%% d("enc_AuditReturnParameter -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+%% d("enc_AuditReturnParameter -> entry with"
+%% "~n List: ~p", [List]),
+ enc_list([{List, fun enc_auditReturnItem/2}], State).
+
+
+enc_NotifyRequest(#'NotifyRequest'{terminationID = TIDs,
+ observedEventsDescriptor = OED,
+ errorDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_NotifyRequest(#'NotifyRequest'{terminationID = TIDs,
+ observedEventsDescriptor = OED,
+ errorDescriptor = ED}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State)),
+ ?COMMA,
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(#'NotifyReply'{terminationID = TIDs,
+ errorDescriptor = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_NotifyReply(#'NotifyReply'{terminationID = TIDs,
+ errorDescriptor = ED}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ObservedEventsDescriptor(
+ #'ObservedEventsDescriptor'{requestId = RID,
+ observedEventLst = OEL}, State) ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEvents(OEL, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEvents([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(#'ObservedEvent'{eventName = EN,
+ streamID = SID,
+ eventParList = EPL,
+ timeNotation = asn1_NOVALUE}, State) ->
+ [
+ ?LWSP,
+ enc_EventName(EN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ { EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ];
+enc_ObservedEvent(#'ObservedEvent'{eventName = EN,
+ streamID = SID,
+ eventParList = EPL,
+ timeNotation = TN}, State) ->
+ [
+ enc_TimeNotation(TN, State),
+ ?LWSP,
+ ?COLON,
+ ?LWSP,
+ enc_EventName(EN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName', Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(
+ #'ServiceChangeRequest'{terminationID = TIDs,
+ serviceChangeParms = Parms}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(
+ #'ServiceChangeReply'{terminationID = TIDs,
+ serviceChangeResult = Res}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ enc_ServiceChangeResult(Res, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult', Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({errorDescriptor, Val}, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ServiceChangeResult({serviceChangeResParms, Val}, State) ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_ServiceChangeResult({Tag, _}, _State) ->
+ error({invalid_ServiceChangeResult_tag, Tag}).
+
+%% %% Required length of termination ID list is 1
+%% enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+%% enc_TerminationIDList1(Val, State);
+%% enc_TerminationIDList1([Singleton], State) ->
+%% enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDList({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList(Val, State);
+enc_TerminationIDList([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDList(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_termIDList({'TerminationIDList',Val}, State) ->
+ enc_termIDList(Val, State);
+enc_termIDList([Singleton], State) ->
+ enc_TerminationID(Singleton, State);
+enc_termIDList(TidList, State)
+ when is_list(TidList) andalso (length(TidList) > 1) ->
+%% d("enc_termIDList -> entry with"
+%% "~n TidList: ~p", [TidList]),
+ State2 = ?INC_INDENT(State),
+ [
+ ?LSBRKT_INDENT(State),
+ enc_list([{TidList, fun enc_TerminationID/2}], State2),
+ ?RSBRKT_INDENT(State)
+ ].
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[TSD], fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2},
+ {[Val#'StreamParms'.statisticsDescriptor],
+ fun enc_StatisticsDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name =:= "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+%% d("enc_PropertyParm -> entry with"
+%% "~n Val: ~p", [Val]),
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+%% d("enc_PropertyParmValues -> entry with"
+%% "~n Single: ~p", [Single]),
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+%% d("enc_PropertyParmValues -> entry with"
+%% "~n Single: ~p"
+%% "~n Rel: ~p", [Single, Rel]),
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EQUAL,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EQUAL,
+ ?LSBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RSBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDList(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []}, _State) ->
+ [
+ ?EventsToken
+ ];
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = RID,
+ eventList = Evs}, State)
+ when (RID =/= asn1_NOVALUE) andalso (Evs =/= []) ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_RequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = RID,
+ eventList = Evs}, _State) ->
+ error({invalid_EventsDescriptor, RID, Evs}).
+
+enc_RequestedEvent(#'RequestedEvent'{pkgdName = N,
+ streamID = asn1_NOVALUE,
+ eventAction = asn1_NOVALUE,
+ evParList = []}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+enc_RequestedEvent(#'RequestedEvent'{pkgdName = N,
+ streamID = SID,
+ eventAction = EA,
+ evParList = EPL}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_requestedActions(EA)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+decompose_requestedActions(
+ #'RequestedActions'{keepActive = asn1_NOVALUE,
+ eventDM = asn1_NOVALUE,
+ secondEvent = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE,
+ notifyBehaviour = asn1_NOVALUE,
+ resetEventsDescriptor = asn1_NOVALUE}) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of
+%% - KeepActiveToken
+%% - notifyBehaviour
+%% - eventDM
+%% - ResetEventsDescriptor
+%% - eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (KA =/= true) andalso ((SD =/= asn1_NOVALUE) andalso (SD =/= [])) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED}) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ].
+
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso (is_list(Evs) andalso (Evs =/= [])) ->
+ %% d("enc_embedFirst -> entry with"
+ %% "~n RID: ~p"
+ %% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+ %% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+enc_notifyBehaviour({notifyImmediate, 'NULL'}, _State) ->
+ [?NotifyImmediateToken];
+enc_notifyBehaviour({notifyRegulated, Val}, State) ->
+ enc_RegulatedEmbeddedDescriptor(Val, State);
+enc_notifyBehaviour({neverNotify, 'NULL'}, _State) ->
+ [?NeverNotifyToken];
+enc_notifyBehaviour({Tag, Val}, _State) ->
+ error({invalid_notifyBehaviour, Tag, Val}).
+
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE}, _State) ->
+ [
+ ?NotifyRegulatedToken
+ ];
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SE,
+ signalsDescriptor = asn1_NOVALUE}, State) ->
+ [
+ ?NotifyRegulatedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedNoSig(SE, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SE,
+ signalsDescriptor = SD}, State) ->
+ [
+ ?NotifyRegulatedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedWithSig({SE, SD}, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_RegulatedEmbeddedDescriptor(Val, _State) ->
+ error({invalid_RegulatedEmbeddedDescriptor, Val}).
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = asn1_NOVALUE,
+ eventAction = asn1_NOVALUE,
+ evParList = []}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ eventAction = EA,
+ evParList = EPL}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%%
+%% This in the ABNF:
+%% at-most-once each of
+%% - KeepActiveToken
+%% - notifyBehaviour
+%% - eventDM
+%% - ResetEventsDescriptor
+%% - eventStream
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = asn1_NOVALUE,
+ eventDM = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE,
+ notifyBehaviour = asn1_NOVALUE,
+ resetEventsDescriptor = asn1_NOVALUE}) ->
+ [];
+
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (KA =/= true) andalso ((SD =/= asn1_NOVALUE) andalso (SD =/= [])) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[SD], fun enc_embedSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+decompose_secondRequestedActions(SRA) ->
+ error({invalid_SecondRequestedActions, SRA}).
+
+enc_embedSig(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EvSpecs, State)
+ when is_list(EvSpecs) andalso (length(EvSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EvSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EvSpecs, _State) ->
+ error({bad_eventSpecs, EvSpecs}).
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = N,
+ streamID = asn1_NOVALUE,
+ eventParList = []}, State) ->
+ [
+ enc_EventName(N, State)
+ ];
+enc_eventSpec(#'EventSpec'{eventName = N,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(N, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2}, {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(SigRequests, State) when is_list(SigRequests) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{SigRequests, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(#'Signal'{signalName = SN,
+ streamID = SID,
+ sigType = ST,
+ duration = Du,
+ notifyCompletion = NC,
+ keepActive = KA,
+ sigParList = SPL,
+ direction = Di,
+ requestID = RID,
+ intersigDelay = ISD}, State) ->
+ [
+ enc_SignalName(SN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_sigStream/2},
+ {[ST], fun enc_sigSignalType/2},
+ {[Du], fun enc_sigDuration/2},
+ {[NC], fun enc_notifyCompletion/2},
+ {[KA], fun enc_keepActive/2},
+ {SPL, fun enc_sigOther/2},
+ {[Di], fun enc_SignalDirection/2},
+ {[RID], fun enc_sigRequestID/2},
+ {[ISD], fun enc_sigIntsigDelay/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken;
+ onIteration -> ?IterationToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_SignalDirection({'SignalDirection', Val}, State) ->
+ enc_SignalDirection(Val, State);
+enc_SignalDirection(Val, _State) ->
+ [
+ ?DirectionToken,
+ ?EQUAL,
+ case Val of
+ internal -> ?InternalToken;
+ external -> ?ExternalToken;
+ both -> ?BothToken
+ end
+ ].
+
+enc_sigRequestID(Val, State) ->
+ [
+ ?RequestIDToken,
+ ?EQUAL,
+ enc_RequestID(Val, State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_sigIntsigDelay(Val, State) ->
+ [
+ ?IntsigDelayToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = [],
+ durationTimer = asn1_NOVALUE}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2},
+ {[Val#'ServiceChangeParm'.serviceChangeIncompleteFlag],
+ fun('NULL', _) -> ?ServiceChangeIncompleteToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken;
+ _ ->
+ error({invalid_ServiceChangeMethod, Val})
+
+ end
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that the string must contain at least one
+%% BUGBUG: char. This violation of is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+%% d("enc_Value -> entry with"
+%% "~n String: ~p", [String]),
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+%% d("enc_Value -> 0"),
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+%% d("enc_Value -> false"),
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+%% d("enc_Value -> true"),
+ [String]
+ end.
+
+%% needs_quoting(String) ->
+%% case quoted_string_count(String, 0, true) of
+%% {_, 0} ->
+%% true;
+%% {false, _} ->
+%% true;
+%% {true, _} ->
+%% false
+%% end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+%% d("quoted_string_count -> entry with"
+%% "~n H: ~p"
+%% "~n Classified H: ~p"
+%% "~n Count: ~p"
+%% "~n IsSafe: ~p", [H, ?classify_char(H), Count, IsSafe]),
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+%% enc_list(asn1_NOVALUE, _State) ->
+%% [];
+%% enc_list([], _State) ->
+%% [];
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invalid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(get(dbg), F, A).
+%% d(true, F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
+
diff --git a/lib/megaco/src/text/megaco_text_gen_v1.hrl b/lib/megaco/src/text/megaco_text_gen_v1.hrl
new file mode 100644
index 0000000000..b150c9ba58
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_v1.hrl
@@ -0,0 +1,2404 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State),
+ ?INC_INDENT(State),
+ enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res},
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res}, State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(Val, State)
+ when is_record(Val, 'ActionRequest') ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Val#'ActionRequest'.contextId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ActionRequest'.contextAttrAuditReq],
+ fun enc_ContextAttrAuditRequest/2}] ++
+ decompose_ContextRequest(Val#'ActionRequest'.contextRequest) ++
+ [{Val#'ActionRequest'.commandRequests,
+ fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State) ->
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+decompose_ContextRequest(asn1_NOVALUE) ->
+ [{[], dummy}] ;
+decompose_ContextRequest(Val)
+ when is_record(Val, 'ContextRequest') ->
+ OptPriority =
+ case Val#'ContextRequest'.priority of
+ asn1_NOVALUE -> {[], dummy};
+ Prio -> {[Prio], fun enc_priority/2}
+ end,
+ OptEmergency =
+ case Val#'ContextRequest'.emergency of
+ asn1_NOVALUE -> {[], dummy};
+ false -> {[], dummy};
+ true -> {[?EmergencyToken], fun(Elem, _) -> Elem end}
+ end,
+ OptTopologyReq =
+ case Val#'ContextRequest'.topologyReq of
+ asn1_NOVALUE ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', asn1_NOVALUE} ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', List} ->
+ {List, fun enc_TopologyRequest/2};
+ List ->
+ {[List], fun enc_TopologyRequest/2}
+ end,
+ [OptPriority, OptEmergency, OptTopologyReq].
+
+enc_priority(Val, State) ->
+ [
+ ?PriorityToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_ContextAttrAuditRequest(Val, State)
+ when is_record(Val, 'ContextAttrAuditRequest') ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ContextAttrAuditRequest'.topology],
+ fun('NULL', _) -> ?TopologyToken end},
+ {[Val#'ContextAttrAuditRequest'.emergency],
+ fun('NULL', _) -> ?EmergencyToken end},
+ {[Val#'ContextAttrAuditRequest'.priority],
+ fun('NULL', _) -> ?PriorityToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}],?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(Val, State)
+ when is_record(Val, 'TopologyRequest') ->
+ [
+ fun(S) ->
+ [
+ enc_TerminationID(Val#'TopologyRequest'.terminationFrom, S),
+ ?COMMA_INDENT(S),
+ enc_TerminationID(Val#'TopologyRequest'.terminationTo, S),
+ ?COMMA_INDENT(S),
+ case Val#'TopologyRequest'.topologyDirection of
+ bothway -> ?BothwayToken;
+ isolate -> ?IsolateToken;
+ oneway -> ?OnewayToken
+ end
+ ]
+ end(?INC_INDENT(State))
+ ].
+
+enc_AmmRequest(Val, State)
+ when is_record(Val, 'AmmRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'AmmRequest'.terminationID, State),
+ enc_opt_brackets(
+ enc_list([{Val#'AmmRequest'.descriptors, fun enc_ammDescriptor/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(Val, State)
+ when is_record(Val, 'SubtractRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'SubtractRequest'.terminationID, State),
+ case Val#'SubtractRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_AuditRequest(Val, State)
+ when is_record(Val, 'AuditRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1([Val#'AuditRequest'.terminationID], State),
+ case Val#'AuditRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDListN(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = []},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+enc_TerminationAudit({'TerminationAudit',Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([], _State) ->
+ [];
+enc_TerminationAudit([Mand | Opt], State) ->
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State),
+ enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({unknown_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+ enc_list([{List, fun enc_auditReturnItem/2}], ?INC_INDENT(State)).
+
+
+enc_NotifyRequest(Val, State)
+ when is_record(Val, 'NotifyRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'NotifyRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ %% BUGBUG: Mismatch between ASN.1 and ABNF
+ %% BUGBUG: The following ought to be a 'choice'
+ case Val#'NotifyRequest'.errorDescriptor of
+ asn1_NOVALUE ->
+ OED = Val#'NotifyRequest'.observedEventsDescriptor,
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State));
+ ErrorDescr ->
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State))
+ end,
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(Val, State)
+ when is_record(Val, 'NotifyReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ case Val#'NotifyReply'.terminationID of
+ asn1_NOVALUE ->
+ error(asn1_not_compliant_with_abnf);
+ TermId ->
+ enc_TerminationIDList1(TermId, State)
+ end,
+ case Val#'NotifyReply'.errorDescriptor of
+ asn1_NOVALUE ->
+ [];
+ ErrorDescr ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_ObservedEventsDescriptor(Val, State)
+ when is_record(Val, 'ObservedEventsDescriptor') ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(Val#'ObservedEventsDescriptor'.requestId, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEventsDescriptors(Val#'ObservedEventsDescriptor'.observedEventLst, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEventsDescriptors([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(Val, State)
+ when is_record(Val, 'ObservedEvent') ->
+ [
+ case Val#'ObservedEvent'.timeNotation of
+ asn1_NOVALUE ->
+ [];
+ TimeStamp ->
+ [
+ enc_TimeNotation(TimeStamp, State),
+ ?LWSP,
+ ?COLON
+ ]
+ end,
+ ?LWSP,
+ enc_EventName(Val#'ObservedEvent'.eventName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'ObservedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'ObservedEvent'.eventParList, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName',Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(Val, State)
+ when is_record(Val, 'ServiceChangeRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Val#'ServiceChangeRequest'.serviceChangeParms,
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(Val, State)
+ when is_record(Val, 'ServiceChangeReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeReply'.terminationID, State),
+ enc_ServiceChangeResult(Val#'ServiceChangeReply'.serviceChangeResult, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult',Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({Tag, Val}, State) ->
+ case Tag of
+ errorDescriptor ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ serviceChangeResParms ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+ _ ->
+ error({invalid_ServiceChangeResult_tag, Tag})
+ end.
+
+%% Required length of termination ID list is 1
+enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList1(Val, State);
+enc_TerminationIDList1([Singleton], State) ->
+ enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDListN({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDListN(Val, State);
+enc_TerminationIDListN([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDListN(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(Val, State)
+ when is_record(Val, 'MediaDescriptor') ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'MediaDescriptor'.termStateDescr],
+ fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Val#'MediaDescriptor'.streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. <When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name =:= "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EqualToken,
+ ?LBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RBRKT
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDListN(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(Val, State)
+ when is_record(Val, 'EventsDescriptor') ->
+ #'EventsDescriptor'{requestID = RequestId,
+ eventList = Events} = Val,
+ if
+ RequestId == asn1_NOVALUE, Events == [] ->
+ [
+ ?EventsToken
+ ];
+
+ RequestId =/= asn1_NOVALUE, Events =/= [] ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RequestId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Events, fun enc_RequestedEvent/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end.
+
+enc_RequestedEvent(Val, State)
+ when is_record(Val, 'RequestedEvent') ->
+ PkgdName = ?META_ENC(event, Val#'RequestedEvent'.pkgdName),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'RequestedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'RequestedEvent'.evParList, fun enc_eventOther/2} |
+ decompose_requestedActions(Val#'RequestedEvent'.eventAction)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of KeepActiveToken , eventDM and eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (KA =/= true) andalso
+ (SD =/= asn1_NOVALUE) andalso
+ (SD /= []) ->
+% d("decompose_requestedActions -> entry with"
+% "~n EDM: ~p"
+% "~n SE: ~p"
+% "~n SD: ~p", [EDM, SE, SD]),
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD}) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ].
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso is_list(Evs) andalso (Evs =/= []) ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+ [
+ ?EventsToken
+ ].
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ evParList = EPL,
+ eventAction = EA}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list(
+ [{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(Val)
+ when is_record(Val, 'SecondRequestedActions') ->
+ [
+ {[Val#'SecondRequestedActions'.keepActive],
+ fun enc_keepActive/2},
+ {[Val#'SecondRequestedActions'.eventDM],
+ fun enc_EventDM/2},
+ {[Val#'SecondRequestedActions'.signalsDescriptor],
+ fun enc_embeddedSignalsDescriptor/2}
+ ].
+
+enc_embeddedSignalsDescriptor(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EventSpecs, State)
+ when is_list(EventSpecs) andalso (length(EventSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EventSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EventSpecs, _State) ->
+ error({bad_eventSpecs, EventSpecs}).
+
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = Name,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(Name, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(List, State) when is_list(List) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(Val, State)
+ when is_record(Val, 'Signal') ->
+ [
+ enc_SignalName(Val#'Signal'.signalName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'Signal'.streamID], fun enc_sigStream/2},
+ {[Val#'Signal'.sigType], fun enc_sigSignalType/2},
+ {[Val#'Signal'.duration], fun enc_sigDuration/2},
+ {[Val#'Signal'.notifyCompletion], fun enc_notifyCompletion/2},
+ {[Val#'Signal'.keepActive], fun enc_keepActive/2},
+ {Val#'Signal'.sigParList, fun enc_sigOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+ mpl = [],
+ nonStandardData = asn1_NOVALUE},
+ State) ->
+ [
+ ?ModemToken,
+ ?EQUAL,
+ enc_ModemType(Val, State)
+ ];
+enc_ModemDescriptor(Val, State)
+ when is_record(Val, 'ModemDescriptor') ->
+ [
+ ?ModemToken,
+ ?LSBRKT,
+ enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+ ?RSBRKT,
+ enc_opt_brackets(
+ enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+ ?INC_INDENT(State)),
+ State)
+ %% BUGBUG: Is PropertyParm == NAME parmValue?
+ ].
+
+
+enc_ModemType({'ModemType',Val}, State)->
+ enc_ModemType(Val, State);
+enc_ModemType(Val, _State) ->
+ %% BUGBUG: Does not handle extensionParameter
+ case Val of
+ v18 -> ?V18Token;
+ v22 -> ?V22Token;
+ v22bis -> ?V22bisToken;
+ v32 -> ?V32Token;
+ v32bis -> ?V32bisToken;
+ v34 -> ?V34Token;
+ v90 -> ?V90Token;
+ v91 -> ?V91Token;
+ synchISDN -> ?SynchISDNToken
+ end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = []}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken
+ end
+ %% BUGBUG: extension
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invlid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+% d(F) ->
+% d(F, []).
+
+% d(F, A) ->
+% %% d(get(dbg), F, A).
+% d(true, F, A).
+
+% d(true, F, A) ->
+% io:format("DBG:~p:" ++ F ++ "~n", [?MODULE|A]);
+% d(_, _, _) ->
+% ok.
diff --git a/lib/megaco/src/text/megaco_text_gen_v2.hrl b/lib/megaco/src/text/megaco_text_gen_v2.hrl
new file mode 100644
index 0000000000..6cfcac8664
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_v2.hrl
@@ -0,0 +1,2794 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V2 Megaco/H.248 text messages from internal form
+%% The following was changed:
+%% - MuxType (Nx64kToken)
+%% - auditItem (terminationAudit)
+%% - serviceChangeParm (auditItem)
+%%
+%% The following was added:
+%% - All IndAud stuff
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) == 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res},
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res}, State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(Val, State)
+ when is_record(Val, 'ActionRequest') ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Val#'ActionRequest'.contextId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ActionRequest'.contextAttrAuditReq],
+ fun enc_ContextAttrAuditRequest/2}] ++
+ decompose_ContextRequest(Val#'ActionRequest'.contextRequest) ++
+ [{Val#'ActionRequest'.commandRequests,
+ fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when (ED =/= asn1_NOVALUE) ->
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+decompose_ContextRequest(asn1_NOVALUE) ->
+ [{[], dummy}] ;
+decompose_ContextRequest(Val)
+ when is_record(Val, 'ContextRequest') ->
+ OptPriority =
+ case Val#'ContextRequest'.priority of
+ asn1_NOVALUE -> {[], dummy};
+ Prio -> {[Prio], fun enc_priority/2}
+ end,
+ OptEmergency =
+ case Val#'ContextRequest'.emergency of
+ asn1_NOVALUE -> {[], dummy};
+ false -> {[?EmergencyOffToken], fun(Elem, _) -> Elem end};
+ true -> {[?EmergencyToken], fun(Elem, _) -> Elem end}
+ end,
+ OptTopologyReq =
+ case Val#'ContextRequest'.topologyReq of
+ asn1_NOVALUE ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', asn1_NOVALUE} ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', List} ->
+ {List, fun enc_TopologyRequest/2};
+ List ->
+ {[List], fun enc_TopologyRequest/2}
+ end,
+ [OptPriority, OptEmergency, OptTopologyReq].
+
+enc_priority(Val, State) ->
+ [
+ ?PriorityToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_ContextAttrAuditRequest(Val, State)
+ when is_record(Val, 'ContextAttrAuditRequest') ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ContextAttrAuditRequest'.topology],
+ fun('NULL', _) -> ?TopologyToken end},
+ {[Val#'ContextAttrAuditRequest'.emergency],
+ fun('NULL', _) -> ?EmergencyToken end},
+ {[Val#'ContextAttrAuditRequest'.priority],
+ fun('NULL', _) -> ?PriorityToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}],?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir,
+ streamID = asn1_NOVALUE},
+ State) ->
+ [
+ fun(S) ->
+ [
+ enc_TerminationID(From, S),
+ ?COMMA_INDENT(S),
+ enc_TerminationID(To, S),
+ ?COMMA_INDENT(S),
+ case Dir of
+ bothway -> ?BothwayToken;
+ isolate -> ?IsolateToken;
+ oneway -> ?OnewayToken
+ end
+ ]
+ end(?INC_INDENT(State))
+ ];
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir,
+ streamID = SID},
+ State) ->
+ [
+ fun(S) ->
+ [
+ enc_TerminationID(From, S),
+ ?COMMA_INDENT(S),
+ enc_TerminationID(To, S),
+ ?COMMA_INDENT(S),
+ case Dir of
+ bothway -> ?BothwayToken;
+ isolate -> ?IsolateToken;
+ oneway -> ?OnewayToken
+ end,
+ ?COMMA_INDENT(S),
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, S)
+ ]
+ end(?INC_INDENT(State))
+ ].
+
+enc_AmmRequest(Val, State)
+ when is_record(Val, 'AmmRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'AmmRequest'.terminationID, State),
+ enc_opt_brackets(
+ enc_list([{Val#'AmmRequest'.descriptors, fun enc_ammDescriptor/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(Val, State)
+ when is_record(Val, 'SubtractRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'SubtractRequest'.terminationID, State),
+ case Val#'SubtractRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_AuditRequest(Val, State)
+ when is_record(Val, 'AuditRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1([Val#'AuditRequest'.terminationID], State),
+ case Val#'AuditRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDListN(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+%% The ASN.1 does not limit to just one of termStateDescr or streams,
+%% but the ABNF seams to do that...
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Val}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = Val,
+ streams = asn1_NOVALUE},
+ State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({Tag, Val}, State) ->
+ case Tag of
+ oneStream ->
+ enc_IndAudStreamParms(Val, State);
+ multiStream ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+ _ ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag})
+ end.
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL'}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE}, State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = Val,
+ localDescriptor = asn1_NOVALUE,
+ remoteDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ enc_IndAudLocalControlDescriptor(Val, ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(Val, State)
+ when is_record(Val, 'IndAudLocalControlDescriptor') ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'IndAudLocalControlDescriptor'.streamMode],
+ fun('NULL', _) -> ?ModeToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveValue],
+ fun('NULL', _) -> ?ReservedValueToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveGroup],
+ fun('NULL', _) -> ?ReservedGroupToken end},
+ {Val#'IndAudLocalControlDescriptor'.propertyParms,
+ fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = PkgdName}, State) ->
+ enc_PkgdName(PkgdName, State).
+
+enc_IndAudMediaDescriptor_multiStream([Val], State) ->
+ [
+ enc_IndAudStreamDescriptor(Val, ?INC_INDENT(State))
+ ];
+enc_IndAudMediaDescriptor_multiStream(Vals, _State) when is_list(Vals) ->
+ error({invalid_IndAudMediaDescriptor_multiStream_length, Vals});
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventBufferDescriptor') ->
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID} = Val,
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventsDescriptor') ->
+ #'IndAudEventsDescriptor'{requestID = ReqID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE} = Val,
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(ReqID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = Parm},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(Parm, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit',Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([], _State) ->
+ [];
+enc_TerminationAudit([Mand | Opt], State) ->
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+ enc_list([{List, fun enc_auditReturnItem/2}], ?INC_INDENT(State)).
+
+
+enc_NotifyRequest(Val, State)
+ when is_record(Val, 'NotifyRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'NotifyRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ %% BUGBUG: Mismatch between ASN.1 and ABNF
+ %% BUGBUG: The following ought to be a 'choice'
+ case Val#'NotifyRequest'.errorDescriptor of
+ asn1_NOVALUE ->
+ OED = Val#'NotifyRequest'.observedEventsDescriptor,
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State));
+ ErrorDescr ->
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State))
+ end,
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(Val, State)
+ when is_record(Val, 'NotifyReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ case Val#'NotifyReply'.terminationID of
+ asn1_NOVALUE ->
+ error(asn1_not_compliant_with_abnf);
+ TermId ->
+ enc_TerminationIDList1(TermId, State)
+ end,
+ case Val#'NotifyReply'.errorDescriptor of
+ asn1_NOVALUE ->
+ [];
+ ErrorDescr ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_ObservedEventsDescriptor(Val, State)
+ when is_record(Val, 'ObservedEventsDescriptor') ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(Val#'ObservedEventsDescriptor'.requestId, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEventsDescriptors(Val#'ObservedEventsDescriptor'.observedEventLst, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEventsDescriptors([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(Val, State)
+ when is_record(Val, 'ObservedEvent') ->
+ [
+ case Val#'ObservedEvent'.timeNotation of
+ asn1_NOVALUE ->
+ [];
+ TimeStamp ->
+ [
+ enc_TimeNotation(TimeStamp, State),
+ ?LWSP,
+ ?COLON
+ ]
+ end,
+ ?LWSP,
+ enc_EventName(Val#'ObservedEvent'.eventName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'ObservedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'ObservedEvent'.eventParList, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName',Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(Val, State)
+ when is_record(Val, 'ServiceChangeRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Val#'ServiceChangeRequest'.serviceChangeParms,
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(Val, State)
+ when is_record(Val, 'ServiceChangeReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeReply'.terminationID, State),
+ enc_ServiceChangeResult(Val#'ServiceChangeReply'.serviceChangeResult, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult',Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({Tag, Val}, State) ->
+ case Tag of
+ errorDescriptor ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ serviceChangeResParms ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+ _ ->
+ error({invalid_ServiceChangeResult_tag, Tag})
+ end.
+
+%% Required length of termination ID list is 1
+enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList1(Val, State);
+enc_TerminationIDList1([Singleton], State) ->
+ enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDListN({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDListN(Val, State);
+enc_TerminationIDListN([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDListN(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(Val, State)
+ when is_record(Val, 'MediaDescriptor') ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'MediaDescriptor'.termStateDescr],
+ fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Val#'MediaDescriptor'.streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name =:= "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EqualToken,
+ ?LBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RBRKT
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDListN(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(Val, State)
+ when is_record(Val, 'EventsDescriptor') ->
+ #'EventsDescriptor'{requestID = RequestId,
+ eventList = Events} = Val,
+ if
+ RequestId == asn1_NOVALUE, Events == [] ->
+ [
+ ?EventsToken
+ ];
+
+ RequestId /= asn1_NOVALUE, Events /= [] ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RequestId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Events, fun enc_RequestedEvent/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end.
+
+enc_RequestedEvent(Val, State)
+ when is_record(Val, 'RequestedEvent') ->
+%% d("enc_RequestedEvent -> entry with"
+%% "~n Val: ~p", [Val]),
+ PkgdName = ?META_ENC(event, Val#'RequestedEvent'.pkgdName),
+%% d("enc_RequestedEvent -> entry with"
+%% "~n PkgdName: ~p", [PkgdName]),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'RequestedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'RequestedEvent'.evParList, fun enc_eventOther/2} |
+ decompose_requestedActions(Val#'RequestedEvent'.eventAction)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of KeepActiveToken , eventDM and eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (KA =/= true) andalso
+ (SD =/= asn1_NOVALUE) andalso
+ (SD =/= []) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n EDM: ~p"
+%% "~n SE: ~p"
+%% "~n SD: ~p", [EDM, SE, SD]),
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n KA: ~p"
+%% "~n EDM: ~p"
+%% "~n SE: ~p", [KA, EDM, SE]),
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD}) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n KA: ~p"
+%% "~n EDM: ~p"
+%% "~n SE: ~p"
+%% "~n SD: ~p", [KA, EDM, SE, SD]),
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ].
+
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+%% d("enc_embedNoSig -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+%% d("enc_embedWithSig -> entry with"
+%% "~n SD: ~p", [SD]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+%% d("enc_embedWithSig -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p"
+%% "~n SD: ~p", [RID, Evs, SD]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+%% d("enc_keepActive -> entry with"
+%% "~n Val: ~p", [Val]),
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+%% d("enc_EventDM -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso is_list(Evs) andalso (Evs =/= []) ->
+%% d("enc_embedFirst -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+%% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ evParList = EPL,
+ eventAction = EA},
+ State) ->
+%% d("enc_SecondRequestedEvent -> entry with"
+%% "~n N: ~p"
+%% "~n SID: ~p"
+%% "~n EPL: ~p"
+%% "~n EA: ~p", [N, SID, EPL, EA]),
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list(
+ [{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(Val)
+ when is_record(Val, 'SecondRequestedActions') ->
+%% d("decompose_secondRequestedActions -> entry with"
+%% "~n Val: ~p", [Val]),
+ [
+ {[Val#'SecondRequestedActions'.keepActive],
+ fun enc_keepActive/2},
+ {[Val#'SecondRequestedActions'.eventDM],
+ fun enc_EventDM/2},
+ {[Val#'SecondRequestedActions'.signalsDescriptor],
+ fun enc_embeddedSignalsDescriptor/2}
+ ].
+
+enc_embeddedSignalsDescriptor(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EventSpecs, State)
+ when is_list(EventSpecs) and (length(EventSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EventSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EventSpecs, _State) ->
+ error({bad_eventSpecs, EventSpecs}).
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = Name,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(Name, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(List, State) when is_list(List) ->
+% d("enc_SignalsDescriptor -> entry with"
+% "~n List: ~p", [List]),
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+% d("enc_SignalsDescriptor -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(Val, State)
+ when is_record(Val, 'Signal') ->
+ [
+ enc_SignalName(Val#'Signal'.signalName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'Signal'.streamID], fun enc_sigStream/2},
+ {[Val#'Signal'.sigType], fun enc_sigSignalType/2},
+ {[Val#'Signal'.duration], fun enc_sigDuration/2},
+ {[Val#'Signal'.notifyCompletion], fun enc_notifyCompletion/2},
+ {[Val#'Signal'.keepActive], fun enc_keepActive/2},
+ {Val#'Signal'.sigParList, fun enc_sigOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = [],
+ durationTimer = asn1_NOVALUE}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken
+ end
+ %% BUGBUG: extension
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invlid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(true, F, A).
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
+
diff --git a/lib/megaco/src/text/megaco_text_gen_v3.hrl b/lib/megaco/src/text/megaco_text_gen_v3.hrl
new file mode 100644
index 0000000000..1c19a4aa8b
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_v3.hrl
@@ -0,0 +1,3457 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V3 Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) and (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) and (Val /= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) == 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) == 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ segmentReply ->
+ enc_SegmentReply(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res,
+ segmentNumber = asn1_NOVALUE,
+ segmentationComplete = asn1_NOVALUE
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ segmentNumber = asn1_NOVALUE,
+ segmentationComplete = asn1_NOVALUE
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ segmentNumber = SegNo,
+ segmentationComplete = asn1_NOVALUE
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?SLASH,
+ enc_SegmentNumber(SegNo, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res,
+ segmentNumber = SegNo,
+ segmentationComplete = 'NULL'
+ },
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?SLASH,
+ enc_SegmentNumber(SegNo, State),
+ ?SLASH,
+ ?SegmentationCompleteToken,
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_SegmentReply({'SegmentReply', SR}, State) ->
+ enc_SegmentReply(SR, State);
+enc_SegmentReply(#'SegmentReply'{transactionId = TID,
+ segmentNumber = SegNo,
+ segmentationComplete = asn1_NOVALUE
+ }, State) ->
+ [
+ ?MessageSegmentToken,
+ ?EQUAL,
+ enc_TransactionId(TID, State),
+ ?SLASH,
+ enc_SegmentNumber(SegNo, State)
+ ];
+enc_SegmentReply(#'SegmentReply'{transactionId = TID,
+ segmentNumber = SegNo,
+ segmentationComplete = 'NULL'
+ }, State) ->
+ [
+ ?MessageSegmentToken,
+ ?EQUAL,
+ enc_TransactionId(TID, State),
+ ?SLASH,
+ enc_SegmentNumber(SegNo, State),
+ ?SLASH,
+ ?SegmentationCompleteToken
+ ];
+enc_SegmentReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_SegmentNumber({'SegmentNumber', SN}, State) ->
+ enc_SegmentNumber(SN, State);
+enc_SegmentNumber(SN, State) ->
+ enc_UINT16(SN, State).
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = asn1_NOVALUE,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = asn1_NOVALUE,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ActionRequest(#'ActionRequest'{contextId = CID,
+ contextRequest = CtxReq,
+ contextAttrAuditReq = CtxAAR,
+ commandRequests = CmdReqs}, State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(CID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[CtxReq], fun enc_ContextRequest/2},
+ {[CtxAAR], fun enc_ContextAttrAuditRequest/2},
+ {CmdReqs, fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ActionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin]; % Already encoded...
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = asn1_NOVALUE,
+ contextReply = asn1_NOVALUE,
+ commandReply = []},
+ State) ->
+%% d("enc_ActionReply -> entry with"
+%% "~n Id: ~p", [Id]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State)
+ ];
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+%% d("enc_ActionReply -> entry with"
+%% "~n Id: ~p"
+%% "~n ED: ~p"
+%% "~n CtxRep: ~p"
+%% "~n CmdRep: ~p", [Id, ED, CtxRep, CmdRep]),
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, [], State)
+ when CtxRep =/= asn1_NOVALUE ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) and (CmdRep =/= []) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(asn1_NOVALUE, asn1_NOVALUE, CmdRep, State)
+ when CmdRep =/= [] ->
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, [], State)
+ when (ED =/= asn1_NOVALUE) and (CtxRep =/= asn1_NOVALUE) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) and (CmdRep =/= []) ->
+ [
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (ED =/= asn1_NOVALUE) and
+ (CtxRep =/= asn1_NOVALUE) and
+ (CmdRep =/= []) ->
+ [
+ enc_ContextRequest(CtxRep, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_list([{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when ED =/= asn1_NOVALUE ->
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+enc_ContextRequest_priority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_priority(Val, _State) ->
+ {[Val], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextRequest_emergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_emergency(true, _State) ->
+ {[?EmergencyToken], fun(Elem, _) -> Elem end};
+enc_ContextRequest_emergency(false, _State) ->
+ {[?EmergencyOffToken], fun(Elem, _) -> Elem end}.
+
+enc_ContextRequest_topologyReq(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ asn1_NOVALUE}, _State) ->
+ {[], dummy};
+enc_ContextRequest_topologyReq({'ContextRequest_topologyReq',
+ List}, _State) ->
+ {List, fun enc_TopologyRequest/2};
+enc_ContextRequest_topologyReq(List, _State) ->
+ {[List], fun enc_TopologyRequest/2}.
+
+enc_ContextRequest_iepscallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_iepscallind(Bool, _State) ->
+ {[Bool], fun enc_iepsValue/2}.
+
+enc_ContextRequest_contextProp(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextProp(Props, _State) ->
+ {[Props], fun(Elem, S) -> enc_contextAttrDescriptor(Elem, contextProps, S) end}.
+
+enc_ContextRequest_contextList(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextRequest_contextList([], _State) ->
+ {[], dummy};
+enc_ContextRequest_contextList(Props, _State) ->
+ {[Props], fun(Elem, S) ->
+ enc_contextAttrDescriptor(Elem, contextList, S)
+ end}.
+
+enc_contextAttrDescriptor([Mand|Opt], contextProps, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ [enc_PropertyParm(Mand, State) |
+ [[?COMMA_INDENT(State), enc_PropertyParm(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ];
+enc_contextAttrDescriptor(CtxIdList, contextList, State) ->
+ [
+ ?ContextAttrToken,
+ ?LBRKT_INDENT(State),
+ enc_contextIdList(CtxIdList, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_contextIdList([Mand|Opt], State) ->
+ State2 = ?INC_INDENT(State),
+ [
+ ?ContextListToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ [enc_ContextID(Mand, State2) |
+ [[?COMMA_INDENT(State2), enc_ContextID(Val, State2)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE,
+ contextList = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = [],
+ iepscallind = asn1_NOVALUE,
+ contextProp = [],
+ contextList = []}, _State) ->
+ [];
+enc_ContextRequest(#'ContextRequest'{priority = Prio,
+ emergency = Em,
+ topologyReq = TR,
+ iepscallind = Ieps,
+ contextProp = CP,
+ contextList = CL}, State) ->
+ [
+ enc_list([enc_ContextRequest_priority(Prio, State),
+ enc_ContextRequest_emergency(Em, State),
+ enc_ContextRequest_topologyReq(TR, State),
+ enc_ContextRequest_iepscallind(Ieps, State),
+ enc_ContextRequest_contextProp(CP, State),
+ enc_ContextRequest_contextList(CL, State)],
+ State)
+ ].
+
+
+%% -- contextAudit --
+%% contextAudit = ContextAuditToken LBRKT
+%% (contextAuditProperties *(COMMA contextAuditProperties)) /
+%% indAudcontextAttrDesscriptor
+%% RBRKT
+%% contextAuditProperties =
+%% (TopologyToken / EmergencyToken / PriorityToken /
+%% IEPSToken / pkgdName / contextAuditSelect)
+%% contextAuditSelect =
+%% priority / emergencyValue / iepsValue /
+%% contextAttrDescriptor / auditSelectLogic
+%% indAudcontextAttrDesscriptor =
+%% ContextAttrToken LBRKT
+%% (contextAuditProperties *(COMMA contextAuditProperties))
+%% RBRKT
+%%
+%% This could actually either be
+%% a) a list of contextAuditProperties:
+%% contextAuditProperties *(COMMA contextAuditProperties)
+%% b) a indAudcontextAttrDescriptor
+%% But since b) actually has the same content as a) with
+%% the extra ContextAttrToken, there does not seem to be any
+%% reason for using it.
+enc_ContextAttrAuditRequest(asn1_NOVALUE, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE,
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ priority = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = [],
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}, _State) ->
+ [];
+enc_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{topology = Top,
+ emergency = Em,
+ priority = Prio,
+ iepscallind = Ieps,
+ contextPropAud = CPA,
+ selectpriority = SPrio,
+ selectemergency = SEm,
+ selectiepscallind = SIeps,
+ selectLogic = SL}, State) ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+ {[Em], fun('NULL', _) -> ?EmergencyToken end},
+ {[Prio], fun('NULL', _) -> ?PriorityToken end},
+ {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+ {CPA, fun enc_IndAudPropertyParm/2},
+ enc_ContextAttrAuditRequest_selectpriority(SPrio, State),
+ enc_ContextAttrAuditRequest_selectemergency(SEm, State),
+ enc_ContextAttrAuditRequest_selectiepscallind(SIeps, State),
+ enc_ContextAttrAuditRequest_selectLogic(SL, State)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ContextAttrAuditRequest_selectpriority(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectpriority(SPrio, _State) ->
+ {[SPrio], fun(X,S) -> [?PriorityToken,?EQUAL,enc_UINT16(X, S)] end}.
+
+enc_ContextAttrAuditRequest_selectemergency(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectemergency(SEm, _State) ->
+ {[SEm], fun(X,S) -> enc_emergencyValue(X, S) end}.
+
+enc_ContextAttrAuditRequest_selectiepscallind(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectiepscallind(SEm, _State) ->
+ {[SEm], fun(X,S) -> enc_iepsValue(X, S) end}.
+
+enc_ContextAttrAuditRequest_selectLogic(asn1_NOVALUE, _State) ->
+ {[], dummy};
+enc_ContextAttrAuditRequest_selectLogic({andAUDITSelect, 'NULL'}, _State) ->
+ {[], dummy}; % This is default so, there is no reason to add it
+enc_ContextAttrAuditRequest_selectLogic({orAUDITSelect, 'NULL'}, _State) ->
+ {[?OrAUDITselectToken], fun(Elem, _) -> Elem end}.
+
+enc_emergencyValue(true, _) ->
+ [?EmergencyValueToken,?EQUAL,?EmergencyToken];
+enc_emergencyValue(_, _) ->
+ [?EmergencyValueToken,?EQUAL,?EmergencyOffToken].
+
+
+%% enc_IndAudContextAttrDescriptor(
+%% #'ContextAttrAuditRequest'{topology = Top,
+%% emergency = Em,
+%% priority = Prio,
+%% iepscallind = Ieps,
+%% contextPropAud = CPA,
+%% selectpriority = SelPrio,
+%% selectemergency = SelEm,
+%% selectiepscallind = SelIeps,
+%% selectLogic = SelLog}, State) ->
+%% [
+%% ?ContextAttrToken,
+%% ?LBRKT_INDENT(State),
+%% enc_list([{[Top], fun('NULL', _) -> ?TopologyToken end},
+%% {[Em], fun('NULL', _) -> ?EmergencyToken end},
+%% {[Prio], fun('NULL', _) -> ?PriorityToken end},
+%% {[Ieps], fun('NULL', _) -> ?IEPSToken end},
+%% {CPA, fun enc_IndAudPropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% ?RBRKT_INDENT(State)
+%% ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+%% d("enc_Command -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+%% d("enc_CommandReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = asn1_NOVALUE, % OPTIONAL
+ topologyDirectionExtension = asn1_NOVALUE % OPTIONAL
+ }, State) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = SID, % OPTIONAL
+ topologyDirectionExtension = asn1_NOVALUE}, % OPTIONAL
+ State) when (SID =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_StreamID(SID, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = asn1_NOVALUE, % OPTIONAL
+ topologyDirectionExtension = TDE}, % OPTIONAL
+ State) when (TDE =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirectionExtension(TDE, State)
+ ];
+enc_TopologyRequest1(
+ #'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = TD,
+ streamID = SID, % OPTIONAL
+ topologyDirectionExtension = TDE}, % OPTIONAL
+ State) when (SID =/= asn1_NOVALUE) and (TDE =/= asn1_NOVALUE) ->
+ [
+ enc_TerminationID(From, State),
+ ?COMMA_INDENT(State),
+ enc_TerminationID(To, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirection(TD, State),
+ ?COMMA_INDENT(State),
+ enc_StreamID(SID, State),
+ ?COMMA_INDENT(State),
+ enc_TopologyDirectionExtension(TDE, State)
+ ].
+
+enc_TopologyDirection(bothway, _State) ->
+ ?BothwayToken;
+enc_TopologyDirection(isolate, _State) ->
+ ?IsolateToken;
+enc_TopologyDirection(oneway, _State) ->
+ ?OnewayToken.
+
+enc_TopologyDirectionExtension(onewayexternal, _State) ->
+ ?OnewayExternalToken;
+enc_TopologyDirectionExtension(onewayboth, _State) ->
+ ?OnewayBothToken.
+
+enc_iepsValue(Val, _State) ->
+ [
+ ?IEPSToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+
+
+enc_AmmRequest(#'AmmRequest'{terminationID = TIDs,
+ descriptors = Ds}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ enc_opt_brackets(
+ enc_list([{Ds, fun enc_ammDescriptor/2}], ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ statisticsDescriptor -> enc_StatisticsDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = []}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = TIDs,
+ terminationAudit = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(#'SubtractRequest'{terminationID = TIDs,
+ auditDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_SubtractRequest(#'SubtractRequest'{terminationID = TIDs,
+ auditDescriptor = AD},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = [TID|_] = TIDList},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = asn1_NOVALUE,
+ terminationIDList = TIDList},
+ _State) ->
+ error({invalid_terminationID, TID, TIDList});
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList([TID], State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = [TID|_] = TIDList},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDList, State),
+ ?LBRKT_INDENT(State),
+ enc_AuditDescriptor(AD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_AuditRequest(#'AuditRequest'{terminationID = TID,
+ auditDescriptor = _AD,
+ terminationIDList = TIDList},
+ _State) ->
+ error({invalid_terminationID, TID, TIDList}).
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+%% d("enc_AuditReply -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDList(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ auditResultTermList ->
+ enc_TermListAuditResult(Val, State);
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+%% This is actually the same as AuditResult with the exception
+%% that instead of terminationID we have terminationIDList.
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p", [TIDList]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = []}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p", [TIDList]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State)
+ ];
+enc_TermListAuditResult(
+ #'TermListAuditResult'{terminationIDList = TIDList,
+ terminationAuditResult = TAR}, State) ->
+%% d("enc_TermListAuditResult -> entry with"
+%% "~n TIDList: ~p"
+%% "~n TAR: ~p", [TIDList, TAR]),
+ [
+ ?EQUAL,
+ enc_termIDList(TIDList, State),
+ case lists:flatten(enc_TerminationAudit(TAR, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = TID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_termIDList([TID], State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor(asn1_NOVALUE) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+% d("enc_AuditDescriptor([]) -> entry"),
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = asn1_NOVALUE}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(
+ #'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(TSD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Streams, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({oneStream, Val}, State) ->
+ enc_IndAudStreamParms(Val, State);
+enc_IndAudMediaDescriptor_streams({multiStream, Val}, State) ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+enc_IndAudMediaDescriptor_streams({Tag, _Val}, _State) ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag}).
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL',
+ serviceStateSel = asn1_NOVALUE},
+ _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = SSS},
+ State) when SSS =/= asn1_NOVALUE ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_serviceState(SSS, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = asn1_NOVALUE},
+ _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE,
+ serviceStateSel = asn1_NOVALUE},
+ State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudStreamParms(
+ #'IndAudStreamParms'{localControlDescriptor = LCD,
+ localDescriptor = LD,
+ remoteDescriptor = RD,
+ statisticsDescriptor = SD}, State) ->
+ [
+ enc_list([{[LCD], fun enc_IndAudLocalControlDescriptor/2},
+ {[LD], fun enc_remoteDescriptor/2},
+ {[RD], fun enc_localDescriptor/2},
+ {[SD], fun enc_IndAudStatisticsDescriptor/2}],
+ ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(
+ #'IndAudLocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PP,
+ streamModeSel = asn1_NOVALUE}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun('NULL', _) -> ?ModeToken end},
+ {[RV], fun('NULL', _) -> ?ReservedValueToken end},
+ {[RG], fun('NULL', _) -> ?ReservedGroupToken end},
+ {PP, fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudLocalControlDescriptor(
+ #'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PP,
+ streamModeSel = SMS}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[RV], fun('NULL', _) -> ?ReservedValueToken end},
+ {[RG], fun('NULL', _) -> ?ReservedGroupToken end},
+ { PP, fun enc_IndAudPropertyParm/2},
+ {[SMS], fun enc_StreamMode/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = Name, propertyParms = PP},
+ State) ->
+ [
+ enc_list([{[Name], fun enc_PkgdName/2},
+ {[PP], fun enc_PropertyParm/2}], State)
+ ].
+
+enc_IndAudMediaDescriptor_multiStream(Val, State) when is_list(Val) ->
+ [
+ enc_list([{Val, fun enc_IndAudStreamDescriptor/2}], State)
+ ];
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID}, State) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventStream, ID}, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(
+ #'IndAudEventsDescriptor'{requestID = asn1_NOVALUE,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ ?EventsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventsDescriptor(
+ #'IndAudEventsDescriptor'{requestID = RID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(asn1_NOVALUE, _State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(_State),
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE,
+ signalRequestID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ];
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = SID,
+ signalRequestID = SRID}, State) ->
+ [
+ enc_SignalName(SignalName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_StreamID/2},
+ {[SRID], fun enc_sigRequestID/2}],
+ State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = asn1_NOVALUE},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State)
+ ];
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = SL},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(SL, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit', Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([Mand | Opt], State) ->
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+%% d("enc_AuditReturnParameter -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+%% d("enc_AuditReturnParameter -> entry with"
+%% "~n List: ~p", [List]),
+ enc_list([{List, fun enc_auditReturnItem/2}], State).
+
+
+enc_NotifyRequest(#'NotifyRequest'{terminationID = TIDs,
+ observedEventsDescriptor = OED,
+ errorDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_NotifyRequest(#'NotifyRequest'{terminationID = TIDs,
+ observedEventsDescriptor = OED,
+ errorDescriptor = ED}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State)),
+ ?COMMA,
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(#'NotifyReply'{terminationID = TIDs,
+ errorDescriptor = asn1_NOVALUE}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State)
+ ];
+enc_NotifyReply(#'NotifyReply'{terminationID = TIDs,
+ errorDescriptor = ED}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_ObservedEventsDescriptor(
+ #'ObservedEventsDescriptor'{requestId = RID,
+ observedEventLst = OEL}, State) ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEvents(OEL, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEvents([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(#'ObservedEvent'{eventName = EN,
+ streamID = SID,
+ eventParList = EPL,
+ timeNotation = asn1_NOVALUE}, State) ->
+ [
+ ?LWSP,
+ enc_EventName(EN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ { EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ];
+enc_ObservedEvent(#'ObservedEvent'{eventName = EN,
+ streamID = SID,
+ eventParList = EPL,
+ timeNotation = TN}, State) ->
+ [
+ enc_TimeNotation(TN, State),
+ ?LWSP,
+ ?COLON,
+ ?LWSP,
+ enc_EventName(EN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName', Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(
+ #'ServiceChangeRequest'{terminationID = TIDs,
+ serviceChangeParms = Parms}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(
+ #'ServiceChangeReply'{terminationID = TIDs,
+ serviceChangeResult = Res}, State) ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_termIDList(TIDs, State),
+ enc_ServiceChangeResult(Res, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult', Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({errorDescriptor, Val}, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_ServiceChangeResult({serviceChangeResParms, Val}, State) ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_ServiceChangeResult({Tag, _}, _State) ->
+ error({invalid_ServiceChangeResult_tag, Tag}).
+
+%% Required length of termination ID list is 1
+%% enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+%% enc_TerminationIDList1(Val, State);
+%% enc_TerminationIDList1([Singleton], State) ->
+%% enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDList({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList(Val, State);
+enc_TerminationIDList([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDList(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_termIDList({'TerminationIDList',Val}, State) ->
+ enc_termIDList(Val, State);
+enc_termIDList([Singleton], State) ->
+ enc_TerminationID(Singleton, State);
+enc_termIDList(TidList, State)
+ when is_list(TidList) and (length(TidList) > 1) ->
+%% d("enc_termIDList -> entry with"
+%% "~n TidList: ~p", [TidList]),
+ State2 = ?INC_INDENT(State),
+ [
+ ?LSBRKT_INDENT(State),
+ enc_list([{TidList, fun enc_TerminationID/2}], State2),
+ ?RSBRKT_INDENT(State)
+ ].
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(#'MediaDescriptor'{termStateDescr = TSD,
+ streams = Streams}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[TSD], fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2},
+ {[Val#'StreamParms'.statisticsDescriptor],
+ fun enc_StatisticsDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') and (H#'PropertyParm'.name == "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EQUAL,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EQUAL,
+ ?LSBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RSBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{Values, fun enc_Value/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDList(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []}, _State) ->
+ [
+ ?EventsToken
+ ];
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = RID,
+ eventList = Evs}, State)
+ when (RID =/= asn1_NOVALUE) and (Evs =/= []) ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_RequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventsDescriptor(#'EventsDescriptor'{requestID = RID,
+ eventList = Evs}, _State) ->
+ error({invalid_EventsDescriptor, RID, Evs}).
+
+enc_RequestedEvent(#'RequestedEvent'{pkgdName = N,
+ streamID = asn1_NOVALUE,
+ eventAction = asn1_NOVALUE,
+ evParList = []}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+enc_RequestedEvent(#'RequestedEvent'{pkgdName = N,
+ streamID = SID,
+ eventAction = EA,
+ evParList = EPL}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_requestedActions(EA)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+decompose_requestedActions(
+ #'RequestedActions'{keepActive = asn1_NOVALUE,
+ eventDM = asn1_NOVALUE,
+ secondEvent = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE,
+ notifyBehaviour = asn1_NOVALUE,
+ resetEventsDescriptor = asn1_NOVALUE}) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of
+%% - KeepActiveToken
+%% - notifyBehaviour
+%% - eventDM
+%% - ResetEventsDescriptor
+%% - eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (KA =/= true) and ((SD =/= asn1_NOVALUE) and (SD =/= [])) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (SD == asn1_NOVALUE) or (SD == []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED}) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ].
+
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) and (is_list(Evs) and (Evs =/= [])) ->
+ %% d("enc_embedFirst -> entry with"
+ %% "~n RID: ~p"
+ %% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+ %% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+enc_notifyBehaviour({notifyImmediate, 'NULL'}, _State) ->
+ [?NotifyImmediateToken];
+enc_notifyBehaviour({notifyRegulated, Val}, State) ->
+ enc_RegulatedEmbeddedDescriptor(Val, State);
+enc_notifyBehaviour({neverNotify, 'NULL'}, _State) ->
+ [?NeverNotifyToken];
+enc_notifyBehaviour({Tag, Val}, _State) ->
+ error({invalid_notifyBehaviour, Tag, Val}).
+
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE}, _State) ->
+ [
+ ?NotifyRegulatedToken
+ ];
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SE,
+ signalsDescriptor = asn1_NOVALUE}, State) ->
+ [
+ ?NotifyRegulatedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedNoSig(SE, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_RegulatedEmbeddedDescriptor(
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SE,
+ signalsDescriptor = SD}, State) ->
+ [
+ ?NotifyRegulatedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedWithSig({SE, SD}, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_RegulatedEmbeddedDescriptor(Val, _State) ->
+ error({invalid_RegulatedEmbeddedDescriptor, Val}).
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = asn1_NOVALUE,
+ eventAction = asn1_NOVALUE,
+ evParList = []}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ eventAction = EA,
+ evParList = EPL}, State) ->
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%%
+%% This in the ABNF:
+%% at-most-once each of
+%% - KeepActiveToken
+%% - notifyBehaviour
+%% - eventDM
+%% - ResetEventsDescriptor
+%% - eventStream
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = asn1_NOVALUE,
+ eventDM = asn1_NOVALUE,
+ signalsDescriptor = asn1_NOVALUE,
+ notifyBehaviour = asn1_NOVALUE,
+ resetEventsDescriptor = asn1_NOVALUE}) ->
+ [];
+
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (KA =/= true) and ((SD =/= asn1_NOVALUE) and (SD =/= [])) ->
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[SD], fun enc_embedSig/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+decompose_secondRequestedActions(
+ #'SecondRequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ signalsDescriptor = SD,
+ notifyBehaviour = NB,
+ resetEventsDescriptor = RED})
+ when (SD == asn1_NOVALUE) or (SD == []) ->
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[NB], fun enc_notifyBehaviour/2},
+ {[RED], fun('NULL', _) -> ?ResetEventsDescriptorToken end}
+ ];
+decompose_secondRequestedActions(SRA) ->
+ error({invalid_SecondRequestedActions, SRA}).
+
+enc_embedSig(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EvSpecs, State)
+ when is_list(EvSpecs) andalso (length(EvSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EvSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EvSpecs, _State) ->
+ error({bad_eventSpecs, EvSpecs}).
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = N,
+ streamID = asn1_NOVALUE,
+ eventParList = []}, State) ->
+ [
+ enc_EventName(N, State)
+ ];
+enc_eventSpec(#'EventSpec'{eventName = N,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(N, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[SID], fun enc_eventStream/2}, {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(SigRequests, State) when is_list(SigRequests) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{SigRequests, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(#'Signal'{signalName = SN,
+ streamID = SID,
+ sigType = ST,
+ duration = Du,
+ notifyCompletion = NC,
+ keepActive = KA,
+ sigParList = SPL,
+ direction = Di,
+ requestID = RID,
+ intersigDelay = ISD}, State) ->
+ [
+ enc_SignalName(SN, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_sigStream/2},
+ {[ST], fun enc_sigSignalType/2},
+ {[Du], fun enc_sigDuration/2},
+ {[NC], fun enc_notifyCompletion/2},
+ {[KA], fun enc_keepActive/2},
+ {SPL, fun enc_sigOther/2},
+ {[Di], fun enc_SignalDirection/2},
+ {[RID], fun enc_sigRequestID/2},
+ {[ISD], fun enc_sigIntsigDelay/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken;
+ onIteration -> ?IterationToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_SignalDirection({'SignalDirection', Val}, State) ->
+ enc_SignalDirection(Val, State);
+enc_SignalDirection(Val, _State) ->
+ [
+ ?DirectionToken,
+ ?EQUAL,
+ case Val of
+ internal -> ?InternalToken;
+ external -> ?ExternalToken;
+ both -> ?BothToken
+ end
+ ].
+
+enc_sigRequestID(Val, State) ->
+ [
+ ?RequestIDToken,
+ ?EQUAL,
+ enc_RequestID(Val, State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when Val == ?megaco_all_request_id ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_sigIntsigDelay(Val, State) ->
+ [
+ ?IntsigDelayToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value},
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2},
+ {[Val#'ServiceChangeParm'.serviceChangeIncompleteFlag],
+ fun('NULL', _) -> ?ServiceChangeIncompleteToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken;
+ _ ->
+ error({invalid_ServiceChangeMethod, Val})
+
+ end
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) and (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) and (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) and (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invalid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) and is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep == true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep == false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++"~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
+
diff --git a/lib/megaco/src/text/megaco_text_mini_decoder.erl b/lib/megaco/src/text/megaco_text_mini_decoder.erl
new file mode 100644
index 0000000000..6e1bf9295a
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_mini_decoder.erl
@@ -0,0 +1,88 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%% Purpose: Encode PRETTY Megaco/H.248 text messages from internal form
+%%----------------------------------------------------------------------
+
+-module(megaco_text_mini_decoder).
+
+-export([decode_message/2]).
+
+-include("megaco_text_tokens.hrl").
+-include_lib("megaco/src/engine/megaco_message_internal.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a mini 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%----------------------------------------------------------------------
+
+decode_message(_, Bin) when is_binary(Bin) ->
+ case megaco_text_scanner:scan(Bin) of
+ {ok, Tokens, _Vsn, _LastLine} ->
+ decode_message(Tokens);
+
+ {error, Reason, Line} ->
+ parse_error(Reason, Line, [])
+ end;
+decode_message(_EC, _BadBin) ->
+ {error, bad_binary}.
+
+
+decode_message(Tokens0) ->
+ Tokens = strip(Tokens0, []),
+ case (catch megaco_text_mini_parser:parse(Tokens)) of
+ {ok, MegacoMessage} ->
+ {ok, MegacoMessage};
+ {error, Reason} ->
+ parse_error(Reason, Tokens);
+
+ %% OTP-4007
+ {'EXIT', Reason} ->
+ parse_error(Reason, Tokens)
+ end.
+
+strip([], Tokens) ->
+ lists:reverse(Tokens);
+strip([{'TransToken', _Line, _Text}|_], Acc) ->
+ strip_finish(Acc);
+strip([{'ReplyToken', _Line, _Text}|_], Acc) ->
+ strip_finish(Acc);
+strip([{'PendingToken', _Line, _Text}|_], Acc) ->
+ strip_finish(Acc);
+strip([{'ResponseAckToken', _Line, _Text}|_], Acc) ->
+ strip_finish(Acc);
+strip([{'ErrorToken', _Line, _Text}|_], Acc) ->
+ strip_finish(Acc);
+strip([H|T], Acc) ->
+ strip(T, [H|Acc]).
+
+strip_finish(RevTokens) ->
+ lists:reverse([{endOfMessage, 1, endOfMessage}|RevTokens]).
+
+
+parse_error(Reason, Tokens) ->
+ {error, [{reason, Reason}, {token, Tokens}]}.
+
+parse_error(Reason, Line, Tokens) ->
+ {error, [{reason, Reason, Line}, {token, Tokens}]}.
+
+
diff --git a/lib/megaco/src/text/megaco_text_mini_parser.hrl b/lib/megaco/src/text/megaco_text_mini_parser.hrl
new file mode 100644
index 0000000000..bb6ee43247
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_mini_parser.hrl
@@ -0,0 +1,1246 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v2.hrl").
+-include("megaco_text_tokens.hrl").
+
+-define(d(F,A), io:format("DBG:"++F++"~n",A)).
+
+make_safe_token({_TokenTag, Line, Text}) ->
+ {safeToken, Line, Text}.
+
+% ensure_value({safeToken, _Line, Text}) ->
+% ensure_value(Text);
+% ensure_value({'QuotedChars', _Line, Text}) ->
+% ensure_value(Text);
+% ensure_value(Text) when list(Text) ->
+% Text. %% BUGBUG: ensure length
+
+% %% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+% ensure_NAME({_TokenTag, _Line, Text}) ->
+% Text. %% BUGBUG: ensure length and chars
+
+% ensure_requestID({safeToken, _Line, "*"}) ->
+% ?megaco_all_request_id;
+% ensure_requestID(RequestId) ->
+% ensure_uint32(RequestId).
+
+% ensure_streamID(StreamId) ->
+% ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% ContextID = (UINT32 / "*" / "-" / "$")
+% ensure_contextID({_TokenTag, _Line, Text}) ->
+% case Text of
+% "*" -> ?megaco_all_context_id;
+% "-" -> ?megaco_null_context_id;
+% "\$" -> ?megaco_choose_context_id;
+% Int -> ensure_uint32(Int)
+% end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+
+ensure_ip4addr({TokenTag, Line, Addr}) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) == 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when (length(Hex4) =< 4) andalso (length(Hex4) > 0) ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+ensure_domainName({_TokenTag, _Line, Name}, Port) ->
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+% ensure_extensionParameter({_TokenTag, Line, Text}) ->
+% case Text of
+% [X, S | _Chars] ->
+% if
+% X /= $X, X /= $x,
+% S /= $+, S /= $- ->
+% return_error(Line, {bad_extension_parameter, Text});
+% true ->
+% {extension_parameter, Text}
+% end;
+% _ ->
+% return_error(Line, {bad_extension_parameter, Text})
+% end.
+
+ensure_message(MegacopToken, MID) ->
+ #'ServiceChangeProfile'{profileName = Name,
+ version = Version} =
+ ensure_profile(MegacopToken),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version, mId = MID};
+ [$!] ->
+ #'Message'{version = Version, mId = MID}
+ end.
+
+
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+% case Text of
+% "v32b" -> v32bis;
+% "v22b" -> v22bis;
+% "v18" -> v18;
+% "v22" -> v22;
+% "v32" -> v32;
+% "v34" -> v34;
+% "v90" -> v90;
+% "v91" -> v91;
+% "synchisdn" -> synchISDN;
+% "sn" -> synchISDN;
+% [$x | _] -> ensure_extensionParameter(Token)
+% end.
+
+%% An mtp address is five octets long
+ensure_mtpAddress({_TokenTag, _Line, Addr}) ->
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+% ensure_muxType({_TokenTag, _Line, Text} = Token) ->
+% case Text of
+% "h221" -> h221;
+% "h223" -> h223;
+% "h226" -> h226;
+% "v76" -> v76;
+% "nx64k" -> nx64k; % v2
+% [$x | _] -> ensure_extensionParameter(Token)
+% end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+% ensure_packagesItem({TokenTag, Line, Text}) ->
+% case string:tokens(Text, [$-]) of
+% [Name, Version] ->
+% #'PackagesItem'{packageName = ensure_NAME({TokenTag, Line, Name}),
+% packageVersion = ensure_uint({TokenTag, Line, Version}, 0, 99)};
+% _ ->
+% return_error(Line, {bad_PackagesItem, Text})
+% end.
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+% ensure_pkgdName({TokenTag, Line, Text}) ->
+% case string:tokens(Text, [$/]) of
+% [Name, Item] ->
+% ensure_name_or_star({TokenTag, Line, Name}),
+% ensure_name_or_star({TokenTag, Line, Item}),
+% Text;
+% _ ->
+% return_error(Line, {bad_pkgdName, Text})
+% end.
+
+% ensure_name_or_star({_, _, Name}) when Name == "*" ->
+% Name;
+% ensure_name_or_star(Name) ->
+% ensure_NAME(Name).
+
+
+
+%% v2 - start
+
+% merge_indAudMediaDescriptor({termStateDescr, Val}) ->
+% #'IndAudMediaDescriptor'{termStateDescr = Val};
+% merge_indAudMediaDescriptor({streamParm, Val}) ->
+% #'IndAudMediaDescriptor'{streams = {oneStream, Val}};
+% merge_indAudMediaDescriptor({streamDescr, Val}) ->
+% #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}}.
+
+% merge_indAudLocalControlDescriptor(Parms) ->
+% do_merge_indAudLocalControlDescriptor(Parms,
+% #'IndAudLocalControlDescriptor'{}).
+
+% do_merge_indAudLocalControlDescriptor([Parm | Parms], Desc) ->
+% case Parm of
+% modeToken when Desc#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE ->
+% Desc2 = Desc#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+% do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+% reservedGroupToken when Desc#'IndAudLocalControlDescriptor'.reserveGroup == asn1_NOVALUE ->
+% Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+% do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+% reservedValueToken when Desc#'IndAudLocalControlDescriptor'.reserveValue == asn1_NOVALUE ->
+% Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+% do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+% {pkgdName, Val} when Desc#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->
+% PropParms = [#'IndAudPropertyParm'{name = Val}],
+% Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms},
+% do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+% {pkgdName, Val} when list(Desc#'IndAudLocalControlDescriptor'.propertyParms) ->
+% PropParms = Desc#'IndAudLocalControlDescriptor'.propertyParms,
+% PropParms2 = [#'IndAudPropertyParm'{name = Val} | PropParms],
+% Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2},
+% do_merge_indAudLocalControlDescriptor(Parms, Desc2)
+% end;
+% do_merge_indAudLocalControlDescriptor([], Desc) ->
+% case Desc#'IndAudLocalControlDescriptor'.propertyParms of
+% [_ | _] = PropParms -> % List has more then one element
+% PropParms2= lists:reverse(PropParms),
+% Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+% _ ->
+% Desc
+% end.
+
+% ensure_indAudLocalParm(Token) ->
+% case Token of
+% {safeToken, _Line, "mode"} -> modeToken;
+% {safeToken, _Line, "mo"} -> modeToken;
+% {safeToken, _Line, "reservedgroup"} -> reservedGroupToken;
+% {safeToken, _Line, "rg"} -> reservedGroupToken;
+% {safeToken, _Line, "reservedvalue"} -> reservedValueToken;
+% {safeToken, _Line, "rv"} -> reservedValueToken;
+% PkgdName -> {pkgdName,
+% ensure_pkgdName(PkgdName)}
+% end.
+
+% merge_indAudTerminationStateDescriptor({pkgdName, Val}) ->
+% PropParm = #'IndAudPropertyParm'{name = Val},
+% #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+% merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+% #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+% merge_indAudTerminationStateDescriptor(bufferToken) ->
+% #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+% merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+% IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+% do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+% do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+% IAEBD;
+% do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+% IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+% do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+% IAEBD) ->
+% %% BUGBUG BUGBUG BUGBUG
+% %% This is an ugly hack to allow the eventParamName which only
+% %% exists in the text encoding...
+% IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+% ensure_indAudSignalListParm(SIG) when record(SIG, 'Signal') ->
+% ensure_indAudSignal(SIG).
+
+% ensure_indAudSignal(#'Signal'{signalName = SignalName,
+% streamID = asn1_NOVALUE,
+% sigType = asn1_NOVALUE,
+% duration = asn1_NOVALUE,
+% notifyCompletion = asn1_NOVALUE,
+% keepActive = asn1_NOVALUE,
+% sigParList = []}) ->
+% #'IndAudSignal'{signalName = SignalName}.
+
+
+% ensure_IADMD({_TokenTag, _Line,
+% #'DigitMapDescriptor'{digitMapName = Name,
+% digitMapValue = asn1_NOVALUE}}) ->
+% #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+
+% merge_indAudPackagesDescriptor(#'PackagesItem'{packageName = N,
+% packageVersion = V}) ->
+% #'IndAudPackagesDescriptor'{packageName = N,
+% packageVersion = V}.
+
+
+% ensure_indAudTerminationStateParm(Token) ->
+% case Token of
+% {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+% {safeToken, _Line, "si"} -> serviceStatesToken;
+% {safeToken, _Line, "buffer"} -> bufferToken;
+% {safeToken, _Line, "bf"} -> bufferToken;
+% PkgdName -> {pkgdName,
+% ensure_pkgdName(PkgdName)}
+% end.
+
+
+% %% Types modified by v2:
+
+% merge_auditDescriptor([]) ->
+% #'AuditDescriptor'{};
+% merge_auditDescriptor(Tokens) when list(Tokens) ->
+% case lists:keysearch(terminationAudit, 1, Tokens) of
+% {value, {terminationAudit, TA}} ->
+% case lists:keydelete(terminationAudit, 1, Tokens) of
+% [] ->
+% #'AuditDescriptor'{auditPropertyToken = TA};
+% AuditTokens ->
+% #'AuditDescriptor'{auditToken = AuditTokens,
+% auditPropertyToken = TA}
+% end;
+% false ->
+% #'AuditDescriptor'{auditToken = Tokens}
+% end;
+% merge_auditDescriptor(_) ->
+% #'AuditDescriptor'{}.
+
+
+% %% v2 - end
+
+
+
+% merge_ServiceChangeParm(Parms) ->
+% Required = [serviceChangeReason, serviceChangeMethod],
+% merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+% merge_ServiceChangeParm([], SCP, []) ->
+% SCP;
+
+% merge_ServiceChangeParm([], _SCP, Required) ->
+% exit({missing_required_serviceChangeParm, Required});
+
+% merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE,
+% SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+% merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+% MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+% exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+% merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE,
+% SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+% merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+% Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+% exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+% merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeProfile == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeVersion == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% %% REQUIRED (i.e. no default value)
+% merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+% when SCP0#'ServiceChangeParm'.serviceChangeReason == undefined ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+% Req = lists:delete(serviceChangeReason, Req0),
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeDelay == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% %% REQUIRED (i.e. no default value)
+% merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+% when SCP0#'ServiceChangeParm'.serviceChangeMethod == undefined ->
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+% Req = lists:delete(serviceChangeMethod, Req0),
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.timeStamp == asn1_NOVALUE ->
+% SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+% merge_ServiceChangeParm(Parms, SCP0, Req);
+
+% merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+% when SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE ->
+% SCI = #'AuditDescriptor'{auditToken = [Val]},
+% SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+% merge_ServiceChangeParm(Parms, SCP, Req);
+
+% merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+% Val2 =
+% case Tag of
+% address ->
+% SCP#'ServiceChangeParm'.serviceChangeAddress;
+% mgc_id ->
+% SCP#'ServiceChangeParm'.serviceChangeMgcId;
+% profile ->
+% SCP#'ServiceChangeParm'.serviceChangeProfile;
+% version ->
+% SCP#'ServiceChangeParm'.serviceChangeVersion;
+% reason ->
+% SCP#'ServiceChangeParm'.serviceChangeReason;
+% delay ->
+% SCP#'ServiceChangeParm'.serviceChangeDelay;
+% method ->
+% SCP#'ServiceChangeParm'.serviceChangeMethod;
+% time_stamp ->
+% SCP#'ServiceChangeParm'.timeStamp;
+% audit_item ->
+% SCP#'ServiceChangeParm'.serviceChangeInfo
+% end,
+% exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}}).
+
+
+% merge_ServiceChangeResParm(Parms) ->
+% merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+% merge_ServiceChangeResParm([], SCRP) ->
+% SCRP;
+% merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE,
+% SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+% SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+% merge_ServiceChangeResParm(Parms, SCRP);
+% merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+% MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+% exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+% merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE,
+% SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+% SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+% merge_ServiceChangeResParm(Parms, SCRP);
+% merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+% Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+% exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+% merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+% SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+% merge_ServiceChangeResParm(Parms, SCRP);
+
+% merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+% SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+% merge_ServiceChangeResParm(Parms, SCRP);
+
+% merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+% when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+% SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+% merge_ServiceChangeResParm(Parms, SCRP);
+
+% merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+% Val2 =
+% case Tag of
+% address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+% mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+% profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+% version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+% time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+% end,
+% exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+% ensure_serviceChangeMethod({safeToken, _Line, "fl"}) ->
+% failover;
+% ensure_serviceChangeMethod({safeToken, _Line, "failover"}) ->
+% failover;
+% ensure_serviceChangeMethod({safeToken, _Line, "fo"}) ->
+% forced;
+% ensure_serviceChangeMethod({safeToken, _Line, "forced"}) ->
+% forced;
+% ensure_serviceChangeMethod({safeToken, _Line, "gr"}) ->
+% graceful;
+% ensure_serviceChangeMethod({safeToken, _Line, "graceful"}) ->
+% graceful;
+% ensure_serviceChangeMethod({safeToken, _Line, "rs"}) ->
+% restart;
+% ensure_serviceChangeMethod({safeToken, _Line, "restart"}) ->
+% restart;
+% ensure_serviceChangeMethod({safeToken, _Line, "dc"}) ->
+% disconnected;
+% ensure_serviceChangeMethod({safeToken, _Line, "disconnected"}) ->
+% disconnected;
+% ensure_serviceChangeMethod({safeToken, _Line, "ho"}) ->
+% handOff;
+% ensure_serviceChangeMethod({safeToken, _Line, "handoff"}) ->
+% handOff;
+% ensure_serviceChangeMethod({safeToken, Line, Text}) ->
+% return_error(Line, {bad_serviceChangeMethod, Text}).
+
+
+ensure_profile({_TokenTag, Line, Text}) ->
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+% merge_signalRequest(SignalName, PropertyParms) ->
+% Sig = #'Signal'{signalName = SignalName},
+% SPL = [],
+% do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+% do_merge_signalRequest(Sig, [H | T], SPL) ->
+% case H of
+% {stream, StreamId} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+% do_merge_signalRequest(Sig#'Signal'{streamID = StreamId}, T, SPL);
+% {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+% do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+% {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+% do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+% {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+% do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+% keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE->
+% do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+% {other, Name, PP} ->
+% SP = #'SigParameter'{sigParameterName = Name,
+% value = PP#'PropertyParm'.value,
+% extraInfo = PP#'PropertyParm'.extraInfo},
+% do_merge_signalRequest(Sig, T, [SP | SPL]);
+% _ ->
+% return_error(0, {bad_sigParm, H})
+% end;
+% do_merge_signalRequest(Sig, [], SPL) ->
+% Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+% %% eventStream = StreamToken EQUAL StreamID
+% %% eventOther = eventParameterName parmValue
+% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+% {stream, ensure_uint16(Value)};
+% select_stream_or_other("st", Value) ->
+% {stream, ensure_uint16(Value)};
+% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+% {stream, ensure_uint16(Value)};
+% select_stream_or_other("stream", Value) ->
+% {stream, ensure_uint16(Value)};
+% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+% EP = #'EventParameter'{eventParameterName = Name,
+% value = Value},
+% {other, EP}.
+
+% ensure_eventDM({_TokenTag, Line, DMD})
+% when record(DMD, 'DigitMapDescriptor') ->
+% Name = DMD#'DigitMapDescriptor'.digitMapName,
+% Val = DMD#'DigitMapDescriptor'.digitMapValue,
+% if
+% Name == asn1_NOVALUE, Val /= asn1_NOVALUE ->
+% {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+% DMV = #'DigitMapValue'{startTimer = Start,
+% shortTimer = Short,
+% longTimer = Long,
+% digitMapBody = Body,
+% durationTimer = Duration},
+% {eventDM, {digitMapValue, DMV}};
+% Name /= asn1_NOVALUE, Val == asn1_NOVALUE ->
+% {eventDM, {digitMapName, Name}};
+% true ->
+% return_error(Line, {bad_eventDM, DMD})
+% end.
+
+% ensure_DMD({_TokenTag, _Line, DMD})
+% when record(DMD, 'DigitMapDescriptor') ->
+% Val2 =
+% case DMD#'DigitMapDescriptor'.digitMapValue of
+% %% Note that the values of the digitMapBody and durationTimers
+% %% are swapped by the scanner (this is done because of a
+% %% problem in the flex scanner).
+% #'DigitMapValue'{durationTimer = Body,
+% digitMapBody = Duration} = DMV ->
+% %% Convert to version 1 DigitMapValue
+% DMV#'DigitMapValue'{digitMapBody = Body,
+% durationTimer = Duration};
+% Other ->
+% Other
+% end,
+% DMD#'DigitMapDescriptor'{digitMapValue = Val2}.
+
+
+% merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+% StreamId = asn1_NOVALUE,
+% EPL = [],
+% do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+% do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+% do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+% do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+% do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+% do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+% #'ObservedEvent'{eventName = EventName,
+% timeNotation = TimeStamp,
+% streamID = StreamID,
+% eventParList = lists:reverse(EPL)}.
+
+% merge_eventSpec(OE) when record(OE, 'ObservedEvent'),
+% OE#'ObservedEvent'.timeNotation == asn1_NOVALUE ->
+% #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+% streamID = OE#'ObservedEvent'.streamID,
+% eventParList = OE#'ObservedEvent'.eventParList};
+% merge_eventSpec(OE) ->
+% return_error(0, {bad_event_spec, OE}).
+
+% merge_eventParameters(Params) ->
+% StreamId = asn1_NOVALUE,
+% EPL = [],
+% RA = #'RequestedActions'{},
+% HasA = no,
+% do_merge_eventParameters(Params, StreamId, EPL, RA, HasA) .
+
+% do_merge_eventParameters([H | T], StreamId, EPL, RA, HasA) ->
+% case H of
+% keepActive when RA#'RequestedActions'.keepActive == asn1_NOVALUE ->
+% RA2 = RA#'RequestedActions'{keepActive = true},
+% do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+% {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+% RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+% secondEvent = SED},
+% do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+% {eventDM, DM} when RA#'RequestedActions'.eventDM == asn1_NOVALUE ->
+% RA2 = RA#'RequestedActions'{eventDM = DM},
+% do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+% {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+% do_merge_eventParameters(T, NewStreamId, EPL, RA, HasA);
+% {other, PP} when record(PP, 'PropertyParm') ->
+% EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+% value = PP#'PropertyParm'.value,
+% extraInfo = PP#'PropertyParm'.extraInfo},
+% do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+% {other, EP} when record(EP, 'EventParameter') ->
+% do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+% _ ->
+% return_error(0, {bad_eventParameter, H})
+% end;
+% do_merge_eventParameters([], StreamId, EPL, RA, yes) ->
+% #'RequestedEvent'{streamID = StreamId,
+% eventAction = RA,
+% evParList = lists:reverse(EPL)};
+% do_merge_eventParameters([], StreamId, EPL, _RA, no) ->
+% #'RequestedEvent'{streamID = StreamId,
+% eventAction = asn1_NOVALUE,
+% evParList = lists:reverse(EPL)}.
+
+% merge_secondEventParameters(Params) ->
+% StreamId = asn1_NOVALUE,
+% EPL = [],
+% SRA = #'SecondRequestedActions'{},
+% HasA = no,
+% do_merge_secondEventParameters(Params, StreamId, EPL, SRA, HasA) .
+
+% do_merge_secondEventParameters([H | T], StreamId, EPL, SRA, HasA) ->
+% case H of
+% keepActive when SRA#'SecondRequestedActions'.keepActive == asn1_NOVALUE ->
+% SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+% do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+% {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+% SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+% do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+% {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM == asn1_NOVALUE ->
+% SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+% do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+% {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+% do_merge_secondEventParameters(T, NewStreamId, EPL, SRA, HasA);
+% {other, PP} when record(PP, 'PropertyParm') ->
+% EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+% value = PP#'PropertyParm'.value,
+% extraInfo = PP#'PropertyParm'.extraInfo},
+% do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+% {other, EP} when record(EP, 'EventParameter') ->
+% do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+% _ ->
+% return_error(0, {bad_secondEventParameter, H})
+% end;
+% do_merge_secondEventParameters([], StreamId, EPL, SRA, yes) ->
+% #'SecondRequestedEvent'{streamID = StreamId,
+% eventAction = SRA,
+% evParList = lists:reverse(EPL)};
+% do_merge_secondEventParameters([], StreamId, EPL, _SRA, no) ->
+% #'SecondRequestedEvent'{streamID = StreamId,
+% eventAction = asn1_NOVALUE,
+% evParList = lists:reverse(EPL)}.
+
+% %% terminationID = "ROOT" / pathName / "$" / "*"
+% %% Total length of pathName must not exceed 64 chars.
+% %% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+% %% ["@" pathDomainName ]
+% %% ABNF allows two or more consecutive "." although it is meaningless
+% %% in a path domain name.
+% %% pathDomainName = (ALPHA / DIGIT / "*" )
+% %% *63(ALPHA / DIGIT / "-" / "*" / ".")
+% ensure_terminationID({safeToken, _Line, LowerText}) ->
+% %% terminationID = "ROOT" / pathName / "$" / "*"
+% decode_term_id(LowerText, false, [], []).
+
+% decode_term_id([H | T], Wild, Id, Component) ->
+% case H of
+% $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+% $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+% $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+% _ -> decode_term_id(T, Wild, Id, [H | Component])
+% end;
+% decode_term_id([], Wild, Id, Component) ->
+% Id2 = [lists:reverse(Component) | Id],
+% #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+ensure_pathName({_TokenTag, _Line, Text}) ->
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+% ensure_timeStamp({'TimeStampToken', Line, Text}) ->
+% case string:tokens(Text, [$T, $t]) of
+% [Date, Time] ->
+% #'TimeNotation'{date = Date, time = Time};
+% _ ->
+% return_error(Line, {bad_timeStamp, Text})
+% end.
+
+% ensure_transactionID(TransId) ->
+% ensure_uint32(TransId).
+
+% %% transactionAck = transactionID / (transactionID "-" transactionID)
+% ensure_transactionAck({safeToken, _Line, Text}) ->
+% case string:tokens(Text, [$-]) of
+% [Id] ->
+% #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+% [Id, Id2] ->
+% #'TransactionAck'{firstAck = ensure_transactionID(Id),
+% lastAck = ensure_transactionID(Id2)}
+% end.
+
+% merge_action_requests(CtxId, Items) ->
+% CtxReq = #'ContextRequest'{},
+% CtxAuditReq = asn1_NOVALUE,
+% CmdReq = [],
+% TopReq = [],
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, Items).
+
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, [H | T]) ->
+% case H of
+% _ when record(H, 'CommandRequest') ->
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, [H | CmdReq], TopReq, T);
+
+% {priority, Int} when CtxReq#'ContextRequest'.priority == asn1_NOVALUE ->
+% CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+% do_merge_action_requests(CtxId, CtxReq2, CtxAuditReq, CmdReq,
+% TopReq, T);
+% {emergency, Bool} when CtxReq#'ContextRequest'.emergency == asn1_NOVALUE ->
+% CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+% do_merge_action_requests(CtxId, CtxReq2, CtxAuditReq, CmdReq,
+% TopReq, T);
+% {topology, Desc} ->
+% TopReq2 = Desc ++ TopReq, %% OTP-4088
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq,
+% TopReq2, T);
+
+% {contextAudit, CAs} ->
+% CtxAuditReq2 = merge_context_attr_audit_request(CtxAuditReq, CAs),
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq2, CmdReq,
+% TopReq, T)
+
+% end;
+% do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, []) ->
+% #'ActionRequest'{contextId = CtxId,
+% contextRequest = strip_contextRequest(CtxReq, TopReq),
+% contextAttrAuditReq = strip_contextAttrAuditRequest(CtxAuditReq),
+% commandRequests = lists:reverse(CmdReq)}.
+
+
+% merge_context_attr_audit_request(asn1_NOVALUE, CAs) ->
+% merge_context_attr_audit_request(#'ContextAttrAuditRequest'{}, CAs);
+% merge_context_attr_audit_request(CAAR, [H|T]) ->
+% CAAR2 =
+% case H of
+% priorityAudit when CAAR#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+% CAAR#'ContextAttrAuditRequest'{priority = 'NULL'};
+
+% priorityAudit ->
+% Prio = CAAR#'ContextAttrAuditRequest'.priority,
+% exit({only_once, priorityAudit, Prio});
+
+% emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+% CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'};
+
+% emergencyAudit ->
+% Em = CAAR#'ContextAttrAuditRequest'.emergency,
+% exit({only_once, emergencyAudit, Em});
+
+% topologyAudit when CAAR#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+% CAAR#'ContextAttrAuditRequest'{topology = 'NULL'};
+
+% topologyAudit ->
+% Top = CAAR#'ContextAttrAuditRequest'.topology,
+% exit({only_once, topologyAudit, Top})
+
+% end,
+% merge_context_attr_audit_request(CAAR2, T);
+% merge_context_attr_audit_request(CAAR, []) ->
+% CAAR.
+
+% %% OTP-5085:
+% %% In order to solve a problem in the parser, the error descriptor
+% %% has been put last in the non-empty commandReplyList, if it is not
+% %% asn1_NOVALUE
+% merge_action_reply(ReplyList) ->
+% CtxReq = #'ContextRequest'{},
+% TopReq = [],
+% CmdList = [],
+% case lists:reverse(ReplyList) of
+% [ED|RL2] when record(ED, 'ErrorDescriptor') ->
+% AR = do_merge_action_reply(lists:reverse(RL2),
+% CtxReq, TopReq, CmdList),
+% AR#'ActionReply'{errorDescriptor = ED};
+% _ ->
+% do_merge_action_reply(ReplyList, CtxReq, TopReq, CmdList)
+% end.
+
+% do_merge_action_reply([H | T], CtxReq, TopReq, CmdList) ->
+% case H of
+% {command, Cmd} ->
+% do_merge_action_reply(T, CtxReq, TopReq, [Cmd | CmdList]);
+% {context, Ctx} ->
+% case Ctx of
+% {priority, Int} when CtxReq#'ContextRequest'.priority == asn1_NOVALUE ->
+% CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+% do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+% {emergency, Bool} when CtxReq#'ContextRequest'.emergency == asn1_NOVALUE ->
+% CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+% do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+% {topology, Desc} ->
+% TopReq2 = Desc ++ TopReq, %% OTP-4088
+% do_merge_action_reply(T, CtxReq, TopReq2, CmdList)
+% end
+% end;
+% do_merge_action_reply([], CtxReq, TopReq, CmdList) ->
+% #'ActionReply'{contextReply = strip_contextRequest(CtxReq, TopReq),
+% commandReply = lists:reverse(CmdList)}.
+
+% strip_contextRequest(R, TopReq)
+% when R#'ContextRequest'.priority == asn1_NOVALUE,
+% R#'ContextRequest'.emergency == asn1_NOVALUE,
+% TopReq == [] ->
+% asn1_NOVALUE;
+% strip_contextRequest(R, []) ->
+% R#'ContextRequest'{topologyReq = asn1_NOVALUE};
+% strip_contextRequest(R, TopReq) ->
+% R#'ContextRequest'{topologyReq = TopReq}. %% OTP-4088
+
+
+% strip_contextAttrAuditRequest(R)
+% when R#'ContextAttrAuditRequest'.priority == asn1_NOVALUE,
+% R#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE,
+% R#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+% asn1_NOVALUE;
+% strip_contextAttrAuditRequest(R) ->
+% R.
+
+% make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+% Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+% case Text of
+% [$w, $- | _] ->
+% Req#'CommandRequest'{wildcardReturn = 'NULL'};
+% [$o, $-, $w, $- | _] ->
+% Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+% [$o, $- | _] ->
+% Req#'CommandRequest'{optional = 'NULL'};
+% _ ->
+% Req
+% end.
+
+% merge_terminationAudit(AuditReturnParameters) ->
+% lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+% do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+% case H of
+% {auditReturnItem, AuditItem} ->
+% do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+% AuditReturnParameter ->
+% do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+% end;
+% do_merge_terminationAudit([], AuditReturnParameters, []) ->
+% AuditReturnParameters;
+% do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+% AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+% AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+% [AuditReturnParameter | AuditReturnParameters].
+
+% merge_mediaDescriptor(MediaParms) ->
+% do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+% do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+% case H of
+% {streamParm, Parm} when Multi == [] ->
+% do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+% {streamDescriptor, Desc} when One == [] ->
+% do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+% {termState, TS2} when TS == asn1_NOVALUE ->
+% do_merge_mediaDescriptor(T, TS2, One, Multi);
+% _ ->
+% return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+% end;
+% do_merge_mediaDescriptor([], TS, One, Multi) ->
+% if
+% One == [], Multi == [] ->
+% #'MediaDescriptor'{streams = asn1_NOVALUE,
+% termStateDescr = TS};
+% One /= [], Multi == [] ->
+% #'MediaDescriptor'{streams = {oneStream, merge_streamParms(One)},
+% termStateDescr = TS};
+% One == [], Multi /= [] ->
+% #'MediaDescriptor'{streams = {multiStream, lists:reverse(Multi)},
+% termStateDescr = TS}
+% end.
+
+% merge_streamParms(TaggedStreamParms) ->
+% SP = #'StreamParms'{},
+% do_merge_streamParms(TaggedStreamParms, SP).
+
+% do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+% case Tag of
+% local when SP#'StreamParms'.localDescriptor == asn1_NOVALUE ->
+% do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+% remote when SP#'StreamParms'.remoteDescriptor == asn1_NOVALUE ->
+% do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+% control ->
+% LCD =
+% case SP#'StreamParms'.localControlDescriptor of
+% asn1_NOVALUE ->
+% #'LocalControlDescriptor'{propertyParms = []};
+% PrevLCD ->
+% PrevLCD
+% end,
+% LCD2 = do_merge_control_streamParms(D, LCD),
+% do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+% _ ->
+% return_error(0, {do_merge_streamParms, [All, SP]})
+% end;
+% do_merge_streamParms([], SP) when record(SP#'StreamParms'.localControlDescriptor, 'LocalControlDescriptor') ->
+% LCD = SP#'StreamParms'.localControlDescriptor,
+% PP = LCD#'LocalControlDescriptor'.propertyParms,
+% LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+% SP#'StreamParms'{localControlDescriptor = LCD2};
+% do_merge_streamParms([], SP) ->
+% SP.
+
+
+% do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+% case SubTag of
+% group when LCD#'LocalControlDescriptor'.reserveGroup == asn1_NOVALUE ->
+% LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+% do_merge_control_streamParms(T, LCD2);
+% value when LCD#'LocalControlDescriptor'.reserveValue == asn1_NOVALUE ->
+% LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+% do_merge_control_streamParms(T, LCD2);
+% mode when LCD#'LocalControlDescriptor'.streamMode == asn1_NOVALUE ->
+% LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+% do_merge_control_streamParms(T, LCD2);
+% prop ->
+% PP = LCD#'LocalControlDescriptor'.propertyParms,
+% LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+% do_merge_control_streamParms(T, LCD2);
+% _ ->
+% return_error(0, {do_merge_control_streamParms, [All, LCD]})
+% end;
+% do_merge_control_streamParms([], LCD) ->
+% LCD.
+
+% merge_terminationStateDescriptor(Parms) ->
+% TSD = #'TerminationStateDescriptor'{propertyParms = []},
+% do_merge_terminationStateDescriptor(Parms, TSD).
+
+% do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+% case Tag of
+% serviceState when TSD#'TerminationStateDescriptor'.serviceState == asn1_NOVALUE ->
+% TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+% do_merge_terminationStateDescriptor(T, TSD2);
+% eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl == asn1_NOVALUE->
+% TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+% do_merge_terminationStateDescriptor(T, TSD2);
+% propertyParm ->
+% PP = TSD#'TerminationStateDescriptor'.propertyParms,
+% TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+% do_merge_terminationStateDescriptor(T, TSD2)
+% end;
+% do_merge_terminationStateDescriptor([], TSD) ->
+% PP = TSD#'TerminationStateDescriptor'.propertyParms,
+% TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+% ensure_prop_groups({_TokenTag, _Line, Text}) ->
+% Group = [],
+% Groups = [],
+% parse_prop_name(Text, Group, Groups).
+
+% parse_prop_name([Char | Rest] = All, Group, Groups) ->
+% case ?classify_char(Char) of
+% white_space ->
+% parse_prop_name(Rest, Group, Groups);
+% end_of_line ->
+% parse_prop_name(Rest, Group, Groups);
+% _ ->
+% Name = [],
+% do_parse_prop_name(All, Name, Group, Groups)
+% end;
+% parse_prop_name([] = All, Group, Groups) ->
+% Name = [],
+% do_parse_prop_name(All, Name, Group, Groups).
+
+% do_parse_prop_name([Char | Rest], Name, Group, Groups) ->
+% case ?classify_char(Char) of
+% safe_char ->
+% do_parse_prop_name(Rest, [Char | Name], Group, Groups);
+% rest_char when Char == $=, Name /= [] ->
+% %% Now we have a complete name
+% if
+% Name == "v", Group /= [] ->
+% %% v= is a property group delimiter,
+% %% lets create yet another property group.
+% Groups2 = [lists:reverse(Group) | Groups],
+% Group2 = [],
+% parse_prop_value(Rest, Name, Group2, Groups2);
+% true ->
+% %% Use current property group
+% parse_prop_value(Rest, Name, Group, Groups)
+% end;
+% _ ->
+% return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+% end;
+% do_parse_prop_name([], [], [], Groups) ->
+% lists:reverse(Groups);
+% do_parse_prop_name([], [], Group, Groups) ->
+% Group2 = lists:reverse(Group),
+% lists:reverse([Group2 | Groups]);
+% do_parse_prop_name([], Name, Group, Groups) when Name /= [] ->
+% %% Assume end of line
+% Value = [],
+% PP = make_prop_parm(Name, Value),
+% Group2 = lists:reverse([PP | Group]),
+% lists:reverse([Group2 | Groups]).
+
+% parse_prop_value(Chars, Name, Group, Groups) ->
+% Value = [],
+% do_parse_prop_value(Chars, Name, Value, Group, Groups).
+
+% do_parse_prop_value([Char | Rest], Name, Value, Group, Groups) ->
+% case ?classify_char(Char) of
+% end_of_line ->
+% %% Now we have a complete "name=value" pair
+% PP = make_prop_parm(Name, Value),
+% parse_prop_name(Rest, [PP | Group], Groups);
+% _ ->
+% do_parse_prop_value(Rest, Name, [Char | Value], Group, Groups)
+% end;
+% do_parse_prop_value([], Name, Value, Group, Groups) ->
+% %% Assume end of line
+% PP = make_prop_parm(Name, Value),
+% Group2 = lists:reverse([PP | Group]),
+% lists:reverse([Group2 | Groups]).
+
+% make_prop_parm(Name, Value) ->
+% #'PropertyParm'{name = lists:reverse(Name),
+% value = [lists:reverse(Value)]}.
+
+ensure_uint({_TokenTag, Line, Val}, Min, Max) when is_integer(Val) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end;
+ensure_uint({TokenTag, Line, Text}, Min, Max) ->
+ case catch list_to_integer(Text) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint({TokenTag, Line, Val}, Min, Max)
+ end;
+ensure_uint(Val, Min, Max) ->
+ ensure_uint({uint, 0, Val}, Min, Max).
+
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+% ensure_uint32(Int) ->
+% ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when $0 =< Char, Char =< $9 ->
+ Char - $0;
+hchar_to_int(Char) when $A =< Char, Char =< $F ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when $a =< Char, Char =< $f ->
+ Char - $a + 10. % OTP-4710
+
+% value_of({_TokenTag, _Line, Text}) ->
+% Text.
+
+
+% d(F) ->
+% d(F, []).
+
+% d(F, A) ->
+% d(get(dbg), F, A).
+
+% d(true, F, A) ->
+% io:format("~p:" ++ F ++ "~n", [?MODULE|A]);
+% d(_, _, _) ->
+% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_mini_parser.yrl b/lib/megaco/src/text/megaco_text_mini_parser.yrl
new file mode 100644
index 0000000000..50e31b9eb4
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_mini_parser.yrl
@@ -0,0 +1,398 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for mini text decoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%----------------------------------------------------------------------
+
+Expect 1.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ authenticationHeader
+ daddr
+ deviceName
+ domainAddress
+ domainName
+ mId
+ megacoMessage
+ message
+ mtpAddress
+ optSep
+ pathName
+ portNumber
+ safeToken
+ safeToken2
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ %% 'AddToken'
+ %% 'AndAUDITselectToken'
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ %% 'BothToken'
+ %% 'BothwayToken'
+ 'BriefToken'
+ %% 'BufferToken'
+ 'COLON'
+ %% 'ContextAttrToken'
+ 'ContextAuditToken'
+ %% 'ContextListToken'
+ 'CtxToken'
+ 'DelayToken'
+ %% 'DigitMapToken'
+ %% 'DigitMapDescriptorToken'
+ 'DirectionToken'
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ %% 'EmergencyToken'
+ %% 'EmergencyOffToken'
+ %% 'EmergencyValueToken'
+ 'ErrorToken'
+ %% 'EventBufferToken'
+ %% 'EventsToken'
+ %% 'ExternalToken'
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ %% 'IEPSToken'
+ 'ImmAckRequiredToken'
+ 'InSvcToken'
+ 'InactiveToken'
+ %% 'InternalToken'
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ %% 'IntsigDelayToken'
+ %% 'IsolateToken'
+ %% 'IterationToken'
+ 'KeepActiveToken'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ %% 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ %% 'MediaToken'
+ %% 'MessageSegmentToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ %% 'ModeToken'
+ %% 'ModemToken'
+ %% 'ModifyToken'
+ %% 'MoveToken'
+ 'MtpAddressToken'
+ %% 'MuxToken'
+ %% 'NeverNotifyToken'
+ 'NotifyCompletionToken'
+ %% 'NotifyImmediateToken'
+ %% 'NotifyRegulatedToken'
+ 'NotifyToken'
+ 'Nx64Token'
+ %% 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ %% 'OnewayToken'
+ %% 'OnewayExternalToken'
+ %% 'OnewayBothToken'
+ %% 'OrAUDITselectToken'
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ %% 'PackagesToken'
+ 'PendingToken'
+ %% 'PriorityToken'
+ 'ProfileToken'
+ %% 'QuotedChars'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ %% 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'RequestIDToken'
+ %% 'ReservedGroupToken'
+ %% 'ReservedValueToken'
+ %% 'ResetEventsDescriptorToken'
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ %% 'ServiceChangeIncompleteToken'
+ %% 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ %% 'SignalsToken'
+ %% 'StatsToken'
+ 'StreamToken'
+ %% 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ %% 'TimeStampToken'
+ %% 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId : ensure_message('$1', '$2') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+%% safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+%% safeToken2 -> 'BothToken' : '$1' . % v3
+%% safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+%% safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% safeToken2 -> 'ContextListToken' : '$1' . % v3
+%% safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+%% safeToken2 -> 'EmergencyToken' : '$1' .
+%% safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% safeToken2 -> 'EventBufferToken' : '$1' .
+%% safeToken2 -> 'EventsToken' : '$1' .
+%% safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+%% safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+%% safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+%% safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+%% safeToken2 -> 'ModeToken' : '$1' .
+%% safeToken2 -> 'ModifyToken' : '$1' .
+%% safeToken2 -> 'ModemToken' : '$1' .
+%% safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64Token' : '$1' .
+%% safeToken2 -> 'ObservedEventsToken' : '$1' .
+%% safeToken2 -> 'OnewayToken' : '$1' .
+%% safeToken2 -> 'OnewayExternalToken' : '$1' .
+%% safeToken2 -> 'OnewayBothToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+%% safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+safeToken2 -> 'RequestIDToken' : '$1' .
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'SafeChars' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+%% safeToken2 -> 'ReservedGroupToken' : '$1' .
+%% safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+%% safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+%% safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' .
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+%% safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+%% safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_mini_parser.hrl").
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3a.hrl b/lib/megaco/src/text/megaco_text_parser_prev3a.hrl
new file mode 100644
index 0000000000..7faf46afc8
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3a.hrl
@@ -0,0 +1,1670 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3a.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. % We really should ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% The values 0x0, 0xFFFFFFFE and 0xFFFFFFFF are reserved.
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+%% case string:tokens(Addr, [$.]) of
+%% [T1, T2, T3, T4] ->
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and issue the
+ %% the error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) == 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when length(Hex4) =< 4, length(Hex4) > 0 ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ X /= $X, X /= $x,
+ S /= $+, S /= $- ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% and since this functon is only used when creating
+%% a ModemDescriptor, iit is removed.
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+%% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+%% case Text of
+%% "v32b" -> v32bis;
+%% "v22b" -> v22bis;
+%% "v18" -> v18;
+%% "v22" -> v22;
+%% "v32" -> v32;
+%% "v34" -> v34;
+%% "v90" -> v90;
+%% "v91" -> v91;
+%% "synchisdn" -> synchISDN;
+%% "sn" -> synchISDN;
+%% [$x | _] -> ensure_extensionParameter(Token)
+%% end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ "nx64k" -> nx64k; % v2
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_packagesItem,1}]}).
+-endif.
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (length or content) there is really no point in
+ %% "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+
+%% v2 - start
+
+merge_indAudMediaDescriptor({termStateDescr, Val}) ->
+ #'IndAudMediaDescriptor'{termStateDescr = Val};
+merge_indAudMediaDescriptor({streamParm, Val}) ->
+ #'IndAudMediaDescriptor'{streams = {oneStream, Val}};
+merge_indAudMediaDescriptor({streamDescr, Val}) ->
+ #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline, [{merge_indAudLocalControlDescriptor,1}]}).
+-endif.
+merge_indAudLocalControlDescriptor(Parms) ->
+ do_merge_indAudLocalControlDescriptor(Parms,
+ #'IndAudLocalControlDescriptor'{}).
+
+do_merge_indAudLocalControlDescriptor([Parm | Parms], Desc) ->
+ case Parm of
+ modeToken when Desc#'IndAudLocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedGroupToken when Desc#'IndAudLocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedValueToken when Desc#'IndAudLocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when Desc#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE ->
+ PropParms = [#'IndAudPropertyParm'{name = Val}],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when is_list(Desc#'IndAudLocalControlDescriptor'.propertyParms) ->
+ PropParms = Desc#'IndAudLocalControlDescriptor'.propertyParms,
+ PropParms2 = [#'IndAudPropertyParm'{name = Val} | PropParms],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2)
+ end;
+do_merge_indAudLocalControlDescriptor([], Desc) ->
+ case Desc#'IndAudLocalControlDescriptor'.propertyParms of
+ [_ | _] = PropParms -> % List has more then one element
+ PropParms2= lists:reverse(PropParms),
+ Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+ _ ->
+ Desc
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudLocalParm,1}]}).
+-endif.
+ensure_indAudLocalParm(Token) ->
+ case Token of
+ {safeToken, _Line, "mode"} -> modeToken;
+ {safeToken, _Line, "mo"} -> modeToken;
+ {safeToken, _Line, "reservedgroup"} -> reservedGroupToken;
+ {safeToken, _Line, "rg"} -> reservedGroupToken;
+ {safeToken, _Line, "reservedvalue"} -> reservedValueToken;
+ {safeToken, _Line, "rv"} -> reservedValueToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+merge_indAudTerminationStateDescriptor({pkgdName, Val}) ->
+ PropParm = #'IndAudPropertyParm'{name = Val},
+ #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+ #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+merge_indAudTerminationStateDescriptor(bufferToken) ->
+ #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudEventBufferDescriptor,2}]}).
+-endif.
+merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+ IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+ do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+ IAEBD;
+do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+ IAEBD) ->
+ %% BUGBUG BUGBUG BUGBUG
+ %% This is an ugly hack to allow the eventParamName which only
+ %% exists in the text encoding...
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+ensure_indAudSignalListParm(SIG) when is_record(SIG, 'Signal') ->
+ ensure_indAudSignal(SIG).
+
+ensure_indAudSignal(#'Signal'{signalName = SignalName,
+ streamID = asn1_NOVALUE,
+ sigType = asn1_NOVALUE,
+ duration = asn1_NOVALUE,
+ notifyCompletion = asn1_NOVALUE,
+ keepActive = asn1_NOVALUE,
+ sigParList = []}) ->
+ #'IndAudSignal'{signalName = SignalName}.
+
+
+ensure_IADMD({_TokenTag, _Line,
+ #'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE}}) ->
+ #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+
+merge_indAudPackagesDescriptor(#'PackagesItem'{packageName = N,
+ packageVersion = V}) ->
+ #'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudTerminationStateParm,1}]}).
+-endif.
+ensure_indAudTerminationStateParm(Token) ->
+ case Token of
+ {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+ {safeToken, _Line, "si"} -> serviceStatesToken;
+ {safeToken, _Line, "buffer"} -> bufferToken;
+ {safeToken, _Line, "bf"} -> bufferToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+
+%% Types modified by v2:
+
+merge_auditDescriptor([]) ->
+ #'AuditDescriptor'{};
+merge_auditDescriptor(Tokens) when is_list(Tokens) ->
+ case lists:keysearch(terminationAudit, 1, Tokens) of
+ {value, {terminationAudit, TA}} ->
+ case lists:keydelete(terminationAudit, 1, Tokens) of
+ [] ->
+ #'AuditDescriptor'{auditPropertyToken = TA};
+ AuditTokens ->
+ #'AuditDescriptor'{auditToken = AuditTokens,
+ auditPropertyToken = TA}
+ end;
+ false ->
+ #'AuditDescriptor'{auditToken = Tokens}
+ end;
+merge_auditDescriptor(_) ->
+ #'AuditDescriptor'{}.
+
+
+%% v2 - end
+
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeReason == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeDelay == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeMethod == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.timeStamp == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_atom(Val) ->
+ SCI = #'AuditDescriptor'{auditToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_tuple(Val) ->
+ SCI = #'AuditDescriptor'{auditPropertyToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_atom(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditToken,
+ SCI = SCI0#'AuditDescriptor'{auditToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_tuple(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditPropertyToken,
+ SCI = SCI0#'AuditDescriptor'{auditPropertyToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([incomplete|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeIncompleteFlag == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeIncompleteFlag = 'NULL'},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp;
+ audit_item ->
+ SCP#'ServiceChangeParm'.serviceChangeInfo
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}});
+merge_ServiceChangeParm([Parm|_Parms], SCP, _Req) ->
+ Parm2 =
+ case Parm of
+ incomplete ->
+ SCP#'ServiceChangeParm'.serviceChangeIncompleteFlag
+ end,
+ exit({at_most_once_serviceChangeParm, {Parm, Parm2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+ensure_profile({_TokenTag, Line, Text}) ->
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, SID} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = SID}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ {direction, Dir} when Sig#'Signal'.direction == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{direction = Dir}, T, SPL);
+ {requestId, RID} when Sig#'Signal'.requestID == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{requestID = RID}, T, SPL);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body,
+ durationTimer = Duration},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ #'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ durationTimer = [],
+ digitMapBody = asn1_NOVALUE} ->
+ asn1_NOVALUE;
+ #'DigitMapValue'{durationTimer = Body,
+ digitMapBody = Duration} = DMV ->
+ %% Convert to version 1 DigitMapValue
+ DMV#'DigitMapValue'{digitMapBody = Body,
+ durationTimer = Duration};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation == asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, StreamId, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], StreamId, EPL, RA, HasA) ->
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewStreamId, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], StreamId, EPL, RA, yes) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], StreamId, EPL, _RA, no) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, StreamId, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], StreamId, EPL, SRA, HasA) ->
+ case H of
+ keepActive when SRA#'SecondRequestedActions'.keepActive =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {stream, NewStreamId} when StreamId =:= asn1_NOVALUE ->
+ do_merge_secondEventParameters(T, NewStreamId, EPL, SRA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], StreamId, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], StreamId, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ ensure_transactionAck2(Text, []).
+
+ensure_transactionAck2([], Acc) ->
+ Id = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ensure_transactionAck2([$- | Id2], Acc) ->
+ Id1 = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id1),
+ lastAck = ensure_transactionID(Id2)};
+ensure_transactionAck2([H|T], Acc) ->
+ ensure_transactionAck2(T, [H|Acc]).
+
+
+merge_context_request(CR, []) ->
+ CR;
+merge_context_request(CR, [H|T]) ->
+ case H of
+ {priority, Int} when CR#'ContextRequest'.priority == asn1_NOVALUE ->
+ merge_context_request(CR#'ContextRequest'{priority = Int}, T);
+
+ {emergency, Bool} when CR#'ContextRequest'.emergency == asn1_NOVALUE ->
+ merge_context_request(CR#'ContextRequest'{emergency = Bool}, T);
+
+ {topology, Desc} when CR#'ContextRequest'.topologyReq == asn1_NOVALUE ->
+ merge_context_request(CR#'ContextRequest'{topologyReq = Desc}, T);
+
+ {iepsCallind, Ind} when CR#'ContextRequest'.iepsCallind == asn1_NOVALUE ->
+ merge_context_request(CR#'ContextRequest'{iepsCallind = Ind}, T);
+
+ {prop, Prop} when CR#'ContextRequest'.contextProp == asn1_NOVALUE ->
+ merge_context_request(CR#'ContextRequest'{contextProp = [Prop]}, T);
+ {Tag, Val} ->
+ Val2 =
+ case Tag of
+ priority -> CR#'ContextRequest'.priority;
+ emergency -> CR#'ContextRequest'.emergency;
+ topology -> CR#'ContextRequest'.topologyReq;
+ iepsCallind -> CR#'ContextRequest'.iepsCallind;
+ prop -> CR#'ContextRequest'.contextProp
+ end,
+ exit({at_most_once_contextProperty, {Tag, Val, Val2}})
+ end.
+
+
+merge_context_attr_audit_request(CAAR, []) ->
+ CAAR;
+merge_context_attr_audit_request(CAAR, [H|T]) ->
+ case H of
+ priorityAudit when CAAR#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{priority = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ topologyAudit when CAAR#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{topology = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ iepsCallind when CAAR#'ContextAttrAuditRequest'.iepsCallind == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{iepsCallind = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} when CAAR#'ContextAttrAuditRequest'.contextPropAud == asn1_NOVALUE ->
+ CPA = [#'IndAudPropertyParm'{name = Name}],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} ->
+ CPA = CAAR#'ContextAttrAuditRequest'.contextPropAud,
+ CPA2 = [#'IndAudPropertyParm'{name = Name}|CPA],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA2},
+ merge_context_attr_audit_request(CAAR2, T)
+
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_request,2}]}).
+-endif.
+merge_action_request(CtxId, Items) ->
+ do_merge_action_request(Items, [], asn1_NOVALUE, asn1_NOVALUE, CtxId).
+
+do_merge_action_request([H|T], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ case H of
+ {commandRequest, CmdReq} ->
+ do_merge_action_request(T, [CmdReq|CmdReqs],
+ CtxReq, CtxAuditReq, CtxId);
+
+ {contextProps, ContextReq} when CtxReq == asn1_NOVALUE ->
+ do_merge_action_request(T, CmdReqs,
+ ContextReq, CtxAuditReq, CtxId);
+
+ {contextAudit, ContextAuditReq} when CtxAuditReq == asn1_NOVALUE ->
+ do_merge_action_request(T, CmdReqs,
+ CtxReq, ContextAuditReq, CtxId)
+ end;
+do_merge_action_request([], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ #'ActionRequest'{contextId = CtxId,
+ contextRequest = strip_ContextRequest(CtxReq),
+ contextAttrAuditReq = strip_ContextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReqs)}.
+
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(Items) ->
+ do_merge_action_reply(Items, asn1_NOVALUE, asn1_NOVALUE, []).
+
+do_merge_action_reply([], Err, Ctx, Cmds) ->
+ #'ActionReply'{errorDescriptor = Err,
+ contextReply = strip_ContextRequest(Ctx),
+ commandReply = lists:reverse(Cmds)};
+do_merge_action_reply([H|T], Err0, Ctx0, Cmds) ->
+ case H of
+ {error, Err1} when Err0 == asn1_NOVALUE ->
+ do_merge_action_reply(T, Err1, Ctx0, Cmds);
+ {command, Cmd} ->
+ do_merge_action_reply(T, Err0, Ctx0, [Cmd | Cmds]);
+ {context, Ctx1} when Ctx0 == asn1_NOVALUE ->
+ do_merge_action_reply(T, Err0, Ctx1, Cmds)
+ end.
+
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextProp = []}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(asn1_NOVALUE) ->
+ asn1_NOVALUE;
+strip_ContextRequest(R) ->
+ R.
+
+strip_ContextAttrAuditRequest(asn1_NOVALUE) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepsCallind = asn1_NOVALUE,
+ contextPropAud = []}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(R) ->
+ R.
+
+merge_AmmRequest_descriptors([], Acc) ->
+ lists:reverse(Acc);
+merge_AmmRequest_descriptors([{_, deprecated}|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, Acc);
+merge_AmmRequest_descriptors([Desc|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, [Desc|Acc]).
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ statistics when SP#'StreamParms'.statisticsDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{statisticsDescriptor = D});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor,
+ 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ parse_prop_name(Text, Group).
+
+parse_prop_name([Char | Rest] = All, Group) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group)
+ end;
+parse_prop_name([] = All, Group) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group).
+
+do_parse_prop_name([Char | Rest], Name, Group)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ NewGroup = [],
+ [lists:reverse(Group) | parse_prop_value(Rest, Name, NewGroup)];
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], []) ->
+ [];
+do_parse_prop_name([], [], Group) ->
+ [lists:reverse(Group)];
+do_parse_prop_name([], Name, Group) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,3}]}).
+-endif.
+parse_prop_value(Chars, Name, Group) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group]);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group)
+ end;
+do_parse_prop_value([], Name, Value, Group) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ Groups.
+
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+
+%% -------------------------------------------------------------------
+
+% d(F) ->
+% d(F,[]).
+% d(F, A) ->
+% d(get(dbg), F, A).
+
+% d(true, F, A) ->
+% io:format("DBG:~w:" ++ F ++ "~n", [?MODULE | A]);
+% d(_, _, _) ->
+% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3a.yrl b/lib/megaco/src/text/megaco_text_parser_prev3a.yrl
new file mode 100644
index 0000000000..b8c39a5f33
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3a.yrl
@@ -0,0 +1,1591 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%
+%% NOTE 1 - This syntax specification does not enforce all restrictions
+%% on element inclusions and values. Some additional
+%% restrictions are stated in comments and other restrictions
+%% appear in the text of this Recommendation. These additional
+%% restrictions are part of the protocol even though not
+%% enforced by this Recommendation.
+%% NOTE 2 - The syntax is context-dependent. For example, "Add" can be
+%% the AddToken or a NAME depending on the context in which it
+%% occurs.
+%%
+%% Everything in the ABNF and text encoding is case insensitive. This
+%% includes TerminationIDs, digitmap Ids etc. SDP is case sensitive as
+%% per RFC 2327.
+%%
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 118.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestBody
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ authenticationHeader
+ commandReplyList
+ commandReplys %% v3
+ commandRequest
+ contextAttrDescriptor %% v3
+ contextAttrDescProp %% v3
+ contextAttrDescProps %% v3
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextID
+ contextProperties %% v3
+ contextProperty
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ direction %% v3
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlState
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStream
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+
+ %% v2 - start
+ indAudauditReturnParameter
+ indAuddigitMapDescriptor
+ indAudeventBufferDescriptor
+ indAudeventSpec
+ indAudeventSpecParameter
+ %% indAudeventSpecParameterList
+ indAudeventsDescriptor
+ indAudlocalControlDescriptor
+ indAudlocalParm
+ indAudlocalParmList
+ indAudmediaDescriptor
+ indAudmediaParm
+ %% indAudmediaParmList
+ indAudpackagesDescriptor
+ indAudrequestedEvent
+ indAudsignalsDescriptor
+ indAudsignalList
+ %% indAudsignalListParm
+ indAudsignalParm
+ %% indAudsignalRequest
+ indAudstreamDescriptor
+ indAudstreamParm
+ indAudstatisticsDescriptor
+ indAudterminationAudit
+ indAudterminationAuditList
+ indAudterminationStateDescriptor
+ indAudterminationStateParm
+ %% indAudterminationStateParmList
+ optIndAudeventSpecParameter
+ optIndAudsignalParm
+ %% v2 - end
+
+ indAudcontextAttrDescriptor %% v3
+
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor % Deprecated as of Corr 1
+ modemType % Deprecated as of Corr 1
+ modemTypeList % Deprecated as of Corr 1
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ % observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceState
+ serviceStates
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ terminationA
+ terminationAudit
+ terminationB
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyTriple
+ topologyTripleList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothToken' %% v3
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ 'ContextAttrToken' %% v3
+ 'ContextAuditToken'
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DirectionToken' %% v3
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'EmergencyOffToken'
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'ExternalToken' %% v3
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'IEPSToken' %% v3
+ 'ImmAckRequiredToken'
+ 'InSvcToken'
+ 'InactiveToken'
+ 'InternalToken' %% v3
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'IsolateToken'
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NotifyCompletionToken'
+ 'NotifyToken'
+ 'Nx64kToken' %% v2
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'RequestIDToken' %% v3
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceChangeIncompleteToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ 'AndAUDITSelectToken' %% OTP-7534: v3-fix
+ 'ContextListToken' %% OTP-7534: v3-fix
+ 'EmergencyValueToken' %% OTP-7534: v3-fix
+ 'IntsigDelayToken' %% OTP-7534: v3-fix
+ 'IterationToken' %% OTP-7534: v3-fix
+ 'MessageSegmentToken' %% OTP-7534: v3-fix
+ 'NeverNotifyToken' %% OTP-7534: v3-fix
+ 'NotifyImmediateToken' %% OTP-7534: v3-fix
+ 'NotifyRegulatedToken' %% OTP-7534: v3-fix
+ 'OnewayBothToken' %% OTP-7534: v3-fix
+ 'OnewayExternalToken' %% OTP-7534: v3-fix
+ 'OrAUDITselectToken' %% OTP-7534: v3-fix
+ 'ResetEventsDescriptorToken' %% OTP-7534: v3-fix
+ 'SegmentationCompleteToken' %% OTP-7534: v3-fix
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody : ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck transactionAckList 'RBRKT' : ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT'
+ : #'TransactionPending'{transactionId = ensure_transactionID('$3') } .
+
+transactionRequest -> 'TransToken'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList : ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestBody 'RBRKT'
+ : merge_action_request('$3', '$5') .
+
+actionRequestBody -> actionRequestItem actionRequestItems : ['$1' | '$2'] .
+
+actionRequestItems -> 'COMMA' actionRequestItem actionRequestItems
+ : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+actionRequestItem -> contextProperties : {contextProps, '$1'} .
+actionRequestItem -> contextAudit : {contextAudit, '$1'} .
+actionRequestItem -> commandRequest : {commandRequest, '$1'} .
+
+contextProperties -> contextAttrDescriptor :
+ merge_context_request(#'ContextRequest'{}, '$1') .
+
+contextAttrDescriptor -> 'ContextAttrToken'
+ 'LBRKT' contextAttrDescProp
+ contextAttrDescProps 'RBRKT'
+ : ['$3' | '$4'] .
+
+contextAttrDescProp -> contextProperty : '$1' .
+
+contextAttrDescProps -> 'COMMA' contextAttrDescProp contextAttrDescProps
+ : ['$2' | '$3'] .
+contextAttrDescProps -> '$empty' : [] .
+
+%% at-most-once
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+contextProperty -> 'EmergencyOffToken' : {emergency, false}.
+contextProperty -> 'IEPSToken' : {iepsCallind, true} . % BMK BMK
+contextProperty -> propertyParm : {prop, '$1'} .
+
+contextAudit -> 'ContextAuditToken' 'LBRKT' indAudcontextAttrDescriptor 'RBRKT'
+ : merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, '$3') .
+
+indAudcontextAttrDescriptor -> 'ContextAttrToken'
+ 'LBRKT' contextAuditProperty
+ contextAuditProperties 'RBRKT'
+ : ['$3' | '$4'] .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty contextAuditProperties
+ : ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once .
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+contextAuditProperty -> 'IEPSToken' : iepsCallind .
+contextAuditProperty -> pkgdName : {prop, '$1'} .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID
+ 'LBRKT'
+ optImmAckRequired transactionReplyBody
+ 'RBRKT'
+ : #'TransactionReply'{transactionId = '$3',
+ immAckRequired = '$5',
+ transactionResult = '$6'} .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor : {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList : {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReplys commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ [{error, '$2'}] .
+commandReplyList -> 'COMMA' commandReplys commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+commandReplys -> serviceChangeReply : {command, '$1'} .
+commandReplys -> auditReply : {command, '$1'} .
+commandReplys -> ammsReply : {command, '$1'} .
+commandReplys -> notifyReply : {command, '$1'} .
+commandReplys -> contextProperties : {context, '$1'} .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' terminationID ammRequestBody :
+ Descs = merge_AmmRequest_descriptors('$4', []),
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = ['$3'],
+ descriptors = Descs}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, deprecated}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+ammParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' terminationID ammsReplyBody
+ : {'$1', #'AmmsReply'{terminationID = ['$3'],
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL' terminationID
+ optAuditDescriptor
+ : make_commandRequest({subtractReq, '$1'},
+ #'SubtractRequest'{terminationID = ['$3'],
+ auditDescriptor = '$4'}) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+auditRequest -> 'AuditCapToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther
+ : {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther
+ : {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList : {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' : {contextAuditResult, '$2'} .
+
+auditOther -> terminationID :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = []}} .
+auditOther -> terminationID 'LBRKT' terminationAudit 'RBRKT' :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = '$3'}} .
+
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor.
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} .
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT' :
+ merge_auditDescriptor('$3') .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken.
+auditItem -> 'EventBufferToken' : eventBufferToken.
+auditItem -> 'EventsToken' : eventsToken .
+auditItem -> indAudterminationAudit : {terminationAudit, '$1'} . % v2
+%%
+%% IGv11 - end
+
+
+%% v2 - start
+%%
+indAudterminationAudit -> indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$1' | '$2'] .
+
+indAudterminationAuditList -> 'COMMA' indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$2' | '$3'] .
+indAudterminationAuditList -> '$empty' : [] .
+
+indAudauditReturnParameter -> indAudmediaDescriptor
+ : {indAudMediaDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventsDescriptor
+ : {indAudEventsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudsignalsDescriptor
+ : {indAudSignalsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAuddigitMapDescriptor
+ : {indAudDigitMapDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventBufferDescriptor
+ : {indAudEventBufferDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudstatisticsDescriptor
+ : {indAudStatisticsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudpackagesDescriptor
+ : {indAudPackagesDescriptor, '$1'} .
+
+
+indAudmediaDescriptor -> 'MediaToken' 'LBRKT'
+ indAudmediaParm 'RBRKT'
+ : merge_indAudMediaDescriptor('$3') .
+
+%% at-most-once per item
+%% and either streamParm or streamDescriptor but not both
+%% <rambling>
+%% This is solved in another way in text than in binary :(
+%% Instead of having a list of indAudmediaParm we put this
+%% stuff in the indAudterminationAuditList with several
+%% indAudmediaDescriptor's.
+%% </rambling>
+%%
+
+indAudmediaParm -> indAudstreamParm : {streamParm, '$1'} .
+indAudmediaParm -> indAudstreamDescriptor : {streamDescr, '$1'} .
+indAudmediaParm -> indAudterminationStateDescriptor : {termStateDescr, '$1'} .
+
+%% at-most-once
+indAudstreamParm -> indAudlocalControlDescriptor
+ : #'IndAudStreamParms'{localControlDescriptor = '$1'} .
+indAudstreamParm -> indAudstatisticsDescriptor
+ : #'IndAudStreamParms'{statisticsDescriptor = '$1'} .
+
+indAudstreamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' indAudstreamParm 'RBRKT'
+ : #'IndAudStreamDescriptor'{streamID = '$3',
+ streamParms = '$5'} .
+
+
+indAudlocalControlDescriptor -> 'LocalControlToken'
+ 'LBRKT' indAudlocalParm indAudlocalParmList 'RBRKT' :
+ merge_indAudLocalControlDescriptor(['$3'| '$4']) .
+
+indAudlocalParmList -> 'COMMA' indAudlocalParm indAudlocalParmList : ['$2'| '$3'] .
+indAudlocalParmList -> '$empty' : [] .
+
+%% at-most-once per item
+%%
+indAudlocalParm -> safeToken : ensure_indAudLocalParm('$1') .
+
+indAudterminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' indAudterminationStateParm 'RBRKT'
+ :
+ merge_indAudTerminationStateDescriptor('$3') .
+
+%% at-most-once per item
+%%
+
+indAudterminationStateParm -> safeToken :
+ ensure_indAudTerminationStateParm('$1') .
+
+indAudeventBufferDescriptor -> 'EventBufferToken'
+ 'LBRKT' indAudeventSpec 'RBRKT' : '$3' .
+
+indAudeventSpec -> pkgdName optIndAudeventSpecParameter
+ : merge_indAudEventBufferDescriptor('$1','$2') .
+
+optIndAudeventSpecParameter -> 'LBRKT' indAudeventSpecParameter 'RBRKT'
+ : '$2' .
+optIndAudeventSpecParameter -> '$empty' : asn1_NOVALUE .
+
+
+indAudeventSpecParameter -> eventStream : {streamID, '$1'} .
+indAudeventSpecParameter -> eventParameterName : {eventParameterName, '$1'} .
+
+indAudeventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' indAudrequestedEvent 'RBRKT'
+ : #'IndAudEventsDescriptor'{requestID = '$3',
+ pkgdName = '$5'} .
+
+indAudrequestedEvent -> pkgdName : '$1' .
+
+
+indAudsignalsDescriptor -> 'SignalsToken' optIndAudsignalParm : '$2' .
+
+
+optIndAudsignalParm -> 'LBRKT' 'RBRKT' : asn1_NOVALUE .
+optIndAudsignalParm -> 'LBRKT' indAudsignalParm 'RBRKT' : '$2' .
+
+indAudsignalParm -> indAudsignalList : {seqSigList, '$1'} .
+indAudsignalParm -> signalRequest : {signal, ensure_indAudSignal('$1')} .
+
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm 'RBRKT' :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3'),
+ signalList =
+ ensure_indAudSignalListParm('$5')} .
+
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+indAuddigitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_IADMD('$1') .
+
+indAudstatisticsDescriptor -> 'StatsToken' 'LBRKT' pkgdName 'RBRKT' :
+ #'IndAudStatisticsDescriptor'{statName = '$3'} .
+
+indAudpackagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem 'RBRKT'
+ : merge_indAudPackagesDescriptor('$3') .
+
+eventStream -> 'StreamToken' 'EQUAL' streamID : '$3' .
+
+
+%%
+%% v2 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' terminationID
+ 'LBRKT' notifyRequestBody 'RBRKT'
+ : make_commandRequest({notifyReq, '$1'},
+ setelement(#'NotifyRequest'.terminationID, '$5', ['$3'])) .
+
+notifyRequestBody -> observedEventsDescriptor
+ : #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor
+ : #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' terminationID notifyReplyBody
+ : {notifyReply,
+ #'NotifyReply'{terminationID = ['$3'],
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' terminationID
+ 'LBRKT' serviceChangeDescriptor 'RBRKT'
+ : make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = ['$3'],
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' terminationID serviceChangeReplyBody
+ : {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = ['$3'],
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT'
+ : {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT'
+ : {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' : {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT' errorText 'RBRKT'
+ : #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+%% '-' is used for NULL context
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+%% terminationIDList -> LBRKT terminationID *(COMMA terminationID) RBRKT .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT'
+ : ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat
+ : ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-onc .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs} } .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+streamParm -> statisticsDescriptor : {statistics, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm
+ terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue :
+ setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue :
+ '$2' .
+
+parmValue -> 'NEQUAL' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT'
+ : #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value :
+ #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec eventSpecList 'RBRKT'
+ : ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceState : '$3' .
+
+serviceState -> 'TestToken' : test .
+serviceState -> 'OutOfSvcToken' : outOfSvc .
+serviceState -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlState : '$3' .
+
+eventBufferControlState -> 'OffToken' : off .
+eventBufferControlState -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList :
+ #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' : #'RequestedEvent'{evParList = []} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT'
+ : {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT'
+ : {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents : ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody
+ : setelement(#'SecondRequestedEvent'.pkgdName, '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter secondEventParameters 'RBRKT'
+ : merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' : #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters : ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' :
+ ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' : [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther /
+%% notifyCompletion / KeepActiveToken /
+%% direction / sigRequestID
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason)
+%% RBRKT)
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken /
+%% InterruptByNewSignalsDescrToken /
+%% OtherReasonToken )
+%% sigDirection = DirectionToken EQUAL direction
+%% sigRequestID = RequestIDToken EQUAL RequestID
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID :
+ {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType :
+ {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken :
+ {duration, ensure_uint16('$3')} .
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT' :
+ {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+sigParameter -> 'DirectionToken' 'EQUAL' direction : {direction, '$3'} .
+sigParameter -> 'RequestIDToken' 'EQUAL' requestID : {requestId, '$3'} .
+sigParameter -> safeToken parmValue :
+ {other, ensure_NAME('$1'), '$2'}.
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+direction -> 'ExternalToken' : external .
+direction -> 'InternalToken' : internal .
+direction -> 'BothToken' : both .
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms :
+ ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+
+observedEvent -> timeStamp optSep 'COLON' optSep pkgdName observedEventBody :
+ merge_observed_event('$6', '$5', '$1') .
+observedEvent -> optSep pkgdName observedEventBody :
+ merge_observed_event('$3', '$2', asn1_NOVALUE) .
+
+observedEventBody -> 'LBRKT' observedEventParameter
+ observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+%% Deprecated as of Corr 1
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms .
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms.
+modemTypeList -> 'COMMA' modemType modemTypeList.
+modemTypeList -> '$empty'.
+modemType -> safeToken.
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParms 'RBRKT' :
+ ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> 'COMMA' propertyParm propertyParms : ['$2' | '$3'] .
+propertyParms -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_DMD('$1') .
+
+%% each parameter at-most-once, except auditItem
+%% at most one of either serviceChangeAddress or serviceChangeMgcId but
+%% not both. serviceChangeMethod and serviceChangeReason are REQUIRED
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp, '$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+serviceChangeParm -> 'ServiceChangeIncompleteToken' : incomplete . % v3
+serviceChangeParm -> auditItem : {audit_item, '$1'} . % v2
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken :
+ ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber :
+ {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'} .
+servChgReplyParm -> timeStamp : {time_stamp,'$1'} .
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem
+ packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter
+ statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT' topologyTriple
+ topologyTripleList 'RBRKT' : ['$3' | '$4'] .
+
+terminationA -> terminationID : '$1' .
+
+terminationB -> terminationID : '$1' .
+
+topologyTriple -> terminationA 'COMMA'
+ terminationB 'COMMA'
+ topologyDirection :
+ #'TopologyRequest'{terminationFrom = '$1',
+ terminationTo = '$3',
+ topologyDirection = '$5'} .
+
+topologyTripleList -> '$empty' : [] .
+topologyTripleList -> 'COMMA' topologyTriple topologyTripleList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : bothway .
+topologyDirection -> 'IsolateToken' : isolate .
+topologyDirection -> 'OnewayToken' : oneway .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' : ensure_value('$1') .
+value -> safeToken : ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+%% BMK BMK safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothToken' : '$1' . % v3
+safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% v3-safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% v2-safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+%% v3-
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% v2-safeToken2 -> 'EventBufferToken' : '$1' .
+%% v2-safeToken2 -> 'EventsToken' : '$1' .
+%% v3-safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+%% v3-safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+%% v3-safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% v2-safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+safeToken2 -> 'ModeToken' : '$1' .
+%% BMK BMK safeToken2 -> 'ModifyToken' : '$1' .
+%% v2-safeToken2 -> 'ModemToken' : '$1' .
+%% BMK BMK safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% v2-safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64kToken' : '$1' .
+%% v2-safeToken2 -> 'ObservedEventsToken' : '$1' .
+safeToken2 -> 'OnewayToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% v2-safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+%% BMK BMK safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+%% v3-
+safeToken2 -> 'RequestIDToken' : '$1' . % v3
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+safeToken2 -> 'ReservedGroupToken' : '$1' .
+safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' . % v3
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% v2-safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% v2-safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+%% BMK BMK safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+%% BMK BMK safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+%% <OTP-7534>
+safeToken2 -> 'AndAUDITSelectToken' : '$1' . % v3
+safeToken2 -> 'ContextListToken' : '$1' . % v3
+safeToken2 -> 'EmergencyValueToken' : '$1' . % v3
+safeToken2 -> 'IntsigDelayToken' : '$1' . % v3
+safeToken2 -> 'IterationToken' : '$1' . % v3
+safeToken2 -> 'MessageSegmentToken' : '$1' . % v3
+safeToken2 -> 'NeverNotifyToken' : '$1' . % v3
+safeToken2 -> 'NotifyImmediateToken' : '$1' . % v3
+safeToken2 -> 'NotifyRegulatedToken' : '$1' . % v3
+safeToken2 -> 'OnewayBothToken' : '$1' . % v3
+safeToken2 -> 'OnewayExternalToken' : '$1' . % v3
+safeToken2 -> 'OrAUDITselectToken' : '$1' . % v3
+safeToken2 -> 'ResetEventsDescriptorToken' : '$1' . % v3
+safeToken2 -> 'SegmentationCompleteToken' : '$1' . % v3
+%% </OTP-7534>
+
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_prev3a.hrl").
+
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3b.hrl b/lib/megaco/src/text/megaco_text_parser_prev3b.hrl
new file mode 100644
index 0000000000..ba10dfb943
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3b.hrl
@@ -0,0 +1,1717 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3b.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% The values 0x0, 0xFFFFFFFE and 0xFFFFFFFF are reserved.
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+%% case string:tokens(Addr, [$.]) of
+%% [T1, T2, T3, T4] ->
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and issue the
+ %% the error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) == 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when length(Hex4) =< 4, length(Hex4) > 0 ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ X /= $X, X /= $x,
+ S /= $+, S /= $- ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% and since this functon is only used when creating
+%% a ModemDescriptor, iit is removed.
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+%% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+%% case Text of
+%% "v32b" -> v32bis;
+%% "v22b" -> v22bis;
+%% "v18" -> v18;
+%% "v22" -> v22;
+%% "v32" -> v32;
+%% "v34" -> v34;
+%% "v90" -> v90;
+%% "v91" -> v91;
+%% "synchisdn" -> synchISDN;
+%% "sn" -> synchISDN;
+%% [$x | _] -> ensure_extensionParameter(Token)
+%% end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ "nx64k" -> nx64k; % v2
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_packagesItem,1}]}).
+-endif.
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (length or content) there is really no point in
+ %% "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+
+%% v2 - start
+
+merge_indAudMediaDescriptor_streams(asn1_NOVALUE, []) ->
+ asn1_NOVALUE;
+merge_indAudMediaDescriptor_streams(Stream, [])
+ when is_record(Stream, 'IndAudStreamParms') ->
+ {oneStream, Stream};
+merge_indAudMediaDescriptor_streams(asn1_NOVALUE, MStreams) ->
+ {multiStream, lists:reverse(MStreams)};
+merge_indAudMediaDescriptor_streams(Stream, MStreams) ->
+ return_error(0,
+ {invalid_indAudMediaDescriptor_streams, {Stream, MStreams}}).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudMediaDescriptor,1}]}).
+-endif.
+merge_indAudMediaDescriptor(Vals) ->
+ merge_indAudMediaDescriptor(Vals, asn1_NOVALUE, asn1_NOVALUE, []).
+
+merge_indAudMediaDescriptor([], TSD, OneStream, MultiStreams) ->
+ Streams = merge_indAudMediaDescriptor_streams(OneStream, MultiStreams),
+ #'IndAudMediaDescriptor'{termStateDescr = TSD,
+ streams = Streams};
+
+merge_indAudMediaDescriptor([{termStateDescr, H}|T], asn1_NOVALUE, OS, MS) ->
+ merge_indAudMediaDescriptor(T, H, OS, MS);
+merge_indAudMediaDescriptor([{streamDescr, Val}|T], TSD, asn1_NOVALUE, MS) ->
+ merge_indAudMediaDescriptor(T, TSD, asn1_NOVALUE, [Val|MS]);
+merge_indAudMediaDescriptor([{streamParm, Val}|T], TSD, asn1_NOVALUE, []) ->
+ merge_indAudMediaDescriptor(T, TSD, Val, []);
+merge_indAudMediaDescriptor(Vals, TSD, OneStream, MultiStream) ->
+ return_error(0, {invalid_indAudMediaDescriptor,
+ {Vals, TSD, OneStream, MultiStream}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudLocalControlDescriptor,1}]}).
+-endif.
+merge_indAudLocalControlDescriptor(Parms) ->
+ do_merge_indAudLocalControlDescriptor(Parms,
+ #'IndAudLocalControlDescriptor'{}).
+
+do_merge_indAudLocalControlDescriptor([Parm | Parms], Desc) ->
+ case Parm of
+ modeToken when Desc#'IndAudLocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedGroupToken when Desc#'IndAudLocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedValueToken when Desc#'IndAudLocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when Desc#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE ->
+ PropParms = [#'IndAudPropertyParm'{name = Val}],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when is_list(Desc#'IndAudLocalControlDescriptor'.propertyParms) ->
+ PropParms = Desc#'IndAudLocalControlDescriptor'.propertyParms,
+ PropParms2 = [#'IndAudPropertyParm'{name = Val} | PropParms],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2)
+ end;
+do_merge_indAudLocalControlDescriptor([], Desc) ->
+ case Desc#'IndAudLocalControlDescriptor'.propertyParms of
+ [_ | _] = PropParms -> % List has more then one element
+ PropParms2= lists:reverse(PropParms),
+ Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+ _ ->
+ Desc
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudLocalParm,1}]}).
+-endif.
+ensure_indAudLocalParm(Token) ->
+ case Token of
+ {safeToken, _Line, "mode"} -> modeToken;
+ {safeToken, _Line, "mo"} -> modeToken;
+ {safeToken, _Line, "reservedgroup"} -> reservedGroupToken;
+ {safeToken, _Line, "rg"} -> reservedGroupToken;
+ {safeToken, _Line, "reservedvalue"} -> reservedValueToken;
+ {safeToken, _Line, "rv"} -> reservedValueToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+merge_indAudTerminationStateDescriptor({pkgdName, Val}) ->
+ PropParm = #'IndAudPropertyParm'{name = Val},
+ #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+ #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+merge_indAudTerminationStateDescriptor(bufferToken) ->
+ #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudEventBufferDescriptor,2}]}).
+-endif.
+merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+ IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+ do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+ IAEBD;
+do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+ IAEBD) ->
+ %% BUGBUG BUGBUG BUGBUG
+ %% This is an ugly hack to allow the eventParamName which only
+ %% exists in the text encoding...
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+ensure_indAudSignalListParm(SIG) when is_record(SIG, 'Signal') ->
+ ensure_indAudSignal(SIG).
+
+ensure_indAudSignal(#'Signal'{signalName = SignalName,
+ streamID = asn1_NOVALUE,
+ sigType = asn1_NOVALUE,
+ duration = asn1_NOVALUE,
+ notifyCompletion = asn1_NOVALUE,
+ keepActive = asn1_NOVALUE,
+ sigParList = []}) ->
+ #'IndAudSignal'{signalName = SignalName}.
+
+
+ensure_IADMD({_TokenTag, _Line,
+ #'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE}}) ->
+ #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+
+merge_indAudPackagesDescriptor(#'PackagesItem'{packageName = N,
+ packageVersion = V}) ->
+ #'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudTerminationStateParm,1}]}).
+-endif.
+ensure_indAudTerminationStateParm(Token) ->
+ case Token of
+ {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+ {safeToken, _Line, "si"} -> serviceStatesToken;
+ {safeToken, _Line, "buffer"} -> bufferToken;
+ {safeToken, _Line, "bf"} -> bufferToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+
+%% Types modified by v2:
+
+merge_auditDescriptor([]) ->
+ #'AuditDescriptor'{};
+merge_auditDescriptor(Tokens) when is_list(Tokens) ->
+ case lists:keysearch(terminationAudit, 1, Tokens) of
+ {value, {terminationAudit, TA}} ->
+ case lists:keydelete(terminationAudit, 1, Tokens) of
+ [] ->
+ #'AuditDescriptor'{auditPropertyToken = TA};
+ AuditTokens ->
+ #'AuditDescriptor'{auditToken = AuditTokens,
+ auditPropertyToken = TA}
+ end;
+ false ->
+ #'AuditDescriptor'{auditToken = Tokens}
+ end;
+merge_auditDescriptor(_) ->
+ #'AuditDescriptor'{}.
+
+
+%% v2 - end
+
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeReason == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeDelay == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeMethod == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.timeStamp == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_atom(Val) ->
+ SCI = #'AuditDescriptor'{auditToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_tuple(Val) ->
+ SCI = #'AuditDescriptor'{auditPropertyToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_atom(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditToken,
+ SCI = SCI0#'AuditDescriptor'{auditToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_tuple(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditPropertyToken,
+ SCI = SCI0#'AuditDescriptor'{auditPropertyToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([incomplete|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeIncompleteFlag == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeIncompleteFlag = 'NULL'},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp;
+ audit_item ->
+ SCP#'ServiceChangeParm'.serviceChangeInfo
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}});
+merge_ServiceChangeParm([Parm|_Parms], SCP, _Req) ->
+ Parm2 =
+ case Parm of
+ incomplete ->
+ SCP#'ServiceChangeParm'.serviceChangeIncompleteFlag
+ end,
+ exit({at_most_once_serviceChangeParm, {Parm, Parm2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_profile,1}]}).
+-endif.
+ensure_profile(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, SID} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = SID}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ {direction, Dir} when Sig#'Signal'.direction == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{direction = Dir}, T, SPL);
+ {requestId, RID} when Sig#'Signal'.requestID == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{requestID = RID}, T, SPL);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body,
+ durationTimer = Duration},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ #'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ durationTimer = [],
+ digitMapBody = asn1_NOVALUE} ->
+ asn1_NOVALUE;
+ #'DigitMapValue'{durationTimer = Body,
+ digitMapBody = Duration} = DMV ->
+ %% Convert to version 1 DigitMapValue
+ DMV#'DigitMapValue'{digitMapBody = Body,
+ durationTimer = Duration};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation == asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, StreamId, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], StreamId, EPL, RA, HasA) ->
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {stream, NewStreamId} when StreamId =:= asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewStreamId, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], StreamId, EPL, RA, yes) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], StreamId, EPL, _RA, no) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, StreamId, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], StreamId, EPL, SRA, HasA) ->
+ case H of
+ keepActive when SRA#'SecondRequestedActions'.keepActive =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {stream, NewStreamId} when StreamId =:= asn1_NOVALUE ->
+ do_merge_secondEventParameters(T, NewStreamId, EPL, SRA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], StreamId, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], StreamId, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ ensure_transactionAck2(Text, []).
+
+ensure_transactionAck2([], Acc) ->
+ Id = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ensure_transactionAck2([$- | Id2], Acc) ->
+ Id1 = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id1),
+ lastAck = ensure_transactionID(Id2)};
+ensure_transactionAck2([H|T], Acc) ->
+ ensure_transactionAck2(T, [H|Acc]).
+
+
+merge_context_request(asn1_NOVALUE, Prop) ->
+ merge_context_request(#'ContextRequest'{}, Prop);
+
+merge_context_request(#'ContextRequest'{priority = asn1_NOVALUE} = CR,
+ {priority, Int}) ->
+ CR#'ContextRequest'{priority = Int};
+
+merge_context_request(#'ContextRequest'{emergency = asn1_NOVALUE} = CR,
+ {emergency, Bool}) ->
+ CR#'ContextRequest'{emergency = Bool};
+
+merge_context_request(#'ContextRequest'{topologyReq = asn1_NOVALUE} = CR,
+ {topology, Desc}) ->
+ CR#'ContextRequest'{topologyReq = Desc};
+
+merge_context_request(#'ContextRequest'{iepscallind = asn1_NOVALUE} = CR,
+ {iepsCallind, Ind}) ->
+ CR#'ContextRequest'{iepscallind = Ind};
+
+merge_context_request(#'ContextRequest'{contextProp = asn1_NOVALUE} = CR,
+ {contextProp, Props}) ->
+ CR#'ContextRequest'{contextProp = Props};
+
+%% The parser handles this, but we drop it in this version
+%% merge_context_request(#'ContextRequest'{contextList = asn1_NOVALUE} = CR,
+%% {contextList, _IDs}) ->
+%% CR#'ContextRequest'{contextList = IDs};
+merge_context_request(CR, {contextList, _IDs}) ->
+ CR;
+
+merge_context_request(CR, {Tag, Val}) ->
+ Val2 =
+ case Tag of
+ priority -> CR#'ContextRequest'.priority;
+ emergency -> CR#'ContextRequest'.emergency;
+ topology -> CR#'ContextRequest'.topologyReq;
+ iepsCallind -> CR#'ContextRequest'.iepscallind;
+ contextProp -> CR#'ContextRequest'.contextProp%% ;
+ %% contextList -> CR#'ContextRequest'.contextList
+ end,
+ exit({at_most_once_contextProperty, {Tag, Val, Val2}}).
+
+
+merge_context_attr_audit_request(CAAR, []) ->
+ CAAR;
+merge_context_attr_audit_request(CAAR, [H|T]) ->
+ case H of
+ priorityAudit when CAAR#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{priority = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ topologyAudit when CAAR#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{topology = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ iepsCallind when CAAR#'ContextAttrAuditRequest'.iepscallind == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{iepscallind = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} when CAAR#'ContextAttrAuditRequest'.contextPropAud == asn1_NOVALUE ->
+ CPA = [#'IndAudPropertyParm'{name = Name}],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} ->
+ CPA = CAAR#'ContextAttrAuditRequest'.contextPropAud,
+ CPA2 = [#'IndAudPropertyParm'{name = Name}|CPA],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA2},
+ merge_context_attr_audit_request(CAAR2, T)
+
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_request,2}]}).
+-endif.
+merge_action_request(CtxId, Items) ->
+ do_merge_action_request(Items, [], asn1_NOVALUE, asn1_NOVALUE, CtxId).
+
+do_merge_action_request([H|T], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ case H of
+ {commandRequest, CmdReq} ->
+ do_merge_action_request(T, [CmdReq|CmdReqs],
+ CtxReq, CtxAuditReq, CtxId);
+
+ {contextProp, ContextProp} ->
+ do_merge_action_request(T, CmdReqs,
+ merge_context_request(CtxReq, ContextProp),
+ CtxAuditReq, CtxId);
+
+ {contextAudit, ContextAuditReq} when CtxAuditReq == asn1_NOVALUE ->
+ do_merge_action_request(T, CmdReqs,
+ CtxReq, ContextAuditReq, CtxId)
+ end;
+do_merge_action_request([], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ #'ActionRequest'{contextId = CtxId,
+ contextRequest = strip_ContextRequest(CtxReq),
+ contextAttrAuditReq = strip_ContextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReqs)}.
+
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(Items) ->
+ do_merge_action_reply(Items, asn1_NOVALUE, asn1_NOVALUE, []).
+
+do_merge_action_reply([], Err, Ctx, Cmds) ->
+ #'ActionReply'{errorDescriptor = Err,
+ contextReply = strip_ContextRequest(Ctx),
+ commandReply = lists:reverse(Cmds)};
+do_merge_action_reply([H|T], Err0, CR, Cmds) ->
+ case H of
+ {error, Err1} when Err0 == asn1_NOVALUE ->
+ do_merge_action_reply(T, Err1, CR, Cmds);
+ {command, Cmd} ->
+ do_merge_action_reply(T, Err0, CR, [Cmd | Cmds]);
+ {context, CtxProp} ->
+ do_merge_action_reply(T, Err0,
+ merge_context_request(CR, CtxProp), Cmds)
+ end.
+
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = []}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(asn1_NOVALUE) ->
+ asn1_NOVALUE;
+strip_ContextRequest(R) ->
+ R.
+
+strip_ContextAttrAuditRequest(asn1_NOVALUE) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = []}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(R) ->
+ R.
+
+merge_AmmRequest_descriptors([], Acc) ->
+ lists:reverse(Acc);
+merge_AmmRequest_descriptors([{_, deprecated}|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, Acc);
+merge_AmmRequest_descriptors([Desc|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, [Desc|Acc]).
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ statistics when SP#'StreamParms'.statisticsDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{statisticsDescriptor = D});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor,
+ 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ parse_prop_name(Text, Group).
+
+parse_prop_name([Char | Rest] = All, Group) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group)
+ end;
+parse_prop_name([] = All, Group) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group).
+
+do_parse_prop_name([Char | Rest], Name, Group)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ NewGroup = [],
+ [lists:reverse(Group) | parse_prop_value(Rest, Name, NewGroup)];
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], []) ->
+ [];
+do_parse_prop_name([], [], Group) ->
+ [lists:reverse(Group)];
+do_parse_prop_name([], Name, Group) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,3}]}).
+-endif.
+parse_prop_value(Chars, Name, Group) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group]);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group)
+ end;
+do_parse_prop_value([], Name, Value, Group) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ Groups.
+
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(true, F, A).
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("DBG:~w:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3b.yrl b/lib/megaco/src/text/megaco_text_parser_prev3b.yrl
new file mode 100644
index 0000000000..d660fb787a
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3b.yrl
@@ -0,0 +1,1601 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%
+%% NOTE 1 - This syntax specification does not enforce all restrictions
+%% on element inclusions and values. Some additional
+%% restrictions are stated in comments and other restrictions
+%% appear in the text of this Recommendation. These additional
+%% restrictions are part of the protocol even though not
+%% enforced by this Recommendation.
+%% NOTE 2 - The syntax is context-dependent. For example, "Add" can be
+%% the AddToken or a NAME depending on the context in which it
+%% occurs.
+%%
+%% Everything in the ABNF and text encoding is case insensitive. This
+%% includes TerminationIDs, digitmap Ids etc. SDP is case sensitive as
+%% per RFC 2327.
+%%
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 117.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestBody
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ authenticationHeader
+ commandReplyList
+ commandReplys %% v3
+ commandRequest
+ contextAttrDescriptor %% v3
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextID
+ contextIdList %% v3
+ contextIDs %% v3
+%% contextProperties %% v3
+ contextProperty
+%% contextPropertyList
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ direction %% v3
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlState
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStream
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+
+ iepsValue
+
+ %% v2 - start
+ indAudauditReturnParameter
+ indAuddigitMapDescriptor
+ indAudeventBufferDescriptor
+ indAudeventSpec
+ indAudeventSpecParameter
+ %% indAudeventSpecParameterList
+ indAudeventsDescriptor
+ indAudlocalControlDescriptor
+ indAudlocalParm
+ indAudlocalParmList
+ indAudmediaDescriptor
+ indAudmediaParm
+ indAudmediaParms %% v3
+ %% indAudmediaParmList
+ indAudpackagesDescriptor
+ indAudrequestedEvent
+ indAudsignalsDescriptor
+ indAudsignalList
+ %% indAudsignalListParm
+ indAudsignalParm
+ %% indAudsignalRequest
+ indAudstreamDescriptor
+ indAudstreamParm
+ indAudstatisticsDescriptor
+ indAudterminationAudit
+ indAudterminationAuditList
+ indAudterminationStateDescriptor
+ indAudterminationStateParm
+ %% indAudterminationStateParmList
+ optIndAudeventSpecParameter
+ optIndAudsignalParm
+ %% v2 - end
+
+ indAudcontextAttrDescriptor %% v3
+
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor % Deprecated as of Corr 1
+ modemType % Deprecated as of Corr 1
+ modemTypeList % Deprecated as of Corr 1
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ % observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ propertyParmList
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceState
+ serviceStates
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ terminationA
+ terminationAudit
+ terminationB
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyTriple
+ topologyTripleList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothToken' %% v3
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ 'ContextAttrToken' %% v3
+ 'ContextAuditToken'
+ 'ContextListToken' %% v3
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DirectionToken' %% v3
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'EmergencyOffToken'
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'ExternalToken' %% v3
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'IEPSToken' %% v3
+ 'ImmAckRequiredToken'
+ 'InSvcToken'
+ 'InactiveToken'
+ 'InternalToken' %% v3
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'IsolateToken'
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NotifyCompletionToken'
+ 'NotifyToken'
+ 'Nx64Token' %% v2
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'RequestIDToken' %% v3
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceChangeIncompleteToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ 'AndAUDITSelectToken' %% OTP-7534: v3-fix
+ 'EmergencyValueToken' %% OTP-7534: v3-fix
+ 'IntsigDelayToken' %% OTP-7534: v3-fix
+ 'IterationToken' %% OTP-7534: v3-fix
+ 'MessageSegmentToken' %% OTP-7534: v3-fix
+ 'NeverNotifyToken' %% OTP-7534: v3-fix
+ 'NotifyImmediateToken' %% OTP-7534: v3-fix
+ 'NotifyRegulatedToken' %% OTP-7534: v3-fix
+ 'OnewayBothToken' %% OTP-7534: v3-fix
+ 'OnewayExternalToken' %% OTP-7534: v3-fix
+ 'OrAUDITselectToken' %% OTP-7534: v3-fix
+ 'ResetEventsDescriptorToken' %% OTP-7534: v3-fix
+ 'SegmentationCompleteToken' %% OTP-7534: v3-fix
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody : ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck transactionAckList 'RBRKT' : ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT'
+ : #'TransactionPending'{transactionId = ensure_transactionID('$3') } .
+
+transactionRequest -> 'TransToken'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList : ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestBody 'RBRKT'
+ : merge_action_request('$3', '$5') .
+
+actionRequestBody -> actionRequestItem actionRequestItems : ['$1' | '$2'] .
+
+actionRequestItems -> 'COMMA' actionRequestItem actionRequestItems
+ : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+%% actionRequestItem -> contextProperties : '$1' .
+actionRequestItem -> contextProperty : {contextProp, '$1'} .
+actionRequestItem -> contextAudit : {contextAudit, '$1'} .
+actionRequestItem -> commandRequest : {commandRequest, '$1'} .
+
+%% contextProperties -> contextProperty contextPropertyList :
+%% merge_context_request(#'ContextRequest'{}, ['$1' | '$2']) .
+
+%% contextPropertyList -> 'COMMA' contextProperty contextPropertyList : ['$2' | '$3' ] .
+%% contextPropertyList -> '$empty' : [] .
+
+%% at-most-once
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+contextProperty -> 'EmergencyOffToken' : {emergency, false}.
+contextProperty -> iepsValue : {iepsCallind, '$1'} .
+contextProperty -> contextAttrDescriptor : '$1' .
+
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' propertyParms 'RBRKT' :
+ {contextProp, '$3'}.
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' contextIdList 'RBRKT' :
+ {contextList, '$3'}.
+
+contextIdList -> 'ContextListToken' 'EQUAL'
+ 'LBRKT' contextID contextIDs 'RBRKT' : ['$4' | '$5'] .
+
+contextIDs -> 'COMMA' contextID contextIDs : ['$2' | '$3'] .
+contextIDs -> '$empty' : [] .
+
+contextAudit -> 'ContextAuditToken' 'LBRKT' indAudcontextAttrDescriptor 'RBRKT'
+ : merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, '$3') .
+
+indAudcontextAttrDescriptor -> 'ContextAttrToken'
+ 'LBRKT' contextAuditProperty
+ contextAuditProperties 'RBRKT'
+ : ['$3' | '$4'] .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty contextAuditProperties
+ : ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once .
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+contextAuditProperty -> 'IEPSToken' : iepsCallind .
+contextAuditProperty -> pkgdName : {prop, '$1'} .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID
+ 'LBRKT'
+ optImmAckRequired transactionReplyBody
+ 'RBRKT'
+ : #'TransactionReply'{transactionId = '$3',
+ immAckRequired = '$5',
+ transactionResult = '$6'} .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor : {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList : {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReplys commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ [{error, '$2'}] .
+commandReplyList -> 'COMMA' commandReplys commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+commandReplys -> serviceChangeReply : {command, '$1'} .
+commandReplys -> auditReply : {command, '$1'} .
+commandReplys -> ammsReply : {command, '$1'} .
+commandReplys -> notifyReply : {command, '$1'} .
+commandReplys -> contextProperty : {context, '$1'} .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' terminationID ammRequestBody :
+ Descs = merge_AmmRequest_descriptors('$4', []),
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = ['$3'],
+ descriptors = Descs}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, deprecated}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+ammParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' terminationID ammsReplyBody
+ : {'$1', #'AmmsReply'{terminationID = ['$3'],
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL' terminationID
+ optAuditDescriptor
+ : make_commandRequest({subtractReq, '$1'},
+ #'SubtractRequest'{terminationID = ['$3'],
+ auditDescriptor = '$4'}) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+auditRequest -> 'AuditCapToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther
+ : {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther
+ : {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList :
+ {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' :
+ {error, '$2'} .
+
+auditOther -> terminationID :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = []}} .
+auditOther -> terminationID 'LBRKT' terminationAudit 'RBRKT' :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = '$3'}} .
+
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor.
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} .
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT' :
+ merge_auditDescriptor('$3') .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken.
+auditItem -> 'EventBufferToken' : eventBufferToken.
+auditItem -> 'EventsToken' : eventsToken .
+auditItem -> indAudterminationAudit : {terminationAudit, '$1'} . % v2
+%%
+%% IGv11 - end
+
+
+%% v2 - start
+%%
+indAudterminationAudit -> indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$1' | '$2'] .
+
+indAudterminationAuditList -> 'COMMA' indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$2' | '$3'] .
+indAudterminationAuditList -> '$empty' : [] .
+
+indAudauditReturnParameter -> indAudmediaDescriptor
+ : {indAudMediaDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventsDescriptor
+ : {indAudEventsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudsignalsDescriptor
+ : {indAudSignalsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAuddigitMapDescriptor
+ : {indAudDigitMapDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventBufferDescriptor
+ : {indAudEventBufferDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudstatisticsDescriptor
+ : {indAudStatisticsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudpackagesDescriptor
+ : {indAudPackagesDescriptor, '$1'} .
+
+
+indAudmediaDescriptor -> 'MediaToken' 'LBRKT'
+ indAudmediaParm indAudmediaParms 'RBRKT'
+ : merge_indAudMediaDescriptor(['$3'|'$4']) .
+
+%% at-most-once per item
+%% and either streamParm or streamDescriptor but not both
+%%
+
+indAudmediaParm -> indAudstreamParm : {streamParm, '$1'} .
+indAudmediaParm -> indAudstreamDescriptor : {streamDescr, '$1'} .
+indAudmediaParm -> indAudterminationStateDescriptor : {termStateDescr, '$1'} .
+
+indAudmediaParms -> 'COMMA' indAudmediaParm indAudmediaParms : ['$2' | '$3'] .
+indAudmediaParms -> '$empty' : [] .
+
+%% at-most-once
+indAudstreamParm -> indAudlocalControlDescriptor
+ : #'IndAudStreamParms'{localControlDescriptor = '$1'} .
+indAudstreamParm -> indAudstatisticsDescriptor
+ : #'IndAudStreamParms'{statisticsDescriptor = '$1'} .
+
+indAudstreamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' indAudstreamParm 'RBRKT'
+ : #'IndAudStreamDescriptor'{streamID = '$3',
+ streamParms = '$5'} .
+
+
+indAudlocalControlDescriptor -> 'LocalControlToken'
+ 'LBRKT' indAudlocalParm indAudlocalParmList 'RBRKT' :
+ merge_indAudLocalControlDescriptor(['$3' | '$4']) .
+
+indAudlocalParmList -> 'COMMA' indAudlocalParm indAudlocalParmList : ['$2' | '$3'] .
+indAudlocalParmList -> '$empty' : [] .
+
+%% at-most-once per item
+%%
+indAudlocalParm -> safeToken : ensure_indAudLocalParm('$1') .
+
+indAudterminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' indAudterminationStateParm 'RBRKT'
+ :
+ merge_indAudTerminationStateDescriptor('$3') .
+
+%% at-most-once per item
+%%
+
+indAudterminationStateParm -> safeToken :
+ ensure_indAudTerminationStateParm('$1') .
+
+indAudeventBufferDescriptor -> 'EventBufferToken'
+ 'LBRKT' indAudeventSpec 'RBRKT' : '$3' .
+
+indAudeventSpec -> pkgdName optIndAudeventSpecParameter
+ : merge_indAudEventBufferDescriptor('$1','$2') .
+
+optIndAudeventSpecParameter -> 'LBRKT' indAudeventSpecParameter 'RBRKT'
+ : '$2' .
+optIndAudeventSpecParameter -> '$empty' : asn1_NOVALUE .
+
+
+indAudeventSpecParameter -> eventStream : {streamID, '$1'} .
+indAudeventSpecParameter -> eventParameterName : {eventParameterName, '$1'} .
+
+indAudeventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' indAudrequestedEvent 'RBRKT'
+ : #'IndAudEventsDescriptor'{requestID = '$3',
+ pkgdName = '$5'} .
+
+indAudrequestedEvent -> pkgdName : '$1' .
+
+
+indAudsignalsDescriptor -> 'SignalsToken' optIndAudsignalParm : '$2' .
+
+
+optIndAudsignalParm -> 'LBRKT' 'RBRKT' : asn1_NOVALUE .
+optIndAudsignalParm -> 'LBRKT' indAudsignalParm 'RBRKT' : '$2' .
+
+indAudsignalParm -> indAudsignalList : {seqSigList, '$1'} .
+indAudsignalParm -> signalRequest : {signal, ensure_indAudSignal('$1')} .
+
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm 'RBRKT' :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3'),
+ signalList =
+ ensure_indAudSignalListParm('$5')} .
+
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+indAuddigitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_IADMD('$1') .
+
+indAudstatisticsDescriptor -> 'StatsToken' 'LBRKT' pkgdName 'RBRKT' :
+ #'IndAudStatisticsDescriptor'{statName = '$3'} .
+
+indAudpackagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem 'RBRKT'
+ : merge_indAudPackagesDescriptor('$3') .
+
+eventStream -> 'StreamToken' 'EQUAL' streamID : '$3' .
+
+
+%%
+%% v2 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' terminationID
+ 'LBRKT' notifyRequestBody 'RBRKT'
+ : make_commandRequest({notifyReq, '$1'},
+ setelement(#'NotifyRequest'.terminationID, '$5', ['$3'])) .
+
+notifyRequestBody -> observedEventsDescriptor
+ : #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor
+ : #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' terminationID notifyReplyBody
+ : {notifyReply,
+ #'NotifyReply'{terminationID = ['$3'],
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' terminationID
+ 'LBRKT' serviceChangeDescriptor 'RBRKT'
+ : make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = ['$3'],
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' terminationID serviceChangeReplyBody
+ : {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = ['$3'],
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT'
+ : {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT'
+ : {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' : {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT' errorText 'RBRKT'
+ : #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+%% '-' is used for NULL context
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+%% terminationIDList -> LBRKT terminationID *(COMMA terminationID) RBRKT .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT'
+ : ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat
+ : ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-onc .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+streamParm -> statisticsDescriptor : {statistics, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm
+ terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue :
+ setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue :
+ '$2' .
+
+parmValue -> 'NEQUAL' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT'
+ : #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value :
+ #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec eventSpecList 'RBRKT'
+ : ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceState : '$3' .
+
+serviceState -> 'TestToken' : test .
+serviceState -> 'OutOfSvcToken' : outOfSvc .
+serviceState -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlState : '$3' .
+
+eventBufferControlState -> 'OffToken' : off .
+eventBufferControlState -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList :
+ #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' : #'RequestedEvent'{evParList = []} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT'
+ : {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT'
+ : {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents : ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody
+ : setelement(#'SecondRequestedEvent'.pkgdName, '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter secondEventParameters 'RBRKT'
+ : merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' : #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters : ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' :
+ ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' : [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther /
+%% notifyCompletion / KeepActiveToken /
+%% direction / sigRequestID
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason)
+%% RBRKT)
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken /
+%% InterruptByNewSignalsDescrToken /
+%% OtherReasonToken )
+%% sigDirection = DirectionToken EQUAL direction
+%% sigRequestID = RequestIDToken EQUAL RequestID
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID :
+ {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType :
+ {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken :
+ {duration, ensure_uint16('$3')} .
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT' :
+ {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+sigParameter -> 'DirectionToken' 'EQUAL' direction : {direction, '$3'} .
+sigParameter -> 'RequestIDToken' 'EQUAL' requestID : {requestId, '$3'} .
+sigParameter -> safeToken parmValue :
+ {other, ensure_NAME('$1'), '$2'}.
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+direction -> 'ExternalToken' : external .
+direction -> 'InternalToken' : internal .
+direction -> 'BothToken' : both .
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms :
+ ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+
+observedEvent -> timeStamp optSep 'COLON' optSep pkgdName observedEventBody :
+ merge_observed_event('$6', '$5', '$1') .
+observedEvent -> optSep pkgdName observedEventBody :
+ merge_observed_event('$3', '$2', asn1_NOVALUE) .
+
+observedEventBody -> 'LBRKT' observedEventParameter
+ observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+%% Deprecated as of Corr 1
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms .
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms.
+modemTypeList -> 'COMMA' modemType modemTypeList.
+modemTypeList -> '$empty'.
+modemType -> safeToken.
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParmList 'RBRKT' :
+ ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> propertyParm propertyParmList : ['$1' | '$2'] .
+propertyParmList -> 'COMMA' propertyParm propertyParmList : ['$2' | '$3'] .
+propertyParmList -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_DMD('$1') .
+
+%% each parameter at-most-once, except auditItem
+%% at most one of either serviceChangeAddress or serviceChangeMgcId but
+%% not both. serviceChangeMethod and serviceChangeReason are REQUIRED
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp, '$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+serviceChangeParm -> 'ServiceChangeIncompleteToken' : incomplete . % v3
+serviceChangeParm -> auditItem : {audit_item, '$1'} . % v2
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken :
+ ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber :
+ {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'} .
+servChgReplyParm -> timeStamp : {time_stamp,'$1'} .
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem
+ packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter
+ statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT' topologyTriple
+ topologyTripleList 'RBRKT' : ['$3' | '$4'] .
+
+terminationA -> terminationID : '$1' .
+
+terminationB -> terminationID : '$1' .
+
+topologyTriple -> terminationA 'COMMA'
+ terminationB 'COMMA'
+ topologyDirection :
+ #'TopologyRequest'{terminationFrom = '$1',
+ terminationTo = '$3',
+ topologyDirection = '$5'} .
+
+topologyTripleList -> '$empty' : [] .
+topologyTripleList -> 'COMMA' topologyTriple topologyTripleList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : bothway .
+topologyDirection -> 'IsolateToken' : isolate .
+topologyDirection -> 'OnewayToken' : oneway .
+
+iepsValue -> 'IEPSToken' 'EQUAL' onOrOff : '$3' .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' : ensure_value('$1') .
+value -> safeToken : ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+%% BMK BMK safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothToken' : '$1' . % v3
+safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% v3-safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% v3-safeToken2 -> 'ContextListToken' : '$1' . % v3
+%% v2-safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+%% v3-
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% v2-safeToken2 -> 'EventBufferToken' : '$1' .
+%% v2-safeToken2 -> 'EventsToken' : '$1' .
+%% v3-safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+%% v3-safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+%% v3-safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% v2-safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+safeToken2 -> 'ModeToken' : '$1' .
+%% BMK BMK safeToken2 -> 'ModifyToken' : '$1' .
+%% v2-safeToken2 -> 'ModemToken' : '$1' .
+%% BMK BMK safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% v2-safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64Token' : '$1' .
+%% v2-safeToken2 -> 'ObservedEventsToken' : '$1' .
+safeToken2 -> 'OnewayToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% v2-safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+%% BMK BMK safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+%% v3-
+safeToken2 -> 'RequestIDToken' : '$1' . % v3
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+safeToken2 -> 'ReservedGroupToken' : '$1' .
+safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' . % v3
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% v2-safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% v2-safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+%% BMK safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+%% BMK safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+%% <OTP-7534>
+safeToken2 -> 'AndAUDITSelectToken' : '$1' . % v3
+safeToken2 -> 'EmergencyValueToken' : '$1' . % v3
+safeToken2 -> 'IntsigDelayToken' : '$1' . % v3
+safeToken2 -> 'IterationToken' : '$1' . % v3
+safeToken2 -> 'MessageSegmentToken' : '$1' . % v3
+safeToken2 -> 'NeverNotifyToken' : '$1' . % v3
+safeToken2 -> 'NotifyImmediateToken' : '$1' . % v3
+safeToken2 -> 'NotifyRegulatedToken' : '$1' . % v3
+safeToken2 -> 'OnewayBothToken' : '$1' . % v3
+safeToken2 -> 'OnewayExternalToken' : '$1' . % v3
+safeToken2 -> 'OrAUDITselectToken' : '$1' . % v3
+safeToken2 -> 'ResetEventsDescriptorToken' : '$1' . % v3
+safeToken2 -> 'SegmentationCompleteToken' : '$1' . % v3
+%% </OTP-7534>
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_prev3b.hrl").
+
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3c.hrl b/lib/megaco/src/text/megaco_text_parser_prev3c.hrl
new file mode 100644
index 0000000000..ab099e5a24
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3c.hrl
@@ -0,0 +1,1980 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_prev3c.hrl").
+-include("megaco_text_tokens.hrl").
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% The values 0x0, 0xFFFFFFFE and 0xFFFFFFFF are reserved.
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and issue the
+ %% the error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) == 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when length(Hex4) =< 4, length(Hex4) > 0 ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ X /= $X, X /= $x,
+ S /= $+, S /= $- ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% and since this functon is only used when creating
+%% a ModemDescriptor, iit is removed.
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+%% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+%% case Text of
+%% "v32b" -> v32bis;
+%% "v22b" -> v22bis;
+%% "v18" -> v18;
+%% "v22" -> v22;
+%% "v32" -> v32;
+%% "v34" -> v34;
+%% "v90" -> v90;
+%% "v91" -> v91;
+%% "synchisdn" -> synchISDN;
+%% "sn" -> synchISDN;
+%% [$x | _] -> ensure_extensionParameter(Token)
+%% end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ "nx64k" -> nx64k; % v2
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_packagesItem,1}]}).
+-endif.
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (length or content) there is really no point in
+ %% "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+
+
+%% v2 - start
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudMediaDescriptor,1}]}).
+-endif.
+merge_indAudMediaDescriptor(Vals) ->
+ merge_indAudMediaDescriptor(Vals, #'IndAudMediaDescriptor'{}).
+
+merge_indAudMediaDescriptor(
+ [], #'IndAudMediaDescriptor'{streams = Streams1} = D) ->
+ Streams2 =
+ case Streams1 of
+ {multiStream, Descs} ->
+ {multiStream, lists:reverse(Descs)};
+ _ ->
+ Streams1
+ end,
+ D#'IndAudMediaDescriptor'{streams = Streams2};
+merge_indAudMediaDescriptor([{termStateDescr, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.termStateDescr == asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{termStateDescr = Val},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamParm, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.streams == asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{streams = {oneStream, Val}},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamDescr, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.streams == asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamDescr, Val}|Vals],
+ #'IndAudMediaDescriptor'{streams = Streams1} = D1) ->
+ Streams2 =
+ case Streams1 of
+ {multiStream, Descs} ->
+ {multiStream, [Val|Descs]};
+ _ ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamDescr,
+ Val, Streams1})
+ end,
+ D2 = D1#'IndAudMediaDescriptor'{streams = Streams2},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{Tag, Val}|_], D) ->
+ case Tag of
+ termStateDescr ->
+ return_error(0, {bad_IndAudMediaDescriptor_termStateDescr,
+ Val, D#'IndAudMediaDescriptor'.termStateDescr});
+ streamParm ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamParm,
+ Val, D#'IndAudMediaDescriptor'.streams});
+ streamDescr ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamDescr,
+ Val, D#'IndAudMediaDescriptor'.streams});
+ _ ->
+ return_error(0, {bad_IndAudMediaDescriptor_tag, Tag, Val})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudLocalControlDescriptor,1}]}).
+-endif.
+merge_indAudLocalControlDescriptor(Parms) ->
+ merge_indAudLocalControlDescriptor(Parms,
+ #'IndAudLocalControlDescriptor'{},
+ asn1_NOVALUE).
+
+merge_indAudLocalControlDescriptor([modeToken | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.streamModeSel == asn1_NOVALUE) ->
+ D2 = D#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([modeToken | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE) ->
+ merge_indAudLocalControlDescriptor(Parms, D, PP);
+
+merge_indAudLocalControlDescriptor([{mode, Val} | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.streamModeSel == asn1_NOVALUE) ->
+ D2 =
+ case Val of
+ {equal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamModeSel = Val2};
+ {inequal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamModeSel = Val2}
+ end,
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([{mode, Val} | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamModeSel == asn1_NOVALUE) ->
+ D2 =
+ case Val of
+ {equal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ streamModeSel = Val2};
+ {inequal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ streamModeSel = Val2}
+ end,
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([reservedGroupToken | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.reserveGroup == asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([reservedValueToken | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.reserveValue == asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+%% This is really wierd in the standard, so at this point this is the
+%% best I can do... BUGBUG BUGBUG BUGBUG
+%%
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, asn1_NOVALUE) ->
+ PP = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D, PP);
+
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP]},
+ PP2 = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP2);
+
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, PP) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP|PPs]},
+ PP2 = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP2);
+
+%% BUGBUG BUGBUG I cannot construct a proper IndAudPropertyParm with
+%% just the prop (the mandatory name part is missing), so for now I
+%% assume that it this has been used, then the name part
+%% (pkgdName) must precide it?
+merge_indAudLocalControlDescriptor([{prop, Val} | Parms], D, PP)
+ when (PP =/= asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE) ->
+ PP2 = PP#'IndAudPropertyParm'{propertyParms = Val},
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP2]},
+ merge_indAudLocalControlDescriptor(Parms, D2, asn1_NOVALUE);
+
+merge_indAudLocalControlDescriptor([{prop, Val} | Parms], D, PP)
+ when (PP =/= asn1_NOVALUE) andalso
+ is_list(D#'IndAudLocalControlDescriptor'.propertyParms) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PP2 = PP#'IndAudPropertyParm'{propertyParms = Val},
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP2|PPs]},
+ merge_indAudLocalControlDescriptor(Parms, D2, asn1_NOVALUE);
+
+merge_indAudLocalControlDescriptor([H | _T], _D, _PP) ->
+ return_error(0, {bad_indAudLocalControlDescriptor_parm, H});
+
+merge_indAudLocalControlDescriptor([], D, asn1_NOVALUE)
+ when D#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->
+ D;
+merge_indAudLocalControlDescriptor([], D, asn1_NOVALUE) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PropParms2 = lists:reverse(PPs),
+ D#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+merge_indAudLocalControlDescriptor([], D, PP)
+ when D#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->
+ D#'IndAudLocalControlDescriptor'{propertyParms = [PP]};
+merge_indAudLocalControlDescriptor([], D, PP) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PPs2 = lists:reverse([PP|PPs]),
+ D#'IndAudLocalControlDescriptor'{propertyParms = PPs2}.
+
+
+merge_indAudTerminationStateDescriptor({name, Val}) ->
+ PropParm = #'IndAudPropertyParm'{name = Val},
+ #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+%% BUGBUG BUGBUG BUGBUG
+merge_indAudTerminationStateDescriptor({prop, Val}) ->
+ exit({incomplete_propertyParm_in_indAudTerminationStateDescriptor, Val});
+merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+ #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+merge_indAudTerminationStateDescriptor({serviceStates, {equal, Val}}) ->
+ #'IndAudTerminationStateDescriptor'{serviceStateSel = Val};
+merge_indAudTerminationStateDescriptor({serviceStates, {inequal, Val}}) ->
+ #'IndAudTerminationStateDescriptor'{serviceStateSel = Val};
+merge_indAudTerminationStateDescriptor(bufferToken) ->
+ #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudEventBufferDescriptor,2}]}).
+-endif.
+merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+ IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+ do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+ IAEBD;
+do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+ IAEBD) ->
+ %% BUGBUG BUGBUG BUGBUG
+ %% This is an ugly hack to allow the eventParamName which only
+ %% exists in the text encoding...
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudSignalListParm,1}]}).
+-endif.
+ensure_indAudSignalListParm(SIG) ->
+ if
+ is_record(SIG, 'Signal') ->
+ ensure_indAudSignal(SIG);
+ true ->
+ return_error(0, {bad_Signal, SIG})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudSignal,1}]}).
+-endif.
+ensure_indAudSignal(Sig) ->
+ #'Signal'{signalName = SignalName,
+ streamID = SID,
+ sigType = asn1_NOVALUE,
+ duration = asn1_NOVALUE,
+ notifyCompletion = asn1_NOVALUE,
+ keepActive = asn1_NOVALUE,
+ sigParList = [],
+ requestID = RID} = Sig,
+ #'IndAudSignal'{signalName = SignalName,
+ streamID = SID,
+ signalRequestID = RID}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_IADMD,1}]}).
+-endif.
+ensure_IADMD(Token) ->
+ {_TokenTag, _Line, DMD} = Token,
+ #'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE} = DMD,
+ #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudPackagesDescriptor,1}]}).
+-endif.
+merge_indAudPackagesDescriptor(Pkgs) ->
+ #'PackagesItem'{packageName = N,
+ packageVersion = V} = Pkgs,
+ #'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V}.
+
+
+%% ensure_indAudTerminationStateParm(Token) ->
+%% case Token of
+%% {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+%% {safeToken, _Line, "si"} -> serviceStatesToken;
+%% {safeToken, _Line, "buffer"} -> bufferToken;
+%% {safeToken, _Line, "bf"} -> bufferToken;
+%% PkgdName -> {pkgdName,
+%% ensure_pkgdName(PkgdName)}
+%% end.
+
+
+%% Types modified by v2:
+
+merge_auditDescriptor([]) ->
+ #'AuditDescriptor'{};
+merge_auditDescriptor(Tokens) when is_list(Tokens) ->
+ case lists:keysearch(terminationAudit, 1, Tokens) of
+ {value, {terminationAudit, TA}} ->
+ case lists:keydelete(terminationAudit, 1, Tokens) of
+ [] ->
+ #'AuditDescriptor'{auditPropertyToken = TA};
+ AuditTokens ->
+ #'AuditDescriptor'{auditToken = AuditTokens,
+ auditPropertyToken = TA}
+ end;
+ false ->
+ #'AuditDescriptor'{auditToken = Tokens}
+ end;
+merge_auditDescriptor(_) ->
+ #'AuditDescriptor'{}.
+
+
+%% v2 - end
+
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE,
+ SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE,
+ SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeReason == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeDelay == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeMethod == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.timeStamp == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_atom(Val) ->
+ SCI = #'AuditDescriptor'{auditToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo == asn1_NOVALUE) andalso
+ is_tuple(Val) ->
+ SCI = #'AuditDescriptor'{auditPropertyToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_atom(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditToken,
+ SCI = SCI0#'AuditDescriptor'{auditToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_tuple(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditPropertyToken,
+ SCI = SCI0#'AuditDescriptor'{auditPropertyToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([incomplete|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeIncompleteFlag == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeIncompleteFlag = 'NULL'},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp;
+ audit_item ->
+ SCP#'ServiceChangeParm'.serviceChangeInfo
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}});
+merge_ServiceChangeParm([Parm|_Parms], SCP, _Req) ->
+ Parm2 =
+ case Parm of
+ incomplete ->
+ SCP#'ServiceChangeParm'.serviceChangeIncompleteFlag
+ end,
+ exit({at_most_once_serviceChangeParm, {Parm, Parm2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_topologyDescriptor,1}]}).
+-endif.
+merge_topologyDescriptor(Components) ->
+ merge_topologyDescriptor(Components, #'TopologyRequest'{}, []).
+
+merge_topologyDescriptor([], TR, TRs) ->
+ lists:reverse([ensure_TopologyRequest(TR)|TRs]);
+merge_topologyDescriptor(
+ [{tid, From}|Comps],
+ #'TopologyRequest'{terminationFrom = undefined} = TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{terminationFrom = From},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(
+ [{tid, To}|Comps],
+ #'TopologyRequest'{terminationTo = undefined} = TR1,
+ TRs) ->
+ TR2 = TR1#'TopologyRequest'{terminationTo = To},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{tid, From}|Comps], TR1, TRs) ->
+ TR2 = #'TopologyRequest'{terminationFrom = From},
+ merge_topologyDescriptor(Comps, TR2, [TR1 | TRs]);
+merge_topologyDescriptor([{direction, Dir}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirection = Dir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{sid, SID}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{streamID = SID},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(
+ [{direction_ext, EDir}|Comps],
+ #'TopologyRequest'{topologyDirection = asn1_NOVALUE} = TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirection = oneway,
+ topologyDirectionExtension = EDir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{direction_ext, EDir}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirectionExtension = EDir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(Comps, TR, TRs) ->
+ return_error(0, {bad_topologyDescriptor, Comps, TR, TRs}).
+
+
+ensure_TopologyRequest(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir} = R)
+ when (From =/= asn1_NOVALUE) andalso
+ (To =/= asn1_NOVALUE) andalso
+ (Dir =/= asn1_NOVALUE) ->
+ R;
+ensure_TopologyRequest(R) ->
+ return_error(0, {bad_TopologyRequest, R}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_profile,1}]}).
+-endif.
+ensure_profile(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, SID} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = SID}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ {direction, Dir} when Sig#'Signal'.direction == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{direction = Dir}, T, SPL);
+ {requestId, RID} when Sig#'Signal'.requestID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{requestID = RID}, T, SPL);
+ {intersigDelay, ISD} when Sig#'Signal'.intersigDelay == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{intersigDelay = ISD}, T, SPL);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+%% io:format("select_stream_or_other -> entry with"
+%% "~n EventParameterName: ~p"
+%% "~n ParmValue: ~p"
+%% "~n", [EventParameterName, ParmValue]),
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body,
+ durationTimer = Duration},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ #'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ durationTimer = [],
+ digitMapBody = asn1_NOVALUE} ->
+ asn1_NOVALUE;
+ #'DigitMapValue'{durationTimer = Body,
+ digitMapBody = Duration} = DMV ->
+ %% Convert to version 1 DigitMapValue
+ DMV#'DigitMapValue'{digitMapBody = Body,
+ durationTimer = Duration};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation == asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+make_RegulatedEmbeddedDescriptor({embed, SD, SED}) ->
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SED,
+ signalsDescriptor = SD}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+%% io:format("merge_eventParameters -> entry"
+%% "~n", []),
+ SID = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, SID, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], SID, EPL, RA, HasA) ->
+%% io:format("do_merge_eventParameters -> entry with"
+%% "~n H: ~p"
+%% "~n SID: ~p"
+%% "~n EPL: ~p"
+%% "~n RA: ~p"
+%% "~n HasA: ~p"
+%% "~n", [H, SID, EPL, RA, HasA]),
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ resetEventsDescriptor when RA#'RequestedActions'.resetEventsDescriptor =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{resetEventsDescriptor = 'NULL'},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {stream, NewSID} when SID =:= asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewSID, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, SID, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, SID, [EP | EPL], RA, HasA);
+ {notifyBehaviour, NB} when RA#'RequestedActions'.notifyBehaviour =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{notifyBehaviour = NB},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], SID, EPL, RA, yes) ->
+%% io:format("do_merge_eventParameters(yes) -> entry with"
+%% "~n SID: ~p"
+%% "~n EPL: ~p"
+%% "~n RA: ~p"
+%% "~n", [SID, EPL, RA]),
+ #'RequestedEvent'{streamID = SID,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], SID, EPL, _RA, no) ->
+%% io:format("do_merge_eventParameters(no) -> entry with"
+%% "~n SID: ~p"
+%% "~n EPL: ~p"
+%% "~n", [SID, EPL]),
+ #'RequestedEvent'{streamID = SID,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ SID = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, SID, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], SID, EPL, SRA, HasA) ->
+ case H of
+ keepActive when SRA#'SecondRequestedActions'.keepActive =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+
+ resetEventsDescriptor when SRA#'SecondRequestedActions'.resetEventsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{resetEventsDescriptor = 'NULL'},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+
+ {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+
+ {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+
+ {stream, NewSID} when SID =:= asn1_NOVALUE ->
+ do_merge_secondEventParameters(T, NewSID, EPL, SRA, HasA);
+
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, SID, [EP | EPL], SRA, HasA);
+
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, SID, [EP | EPL], SRA, HasA);
+
+ {notifyBehaviour, NB} when SRA#'SecondRequestedActions'.notifyBehaviour =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{notifyBehaviour = NB},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], SID, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = SID,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], SID, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = SID,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ ensure_transactionAck2(Text, []).
+
+ensure_transactionAck2([], Acc) ->
+ Id = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ensure_transactionAck2([$- | Id2], Acc) ->
+ Id1 = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id1),
+ lastAck = ensure_transactionID(Id2)};
+ensure_transactionAck2([H|T], Acc) ->
+ ensure_transactionAck2(T, [H|Acc]).
+
+
+merge_context_request(asn1_NOVALUE, Prop) ->
+ merge_context_request(#'ContextRequest'{}, Prop);
+
+merge_context_request(#'ContextRequest'{priority = asn1_NOVALUE} = CR,
+ {priority, Int}) ->
+ CR#'ContextRequest'{priority = Int};
+
+merge_context_request(#'ContextRequest'{emergency = asn1_NOVALUE} = CR,
+ {emergency, Bool}) ->
+ CR#'ContextRequest'{emergency = Bool};
+
+merge_context_request(#'ContextRequest'{topologyReq = asn1_NOVALUE} = CR,
+ {topology, Desc}) ->
+ CR#'ContextRequest'{topologyReq = Desc};
+
+merge_context_request(#'ContextRequest'{iepscallind = asn1_NOVALUE} = CR,
+ {iepsCallind, Ind}) ->
+ CR#'ContextRequest'{iepscallind = Ind};
+
+merge_context_request(#'ContextRequest'{contextProp = asn1_NOVALUE} = CR,
+ {contextProp, Props}) ->
+ CR#'ContextRequest'{contextProp = Props};
+
+merge_context_request(#'ContextRequest'{contextList = asn1_NOVALUE} = CR,
+ {contextList, IDs}) ->
+ CR#'ContextRequest'{contextList = IDs};
+
+merge_context_request(CR, {Tag, Val}) ->
+ Val2 =
+ case Tag of
+ priority -> CR#'ContextRequest'.priority;
+ emergency -> CR#'ContextRequest'.emergency;
+ topology -> CR#'ContextRequest'.topologyReq;
+ iepsCallind -> CR#'ContextRequest'.iepscallind;
+ contextProp -> CR#'ContextRequest'.contextProp;
+ contextList -> CR#'ContextRequest'.contextList
+ end,
+ exit({at_most_once_contextProperty, {Tag, Val, Val2}}).
+
+
+merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{contextPropAud = asn1_NOVALUE} = CAAR, []) ->
+
+ CAAR;
+merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{contextPropAud = CPA} = CAAR, []) ->
+
+ CAAR#'ContextAttrAuditRequest'{contextPropAud = lists:reverse(CPA)};
+merge_context_attr_audit_request(CAAR, [H|T]) ->
+ case H of
+ priorityAudit when CAAR#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{priority = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ topologyAudit when CAAR#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{topology = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ iepsCallind when CAAR#'ContextAttrAuditRequest'.iepscallind == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{iepscallind = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} when CAAR#'ContextAttrAuditRequest'.contextPropAud == asn1_NOVALUE ->
+ CPA = [#'IndAudPropertyParm'{name = Name}],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} ->
+ CPA = CAAR#'ContextAttrAuditRequest'.contextPropAud,
+ CPA2 = [#'IndAudPropertyParm'{name = Name}|CPA],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA2},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_prio, Prio} when CAAR#'ContextAttrAuditRequest'.selectpriority == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectpriority = Prio},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_emergency, EV} when CAAR#'ContextAttrAuditRequest'.selectemergency == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectemergency = EV},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_ieps, IV} when CAAR#'ContextAttrAuditRequest'.selectiepscallind == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectiepscallind = IV},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_logic, SL} when CAAR#'ContextAttrAuditRequest'.selectLogic == asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectLogic = SL},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ %% BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ %%
+ %% For some strange reason, contextAttrDescriptor was added
+ %% to contextAuditSelector. But there is no place for this
+ %% info in the ContextAttrAuditRequest. Since contextAttrDescriptor
+ %% can also be found in contextProperty (which correspond to
+ %% ContextRequest), the question is if this info should go there
+ %% or if we shall just drop it. For now we drop it.
+ %%
+ {contextProp, _PPs} ->
+ merge_context_attr_audit_request(CAAR, T);
+
+ {contextList, _IDs} ->
+ merge_context_attr_audit_request(CAAR, T);
+
+ _ ->
+ exit({unexpected_contextAttrAudit_item, H})
+
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_request,2}]}).
+-endif.
+merge_action_request(CtxId, Items) ->
+ do_merge_action_request(Items, [], asn1_NOVALUE, asn1_NOVALUE, CtxId).
+
+do_merge_action_request([H|T], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ case H of
+ {commandRequest, CmdReq} ->
+ do_merge_action_request(T, [CmdReq|CmdReqs],
+ CtxReq, CtxAuditReq, CtxId);
+
+ {contextProp, ContextProp} ->
+ do_merge_action_request(T, CmdReqs,
+ merge_context_request(CtxReq, ContextProp),
+ CtxAuditReq, CtxId);
+
+ {contextAudit, ContextAuditReq} when CtxAuditReq == asn1_NOVALUE ->
+ do_merge_action_request(T, CmdReqs,
+ CtxReq, ContextAuditReq, CtxId)
+ end;
+do_merge_action_request([], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ #'ActionRequest'{contextId = CtxId,
+ contextRequest = strip_ContextRequest(CtxReq),
+ contextAttrAuditReq = strip_ContextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReqs)}.
+
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(Items) ->
+ do_merge_action_reply(Items, asn1_NOVALUE, asn1_NOVALUE, []).
+
+do_merge_action_reply([], Err, Ctx, Cmds) ->
+ #'ActionReply'{errorDescriptor = Err,
+ contextReply = strip_ContextRequest(Ctx),
+ commandReply = lists:reverse(Cmds)};
+do_merge_action_reply([H|T], Err0, CR, Cmds) ->
+ case H of
+ {error, Err1} when Err0 == asn1_NOVALUE ->
+ do_merge_action_reply(T, Err1, CR, Cmds);
+ {command, Cmd} ->
+ do_merge_action_reply(T, Err0, CR, [Cmd | Cmds]);
+ {context, CtxProp} ->
+ do_merge_action_reply(T, Err0,
+ merge_context_request(CR, CtxProp), Cmds)
+ end.
+
+merge_auditOther([TID], TAR) ->
+ {auditResult,
+ #'AuditResult'{terminationID = TID,
+ terminationAuditResult = TAR}};
+merge_auditOther(TIDs, TAR) ->
+ {auditResultTermList,
+ #'TermListAuditResult'{terminationIDList = TIDs,
+ terminationAuditResult = TAR}}.
+
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE,
+ contextList = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = [],
+ contextList = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+%% strip_ContextRequest(asn1_NOVALUE) ->
+%% asn1_NOVALUE;
+strip_ContextRequest(R) ->
+ R.
+
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE,
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = [],
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(R) ->
+ R.
+
+merge_AmmRequest_descriptors([], Acc) ->
+ lists:reverse(Acc);
+merge_AmmRequest_descriptors([{_, deprecated}|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, Acc);
+merge_AmmRequest_descriptors([Desc|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, [Desc|Acc]).
+
+make_auditRequest([TID], AD) ->
+ #'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD};
+make_auditRequest([TID|_] = TIDList, AD) ->
+ #'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = TIDList}.
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ statistics when SP#'StreamParms'.statisticsDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{statisticsDescriptor = D});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor,
+ 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ parse_prop_name(Text, Group).
+
+parse_prop_name([Char | Rest] = All, Group) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group)
+ end;
+parse_prop_name([] = All, Group) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group).
+
+do_parse_prop_name([Char | Rest], Name, Group)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ NewGroup = [],
+ [lists:reverse(Group) | parse_prop_value(Rest, Name, NewGroup)];
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], []) ->
+ [];
+do_parse_prop_name([], [], Group) ->
+ [lists:reverse(Group)];
+do_parse_prop_name([], Name, Group) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,3}]}).
+-endif.
+parse_prop_value(Chars, Name, Group) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group]);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group)
+ end;
+do_parse_prop_value([], Name, Value, Group) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ Groups.
+
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max == infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(true, F, A).
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("DBG:~w:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_prev3c.yrl b/lib/megaco/src/text/megaco_text_parser_prev3c.yrl
new file mode 100644
index 0000000000..9b7984deab
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_prev3c.yrl
@@ -0,0 +1,1673 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%
+%% NOTE 1 - This syntax specification does not enforce all restrictions
+%% on element inclusions and values. Some additional
+%% restrictions are stated in comments and other restrictions
+%% appear in the text of this Recommendation. These additional
+%% restrictions are part of the protocol even though not
+%% enforced by this Recommendation.
+%% NOTE 2 - The syntax is context-dependent. For example, "Add" can be
+%% the AddToken or a NAME depending on the context in which it
+%% occurs.
+%%
+%% Everything in the ABNF and text encoding is case insensitive. This
+%% includes TerminationIDs, digitmap Ids etc. SDP is case sensitive as
+%% per RFC 2327.
+%%
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 93.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestBody
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ auditSelectLogic %% v3
+ authenticationHeader
+ commandReplyList
+ commandReplys %% v3
+ commandRequest
+ contextAttrDescriptor %% v3
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextAuditSelector %% v3
+ contextID
+ contextIdList %% v3
+ contextIDs %% v3
+%% contextProperties %% v3
+ contextProperty
+%% contextPropertyList
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ direction %% v3
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ emergencyValue %% v3
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlValue %% v3
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStream
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+
+ iaServiceStates %% v3
+ iepsValue
+
+ %% v2 - start
+ indAudauditReturnParameter
+ indAuddigitMapDescriptor
+ indAudeventBufferDescriptor
+ indAudeventSpec
+ indAudeventSpecParameter
+ %% indAudeventSpecParameterList
+ indAudeventsDescriptor
+ indAudlocalControlDescriptor
+ indAudlocalParm
+ indAudlocalParmList
+ indAudmediaDescriptor
+ indAudmediaParm
+ indAudmediaParms %% v3
+ %% indAudmediaParmList
+ indAudpackagesDescriptor
+ indAudrequestedEvent
+ indAudsignalsDescriptor
+ indAudsignalList
+ %% indAudsignalListParm
+ indAudsignalParm
+ %% indAudsignalRequest
+ indAudstreamDescriptor
+ indAudstreamParm
+ indAudstatisticsDescriptor
+ indAudterminationAudit
+ indAudterminationAuditList
+ indAudterminationStateDescriptor
+ indAudterminationStateParm
+ %% indAudterminationStateParmList
+ optIndAudeventSpecParameter
+ optIndAudsignalParm
+ %% v2 - end
+
+ indAudcontextAttrDescriptor %% v3
+
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor % Deprecated as of Corr 1
+ modemType % Deprecated as of Corr 1
+ modemTypeList % Deprecated as of Corr 1
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyBehaviour %% v3
+ notifyRegulated %% v3
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ % observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ propertyParmList
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceStates
+ serviceStatesValue %% v3
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ termIDList %% v3
+ terminationAudit
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyDescComp
+ topologyDescCompList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AndAUDITselectToken' %% v3
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothToken' %% v3
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ 'ContextAttrToken' %% v3
+ 'ContextAuditToken'
+ 'ContextListToken' %% v3
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DirectionToken' %% v3
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'EmergencyOffToken'
+ 'EmergencyValueToken' %% v3
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'ExternalToken' %% v3
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'IEPSToken' %% v3
+ 'ImmAckRequiredToken'
+ 'INEQUAL' %% v3
+ 'InSvcToken'
+ 'InactiveToken'
+ 'InternalToken' %% v3
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'IntsigDelayToken' %% v3
+ 'IsolateToken'
+ 'IterationToken' %% v3
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NeverNotifyToken' %% v3
+ 'NotifyCompletionToken'
+ 'NotifyImmediateToken' %% v3
+ 'NotifyRegulatedToken' %% v3
+ 'NotifyToken'
+ 'Nx64Token' %% v2
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OnewayExternalToken' %% v3
+ 'OnewayBothToken' %% v3
+ 'OrAUDITselectToken' %% v3
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'RequestIDToken' %% v3
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResetEventsDescriptorToken' %% v3
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceChangeIncompleteToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ 'MessageSegmentToken' %% OTP-7534: v3-fix
+ 'SegmentationCompleteToken' %% OTP-7534: v3-fix
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody :
+ ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck
+ transactionAckList 'RBRKT' : ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck
+ transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT' :
+ #'TransactionPending'{transactionId = ensure_transactionID('$3') } .
+
+transactionRequest -> 'TransToken' 'LBRKT' actionRequest
+ actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL' 'LBRKT' actionRequest
+ actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList : ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+%% actionRequest = CtxToken EQUAL ContextID LBRKT ((contextRequest
+%% [COMMA commandRequestList]) /
+%% commandRequestList) RBRKT
+%% contextRequest = ((contextProperties [COMMA contextAudit]) /
+%% contextAudit)
+%% contextProperties = contextProperty *(COMMA contextProperty)
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestBody 'RBRKT' :
+ merge_action_request('$3', '$5') .
+
+actionRequestBody -> actionRequestItem actionRequestItems : ['$1' | '$2'] .
+
+actionRequestItems -> 'COMMA' actionRequestItem
+ actionRequestItems : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+actionRequestItem -> contextProperty : {contextProp, '$1'} .
+actionRequestItem -> contextAudit : {contextAudit, '$1'} .
+actionRequestItem -> commandRequest : {commandRequest, '$1'} .
+
+
+%% at-most-once (presumebly in contextProperties)
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+contextProperty -> 'EmergencyOffToken' : {emergency, false}.
+contextProperty -> iepsValue : {iepsCallind, '$1'} .
+contextProperty -> contextAttrDescriptor : '$1' .
+
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' propertyParms 'RBRKT' :
+ {contextProp, '$3'}.
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' contextIdList 'RBRKT' :
+ {contextList, '$3'}.
+
+contextIdList -> 'ContextListToken' 'EQUAL'
+ 'LBRKT' contextID contextIDs 'RBRKT' : ['$4' | '$5'] .
+
+contextIDs -> 'COMMA' contextID contextIDs : ['$2' | '$3'] .
+contextIDs -> '$empty' : [] .
+
+contextAudit -> 'ContextAuditToken' 'LBRKT'
+ indAudcontextAttrDescriptor 'RBRKT' :
+ merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, '$3') .
+contextAudit -> 'ContextAuditToken' 'LBRKT'
+ contextAuditProperty contextAuditProperties 'RBRKT' :
+ merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, ['$3' | '$4']) .
+
+indAudcontextAttrDescriptor -> 'ContextAttrToken'
+ 'LBRKT' contextAuditProperty
+ contextAuditProperties 'RBRKT'
+ : ['$3' | '$4'] .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty contextAuditProperties
+ : ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once except contextAuditSelector.
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+contextAuditProperty -> 'IEPSToken' : iepsCallind .
+contextAuditProperty -> pkgdName : {prop, '$1'} .
+contextAuditProperty -> contextAuditSelector : '$1' .
+
+%% at-most-once
+contextAuditSelector -> priority : {select_prio, '$1'} .
+contextAuditSelector -> emergencyValue : {select_emergency, '$1'} .
+contextAuditSelector -> iepsValue : {select_ieps, '$1'} .
+contextAuditSelector -> auditSelectLogic : {select_logic, '$1'} .
+contextAuditSelector -> contextAttrDescriptor : '$1' .
+
+auditSelectLogic -> 'AndAUDITselectToken' : {andAUDITSelect, 'NULL'} .
+auditSelectLogic -> 'OrAUDITselectToken' : {orAUDITSelect, 'NULL'} .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID
+ 'LBRKT'
+ optImmAckRequired transactionReplyBody
+ 'RBRKT'
+ : #'TransactionReply'{transactionId = '$3',
+ immAckRequired = '$5',
+ transactionResult = '$6'} .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor : {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList : {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+actionReply -> 'CtxToken' 'EQUAL' contextID :
+ #'ActionReply'{contextId = '$3'} .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReplys commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ [{error, '$2'}] .
+commandReplyList -> 'COMMA' commandReplys commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+commandReplys -> serviceChangeReply : {command, '$1'} .
+commandReplys -> auditReply : {command, '$1'} .
+commandReplys -> ammsReply : {command, '$1'} .
+commandReplys -> notifyReply : {command, '$1'} .
+commandReplys -> contextProperty : {context, '$1'} .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' termIDList ammRequestBody :
+ Descs = merge_AmmRequest_descriptors('$4', []),
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = '$3',
+ descriptors = Descs}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, deprecated}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+ammParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' termIDList ammsReplyBody
+ : {'$1', #'AmmsReply'{terminationID = '$3',
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL' termIDList optAuditDescriptor :
+ SR = #'SubtractRequest'{terminationID = '$3',
+ auditDescriptor = '$4'},
+ make_commandRequest({subtractReq, '$1'}, SR) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL' termIDList optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ make_auditRequest('$3', '$4')) .
+auditRequest -> 'AuditCapToken' 'EQUAL' termIDList optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ make_auditRequest('$3', '$4')) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit :
+ {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit :
+ {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther :
+ {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther :
+ {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList :
+ {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' :
+ {error, '$2'} .
+
+auditOther -> termIDList :
+ merge_auditOther('$1', []) .
+auditOther -> termIDList 'LBRKT' terminationAudit 'RBRKT' :
+ merge_auditOther('$1', '$3') .
+
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor.
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} .
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT' :
+ merge_auditDescriptor('$3') .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken.
+auditItem -> 'EventBufferToken' : eventBufferToken.
+auditItem -> 'EventsToken' : eventsToken .
+auditItem -> indAudterminationAudit : {terminationAudit, '$1'} . % v2
+%%
+%% IGv11 - end
+
+
+%% v2 - start
+%%
+indAudterminationAudit -> indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$1' | '$2'] .
+
+indAudterminationAuditList -> 'COMMA' indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$2' | '$3'] .
+indAudterminationAuditList -> '$empty' : [] .
+
+indAudauditReturnParameter -> indAudmediaDescriptor
+ : {indAudMediaDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventsDescriptor
+ : {indAudEventsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudsignalsDescriptor
+ : {indAudSignalsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAuddigitMapDescriptor
+ : {indAudDigitMapDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventBufferDescriptor
+ : {indAudEventBufferDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudstatisticsDescriptor
+ : {indAudStatisticsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudpackagesDescriptor
+ : {indAudPackagesDescriptor, '$1'} .
+
+
+indAudmediaDescriptor -> 'MediaToken' 'LBRKT'
+ indAudmediaParm indAudmediaParms 'RBRKT'
+ : merge_indAudMediaDescriptor(['$3'|'$4']) .
+
+%% at-most-once per item
+%% and either streamParm or streamDescriptor but not both
+%%
+
+indAudmediaParm -> indAudstreamParm : {streamParm, '$1'} .
+indAudmediaParm -> indAudstreamDescriptor : {streamDescr, '$1'} .
+indAudmediaParm -> indAudterminationStateDescriptor : {termStateDescr, '$1'} .
+
+indAudmediaParms -> 'COMMA' indAudmediaParm indAudmediaParms : ['$2' | '$3'] .
+indAudmediaParms -> '$empty' : [] .
+
+%% at-most-once
+indAudstreamParm -> 'RemoteDescriptorToken' :
+ RD = ensure_prop_groups('$1'),
+ #'IndAudStreamParms'{remoteDescriptor = RD} .
+indAudstreamParm -> 'LocalDescriptorToken' :
+ LD = ensure_prop_groups('$1'),
+ #'IndAudStreamParms'{localDescriptor = LD} .
+indAudstreamParm -> indAudlocalControlDescriptor :
+ #'IndAudStreamParms'{localControlDescriptor = '$1'} .
+indAudstreamParm -> indAudstatisticsDescriptor :
+ #'IndAudStreamParms'{statisticsDescriptor = '$1'} .
+
+indAudstreamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' indAudstreamParm 'RBRKT'
+ : #'IndAudStreamDescriptor'{streamID = '$3',
+ streamParms = '$5'} .
+
+
+indAudlocalControlDescriptor -> 'LocalControlToken'
+ 'LBRKT' indAudlocalParm
+ indAudlocalParmList 'RBRKT' :
+ merge_indAudLocalControlDescriptor(['$3' | '$4']) .
+
+indAudlocalParmList -> 'COMMA' indAudlocalParm
+ indAudlocalParmList : ['$2' | '$3'] .
+indAudlocalParmList -> '$empty' : [] .
+
+%% at-most-once per item
+%%
+%% propertyparm and streamModes are used only to specify audit selection
+%% criteria. AND/OR selection logic is specified at context level.
+%%
+indAudlocalParm -> 'ReservedGroupToken' : reservedGroupToken .
+indAudlocalParm -> 'ReservedValueToken' : reservedValueToken .
+indAudlocalParm -> 'ModeToken' : modeToken .
+indAudlocalParm -> 'ModeToken' 'EQUAL' streamModes : {mode, {equal, '$3'}} .
+indAudlocalParm -> 'ModeToken' 'INEQUAL' streamModes : {mode, {inequal,'$3'}} .
+indAudlocalParm -> propertyParm : {prop, '$1'} .
+indAudlocalParm -> pkgdName : {name, '$1'} .
+
+indAudterminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' indAudterminationStateParm 'RBRKT'
+ :
+ merge_indAudTerminationStateDescriptor('$3') .
+
+%% at-most-once per item
+%%
+
+%% at-most-once per item except for propertyParm
+indAudterminationStateParm -> iaServiceStates : '$1' .
+indAudterminationStateParm -> 'BufferToken' : bufferToken .
+indAudterminationStateParm -> propertyParm : {prop, '$1'} .
+indAudterminationStateParm -> pkgdName : {name, '$1'} .
+
+iaServiceStates -> 'ServiceStatesToken' :
+ serviceStatesToken .
+iaServiceStates -> 'ServiceStatesToken' 'EQUAL' serviceStatesValue :
+ {serviceStates, {equal, '$3'}} .
+iaServiceStates -> 'ServiceStatesToken' 'INEQUAL' serviceStatesValue :
+ {serviceStates, {inequal, '$3'}} .
+
+indAudeventBufferDescriptor -> 'EventBufferToken'
+ 'LBRKT' indAudeventSpec 'RBRKT' : '$3' .
+
+indAudeventSpec -> pkgdName optIndAudeventSpecParameter
+ : merge_indAudEventBufferDescriptor('$1','$2') .
+
+optIndAudeventSpecParameter -> 'LBRKT' indAudeventSpecParameter 'RBRKT'
+ : '$2' .
+optIndAudeventSpecParameter -> '$empty' : asn1_NOVALUE .
+
+
+indAudeventSpecParameter -> eventStream : {streamID, '$1'} .
+indAudeventSpecParameter -> eventParameterName : {eventParameterName, '$1'} .
+
+indAudeventsDescriptor -> 'EventsToken' 'LBRKT' indAudrequestedEvent 'RBRKT' :
+ #'IndAudEventsDescriptor'{pkgdName = '$3'} .
+indAudeventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' indAudrequestedEvent 'RBRKT' :
+ #'IndAudEventsDescriptor'{requestID = '$3',
+ pkgdName = '$5'} .
+
+indAudrequestedEvent -> pkgdName : '$1' .
+
+
+indAudsignalsDescriptor -> 'SignalsToken' optIndAudsignalParm : '$2' .
+
+
+optIndAudsignalParm -> 'LBRKT' 'RBRKT' : asn1_NOVALUE .
+optIndAudsignalParm -> 'LBRKT' indAudsignalParm 'RBRKT' : '$2' .
+
+indAudsignalParm -> indAudsignalList : {seqSigList, '$1'} .
+indAudsignalParm -> signalRequest : {signal, ensure_indAudSignal('$1')} .
+
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3')} .
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm 'RBRKT' :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3'),
+ signalList =
+ ensure_indAudSignalListParm('$5')} .
+
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+indAuddigitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_IADMD('$1') .
+
+indAudstatisticsDescriptor -> 'StatsToken' 'LBRKT' pkgdName 'RBRKT' :
+ #'IndAudStatisticsDescriptor'{statName = '$3'} .
+
+indAudpackagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem 'RBRKT'
+ : merge_indAudPackagesDescriptor('$3') .
+
+eventStream -> 'StreamToken' 'EQUAL' streamID : '$3' .
+
+
+%%
+%% v2 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' termIDList
+ 'LBRKT' notifyRequestBody 'RBRKT' :
+ NR = setelement(#'NotifyRequest'.terminationID,
+ '$5', '$3'),
+ make_commandRequest({notifyReq, '$1'}, NR) .
+
+notifyRequestBody -> observedEventsDescriptor :
+ #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor :
+ #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' termIDList notifyReplyBody :
+ {notifyReply, #'NotifyReply'{terminationID = '$3',
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' termIDList
+ 'LBRKT' serviceChangeDescriptor 'RBRKT' :
+ make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = '$3',
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' termIDList
+ serviceChangeReplyBody :
+ {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = '$3',
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' :
+ {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT' :
+ {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' :
+ {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT'
+ errorText 'RBRKT' :
+ #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+%% '-' is used for NULL context
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+termIDList -> terminationID : ['$1'] .
+termIDList -> LSBRKT terminationID terminationIDListRepeat RSBRKT :
+ ['$2' | '$3'] .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT' :
+ ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat :
+ ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-once .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs} } .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+streamParm -> statisticsDescriptor : {statistics, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm
+ terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue :
+ setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue :
+ '$2' .
+
+parmValue -> 'NEQUAL' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT' :
+ #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT' :
+ #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT' :
+ #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value :
+ #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec
+ eventSpecList 'RBRKT' :
+ ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceStatesValue : '$3'.
+
+serviceStatesValue -> 'TestToken' : test .
+serviceStatesValue -> 'OutOfSvcToken' : outOfSvc .
+serviceStatesValue -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlValue : '$3' .
+
+eventBufferControlValue -> 'OffToken' : off .
+eventBufferControlValue -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList :
+ #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' : #'RequestedEvent'{evParList = []} .
+
+
+notifyRegulated -> 'NotifyRegulatedToken' :
+ #'RegulatedEmbeddedDescriptor'{} .
+notifyRegulated -> 'NotifyRegulatedToken' 'LBRKT' embedWithSig 'RBRKT' :
+ make_RegulatedEmbeddedDescriptor('$3') .
+notifyRegulated -> 'NotifyRegulatedToken' 'LBRKT' embedNoSig 'RBRKT' :
+ make_RegulatedEmbeddedDescriptor('$3') .
+
+notifyBehaviour -> 'NotifyImmediateToken' : {notifyImmediate, 'NULL'} .
+notifyBehaviour -> 'NeverNotifyToken' : {neverNotify, 'NULL'} .
+notifyBehaviour -> notifyRegulated : {notifyRegulated, '$1'} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+eventParameter -> notifyBehaviour : {notifyBehaviour, '$1'}.
+eventParameter -> 'ResetEventsDescriptorToken' : resetEventsDescriptor .
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT'
+ : {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT'
+ : {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents : ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody
+ : setelement(#'SecondRequestedEvent'.pkgdName, '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter secondEventParameters 'RBRKT'
+ : merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' : #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters : ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+secondEventParameter -> notifyBehaviour : {notifyBehaviour, '$1'}.
+secondEventParameter -> 'ResetEventsDescriptorToken' : resetEventsDescriptor .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' :
+ ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' : [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther /
+%% notifyCompletion / KeepActiveToken /
+%% direction / sigRequestID
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason)
+%% RBRKT)
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken /
+%% InterruptByNewSignalsDescrToken /
+%% OtherReasonToken )
+%% sigDirection = DirectionToken EQUAL direction
+%% sigRequestID = RequestIDToken EQUAL RequestID
+%% sigIntsigDelay = IntsigDelayToken EQUAL UINT16
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID :
+ {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType :
+ {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken :
+ {duration, ensure_uint16('$3')} .
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT' :
+ {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+sigParameter -> 'DirectionToken' 'EQUAL' direction :
+ {direction, '$3'} .
+sigParameter -> 'RequestIDToken' 'EQUAL' requestID :
+ {requestId, '$3'} .
+sigParameter -> 'IntsigDelayToken' 'EQUAL' safeToken :
+ {intersigDelay, ensure_uint16('$3')} .
+sigParameter -> safeToken parmValue :
+ {other, ensure_NAME('$1'), '$2'}.
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+direction -> 'ExternalToken' : external .
+direction -> 'InternalToken' : internal .
+direction -> 'BothToken' : both .
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+notificationReason -> 'IterationToken' : iteration .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms :
+ ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+
+observedEvent -> timeStamp optSep 'COLON' optSep pkgdName observedEventBody :
+ merge_observed_event('$6', '$5', '$1') .
+observedEvent -> optSep pkgdName observedEventBody :
+ merge_observed_event('$3', '$2', asn1_NOVALUE) .
+
+observedEventBody -> 'LBRKT' observedEventParameter
+ observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+%% Deprecated as of Corr 1
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms .
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms.
+modemTypeList -> 'COMMA' modemType modemTypeList.
+modemTypeList -> '$empty'.
+modemType -> safeToken.
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParmList 'RBRKT' :
+ ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> propertyParm propertyParmList : ['$1' | '$2'] .
+propertyParmList -> 'COMMA' propertyParm propertyParmList : ['$2' | '$3'] .
+propertyParmList -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_DMD('$1') .
+
+%% each parameter at-most-once, except auditItem
+%% at most one of either serviceChangeAddress or serviceChangeMgcId but
+%% not both. serviceChangeMethod and serviceChangeReason are REQUIRED
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp, '$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+serviceChangeParm -> 'ServiceChangeIncompleteToken' : incomplete . % v3
+serviceChangeParm -> auditItem : {audit_item, '$1'} . % v2
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken :
+ ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber :
+ {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'} .
+servChgReplyParm -> timeStamp : {time_stamp,'$1'} .
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem
+ packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter
+ statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+statisticsParameter -> pkgdName 'EQUAL' 'LSBRKT' value valueList 'RSBRKT' :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = ['$4' | '$5']} .
+
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT'
+ topologyDescComp topologyDescCompList 'RBRKT' :
+ merge_topologyDescriptor(['$3' | '$4']) .
+
+topologyDescComp -> terminationID : {tid, '$1'} .
+topologyDescComp -> eventStream : {sid, '$1'} .
+topologyDescComp -> topologyDirection : '$1' .
+
+topologyDescCompList -> '$empty' : [] .
+topologyDescCompList -> 'COMMA' topologyDescComp topologyDescCompList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : {direction, bothway} .
+topologyDirection -> 'IsolateToken' : {direction, isolate} .
+topologyDirection -> 'OnewayToken' : {direction, oneway} .
+topologyDirection -> 'OnewayExternalToken' : {direction_ext, onewayexternal} .
+topologyDirection -> 'OnewayBothToken' : {direction_ext, onewayboth} .
+
+iepsValue -> 'IEPSToken' 'EQUAL' onOrOff : '$3' .
+
+emergencyValue -> 'EmergencyValueToken' 'EQUAL' 'EmergencyToken' : true .
+emergencyValue -> 'EmergencyValueToken' 'EQUAL' 'EmergencyOffToken' : false .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' : ensure_value('$1') .
+value -> safeToken : ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+%% BMK BMK safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothToken' : '$1' . % v3
+%% v3-safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+%% v3-safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% v3-safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% v3-safeToken2 -> 'ContextListToken' : '$1' . % v3
+%% v2-safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+%% v3-
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% v2-safeToken2 -> 'EventBufferToken' : '$1' .
+%% v2-safeToken2 -> 'EventsToken' : '$1' .
+%% v3-safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+%% v3-safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+%% v3-safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+%% v3-safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% v2-safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+%% v3-safeToken2 -> 'ModeToken' : '$1' .
+%% BMK BMK safeToken2 -> 'ModifyToken' : '$1' .
+%% v2-safeToken2 -> 'ModemToken' : '$1' .
+%% BMK BMK safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% v2-safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64Token' : '$1' .
+%% v2-safeToken2 -> 'ObservedEventsToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayExternalToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayBothToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% v2-safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+%% BMK BMK safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+%% v3-
+safeToken2 -> 'RequestIDToken' : '$1' . % v3
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+%% v3-safeToken2 -> 'ReservedGroupToken' : '$1' .
+%% v3-safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' . % v3
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% v2-safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% v2-safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+%% BMK BMK safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+%% BMK BMK safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+%% <OTP-7534>
+safeToken2 -> 'MessageSegmentToken' : '$1' . % v3
+safeToken2 -> 'SegmentationCompleteToken' : '$1' . % v3
+%% </OTP-7534>
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_prev3c.hrl").
+
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v1.hrl b/lib/megaco/src/text/megaco_text_parser_v1.hrl
new file mode 100644
index 0000000000..ebc43c0352
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v1.hrl
@@ -0,0 +1,1410 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. % We really should ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% The values 0x0, 0xFFFFFFFE and 0xFFFFFFFF are reserved.
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and issue the
+ %% error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) == 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) == 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when length(Hex4) =< 4, length(Hex4) > 0 ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ (X =/= $X) andalso (X =/= $x) andalso
+ (S =/= $+) andalso (S =/= $-) ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_modemType,1}]}).
+-endif.
+ensure_modemType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "v32b" -> v32bis;
+ "v22b" -> v22bis;
+ "v18" -> v18;
+ "v22" -> v22;
+ "v32" -> v32;
+ "v34" -> v34;
+ "v90" -> v90;
+ "v91" -> v91;
+ "synchisdn" -> synchISDN;
+ "sn" -> synchISDN;
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (neither length nor content) there is really no
+ %% point in "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE)
+ andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE)) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE) ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE)) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE) ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeProfile =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeVersion =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when (SCP0#'ServiceChangeParm'.serviceChangeReason =:= undefined) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeDelay =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when (SCP0#'ServiceChangeParm'.serviceChangeMethod =:= undefined) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.timeStamp =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_profile,1}]}).
+-endif.
+ensure_profile(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, StreamId} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = StreamId}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+%% Version 2 of the DigitMapValue has an extra item (after extension mark),
+%% durationTimer, which does not exist in version 1. The record was created
+%% as defined in megaco_message_internal.hrl, e.g. as in version 2, so we
+%% have to fix it here.
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ %% Convert to version 1 DigitMapValue
+ {'DigitMapValue', Start, Short, Long, _DurationTimer, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+%% Version 2 of the DigitMapValue has an extra item (after extension mark),
+%% durationTimer, which does not exist in version 1. The record is defined
+%% (in megaco_message_internal.hrl) as in version 2, so we have to fix
+%% it here.
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ {'DigitMapValue', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE, []} ->
+ asn1_NOVALUE;
+ {'DigitMapValue', Start, Short, Long, _DurationTimer, Body} ->
+ %% Convert to version 1 DigitMapValue
+ #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation == asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, StreamId, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], StreamId, EPL, RA, HasA) ->
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewStreamId, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], StreamId, EPL, RA, yes) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], StreamId, EPL, _RA, no) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, StreamId, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], StreamId, EPL, SRA, HasA) ->
+ case H of
+ keepActive when (SRA#'SecondRequestedActions'.keepActive =:= asn1_NOVALUE) ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {second_embed, SD} when (SRA#'SecondRequestedActions'.signalsDescriptor =:= asn1_NOVALUE) ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {eventDM, DM} when (SRA#'SecondRequestedActions'.eventDM =:= asn1_NOVALUE) ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {stream, NewStreamId} when (StreamId =:= asn1_NOVALUE) ->
+ do_merge_secondEventParameters(T, NewStreamId, EPL, SRA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], StreamId, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], StreamId, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ ensure_transactionAck2(Text, []).
+
+ensure_transactionAck2([], Acc) ->
+ Id = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ensure_transactionAck2([$- | Id2], Acc) ->
+ Id1 = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id1),
+ lastAck = ensure_transactionID(Id2)};
+ensure_transactionAck2([H|T], Acc) ->
+ ensure_transactionAck2(T, [H|Acc]).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_requests,2}]}).
+-endif.
+merge_action_requests(ContextId, Items) ->
+ CtxReq = #'ContextRequest'{},
+ CtxAuditReq = #'ContextAttrAuditRequest'{},
+ CmdReq = [],
+ TopReq = [],
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq, CmdReq, TopReq, Items).
+
+do_merge_action_requests(ContextId, CtxReq, CtxAuditReq, CmdReq, TopReq, [H | T]) ->
+ case H of
+ _ when is_record(H, 'CommandRequest') ->
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq, [H | CmdReq], TopReq, T);
+
+ {priority, Int} when CtxReq#'ContextRequest'.priority == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+ do_merge_action_requests(ContextId, CtxReq2, CtxAuditReq, CmdReq,
+ TopReq, T);
+ {emergency, Bool} when CtxReq#'ContextRequest'.emergency == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+ do_merge_action_requests(ContextId, CtxReq2, CtxAuditReq, CmdReq,
+ TopReq, T);
+ {topology, Desc} ->
+ TopReq2 = Desc ++ TopReq, %% OTP-4088
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq, CmdReq,
+ TopReq2, T);
+
+ priorityAudit when CtxAuditReq#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+ CtxAuditReq2 = CtxAuditReq#'ContextAttrAuditRequest'{priority = 'NULL'},
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq2, CmdReq,
+ TopReq, T);
+ emergencyAudit when CtxAuditReq#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+ CtxAuditReq2 = CtxAuditReq#'ContextAttrAuditRequest'{emergency = 'NULL'},
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq2, CmdReq,
+ TopReq, T);
+ topologyAudit when CtxAuditReq#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+ CtxAuditReq2 = CtxAuditReq#'ContextAttrAuditRequest'{topology = 'NULL'},
+ do_merge_action_requests(ContextId, CtxReq, CtxAuditReq2, CmdReq,
+ TopReq, T)
+ end;
+do_merge_action_requests(ContextId, CtxReq, CtxAuditReq, CmdReq, TopReq, []) ->
+ #'ActionRequest'{contextId = ContextId,
+ contextRequest = strip_contextRequest(CtxReq, TopReq),
+ contextAttrAuditReq = strip_contextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReq)}.
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(ReplyList) ->
+ CtxReq = #'ContextRequest'{},
+ TopReq = [],
+ CmdList = [],
+ do_merge_action_reply(ReplyList, CtxReq, TopReq, CmdList).
+
+do_merge_action_reply([ED], CtxReq, TopReq, CmdList)
+ when is_record(ED, 'ErrorDescriptor') ->
+ #'ActionReply'{contextReply = strip_contextRequest(CtxReq, TopReq),
+ commandReply = lists:reverse(CmdList),
+ errorDescriptor = ED};
+do_merge_action_reply([H | T], CtxReq, TopReq, CmdList) ->
+ case H of
+ {command, Cmd} ->
+ do_merge_action_reply(T, CtxReq, TopReq, [Cmd | CmdList]);
+ {context, Ctx} ->
+ case Ctx of
+ {priority, Int} when CtxReq#'ContextRequest'.priority =:= asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+ do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+ {emergency, Bool} when CtxReq#'ContextRequest'.emergency =:= asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+ do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+ {topology, Desc} ->
+ TopReq2 = Desc ++ TopReq, %% OTP-4088
+ do_merge_action_reply(T, CtxReq, TopReq2, CmdList)
+ end
+ end;
+do_merge_action_reply([], CtxReq, TopReq, CmdList) ->
+ #'ActionReply'{contextReply = strip_contextRequest(CtxReq, TopReq),
+ commandReply = lists:reverse(CmdList)}.
+
+strip_contextRequest(R, TopReq)
+ when (R#'ContextRequest'.priority =:= asn1_NOVALUE) andalso
+ (R#'ContextRequest'.emergency =:= asn1_NOVALUE) andalso
+ (TopReq =:= []) ->
+ asn1_NOVALUE;
+strip_contextRequest(R, []) ->
+ R#'ContextRequest'{topologyReq = asn1_NOVALUE};
+strip_contextRequest(R, TopReq) ->
+ R#'ContextRequest'{topologyReq = TopReq}. %% OTP-4088
+
+
+strip_contextAttrAuditRequest(R)
+ when (R#'ContextAttrAuditRequest'.priority =:= asn1_NOVALUE) andalso
+ (R#'ContextAttrAuditRequest'.emergency =:= asn1_NOVALUE) andalso
+ (R#'ContextAttrAuditRequest'.topology =:= asn1_NOVALUE) ->
+ asn1_NOVALUE;
+strip_contextAttrAuditRequest(R) ->
+ R.
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor,
+ 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ parse_prop_name(Text, Group).
+
+parse_prop_name([Char | Rest] = All, Group) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group)
+ end;
+parse_prop_name([] = All, Group) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group).
+
+do_parse_prop_name([Char | Rest], Name, Group)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ NewGroup = [],
+ [lists:reverse(Group) | parse_prop_value(Rest, Name, NewGroup)];
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], []) ->
+ [];
+do_parse_prop_name([], [], Group) ->
+ [lists:reverse(Group)];
+do_parse_prop_name([], Name, Group) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,3}]}).
+-endif.
+parse_prop_value(Chars, Name, Group) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group]);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group)
+ end;
+do_parse_prop_value([], Name, Value, Group) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ [Group2].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ %% do_ensure_prop_groups(Groups).
+ Groups.
+
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+% d(F) ->
+% d(F,[]).
+% d(F, A) ->
+% io:format("~p:" ++ F ++ "~n", [?MODULE | A]).
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v1.yrl b/lib/megaco/src/text/megaco_text_parser_v1.yrl
new file mode 100644
index 0000000000..fd50d90523
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v1.yrl
@@ -0,0 +1,1364 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 609.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ authenticationHeader
+ commandReply
+ commandReplyList
+ commandRequest
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextID
+ contextProperty
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlState
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor
+ modemType
+ modemTypeList
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceState
+ serviceStates
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ terminationA
+ terminationAudit
+ terminationB
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyTriple
+ topologyTripleList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ 'ContextAuditToken'
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'ImmAckRequiredToken'
+ 'InSvcToken'
+ 'InactiveToken'
+ 'IsolateToken'
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NotifyCompletionToken'
+ 'NotifyToken'
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ 'AndAUDITSelectToken' %% OTP-7534: v3-fix
+ 'BothToken' %% OTP-7534: v3-fix
+ 'ContextAttrToken' %% OTP-7534: v3-fix
+ 'ContextListToken' %% OTP-7534: v3-fix
+ 'DirectionToken' %% OTP-7534: v3-fix
+ 'EmergencyOffToken' %% OTP-7534: v3-fix
+ 'EmergencyValueToken' %% OTP-7534: v3-fix
+ 'ExternalToken' %% OTP-7534: v3-fix
+ 'IEPSToken' %% OTP-7534: v3-fix
+ 'IntsigDelayToken' %% OTP-7534: v3-fix
+ 'InternalToken' %% OTP-7534: v3-fix
+ 'IterationToken' %% OTP-7534: v3-fix
+ 'MessageSegmentToken' %% OTP-7534: v3-fix
+ 'NeverNotifyToken' %% OTP-7534: v3-fix
+ 'NotifyImmediateToken' %% OTP-7534: v3-fix
+ 'NotifyRegulatedToken' %% OTP-7534: v3-fix
+ 'Nx64kToken' %% OTP-7534: v2-fix
+ 'OnewayBothToken' %% OTP-7534: v3-fix
+ 'OnewayExternalToken' %% OTP-7534: v3-fix
+ 'OrAUDITselectToken' %% OTP-7534: v3-fix
+ 'RequestIDToken' %% OTP-7534: v3-fix
+ 'ResetEventsDescriptorToken' %% OTP-7534: v3-fix
+ 'SegmentationCompleteToken' %% OTP-7534: v3-fix
+ 'ServiceChangeIncompleteToken' %% OTP-7534: v3-fix
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage :
+ #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL'
+ safeToken 'COLON' safeToken 'COLON' safeToken optSep :
+ ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody :
+ ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck transactionAckList 'RBRKT' :
+ ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT' :
+ #'TransactionPending'{transactionId = ensure_transactionID('$3')} .
+
+transactionRequest -> 'TransToken'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList :
+ ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestItem actionRequestItems 'RBRKT' :
+ merge_action_requests('$3', ['$5' | '$6']) .
+
+actionRequestItems -> 'COMMA' actionRequestItem actionRequestItems : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+actionRequestItem -> contextProperty : '$1'.
+actionRequestItem -> contextAudit : '$1' .
+actionRequestItem -> commandRequest : '$1'.
+
+%% at-most-once
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+
+contextAudit -> 'ContextAuditToken'
+ 'LBRKT' contextAuditProperty
+ contextAuditProperties 'RBRKT' :
+ ['$3' | '$4'] .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty
+ contextAuditProperties :
+ ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once .
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID
+ 'LBRKT' optImmAckRequired
+ transactionReplyBody 'RBRKT' :
+ #'TransactionReply'{transactionId = '$3',
+ immAckRequired = '$5',
+ transactionResult = '$6'} .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor :
+ {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList :
+ {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReply commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+commandReply -> serviceChangeReply : {command, '$1'} .
+commandReply -> auditReply : {command, '$1'} .
+commandReply -> ammsReply : {command, '$1'} .
+commandReply -> notifyReply : {command, '$1'} .
+commandReply -> contextProperty : {context, '$1'} .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ ['$2'] .
+commandReplyList -> 'COMMA' commandReply commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' terminationID ammRequestBody :
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = ['$3'],
+ descriptors = '$4'}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, '$1'}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' terminationID ammsReplyBody :
+ {'$1', #'AmmsReply'{terminationID = ['$3'],
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({subtractReq, '$1'},
+ #'SubtractRequest'{terminationID = ['$3'],
+ auditDescriptor = '$4'}) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+auditRequest -> 'AuditCapToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther
+ : {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther
+ : {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList : {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' : {contextAuditResult, '$2'} .
+
+auditOther -> terminationID :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = []}} .
+auditOther -> terminationID 'LBRKT' terminationAudit 'RBRKT' :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = '$3'}} .
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor : {modemDescriptor, '$1'} .
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} . %% IGv11
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT'
+ : #'AuditDescriptor'{auditToken = '$3'} .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+%%
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken .
+auditItem -> 'EventBufferToken' : eventBufferToken .
+auditItem -> 'EventsToken' : eventsToken .
+%%
+%% IGv11 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' terminationID
+ 'LBRKT' notifyRequestBody 'RBRKT'
+ : make_commandRequest({notifyReq, '$1'},
+ setelement(#'NotifyRequest'.terminationID, '$5', ['$3'])) .
+
+notifyRequestBody -> observedEventsDescriptor
+ : #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor
+ : #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' terminationID notifyReplyBody
+ : {notifyReply,
+ #'NotifyReply'{terminationID = ['$3'],
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' terminationID
+ 'LBRKT' serviceChangeDescriptor 'RBRKT'
+ : make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = ['$3'],
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' terminationID serviceChangeReplyBody
+ : {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = ['$3'],
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT'
+ : {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT'
+ : {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' : {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT' errorText 'RBRKT'
+ : #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+%% terminationIDList -> LBRKT terminationID *(COMMA terminationID) RBRKT .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT'
+ : ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat
+ : ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-onc .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs} } .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue : '$2' .
+
+parmValue -> 'NEQUAL' value
+ : #'PropertyParm'{value = ['$2'], extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value
+ : #'PropertyParm'{value = ['$2'], extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value
+ : #'PropertyParm'{value = ['$2'], extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT'
+ : #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value : #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec eventSpecList 'RBRKT'
+ : ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceState : '$3' .
+
+serviceState -> 'TestToken' : test .
+serviceState -> 'OutOfSvcToken' : outOfSvc .
+serviceState -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlState : '$3' .
+
+eventBufferControlState -> 'OffToken' : off .
+eventBufferControlState -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList
+ : #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' :
+ #'RequestedEvent'{evParList = []} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' :
+ [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT' :
+ {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT' :
+ {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT' :
+ {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent
+ secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents :
+ ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody :
+ setelement(#'SecondRequestedEvent'.pkgdName,
+ '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter
+ secondEventParameters 'RBRKT' :
+ merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' :
+ #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters :
+ ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT' :
+ {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken :
+ ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' : ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' :
+ [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther
+%% / notifyCompletion / KeepActiveToken
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason) RBRKT
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken
+%% / InterruptByNewSignalsDescrToken
+%% / OtherReasonToken )
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID : {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType : {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken : {duration, ensure_uint16('$3')} .
+sigParameter -> safeToken parmValue : {other, ensure_NAME('$1'), '$2'}.
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT'
+ : {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms : ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+observedEvent -> observedEventTimeStamp optSep pkgdName observedEventBody :
+ merge_observed_event('$4', '$3', '$1') .
+observedEvent -> pkgdName observedEventBody :
+ merge_observed_event('$2', '$1', asn1_NOVALUE) .
+
+observedEventTimeStamp -> timeStamp optSep 'COLON' : '$1' .
+observedEventTimeStamp -> '$empty' : asn1_NOVALUE .
+
+observedEventBody -> 'LBRKT' observedEventParameter observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms :
+ #'ModemDescriptor'{mtl = ['$3'],
+ mpl = '$4'} .
+
+%% at-most-once of each modem type exept for extensionParameter
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms :
+ #'ModemDescriptor'{mtl = ['$3' | '$4'],
+ mpl = '$6'} .
+
+modemTypeList -> 'COMMA' modemType modemTypeList : ['$2' | '$3'] .
+modemTypeList -> '$empty' : [] .
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParms 'RBRKT' : ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> 'COMMA' propertyParm propertyParms : ['$2' | '$3'] .
+propertyParms -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+modemType -> safeToken : ensure_modemType('$1').
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' : ensure_DMD('$1') .
+
+%% ; at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp,'$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken : ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber : {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'}.
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'}.
+servChgReplyParm -> timeStamp : {time_stamp,'$1'}.
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT' topologyTriple
+ topologyTripleList 'RBRKT' : ['$3' | '$4'] .
+
+terminationA -> terminationID : '$1' .
+
+terminationB -> terminationID : '$1' .
+
+topologyTriple -> terminationA 'COMMA' terminationB 'COMMA'
+ topologyDirection :
+ #'TopologyRequest'{terminationFrom = '$1',
+ terminationTo = '$3',
+ topologyDirection = '$5'} .
+
+topologyTripleList -> '$empty' : [] .
+topologyTripleList -> 'COMMA' topologyTriple topologyTripleList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : bothway .
+topologyDirection -> 'IsolateToken' : isolate .
+topologyDirection -> 'OnewayToken' : oneway .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' : ensure_value('$1') .
+value -> safeToken : ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+safeToken2 -> 'ContextAuditToken' : '$1' .
+safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+safeToken2 -> 'EmergencyToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+safeToken2 -> 'EventBufferToken' : '$1' .
+safeToken2 -> 'EventsToken' : '$1' .
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+safeToken2 -> 'ModeToken' : '$1' .
+safeToken2 -> 'ModifyToken' : '$1' .
+safeToken2 -> 'ModemToken' : '$1' .
+safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'ObservedEventsToken' : '$1' .
+safeToken2 -> 'OnewayToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+safeToken2 -> 'ReservedGroupToken' : '$1' .
+safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+%% <OTP-7534>
+safeToken2 -> 'AndAUDITSelectToken' : '$1' . % v3
+safeToken2 -> 'BothToken' : '$1' . % v3
+safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextListToken' : '$1' . % v3
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'EmergencyOffToken' : '$1' . % v3
+safeToken2 -> 'EmergencyValueToken' : '$1' . % v3
+safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'IntsigDelayToken' : '$1' . % v3
+safeToken2 -> 'IterationToken' : '$1' . % v3
+safeToken2 -> 'MessageSegmentToken' : '$1' . % v3
+safeToken2 -> 'NeverNotifyToken' : '$1' . % v3
+safeToken2 -> 'NotifyImmediateToken' : '$1' . % v3
+safeToken2 -> 'NotifyRegulatedToken' : '$1' . % v3
+safeToken2 -> 'Nx64kToken' : '$1' . % v2
+safeToken2 -> 'OnewayBothToken' : '$1' . % v3
+safeToken2 -> 'OnewayExternalToken' : '$1' . % v3
+safeToken2 -> 'OrAUDITselectToken' : '$1' . % v3
+safeToken2 -> 'RequestIDToken' : '$1' . % v3
+safeToken2 -> 'ResetEventsDescriptorToken' : '$1' . % v3
+safeToken2 -> 'SegmentationCompleteToken' : '$1' . % v3
+safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' . % v3
+%% </OTP-7534>
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_v1.hrl").
+
+%%i(F) ->
+%% i(F, []).
+
+%%i(F, A) ->
+%% i(get(dbg), F, A).
+
+%%i(true, F, A) ->
+%% io:format("DBG:~p:" ++ F ++ "~n", [?MODULE|A]);
+%%i(_, _, _) ->
+%% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v2.hrl b/lib/megaco/src/text/megaco_text_parser_v2.hrl
new file mode 100644
index 0000000000..e968db398d
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v2.hrl
@@ -0,0 +1,1643 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v2.hrl").
+-define(encoder_version_pre_prev3c,true).
+-include("megaco_text_tokens.hrl").
+
+-define(d(F,A), io:format("DBG:"++F++"~n",A)).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% The values 0x0, 0xFFFFFFFE and 0xFFFFFFFF are reserved.
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and issue the
+ %% the error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when (length(A) =:= 16) ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when (length(A) =:= 16) ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when (length(A) =:= 16) ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when length(Hex4) =< 4, length(Hex4) > 0 ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ (X =/= $X) andalso (X =/= $x) andalso
+ (S =/= $+) andalso (S =/= $-) ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% and since this functon is only used when creating
+%% a ModemDescriptor, iit is removed.
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+%% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+%% case Text of
+%% "v32b" -> v32bis;
+%% "v22b" -> v22bis;
+%% "v18" -> v18;
+%% "v22" -> v22;
+%% "v32" -> v32;
+%% "v34" -> v34;
+%% "v90" -> v90;
+%% "v91" -> v91;
+%% "synchisdn" -> synchISDN;
+%% "sn" -> synchISDN;
+%% [$x | _] -> ensure_extensionParameter(Token)
+%% end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ "nx64k" -> nx64k; % v2
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_packagesItem,1}]}).
+-endif.
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (length or content) there is really no point in
+ %% "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+
+%% v2 - start
+
+merge_indAudMediaDescriptor({termStateDescr, Val}) ->
+ #'IndAudMediaDescriptor'{termStateDescr = Val};
+merge_indAudMediaDescriptor({streamParm, Val}) ->
+ #'IndAudMediaDescriptor'{streams = {oneStream, Val}};
+merge_indAudMediaDescriptor({streamDescr, Val}) ->
+ #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudLocalControlDescriptor,1}]}).
+-endif.
+merge_indAudLocalControlDescriptor(Parms) ->
+ do_merge_indAudLocalControlDescriptor(Parms,
+ #'IndAudLocalControlDescriptor'{}).
+
+do_merge_indAudLocalControlDescriptor([Parm | Parms], Desc) ->
+ case Parm of
+ modeToken when Desc#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedGroupToken when Desc#'IndAudLocalControlDescriptor'.reserveGroup == asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ reservedValueToken when Desc#'IndAudLocalControlDescriptor'.reserveValue == asn1_NOVALUE ->
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when Desc#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->
+ PropParms = [#'IndAudPropertyParm'{name = Val}],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2);
+ {pkgdName, Val} when is_list(Desc#'IndAudLocalControlDescriptor'.propertyParms) ->
+ PropParms = Desc#'IndAudLocalControlDescriptor'.propertyParms,
+ PropParms2 = [#'IndAudPropertyParm'{name = Val} | PropParms],
+ Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2},
+ do_merge_indAudLocalControlDescriptor(Parms, Desc2)
+ end;
+do_merge_indAudLocalControlDescriptor([], Desc) ->
+ case Desc#'IndAudLocalControlDescriptor'.propertyParms of
+ [_ | _] = PropParms -> % List has more then one element
+ PropParms2= lists:reverse(PropParms),
+ Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+ _ ->
+ Desc
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudLocalParm,1}]}).
+-endif.
+ensure_indAudLocalParm(Token) ->
+ case Token of
+ {safeToken, _Line, "mode"} -> modeToken;
+ {safeToken, _Line, "mo"} -> modeToken;
+ {safeToken, _Line, "reservedgroup"} -> reservedGroupToken;
+ {safeToken, _Line, "rg"} -> reservedGroupToken;
+ {safeToken, _Line, "reservedvalue"} -> reservedValueToken;
+ {safeToken, _Line, "rv"} -> reservedValueToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+merge_indAudTerminationStateDescriptor({pkgdName, Val}) ->
+ PropParm = #'IndAudPropertyParm'{name = Val},
+ #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+ #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+merge_indAudTerminationStateDescriptor(bufferToken) ->
+ #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudEventBufferDescriptor,2}]}).
+-endif.
+merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+ IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+ do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+ IAEBD;
+do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+ IAEBD) ->
+ %% BUGBUG BUGBUG BUGBUG
+ %% This is an ugly hack to allow the eventParamName which only
+ %% exists in the text encoding...
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+ensure_indAudSignalListParm(SIG) when is_record(SIG, 'Signal') ->
+ ensure_indAudSignal(SIG).
+
+ensure_indAudSignal(#'Signal'{signalName = SignalName,
+ streamID = asn1_NOVALUE,
+ sigType = asn1_NOVALUE,
+ duration = asn1_NOVALUE,
+ notifyCompletion = asn1_NOVALUE,
+ keepActive = asn1_NOVALUE,
+ sigParList = []}) ->
+ #'IndAudSignal'{signalName = SignalName}.
+
+
+ensure_IADMD({_TokenTag, _Line,
+ #'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE}}) ->
+ #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+
+merge_indAudPackagesDescriptor(#'PackagesItem'{packageName = N,
+ packageVersion = V}) ->
+ #'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudTerminationStateParm,1}]}).
+-endif.
+ensure_indAudTerminationStateParm(Token) ->
+ case Token of
+ {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+ {safeToken, _Line, "si"} -> serviceStatesToken;
+ {safeToken, _Line, "buffer"} -> bufferToken;
+ {safeToken, _Line, "bf"} -> bufferToken;
+ PkgdName -> {pkgdName,
+ ensure_pkgdName(PkgdName)}
+ end.
+
+
+%% Types modified by v2:
+
+merge_auditDescriptor([]) ->
+ #'AuditDescriptor'{};
+merge_auditDescriptor(Tokens) when is_list(Tokens) ->
+ case lists:keysearch(terminationAudit, 1, Tokens) of
+ {value, {terminationAudit, TA}} ->
+ case lists:keydelete(terminationAudit, 1, Tokens) of
+ [] ->
+ #'AuditDescriptor'{auditPropertyToken = TA};
+ AuditTokens ->
+ #'AuditDescriptor'{auditToken = AuditTokens,
+ auditPropertyToken = TA}
+ end;
+ false ->
+ #'AuditDescriptor'{auditToken = Tokens}
+ end;
+merge_auditDescriptor(_) ->
+ #'AuditDescriptor'{}.
+
+
+%% v2 - end
+
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE)
+ andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE)) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE)) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeReason == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeDelay == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeMethod == undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.timeStamp == asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+%% OTP-5353.
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeInfo =:= asn1_NOVALUE)
+ andalso is_atom(Val)) ->
+ SCI = #'AuditDescriptor'{auditToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when ((SCP0#'ServiceChangeParm'.serviceChangeInfo =:= asn1_NOVALUE)
+ andalso is_tuple(Val)) ->
+ SCI = #'AuditDescriptor'{auditPropertyToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor')
+ andalso is_atom(Val)) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditToken,
+ SCI = SCI0#'AuditDescriptor'{auditToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor')
+ andalso is_tuple(Val)) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditPropertyToken,
+ SCI = SCI0#'AuditDescriptor'{auditPropertyToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp;
+ audit_item ->
+ SCP#'ServiceChangeParm'.serviceChangeInfo
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE,
+ SCRP0#'ServiceChangeResParm'.serviceChangeAddress == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId == asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp == asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_profile,1}]}).
+-endif.
+ensure_profile({_TokenTag, Line, Text}) ->
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, StreamId} when Sig#'Signal'.streamID == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = StreamId}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion == asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive == asn1_NOVALUE->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body,
+ durationTimer = Duration},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ #'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ durationTimer = [],
+ digitMapBody = asn1_NOVALUE} ->
+ asn1_NOVALUE;
+ #'DigitMapValue'{durationTimer = Body,
+ digitMapBody = Duration} = DMV ->
+ %% Convert to version 1 DigitMapValue
+ DMV#'DigitMapValue'{digitMapBody = Body,
+ durationTimer = Duration};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation == asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, StreamId, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], StreamId, EPL, RA, HasA) ->
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM == asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, StreamId, EPL, RA2, yes);
+ {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewStreamId, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, StreamId, [EP | EPL], RA, HasA);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], StreamId, EPL, RA, yes) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], StreamId, EPL, _RA, no) ->
+ #'RequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, StreamId, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], StreamId, EPL, SRA, HasA) ->
+ case H of
+ keepActive when SRA#'SecondRequestedActions'.keepActive == asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor == asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM == asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, StreamId, EPL, SRA2, yes);
+ {stream, NewStreamId} when StreamId == asn1_NOVALUE ->
+ do_merge_secondEventParameters(T, NewStreamId, EPL, SRA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, StreamId, [EP | EPL], SRA, HasA);
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], StreamId, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], StreamId, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = StreamId,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ ensure_transactionAck2(Text, []).
+
+ensure_transactionAck2([], Acc) ->
+ Id = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ensure_transactionAck2([$- | Id2], Acc) ->
+ Id1 = lists:reverse(Acc),
+ #'TransactionAck'{firstAck = ensure_transactionID(Id1),
+ lastAck = ensure_transactionID(Id2)};
+ensure_transactionAck2([H|T], Acc) ->
+ ensure_transactionAck2(T, [H|Acc]).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_requests,2}]}).
+-endif.
+merge_action_requests(CtxId, Items) ->
+ CtxReq = #'ContextRequest'{},
+ CtxAuditReq = asn1_NOVALUE,
+ CmdReq = [],
+ TopReq = [],
+ do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, Items).
+
+do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, [H | T]) ->
+ case H of
+ _ when is_record(H, 'CommandRequest') ->
+ do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, [H | CmdReq], TopReq, T);
+
+ {priority, Int} when CtxReq#'ContextRequest'.priority == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+ do_merge_action_requests(CtxId, CtxReq2, CtxAuditReq, CmdReq,
+ TopReq, T);
+ {emergency, Bool} when CtxReq#'ContextRequest'.emergency == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+ do_merge_action_requests(CtxId, CtxReq2, CtxAuditReq, CmdReq,
+ TopReq, T);
+ {topology, Desc} ->
+ TopReq2 = Desc ++ TopReq, %% OTP-4088
+ do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq,
+ TopReq2, T);
+
+ {contextAudit, CAs} ->
+ CtxAuditReq2 = merge_context_attr_audit_request(CtxAuditReq, CAs),
+ do_merge_action_requests(CtxId, CtxReq, CtxAuditReq2, CmdReq,
+ TopReq, T)
+
+ end;
+do_merge_action_requests(CtxId, CtxReq, CtxAuditReq, CmdReq, TopReq, []) ->
+ #'ActionRequest'{contextId = CtxId,
+ contextRequest = strip_contextRequest(CtxReq, TopReq),
+ contextAttrAuditReq = strip_contextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReq)}.
+
+
+merge_context_attr_audit_request(asn1_NOVALUE, CAs) ->
+ merge_context_attr_audit_request(#'ContextAttrAuditRequest'{}, CAs);
+merge_context_attr_audit_request(CAAR, [H|T]) ->
+ CAAR2 =
+ case H of
+ priorityAudit when CAAR#'ContextAttrAuditRequest'.priority == asn1_NOVALUE ->
+ CAAR#'ContextAttrAuditRequest'{priority = 'NULL'};
+
+ priorityAudit ->
+ Prio = CAAR#'ContextAttrAuditRequest'.priority,
+ exit({only_once, priorityAudit, Prio});
+
+ emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency == asn1_NOVALUE ->
+ CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'};
+
+ emergencyAudit ->
+ Em = CAAR#'ContextAttrAuditRequest'.emergency,
+ exit({only_once, emergencyAudit, Em});
+
+ topologyAudit when CAAR#'ContextAttrAuditRequest'.topology == asn1_NOVALUE ->
+ CAAR#'ContextAttrAuditRequest'{topology = 'NULL'};
+
+ topologyAudit ->
+ Top = CAAR#'ContextAttrAuditRequest'.topology,
+ exit({only_once, topologyAudit, Top})
+
+ end,
+ merge_context_attr_audit_request(CAAR2, T);
+merge_context_attr_audit_request(CAAR, []) ->
+ CAAR.
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(ReplyList) ->
+ CtxReq = #'ContextRequest'{},
+ TopReq = [],
+ CmdList = [],
+ case lists:reverse(ReplyList) of
+ [ED|RL2] when is_record(ED, 'ErrorDescriptor') ->
+ AR = do_merge_action_reply(lists:reverse(RL2),
+ CtxReq, TopReq, CmdList),
+ AR#'ActionReply'{errorDescriptor = ED};
+ _ ->
+ do_merge_action_reply(ReplyList, CtxReq, TopReq, CmdList)
+ end.
+
+do_merge_action_reply([H | T], CtxReq, TopReq, CmdList) ->
+ case H of
+ {command, Cmd} ->
+ do_merge_action_reply(T, CtxReq, TopReq, [Cmd | CmdList]);
+ {context, Ctx} ->
+ case Ctx of
+ {priority, Int} when CtxReq#'ContextRequest'.priority == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{priority = Int},
+ do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+ {emergency, Bool} when CtxReq#'ContextRequest'.emergency == asn1_NOVALUE ->
+ CtxReq2 = CtxReq#'ContextRequest'{emergency = Bool},
+ do_merge_action_reply(T, CtxReq2, TopReq, CmdList);
+ {topology, Desc} ->
+ TopReq2 = Desc ++ TopReq, %% OTP-4088
+ do_merge_action_reply(T, CtxReq, TopReq2, CmdList)
+ end
+ end;
+do_merge_action_reply([], CtxReq, TopReq, CmdList) ->
+ #'ActionReply'{contextReply = strip_contextRequest(CtxReq, TopReq),
+ commandReply = lists:reverse(CmdList)}.
+
+strip_contextRequest(R, TopReq)
+ when ((R#'ContextRequest'.priority =:= asn1_NOVALUE) andalso
+ (R#'ContextRequest'.emergency =:= asn1_NOVALUE) andalso
+ (TopReq =:= [])) ->
+ asn1_NOVALUE;
+strip_contextRequest(R, []) ->
+ R#'ContextRequest'{topologyReq = asn1_NOVALUE};
+strip_contextRequest(R, TopReq) ->
+ R#'ContextRequest'{topologyReq = TopReq}. %% OTP-4088
+
+
+strip_contextAttrAuditRequest(R)
+ when ((R#'ContextAttrAuditRequest'.priority =:= asn1_NOVALUE) andalso
+ (R#'ContextAttrAuditRequest'.emergency =:= asn1_NOVALUE) andalso
+ (R#'ContextAttrAuditRequest'.topology =:= asn1_NOVALUE)) ->
+ asn1_NOVALUE;
+strip_contextAttrAuditRequest(R) ->
+ R.
+
+merge_AmmRequest_descriptors([], Acc) ->
+ lists:reverse(Acc);
+merge_AmmRequest_descriptors([{_, deprecated}|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, Acc);
+merge_AmmRequest_descriptors([Desc|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, [Desc|Acc]).
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor,
+ 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ Groups = [],
+ parse_prop_name(Text, Group, Groups).
+
+parse_prop_name([Char | Rest] = All, Group, Groups) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group, Groups);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group, Groups);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group, Groups)
+ end;
+parse_prop_name([] = All, Group, Groups) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group, Groups).
+
+do_parse_prop_name([Char | Rest], Name, Group, Groups)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ Groups2 = [lists:reverse(Group) | Groups],
+ Group2 = [],
+ parse_prop_value(Rest, Name, Group2, Groups2);
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group, Groups)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group, Groups) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group, Groups);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group, Groups);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], [], Groups) ->
+ lists:reverse(Groups);
+do_parse_prop_name([], [], Group, Groups) ->
+ Group2 = lists:reverse(Group),
+ lists:reverse([Group2 | Groups]);
+do_parse_prop_name([], Name, Group, Groups) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,4}]}).
+-endif.
+parse_prop_value(Chars, Name, Group, Groups) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group, Groups).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group, Groups) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group], Groups);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group, Groups)
+ end;
+do_parse_prop_value([], Name, Value, Group, Groups) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ Groups.
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{do_ensure_prop_groups,1}]}).
+%% -endif.
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+
+% d(F) ->
+% d(F, []).
+
+% d(F, A) ->
+% d(get(dbg), F, A).
+
+% d(true, F, A) ->
+% io:format("~p:" ++ F ++ "~n", [?MODULE|A]);
+% d(_, _, _) ->
+% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v2.yrl b/lib/megaco/src/text/megaco_text_parser_v2.yrl
new file mode 100644
index 0000000000..8152cc4e9b
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v2.yrl
@@ -0,0 +1,1538 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 135.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ authenticationHeader
+ commandReply
+ commandReplyList
+ commandRequest
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextID
+ contextProperty
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlState
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStream
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+
+ %% v2 - start
+ indAudauditReturnParameter
+ indAuddigitMapDescriptor
+ indAudeventBufferDescriptor
+ indAudeventSpec
+ indAudeventSpecParameter
+ %% indAudeventSpecParameterList
+ indAudeventsDescriptor
+ indAudlocalControlDescriptor
+ indAudlocalParm
+ indAudlocalParmList
+ indAudmediaDescriptor
+ indAudmediaParm
+ %% indAudmediaParmList
+ indAudpackagesDescriptor
+ indAudrequestedEvent
+ indAudsignalsDescriptor
+ indAudsignalList
+ %% indAudsignalListParm
+ indAudsignalParm
+ %% indAudsignalRequest
+ indAudstreamDescriptor
+ indAudstreamParm
+ indAudstatisticsDescriptor
+ indAudterminationAudit
+ indAudterminationAuditList
+ indAudterminationStateDescriptor
+ indAudterminationStateParm
+ %% indAudterminationStateParmList
+ optIndAudeventSpecParameter
+ optIndAudsignalParm
+ %% v2 - end
+
+
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor % Deprecated as of Corr 1
+ modemType % Deprecated as of Corr 1
+ modemTypeList % Deprecated as of Corr 1
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ % observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceState
+ serviceStates
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ terminationA
+ terminationAudit
+ terminationB
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyTriple
+ topologyTripleList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ %% 'ContextAttrToken' % OTP-7138: See OTP-7534 below
+ 'ContextAuditToken'
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'EmergencyOffToken'
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'ImmAckRequiredToken'
+ 'InSvcToken'
+ 'InactiveToken'
+ %% 'IndAudTerminationAuditToken' %% testing fix...
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'IsolateToken'
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NotifyCompletionToken'
+ 'NotifyToken'
+ 'Nx64kToken' %% v2
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ 'AndAUDITSelectToken' %% OTP-7534: v3-fix
+ 'BothToken' %% OTP-7534: v3-fix
+ 'ContextAttrToken' %% OTP-7534: v3-fix
+ 'ContextListToken' %% OTP-7534: v3-fix
+ 'DirectionToken' %% OTP-7534: v3-fix
+ %% 'EmergencyOffToken' %% OTP-7534: v3-fix
+ 'EmergencyValueToken' %% OTP-7534: v3-fix
+ 'ExternalToken' %% OTP-7534: v3-fix
+ 'IEPSToken' %% OTP-7534: v3-fix
+ 'IntsigDelayToken' %% OTP-7534: v3-fix
+ 'InternalToken' %% OTP-7534: v3-fix
+ 'IterationToken' %% OTP-7534: v3-fix
+ 'MessageSegmentToken' %% OTP-7534: v3-fix
+ 'NeverNotifyToken' %% OTP-7534: v3-fix
+ 'NotifyImmediateToken' %% OTP-7534: v3-fix
+ 'NotifyRegulatedToken' %% OTP-7534: v3-fix
+ 'OnewayBothToken' %% OTP-7534: v3-fix
+ 'OnewayExternalToken' %% OTP-7534: v3-fix
+ 'OrAUDITselectToken' %% OTP-7534: v3-fix
+ 'RequestIDToken' %% OTP-7534: v3-fix
+ 'ResetEventsDescriptorToken' %% OTP-7534: v3-fix
+ 'SegmentationCompleteToken' %% OTP-7534: v3-fix
+ 'ServiceChangeIncompleteToken' %% OTP-7534: v3-fix
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody : ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck transactionAckList 'RBRKT' : ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT'
+ : #'TransactionPending'{transactionId = ensure_transactionID('$3') } .
+
+%% OTP-4359: We have the first two rule's in order to be able
+%% to handle chapter 8.1.1 in RFC3525
+transactionRequest -> 'TransToken'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL'
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT'
+ : #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList : ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestItem actionRequestItems 'RBRKT'
+ : merge_action_requests('$3', ['$5' | '$6']) .
+
+actionRequestItems -> 'COMMA' actionRequestItem actionRequestItems : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+actionRequestItem -> contextProperty : '$1' .
+actionRequestItem -> contextAudit : '$1' .
+actionRequestItem -> commandRequest : '$1' .
+
+%% at-most-once
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+contextProperty -> 'EmergencyOffToken' : {emergency, false}.
+
+contextAudit -> 'ContextAuditToken'
+ 'LBRKT' contextAuditProperty contextAuditProperties 'RBRKT'
+ : {contextAudit, ['$3' | '$4']} .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty contextAuditProperties
+ : ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once .
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID
+ 'LBRKT'
+ optImmAckRequired transactionReplyBody
+ 'RBRKT'
+ : #'TransactionReply'{transactionId = '$3',
+ immAckRequired = '$5',
+ transactionResult = '$6'} .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor : {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList : {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReply commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+commandReply -> serviceChangeReply : {command, '$1'} .
+commandReply -> auditReply : {command, '$1'} .
+commandReply -> ammsReply : {command, '$1'} .
+commandReply -> notifyReply : {command, '$1'} .
+commandReply -> contextProperty : {context, '$1'} .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ ['$2'] .
+commandReplyList -> 'COMMA' commandReply commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' terminationID ammRequestBody :
+ Descs = merge_AmmRequest_descriptors('$4', []),
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = ['$3'],
+ descriptors = Descs}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, deprecated}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' terminationID ammsReplyBody
+ : {'$1', #'AmmsReply'{terminationID = ['$3'],
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL' terminationID optAuditDescriptor
+ : make_commandRequest({subtractReq, '$1'},
+ #'SubtractRequest'{terminationID = ['$3'],
+ auditDescriptor = '$4'}) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+auditRequest -> 'AuditCapToken' 'EQUAL'
+ terminationID optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ #'AuditRequest'{terminationID = '$3',
+ auditDescriptor = '$4'}) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit
+ : {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther
+ : {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther
+ : {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList : {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' : {contextAuditResult, '$2'} .
+
+auditOther -> terminationID :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = []}} .
+auditOther -> terminationID 'LBRKT' terminationAudit 'RBRKT' :
+ {auditResult,
+ #'AuditResult'{terminationID = '$1',
+ terminationAuditResult = '$3'}} .
+
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor.
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} .
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT' :
+ merge_auditDescriptor('$3') .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken.
+auditItem -> 'EventBufferToken' : eventBufferToken.
+auditItem -> 'EventsToken' : eventsToken .
+auditItem -> indAudterminationAudit : {terminationAudit, '$1'} . % v2
+%%
+%% IGv11 - end
+
+
+%% v2 - start
+%%
+indAudterminationAudit -> indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$1' | '$2'] .
+
+% testing fix...
+% indAudterminationAudit -> 'IndAudTerminationAuditToken'
+% indAudauditReturnParameter
+% indAudterminationAuditList
+% : ['$2' | '$3'] .
+
+indAudterminationAuditList -> 'COMMA' indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$2' | '$3'] .
+indAudterminationAuditList -> '$empty' : [] .
+
+indAudauditReturnParameter -> indAudmediaDescriptor
+ : {indAudMediaDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventsDescriptor
+ : {indAudEventsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudsignalsDescriptor
+ : {indAudSignalsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAuddigitMapDescriptor
+ : {indAudDigitMapDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventBufferDescriptor
+ : {indAudEventBufferDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudstatisticsDescriptor
+ : {indAudStatisticsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudpackagesDescriptor
+ : {indAudPackagesDescriptor, '$1'} .
+
+
+indAudmediaDescriptor -> 'MediaToken' 'LBRKT'
+ indAudmediaParm 'RBRKT'
+ : merge_indAudMediaDescriptor('$3') .
+
+%% at-most-once per item
+%% and either streamParm or streamDescriptor but not both
+%% <rambling>
+%% This is solved in another way in text than in binary :(
+%% Instead of having a list of indAudmediaParm we put this
+%% stuff in the indAudterminationAuditList with several
+%% indAudmediaDescriptor's.
+%% </rambling>
+%%
+
+indAudmediaParm -> indAudstreamParm : {streamParm, '$1'} .
+indAudmediaParm -> indAudstreamDescriptor : {streamDescr, '$1'} .
+indAudmediaParm -> indAudterminationStateDescriptor : {termStateDescr, '$1'} .
+
+%% at-most-once
+indAudstreamParm -> indAudlocalControlDescriptor
+ : #'IndAudStreamParms'{localControlDescriptor = '$1'} .
+
+indAudstreamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' indAudstreamParm 'RBRKT'
+ : #'IndAudStreamDescriptor'{streamID = '$3',
+ streamParms = '$5'} .
+
+
+indAudlocalControlDescriptor -> 'LocalControlToken'
+ 'LBRKT' indAudlocalParm indAudlocalParmList 'RBRKT' :
+ merge_indAudLocalControlDescriptor(['$3'| '$4']) .
+
+indAudlocalParmList -> 'COMMA' indAudlocalParm indAudlocalParmList : ['$2'| '$3'] .
+indAudlocalParmList -> '$empty' : [] .
+
+%% at-most-once per item
+%%
+indAudlocalParm -> safeToken : ensure_indAudLocalParm('$1') .
+
+indAudterminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' indAudterminationStateParm 'RBRKT'
+ :
+ merge_indAudTerminationStateDescriptor('$3') .
+
+%% at-most-once per item
+%%
+
+indAudterminationStateParm -> safeToken :
+ ensure_indAudTerminationStateParm('$1') .
+
+indAudeventBufferDescriptor -> 'EventBufferToken'
+ 'LBRKT' indAudeventSpec 'RBRKT' : '$3' .
+
+indAudeventSpec -> pkgdName optIndAudeventSpecParameter
+ : merge_indAudEventBufferDescriptor('$1','$2') .
+
+optIndAudeventSpecParameter -> 'LBRKT' indAudeventSpecParameter 'RBRKT'
+ : '$2' .
+optIndAudeventSpecParameter -> '$empty' : asn1_NOVALUE .
+
+
+indAudeventSpecParameter -> eventStream : {streamID, '$1'} .
+indAudeventSpecParameter -> eventParameterName : {eventParameterName, '$1'} .
+
+indAudeventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' indAudrequestedEvent 'RBRKT'
+ : #'IndAudEventsDescriptor'{requestID = '$3',
+ pkgdName = '$5'} .
+
+indAudrequestedEvent -> pkgdName : '$1' .
+
+
+indAudsignalsDescriptor -> 'SignalsToken' optIndAudsignalParm : '$2' .
+
+
+optIndAudsignalParm -> 'LBRKT' 'RBRKT' : asn1_NOVALUE .
+optIndAudsignalParm -> 'LBRKT' indAudsignalParm 'RBRKT' : '$2' .
+
+indAudsignalParm -> indAudsignalList : {seqSigList, '$1'} .
+indAudsignalParm -> signalRequest : {signal, ensure_indAudSignal('$1')} .
+
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm 'RBRKT' :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3'),
+ signalList =
+ ensure_indAudSignalListParm('$5')} .
+
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+indAuddigitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_IADMD('$1') .
+
+indAudstatisticsDescriptor -> 'StatsToken' 'LBRKT' pkgdName 'RBRKT' :
+ #'IndAudStatisticsDescriptor'{statName = '$3'} .
+
+indAudpackagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem 'RBRKT'
+ : merge_indAudPackagesDescriptor('$3') .
+
+eventStream -> 'StreamToken' 'EQUAL' streamID : '$3' .
+
+
+%%
+%% v2 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' terminationID
+ 'LBRKT' notifyRequestBody 'RBRKT'
+ : make_commandRequest({notifyReq, '$1'},
+ setelement(#'NotifyRequest'.terminationID, '$5', ['$3'])) .
+
+notifyRequestBody -> observedEventsDescriptor
+ : #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor
+ : #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' terminationID notifyReplyBody
+ : {notifyReply,
+ #'NotifyReply'{terminationID = ['$3'],
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' terminationID
+ 'LBRKT' serviceChangeDescriptor 'RBRKT'
+ : make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = ['$3'],
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' terminationID serviceChangeReplyBody
+ : {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = ['$3'],
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT'
+ : {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT'
+ : {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' : {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT' errorText 'RBRKT'
+ : #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+%% '-' is used for NULL context
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+%% terminationIDList -> LBRKT terminationID *(COMMA terminationID) RBRKT .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT'
+ : ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat
+ : ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-onc .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue :
+ setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue :
+ '$2' .
+
+parmValue -> 'NEQUAL' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT' :
+ #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT' :
+ #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT' :
+ #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value :
+ #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec eventSpecList 'RBRKT'
+ : ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceState : '$3' .
+
+serviceState -> 'TestToken' : test .
+serviceState -> 'OutOfSvcToken' : outOfSvc .
+serviceState -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlState : '$3' .
+
+eventBufferControlState -> 'OffToken' : off .
+eventBufferControlState -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList :
+ #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' : #'RequestedEvent'{evParList = []} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT'
+ : {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT'
+ : {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents : ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody
+ : setelement(#'SecondRequestedEvent'.pkgdName, '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter secondEventParameters 'RBRKT'
+ : merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' : #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters : ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' :
+ ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' : [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther
+%% / notifyCompletion / KeepActiveToken
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason) RBRKT
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken
+%% / InterruptByNewSignalsDescrToken
+%% / OtherReasonToken )
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID : {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType : {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken : {duration, ensure_uint16('$3')} .
+sigParameter -> safeToken parmValue : {other, ensure_NAME('$1'), '$2'}.
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT'
+ : {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms :
+ ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+
+observedEvent -> timeStamp optSep 'COLON' optSep pkgdName observedEventBody :
+ merge_observed_event('$6', '$5', '$1') .
+observedEvent -> optSep pkgdName observedEventBody :
+ merge_observed_event('$3', '$2', asn1_NOVALUE) .
+
+observedEventBody -> 'LBRKT' observedEventParameter
+ observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+%% Deprecated as of Corr 1
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms .
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms.
+modemTypeList -> 'COMMA' modemType modemTypeList.
+modemTypeList -> '$empty'.
+modemType -> safeToken.
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParms 'RBRKT' :
+ ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> 'COMMA' propertyParm propertyParms : ['$2' | '$3'] .
+propertyParms -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_DMD('$1') .
+
+%% each parameter at-most-once, except auditItem
+%% at most one of either serviceChangeAddress or serviceChangeMgcId but
+%% not both. serviceChangeMethod and serviceChangeReason are REQUIRED
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp, '$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+serviceChangeParm -> auditItem : {audit_item, '$1'} . % v2
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken : ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber :
+ {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'} .
+servChgReplyParm -> timeStamp : {time_stamp,'$1'} .
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value
+ : #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT' topologyTriple
+ topologyTripleList 'RBRKT' : ['$3' | '$4'] .
+
+terminationA -> terminationID : '$1' .
+
+terminationB -> terminationID : '$1' .
+
+topologyTriple -> terminationA 'COMMA' terminationB 'COMMA'
+ topologyDirection 'COMMA' eventStream :
+ #'TopologyRequest'{terminationFrom = '$1',
+ terminationTo = '$3',
+ topologyDirection = '$5',
+ streamID = '$7'} .
+topologyTriple -> terminationA 'COMMA' terminationB 'COMMA'
+ topologyDirection :
+ #'TopologyRequest'{terminationFrom = '$1',
+ terminationTo = '$3',
+ topologyDirection = '$5'} .
+
+topologyTripleList -> '$empty' : [] .
+topologyTripleList -> 'COMMA' topologyTriple topologyTripleList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : bothway .
+topologyDirection -> 'IsolateToken' : isolate .
+topologyDirection -> 'OnewayToken' : oneway .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' :
+ ensure_value('$1') .
+value -> safeToken :
+ ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% safeToken2 -> 'ContextAttrToken' : '$1' .
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% v2-safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+safeToken2 -> 'EmergencyToken' : '$1' .
+safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% v2-safeToken2 -> 'EventBufferToken' : '$1' .
+%% v2-safeToken2 -> 'EventsToken' : '$1' .
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% v2-safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+safeToken2 -> 'ModeToken' : '$1' .
+safeToken2 -> 'ModifyToken' : '$1' .
+%% v2-safeToken2 -> 'ModemToken' : '$1' .
+safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% v2-safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64kToken' : '$1' .
+%% v2-safeToken2 -> 'ObservedEventsToken' : '$1' .
+safeToken2 -> 'OnewayToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% v2-safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+safeToken2 -> 'ReservedGroupToken' : '$1' .
+safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% v2-safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% v2-safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+safeToken2 -> 'TimeStampToken' : '$1' .
+safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+%% <OTP-7534>
+safeToken2 -> 'AndAUDITSelectToken' : '$1' .
+safeToken2 -> 'BothToken' : '$1' .
+safeToken2 -> 'ContextAttrToken' : '$1' .
+safeToken2 -> 'ContextListToken' : '$1' .
+safeToken2 -> 'DirectionToken' : '$1' .
+%% safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'EmergencyValueToken' : '$1' .
+safeToken2 -> 'ExternalToken' : '$1' .
+safeToken2 -> 'IEPSToken' : '$1' .
+safeToken2 -> 'InternalToken' : '$1' .
+safeToken2 -> 'IntsigDelayToken' : '$1' .
+safeToken2 -> 'IterationToken' : '$1' .
+safeToken2 -> 'MessageSegmentToken' : '$1' .
+safeToken2 -> 'NeverNotifyToken' : '$1' .
+safeToken2 -> 'NotifyImmediateToken' : '$1' .
+safeToken2 -> 'NotifyRegulatedToken' : '$1' .
+safeToken2 -> 'OnewayBothToken' : '$1' .
+safeToken2 -> 'OnewayExternalToken' : '$1' .
+safeToken2 -> 'OrAUDITselectToken' : '$1' .
+safeToken2 -> 'RequestIDToken' : '$1' .
+safeToken2 -> 'ResetEventsDescriptorToken' : '$1' .
+safeToken2 -> 'SegmentationCompleteToken' : '$1' .
+safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' .
+%% </OTP-7534>
+
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_v2.hrl").
+
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v3.hrl b/lib/megaco/src/text/megaco_text_parser_v3.hrl
new file mode 100644
index 0000000000..9f68fb6127
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v3.hrl
@@ -0,0 +1,2002 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose : Define semantic text parser actions
+%%----------------------------------------------------------------------
+
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v3.hrl").
+-include("megaco_text_tokens.hrl").
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_safe_token,1}]}).
+-endif.
+make_safe_token(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ {safeToken, Line, Text}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_value,1}]}).
+-endif.
+ensure_value(Token) ->
+ case Token of
+ {safeToken, _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ {'QuotedChars', _Line, Text} when is_list(Text) ->
+ Text; % We really should ensure length
+ Text when is_list(Text) ->
+ Text % We really should ensure length
+ end.
+
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_NAME,1}]}).
+-endif.
+ensure_NAME(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure length and chars
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_requestID,1}]}).
+-endif.
+ensure_requestID(Token) ->
+ case Token of
+ {safeToken, _Line, "*"} ->
+ ?megaco_all_request_id;
+ _ ->
+ ensure_uint32(Token)
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_streamID,1}]}).
+-endif.
+ensure_streamID(StreamId) ->
+ ensure_uint16(StreamId).
+
+ensure_auth_header(SpiToken, SnToken, AdToken) ->
+ Spi = ensure_hex(SpiToken, 8, 8),
+ Sn = ensure_hex(SnToken, 8, 8),
+ Ad = ensure_hex(AdToken, 24, 64),
+ #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.
+
+%% ContextID = (UINT32 / "*" / "-" / "$")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_contextID,1}]}).
+-endif.
+ensure_contextID(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ "*" -> ?megaco_all_context_id;
+ "-" -> ?megaco_null_context_id;
+ "\$" -> ?megaco_choose_context_id;
+ Int ->
+ CID = ensure_uint32(Int),
+ if
+ (CID =/= 0) andalso
+ (CID =/= 16#FFFFFFFE) andalso
+ (CID =/= 16#FFFFFFFF) ->
+ CID;
+ true ->
+ return_error(Line, {bad_ContextID, CID})
+ end
+ end.
+
+ensure_domainAddress([{_T, _L, _A} = Addr0], Port) ->
+ Addr = ensure_ip4addr(Addr0),
+ {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress([colon,colon], Port) ->
+ Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};
+ensure_domainAddress(Addr0, Port) ->
+ Addr = ensure_ip6addr(Addr0),
+ {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.
+
+
+ensure_ip4addr(Token) ->
+ {_TokenTag, Line, Addr} = Token,
+ case split_ip4addr_text(Addr, []) of
+ [T1, T2, T3, T4] ->
+ %% We optimize by sending only the text part (Addr) of
+ %% the token to the function.
+ %% If something is wrong, then we do not get a proper
+ %% position and therefor we catch and sendissue the
+ %% the error again (with the proper line number).
+ case (catch [
+ ensure_uint(T1, 0, 255),
+ ensure_uint(T2, 0, 255),
+ ensure_uint(T3, 0, 255),
+ ensure_uint(T4, 0, 255)
+ ]) of
+ A when is_list(A) ->
+ A;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end;
+ _ ->
+ return_error(Line, {bad_IP4address, Addr})
+ end.
+
+split_ip4addr_text([], Acc) ->
+ [ lists:reverse(Acc) ];
+split_ip4addr_text([$. | Rest], Acc) ->
+ [ lists:reverse(Acc) | split_ip4addr_text(Rest, []) ];
+split_ip4addr_text([H | T], Acc) ->
+ split_ip4addr_text(T, [H | Acc]).
+
+
+ensure_ip6addr([colon,colon|T]) ->
+ [H1|T1] = lists:reverse(T),
+ case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of
+ {true, A} when length(A) =:= 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ lists:duplicate(16 - length(B), 0) ++ B;
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ensure_ip6addr(L) ->
+ case lists:reverse(L) of
+ [colon, colon| T] ->
+ case do_ensure_ip6addr(T, true, [], 1) of
+ {true, A} when length(A) =:= 16 ->
+ A;
+ {true, B} when length(B) < 16 ->
+ B ++ lists:duplicate(16 - length(B), 0);
+ {true, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}})
+ end;
+ [H|L1] -> % A (last element) could be an ip4 address
+ case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of
+ {false, A} when length(A) =:= 16 ->
+ A;
+ %% allow a pad even if the address is full (i.e. 16)
+ {true, B} when length(B) =< 17 ->
+ do_ensure_ip6addr_padding(B, 0);
+ {Pad, C} ->
+ throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}})
+ end
+
+ end.
+
+
+do_ensure_ip6addr([], Pad, Acc, _) ->
+ {Pad, lists:flatten(Acc)};
+do_ensure_ip6addr([colon,colon|T], false, Acc, Line) ->
+ do_ensure_ip6addr(T, true, [pad|Acc], Line);
+do_ensure_ip6addr([colon,colon|T], true, Acc, Line) ->
+ return_error(Line, {bad_mid_duplicate_padding, T, Acc});
+do_ensure_ip6addr([colon|T], Pad, Acc, Line) ->
+ do_ensure_ip6addr(T, Pad, Acc, Line);
+do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) ->
+ do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).
+
+do_ensure_ip6addr_padding([], _) ->
+ [];
+do_ensure_ip6addr_padding([pad|T], N) ->
+ lists:duplicate(16 - (N + length(T)), 0) ++ T;
+do_ensure_ip6addr_padding([H|T], N) ->
+ [H|do_ensure_ip6addr_padding(T, N+1)].
+
+ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) ->
+ case string:tokens(Addr, [$.]) of
+ [T1, T2, T3, T4] ->
+ A1 = ensure_uint({TokenTag, Line, T1}, 0, 255),
+ A2 = ensure_uint({TokenTag, Line, T2}, 0, 255),
+ A3 = ensure_uint({TokenTag, Line, T3}, 0, 255),
+ A4 = ensure_uint({TokenTag, Line, T4}, 0, 255),
+ [A1, A2, A3, A4];
+ _ ->
+ ensure_hex4(V)
+ %% %% BMK BMK BMK
+ %% %% Here we should test for hexseq
+ %% return_error(Line, {bad_IP4address, Addr})
+ end.
+
+ensure_hex4({_TokenTag, Line, Hex4})
+ when (length(Hex4) =< 4) andalso (length(Hex4) > 0) ->
+ case (catch do_ensure_hex4(Hex4)) of
+ IL when is_list(IL) andalso (length(IL) =:= 2) ->
+ IL;
+ Error ->
+ return_error(Line, {bad_hex4, Hex4, Error})
+ end.
+
+do_ensure_hex4([_H1, _H2, _H3, _H4] = H) ->
+ hex_to_int(H, []);
+do_ensure_hex4([H2, H3, H4]) ->
+ hex_to_int([$0, H2, H3, H4], []);
+do_ensure_hex4([H3, H4]) ->
+ hex_to_int([$0, $0, H3, H4], []);
+do_ensure_hex4([H4]) ->
+ hex_to_int([$0, $0, $0, H4], []).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_domainName,2}]}).
+-endif.
+ensure_domainName(Token, Port) ->
+ {_TokenTag, _Line, Name} = Token,
+ %% BUGBUG: we should really validate name
+ {domainName, #'DomainName'{name = Name, portNumber = Port}}.
+
+%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_extensionParameter,1}]}).
+-endif.
+ensure_extensionParameter(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case Text of
+ [X, S | _Chars] ->
+ if
+ (X =/= $X) andalso (X =/= $x) andalso
+ (S =/= $+) andalso (S =/= $-) ->
+ return_error(Line, {bad_extension_parameter, Text});
+ true ->
+ {extension_parameter, Text}
+ end;
+ _ ->
+ return_error(Line, {bad_extension_parameter, Text})
+ end.
+
+ensure_message(MegacopToken, MID, Body) ->
+%% #'ServiceChangeProfile'{profileName = Name,
+%% version = Version} =
+%% ensure_profile(MegacopToken),
+%% case Name of
+%% "megaco" ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body};
+%% [$!] ->
+%% #'Message'{version = Version, mId = MID, messageBody = Body}
+%% end.
+ {_TokenTag, Line, Text} = MegacopToken,
+ case split_Megacop(Text, []) of
+ {Name, Version} ->
+ Version2 = ensure_version(Version),
+ case Name of
+ "megaco" ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body};
+ [$!] ->
+ #'Message'{version = Version2,
+ mId = MID,
+ messageBody = Body}
+ end;
+ _ ->
+ return_error(Line, {bad_name_or_version, Text})
+ end.
+
+split_Megacop([], _) ->
+ error;
+split_Megacop([$/ | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_Megacop([H | T], Acc) ->
+ split_Megacop(T, [H | Acc]).
+
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% and since this functon is only used when creating
+%% a ModemDescriptor, iit is removed.
+%% modemType = (V32bisToken / V22bisToken / V18Token /
+%% V22Token / V32Token / V34Token / V90Token /
+%% V91Token / SynchISDNToken / extensionParameter)
+%% ensure_modemType({_TokenTag, _Line, Text} = Token) ->
+%% case Text of
+%% "v32b" -> v32bis;
+%% "v22b" -> v22bis;
+%% "v18" -> v18;
+%% "v22" -> v22;
+%% "v32" -> v32;
+%% "v34" -> v34;
+%% "v90" -> v90;
+%% "v91" -> v91;
+%% "synchisdn" -> synchISDN;
+%% "sn" -> synchISDN;
+%% [$x | _] -> ensure_extensionParameter(Token)
+%% end.
+
+%% An mtp address is five octets long
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_mtpAddress,1}]}).
+-endif.
+ensure_mtpAddress(Token) ->
+ {_TokenTag, _Line, Addr} = Token,
+ %% BUGBUG: validate address
+ {mtpAddress, Addr}.
+
+%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_muxType,1}]}).
+-endif.
+ensure_muxType(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ case Text of
+ "h221" -> h221;
+ "h223" -> h223;
+ "h226" -> h226;
+ "v76" -> v76;
+ "nx64k" -> nx64k; % v2
+ [$x | _] -> ensure_extensionParameter(Token)
+ end.
+
+%% packagesItem = NAME "-" UINT16
+%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_packagesItem,1}]}).
+-endif.
+ensure_packagesItem(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case split_packagesItem(Text, []) of
+ {Name, Version} ->
+ %% As we don't ensure length of the names, there is no point
+ %% in doing the ensure_NAME thing...
+ #'PackagesItem'{packageName = Name,
+ packageVersion = ensure_uint(Version, 0, 99)};
+ _ ->
+ return_error(Line, {bad_PackagesItem, Text})
+ end.
+
+split_packagesItem([], _) ->
+ error;
+split_packagesItem([$- | Version], Acc) ->
+ {lists:reverse(Acc), Version};
+split_packagesItem([H|T], Acc) ->
+ split_packagesItem(T, [H|Acc]).
+
+
+%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )
+%% PackageName = NAME
+%% ItemID = NAME
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pkgdName,1}]}).
+-endif.
+ensure_pkgdName(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case ensure_pkgdName(Text, []) of
+ ok ->
+ %% As we don't really do any checks on the strings
+ %% (length or content) there is really no point in
+ %% "ensuring" the name and item part of the
+ %% package name
+ %% ensure_name_or_star(Name),
+ %% ensure_name_or_star(Item),
+ Text;
+ _ ->
+ return_error(Line, {bad_pkgdName, Text})
+ end.
+
+ensure_pkgdName([], _) ->
+ error;
+ensure_pkgdName([$/ | T], Acc)
+ when ((length(T) > 0) andalso (length(Acc) > 0)) ->
+ ok;
+ensure_pkgdName([H | T], Acc) ->
+ ensure_pkgdName(T, [H | Acc]).
+
+
+%% -compile({inline,[{ensure_name_or_star,1}]}).
+%% ensure_name_or_star(Val) ->
+%% %% case Token of
+%% %% {_, _, Name} when Name =:= "*" ->
+%% %% Name;
+%% %% _ ->
+%% %% ensure_NAME(Token)
+%% %% end.
+%% if
+%% Val =:= "*" ->
+%% Val;
+%% true ->
+%% %% as we don't really validate the text part of the token(s),
+%% %% we can just return the value assuming it to be correct...
+%% Val
+%% end.
+
+
+%% v2 - start
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudMediaDescriptor,1}]}).
+-endif.
+merge_indAudMediaDescriptor(Vals) ->
+ merge_indAudMediaDescriptor(Vals, #'IndAudMediaDescriptor'{}).
+
+merge_indAudMediaDescriptor(
+ [], #'IndAudMediaDescriptor'{streams = Streams1} = D) ->
+ Streams2 =
+ case Streams1 of
+ {multiStream, Descs} ->
+ {multiStream, lists:reverse(Descs)};
+ _ ->
+ Streams1
+ end,
+ D#'IndAudMediaDescriptor'{streams = Streams2};
+merge_indAudMediaDescriptor([{termStateDescr, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.termStateDescr =:= asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{termStateDescr = Val},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamParm, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.streams =:= asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{streams = {oneStream, Val}},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamDescr, Val}|Vals], D)
+ when D#'IndAudMediaDescriptor'.streams =:= asn1_NOVALUE ->
+ D2 = #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{streamDescr, Val}|Vals],
+ #'IndAudMediaDescriptor'{streams = Streams1} = D1) ->
+ Streams2 =
+ case Streams1 of
+ {multiStream, Descs} ->
+ {multiStream, [Val|Descs]};
+ _ ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamDescr,
+ Val, Streams1})
+ end,
+ D2 = D1#'IndAudMediaDescriptor'{streams = Streams2},
+ merge_indAudMediaDescriptor(Vals, D2);
+merge_indAudMediaDescriptor([{Tag, Val}|_], D) ->
+ case Tag of
+ termStateDescr ->
+ return_error(0, {bad_IndAudMediaDescriptor_termStateDescr,
+ Val, D#'IndAudMediaDescriptor'.termStateDescr});
+ streamParm ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamParm,
+ Val, D#'IndAudMediaDescriptor'.streams});
+ streamDescr ->
+ return_error(0, {bad_IndAudMediaDescriptor_streamDescr,
+ Val, D#'IndAudMediaDescriptor'.streams});
+ _ ->
+ return_error(0, {bad_IndAudMediaDescriptor_tag, Tag, Val})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudLocalControlDescriptor,1}]}).
+-endif.
+merge_indAudLocalControlDescriptor(Parms) ->
+ merge_indAudLocalControlDescriptor(Parms,
+ #'IndAudLocalControlDescriptor'{},
+ asn1_NOVALUE).
+
+merge_indAudLocalControlDescriptor([modeToken | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode =:= asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.streamModeSel =:= asn1_NOVALUE) ->
+ D2 = D#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([modeToken | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode =:= asn1_NOVALUE) ->
+ merge_indAudLocalControlDescriptor(Parms, D, PP);
+
+merge_indAudLocalControlDescriptor([{mode, Val} | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamMode =:= asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.streamModeSel =:= asn1_NOVALUE) ->
+ D2 =
+ case Val of
+ {equal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamModeSel = Val2};
+ {inequal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamModeSel = Val2}
+ end,
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([{mode, Val} | Parms], D, PP)
+ when (D#'IndAudLocalControlDescriptor'.streamModeSel =:= asn1_NOVALUE) ->
+ D2 =
+ case Val of
+ {equal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ streamModeSel = Val2};
+ {inequal, Val2} ->
+ D#'IndAudLocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ streamModeSel = Val2}
+ end,
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([reservedGroupToken | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+merge_indAudLocalControlDescriptor([reservedValueToken | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP);
+
+%% This is really wierd in the standard, so at this point this is the
+%% best I can do... BUGBUG BUGBUG BUGBUG
+%%
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, asn1_NOVALUE) ->
+ PP = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D, PP);
+
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, PP)
+ when D#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE ->
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP]},
+ PP2 = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP2);
+
+merge_indAudLocalControlDescriptor([{name, Val} | Parms], D, PP) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP|PPs]},
+ PP2 = #'IndAudPropertyParm'{name = Val},
+ merge_indAudLocalControlDescriptor(Parms, D2, PP2);
+
+%% BUGBUG BUGBUG I cannot construct a proper IndAudPropertyParm with
+%% just the prop (the mandatory name part is missing), so for now I
+%% assume that it this has been used, then the name part
+%% (pkgdName) must precide it?
+merge_indAudLocalControlDescriptor([{prop, Val} | Parms], D, PP)
+ when (PP =/= asn1_NOVALUE) andalso
+ (D#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE) ->
+ PP2 = PP#'IndAudPropertyParm'{propertyParms = Val},
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP2]},
+ merge_indAudLocalControlDescriptor(Parms, D2, asn1_NOVALUE);
+
+merge_indAudLocalControlDescriptor([{prop, Val} | Parms], D, PP)
+ when (PP =/= asn1_NOVALUE) andalso
+ is_list(D#'IndAudLocalControlDescriptor'.propertyParms) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PP2 = PP#'IndAudPropertyParm'{propertyParms = Val},
+ D2 = D#'IndAudLocalControlDescriptor'{propertyParms = [PP2|PPs]},
+ merge_indAudLocalControlDescriptor(Parms, D2, asn1_NOVALUE);
+
+merge_indAudLocalControlDescriptor([H | _T], _D, _PP) ->
+ return_error(0, {bad_indAudLocalControlDescriptor_parm, H});
+
+merge_indAudLocalControlDescriptor([], D, asn1_NOVALUE)
+ when D#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE ->
+ D;
+merge_indAudLocalControlDescriptor([], D, asn1_NOVALUE) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PropParms2 = lists:reverse(PPs),
+ D#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};
+merge_indAudLocalControlDescriptor([], D, PP)
+ when D#'IndAudLocalControlDescriptor'.propertyParms =:= asn1_NOVALUE ->
+ D#'IndAudLocalControlDescriptor'{propertyParms = [PP]};
+merge_indAudLocalControlDescriptor([], D, PP) ->
+ PPs = D#'IndAudLocalControlDescriptor'.propertyParms,
+ PPs2 = lists:reverse([PP|PPs]),
+ D#'IndAudLocalControlDescriptor'{propertyParms = PPs2}.
+
+
+merge_indAudTerminationStateDescriptor({name, Val}) ->
+ PropParm = #'IndAudPropertyParm'{name = Val},
+ #'IndAudTerminationStateDescriptor'{propertyParms = [PropParm]};
+%% BUGBUG BUGBUG BUGBUG
+merge_indAudTerminationStateDescriptor({prop, Val}) ->
+ exit({incomplete_propertyParm_in_indAudTerminationStateDescriptor, Val});
+merge_indAudTerminationStateDescriptor(serviceStatesToken) ->
+ #'IndAudTerminationStateDescriptor'{serviceState = 'NULL'};
+merge_indAudTerminationStateDescriptor({serviceStates, {equal, Val}}) ->
+ #'IndAudTerminationStateDescriptor'{serviceStateSel = Val};
+merge_indAudTerminationStateDescriptor({serviceStates, {inequal, Val}}) ->
+ #'IndAudTerminationStateDescriptor'{serviceStateSel = Val};
+merge_indAudTerminationStateDescriptor(bufferToken) ->
+ #'IndAudTerminationStateDescriptor'{eventBufferControl = 'NULL'}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudEventBufferDescriptor,2}]}).
+-endif.
+merge_indAudEventBufferDescriptor(EventName, SpecParams) ->
+ IAEBD = #'IndAudEventBufferDescriptor'{eventName = EventName},
+ do_merge_indAudEventBufferDescriptor(SpecParams, IAEBD).
+
+do_merge_indAudEventBufferDescriptor(asn1_NOVALUE, IAEBD) ->
+ IAEBD;
+do_merge_indAudEventBufferDescriptor({streamID, StreamID}, IAEBD) ->
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = StreamID};
+do_merge_indAudEventBufferDescriptor({eventParameterName, _Name} = EPN,
+ IAEBD) ->
+ %% BUGBUG BUGBUG BUGBUG
+ %% This is an ugly hack to allow the eventParamName which only
+ %% exists in the text encoding...
+ IAEBD#'IndAudEventBufferDescriptor'{streamID = EPN}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudSignalListParm,1}]}).
+-endif.
+ensure_indAudSignalListParm(SIG) ->
+ if
+ is_record(SIG, 'Signal') ->
+ ensure_indAudSignal(SIG);
+ true ->
+ return_error(0, {bad_Signal, SIG})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_indAudSignal,1}]}).
+-endif.
+ensure_indAudSignal(Sig) ->
+ #'Signal'{signalName = SignalName,
+ streamID = SID,
+ sigType = asn1_NOVALUE,
+ duration = asn1_NOVALUE,
+ notifyCompletion = asn1_NOVALUE,
+ keepActive = asn1_NOVALUE,
+ sigParList = [],
+ requestID = RID} = Sig,
+ #'IndAudSignal'{signalName = SignalName,
+ streamID = SID,
+ signalRequestID = RID}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_IADMD,1}]}).
+-endif.
+ensure_IADMD(Token) ->
+ {_TokenTag, _Line, DMD} = Token,
+ #'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE} = DMD,
+ #'IndAudDigitMapDescriptor'{digitMapName = Name}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_indAudPackagesDescriptor,1}]}).
+-endif.
+merge_indAudPackagesDescriptor(Pkgs) ->
+ #'PackagesItem'{packageName = N,
+ packageVersion = V} = Pkgs,
+ #'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V}.
+
+
+%% ensure_indAudTerminationStateParm(Token) ->
+%% case Token of
+%% {safeToken, _Line, "servicestates"} -> serviceStatesToken;
+%% {safeToken, _Line, "si"} -> serviceStatesToken;
+%% {safeToken, _Line, "buffer"} -> bufferToken;
+%% {safeToken, _Line, "bf"} -> bufferToken;
+%% PkgdName -> {pkgdName,
+%% ensure_pkgdName(PkgdName)}
+%% end.
+
+
+%% Types modified by v2:
+
+merge_auditDescriptor([]) ->
+ #'AuditDescriptor'{};
+merge_auditDescriptor(Tokens) when is_list(Tokens) ->
+ case lists:keysearch(terminationAudit, 1, Tokens) of
+ {value, {terminationAudit, TA}} ->
+ case lists:keydelete(terminationAudit, 1, Tokens) of
+ [] ->
+ #'AuditDescriptor'{auditPropertyToken = TA};
+ AuditTokens ->
+ #'AuditDescriptor'{auditToken = AuditTokens,
+ auditPropertyToken = TA}
+ end;
+ false ->
+ #'AuditDescriptor'{auditToken = Tokens}
+ end;
+merge_auditDescriptor(_) ->
+ #'AuditDescriptor'{}.
+
+
+%% v2 - end
+
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeParm,1}]}).
+-endif.
+merge_ServiceChangeParm(Parms) ->
+ Required = [serviceChangeReason, serviceChangeMethod],
+ merge_ServiceChangeParm(Parms, #'ServiceChangeParm'{}, Required).
+
+merge_ServiceChangeParm([], SCP, []) ->
+ SCP;
+
+merge_ServiceChangeParm([], _SCP, Required) ->
+ exit({missing_required_serviceChangeParm, Required});
+
+merge_ServiceChangeParm([{address, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{address, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE ->
+ MgcId = SCP0#'ServiceChangeParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, MgcId});
+
+merge_ServiceChangeParm([{mgc_id, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE) andalso
+ (SCP0#'ServiceChangeParm'.serviceChangeAddress =:= asn1_NOVALUE) ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{mgc_id, Val}|_Parms], SCP0, _Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeMgcId =:= asn1_NOVALUE ->
+ Addr = SCP0#'ServiceChangeParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_serviceChangeParm, Val, Addr});
+
+merge_ServiceChangeParm([{profile, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeProfile =:= asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{version, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeVersion =:= asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{reason, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeReason =:= undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeReason = Val},
+ Req = lists:delete(serviceChangeReason, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{delay, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeDelay =:= asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeDelay = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+%% REQUIRED (i.e. no default value)
+merge_ServiceChangeParm([{method, Val}|Parms], SCP0, Req0)
+ when SCP0#'ServiceChangeParm'.serviceChangeMethod =:= undefined ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeMethod = Val},
+ Req = lists:delete(serviceChangeMethod, Req0),
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{time_stamp, Val}|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.timeStamp =:= asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{timeStamp = Val},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{extension, _Val}|Parms], SCP0, Req) ->
+ merge_ServiceChangeParm(Parms, SCP0, Req);
+
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo =:= asn1_NOVALUE) andalso
+ is_atom(Val) ->
+ SCI = #'AuditDescriptor'{auditToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when (SCP0#'ServiceChangeParm'.serviceChangeInfo =:= asn1_NOVALUE) andalso
+ is_tuple(Val) ->
+ SCI = #'AuditDescriptor'{auditPropertyToken = [Val]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_atom(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditToken,
+ SCI = SCI0#'AuditDescriptor'{auditToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+merge_ServiceChangeParm([{audit_item, Val}|Parms], SCP0, Req)
+ when is_record(SCP0#'ServiceChangeParm'.serviceChangeInfo, 'AuditDescriptor') andalso
+ is_tuple(Val) ->
+ SCI0 = SCP0#'ServiceChangeParm'.serviceChangeInfo,
+ L = SCI0#'AuditDescriptor'.auditPropertyToken,
+ SCI = SCI0#'AuditDescriptor'{auditPropertyToken = [Val|L]},
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeInfo = SCI},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([incomplete|Parms], SCP0, Req)
+ when SCP0#'ServiceChangeParm'.serviceChangeIncompleteFlag =:= asn1_NOVALUE ->
+ SCP = SCP0#'ServiceChangeParm'{serviceChangeIncompleteFlag = 'NULL'},
+ merge_ServiceChangeParm(Parms, SCP, Req);
+
+merge_ServiceChangeParm([{Tag, Val}|_Parms], SCP, _Req) ->
+ Val2 =
+ case Tag of
+ address ->
+ SCP#'ServiceChangeParm'.serviceChangeAddress;
+ mgc_id ->
+ SCP#'ServiceChangeParm'.serviceChangeMgcId;
+ profile ->
+ SCP#'ServiceChangeParm'.serviceChangeProfile;
+ version ->
+ SCP#'ServiceChangeParm'.serviceChangeVersion;
+ reason ->
+ SCP#'ServiceChangeParm'.serviceChangeReason;
+ delay ->
+ SCP#'ServiceChangeParm'.serviceChangeDelay;
+ method ->
+ SCP#'ServiceChangeParm'.serviceChangeMethod;
+ time_stamp ->
+ SCP#'ServiceChangeParm'.timeStamp;
+ audit_item ->
+ SCP#'ServiceChangeParm'.serviceChangeInfo
+ end,
+ exit({at_most_once_serviceChangeParm, {Tag, Val, Val2}});
+merge_ServiceChangeParm([Parm|_Parms], SCP, _Req) ->
+ Parm2 =
+ case Parm of
+ incomplete ->
+ SCP#'ServiceChangeParm'.serviceChangeIncompleteFlag
+ end,
+ exit({at_most_once_serviceChangeParm, {Parm, Parm2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_ServiceChangeResParm,1}]}).
+-endif.
+merge_ServiceChangeResParm(Parms) ->
+ merge_ServiceChangeResParm(Parms, #'ServiceChangeResParm'{}).
+
+merge_ServiceChangeResParm([], SCRP) ->
+ SCRP;
+merge_ServiceChangeResParm([{address, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeAddress =:= asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId =:= asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeAddress = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{address, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeAddress =:= asn1_NOVALUE ->
+ MgcId = SCRP0#'ServiceChangeResParm'.serviceChangeMgcId,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, MgcId});
+
+merge_ServiceChangeResParm([{mgc_id, Val}|Parms], SCRP0)
+ when (SCRP0#'ServiceChangeResParm'.serviceChangeMgcId =:= asn1_NOVALUE) andalso
+ (SCRP0#'ServiceChangeResParm'.serviceChangeAddress =:= asn1_NOVALUE) ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeMgcId = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+merge_ServiceChangeResParm([{mgc_id, Val}|_Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeMgcId =:= asn1_NOVALUE ->
+ Addr = SCRP0#'ServiceChangeResParm'.serviceChangeAddress,
+ exit({not_both_address_mgcid_servChgReplyParm, Val, Addr});
+
+merge_ServiceChangeResParm([{profile, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeProfile =:= asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeProfile = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{version, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.serviceChangeVersion =:= asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{serviceChangeVersion = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{time_stamp, Val}|Parms], SCRP0)
+ when SCRP0#'ServiceChangeResParm'.timeStamp =:= asn1_NOVALUE ->
+ SCRP = SCRP0#'ServiceChangeResParm'{timeStamp = Val},
+ merge_ServiceChangeResParm(Parms, SCRP);
+
+merge_ServiceChangeResParm([{Tag, Val}|_Parms], SCRP) ->
+ Val2 =
+ case Tag of
+ address -> SCRP#'ServiceChangeResParm'.serviceChangeAddress;
+ mgc_id -> SCRP#'ServiceChangeResParm'.serviceChangeMgcId;
+ profile -> SCRP#'ServiceChangeResParm'.serviceChangeProfile;
+ version -> SCRP#'ServiceChangeResParm'.serviceChangeVersion;
+ time_stamp -> SCRP#'ServiceChangeResParm'.timeStamp
+ end,
+ exit({at_most_once_servChgReplyParm, {Tag, Val, Val2}}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_serviceChangeMethod,1}]}).
+-endif.
+ensure_serviceChangeMethod(Token) ->
+ case Token of
+ {safeToken, _Line, "fl"} ->
+ failover;
+ {safeToken, _Line, "failover"} ->
+ failover;
+ {safeToken, _Line, "fo"} ->
+ forced;
+ {safeToken, _Line, "forced"} ->
+ forced;
+ {safeToken, _Line, "gr"} ->
+ graceful;
+ {safeToken, _Line, "graceful"} ->
+ graceful;
+ {safeToken, _Line, "rs"} ->
+ restart;
+ {safeToken, _Line, "restart"} ->
+ restart;
+ {safeToken, _Line, "dc"} ->
+ disconnected;
+ {safeToken, _Line, "disconnected"} ->
+ disconnected;
+ {safeToken, _Line, "ho"} ->
+ handOff;
+ {safeToken, _Line, "handoff"} ->
+ handOff;
+ {safeToken, Line, Text} ->
+ return_error(Line, {bad_serviceChangeMethod, Text})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_topologyDescriptor,1}]}).
+-endif.
+merge_topologyDescriptor(Components) ->
+ merge_topologyDescriptor(Components, #'TopologyRequest'{}, []).
+
+merge_topologyDescriptor([], TR, TRs) ->
+ lists:reverse([ensure_TopologyRequest(TR)|TRs]);
+merge_topologyDescriptor(
+ [{tid, From}|Comps],
+ #'TopologyRequest'{terminationFrom = undefined} = TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{terminationFrom = From},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(
+ [{tid, To}|Comps],
+ #'TopologyRequest'{terminationTo = undefined} = TR1,
+ TRs) ->
+ TR2 = TR1#'TopologyRequest'{terminationTo = To},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{tid, From}|Comps], TR1, TRs) ->
+ TR2 = #'TopologyRequest'{terminationFrom = From},
+ merge_topologyDescriptor(Comps, TR2, [TR1 | TRs]);
+merge_topologyDescriptor([{direction, Dir}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirection = Dir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{sid, SID}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{streamID = SID},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(
+ [{direction_ext, EDir}|Comps],
+ #'TopologyRequest'{topologyDirection = asn1_NOVALUE} = TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirection = oneway,
+ topologyDirectionExtension = EDir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor([{direction_ext, EDir}|Comps], TR1, TRs) ->
+ TR2 = TR1#'TopologyRequest'{topologyDirectionExtension = EDir},
+ merge_topologyDescriptor(Comps, TR2, TRs);
+merge_topologyDescriptor(Comps, TR, TRs) ->
+ return_error(0, {bad_topologyDescriptor, Comps, TR, TRs}).
+
+
+ensure_TopologyRequest(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir} = R)
+ when (From =/= asn1_NOVALUE) andalso
+ (To =/= asn1_NOVALUE) andalso
+ (Dir =/= asn1_NOVALUE) ->
+ R;
+ensure_TopologyRequest(R) ->
+ return_error(0, {bad_TopologyRequest, R}).
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_profile,1}]}).
+-endif.
+ensure_profile(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ case string:tokens(Text, [$/]) of
+ [Name, Version] ->
+ Version2 = ensure_version(Version),
+ #'ServiceChangeProfile'{profileName = Name, version = Version2};
+ _ ->
+ return_error(Line, {bad_profile, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_version,1}]}).
+-endif.
+ensure_version(Version) ->
+ ensure_uint(Version, 0, 99).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_signalRequest,2}]}).
+-endif.
+merge_signalRequest(SignalName, PropertyParms) ->
+ Sig = #'Signal'{signalName = SignalName},
+ SPL = [],
+ do_merge_signalRequest(Sig, PropertyParms, SPL).
+
+do_merge_signalRequest(Sig, [H | T], SPL) ->
+ case H of
+ {stream, SID} when Sig#'Signal'.streamID =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{streamID = SID}, T, SPL);
+ {signal_type, SigType} when Sig#'Signal'.sigType =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{sigType = SigType}, T, SPL);
+ {duration, Duration} when Sig#'Signal'.duration =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{duration = Duration}, T, SPL);
+ {notify_completion, NC} when Sig#'Signal'.notifyCompletion =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{notifyCompletion = NC}, T, SPL);
+ keepActive when Sig#'Signal'.keepActive =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{keepActive = true}, T, SPL);
+ {other, Name, PP} ->
+ SP = #'SigParameter'{sigParameterName = Name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_signalRequest(Sig, T, [SP | SPL]);
+ {direction, Dir} when Sig#'Signal'.direction =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{direction = Dir}, T, SPL);
+ {requestId, RID} when Sig#'Signal'.requestID =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{requestID = RID}, T, SPL);
+ {intersigDelay, ISD} when Sig#'Signal'.intersigDelay =:= asn1_NOVALUE ->
+ do_merge_signalRequest(Sig#'Signal'{intersigDelay = ISD}, T, SPL);
+ _ ->
+ return_error(0, {bad_sigParm, H})
+ end;
+do_merge_signalRequest(Sig, [], SPL) ->
+ Sig#'Signal'{sigParList = lists:reverse(SPL)} .
+
+%% eventStream = StreamToken EQUAL StreamID
+%% eventOther = eventParameterName parmValue
+-ifdef(megaco_parser_inline).
+-compile({inline,[{select_stream_or_other,2}]}).
+-endif.
+select_stream_or_other(EventParameterName, ParmValue) ->
+ if
+ (EventParameterName =:= "st") orelse
+ (EventParameterName =:= "stream") ->
+ case ParmValue of
+ #'PropertyParm'{value = [Value]} ->
+ {stream, ensure_uint16(Value)};
+ _ ->
+ {stream, ensure_uint16(ParmValue)}
+ end;
+ true ->
+ #'PropertyParm'{value = Value} = ParmValue,
+ EP = #'EventParameter'{eventParameterName = EventParameterName,
+ value = Value},
+ {other, EP}
+ end.
+
+%% select_stream_or_other("st", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("st", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", #'PropertyParm'{value = [Value]}) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other("stream", Value) ->
+%% {stream, ensure_uint16(Value)};
+%% select_stream_or_other(Name, #'PropertyParm'{value = Value}) ->
+%% EP = #'EventParameter'{eventParameterName = Name,
+%% value = Value},
+%% {other, EP}.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_eventDM,1}]}).
+-endif.
+ensure_eventDM(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Name = DMD#'DigitMapDescriptor'.digitMapName,
+ Val = DMD#'DigitMapDescriptor'.digitMapValue,
+ if
+ (Name =:= asn1_NOVALUE) andalso (Val =/= asn1_NOVALUE) ->
+ {'DigitMapValue', Start, Short, Long, Duration, Body} = Val,
+ DMV = #'DigitMapValue'{startTimer = Start,
+ shortTimer = Short,
+ longTimer = Long,
+ digitMapBody = Body,
+ durationTimer = Duration},
+ {eventDM, {digitMapValue, DMV}};
+ (Name =/= asn1_NOVALUE) andalso (Val =:= asn1_NOVALUE) ->
+ {eventDM, {digitMapName, Name}};
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end;
+ true ->
+ return_error(Line, {bad_eventDM, DMD})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_DMD,1}]}).
+-endif.
+ensure_DMD(Token) ->
+ {_TokenTag, Line, DMD} = Token,
+ if
+ is_record(DMD, 'DigitMapDescriptor') ->
+ Val2 =
+ case DMD#'DigitMapDescriptor'.digitMapValue of
+ %% Note that the values of the digitMapBody and
+ %% durationTimers are swapped by the scanner
+ %% (this is done because of a problem in the flex scanner).
+ #'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ durationTimer = [],
+ digitMapBody = asn1_NOVALUE} ->
+ asn1_NOVALUE;
+ #'DigitMapValue'{durationTimer = Body,
+ digitMapBody = Duration} = DMV ->
+ %% Convert to version 1 DigitMapValue
+ DMV#'DigitMapValue'{digitMapBody = Body,
+ durationTimer = Duration};
+ Other ->
+ Other
+ end,
+ DMD#'DigitMapDescriptor'{digitMapValue = Val2};
+ true ->
+ return_error(Line, {bad_DigitMapDescriptor, DMD})
+ end.
+
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_observed_event,3}]}).
+-endif.
+merge_observed_event(ObservedEvents, EventName, TimeStamp) ->
+ StreamId = asn1_NOVALUE,
+ EPL = [],
+ do_merge_observed_event(ObservedEvents, EventName, TimeStamp, StreamId, EPL).
+
+do_merge_observed_event([{stream, StreamID} | T], EventName, TimeStamp, asn1_NOVALUE, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, EPL);
+do_merge_observed_event([{other, PP} | T], EventName, TimeStamp, StreamID, EPL) ->
+ do_merge_observed_event(T, EventName, TimeStamp, StreamID, [PP | EPL]);
+do_merge_observed_event([], EventName, TimeStamp, StreamID, EPL) ->
+ #'ObservedEvent'{eventName = EventName,
+ timeNotation = TimeStamp,
+ streamID = StreamID,
+ eventParList = lists:reverse(EPL)}.
+
+merge_eventSpec(OE)
+ when is_record(OE, 'ObservedEvent') andalso
+ (OE#'ObservedEvent'.timeNotation =:= asn1_NOVALUE) ->
+ #'EventSpec'{eventName = OE#'ObservedEvent'.eventName,
+ streamID = OE#'ObservedEvent'.streamID,
+ eventParList = OE#'ObservedEvent'.eventParList};
+merge_eventSpec(OE) ->
+ return_error(0, {bad_event_spec, OE}).
+
+make_RegulatedEmbeddedDescriptor({embed, SD, SED}) ->
+ #'RegulatedEmbeddedDescriptor'{secondEvent = SED,
+ signalsDescriptor = SD}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_eventParameters,1}]}).
+-endif.
+merge_eventParameters(Params) ->
+ SID = asn1_NOVALUE,
+ EPL = [],
+ RA = #'RequestedActions'{},
+ HasA = no,
+ do_merge_eventParameters(Params, SID, EPL, RA, HasA) .
+
+do_merge_eventParameters([H | T], SID, EPL, RA, HasA) ->
+ case H of
+ keepActive when RA#'RequestedActions'.keepActive =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{keepActive = true},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ resetEventsDescriptor when RA#'RequestedActions'.resetEventsDescriptor =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{resetEventsDescriptor = 'NULL'},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {embed, SD, SED} when RA#'RequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{signalsDescriptor = SD,
+ secondEvent = SED},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {eventDM, DM} when RA#'RequestedActions'.eventDM =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{eventDM = DM},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ {stream, NewSID} when SID =:= asn1_NOVALUE ->
+ do_merge_eventParameters(T, NewSID, EPL, RA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_eventParameters(T, SID, [EP | EPL], RA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_eventParameters(T, SID, [EP | EPL], RA, HasA);
+ {notifyBehaviour, NB} when RA#'RequestedActions'.notifyBehaviour =:= asn1_NOVALUE ->
+ RA2 = RA#'RequestedActions'{notifyBehaviour = NB},
+ do_merge_eventParameters(T, SID, EPL, RA2, yes);
+ _ ->
+ return_error(0, {bad_eventParameter, H})
+ end;
+do_merge_eventParameters([], SID, EPL, RA, yes) ->
+ #'RequestedEvent'{streamID = SID,
+ eventAction = RA,
+ evParList = lists:reverse(EPL)};
+do_merge_eventParameters([], SID, EPL, _RA, no) ->
+ #'RequestedEvent'{streamID = SID,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_secondEventParameters,1}]}).
+-endif.
+merge_secondEventParameters(Params) ->
+ SID = asn1_NOVALUE,
+ EPL = [],
+ SRA = #'SecondRequestedActions'{},
+ HasA = no,
+ do_merge_secondEventParameters(Params, SID, EPL, SRA, HasA) .
+
+do_merge_secondEventParameters([H | T], SID, EPL, SRA, HasA) ->
+ case H of
+ keepActive when SRA#'SecondRequestedActions'.keepActive =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{keepActive = true},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+ resetEventsDescriptor when SRA#'SecondRequestedActions'.resetEventsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{resetEventsDescriptor = 'NULL'},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+ {second_embed, SD} when SRA#'SecondRequestedActions'.signalsDescriptor =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{signalsDescriptor = SD},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+ {eventDM, DM} when SRA#'SecondRequestedActions'.eventDM =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{eventDM = DM},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+ {stream, NewSID} when SID =:= asn1_NOVALUE ->
+ do_merge_secondEventParameters(T, NewSID, EPL, SRA, HasA);
+ {other, PP} when is_record(PP, 'PropertyParm') ->
+ EP = #'EventParameter'{eventParameterName = PP#'PropertyParm'.name,
+ value = PP#'PropertyParm'.value,
+ extraInfo = PP#'PropertyParm'.extraInfo},
+ do_merge_secondEventParameters(T, SID, [EP | EPL], SRA, HasA);
+ {other, EP} when is_record(EP, 'EventParameter') ->
+ do_merge_secondEventParameters(T, SID, [EP | EPL], SRA, HasA);
+ {notifyBehaviour, NB} when SRA#'SecondRequestedActions'.notifyBehaviour =:= asn1_NOVALUE ->
+ SRA2 = SRA#'SecondRequestedActions'{notifyBehaviour = NB},
+ do_merge_secondEventParameters(T, SID, EPL, SRA2, yes);
+ _ ->
+ return_error(0, {bad_secondEventParameter, H})
+ end;
+do_merge_secondEventParameters([], SID, EPL, SRA, yes) ->
+ #'SecondRequestedEvent'{streamID = SID,
+ eventAction = SRA,
+ evParList = lists:reverse(EPL)};
+do_merge_secondEventParameters([], SID, EPL, _SRA, no) ->
+ #'SecondRequestedEvent'{streamID = SID,
+ eventAction = asn1_NOVALUE,
+ evParList = lists:reverse(EPL)}.
+
+%% terminationID = "ROOT" / pathName / "$" / "*"
+%% Total length of pathName must not exceed 64 chars.
+%% pathName = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+%% ABNF allows two or more consecutive "." although it is meaningless
+%% in a path domain name.
+%% pathDomainName = (ALPHA / DIGIT / "*" )
+%% *63(ALPHA / DIGIT / "-" / "*" / ".")
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_terminationID,1}]}).
+-endif.
+ensure_terminationID(Token) ->
+ {safeToken, _Line, LowerText} = Token,
+ %% terminationID = "ROOT" / pathName / "$" / "*"
+ decode_term_id(LowerText, false, [], []).
+
+decode_term_id([H | T], Wild, Id, Component) ->
+ case H of
+ $/ -> decode_term_id(T, Wild, [lists:reverse(Component) | Id], []);
+ $* -> decode_term_id(T, true, Id, [?megaco_all | Component]);
+ $$ -> decode_term_id(T, true, Id, [?megaco_choose | Component]);
+ _ -> decode_term_id(T, Wild, Id, [H | Component])
+ end;
+decode_term_id([], Wild, Id, Component) ->
+ Id2 = [lists:reverse(Component) | Id],
+ #megaco_term_id{contains_wildcards = Wild, id = lists:reverse(Id2)}.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_pathName,1}]}).
+-endif.
+ensure_pathName(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text. %% BUGBUG: ensure values
+
+%% TimeStamp = Date "T" Time ; per ISO 8601:1988
+%% Date = 8(DIGIT) ; Date = yyyymmdd
+%% Time = 8(DIGIT) ; Time = hhmmssss
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_timeStamp,1}]}).
+-endif.
+ensure_timeStamp(Token) ->
+ {'TimeStampToken', Line, Text} = Token,
+ case string:tokens(Text, [$T, $t]) of
+ [Date, Time] ->
+ #'TimeNotation'{date = Date, time = Time};
+ _ ->
+ return_error(Line, {bad_timeStamp, Text})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionID,1}]}).
+-endif.
+ensure_transactionID(TransId) ->
+ ensure_uint32(TransId).
+
+make_transactionID_and_segment_info({TokenTag, Line, Text}) ->
+ case string:tokens(Text, [$/]) of
+ [TidText, SegNoText, SegComplText] ->
+ Tid = ensure_uint32({TokenTag, Line, TidText}),
+ SegNo = ensure_uint16({TokenTag, Line, SegNoText}),
+ ensure_segmentationComplete({TokenTag, Line, SegComplText}),
+ {Tid, SegNo, 'NULL'};
+ [TidText, SegNoText] ->
+ Tid = ensure_uint32({TokenTag, Line, TidText}),
+ SegNo = ensure_uint16({TokenTag, Line, SegNoText}),
+ {Tid, SegNo};
+ [TidText] ->
+ ensure_uint32({TokenTag, Line, TidText})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_segmentationComplete,1}]}).
+-endif.
+ensure_segmentationComplete(Token) ->
+ {_TokenTag, Line, Text} = Token,
+ if
+ (Text =:= "end") orelse (Text =:= "&") ->
+ ok;
+ true ->
+ return_error(Line, {invalid_segmentationCompleteToken, Text})
+ end.
+
+make_TransactionReply({Tid, SegNo, 'NULL'}, IAR, Res) ->
+ #'TransactionReply'{transactionId = Tid,
+ immAckRequired = IAR,
+ transactionResult = Res,
+ segmentNumber = SegNo,
+ segmentationComplete = 'NULL'};
+make_TransactionReply({Tid, SegNo}, IAR, Res) ->
+ #'TransactionReply'{transactionId = Tid,
+ immAckRequired = IAR,
+ transactionResult = Res,
+ segmentNumber = SegNo};
+make_TransactionReply(Tid, IAR, Res) ->
+ #'TransactionReply'{transactionId = Tid,
+ immAckRequired = IAR,
+ transactionResult = Res}.
+
+make_SegmentReply({Tid, SegNo, 'NULL'}) ->
+ #'SegmentReply'{transactionId = Tid,
+ segmentNumber = SegNo,
+ segmentationComplete = 'NULL'};
+make_SegmentReply({Tid, SegNo}) ->
+ #'SegmentReply'{transactionId = Tid,
+ segmentNumber = SegNo}.
+
+
+%% transactionAck = transactionID / (transactionID "-" transactionID)
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_transactionAck,1}]}).
+-endif.
+ensure_transactionAck(Tokens) ->
+ {safeToken, _Line, Text} = Tokens,
+ case string:tokens(Text, [$-]) of
+ [Id] ->
+ #'TransactionAck'{firstAck = ensure_transactionID(Id)};
+ [Id, Id2] ->
+ #'TransactionAck'{firstAck = ensure_transactionID(Id),
+ lastAck = ensure_transactionID(Id2)}
+ end.
+
+merge_context_request(asn1_NOVALUE, Prop) ->
+ merge_context_request(#'ContextRequest'{}, Prop);
+
+merge_context_request(#'ContextRequest'{priority = asn1_NOVALUE} = CR,
+ {priority, Int}) ->
+ CR#'ContextRequest'{priority = Int};
+
+merge_context_request(#'ContextRequest'{emergency = asn1_NOVALUE} = CR,
+ {emergency, Bool}) ->
+ CR#'ContextRequest'{emergency = Bool};
+
+merge_context_request(#'ContextRequest'{topologyReq = asn1_NOVALUE} = CR,
+ {topology, Desc}) ->
+ CR#'ContextRequest'{topologyReq = Desc};
+
+merge_context_request(#'ContextRequest'{iepscallind = asn1_NOVALUE} = CR,
+ {iepsCallind, Ind}) ->
+ CR#'ContextRequest'{iepscallind = Ind};
+
+merge_context_request(#'ContextRequest'{contextProp = asn1_NOVALUE} = CR,
+ {contextProp, Props}) ->
+ CR#'ContextRequest'{contextProp = Props};
+
+merge_context_request(#'ContextRequest'{contextList = asn1_NOVALUE} = CR,
+ {contextList, IDs}) ->
+ CR#'ContextRequest'{contextList = IDs};
+
+merge_context_request(CR, {Tag, Val}) ->
+ Val2 =
+ case Tag of
+ priority -> CR#'ContextRequest'.priority;
+ emergency -> CR#'ContextRequest'.emergency;
+ topology -> CR#'ContextRequest'.topologyReq;
+ iepsCallind -> CR#'ContextRequest'.iepscallind;
+ contextProp -> CR#'ContextRequest'.contextProp;
+ contextList -> CR#'ContextRequest'.contextList
+ end,
+ exit({at_most_once_contextProperty, {Tag, Val, Val2}}).
+
+
+merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{contextPropAud = asn1_NOVALUE} = CAAR, []) ->
+
+ CAAR;
+merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{contextPropAud = CPA} = CAAR, []) ->
+
+ CAAR#'ContextAttrAuditRequest'{contextPropAud = lists:reverse(CPA)};
+merge_context_attr_audit_request(CAAR, [H|T]) ->
+ case H of
+ priorityAudit when CAAR#'ContextAttrAuditRequest'.priority =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{priority = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ emergencyAudit when CAAR#'ContextAttrAuditRequest'.emergency =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{emergency = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ topologyAudit when CAAR#'ContextAttrAuditRequest'.topology =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{topology = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ iepsCallind when CAAR#'ContextAttrAuditRequest'.iepscallind =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{iepscallind = 'NULL'},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} when CAAR#'ContextAttrAuditRequest'.contextPropAud =:= asn1_NOVALUE ->
+ CPA = [#'IndAudPropertyParm'{name = Name}],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {prop, Name} ->
+ CPA = CAAR#'ContextAttrAuditRequest'.contextPropAud,
+ CPA2 = [#'IndAudPropertyParm'{name = Name}|CPA],
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{contextPropAud = CPA2},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_prio, Prio} when CAAR#'ContextAttrAuditRequest'.selectpriority =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectpriority = Prio},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_emergency, EV} when CAAR#'ContextAttrAuditRequest'.selectemergency =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectemergency = EV},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_ieps, IV} when CAAR#'ContextAttrAuditRequest'.selectiepscallind =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectiepscallind = IV},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ {select_logic, SL} when CAAR#'ContextAttrAuditRequest'.selectLogic =:= asn1_NOVALUE ->
+ CAAR2 = CAAR#'ContextAttrAuditRequest'{selectLogic = SL},
+ merge_context_attr_audit_request(CAAR2, T);
+
+ %% BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ %%
+ %% For some strange reason, contextAttrDescriptor was added
+ %% to contextAuditSelector. But there is no place for this
+ %% info in the ContextAttrAuditRequest. Since contextAttrDescriptor
+ %% can also be found in contextProperty (which correspond to
+ %% ContextRequest), the question is if this info should go there
+ %% or if we shall just drop it. For now we drop it.
+ %%
+ {contextProp, _PPs} ->
+ merge_context_attr_audit_request(CAAR, T);
+
+ {contextList, _IDs} ->
+ merge_context_attr_audit_request(CAAR, T);
+
+ _ ->
+ exit({unexpected_contextAttrAudit_item, H})
+
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_request,2}]}).
+-endif.
+merge_action_request(CtxId, Items) ->
+ do_merge_action_request(Items, [], asn1_NOVALUE, asn1_NOVALUE, CtxId).
+
+do_merge_action_request([H|T], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ case H of
+ {commandRequest, CmdReq} ->
+ do_merge_action_request(T, [CmdReq|CmdReqs],
+ CtxReq, CtxAuditReq, CtxId);
+
+ {contextProp, ContextProp} ->
+ do_merge_action_request(T, CmdReqs,
+ merge_context_request(CtxReq, ContextProp),
+ CtxAuditReq, CtxId);
+
+ {contextAudit, ContextAuditReq} when CtxAuditReq =:= asn1_NOVALUE ->
+ do_merge_action_request(T, CmdReqs,
+ CtxReq, ContextAuditReq, CtxId)
+ end;
+do_merge_action_request([], CmdReqs, CtxReq, CtxAuditReq, CtxId) ->
+ #'ActionRequest'{contextId = CtxId,
+ contextRequest = strip_ContextRequest(CtxReq),
+ contextAttrAuditReq = strip_ContextAttrAuditRequest(CtxAuditReq),
+ commandRequests = lists:reverse(CmdReqs)}.
+
+
+%% OTP-5085:
+%% In order to solve a problem in the parser, the error descriptor
+%% has been put last in the non-empty commandReplyList, if it is not
+%% asn1_NOVALUE
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_action_reply,1}]}).
+-endif.
+merge_action_reply(Items) ->
+ do_merge_action_reply(Items, asn1_NOVALUE, asn1_NOVALUE, []).
+
+do_merge_action_reply([], Err, Ctx, Cmds) ->
+ #'ActionReply'{errorDescriptor = Err,
+ contextReply = strip_ContextRequest(Ctx),
+ commandReply = lists:reverse(Cmds)};
+do_merge_action_reply([H|T], Err0, CR, Cmds) ->
+ case H of
+ {error, Err1} when Err0 =:= asn1_NOVALUE ->
+ do_merge_action_reply(T, Err1, CR, Cmds);
+ {command, Cmd} ->
+ do_merge_action_reply(T, Err0, CR, [Cmd | Cmds]);
+ {context, CtxProp} ->
+ do_merge_action_reply(T, Err0,
+ merge_context_request(CR, CtxProp), Cmds)
+ end.
+
+merge_auditOther([TID], TAR) ->
+ {auditResult,
+ #'AuditResult'{terminationID = TID,
+ terminationAuditResult = TAR}};
+merge_auditOther(TIDs, TAR) ->
+ {auditResultTermList,
+ #'TermListAuditResult'{terminationIDList = TIDs,
+ terminationAuditResult = TAR}}.
+
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = asn1_NOVALUE,
+ contextList = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextRequest(#'ContextRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topologyReq = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextProp = [],
+ contextList = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+%% strip_ContextRequest(asn1_NOVALUE) ->
+%% asn1_NOVALUE;
+strip_ContextRequest(R) ->
+ R.
+
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = asn1_NOVALUE,
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(
+ #'ContextAttrAuditRequest'{priority = asn1_NOVALUE,
+ emergency = asn1_NOVALUE,
+ topology = asn1_NOVALUE,
+ iepscallind = asn1_NOVALUE,
+ contextPropAud = [],
+ selectpriority = asn1_NOVALUE,
+ selectemergency = asn1_NOVALUE,
+ selectiepscallind = asn1_NOVALUE,
+ selectLogic = asn1_NOVALUE}) ->
+ asn1_NOVALUE;
+strip_ContextAttrAuditRequest(R) ->
+ R.
+
+merge_AmmRequest_descriptors([], Acc) ->
+ lists:reverse(Acc);
+merge_AmmRequest_descriptors([{_, deprecated}|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, Acc);
+merge_AmmRequest_descriptors([Desc|Descs], Acc) ->
+ merge_AmmRequest_descriptors(Descs, [Desc|Acc]).
+
+make_auditRequest([TID], AD) ->
+ #'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD};
+make_auditRequest([TID|_] = TIDList, AD) ->
+ #'AuditRequest'{terminationID = TID,
+ auditDescriptor = AD,
+ terminationIDList = TIDList}.
+
+make_commandRequest({CmdTag, {_TokenTag, _Line, Text}}, Cmd) ->
+ Req = #'CommandRequest'{command = {CmdTag, Cmd}},
+ case Text of
+ [$w, $- | _] ->
+ Req#'CommandRequest'{wildcardReturn = 'NULL'};
+ [$o, $-, $w, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL', wildcardReturn = 'NULL'};
+ [$o, $- | _] ->
+ Req#'CommandRequest'{optional = 'NULL'};
+ _ ->
+ Req
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationAudit,1}]}).
+-endif.
+merge_terminationAudit(AuditReturnParameters) ->
+ lists:reverse(do_merge_terminationAudit(AuditReturnParameters, [], [])).
+
+do_merge_terminationAudit([H| T], ARPs, AuditItems) ->
+ case H of
+ {auditReturnItem, AuditItem} ->
+ do_merge_terminationAudit(T, ARPs, [AuditItem | AuditItems]);
+ AuditReturnParameter ->
+ do_merge_terminationAudit(T, [AuditReturnParameter | ARPs], AuditItems)
+ end;
+do_merge_terminationAudit([], AuditReturnParameters, []) ->
+ AuditReturnParameters;
+do_merge_terminationAudit([], AuditReturnParameters, AuditItems) ->
+ AuditDescriptor = #'AuditDescriptor'{auditToken = AuditItems},
+ AuditReturnParameter = {emptyDescriptors, AuditDescriptor},
+ [AuditReturnParameter | AuditReturnParameters].
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_mediaDescriptor,1}]}).
+-endif.
+merge_mediaDescriptor(MediaParms) ->
+ do_merge_mediaDescriptor(MediaParms, asn1_NOVALUE, [], []).
+
+do_merge_mediaDescriptor([H | T], TS, One, Multi) ->
+ case H of
+ {streamParm, Parm} when Multi =:= [] ->
+ do_merge_mediaDescriptor(T, TS, [Parm | One], Multi);
+ {streamDescriptor, Desc} when One =:= [] ->
+ do_merge_mediaDescriptor(T, TS, One, [Desc | Multi]);
+ {termState, TS2} when TS =:= asn1_NOVALUE ->
+ do_merge_mediaDescriptor(T, TS2, One, Multi);
+ _ ->
+ return_error(0, {bad_merge_mediaDescriptor, [H, TS, One, Multi]})
+ end;
+do_merge_mediaDescriptor([], TS, One, Multi) ->
+ if
+ (One =:= []) ->
+ if (Multi =:= []) ->
+ #'MediaDescriptor'{streams = asn1_NOVALUE,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ Streams = {multiStream, lists:reverse(Multi)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS}
+ end;
+ true -> % (One =/= [])
+ if
+ (Multi =:= []) ->
+ Streams = {oneStream, merge_streamParms(One)},
+ #'MediaDescriptor'{streams = Streams,
+ termStateDescr = TS};
+ true -> % (Multi =/= [])
+ return_error(0,
+ {bad_merge_mediaDescriptor, [TS, One, Multi]})
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_streamParms,1}]}).
+-endif.
+merge_streamParms(TaggedStreamParms) ->
+ SP = #'StreamParms'{},
+ do_merge_streamParms(TaggedStreamParms, SP).
+
+do_merge_streamParms([{Tag, D} | T] = All, SP) ->
+ case Tag of
+ local when SP#'StreamParms'.localDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{localDescriptor = D});
+ remote when SP#'StreamParms'.remoteDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{remoteDescriptor = D});
+ control ->
+ LCD =
+ case SP#'StreamParms'.localControlDescriptor of
+ asn1_NOVALUE ->
+ #'LocalControlDescriptor'{propertyParms = []};
+ PrevLCD ->
+ PrevLCD
+ end,
+ LCD2 = do_merge_control_streamParms(D, LCD),
+ do_merge_streamParms(T, SP#'StreamParms'{localControlDescriptor = LCD2});
+ statistics when SP#'StreamParms'.statisticsDescriptor =:= asn1_NOVALUE ->
+ do_merge_streamParms(T, SP#'StreamParms'{statisticsDescriptor = D});
+ _ ->
+ return_error(0, {do_merge_streamParms, [All, SP]})
+ end;
+do_merge_streamParms([], SP)
+ when is_record(SP#'StreamParms'.localControlDescriptor, 'LocalControlDescriptor') ->
+ LCD = SP#'StreamParms'.localControlDescriptor,
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = lists:reverse(PP)},
+ SP#'StreamParms'{localControlDescriptor = LCD2};
+do_merge_streamParms([], SP) ->
+ SP.
+
+
+do_merge_control_streamParms([{SubTag, SD} | T] = All, LCD) ->
+ case SubTag of
+ group when LCD#'LocalControlDescriptor'.reserveGroup =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveGroup = SD},
+ do_merge_control_streamParms(T, LCD2);
+ value when LCD#'LocalControlDescriptor'.reserveValue =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{reserveValue = SD},
+ do_merge_control_streamParms(T, LCD2);
+ mode when LCD#'LocalControlDescriptor'.streamMode =:= asn1_NOVALUE ->
+ LCD2 = LCD#'LocalControlDescriptor'{streamMode = SD},
+ do_merge_control_streamParms(T, LCD2);
+ prop ->
+ PP = LCD#'LocalControlDescriptor'.propertyParms,
+ LCD2 = LCD#'LocalControlDescriptor'{propertyParms = [SD | PP]},
+ do_merge_control_streamParms(T, LCD2);
+ _ ->
+ return_error(0, {do_merge_control_streamParms, [All, LCD]})
+ end;
+do_merge_control_streamParms([], LCD) ->
+ LCD.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{merge_terminationStateDescriptor,1}]}).
+-endif.
+merge_terminationStateDescriptor(Parms) ->
+ TSD = #'TerminationStateDescriptor'{propertyParms = []},
+ do_merge_terminationStateDescriptor(Parms, TSD).
+
+do_merge_terminationStateDescriptor([{Tag, Val} | T], TSD) ->
+ case Tag of
+ serviceState when TSD#'TerminationStateDescriptor'.serviceState =:= asn1_NOVALUE ->
+ TSD2 = TSD#'TerminationStateDescriptor'{serviceState = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ eventBufferControl when TSD#'TerminationStateDescriptor'.eventBufferControl =:= asn1_NOVALUE->
+ TSD2 = TSD#'TerminationStateDescriptor'{eventBufferControl = Val},
+ do_merge_terminationStateDescriptor(T, TSD2);
+ propertyParm ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD2 = TSD#'TerminationStateDescriptor'{propertyParms = [Val | PP]},
+ do_merge_terminationStateDescriptor(T, TSD2)
+ end;
+do_merge_terminationStateDescriptor([], TSD) ->
+ PP = TSD#'TerminationStateDescriptor'.propertyParms,
+ TSD#'TerminationStateDescriptor'{propertyParms = lists:reverse(PP)}.
+
+-ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Group = [],
+ Groups = [],
+ parse_prop_name(Text, Group, Groups).
+
+parse_prop_name([Char | Rest] = All, Group, Groups) ->
+ if
+ ?white_space(Char) ->
+ parse_prop_name(Rest, Group, Groups);
+ ?end_of_line(Char) ->
+ parse_prop_name(Rest, Group, Groups);
+ true ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group, Groups)
+ end;
+parse_prop_name([] = All, Group, Groups) ->
+ Name = [],
+ do_parse_prop_name(All, Name, Group, Groups).
+
+do_parse_prop_name([Char | Rest], Name, Group, Groups)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ Groups2 = [lists:reverse(Group) | Groups],
+ Group2 = [],
+ parse_prop_value(Rest, Name, Group2, Groups2);
+ true ->
+ %% Use current property group
+ parse_prop_value(Rest, Name, Group, Groups)
+ end;
+do_parse_prop_name([Char | Rest], Name, Group, Groups) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_parse_prop_name(Rest, [Char | Name], Group, Groups);
+ safe_char ->
+ do_parse_prop_name(Rest, [Char | Name], Group, Groups);
+ _ ->
+ return_error(0, {bad_prop_name, lists:reverse(Name), Char})
+ end;
+do_parse_prop_name([], [], [], Groups) ->
+ lists:reverse(Groups);
+do_parse_prop_name([], [], Group, Groups) ->
+ Group2 = lists:reverse(Group),
+ lists:reverse([Group2 | Groups]);
+do_parse_prop_name([], Name, Group, Groups) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{parse_prop_value,4}]}).
+-endif.
+parse_prop_value(Chars, Name, Group, Groups) ->
+ Value = [],
+ do_parse_prop_value(Chars, Name, Value, Group, Groups).
+
+do_parse_prop_value([Char | Rest], Name, Value, Group, Groups) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_prop_parm(Name, Value),
+ parse_prop_name(Rest, [PP | Group], Groups);
+ true ->
+ do_parse_prop_value(Rest, Name, [Char | Value], Group, Groups)
+ end;
+do_parse_prop_value([], Name, Value, Group, Groups) ->
+ %% Assume end of line
+ PP = make_prop_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{make_prop_parm,2}]}).
+-endif.
+make_prop_parm(Name, Value) ->
+ #'PropertyParm'{name = lists:reverse(Name),
+ value = [lists:reverse(Value)]}.
+
+-else. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_prop_groups,1}]}).
+-endif.
+ensure_prop_groups(Token) ->
+ {_TokenTag, _Line, Groups} = Token,
+ Groups.
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{do_ensure_prop_groups,1}]}).
+%% -endif.
+%% do_ensure_prop_groups(Groups) when is_list(Groups) ->
+%% [ensure_prop_group(Group) || Group <- Groups];
+%% do_ensure_prop_groups(BadGroups) ->
+%% throw({error, {?MODULE, {bad_property_groups, BadGroups}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_group,1}]}).
+%% -endif.
+%% ensure_prop_group(Group) when is_list(Group) ->
+%% [ensure_prop_parm(PropParm) || PropParm <- Group];
+%% ensure_prop_group(BadGroup) ->
+%% throw({error, {?MODULE, {bad_property_group, BadGroup}}}).
+
+%% -ifdef(megaco_parser_inline).
+%% -compile({inline,[{ensure_prop_parm,1}]}).
+%% -endif.
+%% ensure_prop_parm(#property_parm{name = Name,
+%% value = Value}) ->
+%% #'PropertyParm'{name = Name,
+%% value = Value};
+%% ensure_prop_parm(PP) when is_record(PP, 'PropertyParm') ->
+%% PP;
+%% ensure_prop_parm(BadPropParm) ->
+%% throw({error, {?MODULE, {bad_property_parm, BadPropParm}}}).
+
+-endif. % -ifdef(megaco_nscanner_props).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,3}]}).
+-endif.
+ensure_uint(Token, Min, Max) ->
+ case Token of
+ {_TokenTag, Line, Val} when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line);
+ {_TokenTag, Line, Text} ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(Line, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, Line)
+ end;
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0);
+ Text ->
+ case (catch list_to_integer(Text)) of
+ {'EXIT', _} ->
+ return_error(0, {not_an_integer, Text});
+ Val when is_integer(Val) ->
+ ensure_uint(Val, Min, Max, 0)
+ end
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint,4}]}).
+-endif.
+ensure_uint(Val, Min, Max, Line) ->
+ if
+ is_integer(Min) andalso (Val >= Min) ->
+ if
+ is_integer(Max) andalso (Val =< Max) ->
+ Val;
+ Max =:= infinity ->
+ Val;
+ true ->
+ return_error(Line, {too_large_integer, Val, Max})
+ end;
+ true ->
+ return_error(Line, {too_small_integer, Val, Min})
+ end.
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint16,1}]}).
+-endif.
+ensure_uint16(Int) ->
+ ensure_uint(Int, 0, 65535).
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{ensure_uint32,1}]}).
+-endif.
+ensure_uint32(Int) ->
+ ensure_uint(Int, 0, 4294967295) .
+
+%% OTP-4710
+ensure_hex({_TokenTag, _Line, [$0, $x |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex({_TokenTag, _Line, [$0, $X |Chars]}, Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $x |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []);
+ensure_hex([$0, $X |Chars], Min, Max) ->
+ ensure_uint(length(Chars), Min, Max),
+ hex_to_int(Chars, []).
+
+%% OTP-4710
+hex_to_int([], Acc) ->
+ lists:reverse(Acc);
+hex_to_int([Char1,Char2|Tail], Acc) ->
+ Int1 = hchar_to_int(Char1),
+ Int2 = hchar_to_int(Char2),
+ Val = Int2 bor (Int1 bsl 4),
+ hex_to_int(Tail, [Val| Acc]);
+hex_to_int([Char], Acc) ->
+ Int = hchar_to_int(Char),
+ lists:reverse([Int|Acc]).
+
+hchar_to_int(Char) when ($0 =< Char) andalso (Char =< $9) ->
+ Char - $0;
+hchar_to_int(Char) when ($A =< Char) andalso (Char =< $F) ->
+ Char - $A + 10; % OTP-4710
+hchar_to_int(Char) when ($a =< Char) andalso (Char =< $f) ->
+ Char - $a + 10. % OTP-4710
+
+-ifdef(megaco_parser_inline).
+-compile({inline,[{value_of,1}]}).
+-endif.
+value_of(Token) ->
+ {_TokenTag, _Line, Text} = Token,
+ Text.
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(true, F, A).
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("DBG:~w:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
diff --git a/lib/megaco/src/text/megaco_text_parser_v3.yrl b/lib/megaco/src/text/megaco_text_parser_v3.yrl
new file mode 100644
index 0000000000..d400a93c66
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_parser_v3.yrl
@@ -0,0 +1,1680 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: YECC grammar for text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Annex B TEXT ENCODING OF THE PROTOCOL (NORMATIVE)
+%%
+%% B.1 Coding of wildcards
+%%
+%% In a text encoding of the protocol, while TerminationIDs are
+%% arbitrary, by judicious choice of names, the wildcard character, "*"
+%% may be made more useful. When the wildcard character is encountered,
+%% it will "match" all TerminationIDs having the same previous and
+%% following characters (if appropriate). For example, if there were
+%% TerminationIDs of R13/3/1, R13/3/2 and R13/3/3, the TerminationID
+%% R13/3/* would match all of them. There are some circumstances where
+%% ALL Terminations must be referred to. The TerminationID "*" suffices,
+%% and is referred to as ALL. The CHOOSE TerminationID "$" may be used to
+%% signal to the MG that it has to create an ephemeral Termination or
+%% select an idle physical Termination.
+%%
+%% B.2 ABNF specification
+%%
+%% The protocol syntax is presented in ABNF according to RFC2234. The
+%% protocol is not case sensitive. Identifiers are not case sensitive.
+%%
+%% NOTE 1 - This syntax specification does not enforce all restrictions
+%% on element inclusions and values. Some additional
+%% restrictions are stated in comments and other restrictions
+%% appear in the text of this Recommendation. These additional
+%% restrictions are part of the protocol even though not
+%% enforced by this Recommendation.
+%% NOTE 2 - The syntax is context-dependent. For example, "Add" can be
+%% the AddToken or a NAME depending on the context in which it
+%% occurs.
+%%
+%% Everything in the ABNF and text encoding is case insensitive. This
+%% includes TerminationIDs, digitmap Ids etc. SDP is case sensitive as
+%% per RFC 2327.
+%%
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Number of expected shift/reduce warnings
+%% This is ugly but...
+%%----------------------------------------------------------------------
+
+Expect 91.
+
+
+%%----------------------------------------------------------------------
+%% Non-terminals
+%%----------------------------------------------------------------------
+
+Nonterminals
+
+ actionReply
+ actionReplyBody
+ actionReplyList
+ actionRequest
+ actionRequestBody
+ actionRequestItem
+ actionRequestItems
+ actionRequestList
+ alternativeValue
+ ammParameter
+ ammParameters
+ ammRequest
+ ammRequestBody
+ ammToken
+ ammsReply
+ ammsReplyBody
+ ammsToken
+ auditDescriptor
+ auditDescriptorBody
+ auditItem
+ auditItemList
+ auditOther
+ auditReply
+ auditRequest
+ auditReturnItem
+ auditReturnParameter
+ auditReturnParameterList
+ auditSelectLogic %% v3
+ authenticationHeader
+ commandReplyList
+ commandReplys %% v3
+ commandRequest
+ contextAttrDescriptor %% v3
+ contextAudit
+ contextAuditProperties
+ contextAuditProperty
+ contextAuditSelector %% v3
+ contextID
+ contextIdList %% v3
+ contextIDs %% v3
+%% contextProperties %% v3
+ contextProperty
+%% contextPropertyList
+ contextTerminationAudit
+ daddr
+ deviceName
+ digitMapDescriptor
+ direction %% v3
+ domainAddress
+ domainName
+ embedFirst
+ embedNoSig
+ embedSig
+ embedWithSig
+ emergencyValue %% v3
+ errorCode
+ errorDescriptor
+ errorText
+ eventBufferControl
+ eventBufferControlValue %% v3
+ eventBufferDescriptor
+ eventDM
+ eventParameter
+ eventParameterName
+ eventParameters
+ eventSpec
+ eventSpecList
+ eventStream
+ eventStreamOrOther
+ eventsDescriptor
+ extension
+ extensionParameter
+
+ iaServiceStates %% v3
+ iepsValue
+
+ %% v2 - start
+ indAudauditReturnParameter
+ indAuddigitMapDescriptor
+ indAudeventBufferDescriptor
+ indAudeventSpec
+ indAudeventSpecParameter
+ %% indAudeventSpecParameterList
+ indAudeventsDescriptor
+ indAudlocalControlDescriptor
+ indAudlocalParm
+ indAudlocalParmList
+ indAudmediaDescriptor
+ indAudmediaParm
+ indAudmediaParms %% v3
+ %% indAudmediaParmList
+ indAudpackagesDescriptor
+ indAudrequestedEvent
+ indAudsignalsDescriptor
+ indAudsignalList
+ %% indAudsignalListParm
+ indAudsignalParm
+ %% indAudsignalRequest
+ indAudstreamDescriptor
+ indAudstreamParm
+ indAudstatisticsDescriptor
+ indAudterminationAudit
+ indAudterminationAuditList
+ indAudterminationStateDescriptor
+ indAudterminationStateParm
+ %% indAudterminationStateParmList
+ optIndAudeventSpecParameter
+ optIndAudsignalParm
+ %% v2 - end
+
+ indAudcontextAttrDescriptor %% v3
+
+ localControlDescriptor
+ localParm
+ localParmList
+ mId
+ mediaDescriptor
+ mediaParm
+ mediaParmList
+ megacoMessage
+ message
+ messageBody
+ modemDescriptor % Deprecated as of Corr 1
+ modemType % Deprecated as of Corr 1
+ modemTypeList % Deprecated as of Corr 1
+ mtpAddress
+ muxDescriptor
+ muxType
+ notificationReason
+ notificationReasons
+ notifyBehaviour %% v3
+ notifyRegulated %% v3
+ notifyReply
+ notifyReplyBody
+ notifyRequest
+ notifyRequestBody
+ observedEvent
+ observedEventBody
+ observedEventParameter
+ observedEventParameters
+ % observedEventTimeStamp
+ observedEvents
+ observedEventsDescriptor
+ onOrOff
+ optAuditDescriptor
+ optImmAckRequired
+ optPropertyParms
+ optSep
+ packagesDescriptor
+ packagesItem
+ packagesItems
+ %% parmName
+ parmValue
+ pathName
+ pkgdName
+ portNumber
+ priority
+ propertyParm
+ propertyParms
+ propertyParmList
+ requestID
+ requestedEvent
+ requestedEventBody
+ requestedEvents
+ safeToken
+ safeToken2
+ secondEventParameter
+ secondEventParameters
+ secondRequestedEvent
+ secondRequestedEventBody
+ secondRequestedEvents
+ segmentReply %% v3
+ %% segmentNumber %% v3
+ servChgReplyParm
+ servChgReplyParms
+ serviceChangeAddress
+ serviceChangeDelay
+ serviceChangeDescriptor
+ serviceChangeMethod
+ serviceChangeMgcId
+ serviceChangeParm
+ serviceChangeParms
+ serviceChangeProfile
+ serviceChangeReason
+ serviceChangeReply
+ serviceChangeReplyBody
+ serviceChangeReplyDescriptor
+ serviceChangeRequest
+ serviceChangeVersion
+ serviceStates
+ serviceStatesValue %% v3
+ sigParameter
+ sigParameters
+ signalList
+ signalListId
+ signalListParm
+ signalListParms
+ signalName
+ signalParm
+ signalParms
+ signalRequest
+ signalsDescriptor
+ signalType
+ statisticsDescriptor
+ statisticsParameter
+ statisticsParameters
+ streamDescriptor
+ streamID
+ streamModes
+ streamParm
+ streamParmList
+ subtractRequest
+ termIDList %% v3
+ terminationAudit
+ terminationID
+ terminationIDList
+ terminationIDListRepeat
+ terminationStateDescriptor
+ terminationStateParm
+ terminationStateParms
+ timeStamp
+ topologyDescriptor
+ topologyDirection
+ topologyDescComp
+ topologyDescCompList
+ transactionAck
+ transactionAckList
+ transactionID
+ transactionID_and_segment_info
+ transactionItem
+ transactionList
+ transactionPending
+ transactionReply
+ transactionReplyBody
+ transactionRequest
+ transactionResponseAck
+ value
+ valueList
+
+.
+
+%%----------------------------------------------------------------------
+%% Terminals
+%%----------------------------------------------------------------------
+
+Terminals
+
+ 'AddToken'
+ 'AndAUDITselectToken' %% v3
+ 'AuditCapToken'
+ 'AuditToken'
+ 'AuditValueToken'
+ 'AuthToken'
+ 'BothToken' %% v3
+ 'BothwayToken'
+ 'BriefToken'
+ 'BufferToken'
+ 'COLON'
+ 'COMMA'
+ 'ContextAttrToken' %% v3
+ 'ContextAuditToken'
+ 'ContextListToken' %% v3
+ 'CtxToken'
+ 'DelayToken'
+ 'DigitMapToken'
+ 'DigitMapDescriptorToken'
+ 'DirectionToken' %% v3
+ 'DiscardToken'
+ 'DisconnectedToken'
+ 'DurationToken'
+ 'EQUAL'
+ 'EmbedToken'
+ 'EmergencyToken'
+ 'EmergencyOffToken'
+ 'EmergencyValueToken' %% v3
+ 'ErrorToken'
+ 'EventBufferToken'
+ 'EventsToken'
+ 'ExternalToken' %% v3
+ 'FailoverToken'
+ 'ForcedToken'
+ 'GREATER'
+ 'GracefulToken'
+ 'H221Token'
+ 'H223Token'
+ 'H226Token'
+ 'HandOffToken'
+ 'IEPSToken' %% v3
+ 'ImmAckRequiredToken'
+ 'INEQUAL' %% v3
+ 'InSvcToken'
+ 'InactiveToken'
+ 'InternalToken' %% v3
+ 'InterruptByEventToken'
+ 'InterruptByNewSignalsDescrToken'
+ 'IntsigDelayToken' %% v3
+ 'IsolateToken'
+ 'IterationToken' %% v3
+ 'KeepActiveToken'
+ 'LBRKT'
+ 'LESSER'
+ 'LSBRKT'
+ 'LocalControlToken'
+ 'LocalDescriptorToken'
+ 'LockStepToken'
+ 'LoopbackToken'
+ 'MediaToken'
+ %% 'MegacopToken'
+ 'MessageSegmentToken'
+ 'MethodToken'
+ 'MgcIdToken'
+ 'ModeToken'
+ 'ModemToken'
+ 'ModifyToken'
+ 'MoveToken'
+ 'MtpAddressToken'
+ 'MuxToken'
+ 'NEQUAL'
+ 'NeverNotifyToken' %% v3
+ 'NotifyCompletionToken'
+ 'NotifyImmediateToken' %% v3
+ 'NotifyRegulatedToken' %% v3
+ 'NotifyToken'
+ 'Nx64Token' %% v2
+ 'ObservedEventsToken'
+ 'OffToken'
+ 'OnToken'
+ 'OnOffToken'
+ 'OnewayToken'
+ 'OnewayExternalToken' %% v3
+ 'OnewayBothToken' %% v3
+ 'OrAUDITselectToken' %% v3
+ 'OtherReasonToken'
+ 'OutOfSvcToken'
+ 'PackagesToken'
+ 'PendingToken'
+ 'PriorityToken'
+ 'ProfileToken'
+ 'QuotedChars'
+ 'RBRKT'
+ 'RSBRKT'
+ 'ReasonToken'
+ 'RecvonlyToken'
+ 'RemoteDescriptorToken'
+ 'ReplyToken'
+ 'RequestIDToken' %% v3
+ 'ReservedGroupToken'
+ 'ReservedValueToken'
+ 'ResetEventsDescriptorToken' %% v3
+ 'ResponseAckToken'
+ 'RestartToken'
+ 'SEP'
+ 'SafeChars'
+ %% 'SegmentationCompleteToken'
+ 'SendonlyToken'
+ 'SendrecvToken'
+ 'ServiceChangeAddressToken'
+ 'ServiceChangeToken'
+ 'ServiceChangeIncompleteToken'
+ 'ServiceStatesToken'
+ 'ServicesToken'
+ 'SignalListToken'
+ 'SignalTypeToken'
+ 'SignalsToken'
+ %% 'SLASH'
+ 'StatsToken'
+ 'StreamToken'
+ 'SubtractToken'
+ 'SynchISDNToken'
+ 'TerminationStateToken'
+ 'TestToken'
+ 'TimeOutToken'
+ 'TimeStampToken'
+ 'TopologyToken'
+ 'TransToken'
+ 'V18Token'
+ 'V22Token'
+ 'V22bisToken'
+ 'V32Token'
+ 'V32bisToken'
+ 'V34Token'
+ 'V76Token'
+ 'V90Token'
+ 'V91Token'
+ 'VersionToken'
+ endOfMessage
+
+.
+
+%%----------------------------------------------------------------------
+%% Root symbol
+%%----------------------------------------------------------------------
+
+Rootsymbol megacoMessage.
+
+%%----------------------------------------------------------------------
+%% The grammar
+%%----------------------------------------------------------------------
+
+%% megacoMessage = LWSP [authenticationHeader SEP ] message
+%% authenticationHeader = AuthToken EQUAL SecurityParmIndex COLON
+%% SequenceNum COLON AuthData
+%%
+%% SecurityParmIndex = "0x" 8(HEXDIG)
+%% SequenceNum = "0x" 8(HEXDIG)
+%% AuthData = "0x" 24*64(HEXDIG)
+%% message = MegacopToken SLASH version SEP mId SEP messageBody
+%% version = 1*2(DIGIT) .
+
+megacoMessage -> optSep authenticationHeader message endOfMessage
+ : #'MegacoMessage'{authHeader = '$2', mess = '$3'} .
+
+optSep -> 'SEP' : sep .
+optSep -> '$empty' : no_sep .
+
+authenticationHeader -> 'AuthToken' 'EQUAL' safeToken 'COLON'
+ safeToken 'COLON' safeToken optSep
+ : ensure_auth_header('$3', '$5', '$7') .
+authenticationHeader -> '$empty' : asn1_NOVALUE .
+
+message -> safeToken mId messageBody :
+ ensure_message('$1', '$2', '$3') .
+
+messageBody -> errorDescriptor : {messageError, '$1'} .
+messageBody -> transactionList : {transactions, '$1'} .
+
+transactionList -> transactionItem : ['$1'] .
+transactionList -> transactionItem transactionList : ['$1' | '$2'] .
+
+transactionItem -> transactionRequest : {transactionRequest, '$1'} .
+transactionItem -> transactionReply : {transactionReply, '$1'}.
+transactionItem -> transactionPending : {transactionPending, '$1'} .
+transactionItem -> transactionResponseAck : {transactionResponseAck, '$1'} .
+transactionItem -> segmentReply : {segmentReply, '$1'} .
+
+transactionResponseAck -> 'ResponseAckToken'
+ 'LBRKT' transactionAck
+ transactionAckList 'RBRKT' : ['$3' | '$4'] .
+
+transactionAckList -> 'COMMA' transactionAck
+ transactionAckList : ['$2' | '$3'] .
+transactionAckList -> '$empty' : [] .
+
+transactionAck -> safeToken : ensure_transactionAck('$1') .
+
+transactionPending -> 'PendingToken' 'EQUAL' transactionID 'LBRKT' 'RBRKT' :
+ #'TransactionPending'{transactionId = ensure_transactionID('$3') } .
+
+transactionRequest -> 'TransToken' 'LBRKT' actionRequest
+ actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$3' | '$4']} .
+transactionRequest -> 'TransToken' 'EQUAL' 'LBRKT' actionRequest
+ actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = asn1_NOVALUE,
+ actions = ['$4' | '$5']} .
+transactionRequest -> 'TransToken' 'EQUAL' transactionID
+ 'LBRKT' actionRequest actionRequestList 'RBRKT' :
+ #'TransactionRequest'{transactionId = ensure_transactionID('$3'),
+ actions = ['$5' | '$6']} .
+
+actionRequestList -> 'COMMA' actionRequest actionRequestList : ['$2' | '$3'] .
+actionRequestList -> '$empty' : [] .
+
+%% actionRequest = CtxToken EQUAL ContextID LBRKT ((contextRequest
+%% [COMMA commandRequestList]) /
+%% commandRequestList) RBRKT
+%% contextRequest = ((contextProperties [COMMA contextAudit]) /
+%% contextAudit)
+%% contextProperties = contextProperty *(COMMA contextProperty)
+
+actionRequest -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionRequestBody 'RBRKT' :
+ merge_action_request('$3', '$5') .
+
+actionRequestBody -> actionRequestItem actionRequestItems : ['$1' | '$2'] .
+
+actionRequestItems -> 'COMMA' actionRequestItem
+ actionRequestItems : ['$2' | '$3'] .
+actionRequestItems -> '$empty' : [] .
+
+actionRequestItem -> contextProperty : {contextProp, '$1'} .
+actionRequestItem -> contextAudit : {contextAudit, '$1'} .
+actionRequestItem -> commandRequest : {commandRequest, '$1'} .
+
+
+%% at-most-once (presumebly in contextProperties)
+contextProperty -> topologyDescriptor : {topology, '$1'}.
+contextProperty -> priority : {priority, '$1'}.
+contextProperty -> 'EmergencyToken' : {emergency, true}.
+contextProperty -> 'EmergencyOffToken' : {emergency, false}.
+contextProperty -> iepsValue : {iepsCallind, '$1'} .
+contextProperty -> contextAttrDescriptor : '$1' .
+
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' propertyParms 'RBRKT' :
+ {contextProp, '$3'}.
+contextAttrDescriptor -> 'ContextAttrToken' 'LBRKT' contextIdList 'RBRKT' :
+ {contextList, '$3'}.
+
+contextIdList -> 'ContextListToken' 'EQUAL'
+ 'LBRKT' contextID contextIDs 'RBRKT' : ['$4' | '$5'] .
+
+contextIDs -> 'COMMA' contextID contextIDs : ['$2' | '$3'] .
+contextIDs -> '$empty' : [] .
+
+contextAudit -> 'ContextAuditToken' 'LBRKT'
+ indAudcontextAttrDescriptor 'RBRKT' :
+ merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, '$3') .
+contextAudit -> 'ContextAuditToken' 'LBRKT'
+ contextAuditProperty contextAuditProperties 'RBRKT' :
+ merge_context_attr_audit_request(
+ #'ContextAttrAuditRequest'{}, ['$3' | '$4']) .
+
+indAudcontextAttrDescriptor -> 'ContextAttrToken'
+ 'LBRKT' contextAuditProperty
+ contextAuditProperties 'RBRKT'
+ : ['$3' | '$4'] .
+
+contextAuditProperties -> 'COMMA' contextAuditProperty contextAuditProperties
+ : ['$2' | '$3'] .
+contextAuditProperties -> '$empty' : [] .
+
+%% at-most-once except contextAuditSelector.
+contextAuditProperty -> 'TopologyToken' : topologyAudit .
+contextAuditProperty -> 'EmergencyToken' : emergencyAudit .
+contextAuditProperty -> 'PriorityToken' : priorityAudit .
+contextAuditProperty -> 'IEPSToken' : iepsCallind .
+contextAuditProperty -> pkgdName : {prop, '$1'} .
+contextAuditProperty -> contextAuditSelector : '$1' .
+
+%% at-most-once
+contextAuditSelector -> priority : {select_prio, '$1'} .
+contextAuditSelector -> emergencyValue : {select_emergency, '$1'} .
+contextAuditSelector -> iepsValue : {select_ieps, '$1'} .
+contextAuditSelector -> auditSelectLogic : {select_logic, '$1'} .
+contextAuditSelector -> contextAttrDescriptor : '$1' .
+
+auditSelectLogic -> 'AndAUDITselectToken' : {andAUDITSelect, 'NULL'} .
+auditSelectLogic -> 'OrAUDITselectToken' : {orAUDITSelect, 'NULL'} .
+
+commandRequest -> ammRequest : '$1'.
+commandRequest -> subtractRequest : '$1'.
+commandRequest -> auditRequest : '$1'.
+commandRequest -> notifyRequest : '$1'.
+commandRequest -> serviceChangeRequest : '$1'.
+
+transactionReply -> 'ReplyToken' 'EQUAL' transactionID_and_segment_info
+ 'LBRKT'
+ optImmAckRequired transactionReplyBody
+ 'RBRKT' :
+ make_TransactionReply('$3', '$5', '$6') .
+
+segmentReply -> 'MessageSegmentToken' 'EQUAL'
+ transactionID_and_segment_info :
+ make_SegmentReply('$3') .
+
+%% segmentNumber -> safeToken : ensure_uint16('$1') .
+
+optImmAckRequired -> 'ImmAckRequiredToken' 'COMMA' : 'NULL' .
+optImmAckRequired -> '$empty' : asn1_NOVALUE .
+
+transactionReplyBody -> errorDescriptor : {transactionError, '$1'} .
+transactionReplyBody -> actionReply actionReplyList : {actionReplies, ['$1' | '$2']} .
+
+actionReplyList -> 'COMMA' actionReply actionReplyList : ['$2' | '$3'] .
+actionReplyList -> '$empty' : [] .
+
+actionReply -> 'CtxToken' 'EQUAL' contextID
+ 'LBRKT' actionReplyBody 'RBRKT' :
+ setelement(#'ActionReply'.contextId, '$5', '$3') .
+actionReply -> 'CtxToken' 'EQUAL' contextID :
+ #'ActionReply'{contextId = '$3'} .
+
+actionReplyBody -> errorDescriptor :
+ #'ActionReply'{errorDescriptor = '$1'} .
+actionReplyBody -> commandReplys commandReplyList :
+ merge_action_reply(['$1' | '$2']) .
+
+%% OTP-5085
+%% This ugly thing is to fool the parser. The errorDescriptor does not
+%% realy belong here. The merge_action_reply will remove it and put it
+%% in it's right place later.
+commandReplyList -> 'COMMA' errorDescriptor :
+ [{error, '$2'}] .
+commandReplyList -> 'COMMA' commandReplys commandReplyList :
+ ['$2' | '$3'] .
+commandReplyList -> '$empty' : [] .
+
+commandReplys -> serviceChangeReply : {command, '$1'} .
+commandReplys -> auditReply : {command, '$1'} .
+commandReplys -> ammsReply : {command, '$1'} .
+commandReplys -> notifyReply : {command, '$1'} .
+commandReplys -> contextProperty : {context, '$1'} .
+
+%Add Move and Modify have the same request parameter
+ammRequest -> ammToken 'EQUAL' termIDList ammRequestBody :
+ Descs = merge_AmmRequest_descriptors('$4', []),
+ make_commandRequest('$1',
+ #'AmmRequest'{terminationID = '$3',
+ descriptors = Descs}) .
+
+ammToken -> 'AddToken' : {addReq, '$1'} .
+ammToken -> 'MoveToken' : {moveReq, '$1'} .
+ammToken -> 'ModifyToken' : {modReq, '$1'} .
+
+ammRequestBody -> 'LBRKT' ammParameter ammParameters 'RBRKT' : ['$2' | '$3'] .
+ammRequestBody -> '$empty' : [] .
+
+ammParameters -> 'COMMA' ammParameter ammParameters : ['$2' | '$3'] .
+ammParameters -> '$empty' : [] .
+
+%at-most-once
+ammParameter -> mediaDescriptor : {mediaDescriptor, '$1'}.
+ammParameter -> modemDescriptor : {modemDescriptor, deprecated}.
+ammParameter -> muxDescriptor : {muxDescriptor, '$1'}.
+ammParameter -> eventsDescriptor : {eventsDescriptor, '$1'}.
+ammParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'}.
+ammParameter -> signalsDescriptor : {signalsDescriptor, '$1'}.
+ammParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'}.
+ammParameter -> auditDescriptor : {auditDescriptor, '$1'}.
+ammParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'}.
+
+ammsReply -> ammsToken 'EQUAL' termIDList ammsReplyBody
+ : {'$1', #'AmmsReply'{terminationID = '$3',
+ terminationAudit = '$4'}} .
+
+ammsToken -> 'AddToken' : addReply .
+ammsToken -> 'MoveToken' : moveReply .
+ammsToken -> 'ModifyToken' : modReply .
+ammsToken -> 'SubtractToken' : subtractReply .
+
+ammsReplyBody -> 'LBRKT' terminationAudit 'RBRKT' : '$2' .
+ammsReplyBody -> '$empty' : asn1_NOVALUE .
+
+subtractRequest -> 'SubtractToken' 'EQUAL' termIDList optAuditDescriptor :
+ SR = #'SubtractRequest'{terminationID = '$3',
+ auditDescriptor = '$4'},
+ make_commandRequest({subtractReq, '$1'}, SR) .
+
+
+optAuditDescriptor -> 'LBRKT' auditDescriptor 'RBRKT' : '$2'.
+optAuditDescriptor -> '$empty' : asn1_NOVALUE .
+
+auditRequest -> 'AuditValueToken' 'EQUAL' termIDList optAuditDescriptor :
+ make_commandRequest({auditValueRequest, '$1'},
+ make_auditRequest('$3', '$4')) .
+auditRequest -> 'AuditCapToken' 'EQUAL' termIDList optAuditDescriptor :
+ make_commandRequest({auditCapRequest, '$1'},
+ make_auditRequest('$3', '$4')) .
+
+auditReply -> 'AuditValueToken' 'EQUAL' 'CtxToken' contextTerminationAudit :
+ {auditValueReply, '$4'} .
+auditReply -> 'AuditCapToken' 'EQUAL' 'CtxToken' contextTerminationAudit :
+ {auditCapReply, '$4'} .
+auditReply -> 'AuditValueToken' 'EQUAL' auditOther :
+ {auditValueReply, '$3'} .
+auditReply -> 'AuditCapToken' 'EQUAL' auditOther :
+ {auditCapReply, '$3'} .
+
+contextTerminationAudit -> terminationIDList :
+ {contextAuditResult, '$1'} .
+contextTerminationAudit -> 'LBRKT' errorDescriptor 'RBRKT' :
+ {error, '$2'} .
+
+auditOther -> termIDList :
+ merge_auditOther('$1', []) .
+auditOther -> termIDList 'LBRKT' terminationAudit 'RBRKT' :
+ merge_auditOther('$1', '$3') .
+
+
+terminationAudit -> auditReturnParameter auditReturnParameterList :
+ merge_terminationAudit(['$1' |'$2' ]) .
+
+auditReturnParameterList -> 'COMMA' auditReturnParameter auditReturnParameterList : ['$2' | '$3'] .
+auditReturnParameterList -> '$empty' : [] .
+
+auditReturnParameter -> mediaDescriptor : {mediaDescriptor, '$1'} .
+auditReturnParameter -> modemDescriptor.
+auditReturnParameter -> muxDescriptor : {muxDescriptor, '$1'} .
+auditReturnParameter -> eventsDescriptor : {eventsDescriptor, '$1'} .
+auditReturnParameter -> signalsDescriptor : {signalsDescriptor, '$1'} .
+auditReturnParameter -> digitMapDescriptor : {digitMapDescriptor, '$1'} .
+auditReturnParameter -> observedEventsDescriptor : {observedEventsDescriptor, '$1'} .
+auditReturnParameter -> eventBufferDescriptor : {eventBufferDescriptor, '$1'} .
+auditReturnParameter -> statisticsDescriptor : {statisticsDescriptor, '$1'} .
+auditReturnParameter -> packagesDescriptor : {packagesDescriptor, '$1'} .
+auditReturnParameter -> errorDescriptor : {errorDescriptor, '$1'} .
+auditReturnParameter -> auditReturnItem : {auditReturnItem, '$1'} .
+
+auditDescriptor -> 'AuditToken' 'LBRKT' auditDescriptorBody 'RBRKT' :
+ merge_auditDescriptor('$3') .
+
+auditDescriptorBody -> auditItem auditItemList : ['$1' | '$2'].
+auditDescriptorBody -> '$empty' : asn1_NOVALUE .
+
+auditItemList -> 'COMMA' auditItem auditItemList : ['$2' | '$3'] .
+auditItemList -> '$empty' : [] .
+
+%% IGv11 - begin
+%%
+auditReturnItem -> 'MuxToken' : muxToken .
+auditReturnItem -> 'ModemToken' : modemToken .
+auditReturnItem -> 'MediaToken' : mediaToken .
+auditReturnItem -> 'DigitMapToken' : digitMapToken .
+auditReturnItem -> 'StatsToken' : statsToken .
+auditReturnItem -> 'ObservedEventsToken' : observedEventsToken .
+auditReturnItem -> 'PackagesToken' : packagesToken .
+
+%% at-most-once, and DigitMapToken and PackagesToken are not allowed
+%% in AuditCapabilities command
+auditItem -> auditReturnItem : '$1' .
+auditItem -> 'SignalsToken' : signalsToken.
+auditItem -> 'EventBufferToken' : eventBufferToken.
+auditItem -> 'EventsToken' : eventsToken .
+auditItem -> indAudterminationAudit : {terminationAudit, '$1'} . % v2
+%%
+%% IGv11 - end
+
+
+%% v2 - start
+%%
+indAudterminationAudit -> indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$1' | '$2'] .
+
+indAudterminationAuditList -> 'COMMA' indAudauditReturnParameter
+ indAudterminationAuditList
+ : ['$2' | '$3'] .
+indAudterminationAuditList -> '$empty' : [] .
+
+indAudauditReturnParameter -> indAudmediaDescriptor
+ : {indAudMediaDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventsDescriptor
+ : {indAudEventsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudsignalsDescriptor
+ : {indAudSignalsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAuddigitMapDescriptor
+ : {indAudDigitMapDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudeventBufferDescriptor
+ : {indAudEventBufferDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudstatisticsDescriptor
+ : {indAudStatisticsDescriptor, '$1'} .
+indAudauditReturnParameter -> indAudpackagesDescriptor
+ : {indAudPackagesDescriptor, '$1'} .
+
+
+indAudmediaDescriptor -> 'MediaToken' 'LBRKT'
+ indAudmediaParm indAudmediaParms 'RBRKT'
+ : merge_indAudMediaDescriptor(['$3'|'$4']) .
+
+%% at-most-once per item
+%% and either streamParm or streamDescriptor but not both
+%%
+
+indAudmediaParm -> indAudstreamParm : {streamParm, '$1'} .
+indAudmediaParm -> indAudstreamDescriptor : {streamDescr, '$1'} .
+indAudmediaParm -> indAudterminationStateDescriptor : {termStateDescr, '$1'} .
+
+indAudmediaParms -> 'COMMA' indAudmediaParm indAudmediaParms : ['$2' | '$3'] .
+indAudmediaParms -> '$empty' : [] .
+
+%% at-most-once
+indAudstreamParm -> 'RemoteDescriptorToken' :
+ RD = ensure_prop_groups('$1'),
+ #'IndAudStreamParms'{remoteDescriptor = RD} .
+indAudstreamParm -> 'LocalDescriptorToken' :
+ LD = ensure_prop_groups('$1'),
+ #'IndAudStreamParms'{localDescriptor = LD} .
+indAudstreamParm -> indAudlocalControlDescriptor :
+ #'IndAudStreamParms'{localControlDescriptor = '$1'} .
+indAudstreamParm -> indAudstatisticsDescriptor :
+ #'IndAudStreamParms'{statisticsDescriptor = '$1'} .
+
+indAudstreamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' indAudstreamParm 'RBRKT'
+ : #'IndAudStreamDescriptor'{streamID = '$3',
+ streamParms = '$5'} .
+
+
+indAudlocalControlDescriptor -> 'LocalControlToken'
+ 'LBRKT' indAudlocalParm
+ indAudlocalParmList 'RBRKT' :
+ merge_indAudLocalControlDescriptor(['$3' | '$4']) .
+
+indAudlocalParmList -> 'COMMA' indAudlocalParm
+ indAudlocalParmList : ['$2' | '$3'] .
+indAudlocalParmList -> '$empty' : [] .
+
+%% at-most-once per item
+%%
+%% propertyparm and streamModes are used only to specify audit selection
+%% criteria. AND/OR selection logic is specified at context level.
+%%
+indAudlocalParm -> 'ReservedGroupToken' : reservedGroupToken .
+indAudlocalParm -> 'ReservedValueToken' : reservedValueToken .
+indAudlocalParm -> 'ModeToken' : modeToken .
+indAudlocalParm -> 'ModeToken' 'EQUAL' streamModes : {mode, {equal, '$3'}} .
+indAudlocalParm -> 'ModeToken' 'INEQUAL' streamModes : {mode, {inequal,'$3'}} .
+indAudlocalParm -> propertyParm : {prop, '$1'} .
+indAudlocalParm -> pkgdName : {name, '$1'} .
+
+indAudterminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' indAudterminationStateParm 'RBRKT'
+ :
+ merge_indAudTerminationStateDescriptor('$3') .
+
+%% at-most-once per item
+%%
+
+%% at-most-once per item except for propertyParm
+indAudterminationStateParm -> iaServiceStates : '$1' .
+indAudterminationStateParm -> 'BufferToken' : bufferToken .
+indAudterminationStateParm -> propertyParm : {prop, '$1'} .
+indAudterminationStateParm -> pkgdName : {name, '$1'} .
+
+iaServiceStates -> 'ServiceStatesToken' :
+ serviceStatesToken .
+iaServiceStates -> 'ServiceStatesToken' 'EQUAL' serviceStatesValue :
+ {serviceStates, {equal, '$3'}} .
+iaServiceStates -> 'ServiceStatesToken' 'INEQUAL' serviceStatesValue :
+ {serviceStates, {inequal, '$3'}} .
+
+indAudeventBufferDescriptor -> 'EventBufferToken'
+ 'LBRKT' indAudeventSpec 'RBRKT' : '$3' .
+
+indAudeventSpec -> pkgdName optIndAudeventSpecParameter
+ : merge_indAudEventBufferDescriptor('$1','$2') .
+
+optIndAudeventSpecParameter -> 'LBRKT' indAudeventSpecParameter 'RBRKT'
+ : '$2' .
+optIndAudeventSpecParameter -> '$empty' : asn1_NOVALUE .
+
+
+indAudeventSpecParameter -> eventStream : {streamID, '$1'} .
+indAudeventSpecParameter -> eventParameterName : {eventParameterName, '$1'} .
+
+indAudeventsDescriptor -> 'EventsToken' 'LBRKT' indAudrequestedEvent 'RBRKT' :
+ #'IndAudEventsDescriptor'{pkgdName = '$3'} .
+indAudeventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' indAudrequestedEvent 'RBRKT' :
+ #'IndAudEventsDescriptor'{requestID = '$3',
+ pkgdName = '$5'} .
+
+indAudrequestedEvent -> pkgdName : '$1' .
+
+
+indAudsignalsDescriptor -> 'SignalsToken' optIndAudsignalParm : '$2' .
+
+
+optIndAudsignalParm -> 'LBRKT' 'RBRKT' : asn1_NOVALUE .
+optIndAudsignalParm -> 'LBRKT' indAudsignalParm 'RBRKT' : '$2' .
+
+indAudsignalParm -> indAudsignalList : {seqSigList, '$1'} .
+indAudsignalParm -> signalRequest : {signal, ensure_indAudSignal('$1')} .
+
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3')} .
+indAudsignalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm 'RBRKT' :
+ #'IndAudSeqSigList'{id = ensure_uint16('$3'),
+ signalList =
+ ensure_indAudSignalListParm('$5')} .
+
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+indAuddigitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_IADMD('$1') .
+
+indAudstatisticsDescriptor -> 'StatsToken' 'LBRKT' pkgdName 'RBRKT' :
+ #'IndAudStatisticsDescriptor'{statName = '$3'} .
+
+indAudpackagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem 'RBRKT'
+ : merge_indAudPackagesDescriptor('$3') .
+
+eventStream -> 'StreamToken' 'EQUAL' streamID : '$3' .
+
+
+%%
+%% v2 - end
+
+notifyRequest -> 'NotifyToken' 'EQUAL' termIDList
+ 'LBRKT' notifyRequestBody 'RBRKT' :
+ NR = setelement(#'NotifyRequest'.terminationID,
+ '$5', '$3'),
+ make_commandRequest({notifyReq, '$1'}, NR) .
+
+notifyRequestBody -> observedEventsDescriptor :
+ #'NotifyRequest'{observedEventsDescriptor = '$1'}.
+notifyRequestBody -> errorDescriptor :
+ #'NotifyRequest'{errorDescriptor = '$1'}.
+
+notifyReply -> 'NotifyToken' 'EQUAL' termIDList notifyReplyBody :
+ {notifyReply, #'NotifyReply'{terminationID = '$3',
+ errorDescriptor = '$4'}} .
+
+notifyReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' : '$2'.
+notifyReplyBody -> '$empty' : asn1_NOVALUE .
+
+serviceChangeRequest -> 'ServiceChangeToken' 'EQUAL' termIDList
+ 'LBRKT' serviceChangeDescriptor 'RBRKT' :
+ make_commandRequest({serviceChangeReq, '$1'},
+ #'ServiceChangeRequest'{terminationID = '$3',
+ serviceChangeParms = '$5'}) .
+
+serviceChangeReply -> 'ServiceChangeToken' 'EQUAL' termIDList
+ serviceChangeReplyBody :
+ {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = '$3',
+ serviceChangeResult = '$4'}} .
+
+serviceChangeReplyBody -> 'LBRKT' errorDescriptor 'RBRKT' :
+ {errorDescriptor, '$2'} .
+serviceChangeReplyBody -> 'LBRKT' serviceChangeReplyDescriptor 'RBRKT' :
+ {serviceChangeResParms, '$2'} .
+serviceChangeReplyBody -> '$empty' :
+ {serviceChangeResParms, #'ServiceChangeResParm'{}}.
+
+errorDescriptor -> 'ErrorToken' 'EQUAL' errorCode 'LBRKT'
+ errorText 'RBRKT' :
+ #'ErrorDescriptor'{errorCode = '$3',
+ errorText = '$5'} .
+
+errorCode -> safeToken : ensure_uint('$1', 0, 999) .
+
+errorText -> 'QuotedChars' : value_of('$1') .
+errorText -> '$empty' : asn1_NOVALUE .
+
+transactionID -> safeToken : ensure_uint32('$1') .
+transactionID_and_segment_info -> safeToken :
+ make_transactionID_and_segment_info('$1') .
+
+mId -> domainName : '$1' .
+mId -> domainAddress : '$1' .
+mId -> optSep mtpAddress optSep : '$2' .
+mId -> optSep deviceName optSep : '$2' .
+
+domainName -> 'LESSER' safeToken 'GREATER' 'COLON' portNumber optSep
+ : ensure_domainName('$2', '$5') .
+domainName -> 'LESSER' safeToken 'GREATER'
+ : ensure_domainName('$2', asn1_NOVALUE) .
+
+deviceName -> pathName : {deviceName, '$1'} .
+
+%% '-' is used for NULL context
+contextID -> safeToken : ensure_contextID('$1') .
+
+domainAddress -> 'LSBRKT' daddr 'RSBRKT' 'COLON' portNumber optSep
+ : ensure_domainAddress('$2', '$5') .
+domainAddress -> 'LSBRKT' daddr 'RSBRKT'
+ : ensure_domainAddress('$2', asn1_NOVALUE) .
+
+daddr -> '$empty' : [] .
+daddr -> 'COLON' daddr : [colon| '$2'] .
+daddr -> safeToken daddr : ['$1'| '$2'] .
+
+
+portNumber -> safeToken : ensure_uint16('$1') .
+
+mtpAddress -> 'MtpAddressToken' : ensure_mtpAddress('$1') .
+
+termIDList -> terminationID : ['$1'] .
+termIDList -> LSBRKT terminationID terminationIDListRepeat RSBRKT :
+ ['$2' | '$3'] .
+
+terminationIDList -> 'LBRKT' terminationID terminationIDListRepeat 'RBRKT' :
+ ['$2' | '$3'] .
+
+terminationIDListRepeat -> 'COMMA' terminationID terminationIDListRepeat :
+ ['$2'| '$3'] .
+terminationIDListRepeat -> '$empty' : [] .
+
+
+pathName -> safeToken : ensure_pathName('$1') .
+
+terminationID -> safeToken : ensure_terminationID('$1') .
+
+mediaDescriptor -> 'MediaToken' 'LBRKT' mediaParm mediaParmList 'RBRKT'
+ : merge_mediaDescriptor(['$3' | '$4']) .
+
+mediaParmList -> 'COMMA' mediaParm mediaParmList : ['$2' | '$3'] .
+mediaParmList -> '$empty' : [] .
+
+
+%% at-most-once per item
+%% using either streamParms or streamDescriptors but not both
+mediaParm -> streamParm
+ : {streamParm, '$1'} .
+mediaParm -> streamDescriptor
+ : {streamDescriptor, '$1'} .
+mediaParm -> terminationStateDescriptor
+ : {termState, '$1'} .
+
+%% at-most-once .
+%% Specially treated by the scanner.
+streamParm -> 'LocalDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {local, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> 'RemoteDescriptorToken' :
+ PGs = ensure_prop_groups('$1'),
+ {remote, #'LocalRemoteDescriptor'{propGrps = PGs}} .
+streamParm -> localControlDescriptor : {control, '$1'} .
+streamParm -> statisticsDescriptor : {statistics, '$1'} .
+
+streamDescriptor -> 'StreamToken' 'EQUAL' streamID
+ 'LBRKT' streamParm streamParmList 'RBRKT'
+ : #'StreamDescriptor'{streamID = '$3',
+ streamParms = merge_streamParms(['$5' | '$6'])} .
+
+streamParmList -> 'COMMA' streamParm streamParmList : ['$2' | '$3'] .
+streamParmList -> '$empty' : [] .
+
+localControlDescriptor -> 'LocalControlToken' 'LBRKT' localParm localParmList 'RBRKT'
+ : ['$3' | '$4'] .
+
+localParmList -> 'COMMA' localParm localParmList : ['$2' | '$3'] .
+localParmList -> '$empty': [] .
+
+terminationStateDescriptor -> 'TerminationStateToken'
+ 'LBRKT' terminationStateParm
+ terminationStateParms 'RBRKT'
+ : merge_terminationStateDescriptor(['$3' | '$4']) .
+
+terminationStateParms -> 'COMMA' terminationStateParm terminationStateParms : ['$2' | '$3'] .
+terminationStateParms -> '$empty' : [] .
+
+%% at-most-once per item except for propertyParm
+localParm -> 'ReservedGroupToken' 'EQUAL' onOrOff : {group, '$3'} .
+localParm -> 'ReservedValueToken' 'EQUAL' onOrOff : {value, '$3'} .
+localParm -> 'ModeToken' 'EQUAL' streamModes : {mode, '$3'} .
+localParm -> propertyParm : {prop, '$1'} .
+
+onOrOff -> 'OnToken' : true .
+onOrOff -> 'OffToken' : false .
+
+%% at-most-once
+streamModes -> 'SendonlyToken' : sendOnly .
+streamModes -> 'RecvonlyToken' : recvOnly .
+streamModes -> 'SendrecvToken' : sendRecv .
+streamModes -> 'InactiveToken' : inactive .
+streamModes -> 'LoopbackToken' : loopBack .
+
+propertyParm -> pkgdName parmValue :
+ setelement(#'PropertyParm'.name, '$2', '$1') .
+
+parmValue -> 'EQUAL' alternativeValue :
+ '$2' .
+
+parmValue -> 'NEQUAL' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, unequalTo}} .
+parmValue -> 'LESSER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, smallerThan}} .
+parmValue -> 'GREATER' value :
+ #'PropertyParm'{value = ['$2'],
+ extraInfo = {relation, greaterThan}} .
+
+%% OTP-4013
+%% alternativeValue = ( VALUE /
+%% LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE COLON VALUE RSBRKT ) /
+%% LBRKT VALUE *(COMMA VALUE) RBRKT
+alternativeValue -> 'LBRKT' value valueList 'RBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, false}}. % OR
+
+alternativeValue -> 'LSBRKT' value 'COLON' value 'RSBRKT'
+ : #'PropertyParm'{value = ['$2', '$4'],
+ extraInfo = {range, true}}.
+
+alternativeValue -> 'LSBRKT' value valueList 'RSBRKT'
+ : #'PropertyParm'{value = ['$2' | '$3'],
+ extraInfo = {sublist, true}}. % AND
+
+alternativeValue -> value :
+ #'PropertyParm'{value = ['$1']} .
+
+valueList -> 'COMMA' value valueList : ['$2' | '$3'] .
+valueList -> '$empty' : [] .
+
+
+eventBufferDescriptor -> 'EventBufferToken' : [] .
+eventBufferDescriptor -> 'EventBufferToken' 'LBRKT' eventSpec
+ eventSpecList 'RBRKT' :
+ ['$3' | '$4'] .
+
+eventSpecList -> 'COMMA' eventSpec eventSpecList : ['$2' | '$3'] .
+eventSpecList -> '$empty' : [] .
+
+eventSpec -> observedEvent : merge_eventSpec('$1') .
+
+%% at-most-once per item except for propertyParm
+terminationStateParm -> serviceStates : {serviceState, '$1'} .
+terminationStateParm -> eventBufferControl : {eventBufferControl, '$1'} .
+terminationStateParm -> propertyParm : {propertyParm, '$1'} .
+
+serviceStates -> 'ServiceStatesToken' 'EQUAL' serviceStatesValue : '$3'.
+
+serviceStatesValue -> 'TestToken' : test .
+serviceStatesValue -> 'OutOfSvcToken' : outOfSvc .
+serviceStatesValue -> 'InSvcToken' : inSvc .
+
+eventBufferControl -> 'BufferToken' 'EQUAL' eventBufferControlValue : '$3' .
+
+eventBufferControlValue -> 'OffToken' : off .
+eventBufferControlValue -> 'LockStepToken' : lockStep .
+
+muxDescriptor -> 'MuxToken' 'EQUAL' muxType terminationIDList :
+ #'MuxDescriptor'{muxType = '$3',
+ termList = '$4'} .
+
+muxType -> safeToken : ensure_muxType('$1') .
+
+streamID -> safeToken : ensure_streamID('$1') .
+
+pkgdName -> safeToken : ensure_pkgdName('$1') .
+
+eventsDescriptor -> 'EventsToken' :
+ #'EventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+eventsDescriptor -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' requestedEvent requestedEvents 'RBRKT' :
+ #'EventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+requestedEvents -> 'COMMA' requestedEvent requestedEvents : ['$2' | '$3'] .
+requestedEvents -> '$empty' : [] .
+
+requestedEvent -> pkgdName requestedEventBody :
+ setelement(#'RequestedEvent'.pkgdName, '$2', '$1') .
+
+requestedEventBody -> 'LBRKT' eventParameter eventParameters 'RBRKT' :
+ merge_eventParameters(['$2' | '$3']) .
+requestedEventBody -> '$empty' : #'RequestedEvent'{evParList = []} .
+
+
+notifyRegulated -> 'NotifyRegulatedToken' :
+ #'RegulatedEmbeddedDescriptor'{} .
+notifyRegulated -> 'NotifyRegulatedToken' 'LBRKT' embedWithSig 'RBRKT' :
+ make_RegulatedEmbeddedDescriptor('$3') .
+notifyRegulated -> 'NotifyRegulatedToken' 'LBRKT' embedNoSig 'RBRKT' :
+ make_RegulatedEmbeddedDescriptor('$3') .
+
+notifyBehaviour -> 'NotifyImmediateToken' : {notifyImmediate, 'NULL'} .
+notifyBehaviour -> 'NeverNotifyToken' : {neverNotify, 'NULL'} .
+notifyBehaviour -> notifyRegulated : {notifyRegulated, '$1'} .
+
+eventParameters -> 'COMMA' eventParameter eventParameters :
+ ['$2' | '$3'] .
+eventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+eventParameter -> 'KeepActiveToken' : keepActive .
+eventParameter -> embedWithSig : '$1'.
+eventParameter -> embedNoSig : '$1'.
+eventParameter -> eventDM : '$1'.
+eventParameter -> eventStreamOrOther : '$1'.
+eventParameter -> notifyBehaviour : {notifyBehaviour, '$1'}.
+eventParameter -> 'ResetEventsDescriptorToken' : resetEventsDescriptor .
+
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor
+ 'COMMA' embedFirst 'RBRKT'
+ : {embed, '$3', '$5'} .
+embedWithSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {embed, '$3', asn1_NOVALUE} .
+
+embedNoSig -> 'EmbedToken' 'LBRKT' embedFirst 'RBRKT'
+ : {embed, asn1_NOVALUE, '$3'} .
+
+embedFirst -> 'EventsToken' :
+ #'SecondEventsDescriptor'{requestID = asn1_NOVALUE,
+ eventList = []} .
+embedFirst -> 'EventsToken' 'EQUAL' requestID
+ 'LBRKT' secondRequestedEvent secondRequestedEvents 'RBRKT' :
+ #'SecondEventsDescriptor'{requestID = '$3',
+ eventList = ['$5' | '$6']} .
+
+secondRequestedEvents -> 'COMMA' secondRequestedEvent secondRequestedEvents : ['$2' | '$3'] .
+secondRequestedEvents -> '$empty' : [] .
+
+%% at-most-once of each
+secondRequestedEvent -> pkgdName secondRequestedEventBody
+ : setelement(#'SecondRequestedEvent'.pkgdName, '$2', '$1') .
+
+secondRequestedEventBody -> 'LBRKT' secondEventParameter secondEventParameters 'RBRKT'
+ : merge_secondEventParameters(['$2' | '$3']) .
+secondRequestedEventBody -> '$empty' : #'SecondRequestedEvent'{evParList = []} .
+
+secondEventParameters -> 'COMMA' secondEventParameter secondEventParameters : ['$2' | '$3'] .
+secondEventParameters -> '$empty' : [] .
+
+%% at-most-once each of embedOrKeepActive , eventDM or eventStream
+secondEventParameter -> 'KeepActiveToken' : keepActive .
+secondEventParameter -> embedSig : '$1' .
+secondEventParameter -> eventDM : '$1' .
+secondEventParameter -> eventStreamOrOther : '$1' .
+secondEventParameter -> notifyBehaviour : {notifyBehaviour, '$1'}.
+secondEventParameter -> 'ResetEventsDescriptorToken' : resetEventsDescriptor .
+
+embedSig -> 'EmbedToken' 'LBRKT' signalsDescriptor 'RBRKT'
+ : {second_embed, '$3'} .
+
+eventStreamOrOther -> eventParameterName parmValue :
+ select_stream_or_other('$1', '$2') .
+
+eventParameterName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+eventDM -> 'DigitMapDescriptorToken' :
+ ensure_eventDM('$1') .
+
+%% H248S-IG (IGv11)
+signalsDescriptor -> 'SignalsToken' 'LBRKT' signalParm signalParms 'RBRKT' :
+ ['$3' | '$4'] .
+signalsDescriptor -> 'SignalsToken' : [] .
+
+signalParms -> 'COMMA' signalParm signalParms : [ '$2' | '$3'] .
+signalParms -> '$empty' : [] .
+
+signalParm -> signalList : {seqSigList, '$1'} .
+signalParm -> signalRequest : {signal, '$1'} .
+
+signalRequest -> signalName 'LBRKT' sigParameter sigParameters 'RBRKT'
+ : merge_signalRequest('$1', ['$3' | '$4']).
+signalRequest -> signalName : merge_signalRequest('$1', []).
+
+sigParameters -> 'COMMA' sigParameter sigParameters : ['$2' | '$3'] .
+sigParameters -> '$empty' : [] .
+
+%% sigParameter = sigStream / sigSignalType / sigDuration / sigOther /
+%% notifyCompletion / KeepActiveToken /
+%% direction / sigRequestID
+%% sigStream = StreamToken EQUAL StreamID
+%% sigOther = sigParameterName parmValue
+%% sigParameterName = NAME
+%% sigSignalType = SignalTypeToken EQUAL signalType
+%% signalType = (OnOffToken / TimeOutToken / BriefToken)
+%% sigDuration = DurationToken EQUAL UINT16
+%% notifyCompletion = NotifyCompletionToken EQUAL (LBRKT
+%% notificationReason *(COMMA notificationReason)
+%% RBRKT)
+%%
+%% notificationReason = ( TimeOutToken / InterruptByEventToken /
+%% InterruptByNewSignalsDescrToken /
+%% OtherReasonToken )
+%% sigDirection = DirectionToken EQUAL direction
+%% sigRequestID = RequestIDToken EQUAL RequestID
+%% sigIntsigDelay = IntsigDelayToken EQUAL UINT16
+
+sigParameter -> 'StreamToken' 'EQUAL' streamID :
+ {stream, '$3'}.
+sigParameter -> 'SignalTypeToken' 'EQUAL' signalType :
+ {signal_type, '$3'} .
+sigParameter -> 'DurationToken' 'EQUAL' safeToken :
+ {duration, ensure_uint16('$3')} .
+sigParameter -> 'NotifyCompletionToken' 'EQUAL'
+ 'LBRKT' notificationReason notificationReasons 'RBRKT' :
+ {notify_completion, ['$4' | '$5']} .
+sigParameter -> 'KeepActiveToken' : keepActive .
+sigParameter -> 'DirectionToken' 'EQUAL' direction :
+ {direction, '$3'} .
+sigParameter -> 'RequestIDToken' 'EQUAL' requestID :
+ {requestId, '$3'} .
+sigParameter -> 'IntsigDelayToken' 'EQUAL' safeToken :
+ {intersigDelay, ensure_uint16('$3')} .
+sigParameter -> safeToken parmValue :
+ {other, ensure_NAME('$1'), '$2'}.
+
+signalType -> 'OnOffToken' : onOff.
+signalType -> 'TimeOutToken' : timeOut.
+signalType -> 'BriefToken' : brief.
+
+direction -> 'ExternalToken' : external .
+direction -> 'InternalToken' : internal .
+direction -> 'BothToken' : both .
+
+notificationReasons -> 'COMMA' notificationReason notificationReasons : ['$2' | '$3'] .
+notificationReasons -> '$empty' : [] .
+
+notificationReason -> 'TimeOutToken' : onTimeOut .
+notificationReason -> 'InterruptByEventToken' : onInterruptByEvent .
+notificationReason -> 'InterruptByNewSignalsDescrToken' : onInterruptByNewSignalDescr .
+notificationReason -> 'OtherReasonToken' : otherReason .
+notificationReason -> 'IterationToken' : iteration .
+
+signalList -> 'SignalListToken' 'EQUAL' signalListId
+ 'LBRKT' signalListParm signalListParms 'RBRKT'
+ : #'SeqSigList'{id = ensure_uint16('$3'),
+ signalList = ['$5' | '$6']} .
+
+signalListParms -> 'COMMA' signalListParm signalListParms :
+ ['$2' | '$3'] .
+signalListParms -> '$empty' : [] .
+
+signalListId -> safeToken : ensure_uint16('$1') .
+
+%% exactly once signalType,
+%% at most once duration and every signal parameter
+signalListParm -> signalRequest : '$1'.
+
+signalName -> pkgdName : '$1'.
+
+observedEventsDescriptor -> 'ObservedEventsToken' 'EQUAL' requestID
+ 'LBRKT' observedEvent observedEvents 'RBRKT'
+ : #'ObservedEventsDescriptor'{requestId = '$3',
+ observedEventLst = ['$5' | '$6']} .
+
+observedEvents -> 'COMMA' observedEvent observedEvents : ['$2' | '$3'] .
+observedEvents -> '$empty' : [] .
+
+%%time per event, because it might be buffered
+
+observedEvent -> timeStamp optSep 'COLON' optSep pkgdName observedEventBody :
+ merge_observed_event('$6', '$5', '$1') .
+observedEvent -> optSep pkgdName observedEventBody :
+ merge_observed_event('$3', '$2', asn1_NOVALUE) .
+
+observedEventBody -> 'LBRKT' observedEventParameter
+ observedEventParameters 'RBRKT'
+ : ['$2' | '$3'] .
+observedEventBody -> '$empty' : [] .
+
+observedEventParameters -> 'COMMA' observedEventParameter observedEventParameters : ['$2' | '$3'] .
+observedEventParameters -> '$empty' : [] .
+
+%%at-most-once eventStream, every eventParameterName at most once
+observedEventParameter -> eventStreamOrOther : '$1' .
+
+requestID -> safeToken : ensure_requestID('$1') .
+
+%% Deprecated as of Corr 1
+modemDescriptor -> 'ModemToken' 'EQUAL' modemType optPropertyParms .
+modemDescriptor -> 'ModemToken' 'LSBRKT' modemType modemTypeList 'RSBRKT'
+ optPropertyParms.
+modemTypeList -> 'COMMA' modemType modemTypeList.
+modemTypeList -> '$empty'.
+modemType -> safeToken.
+
+optPropertyParms -> 'LBRKT' propertyParm propertyParmList 'RBRKT' :
+ ['$2' | '$3'] .
+optPropertyParms -> '$empty' : [] .
+
+propertyParms -> propertyParm propertyParmList : ['$1' | '$2'] .
+propertyParmList -> 'COMMA' propertyParm propertyParmList : ['$2' | '$3'] .
+propertyParmList -> '$empty' : [] .
+
+% parmName -> safeToken : ensure_NAME('$1') .
+
+%% The DigitMapDescriptorToken is specially treated by the scanner
+digitMapDescriptor -> 'DigitMapDescriptorToken' :
+ ensure_DMD('$1') .
+
+%% each parameter at-most-once, except auditItem
+%% at most one of either serviceChangeAddress or serviceChangeMgcId but
+%% not both. serviceChangeMethod and serviceChangeReason are REQUIRED
+serviceChangeDescriptor -> 'ServicesToken'
+ 'LBRKT' serviceChangeParm
+ serviceChangeParms 'RBRKT' :
+ merge_ServiceChangeParm(['$3' | '$4']) .
+
+serviceChangeParms -> 'COMMA' serviceChangeParm serviceChangeParms :
+ ['$2' | '$3'] .
+serviceChangeParms -> '$empty' : [] .
+
+serviceChangeParm -> serviceChangeMethod : {method, '$1'} .
+serviceChangeParm -> serviceChangeReason : {reason, '$1'} .
+serviceChangeParm -> serviceChangeDelay : {delay, '$1'} .
+serviceChangeParm -> serviceChangeAddress : {address, '$1'} .
+serviceChangeParm -> serviceChangeProfile : {profile, '$1'} .
+serviceChangeParm -> extension : {extension, '$1'} .
+serviceChangeParm -> timeStamp : {time_stamp, '$1'} .
+serviceChangeParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+serviceChangeParm -> serviceChangeVersion : {version, '$1'} .
+serviceChangeParm -> 'ServiceChangeIncompleteToken' : incomplete . % v3
+serviceChangeParm -> auditItem : {audit_item, '$1'} . % v2
+
+serviceChangeMethod -> 'MethodToken' 'EQUAL' safeToken :
+ ensure_serviceChangeMethod('$3') .
+
+serviceChangeReason -> 'ReasonToken' 'EQUAL' value : ['$3'] .
+
+serviceChangeDelay -> 'DelayToken' 'EQUAL' safeToken : ensure_uint32('$3').
+
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' mId : '$3' .
+serviceChangeAddress -> 'ServiceChangeAddressToken' 'EQUAL' portNumber :
+ {portNumber, '$3'} .
+
+serviceChangeMgcId -> 'MgcIdToken' 'EQUAL' mId : '$3' .
+
+serviceChangeProfile -> 'ProfileToken' 'EQUAL' safeToken : ensure_profile('$3').
+
+serviceChangeVersion -> 'VersionToken' 'EQUAL' safeToken : ensure_version('$3') .
+
+extension -> extensionParameter parmValue
+ : setelement(#'PropertyParm'.name, '$2', '$1') .
+
+%% at most once. Version is REQUIRED on first ServiceChange response
+%% at most of either serviceChangeAddress or serviceChangeMgcId but not both
+serviceChangeReplyDescriptor -> 'ServicesToken'
+ 'LBRKT' servChgReplyParm
+ servChgReplyParms 'RBRKT' :
+ merge_ServiceChangeResParm(['$3' | '$4']) .
+
+servChgReplyParms -> 'COMMA' servChgReplyParm servChgReplyParms :
+ ['$2' | '$3'] .
+servChgReplyParms -> '$empty' : [] .
+
+servChgReplyParm -> serviceChangeAddress : {address, '$1'} .
+servChgReplyParm -> serviceChangeMgcId : {mgc_id, '$1'} .
+servChgReplyParm -> serviceChangeProfile : {profile, '$1'} .
+servChgReplyParm -> serviceChangeVersion : {version, '$1'} .
+servChgReplyParm -> timeStamp : {time_stamp,'$1'} .
+
+packagesDescriptor -> 'PackagesToken' 'LBRKT' packagesItem
+ packagesItems 'RBRKT'
+ : ['$3' | '$4'] .
+
+packagesItems -> 'COMMA' packagesItem packagesItems : ['$2' | '$3'] .
+packagesItems -> '$empty' : [] .
+
+packagesItem -> safeToken : ensure_packagesItem('$1') .
+
+timeStamp -> TimeStampToken : ensure_timeStamp('$1') .
+
+statisticsDescriptor -> 'StatsToken'
+ 'LBRKT' statisticsParameter
+ statisticsParameters 'RBRKT'
+ : ['$3' | '$4'] .
+
+statisticsParameters -> 'COMMA' statisticsParameter statisticsParameters : ['$2' | '$3'] .
+statisticsParameters -> '$empty' : [] .
+
+%%at-most-once per item
+statisticsParameter -> pkgdName :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = asn1_NOVALUE} .
+statisticsParameter -> pkgdName 'EQUAL' value :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = ['$3']} .
+statisticsParameter -> pkgdName 'EQUAL' 'LSBRKT' value valueList 'RSBRKT' :
+ #'StatisticsParameter'{statName = '$1',
+ statValue = ['$4' | '$5']} .
+
+
+topologyDescriptor -> 'TopologyToken' 'LBRKT'
+ topologyDescComp topologyDescCompList 'RBRKT' :
+ merge_topologyDescriptor(['$3' | '$4']) .
+
+topologyDescComp -> terminationID : {tid, '$1'} .
+topologyDescComp -> eventStream : {sid, '$1'} .
+topologyDescComp -> topologyDirection : '$1' .
+
+topologyDescCompList -> '$empty' : [] .
+topologyDescCompList -> 'COMMA' topologyDescComp topologyDescCompList :
+ ['$2' | '$3'] .
+
+topologyDirection -> 'BothwayToken' : {direction, bothway} .
+topologyDirection -> 'IsolateToken' : {direction, isolate} .
+topologyDirection -> 'OnewayToken' : {direction, oneway} .
+topologyDirection -> 'OnewayExternalToken' : {direction_ext, onewayexternal} .
+topologyDirection -> 'OnewayBothToken' : {direction_ext, onewayboth} .
+
+iepsValue -> 'IEPSToken' 'EQUAL' onOrOff : '$3' .
+
+emergencyValue -> 'EmergencyValueToken' 'EQUAL' 'EmergencyToken' : true .
+emergencyValue -> 'EmergencyValueToken' 'EQUAL' 'EmergencyOffToken' : false .
+
+priority -> 'PriorityToken' 'EQUAL' safeToken : ensure_uint16('$3') .
+
+extensionParameter -> safeToken : ensure_extensionParameter('$1') .
+
+value -> 'QuotedChars' : ensure_value('$1') .
+value -> safeToken : ensure_value('$1').
+
+safeToken -> safeToken2 : make_safe_token('$1') .
+
+safeToken2 -> 'SafeChars' : '$1' .
+%% BMK BMK safeToken2 -> 'AddToken' : '$1' .
+safeToken2 -> 'AuditToken' : '$1' .
+safeToken2 -> 'AuditCapToken' : '$1' .
+safeToken2 -> 'AuditValueToken' : '$1' .
+safeToken2 -> 'AuthToken' : '$1' .
+safeToken2 -> 'BothToken' : '$1' . % v3
+%% v3-safeToken2 -> 'BothwayToken' : '$1' .
+safeToken2 -> 'BriefToken' : '$1' .
+%% v3-safeToken2 -> 'BufferToken' : '$1' .
+safeToken2 -> 'CtxToken' : '$1' .
+%% v3-safeToken2 -> 'ContextAttrToken' : '$1' . % v3
+safeToken2 -> 'ContextAuditToken' : '$1' .
+%% v3-safeToken2 -> 'ContextListToken' : '$1' . % v3
+%% v2-safeToken2 -> 'DigitMapToken' : '$1' .
+%% safeToken2 -> 'DigitMapDescriptorToken' : '$1' .
+%% v3-
+safeToken2 -> 'DirectionToken' : '$1' . % v3
+safeToken2 -> 'DiscardToken' : '$1' .
+safeToken2 -> 'DisconnectedToken' : '$1' .
+safeToken2 -> 'DelayToken' : '$1' .
+safeToken2 -> 'DurationToken' : '$1' .
+safeToken2 -> 'EmbedToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyToken' : '$1' .
+%% BMK BMK safeToken2 -> 'EmergencyOffToken' : '$1' .
+safeToken2 -> 'ErrorToken' : '$1' .
+%% v2-safeToken2 -> 'EventBufferToken' : '$1' .
+%% v2-safeToken2 -> 'EventsToken' : '$1' .
+%% v3-safeToken2 -> 'ExternalToken' : '$1' . % v3
+safeToken2 -> 'FailoverToken' : '$1' .
+safeToken2 -> 'ForcedToken' : '$1' .
+safeToken2 -> 'GracefulToken' : '$1' .
+safeToken2 -> 'H221Token' : '$1' .
+safeToken2 -> 'H223Token' : '$1' .
+safeToken2 -> 'H226Token' : '$1' .
+safeToken2 -> 'HandOffToken' : '$1' .
+%% v3-safeToken2 -> 'IEPSToken' : '$1' . % v3
+safeToken2 -> 'ImmAckRequiredToken' : '$1' .
+safeToken2 -> 'InactiveToken' : '$1' .
+%% v3-safeToken2 -> 'InternalToken' : '$1' . % v3
+safeToken2 -> 'InterruptByEventToken' : '$1' .
+safeToken2 -> 'InterruptByNewSignalsDescrToken' : '$1' .
+%% v3-safeToken2 -> 'IsolateToken' : '$1' .
+safeToken2 -> 'InSvcToken' : '$1' .
+safeToken2 -> 'KeepActiveToken' : '$1' .
+%% safeToken2 -> 'LocalToken' : '$1' .
+%% safeToken2 -> 'LocalDescriptorToken' : '$1' .
+safeToken2 -> 'LocalControlToken' : '$1' .
+safeToken2 -> 'LoopbackToken' : '$1' .
+safeToken2 -> 'LockStepToken' : '$1' .
+%% v2-safeToken2 -> 'MediaToken' : '$1' .
+%% safeToken2 -> 'MegacopToken' : '$1' .
+safeToken2 -> 'MethodToken' : '$1' .
+safeToken2 -> 'MgcIdToken' : '$1' .
+%% v3-safeToken2 -> 'ModeToken' : '$1' .
+%% BMK BMK safeToken2 -> 'ModifyToken' : '$1' .
+%% v2-safeToken2 -> 'ModemToken' : '$1' .
+%% BMK BMK safeToken2 -> 'MoveToken' : '$1' .
+%% safeToken2 -> 'MtpToken' : '$1' .
+%% safeToken2 -> 'MtpAddressToken' : '$1' .
+%% v2-safeToken2 -> 'MuxToken' : '$1' .
+safeToken2 -> 'NotifyToken' : '$1' .
+safeToken2 -> 'NotifyCompletionToken' : '$1' .
+safeToken2 -> 'Nx64Token' : '$1' .
+%% v2-safeToken2 -> 'ObservedEventsToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayExternalToken' : '$1' .
+%% v3-safeToken2 -> 'OnewayBothToken' : '$1' .
+safeToken2 -> 'OffToken' : '$1' .
+safeToken2 -> 'OnToken' : '$1' .
+safeToken2 -> 'OnOffToken' : '$1' .
+safeToken2 -> 'OutOfSvcToken' : '$1' .
+safeToken2 -> 'OtherReasonToken' : '$1' .
+%% v2-safeToken2 -> 'PackagesToken' : '$1' .
+safeToken2 -> 'PendingToken' : '$1' .
+%% BMK BMK safeToken2 -> 'PriorityToken' : '$1' .
+safeToken2 -> 'ProfileToken' : '$1' .
+safeToken2 -> 'ReasonToken' : '$1' .
+safeToken2 -> 'RecvonlyToken' : '$1' .
+safeToken2 -> 'ReplyToken' : '$1' .
+%% v3-
+safeToken2 -> 'RequestIDToken' : '$1' . % v3
+safeToken2 -> 'ResponseAckToken' : '$1' .
+safeToken2 -> 'RestartToken' : '$1' .
+%% safeToken2 -> 'RemoteToken' : '$1' .
+%% safeToken2 -> 'RemoteDescriptorToken' : '$1' .
+%% v3-safeToken2 -> 'ReservedGroupToken' : '$1' .
+%% v3-safeToken2 -> 'ReservedValueToken' : '$1' .
+safeToken2 -> 'SendonlyToken' : '$1' .
+safeToken2 -> 'SendrecvToken' : '$1' .
+safeToken2 -> 'ServicesToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceStatesToken' : '$1' .
+safeToken2 -> 'ServiceChangeToken' : '$1' .
+%% v3-safeToken2 -> 'ServiceChangeIncompleteToken' : '$1' . % v3
+safeToken2 -> 'ServiceChangeAddressToken' : '$1' .
+safeToken2 -> 'SignalListToken' : '$1' .
+%% v2-safeToken2 -> 'SignalsToken' : '$1' .
+safeToken2 -> 'SignalTypeToken' : '$1' .
+%% v2-safeToken2 -> 'StatsToken' : '$1' .
+safeToken2 -> 'StreamToken' : '$1' .
+%% BMK BMK safeToken2 -> 'SubtractToken' : '$1' .
+safeToken2 -> 'SynchISDNToken' : '$1' .
+safeToken2 -> 'TerminationStateToken' : '$1' .
+safeToken2 -> 'TestToken' : '$1' .
+safeToken2 -> 'TimeOutToken' : '$1' .
+%% BMK BMK safeToken2 -> 'TopologyToken' : '$1' .
+safeToken2 -> 'TransToken' : '$1' .
+safeToken2 -> 'V18Token' : '$1' .
+safeToken2 -> 'V22Token' : '$1' .
+safeToken2 -> 'V22bisToken' : '$1' .
+safeToken2 -> 'V32Token' : '$1' .
+safeToken2 -> 'V32bisToken' : '$1' .
+safeToken2 -> 'V34Token' : '$1' .
+safeToken2 -> 'V76Token' : '$1' .
+safeToken2 -> 'V90Token' : '$1' .
+safeToken2 -> 'V91Token' : '$1' .
+safeToken2 -> 'VersionToken' : '$1' .
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("megaco_text_parser_v3.hrl").
+
+
diff --git a/lib/megaco/src/text/megaco_text_scanner.erl b/lib/megaco/src/text/megaco_text_scanner.erl
new file mode 100644
index 0000000000..8559941e5f
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_scanner.erl
@@ -0,0 +1,869 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose : Scanner for text encoded Megaco/H.248 messages
+%%----------------------------------------------------------------------
+
+-module('megaco_text_scanner').
+
+-export([scan/1, skip_sep_chars/2]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/src/engine/megaco_message_internal.hrl").
+-include("megaco_text_tokens.hrl").
+
+-define(LOWER1(Char),
+ if
+ (Char >= $A) andalso (Char =< $Z) ->
+ Char - ($A - $a);
+ true ->
+ Char
+ end).
+
+%% This is used when we _know_ it to be upper case
+-define(LOWER2(Char), Char - ($A - $a)).
+
+scan(Bin) when is_binary(Bin) ->
+ Chars = erlang:binary_to_list(Bin),
+ tokens1(Chars, 1, []);
+scan(Chars) when is_list(Chars) ->
+ tokens1(Chars, 1, []).
+
+%% As long as we dont know the version, we will loop in this function
+tokens1(Chars, Line, Acc) ->
+ case any_chars(Chars, Line, 1) of
+ {token, Token, [], LatestLine} ->
+ %% We got to the end without actually getting a version token.
+ Tokens = [{endOfMessage, LatestLine, endOfMessage}, Token | Acc],
+ {error, no_version_found, lists:reverse(Tokens), Line};
+
+ %% -- Version token for version 1 --
+ {token, {'SafeChars',_,"!/1"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 1, [Token | Acc]);
+
+ {token, {'SafeChars',_,"megaco/1"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 1, [Token | Acc]);
+
+
+ %% -- Version token for version 2 --
+ {token, {'SafeChars',_,"!/2"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 2, [Token | Acc]);
+
+ {token, {'SafeChars',_,"megaco/2"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 2, [Token | Acc]);
+
+
+ %% -- Version token for version 3 --
+ {token, {'SafeChars',_,"!/3"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 3, [Token | Acc]);
+
+ {token, {'SafeChars',_,"megaco/3"} = Token, Rest, LatestLine} ->
+ tokens2(Rest, LatestLine, 3, [Token | Acc]);
+
+
+ %% -- Version token for version X --
+ {token, {'SafeChars',_,[$!,$/| Vstr]} = Token, Rest, LatestLine} ->
+ case guess_version(Vstr) of
+ {ok, V} ->
+ tokens2(Rest, LatestLine, V, [Token | Acc]);
+ {error, Reason} ->
+ {error, Reason, LatestLine}
+ end;
+
+ {token, {'SafeChars',_,[$m,$e,$g,$a,$c,$o,$/|Vstr]} = Token, Rest, LatestLine} ->
+ case guess_version(Vstr) of
+ {ok, V} ->
+ tokens2(Rest, LatestLine, V, [Token | Acc]);
+ {error, Reason} ->
+ {error, Reason, LatestLine}
+ end;
+
+ %% -- Other tokens --
+ {token, Token, Rest, LatestLine} ->
+ tokens1(Rest, LatestLine, [Token | Acc]);
+
+ {bad_token, Token, _Rest, _LatestLine} ->
+ {error, {bad_token, [Token, Acc]}, Line}
+ end.
+
+tokens2(Chars, Line0, Version, Tokens0) ->
+ case tokens3(Chars, Line0, Tokens0, Version) of
+ {ok, Tokens, Line} ->
+ {ok, Tokens, Version, Line};
+ Error ->
+ Error
+ end.
+
+tokens3(Chars, Line, Acc, Version) ->
+ %% d("tokens2 -> entry with"
+ %% "~n Chars: ~s"
+ %% "~n Line: ~p", [Chars, Line]),
+ case any_chars(Chars, Line, Version) of
+ {token, Token, [], LatestLine} ->
+ %% d("tokens2 -> Token: ~n~p", [Token]),
+ Tokens = [{endOfMessage, LatestLine, endOfMessage}, Token | Acc],
+ {ok, lists:reverse(Tokens), Line};
+
+ {token, Token, Rest, LatestLine} ->
+ %% d("tokens2 -> Token: ~n~p", [Token]),
+ tokens3(Rest, LatestLine, [Token | Acc], Version);
+
+ {bad_token, Token, _Rest, _LatestLine} ->
+ {error, {bad_token, [Token, Acc]}, Line}
+ end.
+
+
+guess_version([C]) when (48 =< C) and (C =< 57) ->
+ {ok, C-48};
+guess_version(Str) when is_list(Str) ->
+ case (catch list_to_integer(Str)) of
+ I when is_integer(I) ->
+ {ok, I};
+ _ ->
+ {error, {invalid_version, Str}}
+ end.
+
+
+%% Returns {token, Token, Rest, LatestLine}
+%% Returns {bad_token, Token, Rest, LatestLine}
+any_chars([Char | Rest], Line, Version) ->
+ case ?classify_char(Char) of
+ safe_char_upper ->
+ safe_chars(Rest, [Char], [?LOWER2(Char)], Line, Version);
+ safe_char ->
+ safe_chars(Rest, [Char], [Char], Line, Version);
+ rest_char ->
+ case Char of
+ ?SemiColonToken ->
+ comment_chars(Rest, Line);
+ _ ->
+ rest_chars(Rest, [Char], Line)
+ end;
+ double_quote ->
+ quoted_chars(Rest, [], Line);
+ white_space ->
+ sep_chars(Rest, Line);
+ end_of_line ->
+ sep_chars(Rest, Line);
+ bad_char ->
+ %% {bad_token, {'SEP', Line, Char}, Rest, Line}
+ {bad_token, {'AnyChars', Line, Char}, Rest, Line}
+ end;
+any_chars([] = All, Line, _Version) ->
+ {token, {'SEP', Line, end_of_input}, All, Line}.
+
+comment_chars([Char | Rest], Line) ->
+ case ?classify_char(Char) of
+ safe_char_upper ->
+ comment_chars(Rest, Line);
+ safe_char ->
+ comment_chars(Rest, Line);
+ rest_char ->
+ comment_chars(Rest, Line);
+ white_space ->
+ comment_chars(Rest, Line);
+ end_of_line ->
+ sep_chars(Rest, Line);
+ _ when Char =:= 22 ->
+ comment_chars(Rest, Line);
+ _ ->
+ %% {bad_token, {'SEP', Line, Char}, Rest, Line}
+ {bad_token, {'CommentChars', Line, Char}, Rest, Line}
+ end;
+comment_chars([] = All, Line) ->
+ {token, {'SEP', Line}, All, Line}.
+
+sep_chars([Char | Rest] = All, Line) ->
+ case ?classify_char(Char) of
+ safe_char_upper ->
+ {token, {'SEP', Line}, All, Line};
+ safe_char ->
+ {token, {'SEP', Line}, All, Line};
+ rest_char when Char =:= ?SemiColonToken ->
+ comment_chars(Rest, Line);
+ rest_char ->
+ rest_chars(Rest, [Char], Line);
+ white_space ->
+ sep_chars(Rest, Line);
+ end_of_line ->
+ sep_chars(Rest, Line + 1);
+ _ ->
+ %% {bad_token, {'SEP', Line, Char}, Rest, Line}
+ {bad_token, {'SepChars', Line, Char}, Rest, Line}
+ end;
+sep_chars([] = All, Line) ->
+ {token, {'SEP', Line}, All, Line}.
+
+rest_chars(Rest, [?ColonToken], Line) ->
+ {token, {'COLON', Line}, Rest, Line};
+rest_chars(Rest, [AccChar], Line) ->
+ TokenTag =
+ case AccChar of
+ ?EqualToken -> 'EQUAL';
+ ?NequalToken -> 'NEQUAL';
+ ?LesserToken -> 'LESSER';
+ ?GreaterToken -> 'GREATER';
+ ?LbrktToken -> 'LBRKT';
+ ?RbrktToken -> 'RBRKT';
+ ?LsbrktToken -> 'LSBRKT';
+ ?RsbrktToken -> 'RSBRKT';
+ ?LparToken -> 'LPAR';
+ ?RparToken -> 'RPAR';
+ ?VbarToken -> 'VBAR';
+ ?CommaToken -> 'COMMA'
+ end,
+ {Rest2, Line2} = skip_sep_chars(Rest, Line),
+ {token, {TokenTag, Line}, Rest2, Line2}.
+
+skip_sep_chars([Char | Rest] = All, Line) ->
+ case ?classify_char2(Char) of
+ rest_char when Char =:= ?SemiColonToken ->
+ skip_comment_chars(Rest, Line);
+ white_space ->
+ skip_sep_chars(Rest, Line);
+ end_of_line ->
+ skip_sep_chars(Rest, Line + 1);
+ _ ->
+ {All, Line}
+ end;
+skip_sep_chars([] = All, Line) ->
+ {All, Line}.
+
+skip_comment_chars([Char | Rest] = All, Line) ->
+ case ?classify_char(Char) of
+ safe_char_upper ->
+ skip_comment_chars(Rest, Line);
+ safe_char ->
+ skip_comment_chars(Rest, Line);
+ rest_char ->
+ skip_comment_chars(Rest, Line);
+ double_quote ->
+ skip_comment_chars(Rest, Line);
+ white_space ->
+ skip_comment_chars(Rest, Line);
+ end_of_line ->
+ skip_sep_chars(Rest, Line + 1);
+ _ ->
+ {All, Line}
+ end;
+skip_comment_chars([] = All, Line) ->
+ {All, Line}.
+
+quoted_chars([Char | Rest], Acc, Line) ->
+ case ?classify_char(Char) of
+ safe_char_upper ->
+ quoted_chars(Rest, [Char | Acc], Line);
+ safe_char ->
+ quoted_chars(Rest, [Char | Acc], Line);
+ rest_char ->
+ quoted_chars(Rest, [Char | Acc], Line);
+ white_space ->
+ quoted_chars(Rest, [Char | Acc], Line);
+ double_quote ->
+ {token, {'QuotedChars', Line, lists:reverse(Acc)}, Rest, Line};
+ _ ->
+ {bad_token, {'QuotedChars', Line, Char}, Rest, Line}
+ end;
+quoted_chars([] = All, _Acc, Line) ->
+ {bad_token, {'QuotedChars', Line, end_of_input}, All, Line}.
+
+safe_chars([Char | Rest] = All, Acc, LowerAcc, Line, Version) ->
+ %% d("safe_chars -> entry with"
+ %% "~n Char: ~p"
+ %% "~n LowerAcc: ~p", [Char, LowerAcc]),
+ case ?classify_char3(Char) of
+ safe_char_upper ->
+ safe_chars(Rest, [Char | Acc],
+ [?LOWER2(Char) | LowerAcc], Line, Version);
+ safe_char ->
+ safe_chars(Rest, [Char | Acc], [Char | LowerAcc], Line, Version);
+ _ ->
+ LowerSafeChars = lists:reverse(LowerAcc),
+ TokenTag = select_token(LowerSafeChars, Version),
+ SafeChars = lists:reverse(Acc),
+ case TokenTag of
+ 'MtpToken' ->
+ %% 'MtpToken' 'LBRKT' OctetString 'RBRKT'
+ special_chars(All, LowerSafeChars, Line, TokenTag);
+ 'LocalToken' ->
+ %% 'LocalToken' 'LBRKT' OctetString 'RBRKT'
+ special_chars(All, SafeChars, Line, TokenTag);
+ 'RemoteToken' ->
+ %% 'RemoteToken' 'LBRKT' OctetString 'RBRKT'
+ special_chars(All, SafeChars, Line, TokenTag);
+ 'DigitMapToken' ->
+ %% 'DigitMapToken'
+ %% 'DigitMapToken' 'EQUAL' Name
+ %% 'DigitMapToken' 'EQUAL' Name 'LBRKT' Value 'RBRKT'
+ %% 'DigitMapToken' 'EQUAL' 'LBRKT' Value 'RBRKT'
+ %% 'DigitMapToken' 'LBRKT' Value 'RBRKT'
+ special_chars(All, LowerSafeChars, Line, TokenTag);
+ _ ->
+ {token, {TokenTag, Line, LowerSafeChars}, All, Line}
+ end
+ end;
+safe_chars([] = All, _Acc, LowerAcc, Line, Version) ->
+ LowerSafeChars = lists:reverse(LowerAcc),
+ TokenTag = select_token(LowerSafeChars, Version),
+ %%SafeChars = lists:reverse(Acc),
+ {token, {TokenTag, Line, LowerSafeChars}, All, Line}.
+
+collect_safe_chars([Char | Rest] = All, LowerAcc) ->
+ case ?classify_char3(Char) of
+ safe_char_upper ->
+ collect_safe_chars(Rest, [?LOWER2(Char) | LowerAcc]);
+ safe_char ->
+ collect_safe_chars(Rest, [Char | LowerAcc]);
+ _ ->
+ {All, lists:reverse(LowerAcc)}
+ end;
+collect_safe_chars([] = Rest, LowerAcc) ->
+ {Rest, lists:reverse(LowerAcc)}.
+
+special_chars(All, SafeChars, Line, TokenTag) ->
+ {Rest, Line2} = skip_sep_chars(All, Line),
+ case Rest of
+ [?LbrktToken | Rest2] ->
+ {token, {'OctetString', _, OctetString}, Rest4, Line4} =
+ octet_string(Rest2, Line2),
+ case Rest4 of
+ [?RbrktToken | Rest6] ->
+ Token =
+ case TokenTag of
+ 'MtpToken' ->
+ %% 'MtpToken' 'LBRKT' OctetString 'RBRKT'
+ {'MtpAddressToken', Line, OctetString};
+ 'LocalToken' ->
+ %% 'LocalToken' 'LBRKT' OctetString 'RBRKT'
+ PGs = property_groups(OctetString),
+ {'LocalDescriptorToken', Line, PGs};
+ 'RemoteToken' ->
+ %% 'RemoteToken' 'LBRKT' OctetString 'RBRKT'
+ PGs = property_groups(OctetString),
+ {'RemoteDescriptorToken', Line, PGs};
+ 'DigitMapToken' ->
+ %% 'DigitMapToken' 'LBRKT' OctetString 'RBRKT'
+ DMV = digit_map_value(OctetString),
+ DMD = #'DigitMapDescriptor'{digitMapValue = DMV},
+ {'DigitMapDescriptorToken', Line, DMD}
+ end,
+ {token, Token, Rest6, Line4};
+ _ when TokenTag =:= 'DigitMapToken' ->
+ %% 'DigitMapToken'
+ {token, {'DigitMapToken', Line, SafeChars}, All, Line};
+ _ ->
+ {token, {'SafeChars', Line, SafeChars}, All, Line}
+ end;
+ [?EqualToken | Rest2] when TokenTag =:= 'DigitMapToken' ->
+ {Rest3, Line3} = skip_sep_chars(Rest2, Line2),
+ {Rest4, DigitMapName} = collect_safe_chars(Rest3, []),
+ {Rest6, Line6, DMD} =
+ if
+ DigitMapName =:= [] ->
+ {Rest3, Line3, #'DigitMapDescriptor'{}};
+ true ->
+ {Rest5, Line5} = skip_sep_chars(Rest4, Line3),
+ {Rest5, Line5, #'DigitMapDescriptor'{digitMapName = DigitMapName}}
+ end,
+ case Rest6 of
+ [?LbrktToken | Rest7] ->
+ {token, {'OctetString', _, OctetString}, Rest8, Line8} =
+ octet_string(Rest7, Line6),
+ case Rest8 of
+ [?RbrktToken | Rest10] ->
+ %% 'DigitMapToken' 'EQUAL' 'LBRKT' OctetString 'RBRKT'
+ %% 'DigitMapToken' 'EQUAL' Name 'LBRKT' OctetString 'RBRKT'
+ {Rest11, Line11} = skip_sep_chars(Rest10, Line8),
+ DMV = digit_map_value(OctetString),
+ DMD2 = DMD#'DigitMapDescriptor'{digitMapValue = DMV},
+ {token, {'DigitMapDescriptorToken', Line, DMD2}, Rest11, Line11};
+ _ when DMD#'DigitMapDescriptor'.digitMapName /= asn1_NOVALUE ->
+ %% 'DigitMapToken' 'EQUAL' Name
+ {token, {'DigitMapDescriptorToken', Line, DMD}, Rest4, Line3};
+ _ ->
+ %% 'DigitMapToken'
+ {token, {'DigitMapToken', Line, SafeChars}, All, Line}
+ end;
+ _ when DMD#'DigitMapDescriptor'.digitMapName /= asn1_NOVALUE ->
+ %% 'DigitMapToken' 'EQUAL' Name
+ {token, {'DigitMapDescriptorToken', Line, DMD}, Rest4, Line3};
+ _ ->
+ %% 'DigitMapToken'
+ {token, {'DigitMapToken', Line, SafeChars}, All, Line}
+ end;
+ _ when TokenTag =:= 'DigitMapToken' ->
+ %% 'DigitMapToken'
+ {token, {'DigitMapToken', Line, SafeChars}, All, Line};
+ _ ->
+ %% 'DigitMapToken'
+ {token, {'SafeChars', Line, SafeChars}, All, Line}
+ end.
+
+octet_string(Chars, Line) ->
+ {Chars2, Line2} = skip_sep_chars(Chars, Line),
+ Acc = [],
+ {Rest, RevChars, RestLine} = octet_string(Chars2, Acc, Line2),
+ {RevChars2, _} = skip_sep_chars(RevChars, RestLine),
+ OctetString = lists:reverse(RevChars2),
+ {token, {'OctetString', Line, OctetString}, Rest, RestLine}.
+
+
+octet_string([Char | Rest] = All, Acc, Line) ->
+ if
+ (Char =:= ?CrToken) ->
+ octet_string(Rest, [Char | Acc], Line + 1);
+ (Char =:= ?LfToken) ->
+ octet_string(Rest, [Char | Acc], Line + 1);
+ (Char >= 8#1) andalso (Char =< 8#174) ->
+ octet_string(Rest, [Char | Acc], Line);
+ (Char >= 8#176) andalso (Char =< 8#377) ->
+ octet_string(Rest, [Char | Acc], Line);
+ (Char =:= ?BackslashToken) ->
+ case Rest of
+ [?RbrktToken | _Rest2] ->
+ %% OTP-4357
+ octet_string(Rest,
+ [?RbrktToken, ?BackslashToken | Acc], Line);
+ _ ->
+ octet_string(Rest, [Char | Acc], Line)
+ end;
+ true ->
+ {All, Acc, Line}
+ end;
+octet_string([] = All, Acc, Line) ->
+ {All, Acc, Line}.
+
+
+%% digitMapValue = ["T" COLON Timer COMMA]
+%% ["S" COLON Timer COMMA]
+%% ["L" COLON Timer COMMA]
+%% ["Z" COLON Timer COMMA] digitMap
+digit_map_value(Chars) ->
+ digit_map_value(Chars, #'DigitMapValue'{}).
+
+%% NOTE: The swap of the digitMapBody and the durationTimer is
+%% intentional. The reason is a problem with the flex scanner.
+%% Hopefully this is temporary...
+%% The values are swapped back later by the parser...
+digit_map_value([Char, ?ColonToken | Rest] = All, DMV) ->
+ case ?LOWER1(Char) of
+ $t -> digit_map_timer(All, Rest, #'DigitMapValue'.startTimer, DMV);
+ $s -> digit_map_timer(All, Rest, #'DigitMapValue'.shortTimer, DMV);
+ $l -> digit_map_timer(All, Rest, #'DigitMapValue'.longTimer, DMV);
+% $z -> digit_map_timer(All, Rest, #'DigitMapValue'.durationTimer, DMV);
+% _ -> DMV#'DigitMapValue'{digitMapBody = All}
+ $z -> digit_map_timer(All, Rest, #'DigitMapValue'.digitMapBody, DMV);
+ _ -> DMV#'DigitMapValue'{durationTimer = All}
+ end;
+digit_map_value(Chars, DMV) ->
+ DMV#'DigitMapValue'{durationTimer = Chars}.
+
+digit_map_timer(All, Chars, TimerPos, DMV) ->
+ {Rest, Digits} = collect_safe_chars(Chars, []),
+ {Rest2, _} = skip_sep_chars(Rest, 0),
+ case {Rest2, catch list_to_integer(Digits)} of
+ {[?CommaToken | Rest3], Int} when is_integer(Int) andalso
+ (Int >= 0) andalso
+ (element(TimerPos, DMV) =:= asn1_NOVALUE) ->
+ {Rest4, _} = skip_sep_chars(Rest3, 0),
+ DMV2 = setelement(TimerPos, DMV, Int),
+ digit_map_value(Rest4, DMV2);
+ _ ->
+ DMV#'DigitMapValue'{digitMapBody = All}
+ end.
+
+%% ============================================================================
+%% <prev-parser-stuff>
+%%
+%% This stuff was originally in the parser(s), but was,
+%% for performance reasons, moved to the scanner(s). This
+%% scanner does not make it faster, but the flex scanner
+%% does, which is why the move was made.
+%%
+
+property_groups(OctetString) ->
+ Group = [],
+ Groups = [],
+ property_name(OctetString, Group, Groups).
+
+property_name([Char | Rest] = All, Group, Groups) ->
+ if
+ ?white_space(Char) ->
+ property_name(Rest, Group, Groups);
+ ?end_of_line(Char) ->
+ property_name(Rest, Group, Groups);
+ true ->
+ Name = [],
+ do_property_name(All, Name, Group, Groups)
+ end;
+property_name([] = All, Group, Groups) ->
+ Name = [],
+ do_property_name(All, Name, Group, Groups).
+
+do_property_name([Char | Rest], Name, Group, Groups)
+ when (Char =:= $=) andalso (Name =/= []) ->
+ %% Now we have a complete name
+ if
+ (Name =:= "v") andalso (Group =/= []) ->
+ %% v= is a property group delimiter,
+ %% lets create yet another property group.
+ Groups2 = [lists:reverse(Group) | Groups],
+ Group2 = [],
+ property_value(Rest, Name, Group2, Groups2);
+ true ->
+ %% Use current property group
+ property_value(Rest, Name, Group, Groups)
+ end;
+do_property_name([Char | Rest], Name, Group, Groups) ->
+ case ?classify_char4(Char) of
+ safe_char_upper ->
+ do_property_name(Rest, [Char | Name], Group, Groups);
+ safe_char ->
+ do_property_name(Rest, [Char | Name], Group, Groups);
+ _ ->
+ throw({error, {bad_prop_name, lists:reverse(Name), Char}})
+ end;
+do_property_name([], [], [], Groups) ->
+ lists:reverse(Groups);
+do_property_name([], [], Group, Groups) ->
+ Group2 = lists:reverse(Group),
+ lists:reverse([Group2 | Groups]);
+do_property_name([], Name, Group, Groups) when Name =/= [] ->
+ %% Assume end of line
+ Value = [],
+ PP = make_property_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_scanner_inline).
+-compile({inline,[{property_value,4}]}).
+-endif.
+property_value(Chars, Name, Group, Groups) ->
+ Value = [],
+ do_property_value(Chars, Name, Value, Group, Groups).
+
+do_property_value([Char | Rest], Name, Value, Group, Groups) ->
+ if
+ ?end_of_line(Char) ->
+ %% Now we have a complete "name=value" pair
+ PP = make_property_parm(Name, Value),
+ property_name(Rest, [PP | Group], Groups);
+ true ->
+ do_property_value(Rest, Name, [Char | Value], Group, Groups)
+ end;
+do_property_value([], Name, Value, Group, Groups) ->
+ %% Assume end of line
+ PP = make_property_parm(Name, Value),
+ Group2 = lists:reverse([PP | Group]),
+ lists:reverse([Group2 | Groups]).
+
+-ifdef(megaco_scanner_inline).
+-compile({inline,[{make_property_parm,2}]}).
+-endif.
+make_property_parm(Name, Value) ->
+ %% Record name, name field, value field, extraInfo field
+ {'PropertyParm',
+ lists:reverse(Name),
+ [lists:reverse(Value)],
+ asn1_NOVALUE}.
+
+
+%% </prev-parser-stuff>
+%% ===========================================================================
+
+select_token([$o, $- | LowerText], Version) ->
+ select_token(LowerText, Version);
+select_token([$w, $- | LowerText], Version) ->
+ select_token(LowerText, Version);
+select_token(LowerText, Version) ->
+ case LowerText of
+ "add" -> 'AddToken';
+ "a" -> 'AddToken';
+ "andlgc" when (Version >= 3) -> 'AndAUDITSelectToken'; % v3
+ "audit" -> 'AuditToken';
+ "at" -> 'AuditToken';
+ "auditcapability" -> 'AuditCapToken';
+ "ac" -> 'AuditCapToken';
+ "auditvalue" -> 'AuditValueToken';
+ "av" -> 'AuditValueToken';
+ "authentication" -> 'AuthToken';
+ "au" -> 'AuthToken';
+ "both" when (Version >= 3) -> 'BothToken'; % v3
+ "b" when (Version >= 3) -> 'BothToken'; % v3
+ "bothway" -> 'BothwayToken';
+ "bw" -> 'BothwayToken';
+ "brief" -> 'BriefToken';
+ "br" -> 'BriefToken';
+ "buffer" -> 'BufferToken';
+ "bf" -> 'BufferToken';
+ "context" -> 'CtxToken';
+ "c" -> 'CtxToken';
+ "contextattr" when (Version >= 3) -> 'ContextAttrToken'; % v3
+ "ct" when (Version >= 3) -> 'ContextAttrToken'; % v3
+ "contextlist" when (Version >= 3) -> 'ContextListToken'; % v3
+ "clt" when (Version >= 3) -> 'ContextListToken'; % v3
+ "contextaudit" -> 'ContextAuditToken';
+ "ca" -> 'ContextAuditToken';
+ "digitmap" -> 'DigitMapToken';
+ "dm" -> 'DigitMapToken';
+ "spadirection" when (Version >= 3) -> 'DirectionToken'; % v3
+ "direction" when (Version >= 3) -> 'DirectionToken'; % v3 (pre-v3a/v3b)
+ "spadi" when (Version >= 3) -> 'DirectionToken'; % v3
+ "di" when (Version >= 3) -> 'DirectionToken'; % v3 (pre-v3a/v3b)
+ "discard" -> 'DiscardToken';
+ "ds" -> 'DiscardToken';
+ "disconnected" -> 'DisconnectedToken';
+ "dc" -> 'DisconnectedToken';
+ "delay" -> 'DelayToken';
+ "dl" -> 'DelayToken';
+ "delete" -> 'DeleteToken';
+ "de" -> 'DeleteToken';
+ "duration" -> 'DurationToken';
+ "dr" -> 'DurationToken';
+ "embed" -> 'EmbedToken';
+ "em" -> 'EmbedToken';
+ "emergency" -> 'EmergencyToken';
+ "eg" -> 'EmergencyToken';
+ "emergencyofftoken" -> 'EmergencyOffToken';
+ "emergencyoff" when (Version >= 3) -> 'EmergencyOffToken'; % v3 (as of prev3c)
+ "ego" -> 'EmergencyOffToken';
+ "emergencyvalue" when (Version >= 3) -> 'EmergencyValueToken'; % v3
+ "egv" when (Version >= 3) -> 'EmergencyValueToken'; % v3
+ "error" -> 'ErrorToken';
+ "er" -> 'ErrorToken';
+ "eventbuffer" -> 'EventBufferToken';
+ "eb" -> 'EventBufferToken';
+ "events" -> 'EventsToken';
+ "e" -> 'EventsToken';
+ "external" when (Version >= 3) -> 'ExternalToken'; % v3
+ "ex" when (Version >= 3) -> 'ExternalToken'; % v3
+ "failover" -> 'FailoverToken';
+ "fl" -> 'FailoverToken';
+ "forced" -> 'ForcedToken';
+ "fo" -> 'ForcedToken';
+ "graceful" -> 'GracefulToken';
+ "gr" -> 'GracefulToken';
+ "h221" -> 'H221Token';
+ "h223" -> 'H223Token';
+ "h226" -> 'H226Token';
+ "handoff" -> 'HandOffToken';
+ "ho" -> 'HandOffToken';
+ "iepscall" when (Version >= 3) -> 'IEPSToken'; % v3
+ "ieps" when (Version >= 3) -> 'IEPSToken'; % v3
+ "inactive" -> 'InactiveToken';
+ "in" -> 'InactiveToken';
+ "internal" when (Version >= 3) -> 'InternalToken'; % v3
+ "it" when (Version >= 3) -> 'InternalToken'; % v3
+ "immackrequired" -> 'ImmAckRequiredToken';
+ "ia" -> 'ImmAckRequiredToken';
+ "inservice" -> 'InSvcToken';
+ "intersignal" when (Version >= 3) -> 'IntsigDelayToken'; % v3
+ "spais" when (Version >= 3) -> 'IntsigDelayToken'; % v3
+ "intbyevent" -> 'InterruptByEventToken';
+ "ibe" -> 'InterruptByEventToken';
+ "intbysigdescr" -> 'InterruptByNewSignalsDescrToken';
+ "ibs" -> 'InterruptByNewSignalsDescrToken';
+ "iv" -> 'InSvcToken';
+ "isolate" -> 'IsolateToken';
+ "is" -> 'IsolateToken';
+ "iterationtoken" when (Version >= 3) -> 'IterationToken'; % v3
+ "ir" when (Version >= 3) -> 'IterationToken'; % v3
+ "keepactive" -> 'KeepActiveToken';
+ "ka" -> 'KeepActiveToken';
+ "local" -> 'LocalToken';
+ "l" -> 'LocalToken';
+ "localcontrol" -> 'LocalControlToken';
+ "lockstep" -> 'LockStepToken';
+ "sp" -> 'LockStepToken';
+ "o" -> 'LocalControlToken';
+ "loopback" -> 'LoopbackToken';
+ "lb" -> 'LoopbackToken';
+ "media" -> 'MediaToken';
+ "m" -> 'MediaToken';
+ %% "megaco" -> 'MegacopToken';
+ %% "!" -> 'megacoptoken';
+ "segment" when (Version >= 3) -> 'MessageSegmentToken'; % v3
+ "sm" when (Version >= 3) -> 'MessageSegmentToken'; % v3
+ "method" -> 'MethodToken';
+ "mt" -> 'MethodToken';
+ "mtp" -> 'MtpToken';
+ "mgcidtotry" -> 'MgcIdToken';
+ "mg" -> 'MgcIdToken';
+ "mode" -> 'ModeToken';
+ "mo" -> 'ModeToken';
+ "modify" -> 'ModifyToken';
+ "mf" -> 'ModifyToken';
+ "modem" -> 'ModemToken';
+ "md" -> 'ModemToken';
+ "move" -> 'MoveToken';
+ "mv" -> 'MoveToken';
+ "mux" -> 'MuxToken';
+ "mx" -> 'MuxToken';
+ "nevernotify" when (Version >= 3) -> 'NeverNotifyToken'; % v3
+ "nbnn" when (Version >= 3) -> 'NeverNotifyToken'; % v3
+ "notify" -> 'NotifyToken';
+ "n" -> 'NotifyToken';
+ "notifycompletion" -> 'NotifyCompletionToken';
+ "nc" -> 'NotifyCompletionToken';
+ "immediatenotify" when (Version >= 3) -> 'NotifyImmediateToken'; % v3
+ "nbin" when (Version >= 3) -> 'NotifyImmediateToken'; % v3
+ "regulatednotify" when (Version >= 3) -> 'NotifyRegulatedToken'; % v3
+ "nbrn" when (Version >= 3) -> 'NotifyRegulatedToken'; % v3
+ "nx64kservice" when (Version >= 2) -> 'Nx64kToken'; % v2
+ "n64" when (Version >= 2) -> 'Nx64kToken'; % v2
+ "observedevents" -> 'ObservedEventsToken';
+ "oe" -> 'ObservedEventsToken';
+ "oneway" -> 'OnewayToken';
+ "ow" -> 'OnewayToken';
+ "onewayboth" when (Version >= 3) -> 'OnewayBothToken'; % v3
+ "owb" when (Version >= 3) -> 'OnewayBothToken'; % v3
+ "onewayexternal" when (Version >= 3) -> 'OnewayExternalToken'; % v3
+ "owe" when (Version >= 3) -> 'OnewayExternalToken'; % v3
+ "off" -> 'OffToken';
+ "on" -> 'OnToken';
+ "onoff" -> 'OnOffToken';
+ "oo" -> 'OnOffToken';
+ "orlgc" when (Version >= 3) -> 'OrAUDITselectToken'; % v3
+ "otherreason" -> 'OtherReasonToken';
+ "or" -> 'OtherReasonToken';
+ "outofservice" -> 'OutOfSvcToken';
+ "os" -> 'OutOfSvcToken';
+ "packages" -> 'PackagesToken';
+ "pg" -> 'PackagesToken';
+ "pending" -> 'PendingToken';
+ "pn" -> 'PendingToken';
+ "priority" -> 'PriorityToken';
+ "pr" -> 'PriorityToken';
+ "profile" -> 'ProfileToken';
+ "pf" -> 'ProfileToken';
+ "reason" -> 'ReasonToken';
+ "re" -> 'ReasonToken';
+ "receiveonly" -> 'RecvonlyToken';
+ "requestid" when (Version >= 3) -> 'RequestIDToken'; % v3
+ "rq" when (Version >= 3) -> 'RequestIDToken'; % v3
+ "rc" -> 'RecvonlyToken';
+ "reply" -> 'ReplyToken';
+ "p" -> 'ReplyToken';
+ "reseteventsdescriptor" when (Version >= 3) -> 'ResetEventsDescriptorToken'; % v3
+ "rse" when (Version >= 3) -> 'ResetEventsDescriptorToken'; % v3
+ "transactionresponseack"-> 'ResponseAckToken';
+ "k" -> 'ResponseAckToken';
+ "restart" -> 'RestartToken';
+ "rs" -> 'RestartToken';
+ "remote" -> 'RemoteToken';
+ "r" -> 'RemoteToken';
+ "sparequestid" -> 'RequestIDToken';
+ "sparq" -> 'RequestIDToken';
+ "reservedgroup" -> 'ReservedGroupToken';
+ "rg" -> 'ReservedGroupToken';
+ "reservedvalue" -> 'ReservedValueToken';
+ "rv" -> 'ReservedValueToken';
+ "end" when (Version >= 3) -> 'SegmentationCompleteToken'; % v3
+ "&" when (Version >= 3) -> 'SegmentationCompleteToken'; % v3
+ "sendonly" -> 'SendonlyToken';
+ "so" -> 'SendonlyToken';
+ "sendreceive" -> 'SendrecvToken';
+ "sr" -> 'SendrecvToken';
+ "services" -> 'ServicesToken';
+ "sv" -> 'ServicesToken';
+ "servicestates" -> 'ServiceStatesToken';
+ "si" -> 'ServiceStatesToken';
+ "servicechange" -> 'ServiceChangeToken';
+ "sc" -> 'ServiceChangeToken';
+ "servicechangeaddress" -> 'ServiceChangeAddressToken';
+ "ad" -> 'ServiceChangeAddressToken';
+ "servicechangeinc" when (Version >= 3) -> 'ServiceChangeIncompleteToken'; % v3
+ "sic" when (Version >= 3) -> 'ServiceChangeIncompleteToken'; % v3
+ "signallist" -> 'SignalListToken';
+ "sl" -> 'SignalListToken';
+ "signals" -> 'SignalsToken';
+ "sg" -> 'SignalsToken';
+ "signaltype" -> 'SignalTypeToken';
+ "sy" -> 'SignalTypeToken';
+ "statistics" -> 'StatsToken';
+ "sa" -> 'StatsToken';
+ "stream" -> 'StreamToken';
+ "st" -> 'StreamToken';
+ "subtract" -> 'SubtractToken';
+ "s" -> 'SubtractToken';
+ "synchisdn" -> 'SynchISDNToken';
+ "sn" -> 'SynchISDNToken';
+ "terminationstate" -> 'TerminationStateToken';
+ "ts" -> 'TerminationStateToken';
+ "test" -> 'TestToken';
+ "te" -> 'TestToken';
+ "timeout" -> 'TimeOutToken';
+ "to" -> 'TimeOutToken';
+ "topology" -> 'TopologyToken';
+ "tp" -> 'TopologyToken';
+ "transaction" -> 'TransToken';
+ "t" -> 'TransToken';
+ "v18" -> 'V18Token';
+ "v22" -> 'V22Token';
+ "v22b" -> 'V22bisToken';
+ "v32" -> 'V32Token';
+ "v32b" -> 'V32bisToken';
+ "v34" -> 'V34Token';
+ "v76" -> 'V76Token';
+ "v90" -> 'V90Token';
+ "v91" -> 'V91Token';
+ "version" -> 'VersionToken';
+ "v" -> 'VersionToken';
+ [_,_,_,_,_,_,_,_,$t,_,_,_,_,_,_,_,_] -> % Could be a time-stamp
+ [D1,D2,D3,D4,D5,D6,D7,D8,_,T1,T2,T3,T4,T5,T6,T7,T8] = LowerText,
+ select_TimeStampToken(D1,D2,D3,D4,D5,D6,D7,D8,
+ T1,T2,T3,T4,T5,T6,T7,T8);
+ _ -> 'SafeChars'
+ end.
+
+select_TimeStampToken(D1,D2,D3,D4,D5,D6,D7,D8,
+ T1,T2,T3,T4,T5,T6,T7,T8)
+ when ($0 =< D1) andalso (D1 =< $9) andalso
+ ($0 =< D2) andalso (D2 =< $9) andalso
+ ($0 =< D3) andalso (D3 =< $9) andalso
+ ($0 =< D4) andalso (D4 =< $9) andalso
+ ($0 =< D5) andalso (D5 =< $9) andalso
+ ($0 =< D6) andalso (D6 =< $9) andalso
+ ($0 =< D7) andalso (D7 =< $9) andalso
+ ($0 =< D8) andalso (D8 =< $9) andalso
+ ($0 =< T1) andalso (T1 =< $9) andalso
+ ($0 =< T2) andalso (T2 =< $9) andalso
+ ($0 =< T3) andalso (T3 =< $9) andalso
+ ($0 =< T4) andalso (T4 =< $9) andalso
+ ($0 =< T5) andalso (T5 =< $9) andalso
+ ($0 =< T6) andalso (T6 =< $9) andalso
+ ($0 =< T7) andalso (T7 =< $9) andalso
+ ($0 =< T8) andalso (T8 =< $9) ->
+ 'TimeStampToken';
+select_TimeStampToken(_D1,_D2,_D3,_D4,_D5,_D6,_D7,_D8,
+ _T1,_T2,_T3,_T4,_T5,_T6,_T7,_T8) ->
+ 'SafeChars'.
+
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("DBG:~p:" ++ F ++ "~n", [?MODULE|A]);
+%% d(_, _, _) ->
+%% ok.
diff --git a/lib/megaco/src/text/megaco_text_tokens.hrl b/lib/megaco/src/text/megaco_text_tokens.hrl
new file mode 100644
index 0000000000..14f59c3f06
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_tokens.hrl
@@ -0,0 +1,475 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Define of tokens used in text encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Adding a new token requires changes in the following files:
+%%
+%% megaco_text_tokens.hrl
+%% megaco_text_gen.hrl
+%% megaco_compact_text_encoder.erl
+%% megaco_pretty_text_encoder.erl
+%% megaco_text_scanner.erl
+%% megaco_text_parser.yrl (safeToken rule, make_safe_token/1, actual rule)
+%%
+%% Plus regeneration the ASN.1 related files including
+%% manual patches
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Special records
+%%----------------------------------------------------------------------
+
+-record(property_parm,
+ {
+ name,
+ value,
+ extraInfo = asn1_NOVALUE
+ }).
+
+
+
+%%----------------------------------------------------------------------
+%% Special characters
+%%----------------------------------------------------------------------
+
+-define(EqualToken, 16#3d).
+-define(ColonToken, 16#3a).
+-define(LbrktToken, 16#7b).
+-define(RbrktToken, 16#7d).
+-define(LsbrktToken, $[).
+-define(RsbrktToken, $]).
+-define(CommaToken, 16#2c).
+-define(DotToken, 16#2e).
+-define(SlashToken, 16#2f).
+-define(DoubleQuoteToken, 16#22).
+-define(SpToken, 16#20).
+-define(HtabToken, 16#09).
+-define(CrToken, 16#0d).
+-define(LfToken, 16#0a).
+
+-define(SemiColonToken, $;).
+-define(NequalToken, $#).
+-define(GreaterToken, $>).
+-define(LesserToken, $<).
+-define(BackslashToken, $\\).
+-define(LparToken, $().
+-define(RparToken, $)).
+-define(VbarToken, $|).
+
+%%----------------------------------------------------------------------
+%% Pretty version of tokens
+%%----------------------------------------------------------------------
+
+-define(PrettyAddToken , "Add" ).
+-define(PrettyAndAUDITSelectToken , "ANSLgc" ).
+-define(PrettyAuditToken , "Audit" ).
+-define(PrettyAuditCapToken , "AuditCapability" ).
+-define(PrettyAuditValueToken , "AuditValue" ).
+-define(PrettyAuthToken , "Authentication" ).
+-define(PrettyBothToken , "Both" ). % v3
+-define(PrettyBothwayToken , "Bothway" ).
+-define(PrettyBriefToken , "Brief" ).
+-define(PrettyBufferToken , "Buffer" ).
+-define(PrettyCtxToken , "Context" ).
+-define(PrettyContextAuditToken , "ContextAudit" ).
+-define(PrettyContextAttrToken , "ContextAttr" ). % v3
+-define(PrettyContextListToken , "ContextList" ). % v3
+-define(PrettyDigitMapToken , "DigitMap" ).
+-ifdef(encoder_version_pre_prev3c).
+-define(PrettyDirectionToken , "Direction" ). % v3
+-else.
+-define(PrettyDirectionToken , "SPADirection" ). % v3
+-endif.
+-define(PrettyDiscardToken , "Discard" ).
+-define(PrettyDisconnectedToken , "Disconnected" ).
+-define(PrettyDelayToken , "Delay" ).
+-define(PrettyDurationToken , "Duration" ).
+-define(PrettyEmbedToken , "Embed" ).
+-define(PrettyEmergencyToken , "Emergency" ).
+-ifdef(encoder_version_pre_prev3c).
+-define(PrettyEmergencyOffToken , "EmergencyOffToken" ). % v2
+-else.
+-define(PrettyEmergencyOffToken , "EmergencyOff" ). % v3
+-endif.
+-define(PrettyEmergencyValueToken , "EmergencyValue" ). % v3
+-define(PrettyErrorToken , "Error" ).
+-define(PrettyEventBufferToken , "EventBuffer" ).
+-define(PrettyEventsToken , "Events" ).
+-define(PrettyExternalToken , "External" ). % v3
+-define(PrettyFailoverToken , "Failover" ).
+-define(PrettyForcedToken , "Forced" ).
+-define(PrettyGracefulToken , "Graceful" ).
+-define(PrettyH221Token , "H221" ).
+-define(PrettyH223Token , "H223" ).
+-define(PrettyH226Token , "H226" ).
+-define(PrettyHandOffToken , "HandOff" ).
+-define(PrettyIEPSToken , "IEPSCall" ). % v3
+-define(PrettyImmAckRequiredToken , "ImmAckRequired" ).
+-define(PrettyInactiveToken , "Inactive" ).
+-define(PrettyInternalToken , "Internal" ). % v3
+-define(PrettyIntsigDelayToken , "Intersignal" ). % v3
+-define(PrettyInterruptByEventToken , "IntByEvent" ).
+-define(PrettyInterruptByNewSignalsDescrToken, "IntBySigDescr" ).
+-define(PrettyIsolateToken , "Isolate" ).
+-define(PrettyInSvcToken , "InService" ).
+-define(PrettyIterationToken , "Iteration" ). % v3
+-define(PrettyKeepActiveToken , "KeepActive" ).
+-define(PrettyLocalToken , "Local" ).
+-define(PrettyLocalControlToken , "LocalControl" ).
+-define(PrettyLockStepToken , "LockStep" ).
+-define(PrettyLoopbackToken , "Loopback" ).
+-define(PrettyMediaToken , "Media" ).
+-define(PrettyMegacopToken , "MEGACO" ).
+-define(PrettyMessageSegmentToken , "Segment" ). % v3
+-define(PrettyMethodToken , "Method" ).
+-define(PrettyMgcIdToken , "MgcIdToTry" ).
+-define(PrettyModeToken , "Mode" ).
+-define(PrettyModifyToken , "Modify" ).
+-define(PrettyModemToken , "Modem" ).
+-define(PrettyMoveToken , "Move" ).
+-define(PrettyMtpToken , "MTP" ).
+-define(PrettyMuxToken , "Mux" ).
+-define(PrettyNeverNotifyToken , "NeverNotify" ). % v3
+-define(PrettyNotifyToken , "Notify" ).
+-define(PrettyNotifyCompletionToken , "NotifyCompletion" ).
+-define(PrettyNotifyImmediateToken , "ImmediateNotify" ). % v3
+-define(PrettyNotifyRegulatedToken , "RegulatedNotify" ). % v3
+-define(PrettyNx64kToken , "Nx64Kservice" ).
+-define(PrettyObservedEventsToken , "ObservedEvents" ).
+-define(PrettyOffToken , "OFF" ).
+-define(PrettyOnewayToken , "Oneway" ).
+-define(PrettyOnewayBothToken , "OnewayBoth" ). % v3
+-define(PrettyOnewayExternalToken , "OnewayExternal" ). % v3
+-define(PrettyOnOffToken , "OnOff" ).
+-define(PrettyOrAUDITselectToken , "ORLgc" ). % v3
+-define(PrettyOnToken , "ON" ).
+-define(PrettyOtherReasonToken , "OtherReason" ).
+-define(PrettyOutOfSvcToken , "OutOfService" ).
+-define(PrettyPackagesToken , "Packages" ).
+-define(PrettyPendingToken , "Pending" ).
+-define(PrettyPriorityToken , "Priority" ).
+-define(PrettyProfileToken , "Profile" ).
+-define(PrettyReasonToken , "Reason" ).
+-define(PrettyRecvonlyToken , "ReceiveOnly" ).
+-define(PrettyReplyToken , "Reply" ).
+-define(PrettyResetEventsDescriptorToken , "ResetEventsDescriptor" ). % v3
+-define(PrettyRestartToken , "Restart" ).
+-define(PrettyRemoteToken , "Remote" ).
+-ifdef(encoder_version_pre_prev3c).
+-define(PrettyRequestIDToken , "RequestID" ). % v3
+-else.
+-define(PrettyRequestIDToken , "SPARequestID" ). % v3
+-endif.
+-define(PrettyReservedGroupToken , "ReservedGroup" ).
+-define(PrettyReservedValueToken , "ReservedValue" ).
+-define(PrettySegmentationCompleteToken , "END" ). % v3
+-define(PrettySendonlyToken , "SendOnly" ).
+-define(PrettySendrecvToken , "SendReceive" ).
+-define(PrettyServicesToken , "Services" ).
+-define(PrettyServiceStatesToken , "ServiceStates" ).
+-define(PrettyServiceChangeToken , "ServiceChange" ).
+-define(PrettyServiceChangeAddressToken , "ServiceChangeAddress" ).
+-define(PrettyServiceChangeIncompleteToken , "ServiceChangeInc" ). % v3
+-define(PrettySignalListToken , "SignalList" ).
+-define(PrettySignalsToken , "Signals" ).
+-define(PrettySignalTypeToken , "SignalType" ).
+-define(PrettyStatsToken , "Statistics" ).
+-define(PrettyStreamToken , "Stream" ).
+-define(PrettySubtractToken , "Subtract" ).
+-define(PrettySynchISDNToken , "SynchISDN" ).
+-define(PrettyTerminationStateToken , "TerminationState" ).
+-define(PrettyTestToken , "Test" ).
+-define(PrettyTimeOutToken , "TimeOut" ).
+-define(PrettyTopologyToken , "Topology" ).
+-define(PrettyTransToken , "Transaction" ).
+-define(PrettyResponseAckToken , "TransactionResponseAck").
+-define(PrettyV18Token , "V18" ).
+-define(PrettyV22Token , "V22" ).
+-define(PrettyV22bisToken , "V22b" ).
+-define(PrettyV32Token , "V32" ).
+-define(PrettyV32bisToken , "V32b" ).
+-define(PrettyV34Token , "V34" ).
+-define(PrettyV76Token , "V76" ).
+-define(PrettyV90Token , "V90" ).
+-define(PrettyV91Token , "V91" ).
+-define(PrettyVersionToken , "Version" ).
+
+%%----------------------------------------------------------------------
+%% Compact version of tokens
+%%----------------------------------------------------------------------
+
+-define(CompactAddToken , "A" ).
+-define(CompactAndAUDITSelectToken , "ANSLgc" ).
+-define(CompactAuditToken , "AT" ).
+-define(CompactAuditCapToken , "AC" ).
+-define(CompactAuditValueToken , "AV" ).
+-define(CompactAuthToken , "AU" ).
+-define(CompactBothToken , "B" ). % v3
+-define(CompactBothwayToken , "BW" ).
+-define(CompactBriefToken , "BR" ).
+-define(CompactBufferToken , "BF" ).
+-define(CompactCtxToken , "C" ).
+-define(CompactContextAuditToken , "CA" ).
+-define(CompactContextAttrToken , "CT" ). % v3
+-define(CompactContextListToken , "CLT" ). % v3
+-define(CompactDigitMapToken , "DM" ).
+-ifdef(encoder_version_pre_prev3c).
+-define(CompactDirectionToken , "DI" ). % v3
+-else.
+-define(CompactDirectionToken , "SPADI" ). % v3
+-endif.
+-define(CompactDiscardToken , "DS" ).
+-define(CompactDisconnectedToken , "DC" ).
+-define(CompactDelayToken , "DL" ).
+-define(CompactDurationToken , "DR" ).
+-define(CompactEmbedToken , "EM" ).
+-define(CompactEmergencyToken , "EG" ).
+-define(CompactEmergencyOffToken , "EGO" ).
+-define(CompactEmergencyValueToken , "EGV" ). % v3
+-define(CompactErrorToken , "ER" ).
+-define(CompactEventBufferToken , "EB" ).
+-define(CompactEventsToken , "E" ).
+-define(CompactExternalToken , "EX" ). % v3
+-define(CompactFailoverToken , "FL" ).
+-define(CompactForcedToken , "FO" ).
+-define(CompactGracefulToken , "GR" ).
+-define(CompactH221Token , ?PrettyH221Token ).
+-define(CompactH223Token , ?PrettyH223Token ).
+-define(CompactH226Token , ?PrettyH226Token ).
+-define(CompactHandOffToken , "HO" ).
+-define(CompactIEPSToken , "IEPS" ). % v3
+-define(CompactImmAckRequiredToken , "IA" ).
+-define(CompactInactiveToken , "IN" ).
+-define(CompactInternalToken , "IT" ). % v3
+-define(CompactIntsigDelayToken , "SPAIS" ). % v3
+-define(CompactInterruptByEventToken , "IBE" ).
+-define(CompactInterruptByNewSignalsDescrToken, "IBS" ).
+-define(CompactIsolateToken , "IS" ).
+-define(CompactInSvcToken , "IV" ).
+-define(CompactIterationToken , "IR" ). % v3
+-define(CompactKeepActiveToken , "KA" ).
+-define(CompactLocalToken , "L" ).
+-define(CompactLocalControlToken , "O" ).
+-define(CompactLockStepToken , "SP" ).
+-define(CompactLoopbackToken , "LB" ).
+-define(CompactMediaToken , "M" ).
+-define(CompactMegacopToken , "!" ).
+-define(CompactMessageSegmentToken , "SM" ). % v3
+-define(CompactMethodToken , "MT" ).
+-define(CompactMgcIdToken , "MG" ).
+-define(CompactModeToken , "MO" ).
+-define(CompactModifyToken , "MF" ).
+-define(CompactModemToken , "MD" ).
+-define(CompactMoveToken , "MV" ).
+-define(CompactMtpToken , ?PrettyMtpToken ).
+-define(CompactMuxToken , "MX" ).
+-define(CompactNeverNotifyToken , "NBNN" ). % v3
+-define(CompactNotifyToken , "N" ).
+-define(CompactNotifyCompletionToken , "NC" ).
+-define(CompactNotifyImmediateToken , "NBIN" ). % v3
+-define(CompactNotifyRegulatedToken , "NBRN" ). % v3
+-define(CompactNx64kToken , "N64" ).
+-define(CompactObservedEventsToken , "OE" ).
+-define(CompactOffToken , "OFF" ).
+-define(CompactOnewayToken , "OW" ).
+-define(CompactOnewayBothToken , "OWB" ). % v3
+-define(CompactOnewayExternalToken , "OWE" ). % v3
+-define(CompactOnOffToken , "OO" ).
+-define(CompactOrAUDITselectToken , "ORLgc" ). % v3
+-define(CompactOnToken , "ON" ).
+-define(CompactOtherReasonToken , "OR" ).
+-define(CompactOutOfSvcToken , "OS" ).
+-define(CompactPackagesToken , "PG" ).
+-define(CompactPendingToken , "PN" ).
+-define(CompactPriorityToken , "PR" ).
+-define(CompactProfileToken , "PF" ).
+-define(CompactReasonToken , "RE" ).
+-define(CompactRecvonlyToken , "RC" ).
+-define(CompactReplyToken , "P" ).
+-define(CompactResetEventsDescriptorToken , "RSE" ). % v3
+-define(CompactRestartToken , "RS" ).
+-define(CompactRemoteToken , "R" ).
+-ifdef(encoder_version_pre_prev3c).
+-define(CompactRequestIDToken , "RQ" ). % v3
+-else.
+-define(CompactRequestIDToken , "SPARQ" ). % v3
+-endif.
+-define(CompactReservedGroupToken , "RG" ).
+-define(CompactReservedValueToken , "RV" ).
+-define(CompactSegmentationCompleteToken , "&" ). % v3
+-define(CompactSendonlyToken , "SO" ).
+-define(CompactSendrecvToken , "SR" ).
+-define(CompactServicesToken , "SV" ).
+-define(CompactServiceStatesToken , "SI" ).
+-define(CompactServiceChangeToken , "SC" ).
+-define(CompactServiceChangeAddressToken , "AD" ).
+-define(CompactServiceChangeIncompleteToken , "SIC" ). % v3
+-define(CompactSignalListToken , "SL" ).
+-define(CompactSignalsToken , "SG" ).
+-define(CompactSignalTypeToken , "SY" ).
+-define(CompactStatsToken , "SA" ).
+-define(CompactStreamToken , "ST" ).
+-define(CompactSubtractToken , "S" ).
+-define(CompactSynchISDNToken , "SN" ).
+-define(CompactTerminationStateToken , "TS" ).
+-define(CompactTestToken , "TE" ).
+-define(CompactTimeOutToken , "TO" ).
+-define(CompactTopologyToken , "TP" ).
+-define(CompactTransToken , "T" ).
+-define(CompactResponseAckToken , "K" ).
+-define(CompactV18Token , ?PrettyV18Token ).
+-define(CompactV22Token , ?PrettyV22Token ).
+-define(CompactV22bisToken , ?PrettyV22bisToken ).
+-define(CompactV32Token , ?PrettyV32Token ).
+-define(CompactV32bisToken , ?PrettyV32bisToken ).
+-define(CompactV34Token , ?PrettyV34Token ).
+-define(CompactV76Token , ?PrettyV76Token ).
+-define(CompactV90Token , ?PrettyV90Token ).
+-define(CompactV91Token , ?PrettyV91Token ).
+-define(CompactVersionToken , "V" ).
+
+-define(white_space(Char), ((Char) =:= ?SpToken) orelse ((Char) =:= ?HtabToken)).
+-define(end_of_line(Char), ((Char) =:= ?LfToken) orelse ((Char) =:= ?CrToken)).
+
+-define(classify_char(Char),
+ (case Char of
+ $+ -> safe_char;
+ $- -> safe_char;
+ $& -> safe_char;
+ $! -> safe_char;
+ $_ -> safe_char;
+ $/ -> safe_char;
+ $' -> safe_char;
+ $? -> safe_char;
+ $@ -> safe_char;
+ $^ -> safe_char;
+ $` -> safe_char;
+ $~ -> safe_char;
+ $* -> safe_char;
+ $$ -> safe_char;
+ ?BackslashToken -> safe_char;
+ ?LparToken -> safe_char;
+ ?RparToken -> safe_char;
+ $% -> safe_char;
+ ?VbarToken -> safe_char;
+ $. -> safe_char;
+ ?SemiColonToken -> rest_char;
+ ?LsbrktToken -> rest_char;
+ ?RsbrktToken -> rest_char;
+ ?LbrktToken -> rest_char;
+ ?RbrktToken -> rest_char;
+ ?ColonToken -> rest_char;
+ ?CommaToken -> rest_char;
+ ?NequalToken -> rest_char;
+ ?LesserToken -> rest_char;
+ ?GreaterToken -> rest_char;
+ ?EqualToken -> rest_char;
+ ?DoubleQuoteToken -> double_quote;
+ ?SpToken -> white_space;
+ ?HtabToken -> white_space;
+ ?LfToken -> end_of_line;
+ ?CrToken -> end_of_line;
+ _ when (Char >= $0) andalso (Char =< $9) -> safe_char;
+ _ when (Char >= $a) andalso (Char =< $z) -> safe_char;
+ _ when (Char >= $A) andalso (Char =< $Z) -> safe_char_upper;
+ _ -> bad_char
+ end)).
+
+-define(classify_char2(Char),
+ (case Char of
+ ?SemiColonToken -> rest_char;
+ ?LsbrktToken -> rest_char;
+ ?RsbrktToken -> rest_char;
+ ?LbrktToken -> rest_char;
+ ?RbrktToken -> rest_char;
+ ?ColonToken -> rest_char;
+ ?CommaToken -> rest_char;
+ ?NequalToken -> rest_char;
+ ?LesserToken -> rest_char;
+ ?GreaterToken -> rest_char;
+ ?EqualToken -> rest_char;
+ ?SpToken -> white_space;
+ ?HtabToken -> white_space;
+ ?LfToken -> end_of_line;
+ ?CrToken -> end_of_line;
+ _ -> no_skip_char
+ end)).
+
+-define(classify_char3(Char),
+ (case Char of
+ $+ -> safe_char;
+ $- -> safe_char;
+ $& -> safe_char;
+ $! -> safe_char;
+ $_ -> safe_char;
+ $/ -> safe_char;
+ $' -> safe_char;
+ $? -> safe_char;
+ $@ -> safe_char;
+ $^ -> safe_char;
+ $` -> safe_char;
+ $~ -> safe_char;
+ $* -> safe_char;
+ $$ -> safe_char;
+ ?BackslashToken -> safe_char;
+ ?LparToken -> safe_char;
+ ?RparToken -> safe_char;
+ $% -> safe_char;
+ ?VbarToken -> safe_char;
+ $. -> safe_char;
+ _ when (Char >= $0) andalso (Char =< $9) -> safe_char;
+ _ when (Char >= $a) andalso (Char =< $z) -> safe_char;
+ _ when (Char >= $A) andalso (Char =< $Z) -> safe_char_upper;
+ _ -> non_safe_char
+ end)).
+
+%% Only safe_char and safe_char_upper
+-define(classify_char4(Char),
+ (case Char of
+ $+ -> safe_char;
+ $- -> safe_char;
+ $& -> safe_char;
+ $! -> safe_char;
+ $_ -> safe_char;
+ $/ -> safe_char;
+ $' -> safe_char;
+ $? -> safe_char;
+ $@ -> safe_char;
+ $^ -> safe_char;
+ $` -> safe_char;
+ $~ -> safe_char;
+ $* -> safe_char;
+ $$ -> safe_char;
+ ?BackslashToken -> safe_char;
+ ?LparToken -> safe_char;
+ ?RparToken -> safe_char;
+ $% -> safe_char;
+ ?VbarToken -> safe_char;
+ $. -> safe_char;
+ _ when (Char >= $0) andalso (Char =< $9) -> safe_char;
+ _ when (Char >= $a) andalso (Char =< $z) -> safe_char;
+ _ when (Char >= $A) andalso (Char =< $Z) -> safe_char_upper;
+ _ -> not_safe_char
+ end)).
+
diff --git a/lib/megaco/src/text/modules.mk b/lib/megaco/src/text/modules.mk
new file mode 100644
index 0000000000..c493c978a8
--- /dev/null
+++ b/lib/megaco/src/text/modules.mk
@@ -0,0 +1,65 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+MODULES = \
+ megaco_compact_text_encoder \
+ megaco_compact_text_encoder_v1 \
+ megaco_compact_text_encoder_v2 \
+ megaco_compact_text_encoder_v3 \
+ megaco_compact_text_encoder_prev3a \
+ megaco_compact_text_encoder_prev3b \
+ megaco_compact_text_encoder_prev3c \
+ megaco_pretty_text_encoder \
+ megaco_pretty_text_encoder_v1 \
+ megaco_pretty_text_encoder_v2 \
+ megaco_pretty_text_encoder_v3 \
+ megaco_pretty_text_encoder_prev3a \
+ megaco_pretty_text_encoder_prev3b \
+ megaco_pretty_text_encoder_prev3c \
+ megaco_text_mini_decoder \
+ megaco_text_scanner
+
+
+INTERNAL_HRL_FILES = \
+ megaco_text_gen_v1.hrl \
+ megaco_text_gen_v2.hrl \
+ megaco_text_gen_v3.hrl \
+ megaco_text_gen_prev3a.hrl \
+ megaco_text_gen_prev3b.hrl \
+ megaco_text_gen_prev3c.hrl \
+ megaco_text_parser_v1.hrl \
+ megaco_text_parser_v2.hrl \
+ megaco_text_parser_v3.hrl \
+ megaco_text_parser_prev3a.hrl \
+ megaco_text_parser_prev3b.hrl \
+ megaco_text_parser_prev3c.hrl \
+ megaco_text_mini_parser.hrl \
+ megaco_text_tokens.hrl
+
+
+INTERNAL_YRL_FILES = \
+ megaco_text_parser_v1.yrl \
+ megaco_text_parser_v2.yrl \
+ megaco_text_parser_v3.yrl \
+ megaco_text_parser_prev3a.yrl \
+ megaco_text_parser_prev3b.yrl \
+ megaco_text_parser_prev3c.yrl \
+ megaco_text_mini_parser.yrl
+
+