Annotation of src/usr.bin/mandoc/tag.c, Revision 1.3
1.3 ! schwarze 1: /* $OpenBSD: tag.c,v 1.2 2015/07/18 03:40:51 schwarze Exp $ */
1.1 schwarze 2: /*
3: * Copyright (c) 2015 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 AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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: */
17: #include <sys/types.h>
18:
1.2 schwarze 19: #include <signal.h>
1.1 schwarze 20: #include <stddef.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
25:
26: #include <ohash.h>
27:
28: #include "mandoc_aux.h"
29: #include "tag.h"
30:
31: struct tag_entry {
32: size_t line;
33: char s[];
34: };
35:
1.2 schwarze 36: static void tag_signal(int);
1.1 schwarze 37: static void *tag_alloc(size_t, void *);
38: static void tag_free(void *, void *);
39: static void *tag_calloc(size_t, size_t, void *);
40:
41: static struct ohash tag_data;
42: static char *tag_fn = NULL;
43: static int tag_fd = -1;
44:
45:
46: /*
47: * Set up the ohash table to collect output line numbers
48: * where various marked-up terms are documented and create
49: * the temporary tags file, saving the name for the pager.
50: */
1.3 ! schwarze 51: char *
1.1 schwarze 52: tag_init(void)
53: {
54: struct ohash_info tag_info;
55:
56: tag_fn = mandoc_strdup("/tmp/man.XXXXXXXXXX");
1.2 schwarze 57: signal(SIGHUP, tag_signal);
58: signal(SIGINT, tag_signal);
59: signal(SIGTERM, tag_signal);
1.1 schwarze 60: if ((tag_fd = mkstemp(tag_fn)) == -1) {
61: free(tag_fn);
62: tag_fn = NULL;
1.3 ! schwarze 63: return(NULL);
1.1 schwarze 64: }
65:
66: tag_info.alloc = tag_alloc;
67: tag_info.calloc = tag_calloc;
68: tag_info.free = tag_free;
69: tag_info.key_offset = offsetof(struct tag_entry, s);
70: tag_info.data = NULL;
71: ohash_init(&tag_data, 4, &tag_info);
72: return(tag_fn);
73: }
74:
75: /*
76: * Return the line number where a term is defined,
77: * or 0 if the term is unknown.
78: */
79: size_t
80: tag_get(const char *s, size_t len)
81: {
82: struct tag_entry *entry;
83: const char *end;
84: unsigned int slot;
85:
86: if (tag_fd == -1)
87: return(0);
88: if (len == 0)
89: len = strlen(s);
90: end = s + len;
91: slot = ohash_qlookupi(&tag_data, s, &end);
92: entry = ohash_find(&tag_data, slot);
93: return(entry == NULL ? 0 : entry->line);
94: }
95:
96: /*
97: * Set the line number where a term is defined.
98: */
99: void
100: tag_put(const char *s, size_t len, size_t line)
101: {
102: struct tag_entry *entry;
103: const char *end;
104: unsigned int slot;
105:
106: if (tag_fd == -1)
107: return;
108: if (len == 0)
109: len = strlen(s);
110: end = s + len;
111: slot = ohash_qlookupi(&tag_data, s, &end);
112: entry = ohash_find(&tag_data, slot);
113: if (entry == NULL) {
114: entry = mandoc_malloc(sizeof(*entry) + len + 1);
115: memcpy(entry->s, s, len);
116: entry->s[len] = '\0';
117: ohash_insert(&tag_data, slot, entry);
118: }
119: entry->line = line;
120: }
121:
122: /*
123: * Write out the tags file using the previously collected
124: * information and clear the ohash table while going along.
125: */
126: void
127: tag_write(void)
128: {
129: FILE *stream;
130: struct tag_entry *entry;
131: unsigned int slot;
132:
133: if (tag_fd == -1)
134: return;
135: stream = fdopen(tag_fd, "w");
136: entry = ohash_first(&tag_data, &slot);
137: while (entry != NULL) {
138: if (stream != NULL)
139: fprintf(stream, "%s - %zu\n", entry->s, entry->line);
140: free(entry);
141: entry = ohash_next(&tag_data, &slot);
142: }
143: ohash_delete(&tag_data);
144: if (stream != NULL)
145: fclose(stream);
146: }
147:
148: void
149: tag_unlink(void)
150: {
151:
152: if (tag_fn != NULL)
153: unlink(tag_fn);
1.2 schwarze 154: }
155:
156: static void
157: tag_signal(int signum)
158: {
159:
160: tag_unlink();
161: signal(signum, SIG_DFL);
162: kill(getpid(), signum);
163: /* NOTREACHED */
164: _exit(1);
1.1 schwarze 165: }
166:
167: /*
168: * Memory management callback functions for ohash.
169: */
170: static void *
171: tag_alloc(size_t sz, void *arg)
172: {
173:
174: return(mandoc_malloc(sz));
175: }
176:
177: static void *
178: tag_calloc(size_t nmemb, size_t sz, void *arg)
179: {
180:
181: return(mandoc_calloc(nmemb, sz));
182: }
183:
184: static void
185: tag_free(void *p, void *arg)
186: {
187:
188: free(p);
189: }