Annotation of docbook2mdoc/reorg.c, Revision 1.5
1.5 ! schwarze 1: /* $Id: reorg.c,v 1.4 2019/04/28 20:26:49 schwarze Exp $ */
1.1 schwarze 2: /*
3: * Copyright (c) 2019 Ingo Schwarze <schwarze@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
1.3 schwarze 17: #include "string.h"
1.1 schwarze 18:
19: #include "node.h"
20: #include "reorg.h"
21:
22: /*
23: * The implementation of the tree reorganizer.
24: */
25:
1.2 schwarze 26: static void
1.5 ! schwarze 27: reorg_root(struct pnode *root, const char *sec)
1.1 schwarze 28: {
1.4 schwarze 29: struct pnode *date, *info, *name, *vol, *nc;
1.1 schwarze 30:
1.2 schwarze 31: if (root == NULL)
1.1 schwarze 32: return;
33:
34: /* Collect prologue information. */
35:
36: if ((date = pnode_takefirst(root, NODE_PUBDATE)) == NULL &&
37: (date = pnode_takefirst(root, NODE_DATE)) == NULL) {
38: date = pnode_alloc(NULL);
39: pnode_alloc_text(date, "$Mdocdate" "$");
40: }
41: date->node = NODE_DATE;
42: date->parent = root;
43:
44: name = vol = NULL;
45: if ((nc = pnode_findfirst(root, NODE_REFMETA)) != NULL) {
46: name = pnode_takefirst(nc, NODE_REFENTRYTITLE);
47: vol = pnode_takefirst(nc, NODE_MANVOLNUM);
48: }
49: if (name == NULL) {
50: name = pnode_alloc(NULL);
51: name->node = NODE_REFENTRYTITLE;
52: name->parent = root;
53: pnode_alloc_text(name,
54: pnode_getattr_raw(root, ATTRKEY_ID, "UNKNOWN"));
55: }
1.5 ! schwarze 56: if (vol == NULL || sec != NULL) {
! 57: pnode_unlink(vol);
1.1 schwarze 58: vol = pnode_alloc(NULL);
59: vol->node = NODE_MANVOLNUM;
60: vol->parent = root;
1.5 ! schwarze 61: pnode_alloc_text(vol, sec == NULL ? "1" : sec);
1.1 schwarze 62: }
63:
64: /* Insert prologue information at the beginning. */
65:
66: if (pnode_findfirst(root, NODE_REFNAMEDIV) == NULL &&
1.4 schwarze 67: ((info = pnode_findfirst(root, NODE_BOOKINFO)) != NULL ||
68: (info = pnode_findfirst(root, NODE_REFENTRYINFO)) != NULL)) {
69: if ((nc = pnode_takefirst(info, NODE_ABSTRACT)) != NULL)
70: TAILQ_INSERT_HEAD(&root->childq, nc, child);
71: if ((nc = pnode_takefirst(info, NODE_TITLE)) != NULL)
72: TAILQ_INSERT_HEAD(&root->childq, nc, child);
73: }
1.1 schwarze 74: TAILQ_INSERT_HEAD(&root->childq, vol, child);
75: TAILQ_INSERT_HEAD(&root->childq, name, child);
76: TAILQ_INSERT_HEAD(&root->childq, date, child);
1.2 schwarze 77: }
78:
79: static void
1.3 schwarze 80: reorg_refentry(struct pnode *n)
81: {
82: struct pnode *info, *meta, *nc, *title;
83: struct pnode *match, *later;
84:
85: /* Collect nodes that remained behind from the prologue. */
86:
87: meta = NULL;
88: info = pnode_takefirst(n, NODE_BOOKINFO);
89: if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) {
90: pnode_unlink(info);
91: info = NULL;
92: }
93: if (info == NULL) {
94: info = pnode_takefirst(n, NODE_REFENTRYINFO);
95: if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) {
96: pnode_unlink(info);
97: info = NULL;
98: }
99: if (info == NULL)
100: info = pnode_takefirst(n, NODE_INFO);
101: meta = pnode_takefirst(n, NODE_REFMETA);
102: if (meta != NULL && TAILQ_FIRST(&meta->childq) == NULL) {
103: pnode_unlink(meta);
104: meta = NULL;
105: }
106: }
107: if (info == NULL && meta == NULL)
108: return;
109:
110: /*
111: * Find the best place to put this information.
112: * Use the last existing AUTHORS node, if any.
113: * Otherwise, put it behind all standard sections that
114: * conventionally precede AUTHORS, and also behind any
115: * non-standard sections that follow the last of these,
116: * but before the next standard section.
117: */
118:
119: match = later = NULL;
120: TAILQ_FOREACH(nc, &n->childq, child) {
121: switch (nc->node) {
122: case NODE_REFENTRY:
123: case NODE_REFNAMEDIV:
124: case NODE_REFSYNOPSISDIV:
125: later = NULL;
126: continue;
127: case NODE_APPENDIX:
128: case NODE_INDEX:
129: if (later == NULL)
130: later = nc;
131: continue;
132: default:
133: break;
134: }
135: if ((title = pnode_findfirst(nc, NODE_TITLE)) == NULL ||
136: (title = TAILQ_FIRST(&title->childq)) == NULL ||
137: title->node != NODE_TEXT)
138: continue;
139: if (strcasecmp(title->b, "AUTHORS") == 0 ||
140: strcasecmp(title->b, "AUTHOR") == 0)
141: match = nc;
142: else if (strcasecmp(title->b, "NAME") == 0 ||
143: strcasecmp(title->b, "SYNOPSIS") == 0 ||
144: strcasecmp(title->b, "DESCRIPTION") == 0 ||
145: strcasecmp(title->b, "RETURN VALUES") == 0 ||
146: strcasecmp(title->b, "ENVIRONMENT") == 0 ||
147: strcasecmp(title->b, "FILES") == 0 ||
148: strcasecmp(title->b, "EXIT STATUS") == 0 ||
149: strcasecmp(title->b, "EXAMPLES") == 0 ||
150: strcasecmp(title->b, "DIAGNOSTICS") == 0 ||
151: strcasecmp(title->b, "ERRORS") == 0 ||
152: strcasecmp(title->b, "SEE ALSO") == 0 ||
153: strcasecmp(title->b, "STANDARDS") == 0 ||
154: strcasecmp(title->b, "HISTORY") == 0)
155: later = NULL;
156: else if ((strcasecmp(title->b, "CAVEATS") == 0 ||
157: strcasecmp(title->b, "BUGS") == 0) &&
158: later == NULL)
159: later = nc;
160: }
161:
162: /*
163: * If no AUTHORS section was found, create one from scratch,
164: * and insert that at the place selected earlier.
165: */
166:
167: if (match == NULL) {
168: match = pnode_alloc(NULL);
169: match->node = NODE_SECTION;
170: match->flags |= NFLAG_SPC;
171: match->parent = n;
172: nc = pnode_alloc(match);
173: nc->node = NODE_TITLE;
174: nc->flags |= NFLAG_SPC;
175: nc = pnode_alloc_text(nc, "AUTHORS");
176: nc->flags |= NFLAG_SPC;
177: if (later == NULL)
178: TAILQ_INSERT_TAIL(&n->childq, match, child);
179: else
180: TAILQ_INSERT_BEFORE(later, match, child);
181: }
182:
183: /*
184: * Dump the stuff excised at the beginning
185: * into this AUTHORS section.
186: */
187:
188: if (info != NULL)
189: TAILQ_INSERT_TAIL(&match->childq, info, child);
190: if (meta != NULL)
191: TAILQ_INSERT_TAIL(&match->childq, meta, child);
192: }
193:
194: static void
1.2 schwarze 195: default_title(struct pnode *n, const char *title)
196: {
197: struct pnode *nc;
198:
199: if (n->parent == NULL)
200: return;
201:
202: TAILQ_FOREACH(nc, &n->childq, child)
203: if (nc->node == NODE_TITLE)
204: return;
205:
206: nc = pnode_alloc(NULL);
207: nc->node = NODE_TITLE;
208: nc->parent = n;
209: TAILQ_INSERT_HEAD(&n->childq, nc, child);
210: pnode_alloc_text(nc, title);
211: }
212:
213: static void
214: reorg_recurse(struct pnode *n)
215: {
216: struct pnode *nc;
217:
218: if (n == NULL)
219: return;
220:
221: switch (n->node) {
1.4 schwarze 222: case NODE_ABSTRACT:
223: default_title(n, "Abstract");
224: n->node = NODE_SECTION;
225: break;
1.2 schwarze 226: case NODE_APPENDIX:
1.3 schwarze 227: if (n->parent == NULL)
228: reorg_refentry(n);
1.2 schwarze 229: default_title(n, "Appendix");
230: break;
231: case NODE_CAUTION:
232: default_title(n, "Caution");
233: n->node = NODE_NOTE;
234: break;
235: case NODE_LEGALNOTICE:
236: default_title(n, "Legal Notice");
237: n->node = NODE_SIMPLESECT;
238: break;
239: case NODE_NOTE:
240: default_title(n, "Note");
241: break;
242: case NODE_PREFACE:
1.3 schwarze 243: if (n->parent == NULL)
244: reorg_refentry(n);
1.2 schwarze 245: default_title(n, "Preface");
246: n->node = NODE_SECTION;
247: break;
1.3 schwarze 248: case NODE_REFENTRY:
249: reorg_refentry(n);
250: break;
1.2 schwarze 251: case NODE_SECTION:
1.3 schwarze 252: if (n->parent == NULL)
253: reorg_refentry(n);
254: /* FALLTHROUGH */
1.2 schwarze 255: case NODE_SIMPLESECT:
256: default_title(n, "Untitled");
257: break;
258: case NODE_TIP:
259: default_title(n, "Tip");
260: n->node = NODE_NOTE;
261: break;
262: case NODE_WARNING:
263: default_title(n, "Warning");
264: n->node = NODE_NOTE;
265: break;
266: default:
267: break;
268: }
269:
270: TAILQ_FOREACH(nc, &n->childq, child)
271: reorg_recurse(nc);
272: }
273:
274: void
1.5 ! schwarze 275: ptree_reorg(struct ptree *tree, const char *sec)
1.2 schwarze 276: {
1.5 ! schwarze 277: reorg_root(tree->root, sec);
1.2 schwarze 278: reorg_recurse(tree->root);
1.1 schwarze 279: }
CVSweb