1// -*- C++ -*-
2/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
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 "posix.h"
29#include "errarg.h"
30#include "error.h"
31#include "nonposix.h"
32
33#include "refid.h"
34#include "search.h"
35
36int linear_truncate_len = 6;
37const char *linear_ignore_fields = "XYZ";
38
39search_list::search_list()
40: list(0), niterators(0), next_fid(1)
41{
42}
43
44search_list::~search_list()
45{
46  assert(niterators == 0);
47  while (list) {
48    search_item *tem = list->next;
49    delete list;
50    list = tem;
51  }
52}
53
54void search_list::add_file(const char *filename, int silent)
55{
56  search_item *p = make_index_search_item(filename, next_fid);
57  if (!p) {
58    int fd = open(filename, O_RDONLY | O_BINARY);
59    if (fd < 0) {
60      if (!silent)
61	error("can't open `%1': %2", filename, strerror(errno));
62    }
63    else
64      p = make_linear_search_item(fd, filename, next_fid);
65  }
66  if (p) {
67    search_item **pp;
68    for (pp = &list; *pp; pp = &(*pp)->next)
69      ;
70    *pp = p;
71    next_fid = p->next_filename_id();
72  }
73}
74
75int search_list::nfiles() const
76{
77  int n = 0;
78  for (search_item *ptr = list; ptr; ptr = ptr->next)
79    n++;
80  return n;
81}
82
83search_list_iterator::search_list_iterator(search_list *p, const char *q)
84: list(p), ptr(p->list), iter(0), query(strsave(q)),
85  searcher(q, strlen(q), linear_ignore_fields, linear_truncate_len)
86{
87  list->niterators += 1;
88}
89
90search_list_iterator::~search_list_iterator()
91{
92  list->niterators -= 1;
93  a_delete query;
94  delete iter;
95}
96
97int search_list_iterator::next(const char **pp, int *lenp, reference_id *ridp)
98{
99  while (ptr) {
100    if (iter == 0)
101      iter = ptr->make_search_item_iterator(query);
102    if (iter->next(searcher, pp, lenp, ridp))
103      return 1;
104    delete iter;
105    iter = 0;
106    ptr = ptr->next;
107  }
108  return 0;
109}
110
111search_item::search_item(const char *nm, int fid)
112: name(strsave(nm)), filename_id(fid), next(0)
113{
114}
115
116search_item::~search_item()
117{
118  a_delete name;
119}
120
121int search_item::is_named(const char *nm) const
122{
123  return strcmp(name, nm) == 0;
124}
125
126int search_item::next_filename_id() const
127{
128  return filename_id + 1;
129}
130
131search_item_iterator::~search_item_iterator()
132{
133}
134