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