/** * 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; }