1// -*- C++ -*-
2/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2003
3   Free Software Foundation, Inc.
4     Written by James Clark (jjc@jclark.com)
5
6This file is part of groff.
7
8groff is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13groff is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with groff; see the file COPYING.  If not, write to the Free Software
20Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21
22#include "lib.h"
23
24#include <stdlib.h>
25#include <assert.h>
26#include <errno.h>
27
28#include "errarg.h"
29#include "error.h"
30#include "cset.h"
31
32#include "refid.h"
33#include "search.h"
34
35/* for isatty() */
36#include "posix.h"
37#include "nonposix.h"
38
39extern "C" {
40  const char *Version_string;
41}
42
43static void usage(FILE *stream)
44{
45  fprintf(stream, "usage: %s [-v] [-i XYZ] [-t N] database ...\n",
46	  program_name);
47}
48
49int main(int argc, char **argv)
50{
51  program_name = argv[0];
52  static char stderr_buf[BUFSIZ];
53  setbuf(stderr, stderr_buf);
54  int opt;
55  static const struct option long_options[] = {
56    { "help", no_argument, 0, CHAR_MAX + 1 },
57    { "version", no_argument, 0, 'v' },
58    { NULL, 0, 0, 0 }
59  };
60  while ((opt = getopt_long(argc, argv, "vVi:t:", long_options, NULL)) != EOF)
61    switch (opt) {
62    case 'V':
63      verify_flag = 1;
64      break;
65    case 'i':
66      linear_ignore_fields = optarg;
67      break;
68    case 't':
69      {
70	char *ptr;
71	long n = strtol(optarg, &ptr, 10);
72	if (n == 0 && ptr == optarg) {
73	  error("bad integer `%1' in `t' option", optarg);
74	  break;
75	}
76	if (n < 1)
77	  n = 1;
78	linear_truncate_len = int(n);
79	break;
80      }
81    case 'v':
82      {
83	printf("GNU lookbib (groff) version %s\n", Version_string);
84	exit(0);
85	break;
86      }
87    case CHAR_MAX + 1: // --help
88      usage(stdout);
89      exit(0);
90      break;
91    case '?':
92      usage(stderr);
93      exit(1);
94      break;
95    default:
96      assert(0);
97    }
98  if (optind >= argc) {
99    usage(stderr);
100    exit(1);
101  }
102  search_list list;
103  for (int i = optind; i < argc; i++)
104    list.add_file(argv[i]);
105  if (list.nfiles() == 0)
106    fatal("no databases");
107  char line[1024];
108  int interactive = isatty(fileno(stdin));
109  for (;;) {
110    if (interactive) {
111      fputs("> ", stderr);
112      fflush(stderr);
113    }
114    if (!fgets(line, sizeof(line), stdin))
115      break;
116    char *ptr = line;
117    while (csspace(*ptr))
118      ptr++;
119    if (*ptr == '\0')
120      continue;
121    search_list_iterator iter(&list, line);
122    const char *start;
123    int len;
124    int count;
125    for (count = 0; iter.next(&start, &len); count++) {
126      if (fwrite(start, 1, len, stdout) != (size_t)len)
127	fatal("write error on stdout: %1", strerror(errno));
128      // Can happen for last reference in file.
129      if (start[len - 1] != '\n')
130	putchar('\n');
131      putchar('\n');
132    }
133    fflush(stdout);
134    if (interactive) {
135      fprintf(stderr, "%d found\n", count);
136      fflush(stderr);
137    }
138  }
139  if (interactive)
140    putc('\n', stderr);
141  return 0;
142}
143
144