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