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