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