/* nmask.c -- make bitmask for a name list -- 12jan99 jw */ #include #include #include #include #include "bsfunc.h" #include "bscode.h" #define PROG_NAME "nmask" #define PROG_VERSION "1.00" #define AUTHOR_NAME "Jiri Wackermann" #define SYSERRMSG strerror( errno ) #define LINEMAX 2048 #define NAMESMAX 1000 /* function prototypes */ extern void error( int, ... ) __attribute__((noreturn)); extern int split( char *, char **, int ); static void print_help( void ) __attribute__((noreturn)); static void print_version( void ) __attribute__((noreturn)); static void read_args( int, char ** ); static FILE *open_file( char *, char *, FILE * ); static char *load_strings( FILE * ); static int lookup( char *, char **, int, int ); /* global data */ static char *helpinfo = "usage:\n" " %s [options] namebase [namelist] \n" "options:\n" " -b print binary mask\n" " -B print binary mask, prefix `0b'\n" " -i compare case insensitive\n" " -m ignore mismatching names\n" " -n suppress terminating LF\n" " -N list name list passed in line\n" " -o print octal mask\n" " -O print octal mask, prefix `0o'\n" " -x print hexadecimal mask\n" " -X print hexadecimal mask, prefix `0x'\n" ; #undef SHOWPARAMS char *progname = NULL; static char *bfname = 0; /* namebase file name */ static char *lfname = "-"; /* namelist file name */ static int radix = 2; /* conversion radix */ static char *prefix = 0; /* prepend prefix to converted mask */ static int icase = 0; /* case insensitive compare flag */ static int relax = 0; /* ignore mismatching names */ static int no_lf = 0; /* suppress terminating LF */ static char *base_p = 0; /* pointer to loaded name base data */ static char *list_p = 0; /* pointer to loaded name list data */ static char *base_pp[NAMESMAX]; /* array of pointers to base names */ static char *list_pp[NAMESMAX]; /* array of pointers to list names */ /* code starts here */ void main( int argc, char **argv ) { FILE *file; int n_list, n_base, i, j; char *bits, *mask; read_args( argc, argv ); /* read name base */ if ( !base_p ) { file = open_file( bfname, "rt", NULL ); base_p = load_strings( file ); fclose( file ); } n_base = split( base_p, base_pp, NAMESMAX ); bits = bs_alloc( n_base ); mask = malloc( n_base+3 ); /* read name list */ file = open_file( lfname, "rt", stdin ); list_p = load_strings( file ); fclose( file ); n_list = split( list_p, list_pp, NAMESMAX ); /* translate name list to bit mask */ for ( i = 0; i < n_list; i++ ) { j = lookup( list_pp[i], base_pp, n_base, icase ); if ( j >= 0 ) bs_set( bits, n_base, j ); else if ( !relax ) error( 1, list_pp[i], "name not found", 0 ); } /* encode bit mask & print to output */ bs_encode( mask, bits, n_base, radix ); if ( prefix ) fputs( prefix, stdout ); fputs( mask, stdout ); if ( !no_lf ) fputc( '\n', stdout ); exit( 0 ); } void print_help() { fprintf( stderr, helpinfo, progname ); exit( 0 ); } void print_version() { fprintf( stderr, "This is `%s' (version %s) by %s\n", PROG_NAME, PROG_VERSION, AUTHOR_NAME ); exit( 0 ); } void read_args( int argc, char **argv ) { char *p; int o; progname = argv[0]; opterr = 0; while (( o = getopt( argc, argv, "bBimoOnN:xX!?" )) != -1 ) switch ( o ) { case 'b': radix = 2; prefix = 0; break; case 'B': radix = 2; prefix = "0b"; break; case 'm': relax = 1; break; case 'n': no_lf = 1; break; case 'N': base_p = optarg; break; case 'o': radix = 8; prefix = 0; break; case 'O': radix = 8; prefix = "0o"; break; case 'x': radix = 16; prefix = 0; break; case 'X': radix = 16; prefix = "0x"; break; case '!': print_version(); break; case '?': if ( o == optopt ) print_help(); else error( 1, "illegal option", &optopt, 0 ); } if ( optind < argc ) bfname = argv[optind]; if ( optind+1 < argc ) lfname = argv[optind+1]; if ( base_p ) { lfname = bfname; bfname = NULL; } if ( !bfname && !base_p ) error( 1, "name base not specified", 0 ); } FILE *open_file( char *fn, char *mod, FILE *def ) { FILE *f = ( fn[0] == '-' ) ? def : fopen( fn, mod ); if ( !f ) error( 1, fn, SYSERRMSG, 0 ); return f; } char *load_strings( FILE *f ) { char *p; p = malloc( filelength( fileno( f )) + 1 ); if ( p ) { int c; char *q = p; while (( c = fgetc( f )) != EOF ) *q++ = ( c == '\n' ) ? ' ' : c; *q = 0; } else error( 1, "string space", SYSERRMSG, 0 ); return p; } int lookup( char *s, char **pp, int n, int isens ) { int (*cmp)( const char *, const char * ) = isens ? strcmp : stricmp; int i = n; while ( --i >= 0 ) if ( cmp( s, pp[i] ) == 0 ) break; return i; } /* end of file */