1 /*
2  *
3  * idxname.c - Idx handling routines.
4  *
5  * $Id: idxname.c,v 1.25.8.10 2009-02-17 08:45:14 opengl2772 Exp $
6  *
7  * Copyright (C) 1997-1999 Satoru Takabayashi All rights reserved.
8  * Copyright (C) 2000-2009 Namazu Project All rights reserved.
9  * Copyright (C) 1999 NOKUBI Takatsugu All rights reserved.
10  * This is free software with ABSOLUTELY NO WARRANTY.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25  * 02111-1307, USA
26  *
27  *
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #  include "config.h"
32 #endif
33 #ifdef HAVE_SUPPORT_H
34 #  include "support.h"
35 #endif
36 
37 #ifdef HAVE_ERRNO_H
38 #  include <errno.h>
39 #endif
40 
41 #ifdef HAVE_STDLIB_H
42 #  include <stdlib.h>
43 #endif
44 #include <ctype.h>
45 
46 #ifdef HAVE_STRING_H
47 #  include <string.h>
48 #else
49 #  include <strings.h>
50 #endif
51 
52 #include "libnamazu.h"
53 #include "search.h"
54 #include "alias.h"
55 #include "var.h"
56 #include "idxname.h"
57 #include "util.h"
58 
59 static struct nmz_indices indices = {0}; /* Initialize member `num' with 0 */
60 
61 /*
62  * Default directory to place index. This setting can be
63  * changed with nmz_set_defaultidx().
64  */
65 static char defaultidx[BUFSIZE] = OPT_INDEXDIR;
66 
67 /*
68  *
69  * Public functions
70  *
71  */
72 
73 enum nmz_stat
nmz_add_index(const char * idxname)74 nmz_add_index(const char *idxname)
75 {
76     int newidxnum = indices.num;
77 
78     if (newidxnum >= INDEX_MAX) {
79         nmz_warn_printf("Too many indices.\n");
80         return FAILURE;
81     }
82     indices.names[newidxnum] = malloc(strlen(idxname) + 1);
83     if (indices.names[newidxnum] == NULL)
84         return FAILURE;
85     strcpy(indices.names[newidxnum], idxname);
86     indices.hitnumlists[newidxnum] = NULL;
87     indices.num = newidxnum + 1;
88 
89     return SUCCESS;
90 }
91 
92 void
nmz_free_idxnames(void)93 nmz_free_idxnames(void)
94 {
95     int i;
96     for (i = 0; i < indices.num; i++) {
97         free(indices.names[i]);
98         nmz_free_hitnums(indices.hitnumlists[i]);
99     }
100     indices.num = 0;
101 }
102 
103 /*
104  * Except duplicated indices with a simple O(n^2) algorithm.
105  */
106 void
nmz_uniq_idxnames(void)107 nmz_uniq_idxnames(void)
108 {
109     int i, j, k;
110 
111     for (i = 0; i < indices.num - 1; i++) {
112         for (j = i + 1; j < indices.num; j++) {
113             if (strcmp(indices.names[i], indices.names[j]) == 0) {
114                 free(indices.names[j]);
115                 for (k = j + 1; k < indices.num; k++) {
116                     indices.names[k - 1] = indices.names[k];
117                 }
118                 indices.num--;
119                 j--;
120             }
121         }
122     }
123 }
124 
125 /*
126  * Expand index name aliases defined in namazurc.
127  * e.g., Alias quux /home/foobar/NMZ/quux
128  */
129 int
nmz_expand_idxname_aliases(void)130 nmz_expand_idxname_aliases(void)
131 {
132     int i;
133 
134     for (i = 0; i < indices.num; i++) {
135         struct nmz_alias *list = nmz_get_aliases();
136         while (list != NULL) {
137             if (strcmp(indices.names[i], list->alias) == 0) {
138                 free(indices.names[i]);
139                 indices.names[i] = malloc(strlen(list->real) + 1);
140                 if (indices.names[i] == NULL) {
141                     nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
142                     return FAILURE;
143                 }
144                 strcpy(indices.names[i], list->real);
145             }
146             list = list->next;
147         }
148     }
149     return 0;
150 }
151 
152 /*
153  * Complete an abbreviated index name to completed one.
154  * e.g.,  +foobar -> (defaultidx)/foobar
155  */
156 int
nmz_complete_idxnames(void)157 nmz_complete_idxnames(void)
158 {
159     int i;
160 
161     for (i = 0; i < indices.num; i++) {
162         if (*indices.names[i] == '+' &&
163         nmz_isalnum((unsigned char)*(indices.names[i] + 1))) {
164             char *tmp;
165             tmp = malloc(strlen(defaultidx)
166                   + 1 + strlen(indices.names[i]) + 1);
167             if (tmp == NULL) {
168                 nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
169                 return FAILURE;
170             }
171             strcpy(tmp, defaultidx);
172             strcat(tmp, "/");
173             strcat(tmp, indices.names[i] + 1);  /* +1 means '+' */
174             free(indices.names[i]);
175             indices.names[i] = tmp;
176         }
177     }
178     return 0;
179 }
180 
181 /*
182  * Get the name of the index specified by id.
183  */
184 char *
nmz_get_idxname(int id)185 nmz_get_idxname(int id)
186 {
187     return indices.names[id];
188 }
189 
190 /*
191  * Get the total number of indices to search.
192  */
193 int
nmz_get_idxnum()194 nmz_get_idxnum()
195 {
196     return indices.num;
197 }
198 
199 /*
200  * Set the total hit number of the index specified by id.
201  */
202 void
nmz_set_idx_totalhitnum(int id,int hitnum)203 nmz_set_idx_totalhitnum(int id, int hitnum)
204 {
205     indices.totalhitnums[id] = hitnum;
206 }
207 
208 /*
209  * Get the total hit number of the index specified by id.
210  */
211 int
nmz_get_idx_totalhitnum(int id)212 nmz_get_idx_totalhitnum(int id)
213 {
214     return indices.totalhitnums[id];
215 }
216 
217 /*
218  * Get the hitnumlist of the index specified by id.
219  */
220 struct nmz_hitnumlist *
nmz_get_idx_hitnumlist(int id)221 nmz_get_idx_hitnumlist(int id)
222 {
223     return indices.hitnumlists[id];
224 }
225 
226 void
nmz_set_idx_hitnumlist(int id,struct nmz_hitnumlist * hnlist)227 nmz_set_idx_hitnumlist(int id, struct nmz_hitnumlist *hnlist)
228 {
229     indices.hitnumlists[id] = hnlist;
230 }
231 
232 /*
233  * Push something and return pushed list.
234  */
235 struct nmz_hitnumlist *
nmz_push_hitnum(struct nmz_hitnumlist * hn,const char * str,int hitnum,enum nmz_stat stat)236 nmz_push_hitnum(struct nmz_hitnumlist *hn,
237 	    const char *str,
238 	    int hitnum,
239 	    enum nmz_stat stat
240 )
241 {
242     struct nmz_hitnumlist *hnptr = hn, *prevhnptr = hn;
243     while (hnptr != NULL) {
244         prevhnptr = hnptr;
245         hnptr = hnptr->next;
246     }
247     if ((hnptr = malloc(sizeof(struct nmz_hitnumlist))) == NULL) {
248         nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
249         return NULL;
250     }
251     if (prevhnptr != NULL)
252         prevhnptr->next = hnptr;
253     hnptr->hitnum = hitnum;
254     hnptr->stat  = stat;
255     hnptr->phrase = NULL;
256     hnptr->next  = NULL;
257     if ((hnptr->word = malloc(strlen(str) +1)) == NULL) {
258         nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
259         return NULL;
260     }
261     strcpy(hnptr->word, str);
262 
263     if (hn == NULL)
264         return hnptr;
265     return hn;
266 }
267 
268 
269 void
nmz_set_defaultidx(const char * idx)270 nmz_set_defaultidx(const char *idx)
271 {
272     strncpy(defaultidx, idx, BUFSIZE - 1);
273     defaultidx[BUFSIZE - 1] = '\0';
274 }
275 
276 char *
nmz_get_defaultidx(void)277 nmz_get_defaultidx(void)
278 {
279     return defaultidx;
280 }
281