/*
 * Copyright (c) 2004 Endace Technology Ltd, Hamilton, New Zealand.
 * All rights reserved.
 *
 * This source code is proprietary to Endace Technology Limited and no part
 * of it may be redistributed, published or disclosed except as outlined in
 * the written contract supplied with this product.
 *
 * $Id: lex.l 9865 2008-09-01 08:16:23Z vladimir $
 */

%{

/* ------------------------------------------------------------------
   Initial code (copied verbatim to the output file)
   ------------------------------------------------------------------ */

// Includes
#include <string.h>   // strcpy, strncpy
//#include <io.h>       // isatty
#ifdef MSVC
#define  isatty _isatty  // for some reason isatty is called _isatty in VC..
#endif

#define  _LEX_CPP_   // make sure our variables get created
#include <stdlib.h>
#include "lex.h"
#include "gram.h"

//extern int yywrap (); // the yywrap function is declared by the caller

// Forward references
void Identifier ();
void StringConstant ();
void HexaStringConstant ();
void EatComment ();
void mac_addr ();
void Number ();
void HexaNumber ();
void BinNumber ();
unsigned int dagstrtol16 (char * str);
unsigned char getHexaLex (char c);

//// End of inititial code
%}

%option nounput

/* ------------------------------------------------------------------
   Some macros (standard regular expressions)
   ------------------------------------------------------------------ */

LETTER   [a-zA-Z_]
HEXALETTER [a-fA-F]
DIGIT    [0-9]
HEXANUMBER [0][x](({DIGIT}|{HEXALETTER})+)
BINNUMBER  [0][b][01]+
NUM		 {DIGIT}+
HEXA     ({DIGIT}|{HEXALETTER}|[*])
IDENT    {LETTER}({LETTER}|{DIGIT})*
HEXASTR	 \"({DIGIT}|{HEXALETTER}|[ \t\n\r]+)*\"
STR      \"[^\"]*\"
WSPACE   [ \t]+
MACADDR  {HEXA}{HEXA}:{HEXA}{HEXA}:{HEXA}{HEXA}:{HEXA}{HEXA}:{HEXA}{HEXA}:{HEXA}{HEXA}

/* ------------------------------------------------------------------
   The lexer rules
   ------------------------------------------------------------------ */
%%

"packets"	{return PACKETS;}
"packet"	{return PACKET;}
"traffic"	{return TRAFFIC;}
"options"	{return OPTIONS;}
"counters"	{return COUNTERS;}


"{"		{return OPEN_KEY;}
"}"		{return CLOSE_KEY;}
"("		{return OPEN_PAR;}
")"		{return CLOSE_PAR;}
"["		{return OPEN_BRA;}
"]"		{return CLOSE_BRA;}
"send"		{return SEND;}
";"      	{return EOC;}
":"		{return COLON;}
"~"		{return TILDE;}
","		{return COMMA;}
"+"		{return PLUS;}


"src_addr"	{return SRC_ADDR;}
"dst_addr"	{return DST_ADDR;}
{MACADDR}	{mac_addr ();				/* MAC address */
		 return TOKEN_MAC;}
"length"	{return LENGTH;}
"step"		{return STEP;}
"normal"	{return NORMAL;}
"poisson"	{return POISSON;}
"uniform"	{return UNIFORM;}
"constant"	{return CONSTANT;}
"output_file"	{return OUTPUT_FILE;}
"output_format"	{return OUTPUT_FORMAT;}
"verbose"	{return VERBOSE;}
"random_seed"	{return RANDOM_SEED;}
"address"	{return ADDRESS;}
"interface"	{return INTERFACE;}

"eth_802_3"	{return PACKET_ETH802_3;}
"eth_II"	{return PACKET_ETH_II;}
"pos"		{return PACKET_POS;}
"atm"		{return PACKET_ATM;}
"aal5"		{return PACKET_AAL5;}
"infiniband"	{return PACKET_IB;}

"control"	{return CONTROL;}
"protocol_size"	{return PROTOCOL_SIZE;}
"protocol"	{return PROTOCOL;}
"payload"	{return PAYLOAD;}
"fcs_size"	{return FCS_SIZE;}
"rx_error"	{return RX_ERROR;}
"erf"		{return FORMAT_ERF;}
"pcap"		{return FORMAT_PCAP;}
"size"		{return TOKEN_SIZE;}
"dummy"		{return DUMMY;}
"gfc"		{return ATM_GFC;}
"vpi"		{return ATM_VPI;}
"vci"		{return ATM_VCI;}
"pt"		{return ATM_PT;}
"clp"		{return ATM_CLP;}
"type"		{return ATM_TYPE;}
"uni"		{return ATM_UNI;}
"nni"		{return ATM_NNI;}
"uu"		{return AAL5_UU;}
"cpi"		{return AAL5_CPI;}
"crc"		{return AAL5_CRC;}
"loop"		{return LOOP;}
"wlen"		{return WLEN;}
"group"		{return TOKEN_GROUP;}
"snap"		{return SNAP;}

