/**
* scanner.l
*
* Copyright (C) 2003 - 2008 Bojan Smojver, Rexursive
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
%{
#include "private.h"
#define YY_DECL int rxv_spin_yylex(YYSTYPE *yylval_param,yyscan_t yyscanner)
#define YY_NO_INPUT
#include "parser.h"
/*
* Error recovery macro:
*
* Check if we've been here before and if so, just accept it, it was obviosly
* meant to be there. Otherwise, attempt to get more input by trying to fill
* the buffer completely. If that doesn't work, terminate the scan and wait
* for next brigade to hopefully take care of the error.
*
*/
#define YYERROR_RECOVER \
if(!(yyextra->erow==yyextra->row && yyextra->col==yyextra->ecol) && \
yyextra->bpos+yyleng>=yyextra->blen){ \
yyextra->erow=yyextra->row; \
yyextra->ecol=yyextra->col; \
\
yywrap(yyscanner); \
\
if(yyextra->eof && yyextra->blenpool,sizeof(*txt)); \
rxv_spin_node_t *node=(rxv_spin_node_t *)txt; \
size_t i; \
\
yyextra->erow=-1; \
\
node->type=RXV_SPIN_TXT; \
node->next=node; \
\
txt->length=yyleng; \
if(yyextra->f){ \
txt->text=apr_pstrmemdup(yyextra->pool,yytext,yyleng); \
node->ttyp=RXV_SPIN_TXT_TXT; \
} else{ \
txt->start=yyextra->offset; \
node->ttyp=RXV_SPIN_TXT_OFF; \
} \
\
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; \
yyextra->row+=(n); yyextra->col=0; \
\
if(yytext[yyleng-1]!='\n') \
for(i=yyleng-1;*(yytext+i)!='\n';yyextra->col++,i--); \
\
*yylval=node; return TXT;
static apr_status_t regex_cleanup(void *data);
%}
%option prefix="rxv_spin_yy"
%option 8bit reentrant bison-bridge stack
%option warn nodefault
%option never-interactive
%option yywrap
%option full
%option header-file="scanner.h"
%option backup
%option nounput noyy_top_state
RC1 [[:alpha:]][[:alnum:]_-]*
RC2 \.[[:alpha:]][[:alnum:]_-]*(\[[[:digit:]]+\])?
REF \$[#@]*\{{RC1}({RC2})*\}
REG \/([^/]|\\\/)*\/
LIT \"([^"]|\\\")*\"
%x command
%%
/* initial scanner */
{REF} {
size_t noff=2;
int ld=yyextra->ldepth,ldepth,i=0,j=0,chunks;
char *name,*p,*end;
rxv_spin_bool_e loop=RXV_SPIN_FALSE;
rxv_spin_ref_t *ref=NULL,*prev=NULL;
rxv_spin_node_t *node=NULL;
yyextra->erow=-1; /* reset scanning error */
if(*(yytext+1)=='#' || *(yytext+1)=='@') noff++;
name=apr_pstrmemdup(yyextra->pool,yytext+noff,yyleng-(noff+1));
/* count chunks of the name */
for(chunks=0,p=name;p;p=strchr(p,'.')){
p++; chunks++;
}
/* simple reference */
if(chunks==1){
ref=apr_pcalloc(yyextra->pool,sizeof(*ref));
ref->name=name;
} else{ /* link references */
struct{
char *name;
apr_size_t fixed;
rxv_spin_bool_e loop;
}*rn=apr_palloc(yyextra->pool,chunks*sizeof(*rn)),*rnp;
rxv_spin_ref_t *r=NULL;
/* store chunks and their fixed indexes into an array */
for(p=name,rnp=rn;p;rnp++){
rnp->name=p;
/* find end of chunk */
if((p=strchr(p,'.'))){
end=p-1;
p++;
} else{
end=rnp->name+strlen(rnp->name)-1;
}
/* handle indexed chunk or loop */
if(*end==']'){
end=strchr(rnp->name,'[')-1;
rnp->fixed=0; sscanf(end+2,"%" APR_SIZE_T_FMT,&rnp->fixed);
if(!rnp->fixed){
node=NULL;
break;
}
rnp->fixed--;
rnp->loop=RXV_SPIN_FALSE;
} else{
rnp->fixed=0;
rnp->loop=RXV_SPIN_TRUE;
}
/* terminate chunk */
*(end+1)='\0';
}
/* find nearest enclosing loop */
for(ldepth=ld-1;ldepth>=0;ldepth--){
for(j=chunks-2;j>=0;j--){
r=(*(yyextra->loop+ldepth))->ref;
for(i=j;i>=0;i--)
if(!strcmp(r->name,rn[i].name) &&
((rn[i].loop && r->ip!=&r->fixed) ||
(!rn[i].loop && r->ip==&r->fixed && r->fixed==rn[i].fixed))){
if(!(r=r->ref))
goto rfound;
} else{
break;
}
}
rfound:
if(!r){
prev=(*(yyextra->loop+ldepth))->ref;
loop=RXV_SPIN_TRUE;
j++;
break;
}
}
/* check the fixed bit */
for(i=j;i<=chunks-1;i++){
/* impossible reference, ignore */
if(i>0 && rn[i].loop && !(i==chunks-1 && loop)){
node=NULL;
break;
}
ref=apr_pcalloc(yyextra->pool,sizeof(*ref));
ref->node.type=RXV_SPIN_REF;
ref->name=rn[i].name;
ref->ref=prev;
ref->ip=rn[i].loop?(prev?&prev->index:NULL):&ref->fixed;
if(ref->ip) *ref->ip=rn[i].fixed;
prev=ref;
}
}
if(ref){
switch(*(yytext+1)){
case '#': ref->node.rtyp=RXV_SPIN_REF_SIZ; break;
case '@': ref->node.rtyp=RXV_SPIN_REF_IND; break;
default: ref->node.rtyp=RXV_SPIN_REF_REG; break;
}
node=(rxv_spin_node_t *)ref;
node->type=RXV_SPIN_REF;
node->next=node;
}
*yylval=node;
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
return REF;
}
"#for" {
rxv_spin_for_t *loop=apr_pcalloc(yyextra->pool,sizeof(*loop));
rxv_spin_node_t *node=(rxv_spin_node_t *)loop;
yyextra->erow=-1; /* reset scanning error */
/* populate node */
node->type=RXV_SPIN_FOR;
node->next=node;
*(yyextra->loop+yyextra->ldepth)=loop;
*(yyextra->nest+yyextra->depth)=RXV_SPIN_FOR;
yyextra->depth++; yyextra->ldepth++;
if(yyextra->depth>=RXV_SPIN_MAX_DEPTH){
yyextra->error="maximum nesting depth exceeded";
*yylval=NULL; return ERR;
}
yy_push_state(command,yyscanner);
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return FOR;
}
"#if"|"#unless" {
rxv_spin_if_t *cond=apr_pcalloc(yyextra->pool,sizeof(*cond));
rxv_spin_node_t *node=(rxv_spin_node_t *)cond;
yyextra->erow=-1; /* reset scanning error */
/* populate node */
node->type=RXV_SPIN_IF;
node->next=node;
/* are we if (always 0) or unless (always 1) */
if(*(yytext+1)=='u')
node->ityp=RXV_SPIN_IF_UNLESS;
*(yyextra->nest+yyextra->depth)=RXV_SPIN_IF;
yyextra->depth++;
if(yyextra->depth>=RXV_SPIN_MAX_DEPTH){
yyextra->error="maximum nesting depth exceeded";
*yylval=NULL; return ERR;
}
yy_push_state(command,yyscanner);
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return IF;
}
"#else" {
yyextra->erow=-1; /* reset scanning error */
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return ELSE;
}
"#end" {
yyextra->erow=-1; /* reset scanning error */
/* previous node was a #for loop */
if(*(yyextra->nest+yyextra->depth-1)==RXV_SPIN_FOR){
*(yyextra->loop+yyextra->ldepth)=NULL;
yyextra->ldepth--;
}
yyextra->depth--;
if(yyextra->depth<0){
yyextra->error="minimum nesting depth exceeded";
*yylval=NULL; return ERR;
}
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return END;
}
. |
"#f" |
"#fo" |
"#e" |
"#en" |
"#i" |
"#u" |
"#un" |
"#unl" |
"#unle" |
"#unles" |
"#el" |
"#els" |
\$[#@]* |
\$[#@]*\{ |
\$[#@]*\{[[:alpha:]] |
\$[#@]*\{{RC1} |
\$[#@]*\{{RC1}({RC2})*\. |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]] |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]* |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[ |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+ |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+\] {
rxv_spin_node_t *node;
rxv_spin_txt_t *txt;
YYERROR_RECOVER
yyextra->erow=-1; /* reset scanning error */
txt=apr_pcalloc(yyextra->pool,sizeof(*txt));
node=(rxv_spin_node_t *)txt;
node->type=RXV_SPIN_TXT;
node->next=node;
txt->length=yyleng;
if(yyextra->f){
txt->text=apr_pstrmemdup(yyextra->pool,yytext,yyleng);
node->ttyp=RXV_SPIN_TXT_TXT;
} else{
txt->start=yyextra->offset;
node->ttyp=RXV_SPIN_TXT_OFF;
}
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return TXT;
}
[^$#\n]+ {
rxv_spin_txt_t *txt=apr_pcalloc(yyextra->pool,sizeof(*txt));
rxv_spin_node_t *node=(rxv_spin_node_t *)txt;
yyextra->erow=-1; /* reset scanning error */
node->type=RXV_SPIN_TXT;
node->next=node;
txt->length=yyleng;
if(yyextra->f){
txt->text=apr_pstrmemdup(yyextra->pool,yytext,yyleng);
node->ttyp=RXV_SPIN_TXT_TXT;
} else{
txt->start=yyextra->offset;
node->ttyp=RXV_SPIN_TXT_OFF;
}
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return TXT;
}
"#f\n" |
"#fo\n" |
"#e\n" |
"#en\n" |
"#i\n" |
"#u\n" |
"#un\n" |
"#unl\n" |
"#unle\n" |
"#unles\n" |
"#el\n" |
"#els\n" |
\$[#@]*\n |
\$[#@]*\{\n |
\$[#@]*\{[[:alpha:]]\n |
\$[#@]*\{{RC1}\n |
\$[#@]*\{{RC1}({RC2})*\.\n |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]]\n |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\n |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[\n |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+\n |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+\]\n |
[^$#\n]+\n {
YYLINE_LINE(1)
}
/* multiple line matching for better performance */
[^$#\n]*\n[^$#\n]* {
YYLINE_LINE(1)
}
([^$#\n]*\n){2}[^$#\n]* {
YYLINE_LINE(2)
}
([^$#\n]*\n){3}[^$#\n]* {
YYLINE_LINE(3)
}
([^$#\n]*\n){4}[^$#\n]* {
YYLINE_LINE(4)
}
([^$#\n]*\n){5}[^$#\n]* {
YYLINE_LINE(5)
}
([^$#\n]*\n){6}[^$#\n]* {
YYLINE_LINE(6)
}
([^$#\n]*\n){7}[^$#\n]* {
YYLINE_LINE(7)
}
([^$#\n]*\n){8}[^$#\n]* {
YYLINE_LINE(8)
}
([^$#\n]*\n){9}[^$#\n]* {
YYLINE_LINE(9)
}
([^$#\n]*\n){10}[^$#\n]* {
YYLINE_LINE(10)
}
([^$#\n]*\n){11}[^$#\n]* {
YYLINE_LINE(11)
}
([^$#\n]*\n){12}[^$#\n]* {
YYLINE_LINE(12)
}
([^$#\n]*\n){13}[^$#\n]* {
YYLINE_LINE(13)
}
([^$#\n]*\n){14}[^$#\n]* {
YYLINE_LINE(14)
}
([^$#\n]*\n){15}[^$#\n]* {
YYLINE_LINE(15)
}
([^$#\n]*\n){16}[^$#\n]* {
YYLINE_LINE(16)
}
([^$#\n]*\n){17}[^$#\n]* {
YYLINE_LINE(17)
}
([^$#\n]*\n){18}[^$#\n]* {
YYLINE_LINE(18)
}
([^$#\n]*\n){19}[^$#\n]* {
YYLINE_LINE(19)
}
([^$#\n]*\n){20}[^$#\n]* {
YYLINE_LINE(20)
}
([^$#\n]*\n){21}[^$#\n]* {
YYLINE_LINE(21)
}
([^$#\n]*\n){22}[^$#\n]* {
YYLINE_LINE(22)
}
([^$#\n]*\n){23}[^$#\n]* {
YYLINE_LINE(23)
}
([^$#\n]*\n){24}[^$#\n]* {
YYLINE_LINE(24)
}
([^$#\n]*\n){25}[^$#\n]* {
YYLINE_LINE(25)
}
([^$#\n]*\n){26}[^$#\n]* {
YYLINE_LINE(26)
}
([^$#\n]*\n){27}[^$#\n]* {
YYLINE_LINE(27)
}
([^$#\n]*\n){28}[^$#\n]* {
YYLINE_LINE(28)
}
([^$#\n]*\n){29}[^$#\n]* {
YYLINE_LINE(29)
}
([^$#\n]*\n){30}[^$#\n]* {
YYLINE_LINE(30)
}
([^$#\n]*\n){31}[^$#\n]* {
YYLINE_LINE(31)
}
([^$#\n]*\n){32}[^$#\n]* {
YYLINE_LINE(32)
}
([^$#\n]*\n){33}[^$#\n]* {
YYLINE_LINE(33)
}
([^$#\n]*\n){34}[^$#\n]* {
YYLINE_LINE(34)
}
([^$#\n]*\n){35}[^$#\n]* {
YYLINE_LINE(35)
}
([^$#\n]*\n){36}[^$#\n]* {
YYLINE_LINE(36)
}
([^$#\n]*\n){37}[^$#\n]* {
YYLINE_LINE(37)
}
([^$#\n]*\n){38}[^$#\n]* {
YYLINE_LINE(38)
}
([^$#\n]*\n){39}[^$#\n]* {
YYLINE_LINE(39)
}
([^$#\n]*\n){40}[^$#\n]* {
YYLINE_LINE(40)
}
\n+ {
rxv_spin_txt_t *txt=apr_pcalloc(yyextra->pool,sizeof(*txt));
rxv_spin_node_t *node=(rxv_spin_node_t *)txt;
yyextra->erow=-1; /* reset scanning error */
node->type=RXV_SPIN_TXT;
node->next=node;
txt->length=yyleng;
if(yyextra->f){
txt->text=apr_pstrmemdup(yyextra->pool,yytext,yyleng);
node->ttyp=RXV_SPIN_TXT_TXT;
} else{
txt->start=yyextra->offset;
node->ttyp=RXV_SPIN_TXT_OFF;
}
yyextra->offset+=yyleng; yyextra->bpos+=yyleng;
yyextra->row+=yyleng; yyextra->col=0;
*yylval=node; return TXT;
}
/* command scanner */
{
{REF} {
size_t noff=2;
int ld=yyextra->ldepth,ldepth,i=0,j=0,chunks;
char *name,*p,*end;
rxv_spin_bool_e loop=RXV_SPIN_FALSE;
rxv_spin_ref_t *ref=NULL,*prev=NULL;
rxv_spin_node_t *node=NULL;
yyextra->erow=-1; /* reset scanning error */
if(*(yytext+1)=='#' || *(yytext+1)=='@') noff++;
name=apr_pstrmemdup(yyextra->pool,yytext+noff,yyleng-(noff+1));
/* count chunks of the name */
for(chunks=0,p=name;p;p=strchr(p,'.')){
p++; chunks++;
}
/* was this a #for or an #if? */
if(*(yyextra->nest+yyextra->depth-1)==RXV_SPIN_FOR)
ld--;
/* simple reference */
if(chunks==1){
ref=apr_pcalloc(yyextra->pool,sizeof(*ref));
ref->name=name;
} else{ /* link references */
struct{
char *name;
apr_size_t fixed;
rxv_spin_bool_e loop;
}*rn=apr_palloc(yyextra->pool,chunks*sizeof(*rn)),*rnp;
rxv_spin_ref_t *r=NULL;
/* store chunks and their fixed indexes into an array */
for(p=name,rnp=rn;p;rnp++){
rnp->name=p;
/* find end of chunk */
if((p=strchr(p,'.'))){
end=p-1;
p++;
} else{
end=rnp->name+strlen(rnp->name)-1;
}
/* handle indexed chunk or loop */
if(*end==']'){
end=strchr(rnp->name,'[')-1;
rnp->fixed=0; sscanf(end+2,"%" APR_SIZE_T_FMT,&rnp->fixed);
if(!rnp->fixed){
node=NULL;
break;
}
rnp->fixed--;
rnp->loop=RXV_SPIN_FALSE;
} else{
rnp->fixed=0;
rnp->loop=RXV_SPIN_TRUE;
}
/* terminate chunk */
*(end+1)='\0';
}
/* find nearest enclosing loop */
for(ldepth=ld-1;ldepth>=0;ldepth--){
for(j=chunks-2;j>=0;j--){
r=(*(yyextra->loop+ldepth))->ref;
for(i=j;i>=0;i--)
if(!strcmp(r->name,rn[i].name) &&
((rn[i].loop && r->ip!=&r->fixed) ||
(!rn[i].loop && r->ip==&r->fixed && r->fixed==rn[i].fixed))){
if(!(r=r->ref))
goto cfound;
} else{
break;
}
}
cfound:
if(!r){
prev=(*(yyextra->loop+ldepth))->ref;
loop=RXV_SPIN_TRUE;
j++;
break;
}
}
/* check the fixed bit */
for(i=j;i<=chunks-1;i++){
/* impossible reference, ignore */
if(i>0 && rn[i].loop && !(i==chunks-1 && loop)){
node=NULL;
break;
}
ref=apr_pcalloc(yyextra->pool,sizeof(*ref));
ref->node.type=RXV_SPIN_REF;
ref->name=rn[i].name;
ref->ref=prev;
ref->ip=rn[i].loop?(prev?&prev->index:NULL):&ref->fixed;
if(ref->ip) *ref->ip=rn[i].fixed;
prev=ref;
}
}
/* link the reference to the #for loop */
if(ldldepth)
(*(yyextra->loop+ld))->ref=ref;
if(ref){
switch(*(yytext+1)){
case '#': ref->node.rtyp=RXV_SPIN_REF_SIZ; break;
case '@': ref->node.rtyp=RXV_SPIN_REF_IND; break;
default: ref->node.rtyp=RXV_SPIN_REF_REG; break;
}
node=(rxv_spin_node_t *)ref;
node->type=RXV_SPIN_REF;
}
*yylval=node;
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
return CRF;
}
{REG} {
rxv_spin_reg_t *reg=apr_pcalloc(yyextra->pool,sizeof(*reg));
rxv_spin_node_t *node=(rxv_spin_node_t *)reg;
char *p,*r;
yyextra->erow=-1; /* reset scanning error */
/* populate node */
node->type=RXV_SPIN_REG;
reg->srg=apr_pstrmemdup(yyextra->pool,yytext+1,yyleng-2);
/* turn escaped '\/' into '/' */
for(p=reg->srg;*p;p++)
if(*p=='\\' && *(p+1)=='/')
for(r=p;r;r++)
*r=*(r+1);
if(ap_regcomp(®->reg,reg->srg,
AP_REG_EXTENDED|AP_REG_NOSUB)!=APR_SUCCESS){
yyextra->error="invalid regular expression";
*yylval=NULL; return ERR;
}
apr_pool_cleanup_register(yyextra->pool,®->reg,
regex_cleanup,apr_pool_cleanup_null);
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return REG;
}
{LIT} {
rxv_spin_lit_t *lit=apr_pcalloc(yyextra->pool,sizeof(*lit));
rxv_spin_node_t *node=(rxv_spin_node_t *)lit;
char *p,*r;
yyextra->erow=-1; /* reset scanning error */
/* populate node */
node->type=RXV_SPIN_LIT;
lit->lit=apr_pstrmemdup(yyextra->pool,yytext+1,yyleng-2);
/* turn escaped '\"' into '"' */
for(p=lit->lit;*p;p++)
if(*p=='\\' && *(p+1)=='"')
for(r=p;r;r++)
*r=*(r+1);
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return LIT;
}
[[:digit:]]+ {
rxv_spin_num_t *num;
rxv_spin_node_t *node;
YYERROR_RECOVER
num=apr_pcalloc(yyextra->pool,sizeof(*num));
node=(rxv_spin_node_t *)num;
yyextra->erow=-1; /* reset scanning error */
/* populate node */
node->type=RXV_SPIN_NUM;
num->num=0; sscanf(yytext,"%lu",&num->num);
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=node; return NUM;
}
"(" {
yyextra->erow=-1; /* reset scanning error */
yyextra->offset++; yyextra->bpos++; yyextra->col++;
*yylval=NULL; return '(';
}
")" {
yyextra->erow=-1; /* reset scanning error */
yy_pop_state(yyscanner);
yyextra->offset++; yyextra->bpos++; yyextra->col++;
*yylval=NULL; return ')';
}
"=~" {
yyextra->erow=-1; /* reset scanning error */
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return MCH;
}
"==" {
yyextra->erow=-1; /* reset scanning error */
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return EQL;
}
"%" {
yyextra->erow=-1; /* reset scanning error */
yyextra->offset++; yyextra->bpos++; yyextra->col++;
*yylval=NULL; return '%';
}
[ \r\t]+ { /* ignore whitespace */
yyextra->erow=-1; /* reset scanning error */
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
}
\n+ { /* ignore whitespace */
yyextra->erow=-1; /* reset scanning error */
yyextra->offset+=yyleng; yyextra->bpos+=yyleng;
yyextra->row+=yyleng; yyextra->col=0;
}
=[^=~]* |
\$[#@]* |
\$[#@]*\{ |
\$[#@]*\{[[:alpha:]] |
\$[#@]*\{{RC1} |
\$[#@]*\{{RC1}({RC2})*\. |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]] |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]* |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[ |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+ |
\$[#@]*\{{RC1}({RC2})*\.[[:alpha:]][[:alnum:]_-]*\[[[:digit:]]+\] |
\/([^/]|\\\/)* |
\"([^"]|\\\")* { /* garbage */
YYERROR_RECOVER
yyextra->erow=-1; /* reset scanning error */
yyextra->error="garbage text in command";
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return ERR;
}
[^$()=%\"\/[:digit:]\n]+ { /* garbage */
yyextra->erow=-1; /* reset scanning error */
yyextra->error="garbage text in command";
yyextra->offset+=yyleng; yyextra->bpos+=yyleng; yyextra->col+=yyleng;
*yylval=NULL; return ERR;
}
}
%%
#define yyg ((struct yyguts_t *)scanner)
static apr_status_t regex_cleanup(void *data){
ap_regfree((ap_regex_t *)data);
return APR_SUCCESS;
}
int rxv_spin_yywrap(yyscan_t scanner){
apr_size_t len,left,need,max,nbuck=0,soff;
const char *s;
rxv_spin_extra_t *extra=rxv_spin_yyget_extra(scanner);
apr_bucket *b=extra->scan;
extra->blen=0;
while(extra->bleninput)){
extra->eof=b;
break;
}
/* end of stream */
if(APR_BUCKET_IS_EOS(b)){
extra->eos=b;
break;
}
/* some filter only magic */
if(extra->f){
/* send metadata buckets down the filter chain */
if(APR_BUCKET_IS_METADATA(b)){
apr_bucket *e=b;
b=APR_BUCKET_NEXT(b);
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(extra->metabb,e);
continue;
}
/* filters should try non-blocking read first */
switch(apr_bucket_read(b,&s,&len,APR_NONBLOCK_READ)){
case APR_EAGAIN:
/* send FLUSH bucket down the filter chain */
APR_BRIGADE_INSERT_TAIL(extra->output,
apr_bucket_flush_create(extra->output->bucket_alloc));
if(ap_pass_brigade(extra->f->next,extra->output)!=APR_SUCCESS){
extra->error="cannot pass flush bucket to filters";
return 1;
}
apr_brigade_cleanup(extra->output); /* empty brigade for real data */
break;
case APR_SUCCESS:
goto read_done;
default:
extra->error="input read error";
return 1;
}
}
if(apr_bucket_read(b,&s,&len,APR_BLOCK_READ)!=APR_SUCCESS){
extra->error="input read error";
return 1;
}
read_done:
/* skipping until buffer offset is zero */
if(!nbuck && extra->bpos>0){
/* nothing to copy from this bucket */
if(extra->soff+extra->bpos>=len){
extra->bpos-=len-extra->soff;
extra->soff=0;
extra->scan=b=APR_BUCKET_NEXT(b);
continue;
} else{
extra->soff+=extra->bpos;
extra->bpos=0;
}
}
/* subsequent buckets always have offset zero */
soff=nbuck++?0:extra->soff;
left=len-soff;
need=RXV_SPIN_SCAN_MAX-extra->blen;
max=left>need?need:left;
memcpy(extra->buf+extra->blen,s+soff,max);
extra->blen+=max;
b=APR_BUCKET_NEXT(b);
}
/* nothing to scan */
if(!extra->blen)
return 1;
/* terminate flex buffer properly */
memset(extra->buf+extra->blen,0,2);
rxv_spin_yy_delete_buffer(YY_CURRENT_BUFFER,scanner);
rxv_spin_yy_scan_buffer(extra->buf,extra->blen+2,scanner);
return 0;
}