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