]>
git.cameronkatri.com Git - mandoc.git/blob - tag.c
1 /* $Id: tag.c,v 1.10 2015/10/13 15:53:05 schwarze Exp $ */
3 * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
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.
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.
19 #include <sys/types.h>
29 #include "mandoc_aux.h"
30 #include "mandoc_ohash.h"
39 static void tag_signal(int);
41 static struct ohash tag_data
;
42 static struct tag_files tag_files
;
46 * Prepare for using a pager.
47 * Not all pagers are capable of using a tag file,
48 * but for simplicity, create it anyway.
58 /* Save the original standard output for use by the pager. */
60 if ((tag_files
.ofd
= dup(STDOUT_FILENO
)) == -1)
63 /* Create both temporary output files. */
65 (void)strlcpy(tag_files
.ofn
, "/tmp/man.XXXXXXXXXX",
66 sizeof(tag_files
.ofn
));
67 (void)strlcpy(tag_files
.tfn
, "/tmp/man.XXXXXXXXXX",
68 sizeof(tag_files
.tfn
));
69 signal(SIGHUP
, tag_signal
);
70 signal(SIGINT
, tag_signal
);
71 signal(SIGTERM
, tag_signal
);
72 if ((ofd
= mkstemp(tag_files
.ofn
)) == -1)
74 if ((tag_files
.tfd
= mkstemp(tag_files
.tfn
)) == -1)
76 if (dup2(ofd
, STDOUT_FILENO
) == -1)
81 * Set up the ohash table to collect output line numbers
82 * where various marked-up terms are documented.
85 mandoc_ohash_init(&tag_data
, 4, offsetof(struct tag_entry
, s
));
92 if (tag_files
.ofd
!= -1)
94 if (tag_files
.tfd
!= -1)
96 *tag_files
.ofn
= '\0';
97 *tag_files
.tfn
= '\0';
104 * Set the line number where a term is defined,
105 * unless it is already defined at a higher priority.
108 tag_put(const char *s
, int prio
, size_t line
)
110 struct tag_entry
*entry
;
114 if (tag_files
.tfd
<= 0 || strchr(s
, ' ') != NULL
)
116 slot
= ohash_qlookup(&tag_data
, s
);
117 entry
= ohash_find(&tag_data
, slot
);
120 entry
= mandoc_malloc(sizeof(*entry
) + len
);
121 memcpy(entry
->s
, s
, len
);
122 ohash_insert(&tag_data
, slot
, entry
);
123 } else if (entry
->prio
<= prio
)
130 * Write out the tags file using the previously collected
131 * information and clear the ohash table while going along.
137 struct tag_entry
*entry
;
140 if (tag_files
.tfd
<= 0)
142 stream
= fdopen(tag_files
.tfd
, "w");
143 entry
= ohash_first(&tag_data
, &slot
);
144 while (entry
!= NULL
) {
146 fprintf(stream
, "%s %s %zu\n",
147 entry
->s
, tag_files
.ofn
, entry
->line
);
149 entry
= ohash_next(&tag_data
, &slot
);
151 ohash_delete(&tag_data
);
160 if (*tag_files
.ofn
!= '\0')
161 unlink(tag_files
.ofn
);
162 if (*tag_files
.tfn
!= '\0')
163 unlink(tag_files
.tfn
);
167 tag_signal(int signum
)
171 signal(signum
, SIG_DFL
);
172 kill(getpid(), signum
);