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