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