diff options
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/main.c | 71 | ||||
-rw-r--r-- | usr.bin/mandoc/man.1 | 11 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_term.c | 24 | ||||
-rw-r--r-- | usr.bin/mandoc/tag.c | 179 | ||||
-rw-r--r-- | usr.bin/mandoc/tag.h | 27 | ||||
-rw-r--r-- | usr.bin/mandoc/term.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/term_ascii.c | 6 |
8 files changed, 290 insertions, 35 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 91f1e301a25..e78c0aac0e4 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.95 2015/03/27 17:36:56 schwarze Exp $ +# $OpenBSD: Makefile,v 1.96 2015/07/17 22:35:36 schwarze Exp $ .include <bsd.own.mk> @@ -11,7 +11,7 @@ SRCS= mandoc.c mandoc_aux.c preconv.c read.c \ SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c \ mdoc_argv.c mdoc_validate.c att.c msec.c st.c SRCS+= man_macro.c man.c man_hash.c man_validate.c -SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c eqn_term.c +SRCS+= main.c mdoc_term.c tag.c chars.c term.c tree.c man_term.c eqn_term.c SRCS+= mdoc_man.c SRCS+= html.c mdoc_html.c man_html.c out.c eqn_html.c SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index f8e4f1a9c9b..3974cd9e3ed 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.143 2015/04/29 11:03:48 schwarze Exp $ */ +/* $OpenBSD: main.c,v 1.144 2015/07/17 22:35:36 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -38,6 +38,7 @@ #include "roff.h" #include "mdoc.h" #include "man.h" +#include "tag.h" #include "main.h" #include "manconf.h" #include "mansearch.h" @@ -474,7 +475,9 @@ out: if (pager_pid != 0 && pager_pid != 1) { fclose(stdout); + tag_write(); waitpid(pager_pid, NULL, 0); + tag_unlink(); } return((int)rc); @@ -934,10 +937,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)); @@ -973,32 +1016,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); diff --git a/usr.bin/mandoc/man.1 b/usr.bin/mandoc/man.1 index ff3136caf4f..bf5cfc010e1 100644 --- a/usr.bin/mandoc/man.1 +++ b/usr.bin/mandoc/man.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: man.1,v 1.12 2015/04/03 08:45:27 schwarze Exp $ +.\" $OpenBSD: man.1,v 1.13 2015/07/17 22:35:36 schwarze Exp $ .\" .\" Copyright (c) 1989, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -31,7 +31,7 @@ .\" .\" @(#)man.1 8.2 (Berkeley) 1/2/94 .\" -.Dd $Mdocdate: April 3 2015 $ +.Dd $Mdocdate: July 17 2015 $ .Dt MAN 1 .Os .Sh NAME @@ -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/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c index 037597481d2..1e08df4a8bd 100644 --- a/usr.bin/mandoc/mdoc_term.c +++ b/usr.bin/mandoc/mdoc_term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mdoc_term.c,v 1.218 2015/04/18 17:50:02 schwarze Exp $ */ +/* $OpenBSD: mdoc_term.c,v 1.219 2015/07/17 22:35:36 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -32,6 +32,7 @@ #include "mdoc.h" #include "out.h" #include "term.h" +#include "tag.h" #include "main.h" struct termpair { @@ -115,6 +116,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); @@ -143,7 +145,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 */ @@ -1047,6 +1049,7 @@ static int termp_fl_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\-"); @@ -1328,6 +1331,7 @@ static int termp_bold_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); return(1); } @@ -2250,3 +2254,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); +} diff --git a/usr.bin/mandoc/tag.c b/usr.bin/mandoc/tag.c new file mode 100644 index 00000000000..9b191cc73a3 --- /dev/null +++ b/usr.bin/mandoc/tag.c @@ -0,0 +1,179 @@ +/* $OpenBSD: tag.c,v 1.1 2015/07/17 22:35:36 schwarze Exp $ */ +/* + * 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> + +#include <ohash.h> + +#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); +} diff --git a/usr.bin/mandoc/tag.h b/usr.bin/mandoc/tag.h new file mode 100644 index 00000000000..dd3a5f5d4c5 --- /dev/null +++ b/usr.bin/mandoc/tag.h @@ -0,0 +1,27 @@ +/* $OpenBSD: tag.h,v 1.1 2015/07/17 22:35:36 schwarze Exp $ */ +/* + * 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 diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index 47e14f8c813..fd2d6d9d673 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -1,4 +1,4 @@ -/* $OpenBSD: term.h,v 1.58 2015/04/29 18:32:57 schwarze Exp $ */ +/* $OpenBSD: term.h,v 1.59 2015/07/17 22:35:36 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -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/usr.bin/mandoc/term_ascii.c b/usr.bin/mandoc/term_ascii.c index 144c335fc81..a3bd10cdfa8 100644 --- a/usr.bin/mandoc/term_ascii.c +++ b/usr.bin/mandoc/term_ascii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: term_ascii.c,v 1.32 2015/04/04 17:46:58 schwarze Exp $ */ +/* $OpenBSD: term_ascii.c,v 1.33 2015/07/17 22:35:36 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -60,6 +60,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, @@ -151,6 +152,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('-'); @@ -197,6 +199,7 @@ static void ascii_endline(struct termp *p) { + p->line++; putchar('\n'); } @@ -352,6 +355,7 @@ static void locale_endline(struct termp *p) { + p->line++; putwchar(L'\n'); } |