Annotation of mandoc/tag.c, Revision 1.2
1.2 ! schwarze 1: /* $Id: tag.c,v 1.1 2015/07/17 22:38:29 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: */
55: void
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;
67: return;
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: }
77:
78: char *
79: tag_filename(void)
80: {
81:
82: return(tag_fn);
83: }
84:
85: /*
86: * Return the line number where a term is defined,
87: * or 0 if the term is unknown.
88: */
89: size_t
90: tag_get(const char *s, size_t len)
91: {
92: struct tag_entry *entry;
93: const char *end;
94: unsigned int slot;
95:
96: if (tag_fd == -1)
97: return(0);
98: if (len == 0)
99: len = strlen(s);
100: end = s + len;
101: slot = ohash_qlookupi(&tag_data, s, &end);
102: entry = ohash_find(&tag_data, slot);
103: return(entry == NULL ? 0 : entry->line);
104: }
105:
106: /*
107: * Set the line number where a term is defined.
108: */
109: void
110: tag_put(const char *s, size_t len, size_t line)
111: {
112: struct tag_entry *entry;
113: const char *end;
114: unsigned int slot;
115:
116: if (tag_fd == -1)
117: return;
118: if (len == 0)
119: len = strlen(s);
120: end = s + len;
121: slot = ohash_qlookupi(&tag_data, s, &end);
122: entry = ohash_find(&tag_data, slot);
123: if (entry == NULL) {
124: entry = mandoc_malloc(sizeof(*entry) + len + 1);
125: memcpy(entry->s, s, len);
126: entry->s[len] = '\0';
127: ohash_insert(&tag_data, slot, entry);
128: }
129: entry->line = line;
130: }
131:
132: /*
133: * Write out the tags file using the previously collected
134: * information and clear the ohash table while going along.
135: */
136: void
137: tag_write(void)
138: {
139: FILE *stream;
140: struct tag_entry *entry;
141: unsigned int slot;
142:
143: if (tag_fd == -1)
144: return;
145: stream = fdopen(tag_fd, "w");
146: entry = ohash_first(&tag_data, &slot);
147: while (entry != NULL) {
148: if (stream != NULL)
149: fprintf(stream, "%s - %zu\n", entry->s, entry->line);
150: free(entry);
151: entry = ohash_next(&tag_data, &slot);
152: }
153: ohash_delete(&tag_data);
154: if (stream != NULL)
155: fclose(stream);
156: }
157:
158: void
159: tag_unlink(void)
160: {
161:
162: if (tag_fn != NULL)
163: unlink(tag_fn);
1.2 ! schwarze 164: }
! 165:
! 166: static void
! 167: tag_signal(int signum)
! 168: {
! 169:
! 170: tag_unlink();
! 171: signal(signum, SIG_DFL);
! 172: kill(getpid(), signum);
! 173: /* NOTREACHED */
! 174: _exit(1);
1.1 schwarze 175: }
176:
177: /*
178: * Memory management callback functions for ohash.
179: */
180: static void *
181: tag_alloc(size_t sz, void *arg)
182: {
183:
184: return(mandoc_malloc(sz));
185: }
186:
187: static void *
188: tag_calloc(size_t nmemb, size_t sz, void *arg)
189: {
190:
191: return(mandoc_calloc(nmemb, sz));
192: }
193:
194: static void
195: tag_free(void *p, void *arg)
196: {
197:
198: free(p);
199: }
CVSweb