2002-04-16 15:50:10 +00:00
/*
* testRegexp . c : simple module for testing regular expressions
*
* See Copyright for the status of this software .
*
* Daniel Veillard < veillard @ redhat . com >
*/
# include "libxml.h"
# ifdef LIBXML_REGEXP_ENABLED
2007-01-31 18:38:56 +00:00
# include <string.h>
2002-04-16 15:50:10 +00:00
# include <libxml/tree.h>
# include <libxml/xmlregexp.h>
2005-07-28 23:49:35 +00:00
static int repeat = 0 ;
static int debug = 0 ;
2002-04-16 15:50:10 +00:00
static void testRegexp ( xmlRegexpPtr comp , const char * value ) {
int ret ;
ret = xmlRegexpExec ( comp , ( const xmlChar * ) value ) ;
if ( ret = = 1 )
printf ( " %s: Ok \n " , value ) ;
else if ( ret = = 0 )
printf ( " %s: Fail \n " , value ) ;
else
printf ( " %s: Error: %d \n " , value , ret ) ;
if ( repeat ) {
int j ;
for ( j = 0 ; j < 999999 ; j + + )
xmlRegexpExec ( comp , ( const xmlChar * ) value ) ;
}
}
static void
testRegexpFile ( const char * filename ) {
xmlRegexpPtr comp = NULL ;
FILE * input ;
char expression [ 5000 ] ;
int len ;
input = fopen ( filename , " r " ) ;
if ( input = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" Cannot open %s for reading \n " , filename ) ;
return ;
}
while ( fgets ( expression , 4500 , input ) ! = NULL ) {
len = strlen ( expression ) ;
len - - ;
2012-09-11 13:26:36 +08:00
while ( ( len > = 0 ) & &
2002-04-16 15:50:10 +00:00
( ( expression [ len ] = = ' \n ' ) | | ( expression [ len ] = = ' \t ' ) | |
( expression [ len ] = = ' \r ' ) | | ( expression [ len ] = = ' ' ) ) ) len - - ;
2012-09-11 13:26:36 +08:00
expression [ len + 1 ] = 0 ;
2002-04-16 15:50:10 +00:00
if ( len > = 0 ) {
if ( expression [ 0 ] = = ' # ' )
continue ;
if ( ( expression [ 0 ] = = ' = ' ) & & ( expression [ 1 ] = = ' > ' ) ) {
char * pattern = & expression [ 2 ] ;
if ( comp ! = NULL ) {
xmlRegFreeRegexp ( comp ) ;
comp = NULL ;
}
printf ( " Regexp: %s \n " , pattern ) ;
comp = xmlRegexpCompile ( ( const xmlChar * ) pattern ) ;
if ( comp = = NULL ) {
printf ( " failed to compile \n " ) ;
break ;
}
} else if ( comp = = NULL ) {
printf ( " Regexp: %s \n " , expression ) ;
comp = xmlRegexpCompile ( ( const xmlChar * ) expression ) ;
if ( comp = = NULL ) {
printf ( " failed to compile \n " ) ;
break ;
}
} else if ( comp ! = NULL ) {
testRegexp ( comp , expression ) ;
}
}
}
fclose ( input ) ;
if ( comp ! = NULL )
xmlRegFreeRegexp ( comp ) ;
}
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
static void
runFileTest ( xmlExpCtxtPtr ctxt , const char * filename ) {
xmlExpNodePtr expr = NULL , sub ;
FILE * input ;
char expression [ 5000 ] ;
int len ;
input = fopen ( filename , " r " ) ;
if ( input = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" Cannot open %s for reading \n " , filename ) ;
return ;
}
while ( fgets ( expression , 4500 , input ) ! = NULL ) {
len = strlen ( expression ) ;
len - - ;
2012-09-11 13:26:36 +08:00
while ( ( len > = 0 ) & &
2005-08-22 12:07:04 +00:00
( ( expression [ len ] = = ' \n ' ) | | ( expression [ len ] = = ' \t ' ) | |
( expression [ len ] = = ' \r ' ) | | ( expression [ len ] = = ' ' ) ) ) len - - ;
2012-09-11 13:26:36 +08:00
expression [ len + 1 ] = 0 ;
2005-08-22 12:07:04 +00:00
if ( len > = 0 ) {
if ( expression [ 0 ] = = ' # ' )
continue ;
if ( ( expression [ 0 ] = = ' = ' ) & & ( expression [ 1 ] = = ' > ' ) ) {
char * str = & expression [ 2 ] ;
if ( expr ! = NULL ) {
xmlExpFree ( ctxt , expr ) ;
2012-09-11 13:26:36 +08:00
if ( xmlExpCtxtNbNodes ( ctxt ) ! = 0 )
2005-08-22 12:07:04 +00:00
printf ( " Parse/free of Expression leaked %d \n " ,
xmlExpCtxtNbNodes ( ctxt ) ) ;
expr = NULL ;
}
printf ( " Expression: %s \n " , str ) ;
expr = xmlExpParse ( ctxt , str ) ;
if ( expr = = NULL ) {
printf ( " parsing Failed \n " ) ;
break ;
}
} else if ( expr ! = NULL ) {
int expect = - 1 ;
int nodes1 , nodes2 ;
if ( expression [ 0 ] = = ' 0 ' )
expect = 0 ;
if ( expression [ 0 ] = = ' 1 ' )
expect = 1 ;
printf ( " Subexp: %s " , expression + 2 ) ;
nodes1 = xmlExpCtxtNbNodes ( ctxt ) ;
sub = xmlExpParse ( ctxt , expression + 2 ) ;
if ( sub = = NULL ) {
printf ( " parsing Failed \n " ) ;
break ;
} else {
int ret ;
2012-09-11 13:26:36 +08:00
2005-08-22 12:07:04 +00:00
nodes2 = xmlExpCtxtNbNodes ( ctxt ) ;
ret = xmlExpSubsume ( ctxt , expr , sub ) ;
if ( ( expect = = 1 ) & & ( ret = = 1 ) ) {
printf ( " => accept, Ok \n " ) ;
} else if ( ( expect = = 0 ) & & ( ret = = 0 ) ) {
printf ( " => reject, Ok \n " ) ;
} else if ( ( expect = = 1 ) & & ( ret = = 0 ) ) {
printf ( " => reject, Failed \n " ) ;
} else if ( ( expect = = 0 ) & & ( ret = = 1 ) ) {
printf ( " => accept, Failed \n " ) ;
} else {
printf ( " => fail internally \n " ) ;
}
if ( xmlExpCtxtNbNodes ( ctxt ) > nodes2 ) {
printf ( " Subsume leaked %d \n " ,
xmlExpCtxtNbNodes ( ctxt ) - nodes2 ) ;
nodes1 + = xmlExpCtxtNbNodes ( ctxt ) - nodes2 ;
}
xmlExpFree ( ctxt , sub ) ;
if ( xmlExpCtxtNbNodes ( ctxt ) > nodes1 ) {
printf ( " Parse/free leaked %d \n " ,
xmlExpCtxtNbNodes ( ctxt ) - nodes1 ) ;
}
}
}
}
}
if ( expr ! = NULL ) {
xmlExpFree ( ctxt , expr ) ;
2012-09-11 13:26:36 +08:00
if ( xmlExpCtxtNbNodes ( ctxt ) ! = 0 )
2005-08-22 12:07:04 +00:00
printf ( " Parse/free of Expression leaked %d \n " ,
xmlExpCtxtNbNodes ( ctxt ) ) ;
}
fclose ( input ) ;
}
2005-08-22 14:43:43 +00:00
2012-09-11 13:26:36 +08:00
static void
2005-08-22 14:43:43 +00:00
testReduce ( xmlExpCtxtPtr ctxt , xmlExpNodePtr expr , const char * tst ) {
xmlBufferPtr xmlExpBuf ;
xmlExpNodePtr sub , deriv ;
xmlExpBuf = xmlBufferCreate ( ) ;
sub = xmlExpParse ( ctxt , tst ) ;
if ( sub = = NULL ) {
printf ( " Subset %s failed to parse \n " , tst ) ;
return ;
}
2005-08-22 15:50:57 +00:00
xmlExpDump ( xmlExpBuf , sub ) ;
2005-08-22 14:43:43 +00:00
printf ( " Subset parsed as: %s \n " ,
( const char * ) xmlBufferContent ( xmlExpBuf ) ) ;
deriv = xmlExpExpDerive ( ctxt , expr , sub ) ;
if ( deriv = = NULL ) {
printf ( " Derivation led to an internal error, report this ! \n " ) ;
return ;
} else {
xmlBufferEmpty ( xmlExpBuf ) ;
xmlExpDump ( xmlExpBuf , deriv ) ;
if ( xmlExpIsNillable ( deriv ) )
printf ( " Resulting nillable derivation: %s \n " ,
( const char * ) xmlBufferContent ( xmlExpBuf ) ) ;
else
printf ( " Resulting derivation: %s \n " ,
( const char * ) xmlBufferContent ( xmlExpBuf ) ) ;
xmlExpFree ( ctxt , deriv ) ;
}
xmlExpFree ( ctxt , sub ) ;
}
2012-09-11 13:26:36 +08:00
static void
2005-08-22 14:43:43 +00:00
exprDebug ( xmlExpCtxtPtr ctxt , xmlExpNodePtr expr ) {
xmlBufferPtr xmlExpBuf ;
xmlExpNodePtr deriv ;
const char * list [ 40 ] ;
int ret ;
xmlExpBuf = xmlBufferCreate ( ) ;
if ( expr = = NULL ) {
printf ( " Failed to parse \n " ) ;
return ;
}
xmlExpDump ( xmlExpBuf , expr ) ;
printf ( " Parsed as: %s \n " , ( const char * ) xmlBufferContent ( xmlExpBuf ) ) ;
printf ( " Max token input = %d \n " , xmlExpMaxToken ( expr ) ) ;
if ( xmlExpIsNillable ( expr ) = = 1 )
printf ( " Is nillable \n " ) ;
ret = xmlExpGetLanguage ( ctxt , expr , ( const xmlChar * * ) & list [ 0 ] , 40 ) ;
if ( ret < 0 )
printf ( " Failed to get list: %d \n " , ret ) ;
else {
int i ;
printf ( " Language has %d strings, testing string derivations \n " , ret ) ;
for ( i = 0 ; i < ret ; i + + ) {
deriv = xmlExpStringDerive ( ctxt , expr , BAD_CAST list [ i ] , - 1 ) ;
if ( deriv = = NULL ) {
printf ( " %s -> derivation failed \n " , list [ i ] ) ;
} else {
xmlBufferEmpty ( xmlExpBuf ) ;
xmlExpDump ( xmlExpBuf , deriv ) ;
printf ( " %s -> %s \n " , list [ i ] ,
( const char * ) xmlBufferContent ( xmlExpBuf ) ) ;
}
xmlExpFree ( ctxt , deriv ) ;
}
}
xmlBufferFree ( xmlExpBuf ) ;
}
2005-08-22 12:07:04 +00:00
# endif
2002-04-16 15:50:10 +00:00
static void usage ( const char * name ) {
2005-08-22 12:07:04 +00:00
fprintf ( stderr , " Usage: %s [flags] \n " , name ) ;
fprintf ( stderr , " Testing tool for libxml2 string and pattern regexps \n " ) ;
fprintf ( stderr , " --debug: switch on debugging \n " ) ;
fprintf ( stderr , " --repeat: loop on the operation \n " ) ;
# ifdef LIBXML_EXPR_ENABLED
fprintf ( stderr , " --expr: test xmlExp and not xmlRegexp \n " ) ;
# endif
fprintf ( stderr , " --input filename: use the given filename for regexp \n " ) ;
fprintf ( stderr , " --input filename: use the given filename for exp \n " ) ;
2002-04-16 15:50:10 +00:00
}
int main ( int argc , char * * argv ) {
xmlRegexpPtr comp = NULL ;
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
xmlExpNodePtr expr = NULL ;
int use_exp = 0 ;
xmlExpCtxtPtr ctxt = NULL ;
# endif
2002-04-16 15:50:10 +00:00
const char * pattern = NULL ;
char * filename = NULL ;
int i ;
xmlInitMemory ( ) ;
if ( argc < = 1 ) {
usage ( argv [ 0 ] ) ;
return ( 1 ) ;
}
for ( i = 1 ; i < argc ; i + + ) {
if ( ! strcmp ( argv [ i ] , " - " ) )
break ;
if ( argv [ i ] [ 0 ] ! = ' - ' )
continue ;
2008-02-21 22:31:55 +00:00
if ( ! strcmp ( argv [ i ] , " -- " ) )
break ;
2002-04-16 15:50:10 +00:00
if ( ( ! strcmp ( argv [ i ] , " -debug " ) ) | | ( ! strcmp ( argv [ i ] , " --debug " ) ) ) {
debug + + ;
} else if ( ( ! strcmp ( argv [ i ] , " -repeat " ) ) | |
( ! strcmp ( argv [ i ] , " --repeat " ) ) ) {
repeat + + ;
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
} else if ( ( ! strcmp ( argv [ i ] , " -expr " ) ) | |
( ! strcmp ( argv [ i ] , " --expr " ) ) ) {
use_exp + + ;
# endif
} else if ( ( ! strcmp ( argv [ i ] , " -i " ) ) | | ( ! strcmp ( argv [ i ] , " -f " ) ) | |
( ! strcmp ( argv [ i ] , " --input " ) ) )
2002-04-16 15:50:10 +00:00
filename = argv [ + + i ] ;
else {
fprintf ( stderr , " Unknown option %s \n " , argv [ i ] ) ;
usage ( argv [ 0 ] ) ;
}
}
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
if ( use_exp )
ctxt = xmlExpNewCtxt ( 0 , NULL ) ;
# endif
2002-04-16 15:50:10 +00:00
if ( filename ! = NULL ) {
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
if ( use_exp )
runFileTest ( ctxt , filename ) ;
else
# endif
testRegexpFile ( filename ) ;
2002-04-16 15:50:10 +00:00
} else {
2008-02-21 22:31:55 +00:00
int data = 0 ;
2005-08-22 14:43:43 +00:00
# ifdef LIBXML_EXPR_ENABLED
2008-02-21 22:31:55 +00:00
2005-08-22 14:43:43 +00:00
if ( use_exp ) {
for ( i = 1 ; i < argc ; i + + ) {
2008-02-21 22:31:55 +00:00
if ( strcmp ( argv [ i ] , " -- " ) = = 0 )
data = 1 ;
else if ( ( argv [ i ] [ 0 ] ! = ' - ' ) | | ( strcmp ( argv [ i ] , " - " ) = = 0 ) | |
( data = = 1 ) ) {
2005-08-22 14:43:43 +00:00
if ( pattern = = NULL ) {
pattern = argv [ i ] ;
printf ( " Testing expr %s: \n " , pattern ) ;
expr = xmlExpParse ( ctxt , pattern ) ;
if ( expr = = NULL ) {
printf ( " failed to compile \n " ) ;
break ;
}
if ( debug ) {
exprDebug ( ctxt , expr ) ;
}
} else {
testReduce ( ctxt , expr , argv [ i ] ) ;
2002-04-16 15:50:10 +00:00
}
}
}
2008-02-21 22:31:55 +00:00
if ( expr ! = NULL ) {
2005-08-22 14:43:43 +00:00
xmlExpFree ( ctxt , expr ) ;
2008-02-21 22:31:55 +00:00
expr = NULL ;
}
2005-08-22 14:43:43 +00:00
} else
# endif
{
for ( i = 1 ; i < argc ; i + + ) {
2008-02-21 22:31:55 +00:00
if ( strcmp ( argv [ i ] , " -- " ) = = 0 )
data = 1 ;
else if ( ( argv [ i ] [ 0 ] ! = ' - ' ) | | ( strcmp ( argv [ i ] , " - " ) = = 0 ) | |
( data = = 1 ) ) {
2005-08-22 14:43:43 +00:00
if ( pattern = = NULL ) {
pattern = argv [ i ] ;
printf ( " Testing %s: \n " , pattern ) ;
comp = xmlRegexpCompile ( ( const xmlChar * ) pattern ) ;
if ( comp = = NULL ) {
printf ( " failed to compile \n " ) ;
break ;
}
if ( debug )
xmlRegexpPrint ( stdout , comp ) ;
} else {
testRegexp ( comp , argv [ i ] ) ;
}
}
}
if ( comp ! = NULL )
xmlRegFreeRegexp ( comp ) ;
}
2002-04-16 15:50:10 +00:00
}
2005-08-22 12:07:04 +00:00
# ifdef LIBXML_EXPR_ENABLED
if ( ctxt ! = NULL ) {
printf ( " Ops: %d nodes, %d cons \n " ,
xmlExpCtxtNbNodes ( ctxt ) , xmlExpCtxtNbCons ( ctxt ) ) ;
xmlExpFreeCtxt ( ctxt ) ;
}
# endif
2002-04-16 15:50:10 +00:00
xmlCleanupParser ( ) ;
2005-07-14 12:58:49 +00:00
xmlMemoryDump ( ) ;
2002-04-16 15:50:10 +00:00
return ( 0 ) ;
}
# else
# include <stdio.h>
2003-09-29 13:20:24 +00:00
int main ( int argc ATTRIBUTE_UNUSED , char * * argv ATTRIBUTE_UNUSED ) {
2002-04-16 15:50:10 +00:00
printf ( " %s : Regexp support not compiled in \n " , argv [ 0 ] ) ;
return ( 0 ) ;
}
# endif /* LIBXML_REGEXP_ENABLED */