/* 
 * Copyright (c) 2001 Secure Software Solutions
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

%{
#include <string.h>
#include "tokens.h"
#include "engine.h"

int perllex_lineno = 1;

char *yyperlcomment = NULL; /* for consistency, not used */

static void no_match(void);
static void gobble_pod(void);
static void gobble_string(char c);


#define YY_INPUT(buf, result, max_size)                                     \
    if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))    \
        YY_FATAL_ERROR("input in flex scanner failed");                     \
    else {                                                                  \
        char *c, *end = (buf) + result - 1;                                 \
        for (c = (buf);  c < end;  c++) {                                   \
            if (*c == '\r') *c = ' ';                                       \
            if (*c == '\\' && *(c + 1) == '\n') {                           \
                memmove(c + 1, c + 2, end - c);                             \
                result--;                                                   \
                end--;                                                      \
                *c = '\r';                                                  \
            }                                                               \
        }                                                                   \
        if (*end == '\r') *end = ' ';                                       \
        if (*end == '\\') {                                                 \
            result--;                                                       \
            fseek(yyin, -1, SEEK_CUR);                                      \
        }                                                                   \
    }

%}

%%

[\n\r]			{ perllex_lineno++; return NEWLINE; }
[ \t\v\f]		{ ; }
^[ \r\t]*"#".*\n	{ perllex_lineno++; }
"#".*			{ ; }



