Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
lexer.l 22.66 KiB
%{
/*
 * Copyright 2013 Google Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
/*
 * Author: ncardwell@google.com (Neal Cardwell)
 *
 * This is the specification for the lexical scanner for the packetdrill
 * script language. It is processed by the flex lexical scanner
 * generator.
 *
 * For full documentation see: http://flex.sourceforge.net/manual/
 *
 * Here is a quick and dirty tutorial on flex:
 *
 * A flex lexical scanner specification is basically a list of rules,
 * where each rule is a regular expressions for a lexical token to
 * match, followed by a C fragment to execute when the scanner sees
 * that pattern.
 *
 * The lexer feeds a stream of terminal symbols up to this parser,
 * passing up a FOO token for each "return FOO" in the lexer spec. The
 * lexer specifies what value to pass up to the parser by setting a
 * yylval.fooval field, where fooval is a field in the %union in the
 * .y file.
 *
 * TODO: detect overflow in numeric literals.
 */

#include "types.h"

#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include "script.h"
#include "tcp_options.h"
#include "parse.h"
#include "config.h"

/* This include of the bison-generated .h file must go last so that we
 * can first include all of the declarations on which it depends.
 */
#include "parser.h"

/* Suppress flex's generation of an uncalled static input() function, which
 * leads to a compiler warning:
 *    warning: ‘input’ defined but not used
 */
#define YY_NO_INPUT

/* Copy the string name "foo" after the "--" of a "--foo" option. */
static char *option(const char *s)
{
	const int dash_dash_len = 2;
	return strndup(s + dash_dash_len, strlen(s) - dash_dash_len);
}

/* Copy the string inside a quoted string. */
static char *quoted(const char *s)
{
	const int delim_len = 1;
	return strndup(s + delim_len, strlen(s) - 2*delim_len);
}

/* Check to see if the word in yytext is a user-defined symbol, and if so then
 * return its value. Otherwise return the word itself.
 */
int word(void)
{
	char *word = yytext;
	char *value = NULL;

	/* Look in symbol table for matching user-defined symbol->value map. */
	value = definition_get(in_config->defines, word);
	if (value) {
		if (value[0] == '"') {
			yylval.string = quoted(value);		/* SYM="val" */
			return STRING;
		} else if (value[0] == '`') {
			yylval.string = quoted(value);		/* SYM=`val` */
			return BACK_QUOTED;
		} else {
			yylval.string = strdup(value);		/* SYM=val */
			return WORD;
		}
	}
	/* A literal word (e.g. system call name or socket option name). */
	yylval.string = strdup(word);
	return WORD;
}

/* Copy the code inside a code snippet that is enclosed in %{ }% after
 * first stripping the space and tab characters from either end of the
 * snippet. We strip leading and trailing whitespace for Python users
 * to remain sane, since Python is sensitive to whitespace. To summarize,
 * given an input %{<space><code><space>}% we return: <code>
 */
static char *code(const char *s)
{
	const int delim_len = sizeof("%{")-1;

	const char *start = s + delim_len;
	while ((*start == ' ') || (*start == '\t'))
		++start;

	const char *end = s + (strlen(s) - 1) - delim_len;
	while ((*end == ' ') || (*end == '\t'))
		--end;

	const int code_len = end - start + 1;
	return strndup(start, code_len);
}

/* Convert a hex string prefixed by "0x" to an integer value. */
static s64 hextol(const char *s)
{
	return strtol(yytext + 2, NULL, 16);
}

enum ifdef_os {
	Linux_IFDEF = 1, FreeBSD_IFDEF, NetBSD_IFDEF, OpenBSD_IFDEF, Omnet_IFDEF, Apple_IFDEF
};

#define MAX_IFDEF_DEPTH 1
YY_BUFFER_STATE ifdef_stack[MAX_IFDEF_DEPTH];
int ifdef_stack_ptr = 0;

static inline int get_os_name_length(enum ifdef_os os) {
	switch (os) {
	case Linux_IFDEF:
		return strlen("Linux");
	case FreeBSD_IFDEF:
		return strlen("FreeBSD");
	case NetBSD_IFDEF:
		return strlen("NetBSD");
	case OpenBSD_IFDEF:
		return strlen("OpenBSD");
	case Omnet_IFDEF:
		return strlen("Omnet");
	case Apple_IFDEF:
		return strlen("Apple");
	default:
		return -1;
	}
}

static inline bool ignore_ifdef(enum ifdef_os os) {
	switch (os) {
#ifdef linux
	case Linux_IFDEF:
#endif
#ifdef __FreeBSD__
	case FreeBSD_IFDEF:
#endif
#ifdef __OpenBSD__
	case OpenBSD_IFDEF:
#endif
#ifdef __NetBSD__
	case NetBSD_IFDEF:
#endif
#ifdef __APPLE__
	case Apple_IFDEF:
#endif
	/* no need to handle Omnet here */
		return false;
	default:
		return true;
	}
}

static inline char* remove_ifdef_start_and_endtag(char *code, int os_name_length) {
	unsigned int ifdef_length = strlen("#ifdef ");
	unsigned int endif_length = strlen("#endif");
	unsigned int newline_before_endif = 0;
	char *code_without_ifdef = NULL;

	code_without_ifdef = code + ifdef_length + os_name_length;
	newline_before_endif = strlen(code_without_ifdef) - endif_length;
	code_without_ifdef[newline_before_endif] = (char) 0;
	return code_without_ifdef;
}

static int old_yylineno = 0;

static void handle_ifdef(enum ifdef_os os, const char *s) {
	char *code = NULL;
	char *code_without_ifdef = NULL;
	int os_name_length = get_os_name_length(os);

	if (os_name_length == -1) {
		fprintf(stderr, "handle_ifdef with unknown os called.\n");
		exit(1);
	}

	if (ignore_ifdef(os)) {
		return;
	}

	if (ifdef_stack_ptr >= MAX_IFDEF_DEPTH) {
		fprintf(stderr, "Ifdefs nested too deeply");
		exit(1);
	}

	code = strdup(s);

	// keep track of the current value of yylineno, because we need to restore it later (see EOF-Condition),
	// otherwise all ifdefs that were interpreted will count twice in yylineno,
	// which will mess up the value in yylineno.
	old_yylineno = yylineno;

	code_without_ifdef = remove_ifdef_start_and_endtag(code, os_name_length);
	ifdef_stack[ifdef_stack_ptr++] = YY_CURRENT_BUFFER;
	yy_switch_to_buffer(yy_scan_string(code_without_ifdef));

	free(code);
}

%}

