summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/main.c71
-rw-r--r--usr.bin/mandoc/man.111
-rw-r--r--usr.bin/mandoc/mdoc_term.c24
-rw-r--r--usr.bin/mandoc/tag.c179
-rw-r--r--usr.bin/mandoc/tag.h27
-rw-r--r--usr.bin/mandoc/term.h3
-rw-r--r--usr.bin/mandoc/term_ascii.c6
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');
}