Input: wordchrs - set up word - chr list for word - boundary stuff if needed The list is kept as a bunch of arcs between two dummy states ; it s disposed of by the unreachable - states sweep in NFA optimization . Does NEXT () . Must not be called from any unusual lexical context . This should be reconciled with the \ w etc . handling in lex . c and should be cleaned up to reduce dependencies on input scanning . [CODESPLIT] private void wordchrs ( ) throws RegexException { State left ; State right ; if ( wordchrs != null ) { lex . next ( ) ; /* for consistency */ return ; } left = nfa . newstate ( ) ; right = nfa . newstate ( ) ; /* fine point:  implemented with [::], and lexer will set REG_ULOCALE */ lex . lexword ( ) ; lex . next ( ) ; assert savepattern != null && see ( ' ' ) ; bracket ( left , right ) ; assert savepattern != null && see ( ' ' ) ; lex . next ( ) ; wordchrs = left ; }


Input: bracket - handle non - complemented bracket expression Also called from cbracket for complemented bracket expressions . [CODESPLIT] private void bracket ( State lp , State rp ) throws RegexException { assert see ( ' ' ) ; lex . next ( ) ; while ( ! see ( ' ' ) && ! see ( EOS ) ) { brackpart ( lp , rp ) ; } assert see ( ' ' ) ; cm . okcolors ( nfa ) ; }


