summaryrefslogtreecommitdiffstats
path: root/src/fid.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fid.c')
-rw-r--r--src/fid.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/fid.c b/src/fid.c
new file mode 100644
index 0000000..4572ac8
--- /dev/null
+++ b/src/fid.c
@@ -0,0 +1,270 @@
+/* fid.c -- list all tokens in the given file(s)
+ Copyright (C) 1986, 1995, 1996 Free Software Foundation, Inc.
+
+ 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
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+
+#include <config.h>
+#include "system.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"
+
+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));
+
+struct idhead idh;
+int tree8_levels;
+
+/* The name this program was run with. */
+
+char const *program_name;
+
+/* If nonzero, display usage information and exit. */
+
+static int show_help;
+
+/* If nonzero, print the version on standard output then exit. */
+
+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;
+char *hits_buf;
+
+static struct option const long_options[] =
+{
+ { "file", required_argument, 0, 'f' },
+ { "help", no_argument, &show_help, 1 },
+ { "version", no_argument, &show_version, 1 },
+ { 0 }
+};
+
+void
+usage (void)
+{
+ fprintf (stderr, _("Try `%s --help' for more information.\n"),
+ program_name);
+ exit (1);
+}
+
+static void
+help_me (void)
+{
+ printf (_("\
+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\
+"));
+ exit (0);
+}
+
+int
+main (int argc, char **argv)
+{
+ int optc;
+ int index_1 = -1;
+ int index_2 = -1;
+
+ program_name = argv[0];
+ for (;;)
+ {
+ int optc = getopt_long (argc, argv, "f:",
+ long_options, (int *) 0);
+ if (optc < 0)
+ break;
+ switch (optc)
+ {
+ case 0:
+ break;
+
+ case 'f':
+ id_file_name = optarg;
+ break;
+
+ default:
+ usage ();
+ }
+ }
+
+ if (show_version)
+ {
+ printf ("%s - %s\n", program_name, PACKAGE_VERSION);
+ exit (0);
+ }
+
+ 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)
+ {
+ error (0, 0, _("no file name arguments"));
+ usage ();
+ }
+ if (argc > 2)
+ {
+ error (0, 0, _("too many file name arguments"));
+ usage ();
+ }
+
+ index_1 = get_file_index ((argc--, *argv++));
+ if (argc)
+ index_2 = get_file_index ((argc--, *argv++));
+
+ if (index_1 < 0)
+ return 1;
+
+ hits_buf = xmalloc (idh.idh_buf_size);
+ fseek (idh.idh_FILE, idh.idh_tokens_offset, SEEK_SET);
+ {
+ int i;
+ 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);
+ if (is_hit (hits, index_1) && (index_2 < 0 || is_hit (hits, index_2)))
+ printf ("%s\n", tok_string (hits_buf));
+ }
+ }
+
+ return 0;
+}
+
+int
+get_file_index (char *file_name)
+{
+ struct file_link **members;
+ struct file_link **end = &members_0[idh.idh_files];
+ struct file_link *fn_flink = 0;
+ int has_slash = (strchr (file_name, '/') != 0);
+ int file_name_length = strlen (file_name);
+ int index = -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;
+ if (fn_flink)
+ {
+ if (fn_flink != flink)
+ continue;
+ }
+ else if (has_slash)
+ {
+ char buf[PATH_MAX];
+ int member_length;
+ maybe_relative_path (buf, flink, cw_dlink);
+ member_length = strlen (buf);
+ if (file_name_length > member_length
+ || !strequ (&buf[member_length - file_name_length], file_name))
+ continue;
+ }
+ else if (!strequ (flink->fl_name, file_name))
+ continue;
+ if (index >= 0)
+ {
+ error (0, 0, _("`%s' is ambiguous"), file_name);
+ return;
+ }
+ index = members - members_0;
+ }
+ if (index < 0)
+ error (0, 0, _("`%s' not found"), file_name);
+ return index;
+}
+
+int
+is_hit (unsigned char const *hits, int file_number)
+{
+ return is_hit_1 (&hits, tree8_levels, file_number);
+}
+
+int
+is_hit_1 (unsigned char const **hits, int level, int file_number)
+{
+ int file_hit = 1 << ((file_number >> (3 * --level)) & 7);
+ int hit = *(*hits)++;
+ int bit;
+
+ if (!(file_hit & hit))
+ return 0;
+ if (level == 0)
+ return 1;
+
+ for (bit = 1; (bit < file_hit) && (bit & 0xff); bit <<= 1)
+ {
+ if (hit & bit)
+ skip_hits (hits, level);
+ }
+ return is_hit_1 (hits, level, file_number);
+}
+
+void
+skip_hits (unsigned char const **hits, int level)
+{
+ int hit = *(*hits)++;
+ int bit;
+
+ if (--level == 0)
+ return;
+ for (bit = 1; bit & 0xff; bit <<= 1)
+ {
+ if (hit & bit)
+ skip_hits (hits, level);
+ }
+}