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