[BACK]Return to tag.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

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