rewrite man to make the configuration file more flexible
[unix-history] / usr / src / usr.bin / man / config.c
CommitLineData
1ef31675 1/*
00186a84
KB
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
1ef31675 4 *
f15db449 5 * %sccs.include.redist.c%
1ef31675
KB
6 */
7
8#ifndef lint
da0c0e56 9static char sccsid[] = "@(#)config.c 8.2 (Berkeley) %G%";
1ef31675
KB
10#endif /* not lint */
11
da0c0e56
KB
12#include <sys/types.h>
13#include <sys/queue.h>
14
15#include <ctype.h>
16#include <err.h>
1ef31675 17#include <errno.h>
da0c0e56 18#include <stdio.h>
011519cd 19#include <stdlib.h>
da0c0e56 20#include <string.h>
011519cd 21
da0c0e56
KB
22#include "config.h"
23#include "pathnames.h"
1ef31675 24
da0c0e56 25struct queue_entry head;
011519cd 26
1ef31675 27/*
da0c0e56
KB
28 * config --
29 *
30 * Read the configuration file and build a doubly linked
31 * list that looks like:
32 *
33 * tag1 <-> record <-> record <-> record
34 * |
35 * tag2 <-> record <-> record <-> record
1ef31675 36 */
da0c0e56
KB
37void
38config()
1ef31675 39{
da0c0e56
KB
40 ENTRY *ep, *qp;
41 FILE *cfp;
011519cd 42 size_t len;
da0c0e56
KB
43 int lcnt;
44 char *p, *t;
45
46 if ((cfp = fopen(_PATH_MANCONF, "r")) == NULL)
47 err(1, "%s", _PATH_MANCONF);
48 queue_init(&head);
49 for (lcnt = 1; (p = fgetline(cfp, &len)) != NULL; ++lcnt) {
50 if (!len) /* Skip empty lines. */
51 continue;
52 if (p[len - 1] != '\n') { /* Skip corrupted lines. */
53 warnx("%s: line %d corrupted", _PATH_MANCONF, lcnt);
54 continue;
011519cd 55 }
da0c0e56
KB
56 p[len - 1] = '\0'; /* Terminate the line. */
57
58 /* Skip leading space. */
59 for (; *p != '\0' && isspace(*p); ++p);
60 /* Skip empty/comment lines. */
61 if (*p == '\0' || *p == '#')
011519cd 62 continue;
da0c0e56
KB
63 /* Find first token. */
64 for (t = p; *t && !isspace(*t); ++t);
65 if (*t == '\0') /* Need more than one token.*/
011519cd 66 continue;
da0c0e56
KB
67 *t = '\0';
68
69 for (qp = head.qe_next; /* Find any matching tag. */
70 qp != NULL && strcmp(p, qp->s); qp = qp->tags.qe_next);
71
72 if (qp == NULL) /* Create a new tag. */
73 qp = addlist(p);
74
75 /*
76 * Attach new records. The keyword _build takes the rest of
77 * the line as a single entity, everything else is white
78 * space separated. The reason we're not just using strtok(3)
79 * for all of the parsing is so we don't get caught if a line
80 * has only a single token on it.
81 */
82 if (!strcmp(p, "_build")) {
83 while (*++t && isspace(*t));
84 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
85 (ep->s = strdup(t)) == NULL)
86 err(1, NULL);
87 queue_enter_tail(&qp->list, ep, ENTRY *, list);
88 } else while ((p = strtok(t + 1, " \t\n")) != NULL) {
89 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
90 (ep->s = strdup(p)) == NULL)
91 err(1, NULL);
92 queue_enter_tail(&qp->list, ep, ENTRY *, list);
93 t = NULL;
011519cd
KB
94 }
95 }
011519cd 96}
1ef31675 97
da0c0e56
KB
98/*
99 * addlist --
100 * Add a tag to the list.
101 */
102ENTRY *
103addlist(name)
104 char *name;
011519cd 105{
da0c0e56
KB
106 ENTRY *ep;
107
108 if ((ep = malloc(sizeof(ENTRY))) == NULL ||
109 (ep->s = strdup(name)) == NULL)
110 err(1, NULL);
111 queue_init(&ep->list);
112 queue_enter_head(&head, ep, ENTRY *, tags);
113 return (head.qe_next);
011519cd
KB
114}
115
da0c0e56
KB
116/*
117 * getlist --
118 * Return the linked list for a tag if it exists.
119 */
120ENTRY *
121getlist(name)
122 char *name;
011519cd 123{
da0c0e56 124 ENTRY *qp;
011519cd 125
da0c0e56
KB
126 for (qp = head.qe_next; qp != NULL; qp = qp->tags.qe_next)
127 if (!strcmp(name, qp->s))
128 return (qp);
129 return (NULL);
1ef31675
KB
130}
131
da0c0e56
KB
132void
133debug(l)
134 char *l;
011519cd 135{
da0c0e56 136 ENTRY *ep, *qp;
011519cd 137
da0c0e56
KB
138 (void)printf("%s ===============\n", l);
139 for (qp = head.qe_next; qp != NULL; qp = qp->tags.qe_next) {
140 printf("%s\n", qp->s);
141 for (ep = qp->list.qe_next; ep != NULL; ep = ep->list.qe_next)
142 printf("\t%s\n", ep->s);
011519cd 143 }
1ef31675 144}