Imported Upstream version 1.22.4
[platform/upstream/groff.git] / src / utils / lkbib / lkbib.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 1989-2018 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 3 of the License, or
10 (at your option) any later 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
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "lib.h"
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <assert.h>
25
26 #include "errarg.h"
27 #include "error.h"
28
29 #include "defs.h"
30 #include "refid.h"
31 #include "search.h"
32
33 extern "C" const char *Version_string;
34
35 static void usage(FILE *stream)
36 {
37   fprintf(stream, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
38           program_name);
39 }
40
41 int main(int argc, char **argv)
42 {
43   program_name = argv[0];
44   static char stderr_buf[BUFSIZ];
45   setbuf(stderr, stderr_buf);
46   int search_default = 1;
47   search_list list;
48   int opt;
49   static const struct option long_options[] = {
50     { "help", no_argument, 0, CHAR_MAX + 1 },
51     { "version", no_argument, 0, 'v' },
52     { NULL, 0, 0, 0 }
53   };
54   while ((opt = getopt_long(argc, argv, "nvVi:t:p:", long_options, NULL))
55          != EOF)
56     switch (opt) {
57     case 'V':
58       verify_flag = 1;
59       break;
60     case 'n':
61       search_default = 0;
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 lkbib (groff) version %s\n", Version_string);
82         exit(0);
83         break;
84       }
85     case 'p':
86       list.add_file(optarg);
87       break;
88     case CHAR_MAX + 1: // --help
89       usage(stdout);
90       exit(0);
91       break;
92     case '?':
93       usage(stderr);
94       exit(1);
95       break;
96     default:
97       assert(0);
98     }
99   if (optind >= argc) {
100     usage(stderr);
101     exit(1);
102   }
103   char *filename = getenv("REFER");
104   if (filename)
105     list.add_file(filename);
106   else if (search_default)
107     list.add_file(DEFAULT_INDEX, 1);
108   if (list.nfiles() == 0)
109     fatal("no databases");
110   int total_len = 0;
111   int i;
112   for (i = optind; i < argc; i++)
113     total_len += strlen(argv[i]);
114   total_len += argc - optind - 1 + 1; // for spaces and '\0'
115   char *buffer = new char[total_len];
116   char *ptr = buffer;
117   for (i = optind; i < argc; i++) {
118     if (i > optind)
119       *ptr++ = ' ';
120     strcpy(ptr, argv[i]);
121     ptr = strchr(ptr, '\0');
122   }
123   search_list_iterator iter(&list, buffer);
124   const char *start;
125   int len;
126   int count;
127   for (count = 0; iter.next(&start, &len); count++) {
128     if (fwrite(start, 1, len, stdout) != (size_t)len)
129       fatal("write error on stdout: %1", strerror(errno));
130     // Can happen for last reference in file.
131     if (start[len - 1] != '\n')
132       putchar('\n');
133     putchar('\n');
134   }
135   return !count;
136 }