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