diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:03:17 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:03:17 +0000 |
commit | ecf966f305f6aeff2bbdf42c82d8425921aa9eda (patch) | |
tree | db606a57e3619610e4c35cae849d41cf4e0937d5 /Master/texmf-dist/source/latex/splitindex/splitindex.c | |
parent | ac3c55a3216b5988f0e48ba9414ddb059f19a699 (diff) |
source 1
git-svn-id: svn://tug.org/texlive/trunk@105 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/splitindex/splitindex.c')
-rw-r--r-- | Master/texmf-dist/source/latex/splitindex/splitindex.c | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/splitindex/splitindex.c b/Master/texmf-dist/source/latex/splitindex/splitindex.c new file mode 100644 index 00000000000..41a092af734 --- /dev/null +++ b/Master/texmf-dist/source/latex/splitindex/splitindex.c @@ -0,0 +1,576 @@ +/* + * splitindex.c + * Copyright (c) Markus Kohm, 2002 + * + * $Id: splitindex.c,v 1.6 2003/01/05 10:50:07 mjk Exp $ + * + * This file is part of the SplitIndex package + * + * This file can be redistributed and/or modified under the conditions + * of the LaTeX Project Public License, either version 1.2 of this + * license or (at your option) any later version. + * The latest version of this license is in + * http://www.latex-project.org/lppl.txt + * and version 1.2 or later is part of all distributions of LaTeX + * version 1999/12/01 or later. + * + * You are not allowed to redistribute this file without all the + * other files of the SplitIndex package + */ + +#include <sys/types.h> +#include <sys/wait.h> + +#include <ctype.h> +#include <errno.h> +#include <regex.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +enum { + OPT_HELP = 'h', OPT_MAKEINDEX = 'm', OPT_IDENTIFY = 'i', + OPT_RESULTIS = 'r', OPT_VERBOSE = 'v', OPT_SUFFIXIS = 's', + OPT_VERSION = 'V' +}; + +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined (NO_LONGOPT) + +#define HAS_LONGOPT 0 +#define HAPAR "" + +#else /* defined(__OpenBSD__) || defined(__FreeBSD__) || defined(NO_LONGOPT) */ + +#define HAS_LONGOPT 1 +#define HAPAR "\n\t\t" + +#include <getopt.h> + +static const struct option long_options[] = { + { "help", 0, NULL, OPT_HELP }, + { "makeindex", 1, NULL, OPT_MAKEINDEX }, + { "identify", 1, NULL, OPT_IDENTIFY }, + { "resultis", 1, NULL, OPT_RESULTIS }, + { "suffixis", 1, NULL, OPT_SUFFIXIS }, + { "verbose", 0, NULL, OPT_VERBOSE }, + { "version", 0, NULL, OPT_VERSION }, + { NULL, 0, NULL, 0 }, +}; + +#endif + +static const char short_options[] = { + OPT_HELP, + OPT_MAKEINDEX, ':', + OPT_IDENTIFY, ':', + OPT_RESULTIS, ':', + OPT_SUFFIXIS, ':', + OPT_VERBOSE, + OPT_VERSION, +}; + +int Verbose = 0; + +char *MakeIndex = "makeindex"; +char *Identify = "^(\\\\indexentry)\\[([^]]*)\\](.*)$"; +char *ResultIs = "$1$3"; +char *SuffixIs = "-$2"; +char *IDX = NULL; +char *Jobname = NULL; +char * const * MakeIndexArgs = NULL; +char *prgname = "splitindex"; +int MakeIndexArgc = 0; + +static void show_version( void ) { + printf( "splitindex 0.2a\n" + "Copyright (c) 2002 Markus Kohm <kohm@gmx.de>\n" ); +} + +static void show_usage( FILE *out ) { + fputs( "Usage: splitindex [OPTION]... RAWINDEXFILE [MAKEINDEXOPTION]...\n", + out ); +} + +static void usage_error( const char *format, ... ) { + if ( format != NULL ) { + va_list ap; + va_start( ap, format ); + vfprintf( stderr, format, ap ); + va_end( ap ); + } + fputs( "Try `splitindex " +#if HAS_LONGOPT + "--help" +#else + "-h" +#endif + "' for more information.\n", stderr ); + exit( 1 ); +} + +static void show_help( void ) { + show_version(); + printf( "\n" ); + show_usage( stdout ); + printf( + "Split a single raw index file into multiple raw index files.\n" + "Example: splitindex.pl foo.idx.\n" + "\n" + "Options:\n" + " -h" +#if HAS_LONGOPT + ", --help " +#else + " " +#endif + "\tshow this help and terminate\n" + " -m" +#if HAS_LONGOPT + ", --makeindex" +#endif + " PROGNAME " HAPAR + "\tcall PROGNAME instead of default `%s'.\n", + MakeIndex + ); + printf( + " -i" +#if HAS_LONGOPT + ", --identify" +#endif + " EXPRESSION " HAPAR + "\tuse regular EXPRESSION to match entries\n" + "\t\t\t(see also option --resultis and --suffixis).\n" + "\t\t\tDefault is `%s'.\n", + Identify + ); + printf( + " -r" +#if HAS_LONGOPT + ", --resultis" +#endif + " PATTERN " HAPAR + "\tcreate line to be written from PATTERN after matching\n" + "\t\t\tlines (see also option --identify).\n" + "\t\t\tDefault is `%s'.\n", + ResultIs + ); + printf( + " -s" +#if HAS_LONGOPT + ", --suffixis" +#endif + " PATTERN " HAPAR + "\tcreate suffix to be used from PATTERN after matching\n" + "\t\t\tlines (see also option --identify).\n" + "\t\t\tDefault is `%s'.\n", + SuffixIs + ); + printf( + " -v" +#if HAS_LONGOPT + ", --verbose " +#else + " " +#endif + "\tbe more verbose\n" + "\t\t\t(can be used multiple to increase verbosity)\n" + " -V" +#if HAS_LONGOPT + ", --version " +#else + " " +#endif + "\tshow version and terminate\n" + ); + exit(0); +} + +static void ScanArguments( int argc, char * const argv[] ) { + int retVal; + char *hs; + if ( argc > 0 ) + prgname = argv[0]; +#if HAS_LONGOPT + while ( ( retVal = getopt_long( argc, argv, short_options, + long_options, NULL ) ) != - 1 ) { +#else + while ( ( retVal = getopt( argc, argv, short_options ) ) != - 1 ) { +#endif + switch( retVal ) { + case OPT_HELP: + show_help(); + break; /* should never be reached */ + case OPT_VERSION: + show_version(); + exit( 0 ); + break; /* should never be reached */ + case OPT_MAKEINDEX: + MakeIndex = optarg; + break; + case OPT_IDENTIFY: + Identify = optarg; + break; + case OPT_RESULTIS: + ResultIs = optarg; + break; + case OPT_SUFFIXIS: + SuffixIs = optarg; + break; + case OPT_VERBOSE: + Verbose++; + break; + case ':': + case '?': + usage_error( NULL ); + break; /* should never be reached */ + } + } + if ( optind < argc ) { + IDX = argv[optind++]; + MakeIndexArgc = argc - optind; + MakeIndexArgs = argv + optind; + } else { + usage_error( "missing raw index file\n" ); + return; /* should never be reached */ + } + + if ( ( Jobname = strdup( IDX ) ) == NULL ) { + perror( prgname ); + exit( errno ); + } + + if ( ( ( hs = strrchr( Jobname, '.' ) ) != NULL ) + && !strcmp( hs, ".idx" ) ) + *hs = 0; +} + +static char *regsub( const char *string, const char *replace, + int nmatch, regmatch_t pmatch[] ) { + int pass; + int size, n; + const char *hs; + char c; + char *retVal = NULL; + char *ts; + + /* Two times parsing to get size and replace */ + for ( pass = size = 0; pass < 2; pass++ ) { + ts = retVal; + for ( hs = replace; *hs; hs++ ) { + switch( *hs ) { + case '$': + if ( isdigit( hs[1] ) ) { + n = *++hs - '0'; + if ( ( pmatch[n].rm_so >= 0 ) + && ( pmatch[n].rm_so < pmatch[n].rm_eo ) ) { + /* maybe group n is not empty */ + if ( pass ) { + strncpy( ts, + string + pmatch[n].rm_so, + pmatch[n].rm_eo - pmatch[n].rm_so ); + ts += pmatch[n].rm_eo - pmatch[n].rm_so; + } else { + size += pmatch[n].rm_eo - pmatch[n].rm_so; + } + } + } else { + if ( pass ) { + *ts++ = '$'; + } else { + size++; + } + } + break; + case '\\': + switch( c = *++hs ) { + case 0: c = '\\'; hs--; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + } + if ( pass ) { + *ts++ = c; + } else { + size++; + } + break; + default: + if ( pass ) { + *ts++ = *hs; + } else { + size++; + } + break; + } + } + if ( pass ) { + *ts = '\0'; + } else { + if ( ( retVal = malloc( size + 1 ) ) == NULL ) { + perror( prgname ); + exit( 1 ); + } + } + } + + return retVal; +} + +static struct list { + struct list *next; + char *name; + FILE *file; +} *IDXfiles = NULL; + +static FILE *findsuffix( const char *name ) { + struct list *run; + for ( run = IDXfiles; + run != NULL; + run = run->next ) { + const char *suffix = strchr( run->name, '\0' ); + suffix -= 4; /* .idx */ + suffix -= strlen( name ); + if ( ( suffix >= run->name ) + && !strncmp( suffix, name, strlen( name ) ) ) { + return run->file; + } + } + return NULL; +} + +static struct list *addentry( char *name, FILE *file ) { + struct list *newentry = malloc( sizeof( struct list ) ); + if ( !newentry ) { + perror( prgname ); + exit( 1 ); + } + newentry->name = name; + newentry->file = file; + if ( IDXfiles == NULL ) { + newentry->next = NULL; + } else { + newentry->next = IDXfiles; + } + IDXfiles = newentry; + return IDXfiles; +} + +static FILE *newentry( const char *suffix ) { + char *name; + FILE *file; + + if ( ( name = malloc( strlen( Jobname ) + strlen( suffix ) + 5 ) ) == NULL ) { + perror( prgname ); + exit( 1 ); + } + + strcpy( name, Jobname ); + strcat( name, suffix ); + strcat( name, ".idx" ); + + if ( ( file = fopen( name, "w" ) ) == NULL ) { + perror( name ); + exit( errno ); + } + + if ( Verbose > 1 ) + printf( "New index file %s\n", name ); + addentry( name, file ); + return file; +} + +static void CloseAllIDX( void ) { + struct list *run; + for ( run = IDXfiles; run != NULL; run = run->next ) + if ( fclose( run->file ) ) { + perror( run->name ); + exit( 1 ); + } +} + +static void CallMakeIndex( void ) { + char **argv; + int idx; + struct list *run, *next; + + if ( ( argv = calloc( MakeIndexArgc + 3, sizeof( char * ) ) ) == NULL ) { + perror( prgname ); + exit( 0 ); + } + + for ( idx = 0; idx < MakeIndexArgc; idx++ ) + argv[idx+1] = MakeIndexArgs[idx]; + + idx++; + argv[0] = MakeIndex; + + for ( run = IDXfiles; run != NULL; run = next ) { + pid_t fret; + int status; + argv[idx] = run->name; + + if ( ( fret = fork() ) == 0 ) { + /* This is the child */ + if ( Verbose > 1 ) { + int i; + for ( i = 0; argv[i] != NULL; i++ ) + printf( "\"%s\" ", argv[i] ); + printf( "\n" ); + } + if ( execvp( MakeIndex, argv ) ) { + perror( MakeIndex ); + exit( 1 ); + } + } else if ( fret == -1 ) { + perror( prgname ); + exit( 1 ); + } else { + /* Parent */ + waitpid( fret, &status, 0 ); + if ( ! WIFEXITED( status ) ) { + fprintf( stderr, "%s terminated abnormally!\n", MakeIndex ); + exit( 1 ); + } + } + + free( (void *)run->name ); + next = run->next; + free( run ); + } + + +} + +static void ProcessIDXFile( void ) { + FILE *fIDX; + char *line; + regex_t preg; + int retVal; + int buffersize = 2050; + regmatch_t pmatch[10]; + + if ( ( line = malloc( buffersize ) ) == NULL ) { + perror( prgname ); + exit( errno ); + } + + if ( ( retVal = regcomp( &preg, Identify, REG_EXTENDED ) ) != 0 ) { + regerror( retVal, &preg, line, buffersize ); + fprintf( stderr, "Error at identify: %s\n", line ); + free( line ); + exit( 1 ); + } + + if ( ( fIDX = fopen( IDX, "r" ) ) == NULL ) { + if ( !strcmp ( IDX, Jobname ) ) { + if ( ( IDX = malloc( strlen( Jobname + 5 ) ) ) == NULL ) { + perror( prgname ); + regfree( &preg ); + free( line ); + exit( errno ); + } + strcpy( IDX, Jobname ); + strcat( IDX, ".idx" ); + if ( ( fIDX = fopen( IDX, "r" ) ) == NULL ) { + fprintf( stderr, + "Can read neither file %s nor file %s\n", + Jobname, IDX ); + regfree( &preg ); + free( line ); + exit( 1 ); + } + } else { + fprintf( stderr, + "Can't red file %s\n", IDX ); + regfree( &preg ); + free( line ); + exit( 1 ); + } + } + + while ( fgets( line, buffersize, fIDX ) != NULL ) { + char *hs; + char *result, *suffix; + FILE *f; + while ( ( ( hs = strchr( line, '\n' ) ) == NULL ) + && ! feof( fIDX ) ) { + if ( ( line = realloc( line, 2 * buffersize ) ) == NULL ) { + perror( prgname ); + exit( errno ); + } + if ( fgets( line + buffersize - 1, buffersize + 1, fIDX ) == NULL ) + break; + buffersize *= 2; + } + if ( ferror( fIDX ) ) + break; + if ( ( hs = strchr( line, '\n' ) ) != NULL ) // remove newline + *hs = 0; + if ( ( retVal = regexec( &preg, line, 10, pmatch, 0 ) ) == 0 ) { + result = regsub( line, ResultIs, 10, pmatch ); + suffix = regsub( line, SuffixIs, 10, pmatch ); + } else { + int i; + result = strdup( line ); + for ( i = 0; i < 10; i++ ) { + pmatch[i].rm_so = 0; + pmatch[i].rm_eo = 3; + } + suffix = regsub( "idx", SuffixIs, 10, pmatch ); + } + if ( !result || !suffix ) { + perror( prgname ); + exit ( 1 ); + } + + if ( ( f = findsuffix( suffix ) ) == NULL ) + f = newentry( suffix ); + fprintf( f, "%s\n", result ); + + free( suffix ); + free( result ); + } + + regfree( &preg ); + free( line ); + if ( ferror( fIDX ) ) { + perror( IDX ); + fclose( fIDX ); + exit( errno ); + } + fclose( fIDX ); + + CloseAllIDX(); + + CallMakeIndex(); +} + +int main( int argc, char * const argv[] ) { + int retVal = 0; + + ScanArguments( argc, argv ); + + if ( Verbose > 0 ) { + show_version(); + if ( Verbose > 9 ) { + int i; + printf( "Identify: \"%s\"\n", Identify ); + printf( "ResultIs: \"%s\"\n", ResultIs ); + printf( "SuffixIs: \"%s\"\n", SuffixIs ); + printf( "IDX: \"%s\"\n", IDX ); + printf( "Jobname: \"%s\"\n", Jobname ); + printf( "MakeIndex: \"%s\"", MakeIndex ); + for ( i = 0; i < MakeIndexArgc; i++ ) + printf( " \"%s\"", MakeIndexArgs[i] ); + printf( "\n" ); + } + } + + ProcessIDXFile(); + + return retVal; +} |