kernel - support dummy reallocblks in devfs
[dragonfly.git] / usr.sbin / ndiscvt / inf.c
blobca04328e1c058913d2ad2f780c70a7375b1fa3f9
1 /*
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/usr.sbin/ndiscvt/inf.c,v 1.19 2008/12/27 08:03:32 weongyo Exp $
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
40 #include <sys/queue.h>
42 #include "inf.h"
44 extern FILE *yyin;
45 int yyparse (void);
47 const char *words[W_MAX]; /* More than we'll need. */
48 int idx;
50 static struct section_head sh;
51 static struct reg_head rh;
52 static struct assign_head ah;
54 static char *sstrdup (const char *);
55 static struct assign
56 *find_assign (const char *, const char *);
57 static struct assign
58 *find_next_assign
59 (struct assign *);
60 static struct section
61 *find_section (const char *);
62 static void dump_deviceids_pci (void);
63 static void dump_deviceids_pcmcia (void);
64 static void dump_deviceids_usb (void);
65 static void dump_pci_id (const char *);
66 static void dump_pcmcia_id (const char *);
67 static void dump_usb_id (const char *);
68 static void dump_regvals (void);
69 static void dump_paramreg (const struct section *,
70 const struct reg *, int);
72 static FILE *ofp;
74 int
75 inf_parse(FILE *fp, FILE *outfp)
77 TAILQ_INIT(&sh);
78 TAILQ_INIT(&rh);
79 TAILQ_INIT(&ah);
81 ofp = outfp;
82 yyin = fp;
83 yyparse();
85 dump_deviceids_pci();
86 dump_deviceids_pcmcia();
87 dump_deviceids_usb();
88 fprintf(outfp, "#ifdef NDIS_REGVALS\n");
89 dump_regvals();
90 fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
92 return (0);
95 void
96 section_add(const char *s)
98 struct section *sec;
100 sec = malloc(sizeof(struct section));
101 bzero(sec, sizeof(struct section));
102 sec->name = s;
103 TAILQ_INSERT_TAIL(&sh, sec, link);
105 return;
108 static struct assign *
109 find_assign(const char *s, const char *k)
111 struct assign *assign;
112 char newkey[256];
114 /* Deal with string section lookups. */
116 if (k != NULL && k[0] == '%') {
117 bzero(newkey, sizeof(newkey));
118 strncpy(newkey, k + 1, strlen(k) - 2);
119 k = newkey;
122 TAILQ_FOREACH(assign, &ah, link) {
123 if (strcasecmp(assign->section->name, s) == 0) {
124 if (k == NULL)
125 return(assign);
126 else
127 if (strcasecmp(assign->key, k) == 0)
128 return(assign);
131 return(NULL);
134 static struct assign *
135 find_next_assign(struct assign *a)
137 struct assign *assign;
139 TAILQ_FOREACH(assign, &ah, link) {
140 if (assign == a)
141 break;
144 assign = assign->link.tqe_next;
146 if (assign == NULL || assign->section != a->section)
147 return(NULL);
149 return (assign);
152 static const char *
153 stringcvt(const char *s)
155 struct assign *manf;
157 manf = find_assign("strings", s);
158 if (manf == NULL)
159 return(s);
160 return(manf->vals[0]);
163 struct section *
164 find_section(const char *s)
166 struct section *section;
168 TAILQ_FOREACH(section, &sh, link) {
169 if (strcasecmp(section->name, s) == 0)
170 return(section);
172 return(NULL);
175 static void
176 dump_pcmcia_id(const char *s)
178 char *manstr, *devstr;
179 char *p0, *p;
181 p0 = __DECONST(char *, s);
183 p = strchr(p0, '\\');
184 if (p == NULL)
185 return;
186 p0 = p + 1;
188 p = strchr(p0, '-');
189 if (p == NULL)
190 return;
191 *p = '\0';
193 manstr = p0;
195 /* Convert any underscores to spaces. */
197 while (*p0 != '\0') {
198 if (*p0 == '_')
199 *p0 = ' ';
200 p0++;
203 p0 = p + 1;
204 p = strchr(p0, '-');
205 if (p == NULL)
206 return;
207 *p = '\0';
209 devstr = p0;
211 /* Convert any underscores to spaces. */
213 while (*p0 != '\0') {
214 if (*p0 == '_')
215 *p0 = ' ';
216 p0++;
219 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
220 return;
223 static void
224 dump_pci_id(const char *s)
226 char *p;
227 char vidstr[7], didstr[7], subsysstr[14];
229 p = strcasestr(s, "VEN_");
230 if (p == NULL)
231 return;
232 p += 4;
233 strcpy(vidstr, "0x");
234 strncat(vidstr, p, 4);
235 p = strcasestr(s, "DEV_");
236 if (p == NULL)
237 return;
238 p += 4;
239 strcpy(didstr, "0x");
240 strncat(didstr, p, 4);
241 if (p == NULL)
242 return;
243 p = strcasestr(s, "SUBSYS_");
244 if (p == NULL)
245 strcpy(subsysstr, "0x00000000");
246 else {
247 p += 7;
248 strcpy(subsysstr, "0x");
249 strncat(subsysstr, p, 8);
252 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
253 return;
256 static void
257 dump_usb_id(const char *s)
259 char *p;
260 char vidstr[7], pidstr[7];
262 p = strcasestr(s, "VID_");
263 if (p == NULL)
264 return;
265 p += 4;
266 strcpy(vidstr, "0x");
267 strncat(vidstr, p, 4);
268 p = strcasestr(s, "PID_");
269 if (p == NULL)
270 return;
271 p += 4;
272 strcpy(pidstr, "0x");
273 strncat(pidstr, p, 4);
274 if (p == NULL)
275 return;
277 fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr);
280 static void
281 dump_deviceids_pci(void)
283 struct assign *manf, *dev;
284 struct section *sec;
285 struct assign *assign;
286 char xpsec[256];
287 int first = 1, found = 0;
289 /* Find manufacturer name */
290 manf = find_assign("Manufacturer", NULL);
292 nextmanf:
294 /* Find manufacturer section */
295 if (manf->vals[1] != NULL &&
296 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
297 strcasecmp(manf->vals[1], "NTx86") == 0 ||
298 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
299 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
300 /* Handle Windows XP INF files. */
301 snprintf(xpsec, sizeof(xpsec), "%s.%s",
302 manf->vals[0], manf->vals[1]);
303 sec = find_section(xpsec);
304 } else
305 sec = find_section(manf->vals[0]);
307 /* See if there are any PCI device definitions. */
309 TAILQ_FOREACH(assign, &ah, link) {
310 if (assign->section == sec) {
311 dev = find_assign("strings", assign->key);
312 if (strcasestr(assign->vals[1], "PCI") != NULL) {
313 found++;
314 break;
319 if (found == 0)
320 goto done;
322 found = 0;
324 if (first == 1) {
325 /* Emit start of PCI device table */
326 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
327 first = 0;
330 retry:
333 * Now run through all the device names listed
334 * in the manufacturer section and dump out the
335 * device descriptions and vendor/device IDs.
338 TAILQ_FOREACH(assign, &ah, link) {
339 if (assign->section == sec) {
340 dev = find_assign("strings", assign->key);
341 /* Emit device IDs. */
342 if (strcasestr(assign->vals[1], "PCI") != NULL)
343 dump_pci_id(assign->vals[1]);
344 else
345 continue;
346 /* Emit device description */
347 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
348 found++;
352 /* Someone tried to fool us. Shame on them. */
353 if (!found) {
354 found++;
355 sec = find_section(manf->vals[0]);
356 goto retry;
359 /* Handle Manufacturer sections with multiple entries. */
360 manf = find_next_assign(manf);
362 if (manf != NULL)
363 goto nextmanf;
365 done:
366 /* Emit end of table */
368 fprintf(ofp, "\n\n");
370 return;
373 static void
374 dump_deviceids_pcmcia(void)
376 struct assign *manf, *dev;
377 struct section *sec;
378 struct assign *assign;
379 char xpsec[256];
380 int first = 1, found = 0;
382 /* Find manufacturer name */
383 manf = find_assign("Manufacturer", NULL);
385 nextmanf:
387 /* Find manufacturer section */
388 if (manf->vals[1] != NULL &&
389 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
390 strcasecmp(manf->vals[1], "NTx86") == 0 ||
391 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
392 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
393 /* Handle Windows XP INF files. */
394 snprintf(xpsec, sizeof(xpsec), "%s.%s",
395 manf->vals[0], manf->vals[1]);
396 sec = find_section(xpsec);
397 } else
398 sec = find_section(manf->vals[0]);
400 /* See if there are any PCMCIA device definitions. */
402 TAILQ_FOREACH(assign, &ah, link) {
403 if (assign->section == sec) {
404 dev = find_assign("strings", assign->key);
405 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
406 found++;
407 break;
412 if (found == 0)
413 goto done;
415 found = 0;
417 if (first == 1) {
418 /* Emit start of PCMCIA device table */
419 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
420 first = 0;
423 retry:
426 * Now run through all the device names listed
427 * in the manufacturer section and dump out the
428 * device descriptions and vendor/device IDs.
431 TAILQ_FOREACH(assign, &ah, link) {
432 if (assign->section == sec) {
433 dev = find_assign("strings", assign->key);
434 /* Emit device IDs. */
435 if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
436 dump_pcmcia_id(assign->vals[1]);
437 else
438 continue;
439 /* Emit device description */
440 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
441 found++;
445 /* Someone tried to fool us. Shame on them. */
446 if (!found) {
447 found++;
448 sec = find_section(manf->vals[0]);
449 goto retry;
452 /* Handle Manufacturer sections with multiple entries. */
453 manf = find_next_assign(manf);
455 if (manf != NULL)
456 goto nextmanf;
458 done:
459 /* Emit end of table */
461 fprintf(ofp, "\n\n");
463 return;
466 static void
467 dump_deviceids_usb(void)
469 struct assign *manf, *dev;
470 struct section *sec;
471 struct assign *assign;
472 char xpsec[256];
473 int first = 1, found = 0;
475 /* Find manufacturer name */
476 manf = find_assign("Manufacturer", NULL);
478 nextmanf:
480 /* Find manufacturer section */
481 if (manf->vals[1] != NULL &&
482 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
483 strcasecmp(manf->vals[1], "NTx86") == 0 ||
484 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
485 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
486 /* Handle Windows XP INF files. */
487 snprintf(xpsec, sizeof(xpsec), "%s.%s",
488 manf->vals[0], manf->vals[1]);
489 sec = find_section(xpsec);
490 } else
491 sec = find_section(manf->vals[0]);
493 /* See if there are any USB device definitions. */
495 TAILQ_FOREACH(assign, &ah, link) {
496 if (assign->section == sec) {
497 dev = find_assign("strings", assign->key);
498 if (strcasestr(assign->vals[1], "USB") != NULL) {
499 found++;
500 break;
505 if (found == 0)
506 goto done;
508 found = 0;
510 if (first == 1) {
511 /* Emit start of USB device table */
512 fprintf (ofp, "#define NDIS_USB_DEV_TABLE");
513 first = 0;
516 retry:
519 * Now run through all the device names listed
520 * in the manufacturer section and dump out the
521 * device descriptions and vendor/device IDs.
524 TAILQ_FOREACH(assign, &ah, link) {
525 if (assign->section == sec) {
526 dev = find_assign("strings", assign->key);
527 /* Emit device IDs. */
528 if (strcasestr(assign->vals[1], "USB") != NULL)
529 dump_usb_id(assign->vals[1]);
530 else
531 continue;
532 /* Emit device description */
533 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
534 found++;
538 /* Someone tried to fool us. Shame on them. */
539 if (!found) {
540 found++;
541 sec = find_section(manf->vals[0]);
542 goto retry;
545 /* Handle Manufacturer sections with multiple entries. */
546 manf = find_next_assign(manf);
548 if (manf != NULL)
549 goto nextmanf;
551 done:
552 /* Emit end of table */
554 fprintf(ofp, "\n\n");
556 return;
559 static void
560 dump_addreg(const char *s, int devidx)
562 struct section *sec;
563 struct reg *reg;
565 /* Find the addreg section */
566 sec = find_section(s);
568 /* Dump all the keys defined in it. */
569 TAILQ_FOREACH(reg, &rh, link) {
571 * Keys with an empty subkey are very easy to parse,
572 * so just deal with them here. If a parameter key
573 * of the same name also exists, prefer that one and
574 * skip this one.
576 if (reg->section == sec) {
577 if (reg->subkey == NULL) {
578 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
579 fprintf(ofp,"\n\t\"%s \",", reg->key);
580 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
581 reg->value == NULL ? "" :
582 stringcvt(reg->value), devidx);
583 } else if (strncasecmp(reg->subkey,
584 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
585 (reg->key != NULL && strcasecmp(reg->key,
586 "ParamDesc") == 0))
587 dump_paramreg(sec, reg, devidx);
591 return;
594 static void
595 dump_enumreg(const struct section *s, const struct reg *r)
597 struct reg *reg;
598 char enumkey[256];
600 sprintf(enumkey, "%s\\enum", r->subkey);
601 TAILQ_FOREACH(reg, &rh, link) {
602 if (reg->section != s)
603 continue;
604 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
605 continue;
606 fprintf(ofp, " [%s=%s]", reg->key,
607 stringcvt(reg->value));
609 return;
612 static void
613 dump_editreg(const struct section *s, const struct reg *r)
615 struct reg *reg;
617 TAILQ_FOREACH(reg, &rh, link) {
618 if (reg->section != s)
619 continue;
620 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
621 continue;
622 if (reg->key == NULL)
623 continue;
624 if (strcasecmp(reg->key, "LimitText") == 0)
625 fprintf(ofp, " [maxchars=%s]", reg->value);
626 if (strcasecmp(reg->key, "Optional") == 0 &&
627 strcmp(reg->value, "1") == 0)
628 fprintf(ofp, " [optional]");
630 return;
633 /* Use this for int too */
634 static void
635 dump_dwordreg(const struct section *s, const struct reg *r)
637 struct reg *reg;
639 TAILQ_FOREACH(reg, &rh, link) {
640 if (reg->section != s)
641 continue;
642 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
643 continue;
644 if (reg->key == NULL)
645 continue;
646 if (strcasecmp(reg->key, "min") == 0)
647 fprintf(ofp, " [min=%s]", reg->value);
648 if (strcasecmp(reg->key, "max") == 0)
649 fprintf(ofp, " [max=%s]", reg->value);
651 return;
654 static void
655 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
657 struct reg *reg;
658 TAILQ_FOREACH(reg, &rh, link) {
659 if (reg->section != s)
660 continue;
661 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
662 continue;
663 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
664 continue;
665 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
666 stringcvt(reg->value), devidx);
667 return;
669 /* Default registry entry missing */
670 fprintf(ofp, "\n\t{ \"\" }, %d },", devidx);
671 return;
674 static void
675 dump_paramdesc(const struct section *s, const struct reg *r)
677 struct reg *reg;
678 TAILQ_FOREACH(reg, &rh, link) {
679 if (reg->section != s)
680 continue;
681 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
682 continue;
683 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
684 continue;
685 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
686 break;
688 return;
691 static void
692 dump_typeinfo(const struct section *s, const struct reg *r)
694 struct reg *reg;
695 TAILQ_FOREACH(reg, &rh, link) {
696 if (reg->section != s)
697 continue;
698 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
699 continue;
700 if (reg->key == NULL)
701 continue;
702 if (strcasecmp(reg->key, "type"))
703 continue;
704 if (strcasecmp(reg->value, "dword") == 0 ||
705 strcasecmp(reg->value, "int") == 0)
706 dump_dwordreg(s, r);
707 if (strcasecmp(reg->value, "enum") == 0)
708 dump_enumreg(s, r);
709 if (strcasecmp(reg->value, "edit") == 0)
710 dump_editreg(s, r);
712 return;
715 static void
716 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
718 const char *keyname;
720 keyname = r->subkey + strlen("Ndi\\params\\");
721 fprintf(ofp, "\n\t{ \"%s\",", keyname);
722 dump_paramdesc(s, r);
723 dump_typeinfo(s, r);
724 fprintf(ofp, "\",");
725 dump_defaultinfo(s, r, devidx);
727 return;
730 static void
731 dump_regvals(void)
733 struct assign *manf, *dev;
734 struct section *sec;
735 struct assign *assign;
736 char sname[256];
737 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
739 /* Find signature to check for special case of WinNT. */
740 assign = find_assign("version", "signature");
741 if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
742 is_winnt++;
744 /* Emit start of block */
745 fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
747 /* Find manufacturer name */
748 manf = find_assign("Manufacturer", NULL);
750 nextmanf:
752 /* Find manufacturer section */
753 if (manf->vals[1] != NULL &&
754 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
755 strcasecmp(manf->vals[1], "NTx86") == 0 ||
756 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
757 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
758 is_winxp++;
759 /* Handle Windows XP INF files. */
760 snprintf(sname, sizeof(sname), "%s.%s",
761 manf->vals[0], manf->vals[1]);
762 sec = find_section(sname);
763 } else
764 sec = find_section(manf->vals[0]);
766 retry:
768 TAILQ_FOREACH(assign, &ah, link) {
769 if (assign->section == sec) {
770 found++;
772 * Find all the AddReg sections.
773 * Look for section names with .NT, unless
774 * this is a WinXP .INF file.
777 if (is_winxp) {
778 sprintf(sname, "%s.NTx86", assign->vals[0]);
779 dev = find_assign(sname, "AddReg");
780 if (dev == NULL) {
781 sprintf(sname, "%s.NT",
782 assign->vals[0]);
783 dev = find_assign(sname, "AddReg");
785 if (dev == NULL)
786 dev = find_assign(assign->vals[0],
787 "AddReg");
788 } else {
789 sprintf(sname, "%s.NT", assign->vals[0]);
790 dev = find_assign(sname, "AddReg");
791 if (dev == NULL && is_winnt)
792 dev = find_assign(assign->vals[0],
793 "AddReg");
795 /* Section not found. */
796 if (dev == NULL)
797 continue;
798 for (i = 0; i < W_MAX; i++) {
799 if (dev->vals[i] != NULL)
800 dump_addreg(dev->vals[i], devidx);
802 devidx++;
806 if (!found) {
807 sec = find_section(manf->vals[0]);
808 is_winxp = 0;
809 found++;
810 goto retry;
813 manf = find_next_assign(manf);
815 if (manf != NULL)
816 goto nextmanf;
818 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
820 return;
823 void
824 assign_add(const char *a)
826 struct assign *assign;
827 int i;
829 assign = malloc(sizeof(struct assign));
830 bzero(assign, sizeof(struct assign));
831 assign->section = TAILQ_LAST(&sh, section_head);
832 assign->key = sstrdup(a);
833 for (i = 0; i < idx; i++)
834 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
835 TAILQ_INSERT_TAIL(&ah, assign, link);
837 clear_words();
838 return;
841 void
842 define_add(const char *d __unused)
844 #ifdef notdef
845 fprintf(stderr, "define \"%s\"\n", d);
846 #endif
847 return;
850 static char *
851 sstrdup(const char *str)
853 if (str != NULL && strlen(str))
854 return (strdup(str));
855 return (NULL);
858 static int
859 satoi(const char *nptr)
861 if (nptr != NULL && strlen(nptr))
862 return (atoi(nptr));
863 return (0);
866 void
867 regkey_add(const char *r)
869 struct reg *reg;
871 reg = malloc(sizeof(struct reg));
872 bzero(reg, sizeof(struct reg));
873 reg->section = TAILQ_LAST(&sh, section_head);
874 reg->root = sstrdup(r);
875 reg->subkey = sstrdup(words[3]);
876 reg->key = sstrdup(words[2]);
877 reg->flags = satoi(words[1]);
878 reg->value = sstrdup(words[0]);
879 TAILQ_INSERT_TAIL(&rh, reg, link);
881 free(__DECONST(char *, r));
882 clear_words();
883 return;
886 void
887 push_word(const char *w)
889 if (w && strlen(w))
890 words[idx++] = w;
891 else
892 words[idx++] = NULL;
893 return;
896 void
897 clear_words(void)
899 int i;
901 for (i = 0; i < idx; i++) {
902 if (words[i]) {
903 free(__DECONST(char *, words[i]));
906 idx = 0;
907 bzero(words, sizeof(words));
908 return;