diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/megaco/src/flex | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/megaco/src/flex')
-rw-r--r-- | lib/megaco/src/flex/Makefile | 43 | ||||
-rw-r--r-- | lib/megaco/src/flex/Makefile.in | 396 | ||||
-rw-r--r-- | lib/megaco/src/flex/megaco_flex_scanner.erl | 230 | ||||
-rw-r--r-- | lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src | 1943 | ||||
-rw-r--r-- | lib/megaco/src/flex/megaco_flex_scanner_handler.erl | 232 | ||||
-rw-r--r-- | lib/megaco/src/flex/modules.mk | 27 | ||||
-rw-r--r-- | lib/megaco/src/flex/prebuild.skip | 1 |
7 files changed, 2872 insertions, 0 deletions
diff --git a/lib/megaco/src/flex/Makefile b/lib/megaco/src/flex/Makefile new file mode 100644 index 0000000000..ab8183e548 --- /dev/null +++ b/lib/megaco/src/flex/Makefile @@ -0,0 +1,43 @@ +# +# %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% + +# +# Invoke with GNU make or clearmake -C gnu. +# + +include $(ERL_TOP)/make/run_make.mk +include modules.mk + +conf: + cd ../..; $(MAKE) conf + +dconf: + $(MAKE) FLEX_SCANNER_REENTRANT=disable conf + +econf: + $(MAKE) FLEX_SCANNER_REENTRANT=enable conf + +setup: + (cd ../../priv/lib && \ + rm -f $(STD_DRV).so $(MT_DRV).so && \ + ln -s $(TARGET)/$(STD_DRV).so && \ + ln -s $(TARGET)/$(MT_DRV).so ) + +info: + $(MAKE) -f $(TARGET)/Makefile $@ + diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in new file mode 100644 index 0000000000..782d6a4807 --- /dev/null +++ b/lib/megaco/src/flex/Makefile.in @@ -0,0 +1,396 @@ +# +# %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% + +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) + + +# ---------------------------------------------------- +# The following variables differ on different systems, we set +# reasonable defaults, if something different is needed it should +# be set for that system only. +# ---------------------------------------------------- + +FLEX_VSN = $(shell flex --version) + +TMP_CFLAGS = @DED_CFLAGS@ +ifeq ($(TYPE),valgrind) +CFLAGS = $(subst -O2, , $(TMP_CFLAGS)) -DVALGRIND +else +CFLAGS = $(TMP_CFLAGS) +endif +CC = @CC@ +CFLAGS_MT = $(CFLAGS) -D_THREAD_SAFE -D_REENTRANT +LD = @DED_LD@ +LDFLAGS = @DED_LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +PERL = @PERL@ +ERLANG_OSTYPE = @ERLANG_OSTYPE@ + +# Shall we build the flex scanner or not. +# We assume that it does not exist on windows... +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),) +ifeq ($(findstring win32,$(TARGET)), win32) +ENABLE_MEGACO_FLEX_SCANNER = false +ENABLE_REENTRANT_MEGACO_FLEX_SCANNER = false +else +ENABLE_MEGACO_FLEX_SCANNER = @ENABLE_MEGACO_FLEX_SCANNER@ +ENABLE_REENTRANT_MEGACO_FLEX_SCANNER = @ENABLE_REENTRANT_MEGACO_FLEX_SCANNER@ +endif +endif +ERL_COMPILE_FLAGS += -DENABLE_MEGACO_FLEX_SCANNER=$(ENABLE_MEGACO_FLEX_SCANNER) + +ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) +CFLAGS_MT += -DMEGACO_REENTRANT_FLEX_SCANNER +MT_LEX_FLAGS += -R +ERL_COMPILE_FLAGS += -DMEGACO_REENTRANT_FLEX_SCANNER=true +else +ERL_COMPILE_FLAGS += -DMEGACO_REENTRANT_FLEX_SCANNER=false +endif + +# Shall the library be built with line-number checks or without +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER_LINENO),) +# This is not really needed in this case (since we don't support +# this for windows), but just to ensure that the variable _has_ +# a value... +ifeq ($(findstring win32,$(TARGET)), win32) +ENABLE_MEGACO_FLEX_SCANNER_LINENO = true +else +ENABLE_MEGACO_FLEX_SCANNER_LINENO = @ENABLE_MEGACO_FLEX_SCANNER_LINENO@ +endif +endif + + +SYSINCLUDE = -I$(ERL_TOP)/erts/emulator/beam \ + -I$(ERL_TOP)/erts/emulator/sys/$(ERLANG_OSTYPE) +ifeq ($(findstring vxworks,$(TARGET)),vxworks) + SYSINCLUDE += -I$(ERL_TOP)/erts/etc/vxworks +endif + +DRIVER_INCLUDES = $(SYSINCLUDE) + +PRIVDIR = ../../priv +LIBDIR = $(PRIVDIR)/lib/$(TARGET) + + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN) + + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +include modules.mk + +ERL_FILES = $(MODULES:%=%.erl) + +TARGET_FILES = \ + $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +FLEX_SRC = $(FLEX_MODULES:%=%.flex.src) +FLEX_FILES = $(STD_DRV).flex $(MT_DRV).flex + +C_TARGETS = $(STD_DRV).c $(MT_DRV).c + + +# ---------------------------------------------------- +# Misc Macros +# ---------------------------------------------------- + +STD_DRV_NAME=-DMEGACO_DRV_NAME=\"$(STD_DRV)\" +MT_DRV_NAME=-DMEGACO_DRV_NAME=\"$(MT_DRV)\" + +ifeq ($(findstring win32,$(TARGET)), win32) +FLEX_SCANNER_SO = +SOLIBS = $(FLEX_SCANNER_SO) +else +ifeq ($(findstring vxworks,$(TARGET)),vxworks) +FLEX_SCANNER_SO = +SOLIBS = $(FLEX_SCANNER_SO) +else +FLEX_SCANNER_SO = $(LIBDIR)/$(STD_DRV).so +FLEX_SCANNER_MT_SO = $(LIBDIR)/$(MT_DRV).so +SOLIBS = $(FLEX_SCANNER_SO) $(FLEX_SCANNER_MT_SO) +endif +endif + + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ifeq ($(TYPE),debug) +ERL_COMPILE_FLAGS += -Ddebug +endif + +include ../app/megaco.mk + +ERL_COMPILE_FLAGS += \ + $(MEGACO_ERL_COMPILE_FLAGS) \ + -I../../include + +ifeq ($(MFS_DEBUG),true) +CFLAGS += -DMFS_DEBUG=true +endif + +ifeq ($(MFS_FLEX_PERF),true) +STD_LEX_FLAGS += -p +MT_LEX_FLAGS += -p +endif + +ifeq ($(MFS_FLEX_DEBUG),true) +CFLAGS += -DMFS_FLEX_DEBUG=1 +STD_LEX_FLAGS += -d +MT_LEX_FLAGS += -d +else +CFLAGS += -DMFS_FLEX_DEBUG=0 +endif + +CFLAGS += $(DRIVER_INCLUDES) $(DRV_FLAGS) -funroll-loops -Wall + +#ifneq ($(FLEX_VSN),) +#CFLAGS += -DFLEX_VERSION="$(FLEX_VSN)" +#else +#CFLAGS += -DFLEX_VERSION=unknown +#endif + +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER_LINENO),true) +CFLAGS += -DMEGACO_LINENO +STD_LEX_FLAGS += -Ca +MT_LEX_FLAGS += -Ca +ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) +MT_LEX_FLAGS += --yylineno +endif +else +CFLAGS += -DMEGACO_TOKENCNT +STD_LEX_FLAGS += -Cfe +MT_LEX_FLAGS += -Cfe +endif + + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),true) +debug opt: $(TARGET_FILES) $(C_TARGETS) solibs +else +debug opt: $(TARGET_FILES) +endif + +clean: + rm -f $(TARGET_FILES) + rm -f $(FLEX_FILES) + rm -f $(C_TARGETS) + rm -f $(SOLIBS) + rm -f errs core *~ + +docs: + +info: + @echo "ENABLE_MEGACO_FLEX_SCANNER = $(ENABLE_MEGACO_FLEX_SCANNER)" + @echo "ENABLE_MEGACO_FLEX_SCANNER_LINENO = $(ENABLE_MEGACO_FLEX_SCANNER_LINENO)" + @echo "ENABLE_REENTRANT_MEGACO_FLEX_SCANNER = $(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER)" + @echo "" + @echo "FLEX_VSN = $(FLEX_VSN)" + @echo "" + @echo "CFLAGS = $(CFLAGS)" + @echo "CFLAGS_MT = $(CFLAGS_MT)" + @echo "DRV_FLAGS = $(DRV_FLAGS)" + @echo "STD_LEX_FLAGS = $(STD_LEX_FLAGS)" + @echo "MT_LEX_FLAGS = $(MT_LEX_FLAGS)" + @echo "" + @echo "MODULES = $(MODULES)" + @echo "ERL_FILES = $(ERL_FILES)" + @echo "TARGET_FILES = $(TARGET_FILES)" + @echo "" + @echo "FLEX_MODULES = $(FLEX_MODULES)" + @echo "FLEX_SRC = $(FLEX_SRC)" + @echo "FLEX_FILES = $(FLEX_FILES)" + @echo "" + @echo "C_TARGETS = $(C_TARGETS)" + @echo "" + @echo "LIBDIR = $(LIBDIR)" + @echo "LEXLIB = $(LEXLIB)" + @echo "" + @echo "STD_DRV = $(STD_DRV)" + @echo "MT_DRV = $(MT_DRV)" + @echo "" + @echo "STD_DRV_NAME = $(STD_DRV_NAME)" + @echo "MT_DRV_NAME = $(MT_DRV_NAME)" + @echo "" + @echo "SOLIBS = $(SOLIBS)" + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/ebin + $(INSTALL_DIR) $(RELSYSDIR)/src + $(INSTALL_DIR) $(RELSYSDIR)/src/flex + $(INSTALL_DIR) $(RELSYSDIR)/priv/lib + $(INSTALL_DIR) $(RELSYSDIR)/include + $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/flex + $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),true) + $(INSTALL_DATA) $(FLEX_FILES) $(C_TARGETS) $(RELSYSDIR)/src/flex + $(INSTALL_DATA) $(SOLIBS) $(RELSYSDIR)/priv/lib +endif + + +release_docs_spec: + +# megaco_flex_scanner_drv.flex: megaco_flex_scanner_drv.flex.src +# ifeq ($(ENABLE_MEGACO_FLEX_SCANNER_LINENO),true) +# ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) +# @printf "\treentrant [flex] scanner lineno enabled\n" +# $(PERL) -p -e \ +# 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ +# s/%MEGACO_YY_LINENO_OPTION%/%option yylineno/ ; \ +# s/%MEGACO_YY_REENTRANT_OPTION%/%option reentrant/ ; \ +# s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; *\//' \ +# < $< > $@ +# else +# @printf "\tnon-reentrant [flex] scanner lineno enabled\n" +# $(PERL) -p -e \ +# 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ +# s/%MEGACO_YY_LINENO_OPTION%/%option yylineno/ ; \ +# s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ +# s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; *\//' \ +# < $< > $@ +# endif +# else +# ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) +# @printf "\treentrant [flex] scanner lineno disabled\n" +# $(PERL) -p -e \ +# 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ +# s/%MEGACO_YY_LINENO_OPTION%/\/\* %option yylineno \*\// ; \ +# s/%MEGACO_YY_REENTRANT_OPTION%/%option reentrant/ ; \ +# s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; - REENTRANT SCANNER*\//' \ +# < $< > $@ +# else +# @printf "\tnon-reentrant [flex] scanner lineno disabled\n" +# $(PERL) -p -e \ +# 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ +# s/%MEGACO_YY_LINENO_OPTION%/\/\* %option yylineno \*\// ; \ +# s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ +# s/%MEGACO_DUMMY_DECL_YY_LINENO%/static int yylineno = 1;/' \ +# < $< > $@ +# endif +# endif +# + +$(STD_DRV).flex: megaco_flex_scanner_drv.flex.src +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER_LINENO),true) + @printf "std [flex] scanner - lineno enabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/%option yylineno/ ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; *\//' \ + < $< > $@ +else + @printf "std [flex] scanner - lineno disabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/\/\* %option yylineno \*\// ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/static int yylineno = 1;/' \ + < $< > $@ +endif + +$(MT_DRV).flex: megaco_flex_scanner_drv.flex.src +ifeq ($(ENABLE_MEGACO_FLEX_SCANNER_LINENO),true) +ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) + @printf "multi-threaded reentrant [flex] scanner - lineno enabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/%option yylineno/ ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/%option reentrant/ ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; *\//' \ + < $< > $@ +else + @printf "multi-threaded non-reentrant [flex] scanner - lineno enabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/%option yylineno/ ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; *\//' \ + < $< > $@ +endif +else +ifeq ($(ENABLE_REENTRANT_MEGACO_FLEX_SCANNER),true) + @printf "multi-threaded reentrant [flex] scanner - lineno disabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/\/\* %option yylineno \*\// ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/%option reentrant/ ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/\/* static int yylineno = 1; - REENTRANT SCANNER*\//' \ + < $< > $@ +else + @printf "multi-threaded non-reentrant [flex] scanner - lineno disabled\n" + $(PERL) -p -e \ + 's/%FLEX_VERSION%/$(FLEX_VSN)/ ; \ + s/%MEGACO_YY_LINENO_OPTION%/\/\* %option yylineno \*\// ; \ + s/%MEGACO_YY_REENTRANT_OPTION%/\/\* %option reentrant \*\// ; \ + s/%MEGACO_DUMMY_DECL_YY_LINENO%/static int yylineno = 1;/' \ + < $< > $@ +endif +endif + +# megaco_flex_scanner_drv.c: megaco_flex_scanner_drv.flex +# $(LEX) $(LEX_FLAGS) -P$* -o$@ $< +$(STD_DRV).c: $(STD_DRV).flex + $(LEX) $(STD_LEX_FLAGS) -P$* -o$@ $< +$(MT_DRV).c: $(MT_DRV).flex + $(LEX) $(MT_LEX_FLAGS) -P$* -o$@ $< + +solibs: $(LIBDIR) $(SOLIBS) + +# No need to link with -lfl as we have also defined %option noyywrap - +# and having -lfl doesn't work under Darwin for some reason. - Sean +$(LIBDIR)/$(STD_DRV).so: $(STD_DRV).c + @echo "std driver:" + $(CC) $(STD_DRV_NAME) $(CFLAGS) $(LDFLAGS) -o $(LIBDIR)/$(STD_DRV).so $< + +$(LIBDIR)/$(MT_DRV).so: $(MT_DRV).c + @echo "multi-threaded driver:" + $(CC) $(MT_DRV_NAME) $(CFLAGS_MT) $(LDFLAGS) -o $(LIBDIR)/$(MT_DRV).so $< + +$(LIBDIR): + -mkdir -p $(LIBDIR) + diff --git a/lib/megaco/src/flex/megaco_flex_scanner.erl b/lib/megaco/src/flex/megaco_flex_scanner.erl new file mode 100644 index 0000000000..e471412c13 --- /dev/null +++ b/lib/megaco/src/flex/megaco_flex_scanner.erl @@ -0,0 +1,230 @@ +%% +%% %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% +%% + +%%---------------------------------------------------------------------- +%% Purpose : Scanner for text encoded Megaco/H.248 messages +%%---------------------------------------------------------------------- + +-module(megaco_flex_scanner). + +-export([is_enabled/0, is_reentrant_enabled/0, is_scanner_port/2]). +-export([start/0, start/1, stop/1, scan/2]). + +-define(NUM_SCHED(), erlang:system_info(schedulers)). +-define(SCHED_ID(), erlang:system_info(scheduler_id)). +-define(SMP_SUPPORT_DEFAULT(), erlang:system_info(smp_support)). + +is_enabled() -> + case ?ENABLE_MEGACO_FLEX_SCANNER of + true -> + true; + _ -> + false + end. + +is_reentrant_enabled() -> + case ?MEGACO_REENTRANT_FLEX_SCANNER of + true -> + true; + _ -> + false + end. + +is_scanner_port(Port, Port) when is_port(Port) -> + true; +is_scanner_port(Port, Ports) when is_tuple(Ports) -> + is_own_port(Port, Ports); +is_scanner_port(_, _) -> + false. + +is_own_port(Port, Ports) -> + is_own_port(Port, size(Ports), Ports). + +is_own_port(_Port, 0, _Ports) -> + false; +is_own_port(Port, N, Ports) when (N > 0) -> + case element(N, Ports) of + Port -> + true; + _ -> + is_own_port(Port, N-1, Ports) + end. + + +%%---------------------------------------------------------------------- +%% Start the flex scanner +%%---------------------------------------------------------------------- + +start() -> + start(?SMP_SUPPORT_DEFAULT()). + +start(SMP) when ((SMP =:= true) orelse (SMP =:= false)) -> + (catch do_start(is_reentrant_enabled() andalso SMP)). + +do_start(SMP) -> + Path = lib_dir(), + erl_ddll:start(), + load_driver(Path), + PortOrPorts = open_drv_port(SMP), + {ok, PortOrPorts}. + + +lib_dir() -> + case code:priv_dir(megaco) of + {error, Reason} -> + throw({error, {priv_dir, Reason}}); + P when is_list(P) -> + P ++ "/lib" + end. + + +load_driver(Path) -> + case erl_ddll:load_driver(Path, drv_name()) of + ok -> + ok; + {error, Reason} -> + case (catch erl_ddll:format_error(Reason)) of + FormatReason when is_list(FormatReason) -> + throw({error, {load_driver, FormatReason}}); + _ -> + throw({error, {load_driver, Reason}}) + end + end. + + +open_drv_port(true) -> + open_drv_ports(?NUM_SCHED(), []); +open_drv_port(_) -> + open_drv_port(). + +open_drv_ports(0, Acc) -> + list_to_tuple(Acc); +open_drv_ports(N, Acc) when is_integer(N) andalso (N > 0) -> + Port = open_drv_port(), + open_drv_ports(N-1, [Port | Acc]). + +open_drv_port() -> + case (catch erlang:open_port({spawn, drv_name()}, [binary])) of + Port when is_port(Port) -> + Port; + {'EXIT', Reason} -> + erl_ddll:unload_driver(drv_name()), + throw({error, {open_port, Reason}}) + end. + +drv_name() -> + case erlang:system_info(threads) of + true -> + "megaco_flex_scanner_drv_mt"; + false -> + "megaco_flex_scanner_drv" + end. + + +%%---------------------------------------------------------------------- +%% Stop the flex scanner +%%---------------------------------------------------------------------- + +stop(Port) when is_port(Port) -> + erlang:port_close(Port), + erl_ddll:unload_driver(drv_name()), + stopped; +stop(Ports) when is_tuple(Ports) -> + stop(tuple_to_list(Ports)); +stop(Ports) when is_list(Ports) -> + lists:foreach(fun(Port) -> erlang:port_close(Port) end, Ports), + erl_ddll:unload_driver(drv_name()), + stopped. + + +%%---------------------------------------------------------------------- +%% Scan a message +%%---------------------------------------------------------------------- + +scan(Binary, Port) when is_port(Port) -> + do_scan(Binary, Port); +scan(Binary, Ports) when is_tuple(Ports) -> +%% p("scan -> entry with" +%% "~n Ports: ~p", [Ports]), + do_scan(Binary, select_port(Ports)). + +do_scan(Binary, Port) -> +%% p("do_scan -> entry with" +%% "~n Port: ~p", [Port]), + case erlang:port_control(Port, $s, Binary) of + [] -> + receive + {tokens, Tokens, LatestLine} -> +%% p("do_scan -> OK with:" +%% "~n length(Tokens): ~p" +%% "~n LatestLine: ~p", [length(Tokens), LatestLine]), + Vsn = version(Tokens), + {ok, Tokens, Vsn, LatestLine} + after 5000 -> +%% p("do_scan -> ERROR", []), + {error, "Driver term send failure", 1} + end; + Reason -> +%% p("do_scan -> port control failed: " +%% "~n Reason: ~p", [Reason]), + {error, Reason, 1} + end. + +select_port(Ports) -> + SchedId = ?SCHED_ID(), + %% lists:nth(SchedId, Ports). + element(SchedId, Ports). + +version([]) -> + 99; % Let the parser deal with this +version([{'SafeChars',_,"!/1"}|_]) -> + 1; +version([{'SafeChars',_,"megaco/1"}|_]) -> + 1; +version([{'SafeChars',_,"!/2"}|_]) -> + 2; +version([{'SafeChars',_,"megaco/2"}|_]) -> + 2; +version([{'SafeChars',_,"!/3"}|_]) -> + 3; +version([{'SafeChars',_,"megaco/3"}|_]) -> + 3; +version([{'SafeChars',_,[$!, $/ | Vstr]}|_]) -> + guess_version(Vstr); +version([{'SafeChars',_,[$m, $e, $g, $a, $c, $o, $/ | Vstr]}|_]) -> + guess_version(Vstr); +version([_|T]) -> + version(T). + + +guess_version([C]) when (48 =< C) and (C =< 57) -> + C-48; +guess_version(Str) when is_list(Str) -> + case (catch list_to_integer(Str)) of + I when is_integer(I) -> + I; + _ -> + 99 % Let the parser deal with this + end; +guess_version(_) -> + 99. % Let the parser deal with this + + +%% p(F, A) -> +%% io:format("~w [~p,~p] " ++ F ++ "~n", [?MODULE, self(), ?SCHED_ID() | A]). diff --git a/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src new file mode 100644 index 0000000000..b96a69415d --- /dev/null +++ b/lib/megaco/src/flex/megaco_flex_scanner_drv.flex.src @@ -0,0 +1,1943 @@ + /* + * %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% + * + * ---------------------------------------------------------------------- + * Purpose : Scanner for text encoded Megaco/H.248 messages + * ---------------------------------------------------------------------- + * + * Throughout this file the prefix mfs is used for megaco_flex_scanner. + * The reason is to get shorter function and variable names. + */ + +%option case-insensitive + + /* MEGACO_YY_LINENO_OPTION + * Note that this construction is intended to make it + * possible to generate flex files that either reports + * line-number or one that don't. + * See MEGACO_DUMMY_DECL_YY_LINENO and + * MEGACO_LINENO_OR_TOKENCOUNTER below. + */ +%MEGACO_YY_LINENO_OPTION% + +%MEGACO_YY_REENTRANT_OPTION% +%option noyywrap +%option noinput +%option nounput +%{ + +#define HAVE_UIO_H +#include "erl_driver.h" +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define TRUE 1 +#define FALSE 0 +#define SP 0x20 +#define HTAB 0x09 +#define CR 0x0d +#define LF 0x0a +#define SEMI_COLON 0x3b +#define BACKSLASH 0x5c +#define RBRKT 0x7b +#define NUL 0x0 + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + #define MEGACO_EXTENDED_MARKER ERL_DRV_EXTENDED_MARKER + #define MEGACO_DRIVER_FLAGS ERL_DRV_FLAG_USE_PORT_LOCKING + #define MEGACO_EXTENDED_MAJOR_VERSION ERL_DRV_EXTENDED_MAJOR_VERSION + #define MEGACO_EXTENDED_MINOR_VERSION ERL_DRV_EXTENDED_MINOR_VERSION +#else + #define MEGACO_EXTENDED_MARKER 0 + #define MEGACO_DRIVER_FLAGS 0 + #define MEGACO_EXTENDED_MAJOR_VERSION 0 + #define MEGACO_EXTENDED_MINOR_VERSION 0 +#endif + + +#define FREE(bufP) driver_free(bufP) +#define ALLOC(sz) driver_alloc(sz) +#define REALLOC(bufP, sz) driver_realloc(bufP, sz) + +#define YY_MAIN false + +// #define YY_FATAL_ERROR(msg) mfs_fatal_error(msg) + + +typedef struct { + ErlDrvPort port; + char* digit_map_name_ptr; + int digit_map_name_len; + char* digit_map_value_ptr; + int digit_map_value_len; + char* digit_map_start_ptr; + char* digit_map_short_ptr; + char* digit_map_long_ptr; + char* digit_map_duration_ptr; + int error; + char error_msg[512]; + char* text_buf; + char* text_ptr; + ErlDrvTermData* term_spec; + int term_spec_size; + int term_spec_index; + int token_counter; +} MfsErlDrvData; + +#if !defined(MEGACO_REENTRANT_FLEX_SCANNER) +static MfsErlDrvData mfs_drv_data; +#endif + +char flex_version[] = "%FLEX_VERSION%"; + +static ErlDrvTermData mfs_AddToken = 0; +static ErlDrvTermData mfs_AndAUDITSelectToken = 0; /* v3 */ +static ErlDrvTermData mfs_AuditCapToken = 0; +static ErlDrvTermData mfs_AuditToken = 0; +static ErlDrvTermData mfs_AuditValueToken = 0; +static ErlDrvTermData mfs_AuthToken = 0; +static ErlDrvTermData mfs_BothToken = 0; /* v3 */ +static ErlDrvTermData mfs_BothwayToken = 0; +static ErlDrvTermData mfs_BriefToken = 0; +static ErlDrvTermData mfs_BufferToken = 0; +static ErlDrvTermData mfs_COLON = 0; +static ErlDrvTermData mfs_COMMA = 0; +static ErlDrvTermData mfs_ContextAttrToken = 0; /* v3 */ +static ErlDrvTermData mfs_ContextAuditToken = 0; +static ErlDrvTermData mfs_ContextListToken = 0; /* v3 */ +static ErlDrvTermData mfs_CtxToken = 0; +static ErlDrvTermData mfs_DelayToken = 0; +static ErlDrvTermData mfs_DeleteToken = 0; +static ErlDrvTermData mfs_DigitMapDescriptor = 0; +static ErlDrvTermData mfs_DigitMapDescriptorToken = 0; +static ErlDrvTermData mfs_DigitMapToken = 0; +static ErlDrvTermData mfs_DigitMapValue = 0; +static ErlDrvTermData mfs_DirectionToken = 0; /* v3 */ +static ErlDrvTermData mfs_DiscardToken = 0; +static ErlDrvTermData mfs_DisconnectedToken = 0; +static ErlDrvTermData mfs_DurationToken = 0; +static ErlDrvTermData mfs_EQUAL = 0; +static ErlDrvTermData mfs_EmbedToken = 0; +static ErlDrvTermData mfs_EmergencyToken = 0; +static ErlDrvTermData mfs_EmergencyOffToken = 0; /* v3 */ +static ErlDrvTermData mfs_EmergencyValueToken = 0; /* v3 */ +static ErlDrvTermData mfs_ErrorToken = 0; +static ErlDrvTermData mfs_EventBufferToken = 0; +static ErlDrvTermData mfs_EventsToken = 0; +static ErlDrvTermData mfs_ExternalToken = 0; /* v3 */ +static ErlDrvTermData mfs_FailoverToken = 0; +static ErlDrvTermData mfs_ForcedToken = 0; +static ErlDrvTermData mfs_GREATER = 0; +static ErlDrvTermData mfs_GracefulToken = 0; +static ErlDrvTermData mfs_H221Token = 0; +static ErlDrvTermData mfs_H223Token = 0; +static ErlDrvTermData mfs_H226Token = 0; +static ErlDrvTermData mfs_HandOffToken = 0; +static ErlDrvTermData mfs_IEPSToken = 0; /* v3 */ +static ErlDrvTermData mfs_IllegalChar = 0; +static ErlDrvTermData mfs_ImmAckRequiredToken = 0; +static ErlDrvTermData mfs_InactiveToken = 0; +static ErlDrvTermData mfs_InSvcToken = 0; +static ErlDrvTermData mfs_IntsigDelayToken = 0; /* v3 */ +static ErlDrvTermData mfs_InternalToken = 0; /* v3 */ +static ErlDrvTermData mfs_InterruptByEventToken = 0; +static ErlDrvTermData mfs_InterruptByNewSignalsDescrToken = 0; +static ErlDrvTermData mfs_IsolateToken = 0; +static ErlDrvTermData mfs_IterationToken = 0; /* v3 */ +static ErlDrvTermData mfs_KeepActiveToken = 0; +static ErlDrvTermData mfs_LBRKT = 0; +static ErlDrvTermData mfs_LESSER = 0; +static ErlDrvTermData mfs_LSBRKT = 0; +static ErlDrvTermData mfs_LocalControlToken = 0; +static ErlDrvTermData mfs_LocalDescriptorToken = 0; +static ErlDrvTermData mfs_LocalToken = 0; +static ErlDrvTermData mfs_LockStepToken = 0; +static ErlDrvTermData mfs_LoopbackToken = 0; +static ErlDrvTermData mfs_MediaToken = 0; +static ErlDrvTermData mfs_MegacopToken = 0; +static ErlDrvTermData mfs_MethodToken = 0; +static ErlDrvTermData mfs_MessageSegmentToken = 0; +static ErlDrvTermData mfs_MgcIdToken = 0; +static ErlDrvTermData mfs_ModeToken = 0; +static ErlDrvTermData mfs_ModemToken = 0; +static ErlDrvTermData mfs_ModifyToken = 0; +static ErlDrvTermData mfs_MoveToken = 0; +static ErlDrvTermData mfs_MtpAddressToken = 0; +static ErlDrvTermData mfs_MuxToken = 0; +static ErlDrvTermData mfs_NEQUAL = 0; +static ErlDrvTermData mfs_NeverNotifyToken = 0; /* v3 */ +static ErlDrvTermData mfs_NotifyCompletionToken = 0; +static ErlDrvTermData mfs_NotifyImmediateToken = 0; /* v3 */ +static ErlDrvTermData mfs_NotifyRegulatedToken = 0; /* v3 */ +static ErlDrvTermData mfs_NotifyToken = 0; +static ErlDrvTermData mfs_Nx64kToken = 0; +static ErlDrvTermData mfs_ObservedEventsToken = 0; +static ErlDrvTermData mfs_OffToken = 0; +static ErlDrvTermData mfs_OnOffToken = 0; +static ErlDrvTermData mfs_OnToken = 0; +static ErlDrvTermData mfs_OnewayToken = 0; +static ErlDrvTermData mfs_OnewayBothToken = 0; /* v3 */ +static ErlDrvTermData mfs_OnewayExternalToken = 0; /* v3 */ +static ErlDrvTermData mfs_OrAUDITselectToken = 0; /* v3 */ +static ErlDrvTermData mfs_OtherReasonToken = 0; +static ErlDrvTermData mfs_OutOfSvcToken = 0; +static ErlDrvTermData mfs_PackagesToken = 0; +static ErlDrvTermData mfs_PendingToken = 0; +static ErlDrvTermData mfs_PriorityToken = 0; +static ErlDrvTermData mfs_ProfileToken = 0; +static ErlDrvTermData mfs_QuotedChars = 0; +static ErlDrvTermData mfs_RBRKT = 0; +static ErlDrvTermData mfs_RSBRKT = 0; +static ErlDrvTermData mfs_ReasonToken = 0; +static ErlDrvTermData mfs_RecvonlyToken = 0; +static ErlDrvTermData mfs_RemoteDescriptorToken = 0; +static ErlDrvTermData mfs_RemoteToken = 0; +static ErlDrvTermData mfs_RequestIDToken = 0; /* v3 */ +static ErlDrvTermData mfs_ReplyToken = 0; +static ErlDrvTermData mfs_ReservedGroupToken = 0; +static ErlDrvTermData mfs_ReservedValueToken = 0; +static ErlDrvTermData mfs_ResetEventsDescriptorToken = 0; /* v3 */ +static ErlDrvTermData mfs_ResponseAckToken = 0; +static ErlDrvTermData mfs_RestartToken = 0; +static ErlDrvTermData mfs_SEP = 0; +static ErlDrvTermData mfs_SafeChars = 0; +static ErlDrvTermData mfs_SegmentationCompleteToken = 0; /* v3 */ +static ErlDrvTermData mfs_SendonlyToken = 0; +static ErlDrvTermData mfs_SendrecvToken = 0; +static ErlDrvTermData mfs_ServiceChangeAddressToken = 0; +static ErlDrvTermData mfs_ServiceChangeIncompleteToken = 0; /* v3 */ +static ErlDrvTermData mfs_ServiceChangeToken = 0; +static ErlDrvTermData mfs_ServiceStatesToken = 0; +static ErlDrvTermData mfs_ServicesToken = 0; +static ErlDrvTermData mfs_SignalListToken = 0; +static ErlDrvTermData mfs_SignalTypeToken = 0; +static ErlDrvTermData mfs_SignalsToken = 0; +static ErlDrvTermData mfs_StatsToken = 0; +static ErlDrvTermData mfs_StreamToken = 0; +static ErlDrvTermData mfs_SubtractToken = 0; +static ErlDrvTermData mfs_SynchISDNToken = 0; +static ErlDrvTermData mfs_TerminationStateToken = 0; +static ErlDrvTermData mfs_TestToken = 0; +static ErlDrvTermData mfs_TimeOutToken = 0; +static ErlDrvTermData mfs_TimeStampToken = 0; /* OTP-5042 */ +static ErlDrvTermData mfs_TopologyToken = 0; +static ErlDrvTermData mfs_TransToken = 0; +static ErlDrvTermData mfs_V18Token = 0; +static ErlDrvTermData mfs_V22Token = 0; +static ErlDrvTermData mfs_V22bisToken = 0; +static ErlDrvTermData mfs_V32Token = 0; +static ErlDrvTermData mfs_V32bisToken = 0; +static ErlDrvTermData mfs_V34Token = 0; +static ErlDrvTermData mfs_V76Token = 0; +static ErlDrvTermData mfs_V90Token = 0; +static ErlDrvTermData mfs_V91Token = 0; +static ErlDrvTermData mfs_VersionToken = 0; +static ErlDrvTermData mfs_asn1_NOVALUE = 0; +static ErlDrvTermData mfs_endOfMessage = 0; +static ErlDrvTermData mfs_PropertyParm = 0; +static ErlDrvTermData mfs_ErrorDescriptor = 0; + +/* MEGACO_DUMMY_DECL_YY_LINENO + * Note that this construction is intended to make it + * possible to generate flex files that either reports + * line-number or one that don't. + * See MEGACO_YY_LINENO_OPTION above and + * MEGACO_LINENO_OR_TOKENCOUNTER below. + */ +#if !defined(MEGACO_REENTRANT_FLEX_SCANNER) +%MEGACO_DUMMY_DECL_YY_LINENO% +#endif + +/* +static ErlDrvPort mfs_port = 0; +static char* mfs_digit_map_name_ptr = 0; +static int mfs_digit_map_name_len = 0; +static char* mfs_digit_map_value_ptr = 0; +static int mfs_digit_map_value_len = 0; +static char* mfs_digit_map_start_ptr = 0; +static char* mfs_digit_map_short_ptr = 0; +static char* mfs_digit_map_long_ptr = 0; +static char* mfs_digit_map_duration_ptr = 0; +static int mfs_error = FALSE; +static char mfs_error_msg[512]; +static char* mfs_text_buf = 0; +static char* mfs_text_ptr = 0; +static ErlDrvTermData* mfs_term_spec = 0; +static int mfs_term_spec_size = 0; +static int mfs_term_spec_index = 0; +static int mfs_token_counter = 0; +*/ + + +static void mfs_alloc_failed(MfsErlDrvData* dataP, char* msg, int sz); +static void mfs_fatal_error(MfsErlDrvData* dataP, char* msg); +static void mfs_ensure_term_spec(MfsErlDrvData* dataP, int size); + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + +static void mfs_short_load_token(ErlDrvTermData token_tag, + yyscan_t yyscanner); +static void mfs_lower_load_token(ErlDrvTermData token_tag, int is_empty, + yyscan_t yyscanner); +static void mfs_octet_load_token(ErlDrvTermData token_tag, int is_empty, + yyscan_t yyscanner); +static void mfs_load_property_groups(MfsErlDrvData* dataP, yyscan_t yyscanner); +static void mfs_load_map_name(yyscan_t yyscanner); +static void mfs_load_map_value(yyscan_t yyscanner); +static void mfs_load_map_timer(yyscan_t yyscanner); +static void mfs_load_map_token(yyscan_t yyscanner); + +#else + +static void mfs_short_load_token(ErlDrvTermData token_tag); +static void mfs_lower_load_token(ErlDrvTermData token_tag, int is_empty); +static void mfs_octet_load_token(ErlDrvTermData token_tag, int is_empty); +static void mfs_load_property_groups(MfsErlDrvData* dataP); +static void mfs_load_map_name(); +static void mfs_load_map_value(); +static void mfs_load_map_timer(); +static void mfs_load_map_token(); + +#endif + +static ErlDrvData mfs_start(ErlDrvPort port, char *buf); +static void mfs_stop(ErlDrvData handle); +static void mfs_command(ErlDrvData handle, + char *buf, int buf_len); +static int mfs_control(ErlDrvData handle, + unsigned int command, + char *buf, int buf_len, + char **res_buf, int res_buf_len); +static void mfs_finish(void); + +/* + * The driver entry + */ + +static ErlDrvEntry mfs_entry = { + NULL, /* init, always NULL for dynamic drivers */ + mfs_start, /* start, called when port is opened */ + mfs_stop, /* stop, called when port is closed */ + mfs_command, /* output, called when erlang has sent */ + NULL, /* ready_input, called when input descriptor ready */ + NULL, /* ready_output, called when output descriptor ready */ + MEGACO_DRV_NAME, /* char *driver_name, the arg to open_port */ + mfs_finish, /* finish, called when unloaded */ + NULL, /* void * that is not used (BC) */ + mfs_control, /* control, port_control callback */ + NULL, /* timeout, called on timeouts */ + NULL, /* outputv, vector output interface */ + NULL, /* ready_async, called after an asynchronous call has completed */ + NULL, /* flush, port is about to be closed */ + NULL, /* call, a syncronous call into the driver */ + NULL, /* event, event selected by driver_event() has occurred */ + MEGACO_EXTENDED_MARKER, /* extended_marker, which we use if reentrant */ + MEGACO_EXTENDED_MAJOR_VERSION, /* major_version, ... */ + MEGACO_EXTENDED_MINOR_VERSION, /* minor_version, ... */ + MEGACO_DRIVER_FLAGS, /* driver_flags, used for port lock indication */ + NULL, /* handle2, emulator internal use */ + NULL /* process_exit, Called when a process monitor fires */ +#if defined(MEGACO_DRV_ENTRY_HAS_STOP_SELECT) + ,NULL /* stop_select, Called to close an event object */ +#endif +}; + + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + +#define LOAD_TOKEN(TokenTag) mfs_lower_load_token(TokenTag, FALSE, yyscanner) +#define LOAD_EMPTY_TOKEN(TokenTag) mfs_lower_load_token(TokenTag, TRUE, yyscanner) +#define LOAD_SHORT_TOKEN(TokenTag) mfs_short_load_token(TokenTag, yyscanner) +#define LOAD_OCTET_TOKEN(TokenTag) mfs_octet_load_token(TokenTag, FALSE, yyscanner) +#define LOAD_EMPTY_OCTET_TOKEN(TokenTag) mfs_octet_load_token(TokenTag, TRUE, yyscanner) +#define LOAD_MAP_NAME() mfs_load_map_name(yyscanner) +#define LOAD_MAP_TIMER() mfs_load_map_timer(yyscanner) +#define LOAD_MAP_TOKEN() mfs_load_map_token(yyscanner) +#define LOAD_MAP_VALUE() mfs_load_map_value(yyscanner) +#define LOAD_PROP_GRPS(dataP) mfs_load_property_groups(dataP, yyscanner) + +#else + +#define LOAD_TOKEN(TokenTag) mfs_lower_load_token(TokenTag, FALSE) +#define LOAD_EMPTY_TOKEN(TokenTag) mfs_lower_load_token(TokenTag, TRUE) +#define LOAD_SHORT_TOKEN(TokenTag) mfs_short_load_token(TokenTag) +#define LOAD_OCTET_TOKEN(TokenTag) mfs_octet_load_token(TokenTag, FALSE) +#define LOAD_EMPTY_OCTET_TOKEN(TokenTag) mfs_octet_load_token(TokenTag, TRUE) +#define LOAD_MAP_NAME() mfs_load_map_name() +#define LOAD_MAP_TIMER() mfs_load_map_timer() +#define LOAD_MAP_TOKEN() mfs_load_map_token() +#define LOAD_MAP_VALUE() mfs_load_map_value() +#define LOAD_PROP_GRPS(dataP) mfs_load_property_groups(dataP) + +#endif + +/* OTP-4236 */ +#define ASSIGN_TERM_SPEC(dataP, what) \ +{ \ + if (dataP->term_spec != NULL) { \ + dataP->term_spec[dataP->term_spec_index++] = what; \ + } \ +} + +%} + +%x SKIP_RBRKT MTP_HEXDIG LOCAL_OCTETS REMOTE_OCTETS +%x MAP_NAME MAP_OPT_LBRKT MAP_VALUE MAP_SKIP_COMMA MAP_BODY +%x QUOTED_CHARS SKIP_DQUOTE + +digit ([0-9]) +alpha ([a-zA-Z]) +hexdig ([0-9a-fA-F]) +sp (\x20) +htab (\x09) +cr (\x0D) +lf (\x0A) +slash (\/) +dquote (\") +colon (\:) +dot (\.) +wsp ({sp}|{htab}) +eol ({cr}|({cr}{lf})|{lf}) +safechar ({digit}|{alpha}|[\+\-\&\!\_\/\'\?\@\^\`\~\*\$\\\(\)\%\|\.]) +restchar ([\;\[\]\{\}\:\,\#\<\>\=]) +octet ((\\\})|[\x01-\x7C\x7E-\xFF]) + +comment (\;({safechar}|{restchar}|{wsp}|\x22)*{eol}) +lwsp ({wsp}|{comment}|{eol})* + +equal ({lwsp}\={lwsp}) +nequal ({lwsp}\#{lwsp}) +lesser ({lwsp}\<{lwsp}) +greater ({lwsp}\>{lwsp}) +lbrkt ({lwsp}\{{lwsp}) +rbrkt ({lwsp}\}{lwsp}) +lsbrkt ({lwsp}\[{lwsp}) +rsbrkt ({lwsp}\]{lwsp}) +lpar ({lwsp}\({lwsp}) +rpar ({lwsp}\){lwsp}) +vbar ({lwsp}\|{lwsp}) +comma ({lwsp}\,{lwsp}) +sep (({wsp}|{eol}|{comment}){lwsp})+ +opt ((o\-)?) +wild ((w\-)?) + +%% + +<SKIP_RBRKT>{rbrkt} BEGIN(INITIAL); + +{digit}{8,8}t{digit}{8,8} LOAD_TOKEN(mfs_TimeStampToken); /* OTP-5042 */ + +(MTP){lbrkt} BEGIN(MTP_HEXDIG); +<MTP_HEXDIG>{hexdig}{4,8} {LOAD_TOKEN(mfs_MtpAddressToken); BEGIN(SKIP_RBRKT);} + +((Local)|L){lbrkt} BEGIN(LOCAL_OCTETS); +<LOCAL_OCTETS>{rbrkt} {LOAD_EMPTY_OCTET_TOKEN(mfs_LocalDescriptorToken); BEGIN(INITIAL);} +<LOCAL_OCTETS>{octet}+ {LOAD_OCTET_TOKEN(mfs_LocalDescriptorToken); BEGIN(SKIP_RBRKT);} + +((Remote)|R){lbrkt} BEGIN(REMOTE_OCTETS); +<REMOTE_OCTETS>{rbrkt} {LOAD_EMPTY_OCTET_TOKEN(mfs_RemoteDescriptorToken); BEGIN(INITIAL);} +<REMOTE_OCTETS>{octet}+ {LOAD_OCTET_TOKEN(mfs_RemoteDescriptorToken); BEGIN(SKIP_RBRKT);} + +((DigitMap)|DM) LOAD_TOKEN(mfs_DigitMapToken); +((DigitMap)|DM){equal} BEGIN(MAP_NAME); +((DigitMap)|DM){equal}{lbrkt} BEGIN(MAP_VALUE); +((DigitMap)|DM){lbrkt} BEGIN(MAP_VALUE); + +<MAP_NAME>{safechar}+ {LOAD_MAP_NAME(); BEGIN(MAP_OPT_LBRKT);} + +<MAP_OPT_LBRKT>{lbrkt} BEGIN(MAP_VALUE); +<MAP_OPT_LBRKT><<EOF>> {LOAD_MAP_TOKEN(); LOAD_TOKEN(mfs_endOfMessage); BEGIN(INITIAL); yyterminate();} +<MAP_OPT_LBRKT>.|\n {LOAD_MAP_TOKEN(); yyless(0); BEGIN(INITIAL);} + +<MAP_VALUE>t{colon}{digit}{1,2} {LOAD_MAP_TIMER(); BEGIN(MAP_SKIP_COMMA);} +<MAP_VALUE>s{colon}{digit}{1,2} {LOAD_MAP_TIMER(); BEGIN(MAP_SKIP_COMMA);} +<MAP_VALUE>l{colon}{digit}{1,2} {LOAD_MAP_TIMER(); BEGIN(MAP_SKIP_COMMA);} +<MAP_VALUE>z{colon}{digit}{1,2} {LOAD_MAP_TIMER(); BEGIN(MAP_SKIP_COMMA);} +<MAP_VALUE>.|\n {yyless(0); BEGIN(MAP_BODY);} + +<MAP_SKIP_COMMA>{comma} BEGIN(MAP_VALUE); + +<MAP_BODY>{octet}+ {LOAD_MAP_VALUE(); LOAD_MAP_TOKEN(); BEGIN(SKIP_RBRKT);} + +{equal} LOAD_SHORT_TOKEN(mfs_EQUAL); +{colon} LOAD_SHORT_TOKEN(mfs_COLON); +{lbrkt} LOAD_SHORT_TOKEN(mfs_LBRKT); +{rbrkt} LOAD_SHORT_TOKEN(mfs_RBRKT); +{lsbrkt} LOAD_SHORT_TOKEN(mfs_LSBRKT); +{rsbrkt} LOAD_SHORT_TOKEN(mfs_RSBRKT); +{comma} LOAD_SHORT_TOKEN(mfs_COMMA); +{nequal} LOAD_SHORT_TOKEN(mfs_NEQUAL); +{lesser} LOAD_SHORT_TOKEN(mfs_LESSER); +{greater} LOAD_SHORT_TOKEN(mfs_GREATER); +{sep} LOAD_SHORT_TOKEN(mfs_SEP); + +{dquote} BEGIN(QUOTED_CHARS); + +<QUOTED_CHARS>{dquote} {LOAD_EMPTY_TOKEN(mfs_QuotedChars); BEGIN(INITIAL);} +<QUOTED_CHARS>({safechar}|{restchar}|{wsp})+ {LOAD_TOKEN(mfs_QuotedChars); BEGIN(SKIP_DQUOTE);} + +<SKIP_DQUOTE>{dquote} BEGIN(INITIAL); + +{opt}{wild}add LOAD_TOKEN(mfs_AddToken); +{opt}{wild}a LOAD_TOKEN(mfs_AddToken); +andlgc LOAD_TOKEN(mfs_AndAUDITSelectToken); +audit LOAD_TOKEN(mfs_AuditToken); +at LOAD_TOKEN(mfs_AuditToken); +{opt}{wild}auditcapability LOAD_TOKEN(mfs_AuditCapToken); +{opt}{wild}ac LOAD_TOKEN(mfs_AuditCapToken); +{opt}{wild}auditvalue LOAD_TOKEN(mfs_AuditValueToken); +{opt}{wild}av LOAD_TOKEN(mfs_AuditValueToken); +authentication LOAD_TOKEN(mfs_AuthToken); +au LOAD_TOKEN(mfs_AuthToken); +both LOAD_TOKEN(mfs_BothToken); +b LOAD_TOKEN(mfs_BothToken); +bothway LOAD_TOKEN(mfs_BothwayToken); +bw LOAD_TOKEN(mfs_BothwayToken); +brief LOAD_TOKEN(mfs_BriefToken); +br LOAD_TOKEN(mfs_BriefToken); +buffer LOAD_TOKEN(mfs_BufferToken); +bf LOAD_TOKEN(mfs_BufferToken); +context LOAD_TOKEN(mfs_CtxToken); +c LOAD_TOKEN(mfs_CtxToken); +contextattr LOAD_TOKEN(mfs_ContextAttrToken); +ct LOAD_TOKEN(mfs_ContextAttrToken); +contextaudit LOAD_TOKEN(mfs_ContextAuditToken); +ca LOAD_TOKEN(mfs_ContextAuditToken); +contextlist LOAD_TOKEN(mfs_ContextListToken); +clt LOAD_TOKEN(mfs_ContextListToken); +spadirection LOAD_TOKEN(mfs_DirectionToken); +direction LOAD_TOKEN(mfs_DirectionToken); +spadi LOAD_TOKEN(mfs_DirectionToken); +di LOAD_TOKEN(mfs_DirectionToken); +discard LOAD_TOKEN(mfs_DiscardToken); +ds LOAD_TOKEN(mfs_DiscardToken); +disconnected LOAD_TOKEN(mfs_DisconnectedToken); +dc LOAD_TOKEN(mfs_DisconnectedToken); +delay LOAD_TOKEN(mfs_DelayToken); +dl LOAD_TOKEN(mfs_DelayToken); +delete LOAD_TOKEN(mfs_DeleteToken); +de LOAD_TOKEN(mfs_DeleteToken); +duration LOAD_TOKEN(mfs_DurationToken); +dr LOAD_TOKEN(mfs_DurationToken); +embed LOAD_TOKEN(mfs_EmbedToken); +em LOAD_TOKEN(mfs_EmbedToken); +emergency LOAD_TOKEN(mfs_EmergencyToken); +eg LOAD_TOKEN(mfs_EmergencyToken); +emergencyoff LOAD_TOKEN(mfs_EmergencyOffToken); +emergencyofftoken LOAD_TOKEN(mfs_EmergencyOffToken); +ego LOAD_TOKEN(mfs_EmergencyOffToken); +emergencyvalue LOAD_TOKEN(mfs_EmergencyValueToken); +egv LOAD_TOKEN(mfs_EmergencyValueToken); +error LOAD_TOKEN(mfs_ErrorToken); +er LOAD_TOKEN(mfs_ErrorToken); +eventbuffer LOAD_TOKEN(mfs_EventBufferToken); +eb LOAD_TOKEN(mfs_EventBufferToken); +events LOAD_TOKEN(mfs_EventsToken); +e LOAD_TOKEN(mfs_EventsToken); +external LOAD_TOKEN(mfs_ExternalToken); +ex LOAD_TOKEN(mfs_ExternalToken); +failover LOAD_TOKEN(mfs_FailoverToken); +fl LOAD_TOKEN(mfs_FailoverToken); +forced LOAD_TOKEN(mfs_ForcedToken); +fo LOAD_TOKEN(mfs_ForcedToken); +graceful LOAD_TOKEN(mfs_GracefulToken); +gr LOAD_TOKEN(mfs_GracefulToken); +h221 LOAD_TOKEN(mfs_H221Token); +h223 LOAD_TOKEN(mfs_H223Token); +h226 LOAD_TOKEN(mfs_H226Token); +handoff LOAD_TOKEN(mfs_HandOffToken); +ho LOAD_TOKEN(mfs_HandOffToken); +iepscall LOAD_TOKEN(mfs_IEPSToken); +ieps LOAD_TOKEN(mfs_IEPSToken); +inactive LOAD_TOKEN(mfs_InactiveToken); +in LOAD_TOKEN(mfs_InactiveToken); +immackrequired LOAD_TOKEN(mfs_ImmAckRequiredToken); +ia LOAD_TOKEN(mfs_ImmAckRequiredToken); +inservice LOAD_TOKEN(mfs_InSvcToken); +iv LOAD_TOKEN(mfs_InSvcToken); +internal LOAD_TOKEN(mfs_InternalToken); +it LOAD_TOKEN(mfs_InternalToken); +intersignal LOAD_TOKEN(mfs_IntsigDelayToken); +spais LOAD_TOKEN(mfs_IntsigDelayToken); +isolate LOAD_TOKEN(mfs_IsolateToken); +is LOAD_TOKEN(mfs_IsolateToken); +intbyevent LOAD_TOKEN(mfs_InterruptByEventToken); +ibe LOAD_TOKEN(mfs_InterruptByEventToken); +intbysigdescr LOAD_TOKEN(mfs_InterruptByNewSignalsDescrToken); +ibs LOAD_TOKEN(mfs_InterruptByNewSignalsDescrToken); +iteration LOAD_TOKEN(mfs_IterationToken); +ir LOAD_TOKEN(mfs_IterationToken); +keepactive LOAD_TOKEN(mfs_KeepActiveToken); +ka LOAD_TOKEN(mfs_KeepActiveToken); +local LOAD_TOKEN(mfs_LocalToken); +l LOAD_TOKEN(mfs_LocalToken); +localcontrol LOAD_TOKEN(mfs_LocalControlToken); +lockstep LOAD_TOKEN(mfs_LockStepToken); +sp LOAD_TOKEN(mfs_LockStepToken); +o LOAD_TOKEN(mfs_LocalControlToken); +loopback LOAD_TOKEN(mfs_LoopbackToken); +lb LOAD_TOKEN(mfs_LoopbackToken); +media LOAD_TOKEN(mfs_MediaToken); +m LOAD_TOKEN(mfs_MediaToken); +megaco LOAD_TOKEN(mfs_MegacopToken); +! LOAD_TOKEN(mfs_MegacopToken); +segment LOAD_TOKEN(mfs_MessageSegmentToken); +sm LOAD_TOKEN(mfs_MessageSegmentToken); +method LOAD_TOKEN(mfs_MethodToken); +mt LOAD_TOKEN(mfs_MethodToken); +mgcidtotry LOAD_TOKEN(mfs_MgcIdToken); +mg LOAD_TOKEN(mfs_MgcIdToken); +mode LOAD_TOKEN(mfs_ModeToken); +mo LOAD_TOKEN(mfs_ModeToken); +{opt}modify LOAD_TOKEN(mfs_ModifyToken); +{opt}mf LOAD_TOKEN(mfs_ModifyToken); +modem LOAD_TOKEN(mfs_ModemToken); +md LOAD_TOKEN(mfs_ModemToken); +{opt}move LOAD_TOKEN(mfs_MoveToken); +{opt}mv LOAD_TOKEN(mfs_MoveToken); +mux LOAD_TOKEN(mfs_MuxToken); +mx LOAD_TOKEN(mfs_MuxToken); +nevernotify LOAD_TOKEN(mfs_NeverNotifyToken); +nbnn LOAD_TOKEN(mfs_NeverNotifyToken); +{opt}{wild}notify LOAD_TOKEN(mfs_NotifyToken); +{opt}{wild}n LOAD_TOKEN(mfs_NotifyToken); +notifycompletion LOAD_TOKEN(mfs_NotifyCompletionToken); +nc LOAD_TOKEN(mfs_NotifyCompletionToken); +immediatenotify LOAD_TOKEN(mfs_NotifyImmediateToken); +nbin LOAD_TOKEN(mfs_NotifyImmediateToken); +regulatednotify LOAD_TOKEN(mfs_NotifyRegulatedToken); +nbrn LOAD_TOKEN(mfs_NotifyRegulatedToken); +nx64kservice LOAD_TOKEN(mfs_Nx64kToken); +n64 LOAD_TOKEN(mfs_Nx64kToken); +observedevents LOAD_TOKEN(mfs_ObservedEventsToken); +oe LOAD_TOKEN(mfs_ObservedEventsToken); +oneway LOAD_TOKEN(mfs_OnewayToken); +ow LOAD_TOKEN(mfs_OnewayToken); +onewayboth LOAD_TOKEN(mfs_OnewayBothToken); +owb LOAD_TOKEN(mfs_OnewayBothToken); +onewayexternal LOAD_TOKEN(mfs_OnewayExternalToken); +owe LOAD_TOKEN(mfs_OnewayExternalToken); +off LOAD_TOKEN(mfs_OffToken); +on LOAD_TOKEN(mfs_OnToken); +onoff LOAD_TOKEN(mfs_OnOffToken); +oo LOAD_TOKEN(mfs_OnOffToken); +orlgc LOAD_TOKEN(mfs_OrAUDITselectToken); +otherreason LOAD_TOKEN(mfs_OtherReasonToken); +or LOAD_TOKEN(mfs_OtherReasonToken); +outofservice LOAD_TOKEN(mfs_OutOfSvcToken); +os LOAD_TOKEN(mfs_OutOfSvcToken); +packages LOAD_TOKEN(mfs_PackagesToken); +pg LOAD_TOKEN(mfs_PackagesToken); +pending LOAD_TOKEN(mfs_PendingToken); +pn LOAD_TOKEN(mfs_PendingToken); +priority LOAD_TOKEN(mfs_PriorityToken); +pr LOAD_TOKEN(mfs_PriorityToken); +profile LOAD_TOKEN(mfs_ProfileToken); +pf LOAD_TOKEN(mfs_ProfileToken); +reason LOAD_TOKEN(mfs_ReasonToken); +re LOAD_TOKEN(mfs_ReasonToken); +receiveonly LOAD_TOKEN(mfs_RecvonlyToken); +rc LOAD_TOKEN(mfs_RecvonlyToken); +reply LOAD_TOKEN(mfs_ReplyToken); +p LOAD_TOKEN(mfs_ReplyToken); +reseteventsdescriptor LOAD_TOKEN(mfs_ResetEventsDescriptorToken); +rse LOAD_TOKEN(mfs_ResetEventsDescriptorToken); +transactionresponseack LOAD_TOKEN(mfs_ResponseAckToken); +k LOAD_TOKEN(mfs_ResponseAckToken); +restart LOAD_TOKEN(mfs_RestartToken); +rs LOAD_TOKEN(mfs_RestartToken); +remote LOAD_TOKEN(mfs_RemoteToken); +r LOAD_TOKEN(mfs_RemoteToken); +sparequestid LOAD_TOKEN(mfs_RequestIDToken); +requestid LOAD_TOKEN(mfs_RequestIDToken); +sparq LOAD_TOKEN(mfs_RequestIDToken); +rq LOAD_TOKEN(mfs_RequestIDToken); +reservedgroup LOAD_TOKEN(mfs_ReservedGroupToken); +rg LOAD_TOKEN(mfs_ReservedGroupToken); +reservedvalue LOAD_TOKEN(mfs_ReservedValueToken); +rv LOAD_TOKEN(mfs_ReservedValueToken); +end LOAD_TOKEN(mfs_SegmentationCompleteToken); +& LOAD_TOKEN(mfs_SegmentationCompleteToken); +sendonly LOAD_TOKEN(mfs_SendonlyToken); +so LOAD_TOKEN(mfs_SendonlyToken); +sendreceive LOAD_TOKEN(mfs_SendrecvToken); +sr LOAD_TOKEN(mfs_SendrecvToken); +services LOAD_TOKEN(mfs_ServicesToken); +sv LOAD_TOKEN(mfs_ServicesToken); +servicestates LOAD_TOKEN(mfs_ServiceStatesToken); +si LOAD_TOKEN(mfs_ServiceStatesToken); +{opt}{wild}servicechange LOAD_TOKEN(mfs_ServiceChangeToken); +{opt}{wild}sc LOAD_TOKEN(mfs_ServiceChangeToken); +servicechangeaddress LOAD_TOKEN(mfs_ServiceChangeAddressToken); +ad LOAD_TOKEN(mfs_ServiceChangeAddressToken); +servicechangeinc LOAD_TOKEN(mfs_ServiceChangeIncompleteToken); +sic LOAD_TOKEN(mfs_ServiceChangeIncompleteToken); +signallist LOAD_TOKEN(mfs_SignalListToken); +sl LOAD_TOKEN(mfs_SignalListToken); +signals LOAD_TOKEN(mfs_SignalsToken); +sg LOAD_TOKEN(mfs_SignalsToken); +signaltype LOAD_TOKEN(mfs_SignalTypeToken); +sy LOAD_TOKEN(mfs_SignalTypeToken); +statistics LOAD_TOKEN(mfs_StatsToken); +sa LOAD_TOKEN(mfs_StatsToken); +stream LOAD_TOKEN(mfs_StreamToken); +st LOAD_TOKEN(mfs_StreamToken); +{opt}{wild}subtract LOAD_TOKEN(mfs_SubtractToken); +{opt}{wild}s LOAD_TOKEN(mfs_SubtractToken); +synchisdn LOAD_TOKEN(mfs_SynchISDNToken); +sn LOAD_TOKEN(mfs_SynchISDNToken); +terminationstate LOAD_TOKEN(mfs_TerminationStateToken); +ts LOAD_TOKEN(mfs_TerminationStateToken); +test LOAD_TOKEN(mfs_TestToken); +te LOAD_TOKEN(mfs_TestToken); +timeout LOAD_TOKEN(mfs_TimeOutToken); +to LOAD_TOKEN(mfs_TimeOutToken); +topology LOAD_TOKEN(mfs_TopologyToken); +tp LOAD_TOKEN(mfs_TopologyToken); +transaction LOAD_TOKEN(mfs_TransToken); +t LOAD_TOKEN(mfs_TransToken); +v18 LOAD_TOKEN(mfs_V18Token); +v22 LOAD_TOKEN(mfs_V22Token); +v22b LOAD_TOKEN(mfs_V22bisToken); +v32 LOAD_TOKEN(mfs_V32Token); +v32b LOAD_TOKEN(mfs_V32bisToken); +v34 LOAD_TOKEN(mfs_V34Token); +v76 LOAD_TOKEN(mfs_V76Token); +v90 LOAD_TOKEN(mfs_V90Token); +v91 LOAD_TOKEN(mfs_V91Token); +version LOAD_TOKEN(mfs_VersionToken); +v LOAD_TOKEN(mfs_VersionToken); +({safechar})+ LOAD_TOKEN(mfs_SafeChars); + +<<EOF>> {LOAD_SHORT_TOKEN(mfs_endOfMessage); BEGIN(INITIAL); yyterminate();} +<*>.|\n {LOAD_TOKEN(mfs_IllegalChar); BEGIN(INITIAL); yyterminate();} + +%% + +/* MEGACO_LINENO_OR_TOKENCOUNTER + * Note that this construction is intended to make it + * possible to generate flex files that either reports + * line-number or one that don't. + * See MEGACO_YY_LINENO_OPTION and + * MEGACO_DUMMY_DECL_YY_LINENO above. + */ + +#if defined(MEGACO_LINENO) +#define LINENO_OR_TOKENCNT(P) yylineno +#else +#define LINENO_OR_TOKENCNT(P) P->token_counter +#endif + + +/* #define MFS_DEBUG true */ /* temporary */ +#if defined(MFS_DEBUG) +# define DBG( proto ) printf proto +# define DBG_BUF(func, bufName, buf, bufSz) mfs_dbg_buf_print(func, bufName, buf, bufSz) +#else +# define DBG( proto ) ((void) 0) +# define DBG_BUF(func, bufName, buf, bufSz) ((void) 0) +#endif /* if defined(MFS_DEBUG) */ + + +#if defined(MFS_DEBUG) + +#define CHUNK 16 + +static void hexdump(unsigned char *buf, int bufsz) +{ + int i,j; + int count; + + /* do this in chunks of CHUNK bytes */ + for (i=0; i<bufsz; i+=CHUNK) { + /* show the offset */ + printf("0x%06x ", i); + + /* max of CHUNK or remaining bytes */ + count = ((bufsz-i) > CHUNK ? CHUNK : bufsz-i); + + /* show the bytes */ + for (j=0; j<count; j++) { + if (j==CHUNK/2) printf(" "); + printf("%02x ",buf[i+j]); + } + + /* pad with spaces if less than CHUNK */ + for (j=count; j<CHUNK; j++) { + if (j==CHUNK/2) printf(" "); + printf(" "); + } + + /* divider between hex and ascii */ + printf(" "); + + for (j=0; j<count; j++) + printf("%c",(isprint(buf[i+j]) ? buf[i+j] : '.')); + + printf("\n"); + } +} + +static void mfs_dbg_buf_print(char* func, char* bufName, char* buf, int len) +{ + printf("%s -> %s (%d):\n", func, bufName, len); + hexdump((unsigned char*) buf, len); +} + + +#endif /* if defined(MFS_DEBUG) */ + +static void mfs_alloc_failed(MfsErlDrvData* dataP, char* msg, int sz) +{ + /* + * Make sure we are not allready in error state + */ + if (!dataP->error) { + + /* + * Make sure that there is room in the buffer: + * length of msg + 10 chars for the ' of %d bytes' + * + 10 chars for the size value... + * This is really overkill since the msg string is never + * longer then 50 chars, but sinze this function is + * called when we have run out of memory... + */ + + int msg_len = strlen(msg); + if ((10 + 10 + msg_len) < sizeof(dataP->error_msg)) { + if (0 >= sprintf(dataP->error_msg, "%s of %d bytes", msg, sz)) { + mfs_fatal_error(dataP, msg); + } + } else { + mfs_fatal_error(dataP, msg); + } + dataP->error = TRUE; + } +} + + +static void mfs_ensure_term_spec(MfsErlDrvData* dataP, int size) +{ + DBG( ("mfs_ensure_term_spec -> entry with" + "\n size: %d" + "\nwhen" + "\n spec_index: %d" + "\n spec_size: %d" + "\n", size, dataP->term_spec_index, dataP->term_spec_size) ); + + /* OTP-4236 - BEGIN */ + if ((dataP->term_spec_index + size) >= dataP->term_spec_size) { + void *tmp; + + DBG( ("mfs_ensure_term_spec -> allocate more memory when" + "\n term_spec_index: %d" + "\n term_spec_size: %d\n", + dataP->term_spec_index, dataP->term_spec_size) ); + + dataP->term_spec_size = (dataP->term_spec_size * 2) + size; + + DBG( ("mfs_ensure_term_spec -> " + "term_spec is at 0x%X, new term_spec_size is %d\n", + (unsigned int) dataP->term_spec, dataP->term_spec_size) ); + + tmp = REALLOC(dataP->term_spec, + dataP->term_spec_size * sizeof(ErlDrvTermData)); + + if (tmp == NULL) { + /* + * Ouch, we did'nt get any new memory. + * Just give ut. I.e. free the memory we have (note that + * the assign macro tests the buffer before assigning). + */ + FREE(dataP->term_spec); + dataP->term_spec = NULL; + + mfs_alloc_failed(dataP, "failed reallocating term spec buffer", + dataP->term_spec_size * sizeof(ErlDrvTermData)); + + } else { + dataP->term_spec = tmp; + } + + DBG( ("mfs_ensure_term_spec -> new term_spec is at 0x%X\n", + (unsigned int) dataP->term_spec) ); + } + /* OTP-4236 - END */ +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_short_load_token(ErlDrvTermData TokenTag, yyscan_t yyscanner) +#else +static void mfs_short_load_token(ErlDrvTermData TokenTag) +#endif +{ + /* Build a {TokenTag, LineNumber} tuple */ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + /* + DBG( ("mfs_short_load_token -> entry with" + "\n TokenTag: %ld\n", TokenTag) ); + */ + + mfs_ensure_term_spec(dataP, 6); + dataP->token_counter++; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, TokenTag); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); + ASSIGN_TERM_SPEC(dataP, LINENO_OR_TOKENCNT(dataP)); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 2); +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_octet_load_token(ErlDrvTermData TokenTag, int is_empty, + yyscan_t yyscanner) +#else +static void mfs_octet_load_token(ErlDrvTermData TokenTag, int is_empty) +#endif +{ + /* Build a {TokenTag, LineNumber, String} tuple */ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + DBG( ("mfs_octet_load_token -> entry with" + "\n TokenTag: %d" + "\n is_empty: %d" + "\n yyleng: %d" + "\n", (int) TokenTag, is_empty, yyleng) ); + + mfs_ensure_term_spec(dataP, 9); + dataP->token_counter++; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, TokenTag); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); + ASSIGN_TERM_SPEC(dataP, LINENO_OR_TOKENCNT(dataP)); + + if (is_empty) { + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); // End of list + + } else { + + LOAD_PROP_GRPS(dataP); + + } + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 3); +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_lower_load_token(ErlDrvTermData TokenTag, int is_empty, + yyscan_t yyscanner) +#else +static void mfs_lower_load_token(ErlDrvTermData TokenTag, int is_empty) +#endif +{ + /* Build a {TokenTag, LineNumber, LowerCaseString} tuple */ + int i; +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + DBG( ("mfs_lower_load_token -> entry with" + "\n TokenTag: %ld" + "\n is_empty: %d" + "\n", TokenTag, is_empty) ); + + mfs_ensure_term_spec(dataP, 9); + dataP->token_counter++; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, TokenTag); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); + ASSIGN_TERM_SPEC(dataP, LINENO_OR_TOKENCNT(dataP)); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_STRING); + + if (is_empty) { + + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData)""); + ASSIGN_TERM_SPEC(dataP, 0); + + } else { + for ( i = 0; i < yyleng; ++i ) { + dataP->text_ptr[i] = tolower(yytext[i]); + } + + DBG_BUF("mfs_lower_load_token", "dataP->text_ptr", + dataP->text_ptr, yyleng); + + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) dataP->text_ptr); + dataP->text_ptr += yyleng; + ASSIGN_TERM_SPEC(dataP, yyleng); + } + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 3); +} + +#define PG_ERR_PRE "bad_property_parm:" +#define PG_ERR1 "Could not find property parm value for" +#define PG_ERR2 "Could not find proper property parm name" + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_load_property_groups(MfsErlDrvData* dataP, yyscan_t yyscanner) +#else +static void mfs_load_property_groups(MfsErlDrvData* dataP) +#endif +{ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + // MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + // MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + /* + * Process the property groups string + * v= is a property group delimiter + */ + + /* + * For each string, look for the first '='. + * Everything to the left is the name and + * everything to the right is the value. + */ + + int i = 0; // loop counter + int numGroups = 0; // Number of property groups + int numPps = 0; // Number of property parms (in the group) + char* name; // Pointer to the name buffer + int nameStart = 0; // Start position of the property parm name + int nameLen; // Length of the name part + char* value; // Pointer to the value buffer + int valueStart = 0; // Start position of the property parm name + int valueLen = 0; // Length of the value part + + DBG( ("mfs_load_property_groups -> entry\n") ); + + mfs_ensure_term_spec(dataP, 10); /*�Just in case... */ + + while (i <= yyleng) { + + /* Skip white-spaces and end-of-line */ + + DBG( ("mfs_load_property_groups -> " + "skip white-spaces and end-of-line: i = %d\n", i) ); + + if ((yytext[i] != SP) && + (yytext[i] != HTAB) && + (yytext[i] != LF) && + (yytext[i] != CR) && + (yytext[i] != NUL)) { + + DBG( ("mfs_load_property_groups -> " + "start looking for delimiter ('=')\n") ); + + /* Start looking for '=' */ + nameStart = i; + nameLen = 0; + while (i <= yyleng) { + + /* Is it a name-value delimiter? */ + if (yytext[i] == '=') { + + /* + * Found the name/value delimiter + */ + nameLen = i-nameStart; + + DBG( ("mfs_load_property_groups -> " + "found delimiter at %d (name length = %d)\n", i, nameLen) ); + + /* + * "v=" is the start of a new group. + * So, check if this maybe is the beginning of + * the first group or not. If not, we need to + * "terminate" the previous group. + */ + if (0 == strncmp("v", &yytext[nameStart], nameLen)) { + + DBG( ("mfs_load_property_groups -> " + "found a 'v' when group count is %d\n", numGroups) ); + + if (numGroups > 0) { + /* + * End the previous group + * (only if this is not the first group) + */ + + DBG( ("mfs_load_property_groups -> " + "start of new group - terminate previous group\n") ); + + mfs_ensure_term_spec(dataP, 3); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); // End of list + ASSIGN_TERM_SPEC(dataP, ERL_DRV_LIST); // List + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) numPps + 1); // Length of (group) list + numPps = 0; /* reset for next group */ + } // if ... + numGroups++; + } // if ... + numPps++; + i++; + + /* + * Now, look for the end of the value string, + * which is an EOL = (CR [LF] / LF ) + */ + + DBG( ("mfs_load_property_groups -> " + "start looking for end of value\n") ); + valueStart = i; + valueLen = 0; + while (i <= yyleng) { + if ((yytext[i] == CR) || (yytext[i] == LF)) { + valueLen = i-valueStart; + DBG( ("mfs_load_property_groups -> " + "found end of value at %d\n", i) ); + break; + } else { + i++; + } // if ... + } // while ... + + /* Name */ + name = dataP->text_ptr; + strncpy(name, &yytext[nameStart], nameLen); + name[nameLen] = 0; + dataP->text_ptr += (nameLen + 1); // Make room for the NULL termination + + /* Check that we actually got a proper value */ + if (valueLen == 0) { + /* Invalid property parm value */ + DBG( ("mfs_load_property_groups -> " + "property parm value not found\n") ); + + /********************************************** + * -record('ErrorDescriptor', + * { + * errorCode, + * errorText = asn1_NOVALUE + * }). + */ + + if (0 >= sprintf(dataP->error_msg, "%s %s %s", + PG_ERR_PRE, PG_ERR1, name)) { + mfs_fatal_error(dataP, PG_ERR1); + } + dataP->error = TRUE; + + DBG( ("mfs_load_property_groups -> " + "done after value error (%s)\n", name) ); + + return; // Bail out + + } else { + + + /*************************************** + * -record('PropertyParm', + * { + * name, + * value, + * extraInfo = asn1_NOVALUE + * }). % with extension mark + */ + + mfs_ensure_term_spec(dataP, 15); // 2 + 3 + 6 + 2 + 2 + + DBG( ("mfs_load_property_groups -> " + "insert PropertyParm record name\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) mfs_PropertyParm); + + /* Name */ + DBG( ("mfs_load_property_groups -> insert name field\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_STRING); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) name); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) nameLen); + + /* + * value, which is actually a list of length 1 + * where the "actual value" is the (only) element + */ + DBG( ("mfs_load_property_groups -> " + "insert value field (length = %d)\n", valueLen) ); + value = dataP->text_ptr; + strncpy(value, &yytext[valueStart], valueLen); + dataP->text_ptr += valueLen; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_STRING); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) value); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) valueLen); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); // End of value list + ASSIGN_TERM_SPEC(dataP, ERL_DRV_LIST); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) 1 + 1); // Length of (group) list + + /* extraInfo - never used */ + DBG( ("mfs_load_property_groups -> " + "insert the extraInfo field\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) mfs_asn1_NOVALUE); + + DBG( ("mfs_load_property_groups -> " + "terminate PropertyParm tuple\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) 4); + break; + + } // if (valueLen == 0) ... + + } else { + DBG( ("mfs_load_property_groups -> " + "b) skipping %d [%d] (%d)\n", i, yyleng - i, yytext[i]) ); + i++; + } // if (yytext[i] == '=') + + } // while (i <= yyleng) + + /* Check that we actually got a proper name */ + if (nameLen == 0) { + /* Invalid property parm name */ + DBG( ("mfs_load_property_groups -> " + "property parm name not found when " + "nameStart = %d\n", nameStart) ); + + if (0 >= sprintf(dataP->error_msg, "%s %s (name start at %d)", + PG_ERR_PRE, PG_ERR2, nameStart)) { + mfs_fatal_error(dataP, PG_ERR2); + } + + dataP->error = TRUE; + + DBG( ("mfs_load_property_groups -> done after name error\n") ); + + return; // Bail out + + } // if (nameLen == 0) ... + + } else { + DBG( ("mfs_load_property_groups -> " + "a) skipping %d [%d] (%d)\n", i, yyleng - i, yytext[i]) ); + i++; // next + } // if ((yytext[i] != SP)... + } // while ... + + mfs_ensure_term_spec(dataP, 4); // 2 + 2 just in case + + /* Make sure we actually have some groups */ + + if (numGroups > 0) { + + DBG( ("mfs_load_property_groups -> " + "terminate group (list of properties) list (length = %d)\n", + numPps) ); + + /* Terminate the final group */ + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); // End of list + ASSIGN_TERM_SPEC(dataP, ERL_DRV_LIST); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) numPps + 1); // Length of (group) list + + } + + DBG( ("mfs_load_property_groups -> " + "terminate groups (list of property groups) list (length = %d)\n", + numGroups) ); + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); // End of list + ASSIGN_TERM_SPEC(dataP, ERL_DRV_LIST); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) numGroups + 1); // Length of (groups) list + + DBG( ("mfs_load_property_groups -> done\n") ); +} + + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_load_map_name(yyscan_t yyscanner) +#else +static void mfs_load_map_name() +#endif +{ + /* Copy digit map name as lower case */ + int i; +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + for ( i = 0; i < yyleng; ++i ) { + dataP->text_ptr[i] = tolower(yytext[i]); + } + + dataP->digit_map_name_ptr = dataP->text_ptr; + dataP->digit_map_name_len = yyleng; + dataP->text_ptr += yyleng; +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_load_map_value(yyscan_t yyscanner) +#else +static void mfs_load_map_value() +#endif +{ + /* Copy digit map value as lower case */ + int i; +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + for ( i = 0; i < yyleng; ++i ) { + dataP->text_ptr[i] = tolower(yytext[i]); + } + + dataP->digit_map_value_ptr = dataP->text_ptr; + dataP->digit_map_value_len = yyleng; + dataP->text_ptr += yyleng; +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_load_map_timer(yyscan_t yyscanner) +#else +static void mfs_load_map_timer() +#endif +{ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + int timer_len = yyleng - 2; + + /* The digit map timer consists of 3 or 4 characters: + * z and Z are actually version 2 only + * 0 - the kind of timer (t|T|s|S|l|L|z|Z) + * 1 - a colon + * 2 - mandatory digit + * 3 - optional digit + */ + + /* + DBG( ("mfs_load_map_timer -> entry when yyleng: %d\n", yyleng) ); + DBG( ("mfs_load_map_timer -> yytext: 0x%x\n", yytext) ); + + DBG( ("mfs_load_map_timer -> yytext[0]: %u (%c)\n", yytext[0], yytext[0]) ); + DBG( ("mfs_load_map_timer -> yytext[1]: %u (%c)\n", yytext[1], yytext[1]) ); + DBG( ("mfs_load_map_timer -> yytext[2]: %u (%c)\n", yytext[2], yytext[2]) ); + DBG( ("mfs_load_map_timer -> yytext[3]: %u (%c)\n", yytext[3], yytext[3]) ); + */ + + /* Pad with leading zero */ + + if (timer_len == 1) { + dataP->text_ptr[0] = '0'; + dataP->text_ptr[1] = yytext[2]; + } else if (timer_len == 2) { + dataP->text_ptr[0] = yytext[2]; + dataP->text_ptr[1] = yytext[3]; + } + + /* + DBG( ("mfs_load_map_timer -> dataP->text_ptr[0]: %u (%c)\n", + dataP->text_ptr[0], dataP->text_ptr[0]) ); + DBG( ("mfs_load_map_timer -> dataP->text_ptr[1]: %u (%c)\n", + dataP->text_ptr[1], dataP->text_ptr[1]) ); + + DBG( ("mfs_load_map_timer -> dataP->text_ptr: 0x%x\n", + dataP->text_ptr) ); + */ + + switch (yytext[0]) { + case 't': + case 'T': + dataP->digit_map_start_ptr = dataP->text_ptr; + break;; + case 's': + case 'S': + dataP->digit_map_short_ptr = dataP->text_ptr; + break;; + case 'l': + case 'L': + dataP->digit_map_long_ptr = dataP->text_ptr; + break;; + case 'z': + case 'Z': + dataP->digit_map_duration_ptr = dataP->text_ptr; + break;; + } + + /* We pad when there is only one digit, so it will always be two */ + dataP->text_ptr += 2; + +} + +static void mfs_load_timer_field(MfsErlDrvData* dataP, char* text) +{ + mfs_ensure_term_spec(dataP, 2); /* OTP-4236 */ + if (text == NULL) { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_asn1_NOVALUE); + } else { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); + ASSIGN_TERM_SPEC(dataP, ((text[0] - '0') * 10) + (text[1] - '0')); + } +} + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) +static void mfs_load_map_token(yyscan_t yyscanner) +#else +static void mfs_load_map_token() +#endif +{ + /* + * Build a {'DigitMapDescriptorToken', LineNumber, + * {'DigitMapDescriptor', DigitMapName, DigitMapValue}} tuple + */ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + MfsErlDrvData* dataP = (MfsErlDrvData*) yyget_extra(yyscanner); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + mfs_ensure_term_spec(dataP, 20); + dataP->token_counter++; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_DigitMapDescriptorToken); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); + ASSIGN_TERM_SPEC(dataP, LINENO_OR_TOKENCNT(dataP)); + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_DigitMapDescriptor); + + if (dataP->digit_map_name_ptr == 0) { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_asn1_NOVALUE); + } else { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_STRING); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) dataP->digit_map_name_ptr); + ASSIGN_TERM_SPEC(dataP, dataP->digit_map_name_len); + dataP->digit_map_name_ptr = NULL; + } + + if (dataP->digit_map_value_ptr == NULL) { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_asn1_NOVALUE); + } else { + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, mfs_DigitMapValue); + + /* Take care of timer values */ + mfs_load_timer_field(dataP, dataP->digit_map_start_ptr); + dataP->digit_map_start_ptr = NULL; + + mfs_load_timer_field(dataP, dataP->digit_map_short_ptr); + dataP->digit_map_short_ptr = NULL; + + mfs_load_timer_field(dataP, dataP->digit_map_long_ptr); + dataP->digit_map_long_ptr = NULL; + + mfs_load_timer_field(dataP, dataP->digit_map_duration_ptr); + dataP->digit_map_duration_ptr = NULL; + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_STRING); + ASSIGN_TERM_SPEC(dataP, (ErlDrvTermData) dataP->digit_map_value_ptr); + ASSIGN_TERM_SPEC(dataP, dataP->digit_map_value_len); + dataP->digit_map_value_ptr = NULL; + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 6); + } + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 3); + + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + ASSIGN_TERM_SPEC(dataP, 3); + +} + + +DRIVER_INIT(mfs_drv) +{ + DBG( ("DRIVER_INIT(mfs_drv) -> entry\n") ); + + return &mfs_entry; +} + +static ErlDrvData mfs_start(ErlDrvPort port, char *buf) +{ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + MfsErlDrvData* dataP = ALLOC(sizeof(MfsErlDrvData)); +#else + MfsErlDrvData* dataP = &mfs_drv_data; +#endif + + DBG( ("mfs_start -> entry\n") ); + + dataP->port = port; + dataP->digit_map_name_ptr = NULL; + dataP->digit_map_name_len = 0; + dataP->digit_map_value_ptr = NULL; + dataP->digit_map_value_len = 0; + dataP->digit_map_start_ptr = NULL; + dataP->digit_map_short_ptr = NULL; + dataP->digit_map_long_ptr = NULL; + dataP->digit_map_duration_ptr = NULL; + dataP->error = FALSE; + /* dataP->error_msg[512]; */ + dataP->text_buf = NULL; + dataP->text_ptr = NULL; + dataP->term_spec = NULL; + dataP->term_spec_size = 0; + dataP->term_spec_index = 0; + dataP->token_counter = 0; + + mfs_AddToken = driver_mk_atom("AddToken"); + mfs_AndAUDITSelectToken = driver_mk_atom("AndAUDITSelectToken"); + mfs_AuditCapToken = driver_mk_atom("AuditCapToken"); + mfs_AuditToken = driver_mk_atom("AuditToken"); + mfs_AuditValueToken = driver_mk_atom("AuditValueToken"); + mfs_AuthToken = driver_mk_atom("AuthToken"); + mfs_BothToken = driver_mk_atom("BothToken"); + mfs_BothwayToken = driver_mk_atom("BothwayToken"); + mfs_BriefToken = driver_mk_atom("BriefToken"); + mfs_BufferToken = driver_mk_atom("BufferToken"); + mfs_COLON = driver_mk_atom("COLON"); + mfs_COMMA = driver_mk_atom("COMMA"); + mfs_ContextAttrToken = driver_mk_atom("ContextAttrToken"); + mfs_ContextAuditToken = driver_mk_atom("ContextAuditToken"); + mfs_ContextListToken = driver_mk_atom("ContextListToken"); + mfs_CtxToken = driver_mk_atom("CtxToken"); + mfs_DelayToken = driver_mk_atom("DelayToken"); + mfs_DeleteToken = driver_mk_atom("DeleteToken"); + mfs_DigitMapDescriptor = driver_mk_atom("DigitMapDescriptor"); + mfs_DigitMapDescriptorToken = driver_mk_atom("DigitMapDescriptorToken"); + mfs_DigitMapToken = driver_mk_atom("DigitMapToken"); + mfs_DigitMapValue = driver_mk_atom("DigitMapValue"); + mfs_DirectionToken = driver_mk_atom("DirectionToken"); + mfs_DiscardToken = driver_mk_atom("DiscardToken"); + mfs_DisconnectedToken = driver_mk_atom("DisconnectedToken"); + mfs_DurationToken = driver_mk_atom("DurationToken"); + mfs_EQUAL = driver_mk_atom("EQUAL"); + mfs_EmbedToken = driver_mk_atom("EmbedToken"); + mfs_EmergencyToken = driver_mk_atom("EmergencyToken"); + mfs_EmergencyOffToken = driver_mk_atom("EmergencyOffToken"); + mfs_EmergencyValueToken = driver_mk_atom("EmergencyValueToken"); + mfs_ErrorToken = driver_mk_atom("ErrorToken"); + mfs_EventBufferToken = driver_mk_atom("EventBufferToken"); + mfs_EventsToken = driver_mk_atom("EventsToken"); + mfs_ExternalToken = driver_mk_atom("ExternalToken"); + mfs_FailoverToken = driver_mk_atom("FailoverToken"); + mfs_ForcedToken = driver_mk_atom("ForcedToken"); + mfs_GREATER = driver_mk_atom("GREATER"); + mfs_GracefulToken = driver_mk_atom("GracefulToken"); + mfs_H221Token = driver_mk_atom("H221Token"); + mfs_H223Token = driver_mk_atom("H223Token"); + mfs_H226Token = driver_mk_atom("H226Token"); + mfs_HandOffToken = driver_mk_atom("HandOffToken"); + mfs_IEPSToken = driver_mk_atom("IEPSToken"); + mfs_IllegalChar = driver_mk_atom("IllegalChar"); + mfs_ImmAckRequiredToken = driver_mk_atom("ImmAckRequiredToken"); + mfs_InSvcToken = driver_mk_atom("InSvcToken"); + mfs_InactiveToken = driver_mk_atom("InactiveToken"); + mfs_InternalToken = driver_mk_atom("InternalToken"); + mfs_InterruptByEventToken = driver_mk_atom("InterruptByEventToken"); + mfs_InterruptByNewSignalsDescrToken = driver_mk_atom("InterruptByNewSignalsDescrToken"); + mfs_IntsigDelayToken = driver_mk_atom("IntsigDelayToken"); + mfs_IsolateToken = driver_mk_atom("IsolateToken"); + mfs_IterationToken = driver_mk_atom("IterationToken"); + mfs_KeepActiveToken = driver_mk_atom("KeepActiveToken"); + mfs_LBRKT = driver_mk_atom("LBRKT"); + mfs_LESSER = driver_mk_atom("LESSER"); + mfs_LSBRKT = driver_mk_atom("LSBRKT"); + mfs_LocalControlToken = driver_mk_atom("LocalControlToken"); + mfs_LocalDescriptorToken = driver_mk_atom("LocalDescriptorToken"); + mfs_LocalToken = driver_mk_atom("LocalToken"); + mfs_LockStepToken = driver_mk_atom("LockStepToken"); + mfs_LoopbackToken = driver_mk_atom("LoopbackToken"); + mfs_MediaToken = driver_mk_atom("MediaToken"); + mfs_MegacopToken = driver_mk_atom("MegacopToken"); + mfs_MessageSegmentToken = driver_mk_atom("MessageSegmentToken"); + mfs_MethodToken = driver_mk_atom("MethodToken"); + mfs_MgcIdToken = driver_mk_atom("MgcIdToken"); + mfs_ModeToken = driver_mk_atom("ModeToken"); + mfs_ModemToken = driver_mk_atom("ModemToken"); + mfs_ModifyToken = driver_mk_atom("ModifyToken"); + mfs_MoveToken = driver_mk_atom("MoveToken"); + mfs_MtpAddressToken = driver_mk_atom("MtpAddressToken"); + mfs_MuxToken = driver_mk_atom("MuxToken"); + mfs_NEQUAL = driver_mk_atom("NEQUAL"); + mfs_NotifyCompletionToken = driver_mk_atom("NotifyCompletionToken"); + mfs_NotifyImmediateToken = driver_mk_atom("NotifyImmediateToken"); + mfs_NotifyRegulatedToken = driver_mk_atom("NotifyRegulatedToken"); + mfs_NeverNotifyToken = driver_mk_atom("NeverNotifyToken"); + mfs_NotifyToken = driver_mk_atom("NotifyToken"); + mfs_Nx64kToken = driver_mk_atom("Nx64kToken"); + mfs_ObservedEventsToken = driver_mk_atom("ObservedEventsToken"); + mfs_OffToken = driver_mk_atom("OffToken"); + mfs_OnOffToken = driver_mk_atom("OnOffToken"); + mfs_OnToken = driver_mk_atom("OnToken"); + mfs_OnewayToken = driver_mk_atom("OnewayToken"); + mfs_OnewayBothToken = driver_mk_atom("OnewayBothToken"); + mfs_OnewayExternalToken = driver_mk_atom("OnewayExternalToken"); + mfs_OrAUDITselectToken = driver_mk_atom("OrAUDITselectToken"); + mfs_OtherReasonToken = driver_mk_atom("OtherReasonToken"); + mfs_OutOfSvcToken = driver_mk_atom("OutOfSvcToken"); + mfs_PackagesToken = driver_mk_atom("PackagesToken"); + mfs_PendingToken = driver_mk_atom("PendingToken"); + mfs_PriorityToken = driver_mk_atom("PriorityToken"); + mfs_ProfileToken = driver_mk_atom("ProfileToken"); + mfs_QuotedChars = driver_mk_atom("QuotedChars"); + mfs_RBRKT = driver_mk_atom("RBRKT"); + mfs_RSBRKT = driver_mk_atom("RSBRKT"); + mfs_ReasonToken = driver_mk_atom("ReasonToken"); + mfs_RecvonlyToken = driver_mk_atom("RecvonlyToken"); + mfs_RemoteDescriptorToken = driver_mk_atom("RemoteDescriptorToken"); + mfs_RemoteToken = driver_mk_atom("RemoteToken"); + mfs_ReplyToken = driver_mk_atom("ReplyToken"); + mfs_RequestIDToken = driver_mk_atom("RequestIDToken"); + mfs_ReservedGroupToken = driver_mk_atom("ReservedGroupToken"); + mfs_ReservedValueToken = driver_mk_atom("ReservedValueToken"); + mfs_ResetEventsDescriptorToken = driver_mk_atom("ResetEventsDescriptorToken"); + mfs_ResponseAckToken = driver_mk_atom("ResponseAckToken"); + mfs_RestartToken = driver_mk_atom("RestartToken"); + mfs_SEP = driver_mk_atom("SEP"); + mfs_SafeChars = driver_mk_atom("SafeChars"); + mfs_SegmentationCompleteToken = driver_mk_atom("SegmentationCompleteToken"); + mfs_SendonlyToken = driver_mk_atom("SendonlyToken"); + mfs_SendrecvToken = driver_mk_atom("SendrecvToken"); + mfs_ServiceChangeAddressToken = driver_mk_atom("ServiceChangeAddressToken"); + mfs_ServiceChangeIncompleteToken = driver_mk_atom("ServiceChangeIncompleteToken"); + mfs_ServiceChangeToken = driver_mk_atom("ServiceChangeToken"); + mfs_ServiceStatesToken = driver_mk_atom("ServiceStatesToken"); + mfs_ServicesToken = driver_mk_atom("ServicesToken"); + mfs_SignalListToken = driver_mk_atom("SignalListToken"); + mfs_SignalTypeToken = driver_mk_atom("SignalTypeToken"); + mfs_SignalsToken = driver_mk_atom("SignalsToken"); + mfs_StatsToken = driver_mk_atom("StatsToken"); + mfs_StreamToken = driver_mk_atom("StreamToken"); + mfs_SubtractToken = driver_mk_atom("SubtractToken"); + mfs_SynchISDNToken = driver_mk_atom("SynchISDNToken"); + mfs_TerminationStateToken = driver_mk_atom("TerminationStateToken"); + mfs_TestToken = driver_mk_atom("TestToken"); + mfs_TimeOutToken = driver_mk_atom("TimeOutToken"); + mfs_TimeStampToken = driver_mk_atom("TimeStampToken"); /* OTP-5042 */ + mfs_TopologyToken = driver_mk_atom("TopologyToken"); + mfs_TransToken = driver_mk_atom("TransToken"); + mfs_V18Token = driver_mk_atom("V18Token"); + mfs_V22Token = driver_mk_atom("V22Token"); + mfs_V22bisToken = driver_mk_atom("V22bisToken"); + mfs_V32Token = driver_mk_atom("V32Token"); + mfs_V32bisToken = driver_mk_atom("V32bisToken"); + mfs_V34Token = driver_mk_atom("V34Token"); + mfs_V76Token = driver_mk_atom("V76Token"); + mfs_V90Token = driver_mk_atom("V90Token"); + mfs_V91Token = driver_mk_atom("V91Token"); + mfs_VersionToken = driver_mk_atom("VersionToken"); + mfs_asn1_NOVALUE = driver_mk_atom("asn1_NOVALUE"); + mfs_endOfMessage = driver_mk_atom("endOfMessage"); + mfs_PropertyParm = driver_mk_atom("PropertyParm"); + mfs_ErrorDescriptor = driver_mk_atom("ErrorDescriptor"); + + DBG( ("mfs_start -> exit\n") ); + + return (ErlDrvData) dataP; +} + +static void mfs_stop(ErlDrvData handle) +{ + MfsErlDrvData* dataP = (MfsErlDrvData*) handle; + + dataP->port = 0; + + DBG( ("mfs_stop -> exit\n") ); + + return; +} + +static void mfs_command(ErlDrvData handle, + char *buf, int buf_len) +{ + driver_failure_atom(((MfsErlDrvData*) handle)->port, "bad_usage"); + + return; +} + +static int mfs_control(ErlDrvData handle, + unsigned int command, + char *buf, int buf_len, + char **res_buf, int res_buf_len) +{ + MfsErlDrvData* dataP = (MfsErlDrvData*) handle; + char* tmp; + YY_BUFFER_STATE state; +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + yyscan_t scanner; + /* struct yyguts_t * yyg = (struct yyguts_t*) scanner; */ +#endif + + DBG( ("mfs_control -> entry with" + "\n command: %d" + "\n buf_len: %d" + "\n res_buf_len: %d\n", command, buf_len, res_buf_len) ); + + if (NULL == (tmp = ALLOC(buf_len))) { + int len; + mfs_alloc_failed(dataP, "failed allocating text buffer", buf_len); + + len = strlen(dataP->error_msg); + + if (res_buf_len < len) { + /* + * Since we failed the memory allocation in the first place, + * there is no point in trying to get more memory for the + * error code... + */ + len = res_buf_len; + } + + strncpy(*res_buf, dataP->error_msg, len); + + return len; + } + dataP->text_buf = tmp; + dataP->text_ptr = tmp; + + dataP->term_spec_size = 1000 + buf_len; /* OTP-4237 */ + + DBG( ("mfs_control -> allocate term-spec buffer: " + "\n term_spec_size: %d\n", dataP->term_spec_size) ); + + dataP->term_spec = ALLOC(dataP->term_spec_size * sizeof(ErlDrvTermData)); + if (NULL == dataP->term_spec) { + int len; + mfs_alloc_failed(dataP, "failed allocating term spec buffer", + dataP->term_spec_size * sizeof(ErlDrvTermData)); + + len = strlen(dataP->error_msg); + + if (res_buf_len < len) { + /* + * Since we failed the memory allocation in the first place, + * there is no point in trying to get more memory for the + * error code... + */ + len = res_buf_len; + } + + strncpy(*res_buf, dataP->error_msg, len); + + FREE(dataP->text_buf); + + return len; + } + dataP->term_spec_index = 0; + dataP->token_counter = 0; + dataP->error = FALSE; + + /* Prepare the first field in the {tokens, TokenList, LastLine} tuple */ + DBG( ("mfs_control -> prepare the first field in the tokens tuple\n") ); + mfs_ensure_term_spec(dataP, 2); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_ATOM); + ASSIGN_TERM_SPEC(dataP, driver_mk_atom("tokens")); + + /* Perform the actual scan */ +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + + /* + * R e e n t r a n t s c a n n e r + */ + + DBG( ("mfs_control -> initiate scanner\n") ); + yylex_init(&scanner); + + DBG( ("mfs_control -> maybe enable flex debug\n") ); + yyset_debug(MFS_FLEX_DEBUG, scanner); + + DBG( ("mfs_control -> set my extra data (ErlDrvData)\n") ); + yyset_extra(dataP, scanner); + + DBG( ("mfs_control -> scan bytes\n") ); + state = yy_scan_bytes(buf, buf_len, scanner); + + DBG( ("mfs_control -> set initial line-no (1) when state is at 0x%x\n", + (unsigned int) state) ); + yyset_lineno(1, scanner); + + DBG( ("mfs_control -> do the actual scan\n") ); + yylex(scanner); + +#else + + /* + * N o n - R e e n t r a n t s c a n n e r + */ + + yylineno = 1; + state = yy_scan_bytes(buf, buf_len); + yylex(); + yy_delete_buffer(state); + +#endif + + DBG( ("mfs_control -> scan done - now check if ok or not (%d)\n", dataP->error) ); + if (!dataP->error) { + + /* + * Prepare the rest of the {tokens, TokenList, LastLine} tuple + * and send it as message top caller. + */ + + DBG( ("mfs_control -> ensure term spec(7)\n") ); + + mfs_ensure_term_spec(dataP, 7); + DBG( ("mfs_control -> assign nil\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_NIL); + DBG( ("mfs_control -> assign type list\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_LIST); + DBG( ("mfs_control -> assign size of list: %d\n", dataP->token_counter + 1) ); + ASSIGN_TERM_SPEC(dataP, dataP->token_counter + 1); + DBG( ("mfs_control -> assign type int\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_INT); +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + DBG( ("mfs_control -> assign lineno (or tokenno): %d\n", yyget_lineno(scanner)) ); + // ASSIGN_TERM_SPEC(LINENO_OR_TOKENCNT); + ASSIGN_TERM_SPEC(dataP, yyget_lineno(scanner)); +#else + DBG( ("mfs_control -> assign lineno (or tokenno): %d\n", LINENO_OR_TOKENCNT(dataP)) ); + // ASSIGN_TERM_SPEC(LINENO_OR_TOKENCNT); + ASSIGN_TERM_SPEC(dataP, LINENO_OR_TOKENCNT(dataP)); +#endif + // ASSIGN_TERM_SPEC(1); + DBG( ("mfs_control -> assign tuple\n") ); + ASSIGN_TERM_SPEC(dataP, ERL_DRV_TUPLE); + DBG( ("mfs_control -> assign size 3\n") ); + ASSIGN_TERM_SPEC(dataP, 3); + + DBG( ("mfs_control -> send the term when" + "\n term_spec_index: %d" + "\n term_spec_size: %d\n", + dataP->term_spec_index, dataP->term_spec_size) ); + + driver_send_term(dataP->port, + driver_caller(dataP->port), + dataP->term_spec, + dataP->term_spec_index); + + if (dataP->text_buf != NULL) FREE(dataP->text_buf); + if (dataP->term_spec != NULL) FREE(dataP->term_spec); + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + + /* + * R e e n t r a n t s c a n n e r + */ + + DBG( ("mfs_control -> delete buffer\n") ); + yy_delete_buffer(state, scanner); + + DBG( ("mfs_control -> destroy scanner\n") ); + yylex_destroy(scanner); + +#endif + + DBG( ("mfs_control -> done (0)\n") ); + + return 0; + + } else { + /* + * Return the error message + */ + int len = strlen(dataP->error_msg); + + DBG( ("mfs_control -> return the error message: \n%s\n\n", + dataP->error_msg) ); + + /* + * If we fail to alloc a bigger block of memory + * we have to make do with what we got + */ + if (res_buf_len < len) { + void *tmp = ALLOC(len); + if (tmp != NULL) + *res_buf = tmp; + else + len = res_buf_len; + } + + strncpy(*res_buf, dataP->error_msg, len); + + if (dataP->text_buf != NULL) FREE(dataP->text_buf); + if (dataP->term_spec != NULL) FREE(dataP->term_spec); + +#if defined(MEGACO_REENTRANT_FLEX_SCANNER) + + /* + * R e e n t r a n t s c a n n e r + */ + + DBG( ("mfs_control -> delete buffer\n") ); + yy_delete_buffer(state, scanner); + + DBG( ("mfs_control -> destroy scanner\n") ); + yylex_destroy(scanner); + +#endif + + DBG( ("mfs_control -> done (%d)\n", len) ); + + return len; + } +} + +static void mfs_finish(void) +{ + return; +} + +static void mfs_fatal_error(MfsErlDrvData* dataP, char* msg) +{ + if (!dataP->error) { + int len = strlen(msg); + + if (len >= sizeof(dataP->error_msg)) + len = sizeof(dataP->error_msg) - 1; + + strncpy(dataP->error_msg, msg, len); + dataP->error_msg[len] = '\0'; + dataP->error = TRUE; + } +} diff --git a/lib/megaco/src/flex/megaco_flex_scanner_handler.erl b/lib/megaco/src/flex/megaco_flex_scanner_handler.erl new file mode 100644 index 0000000000..d09e0c6fff --- /dev/null +++ b/lib/megaco/src/flex/megaco_flex_scanner_handler.erl @@ -0,0 +1,232 @@ +%% +%% %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% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Handle the flex scanner +%%---------------------------------------------------------------------- + +-module(megaco_flex_scanner_handler). + +-behaviour(gen_server). + + +%%----------------------------------------------------------------- +%% Include files +%%----------------------------------------------------------------- +-include_lib("megaco/src/app/megaco_internal.hrl"). + + +%% External exports +-export([ + start_link/0, start_link/1, + stop/1, + get_config/1 + ]). + +%% gen_server callbacks +-export([ + init/1, + handle_call/3, handle_cast/2, handle_info/2, + terminate/2, + code_change/3 + ]). + +-record(state, {conf}). + + +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- + +start_link() -> + start_link([]). + +start_link(Opts) -> + case gen_server:start_link(?MODULE, Opts, []) of + {ok, Pid} -> + Conf = get_config(Pid), + {ok, Pid, Conf}; + Else -> + Else + end. + +stop(Pid) -> + gen_server:call(Pid, stop). + +get_config(Pid) -> + gen_server:call(Pid, get_config). + + +%%%---------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%---------------------------------------------------------------------- +init(_Opts) -> + process_flag(trap_exit, true), + case start_flex_scanners() of + {ok, PortOrPorts} -> + {ok, #state{conf = {flex, PortOrPorts}}}; + {error, Reason} -> + %% {stop, {failed_starting_scanner, Reason, Opts}}; + {stop, {failed_starting_scanner, Reason, []}}; + Else -> + {stop, {failed_starting_scanner, Else}} + end. + + +%%---------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_call(get_config, _From, #state{conf = Conf} = S) -> + {reply, Conf, S}; + +handle_call(stop, _From, #state{conf = {flex, PortOrPorts}} = S) -> + megaco_flex_scanner:stop(PortOrPorts), + Reason = normal, + Reply = ok, + {stop, Reason, Reply, S}; + +handle_call(Req, From, S) -> + warning_msg("received unexpected request from ~p: " + "~n~w", [From, Req]), + {reply, {error, {unknown_request, Req}}, S}. + + +%%---------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_cast(Msg, S) -> + warning_msg("received unexpected message: " + "~n~w", [Msg]), + {noreply, S}. + + +%%---------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_info({'EXIT', Port, Error}, #state{conf = {flex, PortOrPorts}} = S) -> + case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of + true -> + error_msg("Port [~p] exited:" + "~n~w", [Port, Error]), + {stop, {port_exit, Port, Error}, S}; + false -> + {noreply, S} + end; + +handle_info({'EXIT', Port, _Error}, S) when is_port(Port) -> + %% This is propably the old flex scanner, + %% terminating after a code change... + {noreply, S}; + +handle_info({'EXIT', Id, Error}, S) -> + warning_msg("received unexpected 'EXIT' signal from ~p:" + "~n~w", [Id, Error]), + {noreply, S}; + +handle_info(Info, S) -> + warning_msg("received unexpected info: " + "~n~w", [Info]), + {noreply, S}. + + +%%---------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%---------------------------------------------------------------------- +terminate(_Reason, _S) -> + ok. + + +%%---------------------------------------------------------------------- +%% Func: code_change/3 +%% Purpose: Called to change the internal state +%% Returns: {ok, NewState} +%%---------------------------------------------------------------------- +%% code_change({down, _Vsn}, #state{conf = Conf} = State, downgrade_to_pre_3_8) -> +%% Port = downgrade_flex_scanner(Conf), +%% {ok, State#state{conf = {flex, Port}}}; + +code_change(_Vsn, State, _Extra) -> + {ok, State}. + +%% downgrade_flex_scanner({flex, Port}) when is_port(Port) -> +%% Port; +%% downgrade_flex_scanner({flex, [Port]}) when is_port(Port) -> +%% Port; +%% downgrade_flex_scanner({flex, Ports}) when is_list(Ports) -> +%% megaco_flex_scanner:stop(Ports), +%% case megaco_flex_scanner:start() of +%% {ok, Port} -> +%% Port; +%% Error -> +%% exit(Error) +%% end; +%% downgrade_flex_scanner(BadConfig) -> +%% exit({invalid_config, BadConfig}). + + +%%%---------------------------------------------------------------------- +%%% Internal functions +%%%---------------------------------------------------------------------- + +start_flex_scanners() -> + megaco_flex_scanner:start(). + + +%% get_env(Key, Opts, Default) -> +%% case lists:keysearch(Key, 1, Opts) of +%% {value, {Key, Value}} -> +%% Value; +%% false -> +%% Default +%% end. + +warning_msg(F, A) -> + ?megaco_warning("Flex scanner handler: " ++ F, A). + +error_msg(F, A) -> + ?megaco_error("Flex scanner handler: " ++ F, A). + + + +% d(F, A) -> +% io:format("~w:" ++ F ++ "~n", [?MODULE|A]). + diff --git a/lib/megaco/src/flex/modules.mk b/lib/megaco/src/flex/modules.mk new file mode 100644 index 0000000000..fb9957cffd --- /dev/null +++ b/lib/megaco/src/flex/modules.mk @@ -0,0 +1,27 @@ +#-*-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_flex_scanner \ + megaco_flex_scanner_handler + +FLEX_MODULES = megaco_flex_scanner_drv + +STD_DRV = megaco_flex_scanner_drv +MT_DRV = megaco_flex_scanner_drv_mt diff --git a/lib/megaco/src/flex/prebuild.skip b/lib/megaco/src/flex/prebuild.skip new file mode 100644 index 0000000000..9c558e357c --- /dev/null +++ b/lib/megaco/src/flex/prebuild.skip @@ -0,0 +1 @@ +. |