%{

/*
xor			{ return XOR; }
write			{ return WRITE; }
while			{ return WHILE; }
warn			{ return WARN; }
wantarray		{ return WANTARRAY; }
waitpid			{ return WAITPID; }
wait			{ return WAIT; }
vec			{ return VEC; }
values			{ return VALUES; }
utime			{ return UTIME; }
use			{ return USE; }
until			{ return UNTIL; }
untie			{ return UNTIE; }
unshift			{ return UNSHIFT; }
unpack			{ return UNPACK; }
unlink			{ return UNLINK; }
unless			{ return UNLESS; }
undef			{ return UNDEF; }
umask			{ return UMASK; }
ucfirst			{ return UCFIRST; }
uc			{ return UC; }
truncate		{ return TRUNCATE; }
tr			{ return TR; }
times			{ return TIMES; }
time			{ return TIME; }
tied			{ return TIED; }
tie			{ return TIE; }
telldir			{ return TELLDIR; }
tell			{ return TELL; }
syswrite		{ return SYSWRITE; }
system			{ return SYSTEM; }
sysseek			{ return SYSSEEK; }
sysread			{ return SYSREAD; }
sysopen			{ return SYSOPEN; }
syscall			{ return SYSCALL; }
symlink			{ return SYMLINK; }
substr			{ return SUBSTR; }
sub			{ return SUB; }
study			{ return STUDY; }
stat			{ return STAT; }
srand			{ return SRAND; }
sqrt			{ return SQRT; }
sprintf			{ return SPRINTF; }
split			{ return SPLIT; }
splice			{ return SPLICE; }
sort			{ return SORT; }
socketpair		{ return SOCKETPAIR; }
socket			{ return SOCKET; }
sleep			{ return SLEEP; }
sin			{ return SIN; }
shutdown		{ return SHUTDOWN; }
shmwrite		{ return SHMWRITE; }
shmread			{ return SHMREAD; }
shmget			{ return SHMGET; }
shmctl			{ return SHMCTL; }
shift			{ return SHIFT; }
setsockopt		{ return SETSOCKOPT; }
setservent		{ return SETSERVENT; }
setpwent		{ return SETPWENT; }
setprotoent		{ return SETPROTOENT; }
setpriority		{ return SETPRIORITY; }
setpgrp			{ return SETPGRP; }
setnetent		{ return SETNETENT; }
sethostent		{ return SETHOSTENT; }
setgrent		{ return SETGRENT; }
send			{ return SEND; }
semop			{ return SEMOP; }
semget			{ return SEMGET; }
semctl			{ return SEMCTL; }
select			{ return SELECT; }
seekdir			{ return SEEKDIR; }
seek			{ return SEEK; }
scalar			{ return SCALAR; }
rmdir			{ return RMDIR; }
rindex			{ return RINDEX; }
rewinddir		{ return REWINDDIR; }
reverse			{ return REVERSE; }
return			{ return RETURN; }
reset			{ return RESET; }
require			{ return REQUIRE; }
rename			{ return RENAME; }
ref			{ return REF; }
redo			{ return REDO; }
recv			{ return RECV; }
readpipe		{ return READPIPE; }
readlink		{ return READLINK; }
readline		{ return READLINE; }
readdir			{ return READDIR; }
read			{ return READ; }
rand			{ return RAND; }
qx			{ return QX; }
qw			{ return QW; }
quotemeta		{ return QUOTEMETA; }
qr			{ return QR; }
qq			{ return QQ; }
push			{ return PUSH; }
prototype		{ return PROTOTYPE; }
printf			{ return PRINTF; }
print			{ return PRINT; }
pos			{ return POS; }
pop			{ return POP; }
pipe			{ return PIPE; }
package			{ return PACKAGE; }
pack			{ return PACK; }
our			{ return OUR; }
ord			{ return ORD; }
or			{ return OR; }
opendir			{ return OPENDIR; }
open			{ return OPEN; }
oct			{ return OCT; }
not			{ return NOT; }
no			{ return NO; }
next			{ return NEXT; }
ne			{ return NE; }
my			{ return MY; }
msgsnd			{ return MSGSND; }
msgrcv			{ return MSGRCV; }
msgget			{ return MSGGET; }
msgctl			{ return MSGCTL; }
mkdir			{ return MKDIR; }
map			{ return MAP; }
lt			{ return LT; }
lstat			{ return LSTAT; }
log			{ return LOG; }
lock			{ return LOCK; }
localtime		{ return LOCALTIME; }
local			{ return LOCAL; }
listen			{ return LISTEN; }
link			{ return LINK; }
length			{ return LENGTH; }
le			{ return LE; }
lcfirst			{ return LCFIRST; }
lc			{ return LC; }
last			{ return LAST; }
kill			{ return KILL; }
keys			{ return KEYS; }
join			{ return JOIN; }
ioctl			{ return IOCTL; }
int			{ return INT; }
index			{ return INDEX; }
if			{ return IF; }
hex			{ return HEX; }
gt			{ return GT; }
grep			{ return GREP; }
goto			{ return GOTO; }
gmtime			{ return GMTIME; }
glob			{ return GLOB; }
getsockopt		{ return GETSOCKOPT; }
getsockname		{ return GETSOCKNAME; }
getservent		{ return GETSERVENT; }
getservbyport		{ return GETSERVBYPORT; }
getservbyname		{ return GETSERVBYNAME; }
getpwuid		{ return GETPWUID; }
getpwnam		{ return GETPWNAM; }
getpwent		{ return GETPWENT; }
getprotoent		{ return GETPROTOENT; }
getprotobynumber	{ return GETPROTOBYNUMBER; }
getprotobyname		{ return GETPROTOBYNAME; }
getpriority		{ return GETPRIORITY; }
getppid			{ return GETPPID; }
getpgrp			{ return GETPGRP; }
getpeername		{ return GETPEERNAME; }
getnetent		{ return GETNETENT; }
getnetbyname		{ return GETNETBYNAME; }
getnetbyaddr		{ return GETNETBYADDR; }
getlogin		{ return GETLOGIN; }
gethostent		{ return GETHOSTENT; }
gethostbyname		{ return GETHOSTBYNAME; }
gethostbyaddr		{ return GETHOSTBYADDR; }
getgrnam		{ return GETGRNAM; }
getgrgid		{ return GETGRGID; }
getgrent		{ return GETGRENT; }
getc			{ return GETC; }
ge			{ return GE; }
formline		{ return FORMLINE; }
format			{ return FORMAT; }
fork			{ return FORK; }
foreach			{ return FOREACH; }
for			{ return FOR; }
flock			{ return FLOCK; }
fileno			{ return FILENO; }
fcntl			{ return FCNTL; }
exp			{ return EXP; }
exit			{ return EXIT; }
exists			{ return EXISTS; }
exec			{ return EXEC; }
eval			{ return EVAL; }
eq			{ return EQ; }
eof			{ return EOF; }
endservent		{ return ENDSERVENT; }
endpwent		{ return ENDPWENT; }
endprotoent		{ return ENDPROTOENT; }
endnetent		{ return ENDNETENT; }
endhostent		{ return ENDHOSTENT; }
endgrent		{ return ENDGRENT; }
elsif			{ return ELSIF; }
else			{ return ELSE; }
each			{ return EACH; }
dump			{ return DUMP; }
do			{ return DO; }
die			{ return DIE; }
delete			{ return DELETE; }
defined			{ return DEFINED; }
dbmopen			{ return DBMOPEN; }
dbmclose		{ return DBMCLOSE; }
crypt			{ return CRYPT; }
cos			{ return COS; }
continue		{ return CONTINUE; }
connect			{ return CONNECT; }
cmp			{ return CMP; }
closedir		{ return CLOSEDIR; }
close			{ return CLOSE; }
chroot			{ return CHROOT; }
chr			{ return CHR; }
chown			{ return CHOWN; }
chop			{ return CHOP; }
chomp			{ return CHOMP; }
chmod			{ return CHMOD; }
chdir			{ return CHDIR; }
caller			{ return CALLER; }
bless			{ return BLESS; }
binmode			{ return BINMODE; }
bind			{ return BIND; }
atan2			{ return ATAN2; }
and			{ return AND; }
alarm			{ return ALARM; }
accept			{ return ACCEPT; }
abs			{ return ABS; }
*/
%}

__PACKAGE__ 		{ return TOKEN_PACKAGE; }
__LINE__                { return TOKEN_LINE; }
__FILE__                { return TOKEN_FILE; }
__END__                 { return TOKEN_END; }
__DATA__                { return TOKEN_DATA; }
NULL                    { return TOKEN_NULL; }


