2001-08-20 04:08:40 +04:00
/*
* xmlcatalog . c : a small utility program to handle XML catalogs
*
* See Copyright for the status of this software .
*
* daniel @ veillard . com
*/
# include "libxml.h"
# include <string.h>
# include <stdio.h>
# include <stdarg.h>
2001-09-20 17:56:06 +04:00
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
2001-08-21 13:23:53 +04:00
# ifdef HAVE_LIBREADLINE
# include <readline/readline.h>
# ifdef HAVE_LIBHISTORY
# include <readline/history.h>
# endif
# endif
2001-08-20 04:08:40 +04:00
# include <libxml/xmlmemory.h>
# include <libxml/uri.h>
# include <libxml/catalog.h>
# include <libxml/parser.h>
static int shell = 0 ;
2001-10-08 19:01:59 +04:00
static int sgml = 0 ;
2001-08-20 04:08:40 +04:00
static int noout = 0 ;
2001-08-23 03:44:09 +04:00
static int create = 0 ;
2001-08-21 14:56:31 +04:00
static int add = 0 ;
static int del = 0 ;
2001-08-25 17:33:14 +04:00
static int convert = 0 ;
2001-08-20 04:08:40 +04:00
static int verbose = 0 ;
2001-08-21 14:56:31 +04:00
static char * filename ;
2001-08-20 04:08:40 +04:00
# ifdef LIBXML_CATALOG_ENABLED
/************************************************************************
* *
* Shell Interface *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlShellReadline :
* @ prompt : the prompt value
*
* Read a string
*
* Returns a pointer to it or NULL on EOF the caller is expected to
* free the returned string .
*/
static char *
xmlShellReadline ( const char * prompt ) {
# ifdef HAVE_LIBREADLINE
char * line_read ;
/* Get a line from the user. */
line_read = readline ( prompt ) ;
/* If the line has any text in it, save it on the history. */
if ( line_read & & * line_read )
add_history ( line_read ) ;
return ( line_read ) ;
# else
char line_read [ 501 ] ;
if ( prompt ! = NULL )
fprintf ( stdout , " %s " , prompt ) ;
if ( ! fgets ( line_read , 500 , stdin ) )
return ( NULL ) ;
line_read [ 500 ] = 0 ;
return ( strdup ( line_read ) ) ;
# endif
}
static void usershell ( void ) {
char * cmdline = NULL , * cur ;
int nbargs ;
char command [ 100 ] ;
char arg [ 400 ] ;
2001-08-21 14:56:31 +04:00
char * argv [ 20 ] ;
int i , ret ;
xmlChar * ans ;
2001-08-20 04:08:40 +04:00
while ( 1 ) {
cmdline = xmlShellReadline ( " > " ) ;
if ( cmdline = = NULL )
return ;
/*
* Parse the command itself
*/
cur = cmdline ;
nbargs = 0 ;
while ( ( * cur = = ' ' ) | | ( * cur = = ' \t ' ) ) cur + + ;
i = 0 ;
while ( ( * cur ! = ' ' ) & & ( * cur ! = ' \t ' ) & &
( * cur ! = ' \n ' ) & & ( * cur ! = ' \r ' ) ) {
if ( * cur = = 0 )
break ;
command [ i + + ] = * cur + + ;
}
command [ i ] = 0 ;
if ( i = = 0 ) continue ;
nbargs + + ;
/*
2001-08-21 14:56:31 +04:00
* Parse the argument string
2001-08-20 04:08:40 +04:00
*/
2001-08-21 14:56:31 +04:00
memset ( arg , 0 , sizeof ( arg ) ) ;
2001-08-20 04:08:40 +04:00
while ( ( * cur = = ' ' ) | | ( * cur = = ' \t ' ) ) cur + + ;
i = 0 ;
while ( ( * cur ! = ' \n ' ) & & ( * cur ! = ' \r ' ) & & ( * cur ! = 0 ) ) {
if ( * cur = = 0 )
break ;
arg [ i + + ] = * cur + + ;
}
arg [ i ] = 0 ;
if ( i ! = 0 )
nbargs + + ;
2001-08-21 14:56:31 +04:00
/*
* Parse the arguments
*/
i = 0 ;
nbargs = 0 ;
cur = arg ;
memset ( argv , 0 , sizeof ( argv ) ) ;
while ( * cur ! = 0 ) {
while ( ( * cur = = ' ' ) | | ( * cur = = ' \t ' ) ) cur + + ;
if ( * cur = = ' \' ' ) {
cur + + ;
argv [ i ] = cur ;
while ( ( * cur ! = 0 ) & & ( * cur ! = ' \' ' ) ) cur + + ;
if ( * cur = = ' \' ' ) {
* cur = 0 ;
nbargs + + ;
i + + ;
cur + + ;
}
} else if ( * cur = = ' " ' ) {
cur + + ;
argv [ i ] = cur ;
while ( ( * cur ! = 0 ) & & ( * cur ! = ' " ' ) ) cur + + ;
if ( * cur = = ' " ' ) {
* cur = 0 ;
nbargs + + ;
i + + ;
cur + + ;
}
} else {
argv [ i ] = cur ;
while ( ( * cur ! = 0 ) & & ( * cur ! = ' ' ) & & ( * cur ! = ' \t ' ) )
cur + + ;
* cur = 0 ;
nbargs + + ;
i + + ;
cur + + ;
}
}
2001-08-20 04:08:40 +04:00
/*
* start interpreting the command
*/
if ( ! strcmp ( command , " exit " ) )
break ;
if ( ! strcmp ( command , " quit " ) )
break ;
if ( ! strcmp ( command , " bye " ) )
break ;
if ( ! strcmp ( command , " public " ) ) {
2001-08-21 14:56:31 +04:00
if ( nbargs ! = 1 ) {
printf ( " public requires 1 arguments \n " ) ;
2001-08-20 04:08:40 +04:00
} else {
2001-08-22 04:06:49 +04:00
ans = xmlCatalogResolvePublic ( ( const xmlChar * ) argv [ 0 ] ) ;
if ( ans = = NULL ) {
2001-08-21 14:56:31 +04:00
printf ( " No entry for PUBLIC %s \n " , argv [ 0 ] ) ;
} else {
2001-08-22 04:06:49 +04:00
printf ( " %s \n " , ans ) ;
xmlFree ( ans ) ;
2001-08-21 14:56:31 +04:00
}
2001-08-20 04:08:40 +04:00
}
} else if ( ! strcmp ( command , " system " ) ) {
2001-08-21 14:56:31 +04:00
if ( nbargs ! = 1 ) {
printf ( " system requires 1 arguments \n " ) ;
} else {
2001-08-22 04:06:49 +04:00
ans = xmlCatalogResolveSystem ( ( const xmlChar * ) argv [ 0 ] ) ;
if ( ans = = NULL ) {
2001-08-21 14:56:31 +04:00
printf ( " No entry for SYSTEM %s \n " , argv [ 0 ] ) ;
} else {
2001-08-22 04:06:49 +04:00
printf ( " %s \n " , ans ) ;
xmlFree ( ans ) ;
2001-08-21 14:56:31 +04:00
}
}
} else if ( ! strcmp ( command , " add " ) ) {
2001-10-08 19:01:59 +04:00
if ( sgml ) {
if ( nbargs ! = 1 ) {
printf ( " add requires 1 argument \n " ) ;
} else {
ret = xmlCatalogAdd ( BAD_CAST " sgmlcatalog " , NULL ,
BAD_CAST argv [ 0 ] ) ;
}
2001-08-21 14:56:31 +04:00
} else {
2001-10-08 19:01:59 +04:00
if ( ( nbargs ! = 3 ) & & ( nbargs ! = 2 ) ) {
printf ( " add requires 2 or 3 arguments \n " ) ;
} else {
if ( argv [ 2 ] = = NULL )
ret = xmlCatalogAdd ( BAD_CAST argv [ 0 ] , NULL ,
BAD_CAST argv [ 1 ] ) ;
else
ret = xmlCatalogAdd ( BAD_CAST argv [ 0 ] , BAD_CAST argv [ 1 ] ,
BAD_CAST argv [ 2 ] ) ;
if ( ret ! = 0 )
printf ( " add command failed \n " ) ;
}
2001-08-21 14:56:31 +04:00
}
} else if ( ! strcmp ( command , " del " ) ) {
if ( nbargs ! = 1 ) {
printf ( " del requires 1 \n " ) ;
} else {
ret = xmlCatalogRemove ( BAD_CAST argv [ 0 ] ) ;
if ( ret < = 0 )
printf ( " del command failed \n " ) ;
}
} else if ( ! strcmp ( command , " resolve " ) ) {
if ( nbargs ! = 2 ) {
printf ( " resolve requires 2 arguments \n " ) ;
2001-08-20 04:08:40 +04:00
} else {
2001-08-21 14:56:31 +04:00
ans = xmlCatalogResolve ( BAD_CAST argv [ 0 ] ,
BAD_CAST argv [ 1 ] ) ;
if ( ans = = NULL ) {
printf ( " Resolver failed to find an answer \n " ) ;
} else {
printf ( " %s \n " , ans ) ;
xmlFree ( ans ) ;
}
2001-08-20 04:08:40 +04:00
}
} else if ( ! strcmp ( command , " dump " ) ) {
2001-08-21 14:56:31 +04:00
if ( nbargs ! = 0 ) {
printf ( " dump has no arguments \n " ) ;
} else {
xmlCatalogDump ( stdout ) ;
}
2001-08-22 04:06:49 +04:00
} else if ( ! strcmp ( command , " debug " ) ) {
if ( nbargs ! = 0 ) {
printf ( " debug has no arguments \n " ) ;
} else {
verbose + + ;
xmlCatalogSetDebug ( verbose ) ;
}
} else if ( ! strcmp ( command , " quiet " ) ) {
if ( nbargs ! = 0 ) {
printf ( " quiet has no arguments \n " ) ;
} else {
if ( verbose > 0 )
verbose - - ;
xmlCatalogSetDebug ( verbose ) ;
}
2001-08-20 04:08:40 +04:00
} else {
if ( strcmp ( command , " help " ) ) {
printf ( " Unrecognized command %s \n " , command ) ;
}
printf ( " Commands available: \n " ) ;
printf ( " \t public PublicID: make a PUBLIC identifier lookup \n " ) ;
printf ( " \t system SystemID: make a SYSTEM identifier lookup \n " ) ;
2001-08-21 14:56:31 +04:00
printf ( " \t resolve PublicID SystemID: do a full resolver lookup \n " ) ;
printf ( " \t add 'type' 'orig' 'replace' : add an entry \n " ) ;
printf ( " \t del 'values' : remove values \n " ) ;
2001-08-20 04:08:40 +04:00
printf ( " \t dump: print the current catalog state \n " ) ;
2001-08-22 04:06:49 +04:00
printf ( " \t debug: increase the verbosity level \n " ) ;
printf ( " \t quiet: decrease the verbosity level \n " ) ;
2001-08-20 04:08:40 +04:00
printf ( " \t exit: quit the shell \n " ) ;
}
free ( cmdline ) ; /* not xmlFree here ! */
}
}
/************************************************************************
* *
* Main *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void usage ( const char * name ) {
2001-08-22 04:06:49 +04:00
printf ( " Usage : %s [options] catalogfile entities... \n " , name ) ;
printf ( " \t Parse the catalog file and query it for the entities \n " ) ;
2001-10-08 19:01:59 +04:00
printf ( " \t --sgml : handle an SGML Super catalog \n " ) ;
2001-08-20 04:08:40 +04:00
printf ( " \t --shell : run a shell allowing interactive queries \n " ) ;
2001-08-23 03:44:09 +04:00
printf ( " \t --create : create a new catalog \n " ) ;
2001-08-21 14:56:31 +04:00
printf ( " \t --add 'type' 'orig' 'replace' : add an entry \n " ) ;
printf ( " \t --del 'values' : remove values \n " ) ;
printf ( " \t --noout: avoid dumping the result on stdout \n " ) ;
printf ( " \t used with add or del, it saves the catalog changes \n " ) ;
2001-08-20 04:08:40 +04:00
printf ( " \t -v --verbose : provide debug informations \n " ) ;
}
int main ( int argc , char * * argv ) {
int i ;
2001-08-25 17:33:14 +04:00
int ret ;
2001-08-20 04:08:40 +04:00
if ( argc < = 1 ) {
usage ( argv [ 0 ] ) ;
return ( 1 ) ;
}
LIBXML_TEST_VERSION
for ( i = 1 ; i < argc ; i + + ) {
if ( ! strcmp ( argv [ i ] , " - " ) )
break ;
if ( argv [ i ] [ 0 ] ! = ' - ' )
2001-08-22 04:06:49 +04:00
break ;
2001-08-20 04:08:40 +04:00
if ( ( ! strcmp ( argv [ i ] , " -verbose " ) ) | |
( ! strcmp ( argv [ i ] , " -v " ) ) | |
( ! strcmp ( argv [ i ] , " --verbose " ) ) ) {
verbose + + ;
xmlCatalogSetDebug ( verbose ) ;
2001-08-21 14:56:31 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -noout " ) ) | |
( ! strcmp ( argv [ i ] , " --noout " ) ) ) {
noout = 1 ;
2001-08-20 04:08:40 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -shell " ) ) | |
( ! strcmp ( argv [ i ] , " --shell " ) ) ) {
shell + + ;
noout = 1 ;
2001-10-08 19:01:59 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -sgml " ) ) | |
( ! strcmp ( argv [ i ] , " --sgml " ) ) ) {
sgml + + ;
2001-08-23 03:44:09 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -create " ) ) | |
( ! strcmp ( argv [ i ] , " --create " ) ) ) {
create + + ;
2001-08-25 17:33:14 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -convert " ) ) | |
( ! strcmp ( argv [ i ] , " --convert " ) ) ) {
convert + + ;
2001-08-21 14:56:31 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -add " ) ) | |
( ! strcmp ( argv [ i ] , " --add " ) ) ) {
2001-10-08 19:01:59 +04:00
if ( sgml )
i + = 1 ;
else
i + = 3 ;
2001-08-21 14:56:31 +04:00
add + + ;
} else if ( ( ! strcmp ( argv [ i ] , " -del " ) ) | |
( ! strcmp ( argv [ i ] , " --del " ) ) ) {
i + = 1 ;
del + + ;
2001-08-20 04:08:40 +04:00
} else {
fprintf ( stderr , " Unknown option %s \n " , argv [ i ] ) ;
usage ( argv [ 0 ] ) ;
return ( 1 ) ;
}
}
for ( i = 1 ; i < argc ; i + + ) {
2001-08-21 14:56:31 +04:00
if ( ( ! strcmp ( argv [ i ] , " -add " ) ) | |
( ! strcmp ( argv [ i ] , " --add " ) ) ) {
2001-10-08 19:01:59 +04:00
if ( sgml )
i + = 1 ;
else
i + = 3 ;
2001-08-21 14:56:31 +04:00
continue ;
} else if ( ( ! strcmp ( argv [ i ] , " -del " ) ) | |
( ! strcmp ( argv [ i ] , " --del " ) ) ) {
i + = 1 ;
2001-08-20 04:08:40 +04:00
continue ;
2001-08-21 14:56:31 +04:00
} else if ( argv [ i ] [ 0 ] = = ' - ' )
continue ;
filename = argv [ i ] ;
2001-10-12 21:29:10 +04:00
/* !!!!!!!!!!!!!!!!!! TODO !!!!
2001-10-08 19:01:59 +04:00
if ( sgml )
ret = xmlLoadSGMLSuperCatalog ( argv [ i ] ) ;
else
2001-10-12 21:29:10 +04:00
! ! ! ! ! ! ! ! ! */
2001-10-08 19:01:59 +04:00
ret = xmlLoadCatalog ( argv [ i ] ) ;
if ( ( ! sgml ) & & ( ret < 0 ) & & ( create ) ) {
2001-08-23 03:44:09 +04:00
xmlCatalogAdd ( BAD_CAST " catalog " , BAD_CAST argv [ i ] , NULL ) ;
}
2001-08-21 14:56:31 +04:00
break ;
}
2001-08-25 17:33:14 +04:00
if ( convert )
ret = xmlCatalogConvert ( ) ;
2001-08-21 14:56:31 +04:00
2001-08-25 17:33:14 +04:00
if ( ( add ) | | ( del ) ) {
2001-08-21 14:56:31 +04:00
for ( i = 1 ; i < argc ; i + + ) {
if ( ! strcmp ( argv [ i ] , " - " ) )
break ;
if ( argv [ i ] [ 0 ] ! = ' - ' )
continue ;
if ( ( ! strcmp ( argv [ i ] , " -add " ) ) | |
( ! strcmp ( argv [ i ] , " --add " ) ) ) {
2001-10-08 19:01:59 +04:00
if ( sgml ) {
ret = xmlCatalogAdd ( BAD_CAST " sgmlcatalog " , NULL ,
BAD_CAST argv [ i + 1 ] ) ;
i + = 1 ;
} else {
if ( ( argv [ i + 3 ] = = NULL ) | | ( argv [ i + 3 ] [ 0 ] = = 0 ) )
ret = xmlCatalogAdd ( BAD_CAST argv [ i + 1 ] , NULL ,
BAD_CAST argv [ i + 2 ] ) ;
else
ret = xmlCatalogAdd ( BAD_CAST argv [ i + 1 ] ,
BAD_CAST argv [ i + 2 ] ,
BAD_CAST argv [ i + 3 ] ) ;
if ( ret ! = 0 )
printf ( " add command failed \n " ) ;
i + = 3 ;
}
2001-08-21 14:56:31 +04:00
} else if ( ( ! strcmp ( argv [ i ] , " -del " ) ) | |
( ! strcmp ( argv [ i ] , " --del " ) ) ) {
ret = xmlCatalogRemove ( BAD_CAST argv [ i + 1 ] ) ;
i + = 1 ;
}
}
2001-08-22 04:06:49 +04:00
} else if ( shell ) {
2001-08-20 04:08:40 +04:00
usershell ( ) ;
2001-08-22 04:06:49 +04:00
} else {
for ( i + + ; i < argc ; i + + ) {
xmlURIPtr uri ;
xmlChar * ans ;
uri = xmlParseURI ( argv [ i ] ) ;
if ( uri = = NULL ) {
ans = xmlCatalogResolvePublic ( ( const xmlChar * ) argv [ i ] ) ;
if ( ans = = NULL ) {
printf ( " No entry for PUBLIC %s \n " , argv [ i ] ) ;
} else {
printf ( " %s \n " , ans ) ;
xmlFree ( ans ) ;
}
} else {
xmlFreeURI ( uri ) ;
ans = xmlCatalogResolveSystem ( ( const xmlChar * ) argv [ i ] ) ;
if ( ans = = NULL ) {
printf ( " No entry for SYSTEM %s \n " , argv [ i ] ) ;
} else {
printf ( " %s \n " , ans ) ;
xmlFree ( ans ) ;
}
}
}
2001-08-20 04:08:40 +04:00
}
2001-08-25 17:33:14 +04:00
if ( ( add ) | | ( del ) | | ( create ) | | ( convert ) ) {
2001-08-23 03:44:09 +04:00
if ( noout ) {
FILE * out ;
out = fopen ( filename , " w " ) ;
if ( out = = NULL ) {
fprintf ( stderr , " could not open %s for saving \n " , filename ) ;
noout = 0 ;
} else {
xmlCatalogDump ( out ) ;
}
} else {
xmlCatalogDump ( stdout ) ;
}
}
2001-08-20 04:08:40 +04:00
/*
* Cleanup and check for memory leaks
*/
xmlCleanupParser ( ) ;
xmlMemoryDump ( ) ;
return ( 0 ) ;
}
# else
int main ( int argc , char * * argv ) {
fprintf ( stderr , " libxml was not compiled with catalog support \n " ) ;
return ( 1 ) ;
}
# endif