Annotation of docbook2mdoc/node.c, Revision 1.3
1.3 ! schwarze 1: /* $Id: node.c,v 1.2 2019/03/28 12:21:10 schwarze Exp $ */
1.1 schwarze 2: /*
3: * Copyright (c) 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4: * Copyright (c) 2019 Ingo Schwarze <schwarze@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18: #include <stdlib.h>
19: #include <string.h>
20:
21: #include "node.h"
22:
23: /*
24: * The implementation of the DocBook syntax tree.
25: */
26:
27: static const char *const attrkeys[ATTRKEY__MAX] = {
28: "choice",
29: "class",
30: "close",
1.3 ! schwarze 31: "cols",
1.1 schwarze 32: "id",
33: "linkend",
34: "open",
35: "rep"
36: };
37:
38: static const char *const attrvals[ATTRVAL__MAX] = {
39: "monospaced",
40: "norepeat",
41: "opt",
42: "plain",
43: "repeat",
44: "req"
45: };
46:
47: enum attrkey
48: attrkey_parse(const char *name)
49: {
50: enum attrkey key;
51:
52: for (key = 0; key < ATTRKEY__MAX; key++)
53: if (strcmp(name, attrkeys[key]) == 0)
54: break;
55: return key;
56: }
57:
58: enum attrval
59: attrval_parse(const char *name)
60: {
61: enum attrval val;
62:
63: for (val = 0; val < ATTRVAL__MAX; val++)
64: if (strcmp(name, attrvals[val]) == 0)
65: break;
66: return val;
67: }
68:
69: /*
70: * Recursively free a node (NULL is ok).
71: */
72: static void
73: pnode_free(struct pnode *pn)
74: {
75: struct pnode *pch;
76: struct pattr *ap;
77:
78: if (pn == NULL)
79: return;
80:
81: while ((pch = TAILQ_FIRST(&pn->childq)) != NULL) {
82: TAILQ_REMOVE(&pn->childq, pch, child);
83: pnode_free(pch);
84: }
85: while ((ap = TAILQ_FIRST(&pn->attrq)) != NULL) {
86: TAILQ_REMOVE(&pn->attrq, ap, child);
87: free(ap->rawval);
88: free(ap);
89: }
90: free(pn->real);
91: free(pn);
92: }
93:
94: /*
95: * Unlink a node from its parent and pnode_free() it.
96: */
97: void
98: pnode_unlink(struct pnode *pn)
99: {
100: if (pn == NULL)
101: return;
102: if (pn->parent != NULL)
103: TAILQ_REMOVE(&pn->parent->childq, pn, child);
104: pnode_free(pn);
105: }
106:
107: /*
108: * Unlink all children of a node and pnode_free() them.
109: */
110: void
111: pnode_unlinksub(struct pnode *pn)
112: {
113: while (TAILQ_EMPTY(&pn->childq) == 0)
114: pnode_unlink(TAILQ_FIRST(&pn->childq));
115: }
116:
117: /*
118: * Retrieve an enumeration attribute from a node.
119: * Return ATTRVAL__MAX if the node has no such attribute.
120: */
121: enum attrval
122: pnode_getattr(struct pnode *pn, enum attrkey key)
123: {
124: struct pattr *ap;
125:
126: if (pn == NULL)
127: return ATTRVAL__MAX;
128: TAILQ_FOREACH(ap, &pn->attrq, child)
129: if (ap->key == key)
130: return ap->val;
131: return ATTRVAL__MAX;
132: }
133:
134: /*
135: * Retrieve an attribute string from a node.
136: * Return defval if the node has no such attribute.
137: */
138: const char *
139: pnode_getattr_raw(struct pnode *pn, enum attrkey key, const char *defval)
140: {
141: struct pattr *ap;
142:
143: if (pn == NULL)
144: return defval;
145: TAILQ_FOREACH(ap, &pn->attrq, child)
146: if (ap->key == key)
1.2 schwarze 147: return ap->val != ATTRVAL__MAX ? attrvals[ap->val] :
148: ap->rawval != NULL ? ap->rawval : defval;
1.1 schwarze 149: return defval;
150: }
151:
152: /*
153: * Recursively search and return the first instance of "node".
154: */
155: struct pnode *
156: pnode_findfirst(struct pnode *pn, enum nodeid node)
157: {
158: struct pnode *pch, *res;
159:
160: if (pn->node == node)
161: return pn;
162: TAILQ_FOREACH(pch, &pn->childq, child)
163: if ((res = pnode_findfirst(pch, node)) != NULL)
164: return res;
165: return NULL;
166: }
CVSweb