"local"		{return IB_LOCAL;}
"global"	{return IB_GLOBAL;}
"raw"       {return IB_RAW;}
"non-ib"    {return IB_NON_IB;}
"vlane"         {return IB_LRH_VL;}
"lver"		{return IB_LRH_LVER;}
"slid"		{return IB_LRH_SLID;}
"dlid"		{ return IB_LRH_DLID; }
"destqp"	{return IB_BTH_QP;}
"srcqp"		{return IB_SRC_QP;}
"opcode"	{return IB_BTH_OPCODE;}
"psn"		{return IB_BTH_PSN;}
"tver"		{return IB_BTH_TVER;}
"slevel"	{return IB_LRH_SLEVEL;}


{IDENT}  	{Identifier ();             /* identifier: copy name */
          	 return ID;}
{HEXANUMBER}	{HexaNumber();
		 return NUMBER;}
{BINNUMBER}	{BinNumber();
		 return NUMBER;}
{NUM}		{Number();
		 return NUMBER;}
{HEXASTR}	{HexaStringConstant ();
		 return HEXASTRING;}
{STR}    	{StringConstant ();         /* string constant: copy contents */
          	 return STRING;}
"//"     	{EatComment();}             /* comment:    skip */
\n       	{lineno++;}                 /* newline:    count lines */
{WSPACE} 	{}                          /* whitespace: (do nothing) */
.        	{}       /* other char: error, illegal token */

%%

/* ------------------------------------------------------------------
   Additional code (again copied verbatim to the output file)
   ------------------------------------------------------------------ */

// The comment-skipping function: skip to end-of-line
void EatComment()  {
	char c;

   while ((c = input()) != '\n' && c != 0);
	lineno++;
}

// Pass the id name
void Identifier ()  {
   yylval.str = malloc(strlen(yytext)+1);
   strcpy (yylval.str, yytext);
}

// Pass the string constant
void StringConstant()  {
   int i = (int)strlen(yytext)-2;
   yylval.str = malloc(i+1);
   strncpy (yylval.str, &yytext[1], i); yylval.str[i] = 0;

   // count 'returns' in string to advance line number
   for (i=0; i<(int)strlen(yylval.str); i++)
   	if (yylval.str[i] == '\n') lineno++;
}

// Pass the string constant
void HexaStringConstant()  {
   int i,j;
   int count;
   int length;

   // Atention: yytext includes both '"', we must take this out.

   for (i=0, count=0; i<(int)strlen(yytext); i++) {
	if (yytext[i] == ' '  || yytext[i] == '\t' ||
	    yytext[i] == '\n' || yytext[i] == '\r' ||
	    yytext[i] == '\"' )
		count++;
	if (yytext[i] == '\n') lineno++;
   }

   length = (int)strlen(yytext)-count;
   yylval.str = malloc(length+1);
   memset(yylval.str, 0, length+1);

   for (i=0, j=0; i<(int)strlen(yytext); i++) {
   	if (yytext[i] != ' '  && yytext[i] != '\t' &&
	    yytext[i] != '\n' && yytext[i] != '\r' &&
	    yytext[i] != '\"' )
		yylval.str[j++] = yytext[i];
   }
}

void mac_addr () {
	yylval.str = malloc (strlen(yytext));
	strncpy (yylval.str, yytext, strlen(yytext));
}

void Number () {
	yylval.l = atol(yytext);
}

void HexaNumber () {
	//yylval.l = (unsigned int) strtol(yytext, (char **)NULL, 16);
	yylval.l = dagstrtol16 (yytext);
}

void BinNumber () {
	// binary numbers have the format: 0b10010011
	// we must jump the '0b' part. This is the reason
	// you are seeing &yytext[2]
	yylval.l = (unsigned long) strtol(&yytext[2], (char **)NULL, 2);
}

unsigned int dagstrtol16 (char * str) {
	int i;
	int length;
	unsigned int res = 0;

	length = (int)strlen(str);
	if (length > 10) length = 10;
	for(i=length-1; i>1; i--) {
		res |= getHexaLex(str[i]) << (4*(length-i-1));
	}
	return res;
}


unsigned char getHexaLex (char c) {
	unsigned char res;

	res = 0;
	switch(c) {
	case '0':	res = 0;
			break;
	case '1':	res = 1;
			break;
	case '2':	res = 2;
			break;
	case '3':	res = 3;
			break;
	case '4':	res = 4;
			break;
	case '5':	res = 5;
			break;
	case '6':	res = 6;
			break;
	case '7':	res = 7;
			break;
	case '8':	res = 8;
			break;
	case '9':	res = 9;
			break;
	case 'A':
	case 'a':	res = 10;
			break;
	case 'B':
	case 'b':	res = 11;
			break;
	case 'C':
	case 'c':	res = 12;
			break;
	case 'D':
	case 'd':	res = 13;
			break;
	case 'E':
	case 'e':	res = 14;
			break;
	case 'F':
	case 'f':	res = 15;
			break;
	}

	return res;
}




