DEADSOFTWARE

86b6d227c96893cbc7cde91cdc83ca5c31a7f406
[flatwaifu.git] / src / config.c
1 /* Copyright (C) 2020 SovietPony
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 */
16 #include "glob.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21 #include <ctype.h>
22 #include "system.h"
23 #include "files.h"
24 #include "input.h"
26 #include "common/cp866.h"
28 static FILE *f;
29 static int ch;
31 const cfg_t *CFG_find_entry (const char *key, const cfg_t *cfg) {
32 assert(key != NULL);
33 if (cfg != NULL) {
34 int i = 0;
35 while (cfg[i].cfg && cp866_strcasecmp(cfg[i].cfg, key) != 0) {
36 i++;
37 }
38 return cfg[i].cfg ? &cfg[i] : NULL;
39 } else {
40 return NULL;
41 }
42 }
44 int CFG_update_key (const char *key, const char *value, const cfg_t *cfg) {
45 assert(key != NULL);
46 assert(value != NULL);
47 const cfg_t *entry = CFG_find_entry(key, cfg);
48 if (entry != NULL) {
49 void *p = entry->p;
50 switch (entry->t) {
51 case Y_BYTE: *(byte*)p = atoi(value); break;
52 case Y_WORD: *(word*)p = atoi(value); break;
53 case Y_DWORD: *(dword*)p = atoi(value); break;
54 case Y_STRING: strcpy(p, value); break; // TODO fix this security problem
55 case Y_SW_ON: *(byte*)p = cp866_strcasecmp(value, "on") == 0 ? 1 : 0; break;
56 case Y_SW_OFF: *(byte*)p = cp866_strcasecmp(value, "off") == 0 ? 1 : 0; break;
57 case Y_FILES: F_addwad(value); break;
58 case Y_KEY: *(int*)p = I_string_to_key(value); break;
59 default: assert(0); // unknown type -> something broken
60 }
61 //logo("CFG_update_key: [%s] = [%s]\n", key, value);
62 return 1;
63 } else {
64 return 0;
65 }
66 }
68 /* --- parser --- */
70 int CFG_open_iterator (const char *name) {
71 assert(f == NULL);
72 f = fopen(name, "rb");
73 if (f != NULL) {
74 ch = fgetc(f);
75 }
76 return f != NULL;
77 }
79 static void CFG_skip_space (void) {
80 while (feof(f) == 0 && isspace(ch)) {
81 ch = fgetc(f);
82 }
83 }
85 static void CFG_skip_line (void) {
86 while (feof(f) == 0 && ch != '\n' && ch != '\r') {
87 ch = fgetc(f);
88 }
89 while (feof(f) == 0 && ch == '\n' && ch == '\r') {
90 ch = fgetc(f);
91 }
92 }
94 int CFG_scan_iterator (char *key, int keylen, char *value, int valuelen) {
95 assert(key != NULL);
96 assert(keylen > 0);
97 assert(value != NULL);
98 assert(valuelen > 0);
99 int i;
100 int found = 0;
101 while (feof(f) == 0 && found == 0) {
102 CFG_skip_space();
103 if (ch == ';') {
104 CFG_skip_line();
105 } else if (feof(f) == 0) {
106 found = 1;
107 i = 0;
108 while (feof(f) == 0 && isspace(ch) == 0 && ch != '=') {
109 if (i < keylen - 1) {
110 key[i] = ch;
111 i += 1;
113 ch = fgetc(f);
115 key[i] = 0;
116 CFG_skip_space();
117 if (feof(f) == 0 && ch == '=') {
118 ch = fgetc(f);
119 CFG_skip_space();
121 i = 0;
122 while (feof(f) == 0 && ch != '\n' && ch != '\r') {
123 if (i < valuelen - 1) {
124 value[i] = ch;
125 i += 1;
127 ch = fgetc(f);
129 value[i] = 0;
130 CFG_skip_line();
133 return found;
136 void CFG_close_iterator (void) {
137 assert(f != NULL);
138 fclose(f);
139 f = NULL;
142 /* --- reader --- */
144 int CFG_read_config (const char *name, int n, const cfg_t **cfg) {
145 assert(name != NULL);
146 assert(n >= 0);
147 assert(cfg != NULL);
148 int i;
149 char key[64];
150 char value[64];
151 assert(name != NULL);
152 if (CFG_open_iterator(name)) {
153 while (CFG_scan_iterator(key, 64, value, 64)) {
154 i = 0;
155 while (i < n && CFG_update_key(key, value, cfg[i]) == 0) {
156 i++;
159 CFG_close_iterator();
160 return 1;
161 } else {
162 return 0;
168 /* --- writer --- */
170 static void CFG_write_key_value (FILE *f, const char *key, const char *value) {
171 assert(f != NULL);
172 assert(key != NULL);
173 assert(value != NULL);
174 fwrite(key, strlen(key), 1, f);
175 fwrite("=", 1, 1, f);
176 fwrite(value, strlen(value), 1, f);
177 fwrite("\n", 1, 1, f);
180 static int CFG_write_entry (FILE *f, const cfg_t *entry) {
181 assert(f != NULL);
182 assert(entry != NULL);
183 char buf[16];
184 const char *str;
185 const char *key = entry->cfg;
186 if (key != NULL) {
187 switch (entry->t) {
188 case Y_BYTE:
189 snprintf(buf, 16, "%i", *(byte*)entry->p);
190 CFG_write_key_value(f, key, buf);
191 break;
192 case Y_WORD:
193 snprintf(buf, 16, "%i", *(word*)entry->p);
194 CFG_write_key_value(f, key, buf);
195 break;
196 case Y_DWORD:
197 snprintf(buf, 16, "%i", *(dword*)entry->p);
198 CFG_write_key_value(f, key, buf);
199 break;
200 case Y_STRING:
201 CFG_write_key_value(f, key, entry->p);
202 break;
203 case Y_SW_ON:
204 case Y_SW_OFF:
205 str = *(byte*)entry->p ? "on" : "off";
206 CFG_write_key_value(f, key, str);
207 break;
208 case Y_KEY:
209 str = I_key_to_string(*(int*)entry->p);
210 CFG_write_key_value(f, key, str);
211 break;
212 case Y_FILES: return 1; // ignore
213 case 0: return 0; // end
214 default: assert(0); // unknown type -> something broken
217 return entry->t == 0 ? 0 : 1;
220 int CFG_update_config (const char *old, const char *new, int n, const cfg_t **cfg, const char *msg) {
221 assert(old != NULL);
222 assert(new != NULL);
223 assert(n >= 0);
224 assert(cfg != NULL);
225 int i, j;
226 char key[64];
227 char value[64];
228 FILE *nf = fopen(new, "wb");
229 if (nf != NULL) {
230 if (msg != NULL) {
231 fwrite("; ", 2, 1, nf);
232 fwrite(msg, strlen(msg), 1, nf);
233 fwrite("\n", 1, 1, nf);
235 if (CFG_open_iterator(old)) {
236 while (CFG_scan_iterator(key, 64, value, 64)) {
237 i = 0;
238 while (i < n && CFG_find_entry(key, cfg[i]) == NULL) {
239 i++;
241 if (i >= n) {
242 CFG_write_key_value(nf, key, value);
245 CFG_close_iterator();
247 for (j = 0; j < n; j++) {
248 if (cfg[j] != NULL) {
249 i = 0;
250 while (CFG_write_entry(nf, &cfg[j][i])) {
251 i++;
255 fclose(nf);
257 return nf != NULL;