"=head1"		{ gobble_pod(); return PERLPOD; }
"=head2"		 { gobble_pod(); return PERLPOD; }
"=back"			 { gobble_pod(); return PERLPOD; }
"=pod"			{ gobble_pod(); return PERLPOD; }
"=item"			{ gobble_pod();  return PERLPOD; }
("'") 			{ gobble_string('\''); return QSTRING_LITERAL; }
("\"")                  { gobble_string('"'); return QQSTRING_LITERAL; }
("`")                  { gobble_string('`'); return BACKTICK_LITERAL; }


"/".*"/"		{ return REGEXP; }
0[xX][a-fA-F0-9]+     { return HEX_CONST; }
0[0-9]+               { return OCT_CONST; }
[0-9]+                { return DEC_CONST; }
[0-9]+[Ee][+-]?[0-9]+              { return FLOAT_CONST; }
[0-9]*"."[0-9]+([Ee][+-]?[0-9]+)?  { return FLOAT_CONST; }
[0-9]+"."[0-9]*([Ee][+-]?[0-9]+)?  { return FLOAT_CONST; }


">>="			{ return RIGHT_ASSIGN; }
"<<="		        { return LEFT_ASSIGN; }

"**="			{ return EXP_ASSIGN; }
"+="			{ return ADD_ASSIGN; }
"-="			{ return SUB_ASSIGN; }
"*="			{ return MUL_ASSIGN; }
"/="			{ return DIV_ASSIGN; }
"%="			{ return MOD_ASSIGN; }
".="                    { return CONCAT_ASSIGN; }
"x="                    { return REPEAT_ASSIGN; }

"&="			{ return AND_ASSIGN; }
"|="			{ return OR_ASSIGN; }
"^="			{ return XOR_ASSIGN; }
">>"                    { return RIGHT_OP; }
"<<"                    { return LEFT_OP; }
"**"                    { return EXP_OP; }
"<="                    { return LE_OP; }
">="                    { return GE_OP; }
"=="                    { return EQ_OP; }
"!="                    { return NE_OP; }
"<>"                    { return NE_OP; }
"!"			{ return '!'; }
"?"			{ return '?'; }
"&"                     { return '&'; }
"~"                     { return '~'; }
"-"                     { return '-'; }
"+"                     { return '+'; }
"*"                     { return '*'; }
"/"                     { return '/'; }
"%"                     { return '%'; }
"<"                     { return '<'; }
">"                     { return '>'; }
"^"                     { return '^'; }
"|"                     { return '|'; }
 
"("			{ return '('; }
")"			{ return ')'; }
"["			{ return '['; }
"]"			{ return ']'; }
"{"			{ return '{'; }
"}"			{ return '}'; }
","			{ return ','; }
":"			{ return ':'; }
"."			{ return '.'; }
"="			{ return '='; }
";"			{ return ';'; }
"x"                     { return 'x'; }
"y"                     { return 'y'; }
"s"                     { return 's'; }
"q"                     { return 'q'; }
"m"                     { return 'm'; }
"\\"			{ return '\\';}


"$"[_&'`+*./|,\;#%=-~^:?!@"$<>)([\]]  {return ID_SCALAR;}
"$"[^][a-zA-Z]			{ return ID_SCALAR; }
"$"[0-9]*			{ return ID_SCALAR; }
"$"[a-zA-Z_$][a-zA-Z0-9_']*	{ return ID_SCALAR; }
"\\"*"@"[ \t]*"{"*["$a-zA-Z_]*[a-zA-Z0-9_'$]*"}"*	{ return ID_ARRAY; }
"%"[a-zA-Z_$][a-zA-Z0-9_']*	{ return ID_HASHT; }
[a-zA-Z_][a-zA-Z0-9_':]*	        { return ID_HANDLE; }


.                       { no_match(); }

%%

int yywrap(void)
{
    return 1;
}


static 
void gobble_string(char which)
{

  int bslash = 0;
  char c;
  while ((c = input()) && c != -1)
  {

    switch(c)  {

      case '\\':
                 if (!bslash)
                   bslash = 1;
                 else
                   bslash = 0;
                 break;
      case '\n':
                 perllex_lineno++;
                 bslash = 0;
                 break;
      default:
                 if (c == which && !bslash)  {
                   return;
                 }
                 bslash = 0;
                 break;
    }
  }
}



static 
void gobble_pod(void)
{

  int bline = 0;
  int cstate = 0;
  char c;
  while ((c = input()) && c != -1)
  {
    switch(c)  {
    
      case '=':
                if (!bline)
                  cstate = 1;
                break;
      case '\n':
                 perllex_lineno++;
                 
                 bline = 0;
                 if (cstate == 4)
                   return;
                 break;
      case 'c': 
                 if (cstate == 1)
                   cstate = 2;
                 break;
      case 'u':  if (cstate == 2)
                   cstate = 3;
                 break;
      case 't':  if (cstate == 3)
                   cstate = 4;
                 break;
      case ' ':
      case '\t':
                 if (cstate == 4)
                   return;
                 break; 
      default:
                 bline++;
                 cstate = 0;
                 break;
    }
  }
}

    

    
static
void no_match(void)
{
    fprintf(stderr, "%s:%d: warning: bad token `%s'\n", current_file, perllex_lineno, yytext);
}








