1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <assert.h>
27 
28 #include "lib.h"
29 #include "errarg.h"
30 #include "error.h"
31 
32 #include "defs.h"
33 #include "refid.h"
34 #include "search.h"
35 
36 static void usage()
37 {
38   fprintf(stderr, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
39 	  program_name);
40   exit(1);
41 }
42 
43 main(int argc, char **argv)
44 {
45   program_name = argv[0];
46   static char stderr_buf[BUFSIZ];
47   setbuf(stderr, stderr_buf);
48   int search_default = 1;
49   search_list list;
50   int opt;
51   while ((opt = getopt(argc, argv, "nvVi:t:p:")) != EOF)
52     switch (opt) {
53     case 'V':
54       verify_flag = 1;
55       break;
56     case 'n':
57       search_default = 0;
58       break;
59     case 'i':
60       linear_ignore_fields = optarg;
61       break;
62     case 't':
63       {
64 	char *ptr;
65 	long n = strtol(optarg, &ptr, 10);
66 	if (n == 0 && ptr == optarg) {
67 	  error("bad integer `%1' in `t' option", optarg);
68 	  break;
69 	}
70 	if (n < 1)
71 	  n = 1;
72 	linear_truncate_len = int(n);
73 	break;
74       }
75     case 'v':
76       {
77 	extern const char *version_string;
78 	fprintf(stderr, "GNU lkbib version %s\n", version_string);
79 	fflush(stderr);
80 	break;
81       }
82     case 'p':
83       list.add_file(optarg);
84       break;
85     case '?':
86       usage();
87     default:
88       assert(0);
89     }
90   if (optind >= argc)
91     usage();
92   char *filename = getenv("REFER");
93   if (filename)
94     list.add_file(filename);
95   else if (search_default)
96     list.add_file(DEFAULT_INDEX, 1);
97   if (list.nfiles() == 0)
98     fatal("no databases");
99   int total_len = 0;
100   for (int i = optind; i < argc; i++)
101     total_len += strlen(argv[i]);
102   total_len += argc - optind - 1 + 1; // for spaces and '\0'
103   char *buffer = new char[total_len];
104   char *ptr = buffer;
105   for (i = optind; i < argc; i++) {
106     if (i > optind)
107       *ptr++ = ' ';
108     strcpy(ptr, argv[i]);
109     ptr = strchr(ptr, '\0');
110   }
111   search_list_iterator iter(&list, buffer);
112   const char *start;
113   int len;
114   for (int count = 0; iter.next(&start, &len); count++) {
115     if (fwrite(start, 1, len, stdout) != len)
116       fatal("write error on stdout: %1", strerror(errno));
117     // Can happen for last reference in file.
118     if (start[len - 1] != '\n')
119       putchar('\n');
120     putchar('\n');
121   }
122   exit(!count);
123 }
124