diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | Makefile.depend | 5 | ||||
-rw-r--r-- | main.c | 69 | ||||
-rw-r--r-- | man.1 | 7 | ||||
-rw-r--r-- | mdoc_term.c | 22 | ||||
-rw-r--r-- | tag.c | 183 | ||||
-rw-r--r-- | tag.h | 27 | ||||
-rw-r--r-- | term.h | 1 | ||||
-rw-r--r-- | term_ascii.c | 4 |
9 files changed, 292 insertions, 29 deletions
@@ -93,6 +93,7 @@ SRCS = att.c \ roff.c \ soelim.c \ st.c \ + tag.c \ tbl.c \ tbl_data.c \ tbl_html.c \ @@ -160,6 +161,7 @@ DISTFILES = INSTALL \ soelim.1 \ st.in \ style.css \ + tag.h \ tbl.3 \ tbl.7 \ term.h \ @@ -234,6 +236,7 @@ BASE_OBJS = $(MANDOC_HTML_OBJS) \ main.o \ manpath.o \ out.o \ + tag.o \ tree.o MAIN_OBJS = $(BASE_OBJS) diff --git a/Makefile.depend b/Makefile.depend index 52e95807..1481d1cd 100644 --- a/Makefile.depend +++ b/Makefile.depend @@ -22,7 +22,7 @@ eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h manconf.h main.h lib.o: lib.c config.h roff.h mdoc.h libmdoc.h lib.in -main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h main.h manconf.h mansearch.h +main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h tag.h main.h manconf.h mansearch.h man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h man_hash.o: man_hash.c config.h roff.h man.h libman.h man_html.o: man_html.c config.h mandoc_aux.h roff.h man.h out.h html.h main.h @@ -42,7 +42,7 @@ mdoc_hash.o: mdoc_hash.c config.h roff.h mdoc.h libmdoc.h mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h -mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h main.h +mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h tag.h main.h mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h msec.o: msec.c config.h mandoc.h libmandoc.h msec.in out.o: out.c config.h mandoc_aux.h mandoc.h out.h @@ -51,6 +51,7 @@ read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h libmandoc.h ro roff.o: roff.c config.h mandoc.h mandoc_aux.h roff.h libmandoc.h roff_int.h libroff.h predefs.in soelim.o: soelim.c config.h compat_stringlist.h st.o: st.c config.h roff.h mdoc.h libmdoc.h st.in +tag.o: tag.c compat_ohash.h mandoc_aux.h tag.h tbl.o: tbl.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h tbl_data.o: tbl_data.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h tbl_html.o: tbl_html.c config.h mandoc.h out.h html.h @@ -39,6 +39,7 @@ #include "roff.h" #include "mdoc.h" #include "man.h" +#include "tag.h" #include "main.h" #include "manconf.h" #include "mansearch.h" @@ -497,7 +498,9 @@ out: if (pager_pid != 0 && pager_pid != 1) { fclose(stdout); + tag_write(); waitpid(pager_pid, NULL, 0); + tag_unlink(); } return((int)rc); @@ -959,10 +962,50 @@ spawn_pager(void) char *argv[MAX_PAGER_ARGS]; const char *pager; char *cp; + size_t cmdlen; int fildes[2]; int argc; pid_t pager_pid; + pager = getenv("MANPAGER"); + if (pager == NULL || *pager == '\0') + pager = getenv("PAGER"); + if (pager == NULL || *pager == '\0') + pager = "more -s"; + cp = mandoc_strdup(pager); + + /* + * Parse the pager command into words. + * Intentionally do not do anything fancy here. + */ + + argc = 0; + while (argc + 4 < MAX_PAGER_ARGS) { + argv[argc++] = cp; + cp = strchr(cp, ' '); + if (cp == NULL) + break; + *cp++ = '\0'; + while (*cp == ' ') + cp++; + if (*cp == '\0') + break; + } + + /* Read all text right away and use the tag file. */ + + if ((cmdlen = strlen(argv[0])) >= 4) { + cp = argv[0] + cmdlen - 4; + if (strcmp(cp, "less") == 0 || + strcmp(cp, "more") == 0) { + tag_init(); + argv[argc++] = mandoc_strdup("+G1G"); + argv[argc++] = mandoc_strdup("-T"); + argv[argc++] = tag_filename(); + } + } + argv[argc] = NULL; + if (pipe(fildes) == -1) { fprintf(stderr, "%s: pipe: %s\n", progname, strerror(errno)); @@ -998,32 +1041,6 @@ spawn_pager(void) } close(fildes[0]); - pager = getenv("MANPAGER"); - if (pager == NULL || *pager == '\0') - pager = getenv("PAGER"); - if (pager == NULL || *pager == '\0') - pager = "more -s"; - cp = mandoc_strdup(pager); - - /* - * Parse the pager command into words. - * Intentionally do not do anything fancy here. - */ - - argc = 0; - while (argc + 1 < MAX_PAGER_ARGS) { - argv[argc++] = cp; - cp = strchr(cp, ' '); - if (cp == NULL) - break; - *cp++ = '\0'; - while (*cp == ' ') - cp++; - if (*cp == '\0') - break; - } - argv[argc] = NULL; - /* Hand over to the pager. */ execvp(argv[0], argv); @@ -360,6 +360,13 @@ Any non-empty value of the environment variable .Ev MANPAGER will be used instead of the standard pagination program, .Xr more 1 . +If +.Xr less 1 +is used, the interactive +.Ic :t +command can be used to go to the definitions of various terms, for +example command line options, command modifiers, internal commands, +and environment variables. .It Ev MANPATH The standard search path used by .Nm diff --git a/mdoc_term.c b/mdoc_term.c index a2ce71fc..95790806 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -34,6 +34,7 @@ #include "mdoc.h" #include "out.h" #include "term.h" +#include "tag.h" #include "main.h" struct termpair { @@ -117,6 +118,7 @@ static int termp_skip_pre(DECL_ARGS); static int termp_sm_pre(DECL_ARGS); static int termp_sp_pre(DECL_ARGS); static int termp_ss_pre(DECL_ARGS); +static int termp_tag_pre(DECL_ARGS); static int termp_under_pre(DECL_ARGS); static int termp_ud_pre(DECL_ARGS); static int termp_vt_pre(DECL_ARGS); @@ -145,7 +147,7 @@ static const struct termact termacts[MDOC_MAX] = { { termp_bold_pre, NULL }, /* Cm */ { NULL, NULL }, /* Dv */ { NULL, NULL }, /* Er */ - { NULL, NULL }, /* Ev */ + { termp_tag_pre, NULL }, /* Ev */ { termp_ex_pre, NULL }, /* Ex */ { termp_fa_pre, NULL }, /* Fa */ { termp_fd_pre, termp_fd_post }, /* Fd */ @@ -1049,6 +1051,7 @@ static int termp_fl_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\-"); @@ -1330,6 +1333,7 @@ static int termp_bold_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); return(1); } @@ -2252,3 +2256,19 @@ termp_under_pre(DECL_ARGS) term_fontpush(p, TERMFONT_UNDER); return(1); } + +static int +termp_tag_pre(DECL_ARGS) +{ + + if (n->child != NULL && + n->child->type == ROFFT_TEXT && + n->prev == NULL && + (n->parent->tok == MDOC_It || + (n->parent->tok == MDOC_Xo && + n->parent->parent->prev == NULL && + n->parent->parent->parent->tok == MDOC_It)) && + ! tag_get(n->child->string, 0)) + tag_put(n->child->string, 0, p->line); + return(1); +} @@ -0,0 +1,183 @@ +/* $Id$ */ +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/types.h> + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if HAVE_OHASH +#include <ohash.h> +#else +#include "compat_ohash.h" +#endif + +#include "mandoc_aux.h" +#include "tag.h" + +struct tag_entry { + size_t line; + char s[]; +}; + +static void *tag_alloc(size_t, void *); +static void tag_free(void *, void *); +static void *tag_calloc(size_t, size_t, void *); + +static struct ohash tag_data; +static char *tag_fn = NULL; +static int tag_fd = -1; + + +/* + * Set up the ohash table to collect output line numbers + * where various marked-up terms are documented and create + * the temporary tags file, saving the name for the pager. + */ +void +tag_init(void) +{ + struct ohash_info tag_info; + + tag_fn = mandoc_strdup("/tmp/man.XXXXXXXXXX"); + if ((tag_fd = mkstemp(tag_fn)) == -1) { + free(tag_fn); + tag_fn = NULL; + return; + } + + tag_info.alloc = tag_alloc; + tag_info.calloc = tag_calloc; + tag_info.free = tag_free; + tag_info.key_offset = offsetof(struct tag_entry, s); + tag_info.data = NULL; + ohash_init(&tag_data, 4, &tag_info); +} + +char * +tag_filename(void) +{ + + return(tag_fn); +} + +/* + * Return the line number where a term is defined, + * or 0 if the term is unknown. + */ +size_t +tag_get(const char *s, size_t len) +{ + struct tag_entry *entry; + const char *end; + unsigned int slot; + + if (tag_fd == -1) + return(0); + if (len == 0) + len = strlen(s); + end = s + len; + slot = ohash_qlookupi(&tag_data, s, &end); + entry = ohash_find(&tag_data, slot); + return(entry == NULL ? 0 : entry->line); +} + +/* + * Set the line number where a term is defined. + */ +void +tag_put(const char *s, size_t len, size_t line) +{ + struct tag_entry *entry; + const char *end; + unsigned int slot; + + if (tag_fd == -1) + return; + if (len == 0) + len = strlen(s); + end = s + len; + slot = ohash_qlookupi(&tag_data, s, &end); + entry = ohash_find(&tag_data, slot); + if (entry == NULL) { + entry = mandoc_malloc(sizeof(*entry) + len + 1); + memcpy(entry->s, s, len); + entry->s[len] = '\0'; + ohash_insert(&tag_data, slot, entry); + } + entry->line = line; +} + +/* + * Write out the tags file using the previously collected + * information and clear the ohash table while going along. + */ +void +tag_write(void) +{ + FILE *stream; + struct tag_entry *entry; + unsigned int slot; + + if (tag_fd == -1) + return; + stream = fdopen(tag_fd, "w"); + entry = ohash_first(&tag_data, &slot); + while (entry != NULL) { + if (stream != NULL) + fprintf(stream, "%s - %zu\n", entry->s, entry->line); + free(entry); + entry = ohash_next(&tag_data, &slot); + } + ohash_delete(&tag_data); + if (stream != NULL) + fclose(stream); +} + +void +tag_unlink(void) +{ + + if (tag_fn != NULL) + unlink(tag_fn); +} + +/* + * Memory management callback functions for ohash. + */ +static void * +tag_alloc(size_t sz, void *arg) +{ + + return(mandoc_malloc(sz)); +} + +static void * +tag_calloc(size_t nmemb, size_t sz, void *arg) +{ + + return(mandoc_calloc(nmemb, sz)); +} + +static void +tag_free(void *p, void *arg) +{ + + free(p); +} @@ -0,0 +1,27 @@ +/* $Id$ */ +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +__BEGIN_DECLS + +void tag_init(void); +char *tag_filename(void); +size_t tag_get(const char *, size_t); +void tag_put(const char *, size_t, size_t); +void tag_write(void); +void tag_unlink(void); + +__END_DECLS @@ -53,6 +53,7 @@ struct termp { struct rofftbl tbl; /* table configuration */ int synopsisonly; /* print the synopsis only */ int mdocstyle; /* imitate mdoc(7) output */ + size_t line; /* Current output line number. */ size_t defindent; /* Default indent for text. */ size_t defrmargin; /* Right margin of the device. */ size_t lastrmargin; /* Right margin before the last ll. */ diff --git a/term_ascii.c b/term_ascii.c index d210c812..596c1142 100644 --- a/term_ascii.c +++ b/term_ascii.c @@ -70,6 +70,7 @@ ascii_init(enum termenc enc, const struct mchars *mchars, p = mandoc_calloc(1, sizeof(struct termp)); p->symtab = mchars; + p->line = 1; p->tabwidth = 5; p->defrmargin = p->lastrmargin = 78; p->fontq = mandoc_reallocarray(NULL, @@ -163,6 +164,7 @@ ascii_sepline(void *arg) size_t i; p = (struct termp *)arg; + p->line += 3; putchar('\n'); for (i = 0; i < p->defrmargin; i++) putchar('-'); @@ -209,6 +211,7 @@ static void ascii_endline(struct termp *p) { + p->line++; putchar('\n'); } @@ -365,6 +368,7 @@ static void locale_endline(struct termp *p) { + p->line++; putwchar(L'\n'); } |