Multi register works with record paths and data1 profile path
[idzebra-moved-to-github.git] / util / res.c
1 /*
2  * Copyright (C) 1994-2002, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Id: res.c,v 1.30 2002-04-04 20:50:37 adam Exp $
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 #ifdef WIN32
13 #include <io.h>
14 #else
15 #include <unistd.h>
16 #endif
17
18 #include <zebrautl.h>
19 #include <yaz/yaz-util.h>
20
21 struct res_entry {
22     char *name;
23     char *value;
24     struct res_entry *next;
25 };
26
27 struct res_struct {
28     struct res_entry *first, *last;
29     char *name;
30     int  init;
31     Res def_res;
32 };
33
34 static struct res_entry *add_entry (Res r)
35 {
36     struct res_entry *resp;
37
38     if (!r->first)
39         resp = r->last = r->first =
40             (struct res_entry *) xmalloc (sizeof(*resp));
41     else
42     {
43         resp = (struct res_entry *) xmalloc (sizeof(*resp));
44         r->last->next = resp;
45         r->last = resp;
46     }
47     resp->next = NULL;
48     return resp;
49 }
50
51 static void reread (Res r)
52 {
53     struct res_entry *resp;
54     char *line;
55     char *val_buf;
56     int val_size, val_max = 256;
57     char fr_buf[1024];
58     FILE *fr;
59
60     assert (r);
61     r->init = 1;
62
63     val_buf = (char*) xmalloc (val_max);
64
65     fr = fopen (r->name, "r");
66     if (!fr)
67     {
68         logf (LOG_WARN|LOG_ERRNO, "Cannot open %s", r->name);
69         return ;
70     }
71     while (1)
72     {
73         line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
74         if (!line)
75             break;
76         if (*line == '#')
77         {
78             int no = 0;
79
80             while (fr_buf[no] && fr_buf[no] != '\n')
81                 no++;
82             fr_buf[no] = '\0';
83
84             resp = add_entry (r);
85             resp->name = (char*) xmalloc (no+1);
86             resp->value = NULL;
87             strcpy (resp->name, fr_buf);
88         }
89         else
90         {
91             int no = 0;
92             while (1)
93             {
94                 if (fr_buf[no] == 0 || fr_buf[no] == '\n' )
95                 {
96                     no = 0;
97                     break;
98                 }
99                 if (strchr (": \t", fr_buf[no]))
100                     break;
101                 no++;
102             }
103             if (!no)
104                 continue;
105             fr_buf[no++] = '\0';
106             resp = add_entry (r);
107             resp->name = (char*) xmalloc (no);
108             strcpy (resp->name, fr_buf);
109             
110             while (strchr (" \t", fr_buf[no]))
111                 no++;
112             val_size = 0;
113             while (1)
114             {
115                 if (fr_buf[no] == '\0' || strchr("\n\r\f", fr_buf[no]))
116                 {
117                     while (val_size > 0 &&
118                               (val_buf[val_size-1] == ' ' ||
119                                val_buf[val_size-1] == '\t'))
120                         val_size--;
121                     val_buf[val_size++] = '\0';
122                     resp->value = (char*) xmalloc (val_size);
123                     strcpy (resp->value, val_buf);
124                     logf (LOG_DEBUG, "(name=%s,value=%s)",
125                          resp->name, resp->value);
126                     break;
127                 }
128                 else if (fr_buf[no] == '\\' && strchr ("\n\r\f", fr_buf[no+1]))
129                 {
130                     line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
131                     if (!line)
132                     {
133                         resp->value = (char*) xmalloc (val_size);
134                         strcpy (resp->value, val_buf);
135                         break;
136                     }
137                     no = 0;
138                 }
139                 else
140                 {
141                     val_buf[val_size++] = fr_buf[no++];
142                     if (val_size+1 >= val_max)
143                     {
144                         char *nb;
145
146                         nb = (char*) xmalloc (val_max+=1024);
147                         memcpy (nb, val_buf, val_size);
148                         xfree (val_buf);
149                         val_buf = nb;
150                     }
151                 }
152             }
153         }
154     }                
155     xfree (val_buf);
156     fclose (fr);
157 }
158
159 Res res_open (const char *name, Res def_res)
160 {
161     Res r;
162 #ifdef WIN32
163     if (access (name, 4))
164 #else
165     if (access (name, R_OK))
166 #endif
167     {
168         logf (LOG_WARN|LOG_ERRNO, "Cannot access resource file `%s'", name);
169         return 0;
170     }
171     r = (Res) xmalloc (sizeof(*r));
172     r->init = 0;
173     r->first = r->last = NULL;
174     r->name = xstrdup (name);
175     r->def_res = def_res;
176     return r;
177 }
178
179 void res_close (Res r)
180 {
181     if (!r)
182         return;
183     if (r->init)
184     {
185         struct res_entry *re, *re1;
186         for (re = r->first; re; re=re1)
187         {
188             if (re->name)
189                 xfree (re->name);
190             if (re->value)
191                 xfree (re->value);
192             re1 = re->next;
193             xfree (re);
194         }
195     }
196     xfree (r->name);
197     xfree (r);
198 }
199
200 char *res_get (Res r, const char *name)
201 {
202     struct res_entry *re;
203
204     if (!r)
205         return 0;
206     if (!r->init)
207         reread (r);
208     for (re = r->first; re; re=re->next)
209         if (re->value && !yaz_matchstr (re->name, name))
210             return re->value;
211
212     return res_get (r->def_res, name);
213 }
214
215 char *res_get_def (Res r, const char *name, char *def)
216 {
217     char *t;
218
219     if (!(t = res_get (r, name)))
220     {
221         logf (LOG_DEBUG, "CAUTION: Using default resource %s:%s", name, def);
222         return def;
223     }
224     else
225         return t;
226 }
227
228 int res_get_match (Res r, const char *name, const char *value, const char *s)
229 {
230     const char *cn = res_get (r, name);
231
232     if (!cn)
233         cn = s;
234     if (cn && !yaz_matchstr (cn, value))
235         return 1;
236     return 0;
237 }
238
239 void res_put (Res r, const char *name, const char *value)
240 {
241     struct res_entry *re;
242     assert (r);
243     if (!r->init)
244         reread (r);
245
246     for (re = r->first; re; re=re->next)
247         if (re->value && !yaz_matchstr (re->name, name))
248         {
249             xfree (re->value);
250             re->value = xstrdup (value);
251             return;
252         }
253     re = add_entry (r);
254     re->name = xstrdup (name);
255     re->value = xstrdup (value);
256 }
257
258 int res_trav (Res r, const char *prefix, void *p,
259               void (*f)(void *p, const char *name, const char *value))
260 {
261     struct res_entry *re;
262     int l = 0;
263     int no = 0;
264     
265     if (!r)
266         return 0;
267     if (prefix)
268         l = strlen(prefix);
269     if (!r->init)
270         reread (r);
271     for (re = r->first; re; re=re->next)
272         if (re->value)
273             if (l==0 || !memcmp (re->name, prefix, l))
274             {
275                 (*f)(p, re->name, re->value);
276                 no++;
277             }
278     if (!no)
279         return res_trav (r->def_res, prefix, p, f);
280     return no;
281 }
282
283
284 int res_write (Res r)
285 {
286     struct res_entry *re;
287     FILE *fr;
288
289     assert (r);
290     if (!r->init)
291         reread (r);
292     fr = fopen (r->name, "w");
293     if (!fr)
294     {
295         logf (LOG_FATAL|LOG_ERRNO, "Cannot create %s", r->name);
296         exit (1);
297     }
298
299     for (re = r->first; re; re=re->next)
300     {
301         int no = 0;
302         int lefts = strlen(re->name)+2;
303
304         if (!re->value)
305             fprintf (fr, "%s\n", re->name);
306         else
307         {
308             fprintf (fr, "%s: ", re->name);
309             while (lefts + strlen(re->value+no) > 78)
310             {
311                 int i = 20;
312                 int ind = no+ 78-lefts;
313                 while (--i >= 0)
314                 {
315                     if (re->value[ind] == ' ')
316                         break;
317                     --ind;
318                 }
319                 if (i<0)
320                     ind = no + 78 - lefts;
321                 for (i = no; i != ind; i++)
322                     putc (re->value[i], fr);
323                 fprintf (fr, "\\\n");
324                 no=ind;
325                 lefts = 0;
326             }
327             fprintf (fr, "%s\n", re->value+no);
328         }
329     }
330     fclose (fr);
331     return 0;
332 }
333
334
335