diff options
author | Greg McGary <greg@mcgary.org> | 1997-04-18 06:43:35 +0000 |
---|---|---|
committer | Greg McGary <greg@mcgary.org> | 1997-04-18 06:43:35 +0000 |
commit | 3720d4b7a1b0ce0903450271aa3d93388e9d8781 (patch) | |
tree | 12200295d735bf3d1bcaaf8d2065547d41cea3b2 /src | |
parent | 916418ea1284e6aa64f50eba077e48ced5944acc (diff) | |
download | idutils-99c80c70c191cfc68cbafa88aea66427ae97cc57.tar.gz idutils-99c80c70c191cfc68cbafa88aea66427ae97cc57.tar.bz2 idutils-99c80c70c191cfc68cbafa88aea66427ae97cc57.zip |
imported from id-utils-3.1r3_1
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/Makefile.in | 75 | ||||
-rw-r--r-- | src/aid | 4 | ||||
-rw-r--r-- | src/defid | 4 | ||||
-rw-r--r-- | src/eid | 4 | ||||
-rw-r--r-- | src/fid.c | 110 | ||||
-rw-r--r-- | src/gid | 4 | ||||
-rw-r--r-- | src/lid.c | 922 | ||||
-rw-r--r-- | src/mkid.c | 213 |
9 files changed, 777 insertions, 566 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3d1b163..21ccc73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,18 +2,19 @@ AUTOMAKE_OPTIONS = ansi2knr -bin_PROGRAMS = mkid lid fid idx -bin_SCRIPTS = eid aid gid pid defid +bin_PROGRAMS = mkid lid fid fnid xtokid +bin_SCRIPTS = eid aid gid defid EXTRA_DIST = ansi2knr.1 ansi2knr.c $(bin_SCRIPTS) localedir = $(datadir)/locale INCLUDES = -I. -I$(srcdir) \ + -I../libidu -I$(top_srcdir)/libidu \ -I../lib -I$(top_srcdir)/lib \ -I../intl -I$(top_srcdir)/intl \ -I.. -I$(top_srcdir) DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ -LDADD = @INTLLIBS@ ../lib/libidu.a +LDADD = @INTLLIBS@ ../libidu/libidu.a ../lib/libsys.a $(PROGRAMS): $(LDADD) diff --git a/src/Makefile.in b/src/Makefile.in index 8ea0b5c..cda6580 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -40,19 +40,20 @@ transform = @program_transform_name@ AUTOMAKE_OPTIONS = ansi2knr -bin_PROGRAMS = mkid lid fid idx -bin_SCRIPTS = eid aid gid pid defid +bin_PROGRAMS = mkid lid fid fnid xtokid +bin_SCRIPTS = eid aid gid defid EXTRA_DIST = ansi2knr.1 ansi2knr.c $(bin_SCRIPTS) localedir = $(datadir)/locale INCLUDES = -I. -I$(srcdir) \ + -I../libidu -I$(top_srcdir)/libidu \ -I../lib -I$(top_srcdir)/lib \ -I../intl -I$(top_srcdir)/intl \ -I.. -I$(top_srcdir) DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ -LDADD = @INTLLIBS@ ../lib/libidu.a +LDADD = @INTLLIBS@ ../libidu/libidu.a ../lib/libsys.a mkinstalldirs = $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h PROGRAMS = $(bin_PROGRAMS) @@ -83,10 +84,14 @@ fid_SOURCES = fid.c fid_OBJECTS = fid$o EXTRA_fid_SOURCES = fid_LDADD = $(LDADD) -idx_SOURCES = idx.c -idx_OBJECTS = idx$o -EXTRA_idx_SOURCES = -idx_LDADD = $(LDADD) +fnid_SOURCES = fnid.c +fnid_OBJECTS = fnid$o +EXTRA_fnid_SOURCES = +fnid_LDADD = $(LDADD) +xtokid_SOURCES = xtokid.c +xtokid_OBJECTS = xtokid$o +EXTRA_xtokid_SOURCES = +xtokid_LDADD = $(LDADD) SCRIPTS = $(bin_SCRIPTS) DIST_COMMON = Makefile.am Makefile.in @@ -101,8 +106,8 @@ DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(BUILT_SOURCES) $(HEADERS) \ $(TEXINFOS) $(INFO_DEPS) $(MANS) $(EXTRA_DIST) $(DATA) TAR = tar -SOURCES = mkid.c lid.c fid.c idx.c -OBJECTS = mkid$o lid$o fid$o idx$o +SOURCES = mkid.c lid.c fid.c fnid.c xtokid.c +OBJECTS = mkid$o lid$o fid$o fnid$o xtokid$o default: all @@ -189,10 +194,14 @@ $(fid_OBJECTS): ../config.h fid: $(fid_OBJECTS) $(fid_DEPENDENCIES) $(LINK) $(fid_OBJECTS) $(fid_LDADD) $(LIBS) -$(idx_OBJECTS): ../config.h +$(fnid_OBJECTS): ../config.h -idx: $(idx_OBJECTS) $(idx_DEPENDENCIES) - $(LINK) $(idx_OBJECTS) $(idx_LDADD) $(LIBS) +fnid: $(fnid_OBJECTS) $(fnid_DEPENDENCIES) + $(LINK) $(fnid_OBJECTS) $(fnid_LDADD) $(LIBS) +$(xtokid_OBJECTS): ../config.h + +xtokid: $(xtokid_OBJECTS) $(xtokid_DEPENDENCIES) + $(LINK) $(xtokid_OBJECTS) $(xtokid_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) $(mkinstalldirs) $(bindir) @@ -235,22 +244,32 @@ distdir: $(DEP_DISTFILES) || ln $(srcdir)/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $(srcdir)/$$file $(distdir)/$$file; \ done -fid$o: fid.c system.h idfile.h \ - hash.h bitops.h filenames.h \ - misc.h strxtra.h alloc.h \ - token.h error.h pathmax.h -idx$o: idx.c alloc.h system.h \ - misc.h filenames.h scanners.h \ - idfile.h hash.h pathmax.h -lid$o: lid.c system.h alloc.h \ - idfile.h hash.h token.h \ - bitops.h strxtra.h misc.h \ - filenames.h error.h pathmax.h -mkid$o: mkid.c system.h pathmax.h \ - strxtra.h alloc.h idfile.h \ - hash.h token.h bitops.h \ - misc.h filenames.h scanners.h \ - error.h +fid$o: ../src/fid.c ../lib/xstring.h ../lib/xunistd.h \ + ../libidu/xnls.h ../libidu/idfile.h ../lib/xobstack.h \ + ../lib/xmalloc.h ../libidu/hash.h ../libidu/dynvec.h \ + ../libidu/tokflags.h ../lib/error.h ../lib/pathmax.h \ + ../lib/xalloca.h +fnid$o: ../src/fnid.c ../lib/xfnmatch.h ../lib/xstring.h \ + ../lib/xmalloc.h ../libidu/xnls.h ../libidu/idfile.h \ + ../lib/xobstack.h ../libidu/hash.h ../libidu/dynvec.h \ + ../libidu/tokflags.h ../lib/pathmax.h ../lib/error.h \ + ../lib/xalloca.h +lid$o: ../src/lid.c ../lib/xstdlib.h ../lib/xstring.h \ + ../lib/xunistd.h ../libidu/xnls.h ../lib/xmalloc.h \ + ../libidu/idfile.h ../lib/xobstack.h ../libidu/hash.h \ + ../libidu/dynvec.h ../libidu/tokflags.h ../lib/error.h \ + ../lib/pathmax.h ../lib/xalloca.h +mkid$o: ../src/mkid.c ../lib/xstdlib.h ../lib/xsysstat.h \ + ../lib/xstddef.h ../lib/xunistd.h ../libidu/xnls.h \ + ../lib/pathmax.h ../lib/xstring.h ../libidu/idfile.h \ + ../lib/xobstack.h ../lib/xmalloc.h ../libidu/hash.h \ + ../libidu/dynvec.h ../libidu/tokflags.h ../libidu/scanners.h \ + ../lib/error.h ../lib/xalloca.h +xtokid$o: ../src/xtokid.c ../libidu/xnls.h \ + ../libidu/scanners.h ../lib/xobstack.h ../lib/xmalloc.h \ + ../lib/xstring.h ../libidu/idfile.h ../libidu/hash.h \ + ../libidu/dynvec.h ../libidu/tokflags.h ../lib/pathmax.h \ + ../lib/error.h info: @@ -1,3 +1,3 @@ -#!/bin/sh +#! /bin/sh -lid -E "$@" +exec lid -ils "$@" @@ -1,6 +1,6 @@ -#!/bin/sh +#! /bin/sh for sym do - gid $sym |egrep '(}[ ]*|:[ ]*#[ ]*define[ ]+)'$sym'|'typedef\>.*[ ]+'$sym + gid $sym |egrep '(}[ ]*|:[ ]*#[ ]*define[ ]+)'$sym'|typedef\>.*[ ]+'$sym done @@ -1,3 +1,3 @@ -#!/bin/sh +#! /bin/sh -lid -E "$@" +exec lid -R edit "$@" @@ -1,5 +1,6 @@ /* fid.c -- list all tokens in the given file(s) Copyright (C) 1986, 1995, 1996 Free Software Foundation, Inc. + Written by Greg McGary <gkm@gnu.ai.mit.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,27 +16,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <config.h> #include <stdio.h> -#include <string.h> -#include <ctype.h> #include <getopt.h> - -#include <config.h> -#include "system.h" +#include "xstring.h" +#include "xunistd.h" +#include "xnls.h" #include "idfile.h" -#include "bitops.h" -#include "filenames.h" -#include "misc.h" -#include "strxtra.h" -#include "alloc.h" -#include "token.h" #include "error.h" #include "pathmax.h" +#include "xmalloc.h" +#include "xalloca.h" int get_file_index __P((char *file_name)); int is_hit __P((unsigned char const *hits, int file_number)); int is_hit_1 __P((unsigned char const **hits, int level, int file_number)); void skip_hits __P((unsigned char const **hits, int level)); +void usage __P((void)); struct idhead idh; int tree8_levels; @@ -54,8 +51,6 @@ static int show_version; /* The file name of the ID database. */ -char const *id_file_name; - struct file_link *cw_dlink; struct file_link **members_0; unsigned int bits_vec_size; @@ -81,13 +76,15 @@ static void help_me (void) { printf (_("\ -Usage: %s [OPTION] FILENAME [FILENAME2]\n"), - program_name); +Usage: %s [OPTION] FILENAME [FILENAME2]\n\ +"), program_name); printf (_("\ List identifiers that occur in FILENAME, or if FILENAME2 is\n\ also given list the identifiers that occur in both files.\n\ \n\ - -f, --file=FILE file name of ID database\n\ + -f, --file=FILE file name of ID database\n\ + --help display this help and exit\n\ + --version output version information and exit\n\ ")); exit (0); } @@ -95,11 +92,19 @@ also given list the identifiers that occur in both files.\n\ int main (int argc, char **argv) { - int optc; int index_1 = -1; int index_2 = -1; program_name = argv[0]; + idh.idh_file_name = 0; + + /* Set locale according to user's wishes. */ + setlocale (LC_ALL, ""); + + /* Tell program which translations to use and where to find. */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + for (;;) { int optc = getopt_long (argc, argv, "f:", @@ -112,7 +117,7 @@ main (int argc, char **argv) break; case 'f': - id_file_name = optarg; + idh.idh_file_name = optarg; break; default: @@ -129,22 +134,6 @@ main (int argc, char **argv) if (show_help) help_me (); - /* Look for the ID database up the tree */ - id_file_name = look_up (id_file_name); - if (id_file_name == 0) - error (1, errno, _("can't locate `ID'")); - - init_idh_obstacks (&idh); - init_idh_tables (&idh); - - cw_dlink = get_current_dir_link (); - - /* Determine absolute name of the directory name to which database - constituent files are relative. */ - members_0 = read_id_file (id_file_name, &idh); - bits_vec_size = (idh.idh_files + 7) / 4; /* more than enough */ - tree8_levels = tree8_count_levels (idh.idh_files); - argc -= optind; argv += optind; if (argc < 1) @@ -158,6 +147,22 @@ main (int argc, char **argv) usage (); } + /* Look for the ID database up the tree */ + idh.idh_file_name = locate_id_file_name (idh.idh_file_name); + if (idh.idh_file_name == 0) + error (1, errno, _("can't locate `ID'")); + + init_idh_obstacks (&idh); + init_idh_tables (&idh); + + cw_dlink = get_current_dir_link (); + + /* Determine absolute name of the directory name to which database + constituent files are relative. */ + members_0 = read_id_file (idh.idh_file_name, &idh); + bits_vec_size = (idh.idh_files + 7) / 4; /* more than enough */ + tree8_levels = tree8_count_levels (idh.idh_files); + index_1 = get_file_index ((argc--, *argv++)); if (argc) index_2 = get_file_index ((argc--, *argv++)); @@ -168,16 +173,25 @@ main (int argc, char **argv) hits_buf = xmalloc (idh.idh_buf_size); fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET); { + int count = 0; int i; + int separator = (isatty (STDOUT_FILENO) ? ' ' : '\n'); + for (i = 0; i < idh.idh_tokens; i++) { unsigned char const *hits; - + gets_past_00 (hits_buf, idh.idh_FILE); - hits = tok_hits_addr (hits_buf); + hits = token_hits_addr (hits_buf); if (is_hit (hits, index_1) && (index_2 < 0 || is_hit (hits, index_2))) - printf ("%s\n", tok_string (hits_buf)); + { + fputs (token_string (hits_buf), stdout); + putchar (separator); + count++; + } } + if (count && separator == ' ') + putchar ('\n'); } return 0; @@ -191,11 +205,11 @@ get_file_index (char *file_name) struct file_link *fn_flink = 0; int has_slash = (strchr (file_name, '/') != 0); int file_name_length = strlen (file_name); - int index = -1; + int idx = -1; if (strstr (file_name, "./")) fn_flink = parse_file_name (file_name, cw_dlink); - + for (members = members_0; members < end; members++) { struct file_link *flink = *members; @@ -206,26 +220,26 @@ get_file_index (char *file_name) } else if (has_slash) { - char buf[PATH_MAX]; + char *file_name = ALLOCA (char, PATH_MAX); int member_length; - maybe_relative_path (buf, flink, cw_dlink); - member_length = strlen (buf); + maybe_relative_file_name (file_name, flink, cw_dlink); + member_length = strlen (file_name); if (file_name_length > member_length - || !strequ (&buf[member_length - file_name_length], file_name)) + || !strequ (&file_name[member_length - file_name_length], file_name)) continue; } else if (!strequ (flink->fl_name, file_name)) continue; - if (index >= 0) + if (idx >= 0) { error (0, 0, _("`%s' is ambiguous"), file_name); - return; + return -1; } - index = members - members_0; + idx = members - members_0; } - if (index < 0) + if (idx < 0) error (0, 0, _("`%s' not found"), file_name); - return index; + return idx; } int @@ -1,3 +1,3 @@ -#!/bin/sh +#! /bin/sh -lid -E "$@" +exec lid -R grep "$@" @@ -1,5 +1,6 @@ /* lid.c -- primary query interface for mkid database Copyright (C) 1986, 1995, 1996 Free Software Foundation, Inc. + Written by Greg McGary <gkm@gnu.ai.mit.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,95 +16,131 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <stdlib.h> -#include <unistd.h> +#include <config.h> #include <stdio.h> -#include <string.h> #include <ctype.h> +#include "xstdlib.h" #include <signal.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <assert.h> -#include <limits.h> +#include <getopt.h> +#include "xstring.h" +#include "xunistd.h" +#include "xnls.h" +#include "xmalloc.h" +#include "idfile.h" +#include "xstring.h" +#include "error.h" +#include "pathmax.h" +#include "xalloca.h" +#if HAVE_LIMITS_H +# include <limits.h> +#endif #if WITH_REGEX # include <regex.h> #else # include <rx.h> #endif -#include <config.h> -#include <getopt.h> -#include "system.h" -#include "alloc.h" -#include "idfile.h" -#include "token.h" -#include "bitops.h" -#include "strxtra.h" -#include "misc.h" -#include "filenames.h" -#include "error.h" -#include "pathmax.h" - typedef void (*report_func_t) __P((char const *name, struct file_link **flinkv)); typedef int (*query_func_t) __P((char const *arg, report_func_t)); -unsigned char *tree8_to_bits __P((unsigned char *bits_vec, unsigned char const *hits_tree8)); -void tree8_to_bits_1 __P((unsigned char **bits_vec, unsigned char const **hits_tree8, int level)); -struct file_link **tree8_to_flinkv __P((unsigned char const *hits_tree8)); -struct file_link **bits_to_flinkv __P((unsigned char const *bits_vec)); +enum delimiter_style +{ + ds_bogus, + ds_contextual, + ds_word, + ds_substring +}; + +enum pattern_style +{ + ps_bogus, + ps_contextual, + ps_literal, + ps_regexp +}; + +enum key_style +{ + ks_bogus, + ks_none, + ks_token, + ks_pattern +}; + +enum result_style +{ + rs_bogus, + rs_none, + rs_filenames, + rs_grep, + rs_edit +}; + +enum radix +{ + radix_oct = 1, + radix_dec = 2, + radix_hex = 4, + radix_all = radix_dec | radix_oct | radix_hex +}; void usage __P((void)); static void help_me __P((void)); -int common_prefix_suffix __P((struct file_link const *flink_1, struct file_link const *flink_2)); -int member_file_index_qsort_compare __P((void const *x, void const *y)); -void look_id __P((char const *name, struct file_link **flinkv)); -void grep_id __P((char const *name, struct file_link **flinkv)); -void edit_id __P((char const *name, struct file_link **flinkv)); +void lower_caseify __P((char *str)); +enum key_style parse_key_style __P((char const *arg)); +enum result_style parse_result_style __P((char const *arg)); +query_func_t get_query_func __P((char *pattern)); +report_func_t get_report_func __P((void)); +void report_filenames __P((char const *name, struct file_link **flinkv)); +void report_grep __P((char const *name, struct file_link **flinkv)); +void report_edit __P((char const *name, struct file_link **flinkv)); +void report_nothing __P((char const *name, struct file_link **flinkv)); int vector_cardinality __P((void *vector)); -int skip_to_argv __P((struct file_link **flinkv)); -int query_plain __P((char const *arg, report_func_t report_function)); -int query_anchor __P((char const *arg, report_func_t report_function)); -int query_regexp __P((char const *arg, report_func_t report_function)); -int query_number __P((char const *arg, report_func_t report_function)); -int query_non_unique __P((unsigned int, report_func_t report_function)); -int query_apropos __P((char const *arg, report_func_t report_function)); +int search_flinkv __P((struct file_link **flinkv)); +int query_literal_word __P((char const *pattern, report_func_t report_func)); +int query_literal_prefix __P((char const *pattern, report_func_t report_func)); +int query_regexp __P((char const *pattern_0, report_func_t report_func)); +char const *maybe_add_word_delimiters __P((char const *pattern_0)); +int query_number __P((char const *pattern, report_func_t report_func)); +int query_ambiguous_prefix __P((unsigned int, report_func_t report_func)); +int query_literal_substring __P((char const *pattern, report_func_t report_func)); void parse_frequency_arg __P((char const *arg)); -int frequency_wanted __P((char const *tok)); -char const *strcpos __P((char const *s1, char const *s2)); -char const *file_regexp __P((char const *name0, char const *left_delimit, char const *right_delimit)); -off_t query_token __P((char const *token)); +int desired_frequency __P((char const *tok)); +char *strcasestr __P((char const *s1, char const *s2)); +char const *file_regexp __P((char const *name_0, char const *left_delimit, char const *right_delimit)); +off_t query_binary_search __P((char const *token)); int is_regexp __P((char *name)); +int has_left_delimiter __P((char const *pattern)); +int has_right_delimiter __P((char const *pattern)); int file_name_wildcard __P((char const *re, char const *fn)); -int word_match __P((char const *name0, char const *line)); -int get_radix __P((char const *name)); -int stoi __P((char const *name)); -int otoi __P((char const *name)); -int dtoi __P((char const *name)); -int xtoi __P((char const *name)); +int word_match __P((char const *name_0, char const *line)); +int get_radix __P((char const *str)); +int is_number __P((char const *str)); +int stoi __P((char const *str)); +int otoi __P((char const *str)); +int dtoi __P((char const *str)); +int xtoi __P((char const *str)); +unsigned char *tree8_to_bits __P((unsigned char *bits_vec, unsigned char const *hits_tree8)); +void tree8_to_bits_1 __P((unsigned char **bits_vec, unsigned char const **hits_tree8, int level)); +struct file_link **tree8_to_flinkv __P((unsigned char const *hits_tree8)); +struct file_link **bits_to_flinkv __P((unsigned char const *bits_vec)); + +#if HAVE_TERMIOS_H || HAVE_TERMIO_H || HAVE_SGTTY_H void savetty __P((void)); void restoretty __P((void)); void linetty __P((void)); void chartty __P((void)); - -enum radix { - radix_oct = 1, - radix_dec = 2, - radix_hex = 4, - radix_all = radix_dec | radix_oct | radix_hex -}; +#endif #define TOLOWER(c) (isupper (c) ? tolower (c) : (c)) #define IS_ALNUM(c) (isalnum (c) || (c) == '_') -#ifndef BRACE_NOTATION_DEFAULT -#define BRACE_NOTATION_DEFAULT 1 -#endif - /* Sorry about all the globals, but it's really cleaner this way. */ -int merging; -int file_name_regexp = 0; char anchor_dir[BUFSIZ]; int tree8_levels; unsigned int bits_vec_size; @@ -128,44 +165,42 @@ static int show_version; int radix_flag = radix_all; -/* If nonzero, don't print the name of the matched identifier. */ +/* If nonzero, ignore differences in alphabetic case while matching. */ + +int ignore_case_flag = 0; -int no_id_flag = 0; +/* How will patterns will be delimited? */ -/* If nonzero, merge multiple look_id regexp output lines into a - single line. */ +enum delimiter_style delimiter_style = ds_contextual; -int merge_flag = 0; +/* How will patterns be interpreted? */ -/* If nonzero, ignore differences in alphabetic case while matching. */ +enum pattern_style pattern_style = ps_contextual; -int ignore_case_flag = 0; +/* How will keys be presented? */ + +enum key_style key_style = ks_token; + +/* How will query results be presented? */ + +enum result_style result_style = rs_filenames; -/* If nonzero, print file names in abbreviated fashion using the - shell's brace notation. */ +/* How shall we separate file names when result_style == rs_filenames? */ -int brace_notation_flag = BRACE_NOTATION_DEFAULT; +enum separator_style separator_style = ss_contextual; /* If non-zero, list identifiers that are are non-unique within this number of leading characters. */ unsigned int ambiguous_prefix_length = 0; -/* The file name of the ID database. */ - -char const *id_file_name; - /* The style of report. */ -report_func_t report_function = look_id; +report_func_t report_function; /* The style of query. */ -query_func_t query_func; - -/* The style of query explicitly set by user from the command-line. */ - -query_func_t forced_query_func; +query_func_t query_function; /* Lower and upper bounds on occurrence frequency. */ @@ -180,18 +215,17 @@ static struct option const long_options[] = { "file", required_argument, 0, 'f' }, { "frequency", required_argument, 0, 'F' }, { "ambiguous", required_argument, 0, 'a' }, - { "grep", no_argument, 0, 'G' }, - { "apropos", no_argument, 0, 'A' }, - { "edit", no_argument, 0, 'E' }, - { "regexp", no_argument, 0, 'e' }, - { "braces", no_argument, 0, 'b' }, - { "merge", no_argument, 0, 'm' }, + { "key", required_argument, 0, 'k' }, + { "result", required_argument, 0, 'R' }, + { "separator", required_argument, 0, 'S' }, { "ignore-case", no_argument, 0, 'i' }, + { "literal", no_argument, 0, 'l' }, + { "regexp", no_argument, 0, 'r' }, { "word", no_argument, 0, 'w' }, + { "substring", no_argument, 0, 's' }, { "hex", no_argument, 0, 'x' }, { "decimal", no_argument, 0, 'd' }, { "octal", no_argument, 0, 'o' }, - { "no-id", no_argument, 0, 'n' }, { "help", no_argument, &show_help, 1 }, { "version", no_argument, &show_version, 1 }, { 0 } @@ -209,41 +243,46 @@ static void help_me (void) { printf (_("\ -Usage: %s [OPTION]... PATTERN...\n"), - program_name); +Usage: %s [OPTION]... PATTERN...\n\ +"), program_name); + printf (_("\ Query ID database and report results.\n\ By default, output consists of multiple lines, each line containing the\n\ matched identifier followed by the list of file names in which it occurs.\n\ \n\ - -f, --file=FILE file name of ID database\n\ - -G, --grep show every line where the matched identifier occurs\n\ - -E, --edit edit every file where the matched identifier occurs\n\ - -m, --merge output a multi-line regexp match as a single line\n\ - -n, --no-id print file names only - omit the identifier\n\ - -b, --braces toggle shell brace-notation for output file names\n\ + -f, --file=FILE file name of ID database\n\ \n\ -If PATTERN contains regular expression metacharacters, it is interpreted\n\ -as a regular expression. Otherwise, PATTERN is interpreted as a literal\n\ -word.\n\ + -i, --ignore-case match PATTERN case insensitively\n\ + -l, --literal match PATTERN as a literal string\n\ + -r, --regexp match PATTERN as a regular expression\n\ + -w, --word match PATTERN as a delimited word\n\ + -s, --substring match PATTERN as a substring\n\ + Note: If PATTERN contains extended regular expression meta-\n\ + characters, it is interpreted as a regular expression substring.\n\ + Otherwise, PATTERN is interpreted as a literal word.\n\ \n\ - -e, --regexp match PATTERN as a regular expression substring\n\ - -w, --word match PATTERN as a word\n\ - -i, --ignore-case match PATTERN case insinsitively\n\ - -A, --apropos match PATTERN as a case-insensitive substring\n\ + -k, --key=STYLE STYLE is one of `token', `pattern' or `none'\n\ + -R, --result=STYLE STYLE is one of `filenames', `grep', `edit' or `none'\n\ + -S, --separator=STYLE STYLE is one of `braces', `space' or `newline' and\n\ + only applies to file names when `--result=filenames'\n\ + The above STYLE options control how query results are presented.\n\ + Defaults are --key=token --result=filenames --separator=%s\n\ \n\ - -F, --frequency=FREQ find identifiers that occur FREQ times, where FREQ\n\ - is a range expressed as `N..M'. N omitted defaults\n\ - to 1, M omitted defaults to MAX_USHRT.\n\ - -a, --ambiguous=LEN find identifiers whose names are ambiguous for LEN chars\n\ + -F, --frequency=FREQ find tokens that occur FREQ times, where FREQ\n\ + is a range expressed as `N..M'. If N is omitted, it\n\ + defaults to 1, if M is omitted it defaults to MAX_USHRT\n\ + -a, --ambiguous=LEN find tokens whose names are ambiguous for LEN chars\n\ \n\ - -x, --hex only find numbers expressed as hexadecimal\n\ - -d, --decimal only find numbers expressed as decimal\n\ - -o, --octal only find numbers expressed as octal\n\ + -x, --hex only find numbers expressed as hexadecimal\n\ + -d, --decimal only find numbers expressed as decimal\n\ + -o, --octal only find numbers expressed as octal\n\ + By default, searches match numbers of any radix.\n\ \n\ - --help display this help and exit\n\ - --version output version information and exit\n\ -")); + --help display this help and exit\n\ + --version output version information and exit\n\ +"), + (separator_style == ss_braces ? _("braces") : _("space"))); exit (0); } @@ -251,9 +290,18 @@ int main (int argc, char **argv) { program_name = argv[0]; + idh.idh_file_name = 0; + + /* Set locale according to user's wishes. */ + setlocale (LC_ALL, ""); + + /* Tell program which translations to use and where to find. */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + for (;;) { - int optc = getopt_long (argc, argv, "f:F:a:GAEebmiwxdon", + int optc = getopt_long (argc, argv, "f:F:a:k:R:S:ilrwsxdo", long_options, (int *) 0); if (optc < 0) break; @@ -263,7 +311,7 @@ main (int argc, char **argv) break; case 'f': - id_file_name = optarg; + idh.idh_file_name = optarg; break; case 'F': @@ -274,38 +322,41 @@ main (int argc, char **argv) ambiguous_prefix_length = stoi (optarg); break; - case 'G': - report_function = grep_id; + case 'k': + key_style = parse_key_style (optarg); break; - case 'A': - forced_query_func = query_apropos; - report_function = look_id; + case 'R': + result_style = parse_result_style (optarg); break; - - case 'E': - report_function = edit_id; + + case 'S': + separator_style = parse_separator_style (optarg); break; - case 'e': - forced_query_func = query_regexp; - file_name_regexp = 1; + case 'i': + ignore_case_flag = REG_ICASE; break; - case 'b': - brace_notation_flag = !brace_notation_flag; + case 'l': + pattern_style = ps_literal; break; - case 'm': - merge_flag = 1; + case 'r': + pattern_style = ps_regexp; break; - case 'i': - ignore_case_flag = REG_ICASE; + case 'e': + pattern_style = ps_regexp; + error (0, 0, _("notice: use of `-e' is deprecated, use `-r' instead")); break; case 'w': - forced_query_func = query_plain; + delimiter_style = ds_word; + break; + + case 's': + delimiter_style = ds_substring; break; case 'x': @@ -320,10 +371,6 @@ main (int argc, char **argv) radix_flag |= radix_oct; break; - case 'n': - no_id_flag = 1; - break; - default: usage (); } @@ -338,11 +385,30 @@ main (int argc, char **argv) if (show_help) help_me (); + if (separator_style == ss_contextual) + { + if (isatty (STDOUT_FILENO)) + separator_style = DEFAULT_SEPARATOR_STYLE; + else if (key_style == ks_none) + separator_style = ss_newline; + else + separator_style = ss_space; + } + + argc -= optind; + argv += optind; + if (argc == 0) + { + static char *dot = (char *) "."; + argc = 1; + argv = ˙ + } + /* Look for the ID database up the tree */ - id_file_name = look_up (id_file_name); - if (id_file_name == 0) + idh.idh_file_name = locate_id_file_name (idh.idh_file_name); + if (idh.idh_file_name == 0) error (1, errno, _("can't locate `ID'")); - + init_idh_obstacks (&idh); init_idh_tables (&idh); @@ -350,138 +416,131 @@ main (int argc, char **argv) /* Determine absolute name of the directory name to which database constituent files are relative. */ - members_0 = read_id_file (id_file_name, &idh); + members_0 = read_id_file (idh.idh_file_name, &idh); bits_vec_size = (idh.idh_files + 7) / 4; /* more than enough */ tree8_levels = tree8_count_levels (idh.idh_files); - argc -= optind; - argv += optind; - if (argc == 0) + hits_buf_1 = MALLOC (char, idh.idh_buf_size); + hits_buf_2 = MALLOC (char, idh.idh_buf_size); + bits_vec = MALLOC (unsigned char, bits_vec_size); + + report_function = get_report_func (); + if (ambiguous_prefix_length) { - argc++; - *(char const **)--argv = ".*"; + if (!query_ambiguous_prefix (ambiguous_prefix_length, report_function)) + fprintf (stderr, _("All identifiers are non-ambiguous within the first %d characters\n"), + ambiguous_prefix_length); } - - while (argc) + else { - long val = -1; - char *arg = (argc--, *argv++); - - if (forced_query_func) - query_func = forced_query_func; - else if (get_radix (arg) && (val = stoi (arg)) >= 0) - query_func = query_number; - else if (is_regexp (arg)) - query_func = query_regexp; - else if (arg[0] == '^') - query_func = query_anchor; - else - query_func = query_plain; - - if ((report_function == look_id && !merge_flag) - || (query_func == query_number - && val > 7 - && radix_flag != radix_dec - && radix_flag != radix_oct - && radix_flag != radix_hex)) - merging = 0; - else - merging = 1; - - hits_buf_1 = xmalloc (idh.idh_buf_size); - hits_buf_2 = xmalloc (idh.idh_buf_size); - bits_vec = MALLOC (unsigned char, bits_vec_size); - - if (ambiguous_prefix_length) - { - if (!query_non_unique (ambiguous_prefix_length, report_function)) - fprintf (stderr, _("All identifiers are non-ambiguous within the first %d characters\n"), - ambiguous_prefix_length); - exit (0); - } - else if (!(*query_func) (arg, report_function)) + while (argc) { - fprintf (stderr, _("%s: not found\n"), arg); - continue; + char *pattern = (argc--, *argv++); + if (ignore_case_flag) + lower_caseify (pattern); + query_function = get_query_func (pattern); + (*query_function) (pattern, report_function); } } + fclose (idh.idh_FILE); exit (0); } -/* common_prefix_suffix returns non-zero if two file names have a - fully common directory prefix and a common suffix (i.e., they're - eligible for coalescing with brace notation. */ +void +lower_caseify (char *str) +{ + while (*str) + { + *str = TOLOWER (*str); + str++; + } +} -int -common_prefix_suffix (struct file_link const *flink_1, struct file_link const *flink_2) +enum key_style +parse_key_style (char const *arg) { - return (flink_1->fl_parent == flink_2->fl_parent - && strequ (suff_name (flink_1->fl_name), suff_name (flink_2->fl_name))); + MAYBE_RETURN_PREFIX_MATCH (arg, "none", ks_none); + MAYBE_RETURN_PREFIX_MATCH (arg, "token", ks_token); + MAYBE_RETURN_PREFIX_MATCH (arg, "pattern", ks_pattern); + error (0, 0, _("invalid `--key' style: `%s'"), arg); + usage (); + return ks_bogus; } -void -look_id (char const *name, struct file_link **flinkv) +enum result_style +parse_result_style (char const *arg) { - struct file_link const *arg; - struct file_link const *dlink; - int brace_is_open = 0; + MAYBE_RETURN_PREFIX_MATCH (arg, "none", rs_none); + MAYBE_RETURN_PREFIX_MATCH (arg, "filenames", rs_filenames); + MAYBE_RETURN_PREFIX_MATCH (arg, "grep", rs_grep); + MAYBE_RETURN_PREFIX_MATCH (arg, "edit", rs_edit); + error (0, 0, _("invalid `--result' style: `%s'"), arg); + usage (); + return rs_bogus; +} - if (!no_id_flag) - printf ("%-14s ", name); - while (*flinkv) +query_func_t +get_query_func (char *pattern) +{ + switch (pattern_style) { - arg = *flinkv++; - if (*flinkv && brace_notation_flag - && common_prefix_suffix (arg, *flinkv)) - { - if (brace_is_open) - printf (",%s", root_name (arg->fl_name)); - else - { - dlink = arg->fl_parent; - if (dlink && dlink != cw_dlink) - { - char buf[PATH_MAX]; - maybe_relative_path (buf, dlink, cw_dlink); - fputs (buf, stdout); - putchar ('/'); - } - printf ("{%s", root_name (arg->fl_name)); - } - brace_is_open = 1; - } + case ps_regexp: + return query_regexp; + + case ps_literal: + if (delimiter_style == ds_substring) + return query_literal_substring; else - { - if (brace_is_open) - printf (",%s}%s", root_name (arg->fl_name), suff_name (arg->fl_name)); - else - { - char buf[PATH_MAX]; - maybe_relative_path (buf, arg, cw_dlink); - fputs (buf, stdout); - } - brace_is_open = 0; - if (*flinkv) - putchar (' '); - } + return query_literal_word; + + default: + if (is_regexp (pattern)) + return query_regexp; + else if (has_left_delimiter (pattern)) + return query_literal_prefix; + else if (delimiter_style == ds_substring) + return query_literal_substring; + else if (is_number (pattern)) + return query_number; + else if (delimiter_style == ds_word) + return query_literal_word; + else + return query_literal_word; } - putchar ('\n'); } -/* FIXME: use regcomp regexec */ +report_func_t +get_report_func (void) +{ + switch (result_style) + { + case rs_filenames: return report_filenames; + case rs_grep: return report_grep; + case rs_edit: return report_edit; + default: return report_nothing; + } +} + +void +report_filenames (char const *name, struct file_link **flinkv) +{ + if (name && key_style != ks_none) + printf ("%-14s ", name); + print_filenames (flinkv, separator_style); +} void -grep_id (char const *name, struct file_link **flinkv) +report_grep (char const *name, struct file_link **flinkv) { char line[BUFSIZ]; char const *pattern = 0; regex_t compiled; int line_number; - if (merging) + if (key_style == ks_pattern) { - pattern = file_regexp (name, "[^a-zA-Z0-9_À-ÿ]_*", "[^a-zA-Z0-9_À-ÿ]"); + pattern = file_regexp (name, "[^a-zA-Z0-9_\300-\377]_*", "[^a-zA-Z0-9_\300-\377]"); if (pattern) { int regcomp_errno = regcomp (&compiled, pattern, @@ -498,10 +557,10 @@ grep_id (char const *name, struct file_link **flinkv) line[0] = ' '; /* sentry */ while (*flinkv) { + char *file_name = ALLOCA (char, PATH_MAX); FILE *gid_FILE; - char file_name[PATH_MAX]; - maybe_relative_path (file_name, *flinkv++, cw_dlink); + maybe_relative_file_name (file_name, *flinkv++, cw_dlink); gid_FILE = fopen (file_name, "r"); if (gid_FILE == 0) error (0, errno, "can't open `%s'", file_name); @@ -520,20 +579,20 @@ grep_id (char const *name, struct file_link **flinkv) } else if (!word_match (name, line)) continue; - printf ("%s:%d: %s", file_name, line_number, &line[1]); + printf ("%s:%d:%s", file_name, line_number, &line[1]); } fclose (gid_FILE); } } void -edit_id (char const *name, struct file_link **flinkv) +report_edit (char const *name, struct file_link **flinkv) { static char const *editor; static char const *eid_arg; static char const *eid_right_del; static char const *eid_left_del; - char re_buffer[BUFSIZ]; + char regexp_buf[BUFSIZ]; char ed_arg_buffer[BUFSIZ]; char const *pattern; int c; @@ -541,9 +600,13 @@ edit_id (char const *name, struct file_link **flinkv) if (editor == 0) { - editor = getenv ("EDITOR"); + editor = getenv ("VISUAL"); if (editor == 0) - editor = "vi"; + { + editor = getenv ("EDITOR"); + if (editor == 0) + editor = "vi"; + } } if (eid_arg == 0) @@ -563,55 +626,53 @@ edit_id (char const *name, struct file_link **flinkv) eid_right_del = (using_vi ? "\\>" : ""); } - look_id (name, flinkv); + report_filenames (name, flinkv); savetty (); for (;;) { - /* FIXME: i18n */ - printf (_("Edit? [y1-9^S/nq] ")); + /* FIXME: i18n of responses */ + printf (_("edit? [y1-9^S/nq] ")); fflush (stdout); chartty (); c = (getchar () & 0177); restoretty (); switch (TOLOWER (c)) { - case '/': - case ('s' & 037): + case '/': case ('s' & 037): putchar ('/'); - skip = skip_to_flinkv (flinkv); + skip = search_flinkv (flinkv); if (skip < 0) continue; flinkv += skip; goto editit; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': putchar (c); skip = c - '0'; break; + case 'y': putchar (c); skip = 0; break; + case '\n': case '\r': putchar ('y'); skip = 0; break; + case 'q': putchar (c); putchar ('\n'); exit (0); + case 'n': putchar (c); putchar ('\n'); return; + default: putchar (c); putchar ('\n'); @@ -626,14 +687,14 @@ edit_id (char const *name, struct file_link **flinkv) } editit: - if (merging) + if (key_style == ks_pattern) pattern = file_regexp (name, eid_left_del, eid_right_del); else pattern = 0; if (pattern == 0) { - pattern = re_buffer; - sprintf (re_buffer, "%s%s%s", eid_left_del, name, eid_right_del); + pattern = regexp_buf; + sprintf (regexp_buf, "%s%s%s", eid_left_del, name, eid_right_del); } switch (fork ()) @@ -647,11 +708,7 @@ editit: char **argv_0 = MALLOC (char *, 3 + vector_cardinality (flinkv)); char **argv = argv_0 + 2; while (*flinkv) - { - char buf[PATH_MAX]; - maybe_relative_path (buf, *flinkv++, cw_dlink); - *argv++ = strdup (buf); - } + *argv++ = maybe_relative_file_name (0, *flinkv++, cw_dlink); *argv = 0; argv = argv_0 + 1; if (eid_arg) @@ -659,7 +716,7 @@ editit: sprintf (ed_arg_buffer, eid_arg, pattern); *--argv = ed_arg_buffer; } - *(char const **)argv = editor; + *(char const **) argv = editor; execvp (editor, argv); error (0, errno, _("can't exec `%s'"), editor); } @@ -679,10 +736,17 @@ editit: } } +void +report_nothing (char const *name, struct file_link **flinkv) +{ + if (key_style != ks_none) + puts (name); +} + int vector_cardinality (void *vector) { - void **v = (void **)vector; + void **v = (void **) vector; int count = 0; while (*v++) @@ -691,7 +755,7 @@ vector_cardinality (void *vector) } int -skip_to_flinkv (struct file_link **flinkv) +search_flinkv (struct file_link **flinkv) { char pattern[BUFSIZ]; unsigned int count; @@ -701,66 +765,68 @@ skip_to_flinkv (struct file_link **flinkv) for (count = 0; *flinkv; count++, flinkv++) { - char buf[PATH_MAX]; - maybe_relative_path (buf, *flinkv, cw_dlink); - if (strcpos (buf, pattern)) + char *file_name = ALLOCA (char, PATH_MAX); + maybe_relative_file_name (file_name, *flinkv, cw_dlink); + if (strcasestr (file_name, pattern)) return count; } return -1; } int -query_plain (char const *arg, report_func_t report_function) +query_literal_word (char const *arg, report_func_t report_func) { - if (query_token (arg) == 0) + if (query_binary_search (arg) == 0) return 0; gets_past_00 (hits_buf_1, idh.idh_FILE); assert (*hits_buf_1); - if (!frequency_wanted (hits_buf_1)) + if (!desired_frequency (hits_buf_1)) return 0; - (*report_function) (hits_buf_1, tree8_to_flinkv (tok_hits_addr (hits_buf_1))); + (*report_func) (hits_buf_1, tree8_to_flinkv (token_hits_addr (hits_buf_1))); return 1; } int -query_anchor (char const *arg, report_func_t report_function) +query_literal_prefix (char const *arg, report_func_t report_func) { int count; unsigned int length; - if (query_token (++arg) == 0) + if (query_binary_search (++arg) == 0) return 0; length = strlen (arg); count = 0; - if (merging) + if (key_style != ks_token) memset (bits_vec, 0, bits_vec_size); while (gets_past_00 (hits_buf_1, idh.idh_FILE) > 0) { assert (*hits_buf_1); - if (!frequency_wanted (hits_buf_1)) + if (!desired_frequency (hits_buf_1)) continue; if (!strnequ (arg, hits_buf_1, length)) break; - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (hits_buf_1)); + if (key_style == ks_token) + (*report_func) (hits_buf_1, tree8_to_flinkv (token_hits_addr (hits_buf_1))); else - (*report_function) (hits_buf_1, tree8_to_flinkv (tok_hits_addr (hits_buf_1))); + tree8_to_bits (bits_vec, token_hits_addr (hits_buf_1)); count++; } - if (merging && count) - (*report_function) (--arg, bits_to_flinkv (bits_vec)); + if (key_style != ks_token && count) + (*report_func) (--arg, bits_to_flinkv (bits_vec)); return count; } int -query_regexp (char const *pattern, report_func_t report_function) +query_regexp (char const *pattern_0, report_func_t report_func) { int count; regex_t compiled; int regcomp_errno; + char const *pattern = pattern_0; + pattern = maybe_add_word_delimiters (pattern); regcomp_errno = regcomp (&compiled, pattern, ignore_case_flag | REG_EXTENDED); if (regcomp_errno) @@ -772,33 +838,66 @@ query_regexp (char const *pattern, report_func_t report_function) fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET); count = 0; - if (merging) + if (key_style != ks_token) memset (bits_vec, 0, bits_vec_size); while (gets_past_00 (hits_buf_1, idh.idh_FILE) > 0) { int regexec_errno; assert (*hits_buf_1); - if (!frequency_wanted (hits_buf_1)) + if (!desired_frequency (hits_buf_1)) continue; regexec_errno = regexec (&compiled, hits_buf_1, 0, 0, 0); if (regexec_errno == REG_ESPACE) error (0, 0, _("can't match regular-expression: memory exhausted")); else if (regexec_errno) continue; - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (hits_buf_1)); + if (key_style == ks_token) + (*report_func) (hits_buf_1, tree8_to_flinkv (token_hits_addr (hits_buf_1))); else - (*report_function) (hits_buf_1, tree8_to_flinkv (tok_hits_addr (hits_buf_1))); + tree8_to_bits (bits_vec, token_hits_addr (hits_buf_1)); count++; } - if (merging && count) - (*report_function) (pattern, bits_to_flinkv (bits_vec)); + if (key_style != ks_token && count) + (*report_func) (pattern, bits_to_flinkv (bits_vec)); + + if (pattern != pattern_0) + free ((char *) pattern); return count; } +char const * +maybe_add_word_delimiters (char const *pattern_0) +{ + if (delimiter_style != ds_word) + return pattern_0; + else + { + int length = strlen (pattern_0); + int has_left = has_left_delimiter (pattern_0); + int has_right = has_right_delimiter (&pattern_0[length]); + if (has_left && has_right) + return pattern_0; + else + { + char *pattern = MALLOC (char, length + 4); + if (has_left) + strcpy (pattern, pattern_0); + else + { + length += 2; + strcpy (pattern, "\\<"); + strcpy (pattern + 2, pattern_0); + } + if (!has_right) + strcpy (pattern + length, "\\>"); + return pattern; + } + } +} + int -query_number (char const *arg, report_func_t report_function) +query_number (char const *arg, report_func_t report_func) { int count; int radix; @@ -809,7 +908,7 @@ query_number (char const *arg, report_func_t report_function) fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET); count = 0; - if (merging) + if (key_style != ks_token) memset (bits_vec, 0, bits_vec_size); while (gets_past_00 (hits_buf_1, idh.idh_FILE) > 0) { @@ -827,14 +926,14 @@ query_number (char const *arg, report_func_t report_function) if (!((radix_flag ? radix_flag : radix) & get_radix (hits_buf_1)) || stoi (hits_buf_1) != val) continue; - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (hits_buf_1)); + if (key_style == ks_token) + (*report_func) (hits_buf_1, tree8_to_flinkv (token_hits_addr (hits_buf_1))); else - (*report_function) (hits_buf_1, tree8_to_flinkv (tok_hits_addr (hits_buf_1))); + tree8_to_bits (bits_vec, token_hits_addr (hits_buf_1)); count++; } - if (merging && count) - (*report_function) (arg, bits_to_flinkv (bits_vec)); + if (key_style != ks_token && count) + (*report_func) (arg, bits_to_flinkv (bits_vec)); return count; } @@ -843,7 +942,7 @@ query_number (char const *arg, report_func_t report_function) characters. */ int -query_non_unique (unsigned int limit, report_func_t report_function) +query_ambiguous_prefix (unsigned int limit, report_func_t report_func) { char *old = hits_buf_1; char *new = hits_buf_2; @@ -861,68 +960,70 @@ query_non_unique (unsigned int limit, report_func_t report_function) while (gets_past_00 (old, idh.idh_FILE) > 0) { char *tmp; - if (!(tok_flags (old) & TOK_NAME)) + if (!(token_flags (old) & TOK_NAME)) continue; tmp = old; old = new; new = tmp; if (!strnequ (new, old, limit)) { - if (consecutive && merging) + if (consecutive && key_style != ks_token) { strncpy (&name[1], old, limit); - (*report_function) (name, bits_to_flinkv (bits_vec)); + (*report_func) (name, bits_to_flinkv (bits_vec)); } consecutive = 0; continue; } if (!consecutive++) { - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (old)); + if (key_style != ks_token) + tree8_to_bits (bits_vec, token_hits_addr (old)); else - (*report_function) (old, tree8_to_flinkv (tok_hits_addr (old))); + (*report_func) (old, tree8_to_flinkv (token_hits_addr (old))); count++; } - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (new)); + if (key_style == ks_token) + (*report_func) (new, tree8_to_flinkv (token_hits_addr (new))); else - (*report_function) (new, tree8_to_flinkv (tok_hits_addr (new))); + tree8_to_bits (bits_vec, token_hits_addr (new)); count++; } - if (consecutive && merging) + if (consecutive && key_style != ks_token) { strncpy (&name[1], new, limit); - (*report_function) (name, bits_to_flinkv (bits_vec)); + (*report_func) (name, bits_to_flinkv (bits_vec)); } return count; } int -query_apropos (char const *arg, report_func_t report_function) +query_literal_substring (char const *arg, report_func_t report_func) { int count; + char *(*strstr_func) __P((char const *, char const *)); fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET); count = 0; - if (merging) + if (key_style != ks_token) memset (bits_vec, 0, bits_vec_size); + strstr_func = (ignore_case_flag ? strcasestr : strstr); while (gets_past_00 (hits_buf_1, idh.idh_FILE) > 0) { assert (*hits_buf_1); - if (!frequency_wanted (hits_buf_1)) + if (!desired_frequency (hits_buf_1)) continue; - if (strcpos (hits_buf_1, arg) == 0) + if ((*strstr_func) (hits_buf_1, arg) == 0) continue; - if (merging) - tree8_to_bits (bits_vec, tok_hits_addr (hits_buf_1)); + if (key_style == ks_token) + (*report_func) (hits_buf_1, tree8_to_flinkv (token_hits_addr (hits_buf_1))); else - (*report_function) (hits_buf_1, tree8_to_flinkv (tok_hits_addr (hits_buf_1))); + tree8_to_bits (bits_vec, token_hits_addr (hits_buf_1)); count++; } - if (merging && count) - (*report_function) (arg, bits_to_flinkv (bits_vec)); + if (key_style != ks_token && count) + (*report_func) (arg, bits_to_flinkv (bits_vec)); return count; } @@ -955,17 +1056,17 @@ parse_frequency_arg (char const *arg) } int -frequency_wanted (char const *tok) +desired_frequency (char const *tok) { - unsigned int count = tok_count (tok); + unsigned int count = token_count (tok); return (frequency_low <= count && count <= frequency_high); } /* if string `s2' occurs in `s1', return a pointer to the first match. Ignore differences in alphabetic case. */ -char const * -strcpos (char const *s1, char const *s2) +char * +strcasestr (char const *s1, char const *s2) { char const *s1p; char const *s2p; @@ -974,7 +1075,7 @@ strcpos (char const *s1, char const *s2) for (s1last = &s1[strlen (s1) - strlen (s2)]; s1 <= s1last; s1++) for (s1p = s1, s2p = s2; TOLOWER (*s1p) == TOLOWER (*s2p); s1p++) if (*++s2p == '\0') - return s1; + return (char *) s1; return 0; } @@ -983,12 +1084,12 @@ strcpos (char const *s1, char const *s2) in files. */ char const * -file_regexp (char const *name0, char const *left_delimit, char const *right_delimit) +file_regexp (char const *name_0, char const *left_delimit, char const *right_delimit) { static char pat_buf[BUFSIZ]; - char *name = (char *) name0; + char *name = (char *) name_0; - if (query_func == query_number && merging) + if (query_function == query_number && key_style == ks_pattern) { sprintf (pat_buf, "%s0*[Xx]*0*%d[Ll]*%s", left_delimit, stoi (name), right_delimit); return pat_buf; @@ -998,7 +1099,7 @@ file_regexp (char const *name0, char const *left_delimit, char const *right_deli return 0; if (name[0] == '^') - name0++; + name_0++; else left_delimit = ""; while (*++name) @@ -1008,12 +1109,12 @@ file_regexp (char const *name0, char const *left_delimit, char const *right_deli else right_delimit = ""; - sprintf (pat_buf, "%s%s%s", left_delimit, name0, right_delimit); + sprintf (pat_buf, "%s%s%s", left_delimit, name_0, right_delimit); return pat_buf; } off_t -query_token (char const *token_0) +query_binary_search (char const *token_0) { off_t offset = 0; off_t start = idh.idh_tokens_offset - 2; @@ -1043,7 +1144,7 @@ query_token (char const *token_0) token++; incr++; } - if (c && !*token && query_func == query_anchor) + if (c && !*token && query_function == query_literal_prefix) anchor_offset = offset; order = *token - c; @@ -1075,6 +1176,8 @@ is_regexp (char *name) if (*name == '^') name++; + else if (strnequ (name, "\\<", 2)) + name += 2; while (*name) { if (*name == '\\') @@ -1083,7 +1186,7 @@ is_regexp (char *name) return 1; name++, backslash++; } - else if (strchr ("[]{}().*+^$", *name)) + else if (strchr ("[]().*+^$", *name)) return 1; name++; } @@ -1097,6 +1200,18 @@ is_regexp (char *name) return 0; } +int +has_left_delimiter (char const *pattern) +{ + return (*pattern == '^' || strnequ (pattern, "\\<", 2)); +} + +int +has_right_delimiter (char const *pattern) +{ + return (pattern[-1] == '$' || strequ (pattern - 2, "\\>")); +} + /* file_name_wildcard implements a simple pattern matcher that emulates the shell wild card capability. @@ -1160,7 +1275,7 @@ file_name_wildcard (char const *pattern, char const *fn) if (revset) for (i = 1; i < 256; ++i) set[i] = !set[i]; - if (!set[(int)*fn++]) + if (!set[(int) *fn++]) return 0; } else @@ -1177,9 +1292,9 @@ file_name_wildcard (char const *pattern, char const *fn) /* Does `name' occur in `line' delimited by non-alphanumerics?? */ int -word_match (char const *name0, char const *line) +word_match (char const *name_0, char const *line) { - char const *name = name0; + char const *name = name_0; for (;;) { @@ -1202,7 +1317,7 @@ word_match (char const *name0, char const *line) /* is this the end of `name', is there a word delimiter ?? */ if (*name == '\0' && !IS_ALNUM (*line)) return 1; - name = name0; + name = name_0; } } @@ -1212,34 +1327,48 @@ word_match (char const *name0, char const *line) 0, so return all possibilities. */ int -get_radix (char const *name) +get_radix (char const *str) { - if (!isdigit (*name)) + if (!isdigit (*str)) return 0; - if (*name != '0') + if (*str != '0') return radix_dec; - name++; - if (*name == 'x' || *name == 'X') + str++; + if (*str == 'x' || *str == 'X') return radix_hex; - while (*name && *name == '0') - name++; - return (*name ? radix_oct : (radix_oct | radix_dec)); + while (*str && *str == '0') + str++; + return (*str ? radix_oct : (radix_oct | radix_dec)); +} + +int +is_number (char const *str) +{ + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + str += 2; + str += strspn (str, "0123456789aAbBcCdDeEfF"); + } + else + str += strspn (str, "0123456789"); + str += strspn (str, "uUlL"); + return (*str == '\0'); } /* Convert an ascii string number to an integer. Determine the radix before converting. */ int -stoi (char const *name) +stoi (char const *str) { - switch (get_radix (name)) + switch (get_radix (str)) { case radix_dec: - return (dtoi (name)); + return (dtoi (str)); case radix_oct: - return (otoi (&name[1])); + return (otoi (&str[1])); case radix_hex: - return (xtoi (&name[2])); + return (xtoi (&str[2])); case radix_dec | radix_oct: return 0; default: @@ -1250,57 +1379,57 @@ stoi (char const *name) /* Convert an ascii octal number to an integer. */ int -otoi (char const *name) +otoi (char const *str) { int n = 0; - while (*name >= '0' && *name <= '7') + while (*str >= '0' && *str <= '7') { n *= 010; - n += *name++ - '0'; + n += *str++ - '0'; } - if (*name == 'l' || *name == 'L') - name++; - return (*name ? -1 : n); + while (*str && strchr ("uUlL", *str)) + str++; + return (*str ? -1 : n); } /* Convert an ascii decimal number to an integer. */ int -dtoi (char const *name) +dtoi (char const *str) { int n = 0; - while (isdigit (*name)) + while (isdigit (*str)) { n *= 10; - n += *name++ - '0'; + n += *str++ - '0'; } - if (*name == 'l' || *name == 'L') - name++; - return (*name ? -1 : n); + while (*str && strchr ("uUlL", *str)) + str++; + return (*str ? -1 : n); } /* Convert an ascii hex number to an integer. */ int -xtoi (char const *name) +xtoi (char const *str) { int n = 0; - while (isxdigit (*name)) + while (isxdigit (*str)) { n *= 0x10; - if (isdigit (*name)) - n += *name++ - '0'; - else if (islower (*name)) - n += 0xa + *name++ - 'a'; + if (isdigit (*str)) + n += *str++ - '0'; + else if (islower (*str)) + n += 0xa + *str++ - 'a'; else - n += 0xA + *name++ - 'A'; + n += 0xA + *str++ - 'A'; } - if (*name == 'l' || *name == 'L') - name++; - return (*name ? -1 : n); + while (*str && strchr ("uUlL", *str)) + str++; + return (*str ? -1 : n); } unsigned char * @@ -1419,22 +1548,10 @@ struct sgttyb savemode; #define SET_TTY_MODES(modes) stty (0, (modes)) # endif -void -savetty (void) -{ -# ifdef TIOCGETP - ioctl(0, TIOCGETP, &savemode); -# else - gtty(0, &savemode); -# endif - charmode = linemode = savemode; - - charmode.sg_flags &= ~ECHO; - charmode.sg_flags |= RAW; +# else /* not HAVE_SGTTY_H */ - linemode.sg_flags |= ECHO; - linemode.sg_flags &= ~RAW; -} +#define GET_TTY_MODES(modes) +#define SET_TTY_MODES(modes) # endif /* not HAVE_SGTTY_H */ # endif /* not HAVE_TERMIO_H */ @@ -1457,9 +1574,36 @@ savetty (void) linemode.c_cc[VEOL] = 0377; } -#endif +#else /* not (HAVE_TERMIOS_H || HAVE_TERMIO_H) */ -#if HAVE_TERMIOS_H || HAVE_TERMIO_H || HAVE_SGTTY_H +# if HAVE_SGTTY_H + +void +savetty (void) +{ +# ifdef TIOCGETP + ioctl(0, TIOCGETP, &savemode); +# else + gtty(0, &savemode); +# endif + charmode = linemode = savemode; + + charmode.sg_flags &= ~ECHO; + charmode.sg_flags |= RAW; + + linemode.sg_flags |= ECHO; + linemode.sg_flags &= ~RAW; +} + +# else /* not HAVE_SGTTY_H */ + +void +savetty (void) +{ +} + +# endif /* not HAVE_SGTTY_H */ +#endif /* not (HAVE_TERMIOS_H || HAVE_TERMIO_H) */ void restoretty (void) @@ -1478,5 +1622,3 @@ chartty (void) { SET_TTY_MODES (&charmode); } - -#endif @@ -1,5 +1,6 @@ /* mkid.c -- build an identifer database Copyright (C) 1986, 1995, 1996 Free Software Foundation, Inc. + Written by Greg McGary <gkm@gnu.ai.mit.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,32 +16,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <sys/types.h> -#include <sys/stat.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <limits.h> +#include <config.h> +#include "xstdlib.h" #include <assert.h> #include <stdio.h> -#include <string.h> -#include <ctype.h> #include <errno.h> #include <getopt.h> - -#include <config.h> -#include "system.h" +#include "xsysstat.h" +#include "xstddef.h" +#include "xunistd.h" +#include "xnls.h" #include "pathmax.h" -#include "strxtra.h" -#include "alloc.h" +#include "xstring.h" #include "idfile.h" -#include "token.h" -#include "bitops.h" -#include "misc.h" -#include "filenames.h" +#include "xmalloc.h" #include "hash.h" #include "scanners.h" #include "error.h" +#include "xalloca.h" +#if HAVE_LIMITS_H +# include <limits.h> +#endif struct summary { @@ -112,12 +108,11 @@ struct summary *summary_leaf; char const *program_name; -char *include_languages = 0; -char *exclude_languages = 0; char *lang_map_file_name = 0; int show_version = 0; int show_help = 0; struct idhead idh; +struct file_link *cw_dlink; void usage (void) @@ -132,9 +127,11 @@ static struct option const long_options[] = { "file", required_argument, 0, 'f' }, { "output", required_argument, 0, 'o' }, { "include", required_argument, 0, 'i' }, - { "exclude", required_argument, 0, 'r' }, - { "lang-arg", required_argument, 0, 'l' }, + { "exclude", required_argument, 0, 'x' }, + { "lang-option", required_argument, 0, 'l' }, { "lang-map", required_argument, 0, 'm' }, + { "default-lang", required_argument, 0, 'd' }, + { "prune", required_argument, 0, 'p' }, { "verbose", no_argument, 0, 'v' }, { "statistics", no_argument, 0, 's' }, { "help", no_argument, &show_help, 1 }, @@ -146,8 +143,8 @@ static void help_me (void) { printf (_("\ -Usage: %s [OPTION]... [FILE]...\n"), - program_name); +Usage: %s [OPTION]... [FILE]...\n\ +"), program_name); printf (_("\ Build an identifier database.\n\ @@ -155,16 +152,19 @@ Build an identifier database.\n\ -f, --file=OUTFILE synonym for --output\n\ -i, --include=LANGS include languages in LANGS (default: \"C C++ asm\")\n\ -x, --exclude=LANGS exclude languages in LANGS\n\ - -l, --lang-arg=LANG:ARG pass ARG as a default for LANG (see below)\n\ + -l, --lang-option=L:OPT pass OPT as a default for language L (see below)\n\ -m, --lang-map=MAPFILE use MAPFILE to map file names onto source language\n\ - -v, --verbose report progress and as files are scanned\n\ + -d, --default-lang=LANG make LANG the default source language\n\ + -p, --prune=NAMES exclude the named files and/or directories\n\ + -v, --verbose report per file statistics\n\ -s, --statistics report statistics at end of run\n\ \n\ --help display this help and exit\n\ --version output version information and exit\n\ \n\ FILE may be a file name, or a directory name to recursively search.\n\ -The `--include' and `--exclude' options are mutually-exclusive.\n\ +If no FILE is given, the current directory is searched by default.\n\ +Note that the `--include' and `--exclude' options are mutually-exclusive.\n\ \n\ The following arguments apply to the language-specific scanners:\n\ ")); @@ -172,9 +172,6 @@ The following arguments apply to the language-specific scanners:\n\ exit (0); } -#if !HAVE_DECL_SBRK -extern void *sbrk (); -#endif char const *heap_initial; char const *heap_after_walk; char const *heap_after_scan; @@ -183,10 +180,19 @@ int main (int argc, char **argv) { program_name = argv[0]; - idh.idh_file_name = ID_FILE_NAME; + heap_initial = (char const *) sbrk (0); + idh.idh_file_name = DEFAULT_ID_FILE_NAME; + + /* Set locale according to user's wishes. */ + setlocale (LC_ALL, ""); + + /* Tell program which translations to use and where to find. */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + for (;;) { - int optc = getopt_long (argc, argv, "o:f:i:x:l:m:uvs", + int optc = getopt_long (argc, argv, "o:f:i:x:l:m:d:p:vs", long_options, (int *) 0); if (optc < 0) break; @@ -201,23 +207,34 @@ main (int argc, char **argv) break; case 'i': - include_languages = optarg; + include_languages (optarg); break; case 'x': - exclude_languages = optarg; + exclude_languages (optarg); break; case 'l': language_save_arg (optarg); break; - + case 'm': lang_map_file_name = optarg; break; + case 'd': + set_default_language (optarg); + break; + + case 'p': + if (cw_dlink == 0) + cw_dlink = init_walker (&idh); + prune_file_names (optarg, cw_dlink); + break; + case 'v': verbose_flag = 1; + statistics_flag = 1; break; case 's': @@ -237,38 +254,46 @@ main (int argc, char **argv) if (show_help) help_me (); - + argc -= optind; argv += optind; - language_getopt (); + if (argc == 0) + { + static char *dot = (char *) "."; + argc = 1; + argv = ˙ + } + language_getopt (); assert_writeable (idh.idh_file_name); + if (cw_dlink == 0) + cw_dlink = init_walker (&idh); + parse_language_map (lang_map_file_name); - if (argc == 0) + while (argc--) { - argc++; - *(char const **)--argv = "."; + struct file_link *flink = parse_file_name (*argv++, cw_dlink); + if (flink) + walk_flink (flink, 0); } - heap_initial = (char const *) sbrk (0); - init_idh_obstacks (&idh); - init_idh_tables (&idh); - parse_language_map (lang_map_file_name); - - { - struct file_link *cwd_link = get_current_dir_link (); - while (argc--) - walk_flink (parse_file_name (*argv++, cwd_link), 0); - mark_member_file_links (&idh); - heap_after_walk = (char const *) sbrk (0); - scan_files (&idh); - heap_after_scan = sbrk (0); - free_summary_tokens (); - free (token_table.ht_vec); - chdir_to_link (cwd_link); - write_id_file (&idh); - } - if (statistics_flag) - report_statistics (); + heap_after_walk = (char const *) sbrk (0); + + mark_member_file_links (&idh); + if (idh.idh_member_file_table.ht_fill) + { + scan_files (&idh); + heap_after_scan = sbrk (0); + + free_summary_tokens (); + free (token_table.ht_vec); + chdir_to_link (cw_dlink); + write_id_file (&idh); + + if (statistics_flag) + report_statistics (); + } + else + error (0, 0, "nothing to do"); exit (0); } @@ -280,6 +305,8 @@ assert_writeable (char const *file_name) if (errno == ENOENT) { char const *dir_name = dirname (file_name); + if (!dir_name || !*dir_name) + dir_name = "."; if (access (dir_name, 06) < 0) error (1, errno, _("can't create `%s' in `%s'"), basename (file_name), dir_name); @@ -296,7 +323,7 @@ scan_files (struct idhead *idhp) = (struct member_file **) hash_dump (&idhp->idh_member_file_table, 0, member_file_qsort_compare); struct member_file **end = &members_0[idhp->idh_member_file_table.ht_fill]; - struct member_file **members; + struct member_file **members = members_0; hash_init (&token_table, idhp->idh_member_file_table.ht_fill * 64, token_hash_1, token_hash_2, token_hash_cmp); @@ -304,8 +331,17 @@ scan_files (struct idhead *idhp) init_summary (); obstack_init (&tokens_obstack); - for (members = members_0; members < end; members++) - scan_member_file (*members); + for (;;) + { + struct member_file *member = *members++; + scan_member_file (member); + if (members == end) + break; + if (current_hits_signature[0] & 0x80) + summarize (); + bump_current_hits_signature (); + } + free (members_0); } @@ -318,48 +354,44 @@ scan_member_file (struct member_file const *member) struct file_link *flink = member->mf_link; struct stat st; FILE *source_FILE; - size_t bytes; chdir_to_link (flink->fl_parent); - source_FILE = open_source_FILE (flink->fl_name); + source_FILE = fopen (flink->fl_name, "r"); if (source_FILE) { - char buf[PATH_MAX]; - if (verbose_flag) + if (statistics_flag) { - printf ("%d: %s: %s", member->mf_index, lang->lg_name, - absolute_path (buf, flink)); - fflush (stdout); + if (fstat (fileno (source_FILE), &st) < 0) + { + char *file_name = ALLOCA (char, PATH_MAX); + maybe_relative_file_name (file_name, flink, cw_dlink); + error (0, errno, _("can't stat `%s'"), file_name); + } + else + input_chars += st.st_size; } - if (fstat (fileno (source_FILE), &st) < 0) - error (0, errno, _("can't stat `%s'"), absolute_path (buf, flink)); - else + if (verbose_flag) { - bytes = st.st_size; - input_chars += bytes; + char *file_name = ALLOCA (char, PATH_MAX); + maybe_relative_file_name (file_name, flink, cw_dlink); + printf ("%d: %s: %s", member->mf_index, lang->lg_name, file_name); + fflush (stdout); } scan_member_file_1 (get_token, lang_args->la_args_digested, source_FILE); if (verbose_flag) putchar ('\n'); - close_source_FILE (source_FILE); + fclose (source_FILE); } - if (current_hits_signature[0] & 0x80) - summarize (); -#if 0 - if (member->mf_index < file_name_count) -#endif - bump_current_hits_signature (); + else + error (0, errno, _("can't open `%s'"), flink->fl_name); } void scan_member_file_1 (get_token_func_t get_token, void const *args, FILE *source_FILE) { - struct stat st; struct token **slot; struct token *token; int flags; - int bytes = 0; - int total_tokens = 0; int new_tokens = 0; int distinct_tokens = 0; @@ -369,16 +401,18 @@ scan_member_file_1 (get_token_func_t get_token, void const *args, FILE *source_F obstack_free (&tokens_obstack, token); continue; } - total_tokens++; slot = (struct token **) hash_find_slot (&token_table, token); if (HASH_VACANT (*slot)) { + token->tok_flags = flags; token->tok_count = 1; memset (token->tok_hits, 0, sizeof (token->tok_hits)); - token->tok_flags = flags; sign_token (token); - distinct_tokens++; - new_tokens++; + if (verbose_flag) + { + distinct_tokens++; + new_tokens++; + } hash_insert_at (&token_table, token, slot); } else @@ -391,7 +425,8 @@ scan_member_file_1 (get_token_func_t get_token, void const *args, FILE *source_F if (!(token->tok_hits[0] & current_hits_signature[0])) { sign_token (token); - distinct_tokens++; + if (verbose_flag) + distinct_tokens++; } } } |