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