English Language flag
// Log In
// CVSweb
Project: FreeWRT
// Summary // Activity // Search // Tracker // Lists // News // SCM // Wiki

SCM Repository

ViewVC logotype

Contents of /branches/common-nfo/tools/nfotiser/pfile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3488 - (show annotations) (download)
Mon Aug 13 15:09:52 2007 UTC (6 years, 6 months ago) by tg
File MIME type: text/plain
File size: 9998 byte(s)
begin working on default values, but I'm going to have to implement
different arg types (string ./. integer) first, d’oh

1 /* $FreeWRT: src/share/misc/licence.template,v 1.20 2006/12/11 21:04:56 tg Rel $ */
2
3 /*-
4 * Copyright (c) 2007
5 * Thorsten Glaser <tg@mirbsd.de>
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * Advertising materials mentioning features or use of this work must
14 * display the following acknowledgement:
15 * This product includes material provided by Thorsten Glaser.
16 * This acknowledgement does not need to be reprinted if this work is
17 * linked into a bigger work whose licence does not allow such clause
18 * and the author of this work is given due credit in the bigger work
19 * or its accompanying documents, where such information is generally
20 * kept, provided that said credits are retained.
21 *
22 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
23 * the utmost extent permitted by applicable law, neither express nor
24 * implied; without malicious intent or gross negligence. In no event
25 * may a licensor, author or contributor be held liable for indirect,
26 * direct, other damage, loss, or other issues arising in any way out
27 * of dealing in the work, even if advised of the possibility of such
28 * damage or existence of a defect, except proven that it results out
29 * of said person's immediate fault when using the work as intended.
30 */
31
32 #include <sys/param.h>
33
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdbool.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 enum kwords {
45 KA_DISTFILE,
46 KA_HASH,
47 KA_RCCONF,
48 KN_DISTFILES,
49 K_BDEPS,
50 K_BROKEN,
51 K_CATEGORY,
52 K_CITEM,
53 K_CONFFILES,
54 K_CONFSYMS,
55 K_CSYM,
56 K_DASHVER,
57 K_DEFLT,
58 K_DESC,
59 K_FLAVOURS,
60 K_GROUPS,
61 K_HASHES,
62 K_HELP,
63 K_MDEPS,
64 K_MENUITEM,
65 K_MULTIPKGS,
66 K_NAME,
67 K_PERMIT_BIN,
68 K_PERMIT_SRC,
69 K_PKGDEPS,
70 K_PKGNAME,
71 K_RCCONF_SYMS,
72 K_SDEPS,
73 K_SITES,
74 K_URLS,
75 K_USERS,
76 K_VDEPS,
77 K_VERSION,
78 KX_INVALID
79 };
80 #define parser_kwords enum kwords
81
82 #include "extern.h"
83
84 static const struct parser_keywords kwords[] = {
85 /* sorted but shortest-match aware */
86 { "BROKEN", K_BROKEN, KWT_NORMAL, ARGT_STRING },
87 { "BUILDDEPS", K_BDEPS, KWT_MULTI, ARGT_STRING },
88 { "CATEGORY", K_CATEGORY, KWT_MULTI, ARGT_STRING },
89 { "CITEM", K_CITEM, KWT_MULTI, ARGT_STRING },
90 { "CONFFILES", K_CONFFILES, KWT_MULTI, ARGT_STRING },
91 { "CONFSYMS", K_CONFSYMS, KWT_NORMAL, ARGT_STRING },
92 { "CSYMDEPS", K_SDEPS, KWT_MULTI, ARGT_STRING },
93 { "CSYM", K_CSYM, KWT_MULTI, ARGT_STRING },
94 { "CVALDEPS", K_VDEPS, KWT_MULTI, ARGT_STRING },
95 { "DASHVER", K_DASHVER, KWT_NORMAL, ARGT_INTEGER },
96 { "DEFAULT", K_DEFLT, KWT_MULTI, ARGT_STRING },
97 { "DESCRIPTION", K_DESC, KWT_MULTI, ARGT_STRING },
98 { "DISTFILES", KN_DISTFILES, KWT_NORMAL, ARGT_INTEGER },
99 { "DISTFILE", KA_DISTFILE, KWT_ITERATED, ARGT_STRING },
100 { "FLAVOURS", K_FLAVOURS, KWT_MULTI, ARGT_STRING },
101 { "GROUPS", K_GROUPS, KWT_NORMAL, ARGT_STRING },
102 { "HASHES", K_HASHES, KWT_NORMAL, ARGT_STRING },
103 { "HASH", KA_HASH, KWT_MULTITOP, ARGT_STRING },
104 { "HELPTEXT", K_HELP, KWT_MULTI, ARGT_STRING },
105 { "MASTER_SITES", K_SITES, KWT_ITERATED, ARGT_STRING },
106 { "MENUDEPS", K_MDEPS, KWT_MULTI, ARGT_STRING },
107 { "MENUITEM", K_MENUITEM, KWT_MULTI, ARGT_STRING },
108 { "MULTIPKGS", K_MULTIPKGS, KWT_NORMAL, ARGT_STRING },
109 { "NAME", K_NAME, KWT_NORMAL, ARGT_STRING },
110 { "PERMIT_BIN", K_PERMIT_BIN, KWT_MULTI, ARGT_STRING },
111 { "PERMIT_SRC", K_PERMIT_SRC, KWT_NORMAL, ARGT_STRING },
112 { "PKGDEPS", K_PKGDEPS, KWT_MULTI, ARGT_STRING },
113 { "PKGNAME", K_PKGNAME, KWT_NORMAL, ARGT_STRING },
114 { "RCCONF_SYMS", K_RCCONF_SYMS, KWT_NORMAL, ARGT_INTEGER },
115 { "RCCONF", KA_RCCONF, KWT_MULTITER, ARGT_STRING },
116 { "URLS", K_URLS, KWT_NORMAL, ARGT_STRING },
117 { "USERS", K_USERS, KWT_NORMAL, ARGT_STRING },
118 { "VERSION", K_VERSION, KWT_NORMAL, ARGT_STRING },
119 { NULL, KX_INVALID, KWT_INVALID, ARGT_INVALID }
120 };
121
122 static const enum kwords zeroiter[] = {
123 /* for these, an iter of 0 is set to 1 later */
124 KA_DISTFILE,
125 K_SITES,
126 KX_INVALID,
127 /* for these, an iter of 0 is an error */
128 KA_RCCONF,
129 KX_INVALID
130 };
131
132 static void do_defaultvalues(struct parser_result *);
133 static void do_varexpand(struct parser_result *);
134
135 void
136 pfile(const char *fn)
137 {
138 struct parser_result *parsed;
139 struct parser_res *entry;
140 int fd;
141 size_t nument;
142
143 if ((fd = open(fn, O_RDONLY)) < 0)
144 err(255, "cannot open input file '%s'", fn);
145 printf("parsing %s…", fn);
146 if (parser_errpfx != NULL)
147 free(parser_errpfx);
148 parser_errpfx = strdup(fn);
149 parsed = nfo_parse(fd, kwords);
150 free(parser_errpfx);
151 parser_errpfx = NULL;
152 close(fd);
153 if (CIRCLEQ_EMPTY(parsed))
154 errx(1, "error, no entries in the file!");
155 nument = 0;
156 CIRCLEQ_FOREACH(entry, parsed, e)
157 ++nument;
158 printf("ok, %zu entries\n", nument);
159
160 do_defaultvalues(parsed);
161 do_varexpand(parsed);
162
163 /* do something with ‘parsed’ */
164 nument = 0;
165 CIRCLEQ_FOREACH(entry, parsed, e) {
166 printf("ent #%03zu: ", nument++);
167 parser_dump(entry, kwords);
168 }
169
170 parser_free(parsed);
171 }
172
173 static struct defaultvalue {
174 parser_kwords prefix;
175 enum parser_kwtype type;
176 const char *fmt;
177 } defaultvalues[] = {
178 { K_BROKEN, KWT_NORMAL, "n" },
179 { K_DASHVER, KWT_NORMAL, "1" },
180 { KX_INVALID, KWT_INVALID, NULL }
181 };
182
183 static void
184 do_defaultvalues(struct parser_result *head)
185 {
186 struct parser_res *entry, *evar;
187
188 /* we only do some expansion here, not yet checking for required */
189
190 }
191
192 static void
193 do_varexpand(struct parser_result *head)
194 {
195 struct parser_res *entry, *evar;
196 char ch, *cp, *tp, *dp;
197 bool do_again;
198
199 expand_loop:
200 do_again = false;
201 CIRCLEQ_FOREACH(entry, head, e) {
202 if ((cp = entry->value) == NULL)
203 continue;
204 /* scan the value for variable references */
205 while ((ch = *cp++))
206 if (ch == '\\')
207 cp++;
208 else if (ch == '$')
209 break;
210 if (!ch)
211 continue;
212 /* cp points past a dollar sign, copy head */
213 dp = str_nsave(entry->value, cp - entry->value - 1);
214 /* read variable name */
215 if (*cp != '{' /*}*/)
216 goto copy_rest;
217 tp = ++cp;
218 while (*tp && (*tp != /*{*/ '}'))
219 ++tp;
220 if (*tp != /*{*/ '}')
221 goto copy_rest;
222 *tp++ = '\0';
223 /* variable name in cp, rest of string in tp */
224 evar = parse_lookupbyname(head, cp);
225 tp[-1] = /*{*/ '}';
226 cp = tp;
227 /* variable content in evar, rest of string in cp */
228 if (evar && evar->value)
229 dp = str_add(dp, evar->value);
230 else if (!evar)
231 D(1, "warning: expansion in '%s' undefined for '%s'\n",
232 entry->value, cp);
233 copy_rest:
234 dp = str_add(dp, cp);
235 D(2, "do_varexpand: '%s' -> '%s'\n", entry->value, dp);
236 free(entry->value);
237 entry->value = dp;
238 /* string was modified, so reloop */
239 do_again = true;
240 break;
241 }
242 if (do_again)
243 goto expand_loop;
244 /* all variable references have been expanded */
245 CIRCLEQ_FOREACH(entry, head, e) {
246 if ((cp = entry->value) == NULL)
247 continue;
248 if (strchr(cp, '\\') == NULL)
249 continue;
250 /* unescape backslashes */
251 tp = dp = str_save(cp);
252 while ((ch = *cp++)) {
253 if (ch == '\\')
254 ch = *cp++;
255 *tp++ = ch;
256 }
257 free(entry->value);
258 entry->value = str_nsave(dp, tp - dp);
259 free(dp);
260 }
261 }
262
263 struct parser_res *
264 parse_lookup(struct parser_result *head, struct parser_res *sample)
265 {
266 struct parser_res *rv;
267 char *name;
268
269 if (head == NULL || sample == NULL)
270 return (NULL);
271 if ((name = parse_fmt(sample->keyword, sample->itype,
272 sample->kw_multi, sample->kw_iter, 0)) == NULL)
273 return (NULL);
274 rv = parse_lookupbyname(head, name);
275 free(name);
276 return (rv);
277 }
278
279 char *
280 varnameck(const char *func, const char *ivar)
281 {
282 char *ovar, *cp;
283
284 /* make “ivar” upper-case and validate */
285 cp = ovar = str_save(ivar);
286 if (*cp >= '0' && *cp <= '9')
287 errx(1, "%s: variable name '%s' must not begin with a digit!",
288 func, ivar);
289 while (*cp) {
290 if (*cp >= 'a' && *cp <= 'z')
291 *cp = *cp - 0x20;
292 else if ((*cp < 'A' || *cp > 'Z') && *cp != '_' &&
293 (*cp < '0' || *cp > '9'))
294 errx(1, "%s: variable name '%s' contains invalid"
295 " char %02X!", func, ivar, (uint8_t)(*cp));
296 ++cp;
297 }
298 return (ovar);
299 }
300
301 struct parser_res *
302 parse_lookupbyname(struct parser_result *head, const char *name)
303 {
304 struct parser_res *entry;
305 char *iname, *ename, *cp;
306 bool found = false;
307
308 if (head == NULL || name == NULL || *name == '\0')
309 return (NULL);
310
311 iname = varnameck(__func__, name);
312
313 D(2, "parse_lookupbyname: try '%s' (orig '%s')\n", iname, name);
314
315 CIRCLEQ_FOREACH(entry, head, e) {
316 /* recreate varname */
317 if ((ename = parse_fmt(entry->keyword, entry->itype,
318 entry->kw_multi, entry->kw_iter, 0)) == NULL)
319 continue;
320 /* upper-case, normalise */
321 ename = varnameck(__func__, cp = ename);
322 free(cp);
323 if (!strcmp(iname, ename))
324 found = true;
325 D(2, "parse_lookupbyname: cmp '%s', %smatch\n", ename,
326 found ? "" : "no ");
327 free(ename);
328 if (found)
329 break;
330 }
331 free(iname);
332 return (found ? entry : NULL);
333 }
334
335 char *
336 parse_fmt(parser_kwords kw, enum parser_kwtype kt, char *km, unsigned ki, int u)
337 {
338 char buf[64], *res;
339 const struct parser_keywords *kwp;
340
341 if (kt == KWT_INVALID)
342 return (NULL);
343 if ((kwp = parser_getkwbynum(kw, kwords)) == NULL) {
344 if (!u)
345 return (NULL);
346 snprintf(buf, sizeof (buf), "<unknown:%u>", (int)kw);
347 res = str_save(buf);
348 } else
349 res = str_save(kwp->kwprefix);
350 if (kt == KWT_NORMAL)
351 return (res);
352 if (kt == KWT_MULTITOP)
353 kt = KWT_MULTITER;
354 if (kt == KWT_ITERATED || kt == KWT_MULTITER) {
355 snprintf(buf, sizeof (buf), "_%u", ki);
356 res = str_add(res, buf);
357 }
358 if (kt == KWT_MULTI || kt == KWT_MULTITER) {
359 buf[0] = '_';
360 strlcpy(buf + 1, km, sizeof (buf) - 1);
361 res = str_add(res, buf);
362 }
363 if (kt == KWT_MULTI || kt == KWT_ITERATED || kt == KWT_MULTITER)
364 return (res);
365 /* invalid KWT */
366 free(res);
367 return (NULL);
368 }
369
370 char *
371 parse_fms(const char *fmt, struct parser_res *entry)
372 {
373 if (entry == NULL)
374 return (NULL);
375 return (xasprintf(fmt, entry->kw_multi, entry->kw_iter));
376 }

root@freewrt.org:443
ViewVC Help
Powered by ViewVC 1.1.20