Annotation of mandoc/tag.c, Revision 1.5
1.5 ! schwarze 1: /* $Id: tag.c,v 1.4 2015/07/25 14:02:06 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: /*
1.5 ! schwarze 81: * Set the line number where a term is defined,
! 82: * unless it is already defined at a higher priority.
1.1 schwarze 83: */
84: void
1.5 ! schwarze 85: tag_put(const char *s, int prio, size_t line)
1.1 schwarze 86: {
87: struct tag_entry *entry;
1.5 ! schwarze 88: size_t len;
1.1 schwarze 89: unsigned int slot;
90:
91: if (tag_fd == -1)
92: return;
1.5 ! schwarze 93: slot = ohash_qlookup(&tag_data, s);
1.1 schwarze 94: entry = ohash_find(&tag_data, slot);
95: if (entry == NULL) {
1.5 ! schwarze 96: len = strlen(s) + 1;
! 97: entry = mandoc_malloc(sizeof(*entry) + len);
1.1 schwarze 98: memcpy(entry->s, s, len);
99: ohash_insert(&tag_data, slot, entry);
1.5 ! schwarze 100: } else if (entry->prio <= prio)
! 101: return;
1.1 schwarze 102: entry->line = line;
1.4 schwarze 103: entry->prio = prio;
1.1 schwarze 104: }
105:
106: /*
107: * Write out the tags file using the previously collected
108: * information and clear the ohash table while going along.
109: */
110: void
111: tag_write(void)
112: {
113: FILE *stream;
114: struct tag_entry *entry;
115: unsigned int slot;
116:
117: if (tag_fd == -1)
118: return;
119: stream = fdopen(tag_fd, "w");
120: entry = ohash_first(&tag_data, &slot);
121: while (entry != NULL) {
122: if (stream != NULL)
123: fprintf(stream, "%s - %zu\n", entry->s, entry->line);
124: free(entry);
125: entry = ohash_next(&tag_data, &slot);
126: }
127: ohash_delete(&tag_data);
128: if (stream != NULL)
129: fclose(stream);
130: }
131:
132: void
133: tag_unlink(void)
134: {
135:
136: if (tag_fn != NULL)
137: unlink(tag_fn);
1.2 schwarze 138: }
139:
140: static void
141: tag_signal(int signum)
142: {
143:
144: tag_unlink();
145: signal(signum, SIG_DFL);
146: kill(getpid(), signum);
147: /* NOTREACHED */
148: _exit(1);
1.1 schwarze 149: }
150:
151: /*
152: * Memory management callback functions for ohash.
153: */
154: static void *
155: tag_alloc(size_t sz, void *arg)
156: {
157:
158: return(mandoc_malloc(sz));
159: }
160:
161: static void *
162: tag_calloc(size_t nmemb, size_t sz, void *arg)
163: {
164:
165: return(mandoc_calloc(nmemb, sz));
166: }
167:
168: static void
169: tag_free(void *p, void *arg)
170: {
171:
172: free(p);
173: }
CVSweb