/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 2001-2013. 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_DRIVER_FLAGS ERL_DRV_FLAG_USE_PORT_LOCKING
#else
# define MEGACO_DRIVER_FLAGS 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;
ErlDrvTermData port_id;
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;
/* IBL = In Buffer Length - the raw (un-decoded) message buffer length */
#define TERM_SPEC_SIZE_INITIAL(IBL) (1024 + 2*(IBL))
/* CTSS = Current term spec size - the current term spec length */
/* S = Size - how many positions we need */
#define TERM_SPEC_SIZE_NEXT(CTSS,S) ((CTSS) + 1024 + (S))
#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, ErlDrvSizeT buf_len);
static ErlDrvSSizeT mfs_control(ErlDrvData handle,
unsigned int command,
char *buf, ErlDrvSizeT buf_len,
char **res_buf, ErlDrvSizeT 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 */
ERL_DRV_EXTENDED_MARKER,
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_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_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
#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 = TERM_SPEC_SIZE_NEXT(dataP->term_spec_size, size);
DBG( ("mfs_ensure_term_spec -> "
"term_spec is at 0x%X, new term_spec_size is %d (%lu)\n",
(unsigned int) dataP->term_spec,
dataP->term_spec_size,
dataP->term_spec_size * sizeof(ErlDrvTermData)) );
tmp = REALLOC(dataP->term_spec,
dataP->term_spec_size * sizeof(ErlDrvTermData));
DBG( ("mfs_ensure_term_spec -> "
"realloc result: 0x%X\n", (unsigned int) tmp) );
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);
DBG( ("mfs_octet_load_token -> done\n") );
}
#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, 6); // 3 + 3 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->port_id = driver_mk_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, ErlDrvSizeT buf_len)
{
driver_failure_atom(((MfsErlDrvData*) handle)->port, "bad_usage");
return;
}
static ErlDrvSSizeT mfs_control(ErlDrvData handle,
unsigned int command,
char *buf, ErlDrvSizeT buf_len,
char **res_buf, ErlDrvSizeT 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 = TERM_SPEC_SIZE_INITIAL(buf_len);
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) );
erl_drv_send_term(dataP->port_id,
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;
}
}