%{
#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno;
%}
%option yylineno
%option nounput

/* A regexp for C++ comments: */
cpp_comment	\/\/[^\n]*\n

/* Here is a summary of the regexp for C comments:
 *   open-comment
 *   any number of:
 *     (non-stars) or (star then non-slash)
 *   close comment
 */
c_comment	\/\*(([^*])|(\*[^\/]))*\*\/

/* This matches the following platform specific #ifdef-forms:
 *   #ifdef Linux   => Code that only Linux hosts should execute
 *   #ifdef FreeBSD => Code that only FreeBSD hosts should execute
 *   #ifdef NetBSD  => Code that only NetBSD hosts should execute
 *   #ifdef OpenBSD => Code that only OpenBSD hosts should execute
 *   #ifdef Omnet   => Code that only an Omnet based simulation should execute
 *
 *   the pattern for using #ifdef is like this:
 *   #ifdef Linux
 *   (specific code only for linux)
 *   #endif
 */

/* these are the tags that identify the start and ending of an ifdef block */
ifdef_begin #ifdef[ ]
ifdef_end   #endif
/* end_matcher actually matches everything except the "#endif" tag. */
end_matcher (([^#])|(#[^e])|(#e[^n])|(#en[^d])|(#end[^i])|(#endi[^f]))*

ifdef_freebsd	{ifdef_begin}(?i:FreeBSD){end_matcher}{ifdef_end}
ifdef_linux	{ifdef_begin}(?i:Linux){end_matcher}{ifdef_end}
ifdef_netbsd	{ifdef_begin}(?i:NetBSD){end_matcher}{ifdef_end}
ifdef_openbsd	{ifdef_begin}(?i:OpenBSD){end_matcher}{ifdef_end}
ifdef_omnet	{ifdef_begin}(?i:Omnet){end_matcher}{ifdef_end}

/* The regexp for code snippets is analogous to that for C comments.
 * Here is a summary of the regexp for code snippets:
 *   %{
 *   any number of:
 *     (non-}) or (} then non-%)
 *   }%
 */
code		\%\{(([^}])|(\}[^\%]))*\}\%

/* IPv4: a regular experssion for an IPv4 address */
ipv4_addr		[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+

/* IPv6: a regular experssion for an IPv6 address. The complexity is
 * unfortunate, but we can't use a super-simple approach because TCP
 * sequence number ranges like 1:1001 can look like IPv6 addresses if
 * we use a naive approach.
 */
seg	[0-9a-fA-F]{1,4}
v0	[:][:]
v1	({seg}[:]){7,7}{seg}
v2	({seg}[:]){1,7}[:]
v3	({seg}[:]){1,6}[:]{seg}
v4	({seg}[:]){1,5}([:]{seg}){1,2}
v5	({seg}[:]){1,4}([:]{seg}){1,3}
v6	({seg}[:]){1,3}([:]{seg}){1,4}
v7	({seg}[:]){1,2}([:]{seg}){1,5}
v8	{seg}[:](([:]{seg}){1,6})
v9	[:]([:]{seg}){1,7}
/* IPv4-mapped IPv6 address: */
v10	[:][:]ffff[:]{ipv4_addr}
/* IPv4-translated IPv6 address: */
v11	[:][:]ffff[:](0){1,4}[:]{ipv4_addr}
/* IPv4-embedded IPv6 addresses: */
v12	({seg}[:]){1,4}[:]{ipv4_addr}
ipv6_addr ({v0}|{v1}|{v2}|{v3}|{v4}|{v5}|{v6}|{v7}|{v8}|{v9}|{v10}|{v11}|{v12})

%%
sa_family			return SA_FAMILY;
sin_port			return SIN_PORT;
sin_addr			return SIN_ADDR;
msg_name			return MSG_NAME;
msg_iov				return MSG_IOV;
msg_control			return MSG_CONTROL;
msg_flags			return MSG_FLAGS;
cmsg_len			return _CMSG_LEN_;
cmsg_level			return CMSG_LEVEL;
cmsg_type			return CMSG_TYPE;
cmsg_data			return _CMSG_DATA_;
fd				return FD;
events				return EVENTS;
revents				return REVENTS;
onoff				return ONOFF;
linger				return LINGER;
htons				return _HTONS_;
htonl				return _HTONL_;
ipv4				return IPV4;
ipv6				return IPV6;
icmp				return ICMP;
sctp				return SCTP;
udp				return UDP;
udplite				return UDPLITE;
gre				return GRE;
mpls				return MPLS;
label				return LABEL;
tc				return TC;
ttl				return TTL;
inet_addr			return INET_ADDR;
ack				return ACK;
eol				return EOL;
ecr				return ECR;
mss				return MSS;
mtu				return MTU;
nop				return NOP;
sack				return SACK;
sackOK				return SACKOK;
TS				return TIMESTAMP;
EXP-FO				return EXP_FAST_OPEN;
FO				return FAST_OPEN;
val				return VAL;
win				return WIN;
wscale				return WSCALE;
ect01				return ECT01;
ect0				return ECT0;
ect1				return ECT1;
noecn				return NO_ECN;
ce				return CE;
iov_base			return IOV_BASE;
iov_len				return IOV_LEN;
headers				return SF_HDTR_HEADERS;
trailers			return SF_HDTR_TRAILERS;
[.][.][.]			return ELLIPSIS;
af_name				return AF_NAME;
af_arg				return AF_ARG;
function_set_name		return FUNCTION_SET_NAME;
pcbcnt				return PCBCNT;
assoc_id			return ASSOC_ID;
assoc_value			return ASSOC_VALUE;
shmac_number_of_idents		return SHMAC_NUMBER_OF_IDENTS;
shmac_idents			return SHMAC_IDENTS;
stream_id			return STREAM_ID;
stream_value			return STREAM_VALUE;
scact_assoc_id			return SCACT_ASSOC_ID;
scact_keynumber			return SCACT_KEYNUMBER;
sack_assoc_id			return SACK_ASSOC_ID;
sack_delay			return SACK_DELAY;
sack_freq			return SACK_FREQ;
srto_assoc_id			return SRTO_ASSOC_ID;
srto_initial			return SRTO_INITIAL;
srto_max			return SRTO_MAX;
srto_min			return SRTO_MIN;
sasoc_assoc_id	 		return SASOC_ASSOC_ID;
sasoc_asocmaxrxt		return SASOC_ASOCMAXRXT;
sasoc_number_peer_destinations	return SASOC_NUMBER_PEER_DESTINATIONS;
sasoc_peer_rwnd			return SASOC_PEER_RWND;
sasoc_local_rwnd		return SASOC_LOCAL_RWND;
sasoc_cookie_life		return SASOC_COOKIE_LIFE;
sinit_num_ostreams		return SINIT_NUM_OSTREAMS;
sinit_max_instreams		return SINIT_MAX_INSTREAMS;
sinit_max_attempts		return SINIT_MAX_ATTEMPTS;
sinit_max_init_timeo		return SINIT_MAX_INIT_TIMEO;
sstat_assoc_id			return SSTAT_ASSOC_ID;
sstat_state			return SSTAT_STATE;
sstat_rwnd			return SSTAT_RWND;
sstat_unackdata			return SSTAT_UNACKDATA;
sstat_penddata			return SSTAT_PENDDATA;
sstat_instrms			return SSTAT_INSTRMS;
sstat_outstrms			return SSTAT_OUTSTRMS;
sstat_fragmentation_point	return SSTAT_FRAGMENTATION_POINT;
sstat_primary			return SSTAT_PRIMARY;
spinfo_assoc_id			return SPINFO_ASSOC_ID;
spinfo_address			return SPINFO_ADDRESS;
spinfo_state			return SPINFO_STATE;
spinfo_cwnd			return SPINFO_CWND;
spinfo_srtt			return SPINFO_SRTT;
spinfo_rto			return SPINFO_RTO;
spinfo_mtu			return SPINFO_MTU;
spp_assoc_id			return SPP_ASSOC_ID;
spp_address			return SPP_ADDRESS;
spp_hbinterval			return SPP_HBINTERVAL;
spp_pathmaxrxt			return SPP_PATHMAXRXT;
spp_pathmtu			return SPP_PATHMTU;
spp_flags			return SPP_FLAGS;
spp_ipv6_flowlabel		return SPP_IPV6_FLOWLABEL_; /* avoid name clash */
spp_dscp			return SPP_DSCP_; /* avoid name clash */
se_assoc_id			return SE_ASSOC_ID;
se_type				return SE_TYPE;
se_on				return SE_ON;
sctp_data_io_event		return _SCTP_DATA_IO_EVENT_;
sctp_association_event		return _SCTP_ASSOCIATION_EVENT_;
sctp_address_event		return _SCTP_ADDRESS_EVENT_;
sctp_send_failure_event		return _SCTP_SEND_FAILURE_EVENT_;
sctp_peer_error_event		return _SCTP_PEER_ERROR_EVENT_;
sctp_shutdown_event		return _SCTP_SHUTDOWN_EVENT_;
sctp_partial_delivery_event	return _SCTP_PARTIAL_DELIVERY_EVENT_;
sctp_adaptation_layer_event	return _SCTP_ADAPTATION_LAYER_EVENT_;
sctp_authentication_event	return _SCTP_AUTHENTICATION_EVENT_;
sctp_sender_dry_event		return _SCTP_SENDER_DRY_EVENT_;
snd_sid				return SND_SID;
snd_flags			return SND_FLAGS;
snd_ppid			return SND_PPID;
snd_context			return SND_CONTEXT;
snd_assoc_id			return SND_ASSOC_ID;
ssp_assoc_id			return SSP_ASSOC_ID;
ssp_addr			return SSP_ADDR;
ssb_adaptation_ind		return SSB_ADAPTATION_IND;
sinfo_stream			return SINFO_STREAM;
sinfo_ssn			return SINFO_SSN;
sinfo_flags			return SINFO_FLAGS;
sinfo_ppid			return SINFO_PPID;
sinfo_context			return SINFO_CONTEXT;
sinfo_timetolive		return SINFO_TIMETOLIVE;
sinfo_tsn			return SINFO_TSN;
sinfo_cumtsn			return SINFO_CUMTSN;
sinfo_assoc_id			return SINFO_ASSOC_ID;
sinfo_pr_value			return SINFO_PR_VALUE;
serinfo_next_flags		return SERINFO_NEXT_FLAGS;
serinfo_next_stream		return SERINFO_NEXT_STREAM;
serinfo_next_aid		return SERINFO_NEXT_AID;
serinfo_next_length		return SERINFO_NEXT_LENGTH;
serinfo_next_ppid		return SERINFO_NEXT_PPID;
pr_policy			return PR_POLICY;
pr_value			return PR_VALUE;
pr_assoc_id			return PR_ASSOC_ID;
sendv_flags			return SENDV_FLAGS;
sendv_sndinfo			return SENDV_SNDINFO;
sendv_prinfo			return SENDV_PRINFO;
sendv_authinfo			return SENDV_AUTHINFO;
ssfe_type			return SSFE_TYPE;
ssfe_flags			return SSFE_FLAGS;
ssfe_length			return SSFE_LENGTH;
ssfe_error			return SSFE_ERROR;
ssfe_info			return SSFE_INFO;
ssfe_assoc_id			return SSFE_ASSOC_ID;
ssfe_data			return SSFE_DATA;
rcv_sid				return RCV_SID;
rcv_ssn				return RCV_SSN;
rcv_flags			return RCV_FLAGS;
rcv_ppid			return RCV_PPID;
rcv_tsn				return RCV_TSN;
rcv_cumtsn			return RCV_CUMTSN;
rcv_context			return RCV_CONTEXT;
rcv_assoc_id			return RCV_ASSOC_ID;
nxt_sid				return NXT_SID;
nxt_flags			return NXT_FLAGS;
nxt_ppid			return NXT_PPID;
nxt_length			return NXT_LENGTH;
nxt_assoc_id			return NXT_ASSOC_ID;
recvv_rcvinfo			return RECVV_RCVINFO;
recvv_nxtinfo			return RECVV_NXTINFO;
sse_type			return SSE_TYPE;
sse_flags			return SSE_FLAGS;
sse_length			return SSE_LENGTH;
sse_assoc_id			return SSE_ASSOC_ID;
sac_type			return SAC_TYPE;
sac_flags			return SAC_FLAGS;
sac_length			return SAC_LENGTH;
sac_state			return SAC_STATE;
sac_error			return SAC_ERROR;
sac_outbound_streams		return SAC_OUTBOUND_STREAMS;
sac_inbound_streams		return SAC_INBOUND_STREAMS;
sac_assoc_id			return SAC_ASSOC_ID;
sac_info			return SAC_INFO;
sre_type			return SRE_TYPE;
sre_flags			return SRE_FLAGS;
sre_length			return SRE_LENGTH;
sre_error			return SRE_ERROR;
sre_assoc_id			return SRE_ASSOC_ID;
sre_data			return SRE_DATA;
auth_type			return AUTH_TYPE;
auth_flags			return AUTH_FLAGS;
auth_length			return AUTH_LENGTH;
auth_keynumber			return AUTH_KEYNUMBER;
auth_indication			return AUTH_INDICATION;
auth_assoc_id			return AUTH_ASSOC_ID;
sender_dry_type			return SENDER_DRY_TYPE;
sender_dry_flags		return SENDER_DRY_FLAGS;
sender_dry_length		return SENDER_DRY_LENGTH;
sender_dry_assoc_id		return SENDER_DRY_ASSOC_ID;
pdapi_type			return PDAPI_TYPE;
pdapi_flags			return PDAPI_FLAGS;
pdapi_length			return PDAPI_LENGTH;
pdapi_indication		return PDAPI_INDICATION;
pdapi_stream			return PDAPI_STREAM;
pdapi_seq			return PDAPI_SEQ;
pdapi_assoc_id			return PDAPI_ASSOC_ID;
spc_type			return SPC_TYPE;
spc_length			return SPC_LENGTH;
spc_flags			return SPC_FLAGS;
spc_aaddr			return SPC_AADDR;
spc_state			return SPC_STATE;
spc_error			return SPC_ERROR;
spc_assoc_id			return SPC_ASSOC_ID;
ssf_type			return SSF_TYPE;
ssf_length			return SSF_LENGTH;
ssf_flags			return SSF_FLAGS;
ssf_error			return SSF_ERROR;
ssf_info			return SSF_INFO;
ssf_assoc_id			return SSF_ASSOC_ID;
ssf_data			return SSF_DATA;
sai_type			return SAI_TYPE;
sai_length			return SAI_LENGTH;
sai_flags			return SAI_FLAGS;
sai_adaptation_ind		return SAI_ADAPTATION_IND;
sai_assoc_id			return SAI_ASSOC_ID;
sn_type				return SN_TYPE;
sn_length			return SN_LENGTH;
sn_flags			return SN_FLAGS;
gaids_number_of_ids		return GAIDS_NUMBER_OF_IDS;
gaids_assoc_id			return GAIDS_ASSOC_ID;
gauth_assoc_id			return GAUTH_ASSOC_ID;
gauth_number_of_chunks		return GAUTH_NUMBER_OF_CHUNKS;
gauth_chunks			return GAUTH_CHUNKS;
sspp_assoc_id			return SSPP_ASSOC_ID;
sspp_addr			return SSPP_ADDR;
sauth_chunk			return SAUTH_CHUNK;
sca_assoc_id			return SCA_ASSOC_ID;
sca_keynumber			return SCA_KEYNUMBER;
sca_keylength			return SCA_KEYLENGTH;
sca_key				return SCA_KEY;
srs_assoc_id			return SRS_ASSOC_ID;
srs_flags			return SRS_FLAGS;
srs_number_streams		return SRS_NUMBER_STREAMS;
srs_stream_list			return SRS_STREAM_LIST;
sas_assoc_id			return SAS_ASSOC_ID;
sas_instrms			return SAS_INSTRMS;
sas_outstrms			return SAS_OUTSTRMS;
strreset_type			return STRRESET_TYPE;
strreset_flags			return STRRESET_FLAGS;
strreset_length			return STRRESET_LENGTH;
strreset_assoc_id		return STRRESET_ASSOC_ID;
strreset_stream_list		return STRRESET_STREAM_LIST;
assocreset_type			return ASSOCRESET_TYPE;
assocreset_flags		return ASSOCRESET_FLAGS;
assocreset_length		return ASSOCRESET_LENGTH;
assocreset_assoc_id		return ASSOCRESET_ASSOC_ID;
assocreset_local_tsn		return ASSOCRESET_LOCAL_TSN;
assocreset_remote_tsn		return ASSOCRESET_REMOTE_TSN;
strchange_type			return STRCHANGE_TYPE;
strchange_flags			return STRCHANGE_FLAGS;
strchange_length		return STRCHANGE_LENGTH;
strchange_assoc_id		return STRCHANGE_ASSOC_ID;
strchange_instrms		return STRCHANGE_INSTRMS;
strchange_outstrms		return STRCHANGE_OUTSTRMS;
sue_assoc_id			return SUE_ASSOC_ID;
sue_address			return SUE_ADDRESS;
sue_port			return SUE_PORT;
CHUNK				return CHUNK;
DATA				return DATA;
INIT				return INIT;
INIT_ACK			return INIT_ACK;
SACK				return SACK;
NR_SACK				return NR_SACK;
HEARTBEAT			return HEARTBEAT;
HEARTBEAT_ACK			return HEARTBEAT_ACK;
ABORT				return ABORT;
SHUTDOWN			return SHUTDOWN;
SHUTDOWN_ACK			return SHUTDOWN_ACK;
ERROR				return ERROR;
COOKIE_ECHO			return COOKIE_ECHO;
COOKIE_ACK			return COOKIE_ACK;
ECNE				return ECNE;
CWR				return CWR;
SHUTDOWN_COMPLETE		return SHUTDOWN_COMPLETE;
I_DATA				return I_DATA;
PAD				return PAD;
RECONFIG			return RECONFIG;
FORWARD_TSN			return FORWARD_TSN;
I_FORWARD_TSN			return I_FORWARD_TSN;
AUTH				return AUTH;
ASCONF				return ASCONF;
ASCONF_ACK			return ASCONF_ACK;
type				return TYPE;
flgs				return FLAGS;
len				return LEN;
tag				return TAG;
a_rwnd				return A_RWND;
is				return IS;
os				return OS;
tsn				return TSN;
sid				return SID;
ssn				return SSN;
mid				return MID;
ppid				return PPID;
fsn				return FSN;
cum_tsn				return CUM_TSN;
gaps				return GAPS;
nr_gaps				return NR_GAPS;
dups				return DUPS;
adaptation_code_point		return ADAPTATION_CODE_POINT;
OUTGOING_SSN_RESET		return OUTGOING_SSN_RESET;
INCOMING_SSN_RESET		return INCOMING_SSN_RESET;
SSN_TSN_RESET			return SSN_TSN_RESET;
RECONFIG_RESPONSE		return RECONFIG_RESPONSE;
ADD_OUTGOING_STREAMS		return ADD_OUTGOING_STREAMS;
ADD_INCOMING_STREAMS		return ADD_INCOMING_STREAMS;
RECONFIG_REQUEST_GENERIC	return RECONFIG_REQUEST_GENERIC;
req_sn				return REQ_SN;
resp_sn				return RESP_SN;
last_tsn			return LAST_TSN;
sids				return SIDS;
ids				return IDS;
result				return RESULT;
sender_next_tsn			return SENDER_NEXT_TSN;
receiver_next_tsn		return RECEIVER_NEXT_TSN;
number_of_new_streams		return NUMBER_OF_NEW_STREAMS;
PARAMETER			return PARAMETER;
HEARTBEAT_INFORMATION		return HEARTBEAT_INFORMATION;
IPV4_ADDRESS			return IPV4_ADDRESS;
IPV6_ADDRESS			return IPV6_ADDRESS;
STATE_COOKIE			return STATE_COOKIE;
UNRECOGNIZED_PARAMETER		return UNRECOGNIZED_PARAMETER;
COOKIE_PRESERVATIVE		return COOKIE_PRESERVATIVE;
HOSTNAME_ADDRESS		return HOSTNAME_ADDRESS;
SUPPORTED_ADDRESS_TYPES		return SUPPORTED_ADDRESS_TYPES;
ADAPTATION_INDICATION		return ADAPTATION_INDICATION;
ECN_CAPABLE			return ECN_CAPABLE;
FORWARD_TSN_SUPPORTED		return FORWARD_TSN_SUPPORTED;
SUPPORTED_EXTENSIONS		return SUPPORTED_EXTENSIONS;
addr				return ADDR;
incr				return INCR;
types				return TYPES;
params				return PARAMS;
IPv4				return IPV4_TYPE;
IPv6				return IPV6_TYPE;
HOSTNAME			return HOSTNAME_TYPE;
CAUSE				return CAUSE;
INVALID_STREAM_IDENTIFIER	return INVALID_STREAM_IDENTIFIER;
MISSING_MANDATORY_PARAMETER	return MISSING_MANDATORY_PARAMETER;
STALE_COOKIE_ERROR		return STALE_COOKIE_ERROR;
OUT_OF_RESOURCE			return OUT_OF_RESOURCE;
UNRESOLVABLE_ADDRESS		return UNRESOLVABLE_ADDRESS;
UNRECOGNIZED_CHUNK_TYPE		return UNRECOGNIZED_CHUNK_TYPE;
INVALID_MANDATORY_PARAMETER	return INVALID_MANDATORY_PARAMETER;
UNRECOGNIZED_PARAMETERS		return UNRECOGNIZED_PARAMETERS;
NO_USER_DATA			return NO_USER_DATA;
COOKIE_RECEIVED_WHILE_SHUTDOWN  return COOKIE_RECEIVED_WHILE_SHUTDOWN;
RESTART_WITH_NEW_ADDRESSES	return RESTART_WITH_NEW_ADDRESSES;
USER_INITIATED_ABORT		return USER_INITIATED_ABORT;
PROTOCOL_VIOLATION		return PROTOCOL_VIOLATION;
code				return CAUSE_CODE;
info				return CAUSE_INFO;
staleness			return STALENESS;
param				return PARAM;
chk				return CHK;
bad_crc32c			return BAD_CRC32C;
NULL				return NULL_;
--[a-zA-Z0-9_]+			yylval.string	= option(yytext); return OPTION;
[-]?[0-9]*[.][0-9]+		yylval.floating	= atof(yytext);   return FLOAT;
[-]?[0-9]+			yylval.integer	= atoll(yytext);  return INTEGER;
0x[0-9a-fA-F]+			yylval.integer	= hextol(yytext); return HEX_INTEGER;
[a-zA-Z0-9_]+			return word();
\"(\\.|[^"])*\"			yylval.string	= quoted(yytext); return STRING;
\`(\\.|[^`])*\`			yylval.string	= quoted(yytext); return BACK_QUOTED;
[^ \t\n]			return (int) yytext[0];
[ \t\n]+			/* ignore whitespace */;
{cpp_comment}			/* ignore C++-style comment */;
{c_comment}			/* ignore C-style comment */;
{ifdef_freebsd}			handle_ifdef(FreeBSD_IFDEF, yytext);
{ifdef_linux}			handle_ifdef(Linux_IFDEF, yytext);
{ifdef_netbsd}			handle_ifdef(NetBSD_IFDEF, yytext);
{ifdef_openbsd}			handle_ifdef(OpenBSD_IFDEF, yytext);
{ifdef_omnet}			handle_ifdef(Omnet_IFDEF, yytext);
{code}				yylval.string = code(yytext);   return CODE;
{ipv4_addr}			yylval.string = strdup(yytext); return IPV4_ADDR;
{ipv6_addr}			yylval.string = strdup(yytext); return IPV6_ADDR;
<<EOF>>				{
					if ( --ifdef_stack_ptr < 0 ) {
						yyterminate();
					} else {
						// here we need to restore the saved correct value of yylineno
						yylineno = old_yylineno;
						yy_delete_buffer(YY_CURRENT_BUFFER);
						yy_switch_to_buffer(ifdef_stack[ifdef_stack_ptr]);
					}
				}
%%