Input:
brackpart - handle one item ( or range ) within a bracket expression [CODESPLIT] private void brackpart ( State lp , State rp ) throws RegexException { UnicodeSet set ; /*
         * OK, well; if the user uses \U the item that comes next can be a full codepoint.
         * If the user does not, it might be part of a surrogate.
         */ int c ; // start and end chars of a range int startc ; int endc = 0 ; int ele ; /* parse something, get rid of special cases, take shortcuts */ switch ( nexttype ) { case RANGE : /* a-b-c or other botch */ throw new RegexException ( "Invalid syntax in range expression." ) ; case PLAIN : c = nextvalue ; lex . next ( ) ; if ( c <= Character . MAX_VALUE && Character . isHighSurrogate ( ( char ) c ) ) { // some idiot could write a high surrogate and then immediate \\Uxxxxx, woof. char low = ( char ) nextvalue ; lex . next ( ) ; startc = Character . toCodePoint ( ( char ) c , low ) ; } else { startc = c ; } /* shortcut for ordinary char (not range, not MCCE leader) */ if ( ! see ( RANGE ) ) { onechr ( startc , lp , rp ) ; return ; } break ; // COLLEL and ECLASS are of dubious utility and don't try to get surrogates right. case COLLEL : String charName = scanplain ( ) ; if ( charName . length ( ) == 0 ) { throw new RegexException ( "Missing character name for collation." ) ; } ele = Locale . element ( charName ) ; if ( ele == - 1 ) { throw new RegexException ( "Invalid character name " + charName ) ; } else { startc = ( char ) ele ; } break ; case ECLASS : charName = scanplain ( ) ; if ( charName . length ( ) == 0 ) { throw new RegexException ( "Unterminated or invalid equivalence class." ) ; } ele = Locale . element ( charName ) ; if ( ele == - 1 ) { throw new RegexException ( "Invalid character name " + charName ) ; } else { startc = ( char ) ele ; } set = Locale . eclass ( ( char ) startc , 0 != ( cflags & Flags . REG_ICASE ) ) ; dovec ( set , lp , rp ) ; return ; case CCLASS : String className = scanplain ( ) ; if ( className . length ( ) == 0 ) { throw new RegexException ( "Missing class name for char class." ) ; } set = Locale . cclass ( className , 0 != ( cflags & Flags . REG_ICASE ) ) ; dovec ( set , lp , rp ) ; return ; default : throw new RegexException ( "Impossible lexical state." ) ; } if ( see ( RANGE ) ) { lex . next ( ) ; switch ( nexttype ) { case PLAIN : case RANGE : c = nextvalue ; lex . next ( ) ; if ( c <= Character . MAX_VALUE && Character . isHighSurrogate ( ( char ) c ) ) { char low = ( char ) nextvalue ; lex . next ( ) ; endc = Character . toCodePoint ( ( char ) c , low ) ; } else { endc = c ; } break ; case COLLEL : String charName = scanplain ( ) ; if ( charName . length ( ) == 0 ) { throw new RegexException ( "Missing character name in collation." ) ; } // look up named character. ele = Locale . element ( charName ) ; if ( ele == - 1 ) { throw new RegexException ( "Invalid character name " + charName ) ; } break ; default : throw new RegexException ( "Invalid syntax in range." ) ; } } else { endc = startc ; } set = new UnicodeSet ( startc , endc ) ; if ( 0 != ( cflags & Flags . REG_ICASE ) ) { set . closeOver ( UnicodeSet . ADD_CASE_MAPPINGS ) ; } dovec ( set , lp , rp ) ; }


Input: scanplain - scan PLAIN contents of [ . etc . Certain bits of trickery in lex . c know that this code does not try to look past the final bracket of the [ . etc . [CODESPLIT] private String scanplain ( ) throws RegexException { int startp = now ; int endp ; assert see ( COLLEL ) || see ( ECLASS ) || see ( CCLASS ) ; lex . next ( ) ; endp = now ; while ( see ( PLAIN ) ) { endp = now ; lex . next ( ) ; } String ret = new String ( pattern , startp , endp - startp ) ; assert see ( END ) ; lex . next ( ) ; return ret ; }


Input: cbracket - handle complemented bracket expression We do it by calling bracket () with dummy endpoints and then complementing the result . The alternative would be to invoke rainbow () and then delete arcs as the b . e . is seen ... but that gets messy . [CODESPLIT] private void cbracket ( State lp , State rp ) throws RegexException { State left = nfa . newstate ( ) ; State right = nfa . newstate ( ) ; bracket ( left , right ) ; if ( 0 != ( cflags & Flags . REG_NLSTOP ) ) { nfa . newarc ( PLAIN , nlcolor , left , right ) ; } assert lp . nouts == 0 ; /* all outarcs will be ours */ /* easy part of complementing */ cm . colorcomplement ( nfa , PLAIN , left , lp , rp ) ; // No MCCE in Java. nfa . dropstate ( left ) ; assert right . nins == 0 ; nfa . freestate ( right ) ; }


Input: newlacon - allocate a lookahead - constraint subRE [CODESPLIT] private int newlacon ( State begin , State end , int pos ) { if ( lacons . size ( ) == 0 ) { // skip 0 lacons . add ( null ) ; } Subre sub = new Subre ( ( char ) 0 , 0 , begin , end ) ; sub . subno = pos ; lacons . add ( sub ) ; return lacons . size ( ) - 1 ; // it's the index into the array, -1. }


Input: onechr - fill in arcs for a plain character and possible case complements This is mostly a shortcut for efficient handling of the common case . [CODESPLIT] private void onechr ( int c , State lp , State rp ) throws RegexException { if ( 0 == ( cflags & Flags . REG_ICASE ) ) { nfa . newarc ( PLAIN , cm . subcolor ( c ) , lp , rp ) ; return ; } /* rats, need general case anyway... */ dovec ( Locale . allcases ( c ) , lp , rp ) ; }


Input:
dovec - fill in arcs for each element of a cvec all kinds of MCCE complexity removed . [CODESPLIT] private void dovec ( UnicodeSet set , State lp , State rp ) throws RegexException { int rangeCount = set . getRangeCount ( ) ; for ( int rx = 0 ; rx < rangeCount ; rx ++ ) { int rangeStart = set . getRangeStart ( rx ) ; int rangeEnd = set . getRangeEnd ( rx ) ; /*
             * Note: ICU operates in UTF-32 here, and the ColorMap is happy to play along.
             */ if ( LOG . isDebugEnabled ( ) && IS_DEBUG ) { LOG . debug ( String . format ( "%s %d %4x %4x" , set , rx , rangeStart , rangeEnd ) ) ; } //TODO: this arc is probably redundant. if ( rangeStart == rangeEnd ) { nfa . newarc ( PLAIN , cm . subcolor ( rangeStart ) , lp , rp ) ; } cm . subrange ( rangeStart , rangeEnd , lp , rp ) ; } }


Input: Compile a pattern . [CODESPLIT] public static RePattern compile ( String pattern , EnumSet < PatternFlags > flags ) throws RegexException { return Compiler . compile ( pattern , flags ) ; }


Input: Compile a pattern . [CODESPLIT] public static RePattern compile ( String pattern , PatternFlags ... flags ) throws RegexException { EnumSet < PatternFlags > flagSet = EnumSet . noneOf ( PatternFlags . class ) ; Collections . addAll ( flagSet , flags ) ; return Compiler . compile ( pattern , flagSet ) ; }


Input: / * back chain [CODESPLIT] Arc findarc ( int type , short co ) { for ( Arc a = outs ; a != null ; a = a . outchain ) { if ( a . type == type && a . co == co ) { return a ; } } return null ; }


Input: Retrieve the color for a character . [CODESPLIT] private short getcolor ( int c ) { try { return map . get ( c ) ; } catch ( NullPointerException npe ) { throw new RegexRuntimeException ( String . format ( "Failed to map codepoint U+%08X." , c ) ) ; } }


Input: pseudocolor - allocate a false color to be managed by other means . [CODESPLIT] short pseudocolor ( ) { short co = newcolor ( ) ; ColorDesc cd = colorDescs . get ( co ) ; cd . setNChars ( 1 ) ; cd . markPseudo ( ) ; return co ; }


Input: subcolor - allocate a new subcolor ( if necessary ) to this char Internal API that can do a range of characters ; called from { @link #subrange } . [CODESPLIT] private short subcolor ( int c , int rangeCount ) throws RegexException { short co ; /* current color of c */ short sco ; /* new subcolor */ co = getcolor ( c ) ; sco = newsub ( co ) ; assert sco != Constants . COLORLESS ; if ( co == sco ) /* already in an open subcolor */ { return co ; /* rest is redundant */ } ColorDesc cd = colorDescs . get ( co ) ; cd . incrementNChars ( - rangeCount ) ; ColorDesc scd = colorDescs . get ( sco ) ; scd . incrementNChars ( rangeCount ) ; map . put ( Range . closedOpen ( c , c + rangeCount ) , sco ) ; return sco ; }


Input: newsub - allocate a new subcolor ( if necessary ) for a color [CODESPLIT] private short newsub ( short co ) throws RegexException { short sco ; // new subcolor. ColorDesc cd = colorDescs . get ( co ) ; sco = colorDescs . get ( co ) . sub ; if ( sco == Constants . NOSUB ) { /* color has no open subcolor */ if ( cd . getNChars ( ) == 1 ) { /* optimization */ return co ; } sco = newcolor ( ) ; /* must create subcolor */ if ( sco == Constants . COLORLESS ) { throw new RegexException ( "Invalid color allocation" ) ; } ColorDesc subcd = colorDescs . get ( sco ) ; cd . sub = sco ; subcd . sub = sco ; /* open subcolor points to self */ } return sco ; }


Input:
subrange - allocate new subcolors to this range of chars fill in arcs . The range will overlap existing ranges ; even in the simplest case it will overlap the initial WHITE range . For each existing range that it overlaps allocate a new color mark the range as mapping to that color and add an arc between the states for that color . [CODESPLIT] void subrange ( int from , int to , State lp , State rp ) throws RegexException { /* Avoid one call to map.get() for each character in the range.
         * This map will usually contain one item, but in complex cases more.
         * For example, if we had [a-f][g-h] and then someone asked for [f-g], there
         * would be two. Each of these new ranges will get a new color via subcolor.
         */ Map < Range < Integer > , Short > curColors = map . subRangeMap ( Range . closed ( from , to ) ) . asMapOfRanges ( ) ; /*
         * To avoid concurrent mod problems, we need to copy the ranges we are working from.
         */ List < Range < Integer > > ranges = Lists . newArrayList ( curColors . keySet ( ) ) ; for ( Range < Integer > rangeToProcess : ranges ) { // bound management here irritating. int start = rangeToProcess . lowerEndpoint ( ) ; if ( rangeToProcess . lowerBoundType ( ) == BoundType . OPEN ) { start ++ ; } int end = rangeToProcess . upperEndpoint ( ) ; if ( rangeToProcess . upperBoundType ( ) == BoundType . CLOSED ) { end ++ ; } // allocate a new subcolor and account it owning the entire range. short color = subcolor ( start , end - start ) ; compiler . getNfa ( ) . newarc ( Compiler . PLAIN , color , lp , rp ) ; } }


Input: okcolors - promote subcolors to full colors [CODESPLIT] void okcolors ( Nfa nfa ) { ColorDesc cd ; ColorDesc scd ; Arc a ; short sco ; for ( short co = 0 ; co < colorDescs . size ( ) ; co ++ ) { cd = colorDescs . get ( co ) ; if ( cd == null ) { continue ; // not in use at all, so can't have a subcolor. } sco = cd . sub ; if ( sco == Constants . NOSUB ) { /* has no subcolor, no further action */ } else if ( sco == co ) { /* is subcolor, let parent deal with it */ } else if ( cd . getNChars ( ) == 0 ) { /* parent empty, its arcs change color to subcolor */ cd . sub = Constants . NOSUB ; scd = colorDescs . get ( sco ) ; assert scd . getNChars ( ) > 0 ; assert scd . sub == sco ; scd . sub = Constants . NOSUB ; while ( ( a = cd . arcs ) != null ) { assert a . co == co ; cd . arcs = a . colorchain ; a . setColor ( sco ) ; a . colorchain = scd . arcs ; scd . arcs = a ; } freecolor ( co ) ; } else { /* parent's arcs must gain parallel subcolor arcs */ cd . sub = Constants . NOSUB ; scd = colorDescs . get ( sco ) ; assert scd . getNChars ( ) > 0 ; assert scd . sub == sco ; scd . sub = Constants . NOSUB ; for ( a = cd . arcs ; a != null ; a = a . colorchain ) { assert a . co == co ; nfa . newarc ( a . type , sco , a . from , a . to ) ; } } } }


Input: colorchain - add this arc to the color chain of its color [CODESPLIT] void colorchain ( Arc a ) { ColorDesc cd = colorDescs . get ( a . co ) ; a . colorchain = cd . arcs ; cd . arcs = a ; }


Input: uncolorchain - delete this arc from the color chain of its color [CODESPLIT] void uncolorchain ( Arc a ) { ColorDesc cd = colorDescs . get ( a . co ) ; Arc aa ; aa = cd . arcs ; if ( aa == a ) { /* easy case */ cd . arcs = a . colorchain ; } else { for ( ; aa != null && aa . colorchain != a ; aa = aa . colorchain ) { // } assert aa != null ; aa . colorchain = a . colorchain ; } a . colorchain = null ; /* paranoia */ }


Input: rainbow - add arcs of all full colors ( but one ) between specified states [CODESPLIT] void rainbow ( Nfa nfa , int type , short but , State from , State to ) { ColorDesc cd ; short co ; for ( co = 0 ; co < colorDescs . size ( ) ; co ++ ) { cd = colorDescs . get ( co ) ; if ( cd != null && cd . sub != co && co != but && ! cd . pseudo ( ) ) { nfa . newarc ( type , co , from , to ) ; } } }


Input: colorcomplement - add arcs of complementary colors The calling sequence ought to be reconciled with cloneouts () . [CODESPLIT] void colorcomplement ( Nfa nfa , int type , State of , State from , State to ) { ColorDesc cd ; short co ; assert of != from ; for ( co = 0 ; co < colorDescs . size ( ) ; co ++ ) { cd = colorDescs . get ( co ) ; if ( cd != null && ! cd . pseudo ( ) ) { if ( of . findarc ( Compiler . PLAIN , co ) == null ) { nfa . newarc ( type , co , from , to ) ; } } } }


Input:
dumpcolors - debugging output [CODESPLIT] void dumpcolors ( ) { /*
         * we want to organize this by colors.
         */ for ( int co = 0 ; co < colorDescs . size ( ) ; co ++ ) { ColorDesc cd = colorDescs . get ( co ) ; if ( cd != null ) { dumpcolor ( co , cd ) ; } } }


Input: / * Not speedy . This is for debugging . [CODESPLIT] private void dumpcolor ( int co , ColorDesc cd ) { StringWriter sw = new StringWriter ( ) ; PrintWriter pw = new PrintWriter ( sw ) ; pw . format ( "Color %d - %d chars %s\n" , co , cd . getNChars ( ) , cd . pseudo ( ) ? " (pseudo)" : "" ) ; for ( Map . Entry < Range < Integer > , Short > me : map . asMapOfRanges ( ) . entrySet ( ) ) { if ( me . getValue ( ) == co ) { pw . format ( " %s %s\n" , me . getKey ( ) , UCharacter . getExtendedName ( me . getKey ( ) . lowerEndpoint ( ) ) ) ; } } pw . flush ( ) ; String r = sw . toString ( ) ; System . out . println ( r ) ; }


Input: lexstart - set up lexical stuff scan leading options [CODESPLIT] void lexstart ( ) throws RegexException { prefixes ( ) ; /* may turn on new type bits etc. */ if ( 0 != ( v . cflags & Flags . REG_QUOTE ) ) { assert 0 == ( v . cflags & ( Flags . REG_ADVANCED | Flags . REG_EXPANDED | Flags . REG_NEWLINE ) ) ; intocon ( L_Q ) ; } else if ( 0 != ( v . cflags & Flags . REG_EXTENDED ) ) { assert 0 == ( v . cflags & Flags . REG_QUOTE ) ; intocon ( L_ERE ) ; } else { assert 0 == ( v . cflags & ( Flags . REG_QUOTE | Flags . REG_ADVF ) ) ; intocon ( L_BRE ) ; } v . nexttype = Compiler . EMPTY ; /* remember we were at the start */ next ( ) ; /* set up the first token */ }


Input: prefixes - implement various special prefixes [CODESPLIT] void prefixes ( ) throws RegexException { /* literal string doesn't get any of this stuff */ if ( 0 != ( v . cflags & Flags . REG_QUOTE ) ) { return ; } /* initial "***" gets special things */ if ( have ( 4 ) && next3 ( ' ' , ' ' , ' ' ) ) { switch ( charAtNowPlus ( 3 ) ) { case ' ' : /* "***?" error, msg shows version */ throw new RegexException ( "REG_BADPAT" ) ; case ' ' : /* "***=" shifts to literal string */ v . note ( Flags . REG_UNONPOSIX ) ; v . cflags |= Flags . REG_QUOTE ; v . cflags &= ~ ( Flags . REG_ADVANCED | Flags . REG_EXPANDED | Flags . REG_NEWLINE ) ; v . now += 4 ; return ; /* and there can be no more prefixes */ case ' ' : /* "***:" shifts to AREs */ v . note ( Flags . REG_UNONPOSIX ) ; v . cflags |= Flags . REG_ADVANCED ; v . now += 4 ; break ; default : /* otherwise *** is just an error */ throw new RegexException ( "REG_BADRPT" ) ; } } /* BREs and EREs don't get embedded options */ if ( ( v . cflags & Flags . REG_ADVANCED ) != Flags . REG_ADVANCED ) { return ; } /* embedded options (AREs only) */ if ( have ( 3 ) && next2 ( ' ' , ' ' ) && iscalpha ( charAtNowPlus ( 2 ) ) ) { v . note ( Flags . REG_UNONPOSIX ) ; v . now += 2 ; for ( ; ! ateos ( ) && iscalpha ( charAtNow ( ) ) ; v . now ++ ) { switch ( charAtNow ( ) ) { case ' ' : /* BREs (but why???) */ v . cflags &= ~ ( Flags . REG_ADVANCED | Flags . REG_QUOTE ) ; break ; case ' ' : /* case sensitive */ v . cflags &= ~ Flags . REG_ICASE ; break ; case ' ' : /* plain EREs */ v . cflags |= Flags . REG_EXTENDED ; v . cflags &= ~ ( Flags . REG_ADVF | Flags . REG_QUOTE ) ; break ; case ' ' : /* case insensitive */ v . cflags |= Flags . REG_ICASE ; break ; case ' ' : /* Perloid synonym for n */ case ' ' : /* \n affects ^ $ . [^ */ v . cflags |= Flags . REG_NEWLINE ; break ; case ' ' : /* ~Perl, \n affects . [^ */ v . cflags |= Flags . REG_NLSTOP ; v . cflags &= ~ Flags . REG_NLANCH ; break ; case ' ' : /* literal string */ v . cflags |= Flags . REG_QUOTE ; v . cflags &= ~ Flags . REG_ADVANCED ; break ; case ' ' : /* single line, \n ordinary */ v . cflags &= ~ Flags . REG_NEWLINE ; break ; case ' ' : /* tight syntax */ v . cflags &= ~ Flags . REG_EXPANDED ; break ; case ' ' : /* weird, \n affects ^ $ only */ v . cflags &= ~ Flags . REG_NLSTOP ; v . cflags |= Flags . REG_NLANCH ; break ; case ' ' : /* expanded syntax */ v . cflags |= Flags . REG_EXPANDED ; break ; default : throw new RegexException ( "REG_BADOPT" ) ; } } if ( ! next1 ( ' ' ) ) { throw new RegexException ( "REG_BADOPT" ) ; } v . now ++ ; if ( 0 != ( v . cflags & Flags . REG_QUOTE ) ) { v . cflags &= ~ ( Flags . REG_EXPANDED | Flags . REG_NEWLINE ) ; } } }


Input: lexnest - call a subroutine interpolating string at the lexical level Note this is not a very general facility . There are a number of implicit assumptions about what sorts of strings can be subroutines . [CODESPLIT] void lexnest ( char [ ] interpolated ) { assert v . savepattern == null ; /* only one level of nesting */ v . savepattern = v . pattern ; v . savenow = v . now ; v . savestop = v . stop ; v . savenow = v . now ; v . pattern = interpolated ; v . now = 0 ; v . stop = v . pattern . length ; }


Input: next - get next token [CODESPLIT] boolean next ( ) throws RegexException { char c ; /* remember flavor of last token */ v . lasttype = v . nexttype ; /* REG_BOSONLY */ if ( v . nexttype == Compiler . EMPTY && ( 0 != ( v . cflags & Flags . REG_BOSONLY ) ) ) { /* at start of a REG_BOSONLY RE */ return retv ( Compiler . SBEGIN , ( char ) 0 ) ; /* same as \A */ } /* if we're nested and we've hit end, return to outer level */ if ( v . savepattern != null && ateos ( ) ) { v . now = v . savenow ; v . stop = v . savestop ; v . savenow = - 1 ; v . savestop = - 1 ; v . pattern = v . savepattern ; v . savepattern = null ; // mark that it's not saved. } /* skip white space etc. if appropriate (not in literal or []) */ if ( 0 != ( v . cflags & Flags . REG_EXPANDED ) ) { switch ( v . lexcon ) { case L_ERE : case L_BRE : case L_EBND : case L_BBND : skip ( ) ; break ; } } /* handle EOS, depending on context */ if ( ateos ( ) ) { switch ( v . lexcon ) { case L_ERE : case L_BRE : case L_Q : return ret ( Compiler . EOS ) ; case L_EBND : case L_BBND : throw new RegexException ( "Unbalanced braces." ) ; case L_BRACK : case L_CEL : case L_ECL : case L_CCL : throw new RegexException ( "Unbalanced brackets." ) ; } assert false ; } /* okay, time to actually get a character */ c = charAtNowAdvance ( ) ; /* deal with the easy contexts, punt EREs to code below */ switch ( v . lexcon ) { case L_BRE : /* punt BREs to separate function */ return brenext ( c ) ; case L_ERE : /* see below */ break ; case L_Q : /* literal strings are easy */ return retv ( Compiler . PLAIN , c ) ; case L_BBND : /* bounds are fairly simple */ case L_EBND : switch ( c ) { case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : return retv ( Compiler . DIGIT , digitval ( c ) ) ; case ' ' : return ret ( ' ' ) ; case ' ' : /* ERE bound ends with } */ if ( incon ( L_EBND ) ) { intocon ( L_ERE ) ; if ( 0 != ( v . cflags & Flags . REG_ADVF ) && next1 ( ' ' ) ) { v . now ++ ; note ( Flags . REG_UNONPOSIX ) ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; } else { throw new RegexException ( "Errors.REG_BADBR" ) ; } case ' ' : /* BRE bound ends with \} */ if ( incon ( L_BBND ) && next1 ( ' ' ) ) { v . now ++ ; intocon ( L_BRE ) ; return ret ( ' ' ) ; } else { throw new RegexException ( "Errors.REG_BADBR" ) ; } default : throw new RegexException ( "Errors.REG_BADBR" ) ; } case L_BRACK : /* brackets are not too hard */ switch ( c ) { case ' ' : if ( lasttype ( ' ' ) ) { return retv ( Compiler . PLAIN , c ) ; } else { intocon ( 0 != ( v . cflags & Flags . REG_EXTENDED ) ? L_ERE : L_BRE ) ; return ret ( ' ' ) ; } case ' ' : note ( Flags . REG_UBBS ) ; if ( 0 == ( v . cflags & Flags . REG_ADVF ) ) { return retv ( Compiler . PLAIN , c ) ; } note ( Flags . REG_UNONPOSIX ) ; if ( ateos ( ) ) { throw new RegexException ( "REG_EESCAPE" ) ; } lexescape ( ) ; switch ( v . nexttype ) { /* not all escapes okay here */ case Compiler . PLAIN : return true ; case Compiler . CCLASS : switch ( v . nextvalue ) { case ' ' : lexnest ( brbackd ) ; break ; case ' ' : lexnest ( brbacks ) ; break ; case ' ' : lexnest ( brbackw ) ; break ; default : throw new RegexException ( "Errors.REG_EESCAPE" ) ; } /* lexnest done, back up and try again */ v . nexttype = v . lasttype ; return next ( ) ; } /* not one of the acceptable escapes */ throw new RegexException ( "Errors.REG_EESCAPE" ) ; case ' ' : if ( lasttype ( ' ' ) || next1 ( ' ' ) ) { return retv ( Compiler . PLAIN , c ) ; } else { return retv ( Compiler . RANGE , c ) ; } case ' ' : if ( ateos ( ) ) { throw new RegexException ( "Errors.REG_EBRACK" ) ; } switch ( charAtNowAdvance ( ) ) { case ' ' : intocon ( L_CEL ) ; /* might or might not be locale-specific */ return ret ( Compiler . COLLEL ) ; case ' ' : intocon ( L_ECL ) ; note ( Flags . REG_ULOCALE ) ; return ret ( Compiler . ECLASS ) ; case ' ' : intocon ( L_CCL ) ; note ( Flags . REG_ULOCALE ) ; return ret ( Compiler . CCLASS ) ; default : /* oops */ v . now -- ; return retv ( Compiler . PLAIN , c ) ; } default : return retv ( Compiler . PLAIN , c ) ; } case L_CEL : /* collating elements are easy */ if ( c == ' ' && next1 ( ' ' ) ) { v . now ++ ; intocon ( L_BRACK ) ; return retv ( Compiler . END , ' ' ) ; } else { return retv ( Compiler . PLAIN , c ) ; } case L_ECL : /* ditto equivalence classes */ if ( c == ' ' && next1 ( ' ' ) ) { v . now ++ ; intocon ( L_BRACK ) ; return retv ( Compiler . END , ' ' ) ; } else { return retv ( Compiler . PLAIN , c ) ; } case L_CCL : /* ditto character classes */ if ( c == ' ' && next1 ( ' ' ) ) { v . now ++ ; intocon ( L_BRACK ) ; return retv ( Compiler . END , ' ' ) ; } else { return retv ( Compiler . PLAIN , c ) ; } default : assert false ; break ; } /* that got rid of everything except EREs and AREs */ assert incon ( L_ERE ) ; /* deal with EREs and AREs, except for backslashes */ switch ( c ) { case ' ' : return ret ( ' ' ) ; case ' ' : if ( 0 != ( v . cflags & Flags . REG_ADVF ) && next1 ( ' ' ) ) { v . now ++ ; note ( Flags . REG_UNONPOSIX ) ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; case ' ' : if ( 0 != ( v . cflags & Flags . REG_ADVF ) && next1 ( ' ' ) ) { v . now ++ ; note ( Flags . REG_UNONPOSIX ) ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; case ' ' : if ( 0 != ( v . cflags & Flags . REG_ADVF ) && next1 ( ' ' ) ) { v . now ++ ; note ( Flags . REG_UNONPOSIX ) ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; case ' ' : /* bounds start or plain character */ if ( 0 != ( v . cflags & Flags . REG_EXPANDED ) ) { skip ( ) ; } if ( ateos ( ) || ! iscdigit ( charAtNow ( ) ) ) { note ( Flags . REG_UBRACES ) ; note ( Flags . REG_UUNSPEC ) ; return retv ( Compiler . PLAIN , c ) ; } else { note ( Flags . REG_UBOUNDS ) ; intocon ( L_EBND ) ; return ret ( ' ' ) ; } case ' ' : /* parenthesis, or advanced extension */ if ( 0 != ( v . cflags & Flags . REG_ADVF ) && next1 ( ' ' ) ) { note ( Flags . REG_UNONPOSIX ) ; v . now ++ ; char flagChar = charAtNowAdvance ( ) ; switch ( flagChar ) { case ' ' : /* non-capturing paren */ return retv ( ' ' , 0 ) ; case ' ' : /* comment */ while ( ! ateos ( ) && charAtNow ( ) != ' ' ) { v . now ++ ; } if ( ! ateos ( ) ) { v . now ++ ; } assert v . nexttype == v . lasttype ; return next ( ) ; case ' ' : /* positive lookahead */ note ( Flags . REG_ULOOKAHEAD ) ; return retv ( Compiler . LACON , 1 ) ; case ' ' : /* negative lookahead */ note ( Flags . REG_ULOOKAHEAD ) ; return retv ( Compiler . LACON , 0 ) ; default : throw new RegexException ( String . format ( "Invalid flag after '(?': %c" , flagChar ) ) ; } } if ( 0 != ( v . cflags & Flags . REG_NOSUB ) || 0 != ( v . cflags & Flags . REG_NOCAPT ) ) { return retv ( ' ' , 0 ) ; /* all parens non-capturing */ } else { return retv ( ' ' , 1 ) ; } case ' ' : if ( lasttype ( ' ' ) ) { note ( Flags . REG_UUNSPEC ) ; } return retv ( ' ' , c ) ; case ' ' : /* easy except for [[:<:]] and [[:>:]] */ if ( have ( 6 ) && charAtNow ( ) == ' ' && charAtNowPlus ( 1 ) == ' ' && ( charAtNowPlus ( 2 ) == ' ' || charAtNowPlus ( 2 ) == ' ' ) && charAtNowPlus ( 3 ) == ' ' && charAtNowPlus ( 4 ) == ' ' && charAtNowPlus ( 5 ) == ' ' ) { c = charAtNowPlus ( 2 ) ; v . now += 6 ; note ( Flags . REG_UNONPOSIX ) ; return ret ( ( c == ' ' ) ? ' ' : ' ' ) ; } intocon ( L_BRACK ) ; if ( next1 ( ' ' ) ) { v . now ++ ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; case ' ' : return ret ( ' ' ) ; case ' ' : return ret ( ' ' ) ; case ' ' : return ret ( ' ' ) ; case ' ' : /* mostly punt backslashes to code below */ if ( ateos ( ) ) { throw new RegexException ( "REG_EESCAPE" ) ; } break ; default : /* ordinary character */ return retv ( Compiler . PLAIN , c ) ; } /* ERE/ARE backslash handling; backslash already eaten */ assert ! ateos ( ) ; if ( 0 == ( v . cflags & Flags . REG_ADVF ) ) { /* only AREs have non-trivial escapes */ if ( iscalnum ( charAtNow ( ) ) ) { note ( Flags . REG_UBSALNUM ) ; note ( Flags . REG_UUNSPEC ) ; } return retv ( Compiler . PLAIN , charAtNowAdvance ( ) ) ; } lexescape ( ) ; if ( v . nexttype == Compiler . CCLASS ) { /* fudge at lexical level */ switch ( v . nextvalue ) { case ' ' : lexnest ( backd ) ; break ; case ' ' : lexnest ( backD ) ; break ; case ' ' : lexnest ( backs ) ; break ; case ' ' : lexnest ( backS ) ; break ; case ' ' : lexnest ( backw ) ; break ; case ' ' : lexnest ( backW ) ; break ; default : throw new RuntimeException ( "Invalid escape " + Character . toString ( ( char ) v . nextvalue ) ) ; } /* lexnest done, back up and try again */ v . nexttype = v . lasttype ; return next ( ) ; } /* otherwise, lexescape has already done the work */ return true ; }


Input: brenext - get next BRE token This is much like EREs except for all the stupid backslashes and the [CODESPLIT] boolean brenext ( char pc ) throws RegexException { char c = pc ; switch ( c ) { case ' ' : if ( lasttype ( Compiler . EMPTY ) || lasttype ( ' ' ) || lasttype ( ' ' ) ) { return retv ( Compiler . PLAIN , c ) ; } return ret ( ' ' ) ; case ' ' : //CHECKSTYLE:OFF if ( have ( 6 ) && charAtNow ( ) == ' ' && charAtNowPlus ( 1 ) == ' ' && ( charAtNowPlus ( 2 ) == ' ' || charAtNowPlus ( 2 ) == ' ' ) && charAtNowPlus ( 3 ) == ' ' && charAtNowPlus ( 4 ) == ' ' && charAtNowPlus ( 5 ) == ' ' ) { c = charAtNowPlus ( 2 ) ; v . now += 6 ; note ( Flags . REG_UNONPOSIX ) ; return ret ( ( c == ' ' ) ? ' ' : ' ' ) ; //CHECKSTYLE:ON } intocon ( L_BRACK ) ; if ( next1 ( ' ' ) ) { v . now ++ ; return retv ( ' ' , 0 ) ; } return retv ( ' ' , 1 ) ; case ' ' : return ret ( ' ' ) ; case ' ' : if ( lasttype ( Compiler . EMPTY ) ) { return ret ( ' ' ) ; } if ( lasttype ( ' ' ) ) { note ( Flags . REG_UUNSPEC ) ; return ret ( ' ' ) ; } return retv ( Compiler . PLAIN , c ) ; case ' ' : if ( 0 != ( v . cflags & Flags . REG_EXPANDED ) ) { skip ( ) ; } if ( ateos ( ) ) { return ret ( ' ' ) ; } if ( next2 ( ' ' , ' ' ) ) { note ( Flags . REG_UUNSPEC ) ; return ret ( ' ' ) ; } return retv ( Compiler . PLAIN , c ) ; case ' ' : break ; /* see below */ default : return retv ( Compiler . PLAIN , c ) ; } assert c == ' ' ; if ( ateos ( ) ) { throw new RegexException ( "REG_EESCAPE" ) ; } c = charAtNowAdvance ( ) ; switch ( c ) { case ' ' : intocon ( L_BBND ) ; note ( Flags . REG_UBOUNDS ) ; return ret ( ' ' ) ; case ' ' : return retv ( ' ' , 1 ) ; case ' ' : return retv ( ' ' , c ) ; case ' ' : note ( Flags . REG_UNONPOSIX ) ; return ret ( ' ' ) ; case ' ' : note ( Flags . REG_UNONPOSIX ) ; return ret ( ' ' ) ; case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : note ( Flags . REG_UBACKREF ) ; return retv ( Compiler . BACKREF , digitval ( c ) ) ; default : if ( iscalnum ( c ) ) { note ( Flags . REG_UBSALNUM ) ; note ( Flags . REG_UUNSPEC ) ; } return retv ( Compiler . PLAIN , c ) ; } }


Input: CHECKSTYLE : OFF [CODESPLIT] boolean lexescape ( ) throws RegexException { int c ; int save ; assert 0 != ( v . cflags & Flags . REG_ADVF ) ; assert ! ateos ( ) ; c = charAtNowAdvance ( ) ; if ( ! iscalnum ( ( char ) c ) ) { return retv ( Compiler . PLAIN , c ) ; } note ( Flags . REG_UNONPOSIX ) ; switch ( c ) { case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : return retv ( Compiler . SBEGIN , 0 ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : if ( ateos ( ) ) { throw new RegexException ( "Incomplete \\c escape." ) ; } return retv ( Compiler . PLAIN , ( char ) ( charAtNowAdvance ( ) & 037 ) ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : return ret ( ' ' ) ; case ' ' : return ret ( ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : c = lexdigits ( 16 , 4 , 4 ) ; return retv ( Compiler . PLAIN , c ) ; case ' ' : c = lexdigits ( 16 , 8 , 8 ) ; // This escape is for UTF-32 characters. There are, ahem, certain requirements. if ( c > Character . MAX_CODE_POINT ) { throw new RegexException ( "Invalid UTF-32 escape." ) ; } return retv ( Compiler . PLAIN , c ) ; case ' ' : return retv ( Compiler . PLAIN , ' ' ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . CCLASS , ' ' ) ; case ' ' : c = lexdigits ( 16 , 1 , 255 ) ; /* REs >255 long outside spec */ return retv ( Compiler . PLAIN , c ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . WBDRY , 0 ) ; case ' ' : note ( Flags . REG_ULOCALE ) ; return retv ( Compiler . NWBDRY , 0 ) ; case ' ' : return retv ( Compiler . SEND , 0 ) ; case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : save = v . now ; v . now -- ; /* put first digit back */ c = lexdigits ( 10 , 1 , 255 ) ; /* REs >255 long outside spec */ /* ugly heuristic (first test is "exactly 1 digit?") */ if ( v . now - save == 0 || c <= v . getSubs ( ) . size ( ) ) { note ( Flags . REG_UBACKREF ) ; return retv ( Compiler . BACKREF , ( char ) c ) ; } /* oops, doesn't look like it's a backref after all... */ v . now = save ; /* and fall through into octal number */ case ' ' : v . now -- ; /* put first digit back */ c = lexdigits ( 8 , 1 , 3 ) ; return retv ( Compiler . PLAIN , c ) ; default : throw new RegexException ( "Invalid escape" ) ; // unknown escape. } }


Input: / * chr value ; errors signalled via ERR [CODESPLIT] private int lexdigits ( int base , int minlen , int maxlen ) throws RegexException { int n ; /* unsigned to avoid overflow misbehavior */ int len ; int c ; int d ; final char ub = ( char ) base ; n = 0 ; for ( len = 0 ; len < maxlen && ! ateos ( ) ; len ++ ) { c = charAtNowAdvance ( ) ; switch ( c ) { case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : d = digitval ( ( char ) c ) ; break ; case ' ' : case ' ' : d = 10 ; break ; case ' ' : case ' ' : d = 11 ; break ; case ' ' : case ' ' : d = 12 ; break ; case ' ' : case ' ' : d = 13 ; break ; case ' ' : case ' ' : d = 14 ; break ; case ' ' : case ' ' : d = 15 ; break ; default : v . now -- ; /* oops, not a digit at all */ d = - 1 ; break ; } if ( d >= base ) { /* not a plausible digit */ v . now -- ; d = - 1 ; } if ( d < 0 ) { break ; /* NOTE BREAK OUT */ } n = n * ub + d ; } if ( len < minlen ) { throw new RegexException ( "Not enough digits." ) ; } return n ; }


Input: Retrieve the color for a full codepoint . [CODESPLIT] short getcolor ( int codepoint ) { try { return fullMap . get ( codepoint ) ; } catch ( NullPointerException npe ) { throw new RuntimeException ( String . format ( " CP %08x no mapping" , codepoint ) ) ; } }


Input: Called at the start of a match . arguably we could just construct a new DFA each time . [CODESPLIT] StateSet initialize ( int start ) { // Discard state sets; reuse would be faster if we kept them, // but then we'd need the real cache. stateSets . clear ( ) ; StateSet stateSet = new StateSet ( nstates , ncolors ) ; stateSet . states . set ( cnfa . pre ) ; stateSet . noprogress = true ; // Insert into hash table based on that one state. stateSets . put ( stateSet . states , stateSet ) ; stateSet . setLastSeen ( start ) ; return stateSet ; }


Input: miss -- the state set was not found in the stateSets . [CODESPLIT] StateSet miss ( StateSet css , short co , int cp ) { if ( css . outs [ co ] != null ) { return css . outs [ co ] ; } /* first, what set of states would we end up in? */ BitSet work = new BitSet ( nstates ) ; boolean ispost = false ; boolean noprogress = true ; boolean gotstate = false ; for ( int i = 0 ; i < nstates ; i ++ ) { if ( css . states . get ( i ) ) { long ca ; int ax ; short caco ; int catarget ; for ( ax = cnfa . states [ i ] + 1 , ca = cnfa . arcs [ ax ] , caco = Cnfa . carcColor ( ca ) , catarget = Cnfa . carcTarget ( ca ) ; caco != Constants . COLORLESS ; ax ++ , ca = cnfa . arcs [ ax ] , caco = Cnfa . carcColor ( ca ) , catarget = Cnfa . carcTarget ( ca ) ) { if ( caco == co ) { work . set ( catarget ) ; gotstate = true ; if ( catarget == cnfa . post ) { ispost = true ; } // get target state, index arcs, get color, compare to 0. if ( 0 == Cnfa . carcColor ( cnfa . arcs [ cnfa . states [ catarget ] ] ) ) { noprogress = false ; } } } } } boolean dolacons = gotstate && cnfa . hasLacons ; boolean sawlacons = false ; while ( dolacons ) { /* transitive closure */ dolacons = false ; for ( int i = 0 ; i < nstates ; i ++ ) { if ( work . get ( i ) ) { long ca ; int ax ; short caco ; int catarget ; for ( ax = cnfa . states [ i ] + 1 , ca = cnfa . arcs [ ax ] , caco = Cnfa . carcColor ( ca ) , catarget = Cnfa . carcTarget ( ca ) ; caco != Constants . COLORLESS ; ax ++ , ca = cnfa . arcs [ ax ] , caco = Cnfa . carcColor ( ca ) , catarget = Cnfa . carcTarget ( ca ) ) { if ( caco <= ncolors ) { continue ; /* NOTE CONTINUE */ } sawlacons = true ; if ( work . get ( catarget ) ) { continue ; /* NOTE CONTINUE */ } if ( ! lacon ( cp , caco ) ) { continue ; /* NOTE CONTINUE */ } work . set ( catarget ) ; dolacons = true ; if ( catarget == cnfa . post ) { ispost = true ; } if ( 0 == Cnfa . carcColor ( cnfa . arcs [ cnfa . states [ catarget ] ] ) ) { noprogress = false ; } } } } } if ( ! gotstate ) { return null ; } StateSet stateSet = stateSets . get ( work ) ; if ( stateSet == null ) { stateSet = new StateSet ( work , ncolors ) ; stateSet . ins = new Arcp ( null , Constants . WHITE ) ; stateSet . poststate = ispost ; stateSet . noprogress |= noprogress ; /* lastseen to be dealt with by caller */ stateSets . put ( work , stateSet ) ; } if ( ! sawlacons ) { css . outs [ co ] = stateSet ; css . inchain [ co ] = stateSet . ins ; stateSet . ins = new Arcp ( css , co ) ; } return stateSet ; }


Input:
longest - longest - preferred matching engine [CODESPLIT] int longest ( int start , int stop , boolean [ ] hitstop ) { int cp ; int realstop = ( stop == runtime . dataLength ) ? stop : stop + 1 ; short co ; StateSet css ; int post ; /* initialize */ css = initialize ( start ) ; cp = start ; if ( hitstop != null ) { hitstop [ 0 ] = false ; } /* startup */ if ( cp == 0 ) { co = cnfa . bos [ 0 != ( runtime . eflags & Flags . REG_NOTBOL ) ? 0 : 1 ] ; } else { char theChar = runtime . data . charAt ( cp - 1 ) ; if ( Character . isLowSurrogate ( theChar ) ) { // collect the other end of the surrogate. theChar = runtime . data . charAt ( cp - 2 ) ; char high = theChar ; int codepoint = Character . toCodePoint ( high , theChar ) ; co = cm . getcolor ( codepoint ) ; // and get a color for the pair. } else { co = cm . getcolor ( theChar ) ; } } css = miss ( css , co , cp ) ; if ( css == null ) { return - 1 ; } css . setLastSeen ( cp ) ; StateSet ss ; /* main loop */ while ( cp < realstop ) { char theChar = runtime . data . charAt ( cp ) ; int increment = 1 ; if ( Character . isHighSurrogate ( theChar ) ) { int codepoint = Character . toCodePoint ( theChar , runtime . data . charAt ( cp + 1 ) ) ; co = cm . getcolor ( codepoint ) ; increment = 2 ; } else { co = cm . getcolor ( theChar ) ; } ss = css . outs [ co ] ; if ( ss == null ) { ss = miss ( css , co , cp + increment ) ; if ( ss == null ) { break ; /* NOTE BREAK OUT */ } } cp = cp + increment ; ss . setLastSeen ( cp ) ; css = ss ; } /* shutdown */ if ( cp == runtime . dataLength && stop == runtime . dataLength ) { if ( hitstop != null ) { hitstop [ 0 ] = true ; } co = cnfa . eos [ 0 != ( runtime . eflags & Flags . REG_NOTEOL ) ? 0 : 1 ] ; ss = miss ( css , co , cp ) ; /* special case:  match ended at eol? */ if ( ss != null && ss . poststate ) { return cp ; } else if ( ss != null ) { ss . setLastSeen ( cp ) ; /* to be tidy */ } } /* find last match, if any */ post = - 1 ; for ( StateSet thisSS : stateSets . values ( ) ) { //.object2ObjectEntrySet()) { if ( thisSS . poststate && post != thisSS . getLastSeen ( ) && ( post == - 1 || post < thisSS . getLastSeen ( ) ) ) { post = thisSS . getLastSeen ( ) ; } } if ( post != - 1 ) { /* found one */ /* Post points after the codepoint after the last one in the match (!) */ /* So, if that is an SMP codepoint, we need to back up 2 to get to the beginning of it,
             * and thus be just after the last character of the match. */ char postChar = runtime . data . charAt ( post - 1 ) ; if ( Character . isLowSurrogate ( postChar ) ) { return post - 2 ; } else { return post - 1 ; } } return - 1 ; }


Input: lastcold - determine last point at which no progress had been made [CODESPLIT] int lastcold ( ) { int nopr = 0 ; for ( StateSet ss : stateSets . values ( ) ) { if ( ss . noprogress && nopr < ss . getLastSeen ( ) ) { nopr = ss . getLastSeen ( ) ; } } return nopr ; }


Input: eclass - Because we have no MCCE support this just processing single characters . [CODESPLIT] static UnicodeSet eclass ( char c , boolean cases ) { /* otherwise, none */ if ( cases ) { return allcases ( c ) ; } else { UnicodeSet set = new UnicodeSet ( ) ; set . add ( c ) ; return set ; } }


Input: allcases - supply cvec for all case counterparts of a chr ( including itself ) This is a shortcut preferably an efficient one for simple characters ; messy cases are done via range () . [CODESPLIT] static UnicodeSet allcases ( int c ) { UnicodeSet set = new UnicodeSet ( ) ; set . add ( c ) ; set . closeOver ( UnicodeSet . ADD_CASE_MAPPINGS ) ; return set ; }


Input: Return a UnicodeSet for a character class name . It appears that the names that TCL accepts are also acceptable to ICU . [CODESPLIT] public static UnicodeSet cclass ( String cclassName , boolean casefold ) throws RegexException { try { if ( casefold ) { return KNOWN_SETS_CI . get ( cclassName ) ; } else { return KNOWN_SETS_CS . get ( cclassName ) ; } } catch ( ExecutionException e ) { Throwables . propagateIfInstanceOf ( e . getCause ( ) , RegexException . class ) ; throw new RegexRuntimeException ( e . getCause ( ) ) ; } }


Input: carcsort - sort compacted - NFA arcs by color Really dumb algorithm but if the list is long enough for that to matter you re in real trouble anyway . [CODESPLIT] void carcsort ( int first , int last ) { int p ; int q ; long tmp ; if ( last - first <= 1 ) { return ; } for ( p = first ; p <= last ; p ++ ) { for ( q = p ; q <= last ; q ++ ) { short pco = Cnfa . carcColor ( arcs [ p ] ) ; short qco = Cnfa . carcColor ( arcs [ q ] ) ; int pto = Cnfa . carcTarget ( arcs [ p ] ) ; int qto = Cnfa . carcTarget ( arcs [ q ] ) ; if ( pco > qco || ( pco == qco && pto > qto ) ) { assert p != q ; tmp = arcs [ p ] ; arcs [ p ] = arcs [ q ] ; arcs [ q ] = tmp ; } } } }


Input: dumpst - dump a subRE tree [CODESPLIT] String dumpst ( boolean nfapresent ) { StringBuilder sb = new StringBuilder ( ) ; sb . append ( String . format ( "%s. `%c'" , shortId ( ) , op ) ) ; if ( 0 != ( flags & LONGER ) ) { sb . append ( " longest" ) ; } if ( 0 != ( flags & SHORTER ) ) { sb . append ( " shortest" ) ; } if ( 0 != ( flags & MIXED ) ) { sb . append ( " hasmixed" ) ; } if ( 0 != ( flags & CAP ) ) { sb . append ( " hascapture" ) ; } if ( 0 != ( flags & BACKR ) ) { sb . append ( " hasbackref" ) ; } if ( 0 == ( flags & INUSE ) ) { sb . append ( " UNUSED" ) ; } if ( subno != 0 ) { sb . append ( String . format ( " (#%d)" , subno ) ) ; } if ( min != 1 || max != 1 ) { sb . append ( String . format ( " {%d," , min ) ) ; if ( max != Compiler . INFINITY ) { sb . append ( String . format ( "%d" , max ) ) ; } sb . append ( "}" ) ; } if ( nfapresent ) { sb . append ( String . format ( " %d-%d" , begin . no , end . no ) ) ; } if ( left != null ) { sb . append ( String . format ( " L:%s" , left . toString ( ) ) ) ; } if ( right != null ) { sb . append ( String . format ( " R:%s" , right . toString ( ) ) ) ; } sb . append ( "\n" ) ; if ( left != null ) { left . dumpst ( nfapresent ) ; } if ( right != null ) { right . dumpst ( nfapresent ) ; } return sb . toString ( ) ; }


Input: / * Called by all the resetting functions . Allows find to work as specified . [CODESPLIT] private void resetState ( ) { // if there are any matches sitting in the runtime, eliminate. if ( runtime != null && runtime . match != null ) { runtime . match . clear ( ) ; } nextFindOffset = regionStart ; }


Input: Factory method for new states . [CODESPLIT] State newstate ( int flag ) { State newState = new State ( ) ; newState . no = nstates ++ ; // a unique number. if ( states == null ) { states = newState ; } if ( slast != null ) { assert slast . next == null ; slast . next = newState ; } newState . prev = slast ; slast = newState ; newState . flag = flag ; return newState ; }


Input: moveouts - move all out arcs of a state to another state [CODESPLIT] void moveouts ( State old , State newState ) { Arc a ; assert old != newState ; while ( ( a = old . outs ) != null ) { cparc ( a , newState , a . to ) ; freearc ( a ) ; } }


Input: moveins - move all in arcs of a state to another state You might think this could be done better by just updating the existing arcs and you would be right if it weren t for the desire for duplicate suppression which makes it easier to just make new ones to exploit the suppression built into newarc . [CODESPLIT] void moveins ( State old , State newState ) { Arc a ; assert old != newState ; while ( ( a = old . ins ) != null ) { cparc ( a , a . from , newState ) ; freearc ( a ) ; } assert old . nins == 0 ; assert old . ins == null ; }


Input: copyins - copy all in arcs of a state to another state [CODESPLIT] void copyins ( State old , State newState ) { Arc a ; assert old != newState ; for ( a = old . ins ; a != null ; a = a . inchain ) { cparc ( a , a . from , newState ) ; } }


Input: copyouts - copy all out arcs of a state to another state [CODESPLIT] void copyouts ( State old , State newState ) { Arc a ; assert old != newState ; for ( a = old . outs ; a != null ; a = a . outchain ) { cparc ( a , newState , a . to ) ; } }


Input: get rid of a state releasing all its arcs . I m not sure that all this is needed as opposed to depending on the GC . [CODESPLIT] void dropstate ( State s ) { Arc a ; while ( ( a = s . ins ) != null ) { freearc ( a ) ; } while ( ( a = s . outs ) != null ) { freearc ( a ) ; } freestate ( s ) ; }


Input: Unwire a state from the NFA . [CODESPLIT] void freestate ( State s ) { assert s != null ; assert s . nins == 0 ; assert s . nouts == 0 ; if ( s . next != null ) { s . next . prev = s . prev ; } else { assert s == slast ; slast = s . prev ; } if ( s . prev != null ) { s . prev . next = s . next ; } else { assert s == states ; states = s . next ; } }


Input: cparc - allocate a new arc within an NFA copying details from old one [CODESPLIT] void cparc ( Arc oa , State from , State to ) { newarc ( oa . type , oa . co , from , to ) ; }


Input: dupnfa - duplicate sub - NFA Another recursive traversal this time using tmp to point to duplicates as well as mark already - seen states . ( You knew there was a reason why it s a state pointer didn t you? : - )) [CODESPLIT] void dupnfa ( State start , State stop , State from , State to ) { if ( start == stop ) { newarc ( Compiler . EMPTY , ( short ) 0 , from , to ) ; return ; } stop . tmp = to ; duptraverse ( start , from ) ; /* done, except for clearing out the tmp pointers */ stop . tmp = null ; cleartraverse ( start ) ; }


Input: duptraverse - recursive heart of dupnfa [CODESPLIT] void duptraverse ( State s , State stmp ) { Arc a ; if ( s . tmp != null ) { return ; /* already done */ } s . tmp = ( stmp == null ) ? newstate ( ) : stmp ; if ( s . tmp == null ) { return ; } for ( a = s . outs ; a != null ; a = a . outchain ) { duptraverse ( a . to , null ) ; assert a . to . tmp != null ; cparc ( a , s . tmp , a . to . tmp ) ; } }


Input: / * - cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set [CODESPLIT] void cleartraverse ( State s ) { Arc a ; if ( s . tmp == null ) { return ; } s . tmp = null ; for ( a = s . outs ; a != null ; a = a . outchain ) { cleartraverse ( a . to ) ; } }


Input: specialcolors - fill in special colors for an NFA [CODESPLIT] void specialcolors ( ) { /* false colors for BOS, BOL, EOS, EOL */ if ( parent == null ) { bos [ 0 ] = cm . pseudocolor ( ) ; bos [ 1 ] = cm . pseudocolor ( ) ; eos [ 0 ] = cm . pseudocolor ( ) ; eos [ 1 ] = cm . pseudocolor ( ) ; } else { assert parent . bos [ 0 ] != Constants . COLORLESS ; bos [ 0 ] = parent . bos [ 0 ] ; assert parent . bos [ 1 ] != Constants . COLORLESS ; bos [ 1 ] = parent . bos [ 1 ] ; assert parent . eos [ 0 ] != Constants . COLORLESS ; eos [ 0 ] = parent . eos [ 0 ] ; assert parent . eos [ 1 ] != Constants . COLORLESS ; eos [ 1 ] = parent . eos [ 1 ] ; } }


Input: dumpnfa - dump an NFA in human - readable form [CODESPLIT] void dumpnfa ( ) { if ( ! LOG . isDebugEnabled ( ) || ! IS_DEBUG ) { return ; } LOG . debug ( "dump nfa" ) ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( String . format ( "pre %d, post %d init %d final %d" , pre . no , post . no , init . no , finalState . no ) ) ; if ( bos [ 0 ] != Constants . COLORLESS ) { sb . append ( String . format ( ", bos [%d]" , bos [ 0 ] ) ) ; } if ( bos [ 1 ] != Constants . COLORLESS ) { sb . append ( String . format ( ", bol [%d]" , bos [ 1 ] ) ) ; } if ( eos [ 0 ] != Constants . COLORLESS ) { sb . append ( String . format ( ", eos [%d]" , eos [ 0 ] ) ) ; } if ( eos [ 1 ] != Constants . COLORLESS ) { sb . append ( String . format ( ", eol [%d]" , eos [ 1 ] ) ) ; } LOG . debug ( sb . toString ( ) ) ; for ( State s = states ; s != null ; s = s . next ) { dumpstate ( s ) ; } if ( parent == null ) { cm . dumpcolors ( ) ; } }


Input: dumpstate - dump an NFA state in human - readable form [CODESPLIT] void dumpstate ( State s ) { Arc a ; if ( ! LOG . isDebugEnabled ( ) || ! IS_DEBUG ) { return ; } StringBuilder sb = new StringBuilder ( ) ; sb . append ( String . format ( "State %d%s%c" , s . no , ( s . tmp != null ) ? "T" : "" , ( s . flag != 0 ) ? ( char ) s . flag : ' ' ) ) ; if ( s . prev != null && s . prev . next != s ) { sb . append ( String . format ( "\tstate chain bad" ) ) ; } if ( s . nouts == 0 ) { sb . append ( "\tno out arcs" ) ; } else { dumparcs ( s , sb ) ; } LOG . debug ( sb . toString ( ) ) ; for ( a = s . ins ; a != null ; a = a . inchain ) { if ( a . to != s ) { LOG . debug ( String . format ( "\tlink from %d to %d on %d's in-chain" , a . from . no , a . to . no , s . no ) ) ; } } }


Input: dumparcs - dump out - arcs in human - readable form [CODESPLIT] void dumparcs ( State s , StringBuilder sb ) { int pos ; assert s . nouts > 0 ; /* printing arcs in reverse order is usually clearer */ pos = dumprarcs ( s . outs , s , 1 , sb ) ; if ( pos != 1 ) { //sb.append("\n"); } }


Input: dumprarcs - dump remaining outarcs recursively in reverse order [CODESPLIT] int dumprarcs ( Arc a , State s , int pos , StringBuilder sb ) { if ( a . outchain != null ) { pos = dumprarcs ( a . outchain , s , pos , sb ) ; } dumparc ( a , s , sb ) ; if ( pos == 5 ) { sb . append ( "\n" ) ; pos = 1 ; } else { pos ++ ; } return pos ; }


Input: dumparc - dump one outarc in readable form including prefixing tab [CODESPLIT] void dumparc ( Arc a , State s , StringBuilder sb ) { sb . append ( "\t" ) ; switch ( a . type ) { case Compiler . PLAIN : sb . append ( String . format ( "[%d]" , a . co ) ) ; break ; case Compiler . AHEAD : sb . append ( String . format ( ">%d>" , a . co ) ) ; break ; case Compiler . BEHIND : sb . append ( String . format ( "<%d<" , a . co ) ) ; break ; case Compiler . LACON : sb . append ( String . format ( ":%d:" , a . co ) ) ; break ; case ' ' : case ' ' : sb . append ( String . format ( "%c%d" , ( char ) a . type , a . co ) ) ; break ; case Compiler . EMPTY : break ; default : sb . append ( String . format ( "0x%x/0%d" , a . type , a . co ) ) ; break ; } if ( a . from != s ) { sb . append ( String . format ( "?%d?" , a . from . no ) ) ; } sb . append ( "->" ) ; if ( a . to == null ) { sb . append ( "null" ) ; Arc aa ; for ( aa = a . to . ins ; aa != null ; aa = aa . inchain ) { if ( aa == a ) { break ; /* NOTE BREAK OUT */ } } if ( aa == null ) { LOG . debug ( "?!?" ) ; /* missing from in-chain */ } } else { sb . append ( String . format ( "%d" , a . to . no ) ) ; } }


Input: optimize - optimize an NFA [CODESPLIT] long optimize ( ) throws RegexException { LOG . debug ( "initial cleanup" ) ; cleanup ( ) ; /* may simplify situation */ dumpnfa ( ) ; LOG . debug ( "empties" ) ; fixempties ( ) ; /* get rid of EMPTY arcs */ LOG . debug ( "constraints" ) ; pullback ( ) ; /* pull back constraints backward */ pushfwd ( ) ; /* push fwd constraints forward */ LOG . debug ( "final cleanup" ) ; cleanup ( ) ; /* final tidying */ return analyze ( ) ; /* and analysis */ }


Input: analyze - ascertain potentially - useful facts about an optimized NFA [CODESPLIT] long analyze ( ) { Arc a ; Arc aa ; if ( pre . outs == null ) { return Flags . REG_UIMPOSSIBLE ; } for ( a = pre . outs ; a != null ; a = a . outchain ) { for ( aa = a . to . outs ; aa != null ; aa = aa . outchain ) { if ( aa . to == post ) { return Flags . REG_UEMPTYMATCH ; } } } return 0 ; }


Input: pullback - pull back constraints backward to ( with luck ) eliminate them [CODESPLIT] void pullback ( ) throws RegexException { State s ; State nexts ; Arc a ; Arc nexta ; boolean progress ; /* find and pull until there are no more */ do { progress = false ; for ( s = states ; s != null ; s = nexts ) { nexts = s . next ; for ( a = s . outs ; a != null ; a = nexta ) { nexta = a . outchain ; if ( a . type == ' ' || a . type == Compiler . BEHIND ) { if ( pull ( a ) ) { progress = true ; } } assert nexta == null || s . no != State . FREESTATE ; } } if ( progress ) { dumpnfa ( ) ; } } while ( progress ) ; for ( a = pre . outs ; a != null ; a = nexta ) { nexta = a . outchain ; if ( a . type == ' ' ) { assert a . co == 0 || a . co == 1 ; newarc ( Compiler . PLAIN , bos [ a . co ] , a . from , a . to ) ; freearc ( a ) ; } } }


Input: - pull - pull a back constraint backward past its source state A significant property of this function is that it deletes at most one state -- the constraint s from state -- and only if the constraint was that state s last outarc . [CODESPLIT] boolean pull ( Arc con ) throws RegexException { State from = con . from ; State to = con . to ; Arc a ; Arc nexta ; State s ; if ( from == to ) { /* circular constraint is pointless */ freearc ( con ) ; return true ; } if ( 0 != from . flag ) { /* can't pull back beyond start */ return false ; } if ( from . nins == 0 ) { /* unreachable */ freearc ( con ) ; return true ; } /* first, clone from state if necessary to avoid other outarcs */ if ( from . nouts > 1 ) { s = newstate ( ) ; assert to != from ; /* con is not an inarc */ copyins ( from , s ) ; /* duplicate inarcs */ cparc ( con , s , to ) ; /* move constraint arc */ freearc ( con ) ; from = s ; con = from . outs ; } assert from . nouts == 1 ; /* propagate the constraint into the from state's inarcs */ for ( a = from . ins ; a != null ; a = nexta ) { nexta = a . inchain ; switch ( combine ( con , a ) ) { case INCOMPATIBLE : /* destroy the arc */ freearc ( a ) ; break ; case SATISFIED : /* no action needed */ break ; case COMPATIBLE : /* swap the two arcs, more or less */ s = newstate ( ) ; cparc ( a , s , to ) ; /* anticipate move */ cparc ( con , a . from , s ) ; freearc ( a ) ; break ; default : throw new RegexException ( "REG_ASSERT" ) ; } } /* remaining inarcs, if any, incorporate the constraint */ moveins ( from , to ) ; dropstate ( from ) ; /* will free the constraint */ return true ; }


Input: pushfwd - push forward constraints forward to ( with luck ) eliminate them [CODESPLIT] void pushfwd ( ) throws RegexException { State s ; State nexts ; Arc a ; Arc nexta ; boolean progress ; /* find and push until there are no more */ do { progress = false ; for ( s = states ; s != null ; s = nexts ) { nexts = s . next ; for ( a = s . ins ; a != null ; a = nexta ) { nexta = a . inchain ; if ( a . type == ' ' || a . type == Compiler . AHEAD ) { if ( push ( a ) ) { progress = true ; } } assert nexta == null || s . no != State . FREESTATE ; } } if ( progress ) { dumpnfa ( ) ; } } while ( progress ) ; for ( a = post . ins ; a != null ; a = nexta ) { nexta = a . inchain ; if ( a . type == ' ' ) { assert a . co == 0 || a . co == 1 ; newarc ( Compiler . PLAIN , eos [ a . co ] , a . from , a . to ) ; freearc ( a ) ; } } }


Input: push - push a forward constraint forward past its destination state A significant property of this function is that it deletes at most one state -- the constraint s to state -- and only if the constraint was that state s last inarc . [CODESPLIT] boolean push ( Arc con ) throws RegexException { State from = con . from ; State to = con . to ; Arc a ; Arc nexta ; State s ; if ( to == from ) { /* circular constraint is pointless */ freearc ( con ) ; return true ; } if ( 0 != to . flag ) { /* can't push forward beyond end */ return false ; } if ( to . nouts == 0 ) { /* dead end */ freearc ( con ) ; return true ; } /* first, clone to state if necessary to avoid other inarcs */ if ( to . nins > 1 ) { s = newstate ( ) ; copyouts ( to , s ) ; /* duplicate outarcs */ cparc ( con , from , s ) ; /* move constraint */ freearc ( con ) ; to = s ; con = to . ins ; } assert to . nins == 1 ; /* propagate the constraint into the to state's outarcs */ for ( a = to . outs ; a != null ; a = nexta ) { nexta = a . outchain ; switch ( combine ( con , a ) ) { case INCOMPATIBLE : /* destroy the arc */ freearc ( a ) ; break ; case SATISFIED : /* no action needed */ break ; case COMPATIBLE : /* swap the two arcs, more or less */ s = newstate ( ) ; cparc ( con , s , a . to ) ; /* anticipate move */ cparc ( a , from , s ) ; freearc ( a ) ; break ; default : throw new RegexException ( "REG_ASSERT" ) ; } } /* remaining outarcs, if any, incorporate the constraint */ moveouts ( to , from ) ; dropstate ( to ) ; /* will free the constraint */ return true ; }


Input: combine - constraint lands on an arc what happens? [CODESPLIT] int combine ( Arc con , Arc a ) throws RegexException { //# define  CA(ct,at)   (((ct)<<CHAR_BIT) | (at)) //CA(con->type, a->type)) { switch ( ( con . type << 8 ) | a . type ) { case ' ' << 8 | Compiler . PLAIN : /* newlines are handled separately */ case ' ' << 8 | Compiler . PLAIN : return INCOMPATIBLE ; case Compiler . AHEAD << 8 | Compiler . PLAIN : /* color constraints meet colors */ case Compiler . BEHIND << 8 | Compiler . PLAIN : if ( con . co == a . co ) { return SATISFIED ; } return INCOMPATIBLE ; case ' ' << 8 | ' ' : /* collision, similar constraints */ case ' ' << 8 | ' ' : case Compiler . AHEAD << 8 | Compiler . AHEAD : case Compiler . BEHIND << 8 | Compiler . BEHIND : if ( con . co == a . co ) { /* true duplication */ return SATISFIED ; } return INCOMPATIBLE ; case ' ' << 8 | Compiler . BEHIND : /* collision, dissimilar constraints */ case Compiler . BEHIND << 8 | ' ' : case ' ' << 8 | Compiler . AHEAD : case Compiler . AHEAD << 8 | ' ' : return INCOMPATIBLE ; case ' ' << 8 | Compiler . AHEAD : case Compiler . BEHIND << 8 | ' ' : case Compiler . BEHIND << 8 | Compiler . AHEAD : case ' ' << 8 | ' ' : case ' ' << 8 | Compiler . BEHIND : case Compiler . AHEAD << 8 | ' ' : case Compiler . AHEAD << 8 | Compiler . BEHIND : case ' ' << 8 | Compiler . LACON : case Compiler . BEHIND << 8 | Compiler . LACON : case ' ' << 8 | Compiler . LACON : case Compiler . AHEAD << 8 | Compiler . LACON : return COMPATIBLE ; default : throw new RuntimeException ( "Impossible arc" ) ; } }


Input: cleanup - clean up NFA after optimizations [CODESPLIT] void cleanup ( ) { State s ; State nexts ; int n ; /* clear out unreachable or dead-end states */ /* use pre to mark reachable, then post to mark can-reach-post */ markreachable ( pre , null , pre ) ; markcanreach ( post , pre , post ) ; for ( s = states ; s != null ; s = nexts ) { nexts = s . next ; if ( s . tmp != post && 0 == s . flag ) { dropstate ( s ) ; } } assert post . nins == 0 || post . tmp == post ; cleartraverse ( pre ) ; assert post . nins == 0 || post . tmp == null ; /* the nins==0 (final unreachable) case will be caught later */ /* renumber surviving states */ n = 0 ; for ( s = states ; s != null ; s = s . next ) { s . no = n ++ ; } nstates = n ; }


Input: markreachable - recursive marking of reachable states [CODESPLIT] void markreachable ( State s , State okay , State mark ) { Arc a ; if ( s . tmp != okay ) { return ; } s . tmp = mark ; for ( a = s . outs ; a != null ; a = a . outchain ) { markreachable ( a . to , okay , mark ) ; } }


Input: markcanreach - recursive marking of states which can reach here [CODESPLIT] void markcanreach ( State s , State okay , State mark ) { Arc a ; if ( s . tmp != okay ) { return ; } s . tmp = mark ; for ( a = s . ins ; a != null ; a = a . inchain ) { markcanreach ( a . from , okay , mark ) ; } }


Input: fixempties - get rid of EMPTY arcs [CODESPLIT] void fixempties ( ) { State s ; State nexts ; Arc a ; Arc nexta ; boolean progress ; /* find and eliminate empties until there are no more */ do { progress = false ; for ( s = states ; s != null ; s = nexts ) { nexts = s . next ; for ( a = s . outs ; a != null ; a = nexta ) { nexta = a . outchain ; if ( a . type == Compiler . EMPTY && unempty ( a ) ) { progress = true ; } assert nexta == null || s . no != State . FREESTATE ; } } if ( progress ) { dumpnfa ( ) ; } } while ( progress ) ; }


Input: unempty - optimize out an EMPTY arc if possible Actually as it stands this function always succeeds but the return value is kept with an eye on possible future changes . [CODESPLIT] boolean unempty ( Arc a ) { State from = a . from ; State to = a . to ; boolean usefrom ; /* work on from, as opposed to to? */ assert a . type == Compiler . EMPTY ; assert from != pre && to != post ; if ( from == to ) { /* vacuous loop */ freearc ( a ) ; return true ; } /* decide which end to work on */ usefrom = true ; /* default:  attack from */ if ( from . nouts > to . nins ) { usefrom = false ; } else if ( from . nouts == to . nins ) { /* decide on secondary issue:  move/copy fewest arcs */ if ( from . nins > to . nouts ) { usefrom = false ; } } freearc ( a ) ; if ( usefrom ) { if ( from . nouts == 0 ) { /* was the state's only outarc */ moveins ( from , to ) ; freestate ( from ) ; } else { copyins ( from , to ) ; } } else { if ( to . nins == 0 ) { /* was the state's only inarc */ moveouts ( to , from ) ; freestate ( to ) ; } else { copyouts ( to , from ) ; } } return true ; }


Input: Reads the given rule parameters file . [CODESPLIT] private Map < String , String > getRuleParameters ( ) throws CliExecutionException { Map < String , String > ruleParameters ; if ( ruleParametersFile == null ) { ruleParameters = Collections . emptyMap ( ) ; } else { Properties properties = new Properties ( ) ; try { properties . load ( new FileInputStream ( ruleParametersFile ) ) ; } catch ( IOException e ) { throw new CliExecutionException ( "Cannot read rule parameters file '" + ruleParametersFile . getPath ( ) + "'." ) ; } ruleParameters = new TreeMap <> ( ) ; for ( String name : properties . stringPropertyNames ( ) ) { ruleParameters . put ( name , properties . getProperty ( name ) ) ; } } return ruleParameters ; }


Input: Get all configured rule interpreter plugins . [CODESPLIT] private Map < String , Collection < RuleInterpreterPlugin > > getRuleInterpreterPlugins ( ) throws CliExecutionException { try { return pluginRepository . getRuleInterpreterPluginRepository ( ) . getRuleInterpreterPlugins ( Collections . < String , Object > emptyMap ( ) ) ; } catch ( PluginRepositoryException e ) { throw new CliExecutionException ( "Cannot get report plugins." , e ) ; } }


Input: Get all configured report plugins . [CODESPLIT] private Map < String , ReportPlugin > getReportPlugins ( ReportContext reportContext ) throws CliExecutionException { ReportPluginRepository reportPluginRepository ; try { reportPluginRepository = pluginRepository . getReportPluginRepository ( ) ; return reportPluginRepository . getReportPlugins ( reportContext , pluginProperties ) ; } catch ( PluginRepositoryException e ) { throw new CliExecutionException ( "Cannot get report plugins." , e ) ; } }


Input: Return the selection of rules . [CODESPLIT] protected RuleSelection getRuleSelection ( RuleSet ruleSet ) { return RuleSelection . select ( ruleSet , groupIds , constraintIds , conceptIds ) ; }


Input: The main method . [CODESPLIT] public static void main ( String [ ] args ) { try { DefaultTaskFactoryImpl taskFactory = new DefaultTaskFactoryImpl ( ) ; new Main ( taskFactory ) . run ( args ) ; } catch ( CliExecutionException e ) { String message = getErrorMessage ( e ) ; LOGGER . error ( message ) ; System . exit ( e . getExitCode ( ) ) ; } }


Input: Run tasks according to the given arguments . [CODESPLIT] public void run ( String [ ] args ) throws CliExecutionException { Options options = gatherOptions ( taskFactory ) ; CommandLine commandLine = getCommandLine ( args , options ) ; interpretCommandLine ( commandLine , options , taskFactory ) ; }


Input: Extract an error message from the given exception and its causes . [CODESPLIT] private static String getErrorMessage ( CliExecutionException e ) { StringBuffer messageBuilder = new StringBuffer ( ) ; Throwable current = e ; do { messageBuilder . append ( "-> " ) ; messageBuilder . append ( current . getMessage ( ) ) ; current = current . getCause ( ) ; } while ( current != null ) ; return messageBuilder . toString ( ) ; }


Input: Gather all options which are supported by the task ( i . e . including standard and specific options ) . [CODESPLIT] private Options gatherOptions ( TaskFactory taskFactory ) { final Options options = new Options ( ) ; gatherTasksOptions ( taskFactory , options ) ; gatherStandardOptions ( options ) ; return options ; }


Input: Gathers the standard options shared by all tasks . [CODESPLIT] @ SuppressWarnings ( "static-access" ) private void gatherStandardOptions ( final Options options ) { options . addOption ( OptionBuilder . withArgName ( "p" ) . withDescription ( "Path to property file; default is jqassistant.properties in the class path" ) . withLongOpt ( "properties" ) . hasArg ( ) . create ( "p" ) ) ; options . addOption ( new Option ( "help" , "print this message" ) ) ; }


Input: Gathers the task specific options for all tasks . [CODESPLIT] private void gatherTasksOptions ( TaskFactory taskFactory , Options options ) { for ( Task task : taskFactory . getTasks ( ) ) { for ( Option option : task . getOptions ( ) ) { options . addOption ( option ) ; } } }


Input: Returns a string containing the names of all supported tasks . [CODESPLIT] private String gatherTaskNames ( TaskFactory taskFactory ) { final StringBuilder builder = new StringBuilder ( ) ; for ( String taskName : taskFactory . getTaskNames ( ) ) { builder . append ( "'" ) . append ( taskName ) . append ( "' " ) ; } return builder . toString ( ) . trim ( ) ; }


Input: Parse the command line and execute the requested task . [CODESPLIT] private void interpretCommandLine ( CommandLine commandLine , Options options , TaskFactory taskFactory ) throws CliExecutionException { if ( commandLine . hasOption ( OPTION_HELP ) ) { printUsage ( options , null ) ; System . exit ( 1 ) ; } List < String > taskNames = commandLine . getArgList ( ) ; if ( taskNames . isEmpty ( ) ) { printUsage ( options , "A task must be specified, i.e. one  of " + gatherTaskNames ( taskFactory ) ) ; System . exit ( 1 ) ; } List < Task > tasks = new ArrayList <> ( ) ; for ( String taskName : taskNames ) { Task task = taskFactory . fromName ( taskName ) ; if ( task == null ) { printUsage ( options , "Unknown task " + taskName ) ; } tasks . add ( task ) ; } Map < String , Object > properties = readProperties ( commandLine ) ; PluginRepository pluginRepository = getPluginRepository ( ) ; try { executeTasks ( tasks , options , commandLine , pluginRepository , properties ) ; } catch ( PluginRepositoryException e ) { throw new CliExecutionException ( "Unexpected plugin repository problem while executing tasks." , e ) ; } }


Input: Parse the command line [CODESPLIT] private CommandLine getCommandLine ( String [ ] args , Options options ) { final CommandLineParser parser = new BasicParser ( ) ; CommandLine commandLine = null ; try { commandLine = parser . parse ( options , args ) ; } catch ( ParseException e ) { printUsage ( options , e . getMessage ( ) ) ; System . exit ( 1 ) ; } return commandLine ; }


Input: Executes a task . [CODESPLIT] private void executeTask ( Task task , Options option , CommandLine commandLine , PluginRepository pluginRepository , Map < String , Object > properties ) throws CliExecutionException { try { task . withStandardOptions ( commandLine ) ; task . withOptions ( commandLine ) ; } catch ( CliConfigurationException e ) { printUsage ( option , e . getMessage ( ) ) ; System . exit ( 1 ) ; } task . initialize ( pluginRepository , properties ) ; task . run ( ) ; }


Input: Read the plugin properties file if specified on the command line or if it exists on the class path . [CODESPLIT] private Map < String , Object > readProperties ( CommandLine commandLine ) throws CliConfigurationException { final Properties properties = new Properties ( ) ; InputStream propertiesStream ; if ( commandLine . hasOption ( "p" ) ) { File propertyFile = new File ( commandLine . getOptionValue ( "p" ) ) ; if ( ! propertyFile . exists ( ) ) { throw new CliConfigurationException ( "Property file given by command line does not exist: " + propertyFile . getAbsolutePath ( ) ) ; } try { propertiesStream = new FileInputStream ( propertyFile ) ; } catch ( FileNotFoundException e ) { throw new CliConfigurationException ( "Cannot open property file." , e ) ; } } else { propertiesStream = Main . class . getResourceAsStream ( "/jqassistant.properties" ) ; } Map < String , Object > result = new HashMap <> ( ) ; if ( propertiesStream != null ) { try { properties . load ( propertiesStream ) ; } catch ( IOException e ) { throw new CliConfigurationException ( "Cannot load properties from file." , e ) ; } for ( String name : properties . stringPropertyNames ( ) ) { result . put ( name , properties . getProperty ( name ) ) ; } } return result ; }


Input: Print usage information . [CODESPLIT] private void printUsage ( final Options options , final String errorMessage ) { if ( errorMessage != null ) { System . out . println ( "Error: " + errorMessage ) ; } final HelpFormatter formatter = new HelpFormatter ( ) ; formatter . printHelp ( Main . class . getCanonicalName ( ) + " <task> [options]" , options ) ; System . out . println ( "Tasks are: " + gatherTaskNames ( taskFactory ) ) ; System . out . println ( "Example: " + Main . class . getCanonicalName ( ) + " scan -f java:classpath::target/classes java:classpath::target/test-classes" ) ; }


Input: Determine the JQASSISTANT_HOME directory . [CODESPLIT] private File getHomeDirectory ( ) { String dirName = System . getenv ( ENV_JQASSISTANT_HOME ) ; if ( dirName != null ) { File dir = new File ( dirName ) ; if ( dir . exists ( ) ) { LOGGER . debug ( "Using JQASSISTANT_HOME '" + dir . getAbsolutePath ( ) + "'." ) ; return dir ; } else { LOGGER . warn ( "JQASSISTANT_HOME '" + dir . getAbsolutePath ( ) + "' points to a non-existing directory." ) ; return null ; } } LOGGER . warn ( "JQASSISTANT_HOME is not set." ) ; return null ; }


Input: Create the class loader to be used for detecting and loading plugins . [CODESPLIT] private ClassLoader createPluginClassLoader ( ) throws CliExecutionException { ClassLoader parentClassLoader = Task . class . getClassLoader ( ) ; File homeDirectory = getHomeDirectory ( ) ; if ( homeDirectory != null ) { File pluginDirectory = new File ( homeDirectory , DIRECTORY_PLUGINS ) ; if ( pluginDirectory . exists ( ) ) { final List < URL > urls = new ArrayList <> ( ) ; final Path pluginDirectoryPath = pluginDirectory . toPath ( ) ; SimpleFileVisitor < Path > visitor = new SimpleFileVisitor < Path > ( ) { @ Override public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs ) throws IOException { if ( file . toFile ( ) . getName ( ) . endsWith ( ".jar" ) ) { urls . add ( file . toFile ( ) . toURI ( ) . toURL ( ) ) ; } return FileVisitResult . CONTINUE ; } } ; try { Files . walkFileTree ( pluginDirectoryPath , visitor ) ; } catch ( IOException e ) { throw new CliExecutionException ( "Cannot read plugin directory." , e ) ; } LOGGER . debug ( "Using plugin URLs: " + urls ) ; return new com . buschmais . jqassistant . commandline . PluginClassLoader ( urls , parentClassLoader ) ; } } return parentClassLoader ; }


Input: Parses the given list of option values into a map of resources and their associated ( optional ) scopes . [CODESPLIT] private Map < String , String > parseResources ( List < String > optionValues ) { Map < String , String > resources = new HashMap <> ( ) ; for ( String file : optionValues ) { String [ ] parts = file . split ( "::" ) ; String fileName ; String scopeName = null ; if ( parts . length == 2 ) { scopeName = parts [ 0 ] ; fileName = parts [ 1 ] ; } else { fileName = parts [ 0 ] ; } resources . put ( fileName , scopeName ) ; } return resources ; }


Input: Writes a geometry to GeoJSON . Note that any data stored in getUserData () of the geometries that is not on the top level GeometryCollection is lost in the process . [CODESPLIT] public String write ( Geometry geometry ) { try { JSONStringer b = new JSONStringer ( ) ; if ( geometry . getClass ( ) . equals ( GeometryCollection . class ) ) { writeFeatureCollection ( b , ( GeometryCollection ) geometry ) ; } else { writeFeature ( b , geometry ) ; } return b . toString ( ) ; } catch ( JSONException e ) { throw new GeoJsonException ( e ) ; } }


Input: / * The shell of a polygon in GeoJSON is defined in counterclockwise order in JTS it is the other way round [CODESPLIT] private static Polygon createReversed ( Polygon geometry ) { Polygon r = ( Polygon ) geometry . clone ( ) ; r . normalize ( ) ; return ( Polygon ) r . reverse ( ) ; }


Input: Identify which countries are guaranteed to contain the given bounding box fully . The given bounding box may wrap around the 180th longitude i . e minLongitude = 170 and maxLongitude = - 170 . [CODESPLIT] public Set < String > getContainingIds ( double minLongitude , double minLatitude , double maxLongitude , double maxLatitude ) { Set < String > ids = new HashSet <> ( ) ; forCellsIn ( minLongitude , minLatitude , maxLongitude , maxLatitude , cell -> { if ( ids . isEmpty ( ) ) { ids . addAll ( cell . getContainingIds ( ) ) ; } else { ids . retainAll ( cell . getContainingIds ( ) ) ; } } ) ; return ids ; }


Input: Identify which countries intersect with the given bounding box . The given bounding box may wrap around the 180th longitude i . e minLongitude = 170 and maxLongitude = - 170 . [CODESPLIT] public Set < String > getIntersectingIds ( double minLongitude , double minLatitude , double maxLongitude , double maxLatitude ) { Set < String > ids = new HashSet <> ( ) ; forCellsIn ( minLongitude , minLatitude , maxLongitude , maxLatitude , cell -> { ids . addAll ( cell . getAllIds ( ) ) ; } ) ; return ids ; }


Input: http : // geomalgorithms . com / a03 - _inclusion . html [CODESPLIT] private static boolean isPointInPolygon ( Point p , Point [ ] v ) { int wn = 0 ; for ( int j = 0 , i = v . length - 1 ; j < v . length ; i = j ++ ) { if ( v [ i ] . y <= p . y ) { if ( v [ j ] . y > p . y ) { if ( isLeft ( v [ i ] , v [ j ] , p ) > 0 ) ++ wn ; } } else { if ( v [ j ] . y <= p . y ) { if ( isLeft ( v [ i ] , v [ j ] , p ) < 0 ) -- wn ; } } } return wn != 0 ; }


Input: If there s no match returns the result with { [CODESPLIT] public RouteResult < T > route ( HttpMethod method , String uri ) { MethodlessRouter < T > router = routers . get ( method ) ; if ( router == null ) { router = anyMethodRouter ; } QueryStringDecoder decoder = new QueryStringDecoder ( uri ) ; String [ ] tokens = decodePathTokens ( uri ) ; RouteResult < T > ret = router . route ( uri , decoder . path ( ) , tokens ) ; if ( ret != null ) { return new RouteResult < T > ( uri , decoder . path ( ) , ret . pathParams ( ) , decoder . parameters ( ) , ret . target ( ) ) ; } if ( router != anyMethodRouter ) { ret = anyMethodRouter . route ( uri , decoder . path ( ) , tokens ) ; if ( ret != null ) { return new RouteResult < T > ( uri , decoder . path ( ) , ret . pathParams ( ) , decoder . parameters ( ) , ret . target ( ) ) ; } } if ( notFound != null ) { return new RouteResult < T > ( uri , decoder . path ( ) , Collections . < String , String > emptyMap ( ) , decoder . parameters ( ) , notFound ) ; } return null ; }


Input: Given a target and params this method tries to do the reverse routing and returns the URI . [CODESPLIT] public String uri ( HttpMethod method , T target , Object ... params ) { MethodlessRouter < T > router = ( method == null ) ? anyMethodRouter : routers . get ( method ) ; // Fallback to anyMethodRouter if no router is found for the method if ( router == null ) { router = anyMethodRouter ; } String ret = router . uri ( target , params ) ; if ( ret != null ) { return ret ; } // Fallback to anyMethodRouter if the router was not anyMethodRouter and no path is found return ( router != anyMethodRouter ) ? anyMethodRouter . uri ( target , params ) : null ; }


Input: -------------------------------------------------------------------------- [CODESPLIT] public Router < T > CONNECT_FIRST ( String path , T target ) { return addRouteFirst ( HttpMethod . CONNECT , path , target ) ; }


Input: -------------------------------------------------------------------------- [CODESPLIT] public Router < T > CONNECT_LAST ( String path , T target ) { return addRouteLast ( HttpMethod . CONNECT , path , target ) ; }


Input: This method does nothing if the path pattern has already been added . A path pattern can only point to one target . [CODESPLIT] public OrderlessRouter < T > addRoute ( String pathPattern , T target ) { PathPattern p = new PathPattern ( pathPattern ) ; if ( routes . containsKey ( p ) ) { return this ; } routes . put ( p , target ) ; addReverseRoute ( target , p ) ; return this ; }


Input: Removes the route specified by the path pattern . [CODESPLIT] public void removePathPattern ( String pathPattern ) { PathPattern p = new PathPattern ( pathPattern ) ; T target = routes . remove ( p ) ; if ( target == null ) { return ; } Set < PathPattern > paths = reverseRoutes . remove ( target ) ; paths . remove ( p ) ; }


Input: Removes all routes leading to the target . [CODESPLIT] public void removeTarget ( T target ) { Set < PathPattern > patterns = reverseRoutes . remove ( ObjectUtil . checkNotNull ( target , "target" ) ) ; if ( patterns == null ) { return ; } // A pattern can only point to one target. // A target can have multiple patterns. // Remove all patterns leading to this target. for ( PathPattern pattern : patterns ) { routes . remove ( pattern ) ; } }


Input: Returns the number of routes in this router . [CODESPLIT] public int size ( ) { return first . routes ( ) . size ( ) + other . routes ( ) . size ( ) + last . routes ( ) . size ( ) ; }


Input: Adds route to the first section . [CODESPLIT] public MethodlessRouter < T > addRouteFirst ( String pathPattern , T target ) { first . addRoute ( pathPattern , target ) ; return this ; }


Input: Adds route to the other section . [CODESPLIT] public MethodlessRouter < T > addRoute ( String pathPattern , T target ) { other . addRoute ( pathPattern , target ) ; return this ; }


Input: Adds route to the last section . [CODESPLIT] public MethodlessRouter < T > addRouteLast ( String pathPattern , T target ) { last . addRoute ( pathPattern , target ) ; return this ; }


Input: Removes the route specified by the path pattern . [CODESPLIT] public void removePathPattern ( String pathPattern ) { first . removePathPattern ( pathPattern ) ; other . removePathPattern ( pathPattern ) ; last . removePathPattern ( pathPattern ) ; }


Input: Removes all routes leading to the target . [CODESPLIT] public void removeTarget ( T target ) { first . removeTarget ( target ) ; other . removeTarget ( target ) ; last . removeTarget ( target ) ; }


Input: Checks if there s any matching route . [CODESPLIT] public boolean anyMatched ( String [ ] requestPathTokens ) { return first . anyMatched ( requestPathTokens ) || other . anyMatched ( requestPathTokens ) || last . anyMatched ( requestPathTokens ) ; }


Input: ---------------------------------------------------------------------------- [CODESPLIT] @ Override public void channelRead0 ( ChannelHandlerContext ctx , Object msg ) { // This handler is the last inbound handler. // This means msg has not been handled by any previous handler. ctx . close ( ) ; if ( msg != LastHttpContent . EMPTY_LAST_CONTENT ) { onUnknownMessage ( msg ) ; } }


Input: There are two different Criterion for if a property is null or checking equality . This is a convience method to return the one based on if value is null or not . [CODESPLIT] private Criterion smartEqual ( String property , Object value ) { if ( value == null ) { return Restrictions . isNull ( property ) ; } else { return Restrictions . eq ( property , value ) ; } }


Input: Generates the file name String for an owner and book name . [CODESPLIT] protected String getStoreFileName ( String owner , String name ) { final StringBuilder fileNameBuff = new StringBuilder ( ) ; fileNameBuff . append ( owner != null ? "_" + owner : "null" ) ; fileNameBuff . append ( "_" ) ; fileNameBuff . append ( name != null ? "_" + name : "null" ) ; fileNameBuff . append ( ".bms.xml" ) ; return fileNameBuff . toString ( ) ; }


Input: Generates the { @link File } object to use for storing retrieving and deleting the bookmark set . [CODESPLIT] protected File getStoreFile ( String owner , String name ) { final String fileStoreName = this . getStoreFileName ( owner , name ) ; final File basePath = this . getStoreDirectory ( ) ; final File storeFile = new File ( basePath , fileStoreName ) ; return storeFile ; }


Input:
Gets a BookmarkSet for the request using the injected { @link OwnerResolver } and { @link NameResolver } .

 If  create is false and no BookmarkSet exists for the name and owner null is returned .

 If  create is true and no BookmarkSet exists for the name and owner a new BookmarkSet is created . [CODESPLIT] public BookmarkSet getBookmarkSet ( PortletRequest request , boolean create ) { final String owner = this . ownerResolver . getOwner ( request ) ; final String name = this . nameResolver . getBookmarkSetName ( request ) ; BookmarkSet bookmarkSet = this . bookmarkStore . getBookmarkSet ( owner , name ) ; if ( bookmarkSet == null && create ) { bookmarkSet = this . bookmarkStore . createBookmarkSet ( owner , name ) ; if ( bookmarkSet == null ) { throw new IllegalStateException ( "Required BookmarkSet is null even after createBookmarkSet was called." ) ; } } return bookmarkSet ; }


Input: Returns an immutable sorted view of the values of the children Map . The sorting is done using the current childComparator . Warning this is has a time cost of 2n log ( n ) on every call . [CODESPLIT] public List < Entry > getSortedChildren ( ) { if ( this . children == null ) { return null ; } else { final Collection < Entry > childCollection = this . children . values ( ) ; final List < Entry > childList = new ArrayList < Entry > ( childCollection ) ; Collections . sort ( childList , this . childComparator ) ; return Collections . unmodifiableList ( childList ) ; } }


Input: Folders are always greater than non - Folders if they are both Folders or both not Folders they are equal . [CODESPLIT] protected int compareFolders ( final Entry e1 , final Entry e2 ) { final boolean f1 = e1 instanceof Folder ; final boolean f2 = e2 instanceof Folder ; if ( f1 && ! f2 ) { return - 1 ; } else if ( ! f1 && f2 ) { return 1 ; } else { return 0 ; } }


Input: Compairs the entries by name note created and modified properties in that order . [CODESPLIT] protected int compareEntries ( final Entry e1 , final Entry e2 ) { return new CompareToBuilder ( ) . append ( e1 . getName ( ) , e2 . getName ( ) ) . append ( e1 . getNote ( ) , e2 . getNote ( ) ) . append ( e1 . getCreated ( ) , e2 . getCreated ( ) ) . append ( e1 . getModified ( ) , e2 . getModified ( ) ) . toComparison ( ) ; }


Input: If both classes are not Bookmarks they are equal . If they are both bookmarks they are compared by url then newWindow properties . [CODESPLIT] protected int compareBookmarks ( final Entry e1 , final Entry e2 ) { if ( e1 instanceof Bookmark && e2 instanceof Bookmark ) { final Bookmark b1 = ( Bookmark ) e1 ; final Bookmark b2 = ( Bookmark ) e2 ; return new CompareToBuilder ( ) . append ( b1 . getUrl ( ) , b2 . getUrl ( ) ) . append ( b1 . isNewWindow ( ) , b2 . isNewWindow ( ) ) . toComparison ( ) ; } else { return 0 ; } }


Input:
Gets Preferences for the request using the injected { @link OwnerResolver } and { @link NameResolver } .

 If  create is false and no Preferences exists for the name and owner null is returned .

 If  create is true and no Preferences exists for the name and owner a new Preferences is created . [CODESPLIT] public Preferences getPreferences ( PortletRequest request , boolean create ) { final String owner = this . ownerResolver . getOwner ( request ) ; final String name = this . nameResolver . getBookmarkSetName ( request ) ; Preferences preferences = this . preferencesStore . getPreferences ( owner , name ) ; if ( preferences == null && create ) { preferences = this . preferencesStore . createPreferences ( owner , name ) ; if ( preferences == null ) { throw new IllegalStateException ( "Required Preferences is null even after createPreferences was called." ) ; } } return preferences ; }


Input: Returns an immutable sorted view of the values of the children Map . The sorting is done using the current childComparator . Warning this is has a time cost of 2n log ( n ) on every call . [CODESPLIT] public List < Entry > getSortedChildren ( ) { List < Entry > children = new ArrayList < Entry > ( ) ; log . debug ( "children: " + children . size ( ) ) ; HttpClient client = new HttpClient ( ) ; GetMethod get = null ; try { log . debug ( "getting url " + url ) ; get = new GetMethod ( url ) ; int rc = client . executeMethod ( get ) ; if ( rc != HttpStatus . SC_OK ) { log . error ( "HttpStatus:" + rc ) ; } DocumentBuilderFactory domBuilderFactory = DocumentBuilderFactory . newInstance ( ) ; DocumentBuilder builder = domBuilderFactory . newDocumentBuilder ( ) ; InputStream in = get . getResponseBodyAsStream ( ) ; builder = domBuilderFactory . newDocumentBuilder ( ) ; Document doc = builder . parse ( in ) ; get . releaseConnection ( ) ; Element e = ( Element ) doc . getElementsByTagName ( "rdf:RDF" ) . item ( 0 ) ; log . debug ( "got root " + e ) ; NodeList n = e . getElementsByTagName ( "item" ) ; log . debug ( "found items " + n . getLength ( ) ) ; for ( int i = 0 ; i < n . getLength ( ) ; i ++ ) { Bookmark bookmark = new Bookmark ( ) ; Element l = ( Element ) n . item ( i ) ; bookmark . setName ( ( ( Element ) l . getElementsByTagName ( "title" ) . item ( 0 ) ) . getTextContent ( ) ) ; bookmark . setUrl ( ( ( Element ) l . getElementsByTagName ( "link" ) . item ( 0 ) ) . getTextContent ( ) ) ; if ( l . getElementsByTagName ( "description" ) . getLength ( ) > 0 ) { bookmark . setNote ( ( ( Element ) l . getElementsByTagName ( "description" ) . item ( 0 ) ) . getTextContent ( ) ) ; } children . add ( bookmark ) ; log . debug ( "added bookmark " + bookmark . getName ( ) + " " + bookmark . getUrl ( ) ) ; } } catch ( HttpException e ) { log . error ( "Error parsing delicious" , e ) ; } catch ( IOException e ) { log . error ( "Error parsing delicious" , e ) ; } catch ( ParserConfigurationException e ) { log . error ( "Error parsing delicious" , e ) ; } catch ( SAXException e ) { log . error ( "Error parsing delicious" , e ) ; } finally { if ( get != null ) get . releaseConnection ( ) ; } log . debug ( "children: " + children . size ( ) ) ; return children ; }


Input: Get the optional short description <p > The short description is the first line of { @link #getDescription () } < / p > [CODESPLIT] public String getShortDescription ( ) { if ( this . description == null ) { return null ; } final String [ ] lines = this . description . split ( "\\R" , 2 ) ; if ( lines . length > 0 ) { return lines [ 0 ] ; } else { return "" ; } }


Input: Sets the last - modified time of the servlet class file associated with this JspServletWrapper . [CODESPLIT] public void setServletClassLastModifiedTime ( long lastModified ) { if ( this . servletClassLastModifiedTime < lastModified ) { synchronized ( this ) { if ( this . servletClassLastModifiedTime < lastModified ) { this . servletClassLastModifiedTime = lastModified ; reload = true ; } } } }


Input: Compile ( if needed ) and load a tag file [CODESPLIT] public Class loadTagFile ( ) throws JasperException { try { ctxt . compile ( ) ; if ( reload ) { tagHandlerClass = ctxt . load ( ) ; } } catch ( ClassNotFoundException ex ) { } catch ( FileNotFoundException ex ) { log . log ( Level . SEVERE , Localizer . getMessage ( "jsp.error.compiling" ) ) ; throw new JasperException ( ex ) ; } return tagHandlerClass ; }


Input: Compile and load a prototype for the Tag file . This is needed when compiling tag files with circular dependencies . A prototpe ( skeleton ) with no dependencies on other other tag files is generated and compiled . [CODESPLIT] public Class loadTagFilePrototype ( ) throws JasperException { ctxt . setPrototypeMode ( true ) ; try { return loadTagFile ( ) ; } finally { ctxt . setPrototypeMode ( false ) ; } }


Input: Get a list of files that the current page has source dependency on . [CODESPLIT] public java . util . List < String > getDependants ( ) { try { Object target ; if ( isTagFile ) { if ( reload ) { tagHandlerClass = ctxt . load ( ) ; } target = tagHandlerClass . newInstance ( ) ; } else { target = getServlet ( ) ; } if ( target != null && target instanceof JspSourceDependent ) { return ( ( JspSourceDependent ) target ) . getDependants ( ) ; } } catch ( Throwable ex ) { } return null ; }


Input: / * Handles the case where a requested JSP file no longer exists . [CODESPLIT] private void jspFileNotFound ( HttpServletRequest request , HttpServletResponse response ) throws ServletException , IOException { FileNotFoundException fnfe = new FileNotFoundException ( jspUri ) ; ctxt . incrementRemoved ( ) ; String includeRequestUri = ( String ) request . getAttribute ( "javax.servlet.include.request_uri" ) ; if ( includeRequestUri != null ) { // This file was included. Throw an exception as // a response.sendError() will be ignored by the // servlet engine. throw new ServletException ( fnfe ) ; } else { try { response . sendError ( HttpServletResponse . SC_NOT_FOUND , fnfe . getMessage ( ) ) ; } catch ( IllegalStateException ise ) { log . log ( Level . SEVERE , Localizer . getMessage ( "jsp.error.file.not.found" , fnfe . getMessage ( ) ) , fnfe ) ; } } }


Input: / * Parses a JSP document by responding to SAX events . [CODESPLIT] public static Node . Nodes parse ( ParserController pc , String path , JarFile jarFile , Node parent , boolean isTagFile , boolean directivesOnly , String pageEnc , String jspConfigPageEnc , boolean isEncodingSpecifiedInProlog ) throws JasperException { JspDocumentParser jspDocParser = new JspDocumentParser ( pc , path , isTagFile , directivesOnly ) ; Node . Nodes pageNodes = null ; try { // Create dummy root and initialize it with given page encodings Node . Root dummyRoot = new Node . Root ( null , parent , true ) ; dummyRoot . setPageEncoding ( pageEnc ) ; dummyRoot . setJspConfigPageEncoding ( jspConfigPageEnc ) ; dummyRoot . setIsEncodingSpecifiedInProlog ( isEncodingSpecifiedInProlog ) ; jspDocParser . current = dummyRoot ; if ( parent == null ) { jspDocParser . addInclude ( dummyRoot , jspDocParser . pageInfo . getIncludePrelude ( ) ) ; } else { jspDocParser . isTop = false ; } // Parse the input SAXParser saxParser = getSAXParser ( false , jspDocParser ) ; InputStream inStream = null ; try { inStream = JspUtil . getInputStream ( path , jarFile , jspDocParser . ctxt , jspDocParser . err ) ; saxParser . parse ( new InputSource ( inStream ) , jspDocParser ) ; } catch ( EnableDTDValidationException e ) { saxParser = getSAXParser ( true , jspDocParser ) ; jspDocParser . isValidating = true ; if ( inStream != null ) { try { inStream . close ( ) ; } catch ( Exception any ) { } } inStream = JspUtil . getInputStream ( path , jarFile , jspDocParser . ctxt , jspDocParser . err ) ; saxParser . parse ( new InputSource ( inStream ) , jspDocParser ) ; } finally { if ( inStream != null ) { try { inStream . close ( ) ; } catch ( Exception any ) { } } } if ( parent == null ) { jspDocParser . addInclude ( dummyRoot , jspDocParser . pageInfo . getIncludeCoda ( ) ) ; jspDocParser . pageInfo . setRootPath ( path ) ; } // Create Node.Nodes from dummy root pageNodes = new Node . Nodes ( dummyRoot ) ; } catch ( IOException ioe ) { jspDocParser . err . jspError ( "jsp.error.data.file.read" , path , ioe ) ; } catch ( SAXParseException e ) { jspDocParser . err . jspError ( new Mark ( jspDocParser . ctxt , path , e . getLineNumber ( ) , e . getColumnNumber ( ) ) , e . getMessage ( ) ) ; } catch ( Exception e ) { jspDocParser . err . jspError ( e ) ; } return pageNodes ; }


Input: / * Processes the given list of included files . [CODESPLIT] private void addInclude ( Node parent , List files ) throws SAXException { if ( files != null ) { Iterator iter = files . iterator ( ) ; while ( iter . hasNext ( ) ) { String file = ( String ) iter . next ( ) ; AttributesImpl attrs = new AttributesImpl ( ) ; attrs . addAttribute ( "" , "file" , "file" , "CDATA" , file ) ; // Create a dummy Include directive node Node includeDir = new Node . IncludeDirective ( attrs , null , // XXX parent ) ; processIncludeDirective ( file , includeDir ) ; } } }


Input:
/ * Receives notification of the start of an element . [CODESPLIT] public void startElement ( String uri , String localName , String qName , Attributes attrs ) throws SAXException { AttributesImpl taglibAttrs = null ; AttributesImpl nonTaglibAttrs = null ; AttributesImpl nonTaglibXmlnsAttrs = null ; processChars ( ) ; checkPrefixes ( uri , qName , attrs ) ; if ( directivesOnly && ! ( JSP_URI . equals ( uri ) && ( localName . startsWith ( DIRECTIVE_ACTION ) || localName . startsWith ( ROOT_ACTION ) ) ) ) { return ; } // jsp:text must not have any subelements if ( JSP_URI . equals ( uri ) && TEXT_ACTION . equals ( current . getLocalName ( ) ) ) { throw new SAXParseException ( Localizer . getMessage ( "jsp.error.text.has_subelement" ) , locator ) ; } startMark = new Mark ( ctxt , path , locator . getLineNumber ( ) , locator . getColumnNumber ( ) ) ; if ( attrs != null ) { /*
             * Notice that due to a bug in the underlying SAX parser, the
             * attributes must be enumerated in descending order.
             */ boolean isTaglib = false ; for ( int i = attrs . getLength ( ) - 1 ; i >= 0 ; i -- ) { isTaglib = false ; String attrQName = attrs . getQName ( i ) ; if ( ! attrQName . startsWith ( "xmlns" ) ) { if ( nonTaglibAttrs == null ) { nonTaglibAttrs = new AttributesImpl ( ) ; } nonTaglibAttrs . addAttribute ( attrs . getURI ( i ) , attrs . getLocalName ( i ) , attrs . getQName ( i ) , attrs . getType ( i ) , attrs . getValue ( i ) ) ; } else { if ( attrQName . startsWith ( "xmlns:jsp" ) ) { isTaglib = true ; } else { String attrUri = attrs . getValue ( i ) ; // TaglibInfo for this uri already established in // startPrefixMapping isTaglib = pageInfo . hasTaglib ( attrUri ) ; } if ( isTaglib ) { if ( taglibAttrs == null ) { taglibAttrs = new AttributesImpl ( ) ; } taglibAttrs . addAttribute ( attrs . getURI ( i ) , attrs . getLocalName ( i ) , attrs . getQName ( i ) , attrs . getType ( i ) , attrs . getValue ( i ) ) ; } else { if ( nonTaglibXmlnsAttrs == null ) { nonTaglibXmlnsAttrs = new AttributesImpl ( ) ; } nonTaglibXmlnsAttrs . addAttribute ( attrs . getURI ( i ) , attrs . getLocalName ( i ) , attrs . getQName ( i ) , attrs . getType ( i ) , attrs . getValue ( i ) ) ; } } } } Node node = null ; if ( tagDependentPending && JSP_URI . equals ( uri ) && localName . equals ( BODY_ACTION ) ) { tagDependentPending = false ; tagDependentNesting ++ ; current = parseStandardAction ( qName , localName , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; return ; } if ( tagDependentPending && JSP_URI . equals ( uri ) && localName . equals ( ATTRIBUTE_ACTION ) ) { current = parseStandardAction ( qName , localName , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; return ; } if ( tagDependentPending ) { tagDependentPending = false ; tagDependentNesting ++ ; } if ( tagDependentNesting > 0 ) { node = new Node . UninterpretedTag ( qName , localName , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; } else if ( JSP_URI . equals ( uri ) ) { node = parseStandardAction ( qName , localName , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; } else { node = parseCustomAction ( qName , localName , uri , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; if ( node == null ) { node = new Node . UninterpretedTag ( qName , localName , nonTaglibAttrs , nonTaglibXmlnsAttrs , taglibAttrs , startMark , current ) ; } else { // custom action String bodyType = getBodyType ( ( Node . CustomTag ) node ) ; if ( scriptlessBodyNode == null && bodyType . equalsIgnoreCase ( TagInfo . BODY_CONTENT_SCRIPTLESS ) ) { scriptlessBodyNode = node ; } else if ( TagInfo . BODY_CONTENT_TAG_DEPENDENT . equalsIgnoreCase ( bodyType ) ) { tagDependentPending = true ; } } } current = node ; }


Input: / * Receives notification of character data inside an element . [CODESPLIT] public void characters ( char [ ] buf , int offset , int len ) { if ( charBuffer == null ) { charBuffer = new StringBuilder ( ) ; } charBuffer . append ( buf , offset , len ) ; }


Input: / * Receives notification of the end of an element . [CODESPLIT] public void endElement ( String uri , String localName , String qName ) throws SAXException { processChars ( ) ; if ( directivesOnly && ! ( JSP_URI . equals ( uri ) && localName . startsWith ( DIRECTIVE_ACTION ) ) ) { return ; } if ( current instanceof Node . NamedAttribute ) { boolean isTrim = ( ( Node . NamedAttribute ) current ) . isTrim ( ) ; Node . Nodes subElems = ( ( Node . NamedAttribute ) current ) . getBody ( ) ; for ( int i = 0 ; subElems != null && i < subElems . size ( ) ; i ++ ) { Node subElem = subElems . getNode ( i ) ; if ( ! ( subElem instanceof Node . TemplateText ) ) { continue ; } // Ignore any whitespace (including spaces, carriage returns, // line feeds, and tabs, that appear at the beginning and at // the end of the body of the <jsp:attribute> action, if the // action's 'trim' attribute is set to TRUE (default). // In addition, any textual nodes in the <jsp:attribute> that // have only white space are dropped from the document, with // the exception of leading and trailing white-space-only // textual nodes in a <jsp:attribute> whose 'trim' attribute // is set to FALSE, which must be kept verbatim. if ( i == 0 ) { if ( isTrim ) { ( ( Node . TemplateText ) subElem ) . ltrim ( ) ; } } else if ( i == subElems . size ( ) - 1 ) { if ( isTrim ) { ( ( Node . TemplateText ) subElem ) . rtrim ( ) ; } } else { if ( ( ( Node . TemplateText ) subElem ) . isAllSpace ( ) ) { subElems . remove ( subElem ) ; } } } } else if ( current instanceof Node . ScriptingElement ) { checkScriptingBody ( ( Node . ScriptingElement ) current ) ; } if ( isTagDependent ( current ) ) { tagDependentNesting -- ; } if ( scriptlessBodyNode != null && current . equals ( scriptlessBodyNode ) ) { scriptlessBodyNode = null ; } if ( current . getParent ( ) != null ) { current = current . getParent ( ) ; } }