From 7f0964d6bed1077435683bcb011c0c605f6a0255 Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Sun, 27 Nov 2011 18:54:01 +0000 Subject: Get us a whatis(1) mode for apropos(1). This is from a patch to tech@ as critiqued by schwarze@, checked in to get the ball rolling. --- apropos.c | 22 ++++++----- apropos_db.c | 48 +++++++++++++++++++++++- apropos_db.h | 3 +- whatis.1 | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 12 deletions(-) create mode 100644 whatis.1 diff --git a/apropos.c b/apropos.c index cf8fec63..4bfdbf04 100644 --- a/apropos.c +++ b/apropos.c @@ -1,4 +1,4 @@ -/* $Id: apropos.c,v 1.19 2011/11/26 22:38:11 schwarze Exp $ */ +/* $Id: apropos.c,v 1.20 2011/11/27 18:54:01 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -38,7 +38,7 @@ static char *progname; int main(int argc, char *argv[]) { - int ch, rc; + int ch, rc, whatis; struct manpaths paths; size_t terms; struct opts opts; @@ -53,12 +53,13 @@ main(int argc, char *argv[]) else ++progname; + whatis = 0 == strcmp(progname, "whatis"); + memset(&paths, 0, sizeof(struct manpaths)); memset(&opts, 0, sizeof(struct opts)); auxpaths = defpaths = NULL; e = NULL; - rc = 0; while (-1 != (ch = getopt(argc, argv, "M:m:S:s:"))) switch (ch) { @@ -76,20 +77,23 @@ main(int argc, char *argv[]) break; default: usage(); - goto out; + return(EXIT_FAILURE); } argc -= optind; argv += optind; - if (0 == argc) { - rc = 1; - goto out; - } + if (0 == argc) + return(EXIT_SUCCESS); + + rc = 0; manpath_parse(&paths, defpaths, auxpaths); - if (NULL == (e = exprcomp(argc, argv, &terms))) { + e = whatis ? termcomp(argc, argv, &terms) : + exprcomp(argc, argv, &terms); + + if (NULL == e) { fprintf(stderr, "%s: Bad expression\n", progname); goto out; } diff --git a/apropos_db.c b/apropos_db.c index 4f1a325b..4e41a22b 100644 --- a/apropos_db.c +++ b/apropos_db.c @@ -1,4 +1,4 @@ -/* $Id: apropos_db.c,v 1.12 2011/11/26 22:38:11 schwarze Exp $ */ +/* $Id: apropos_db.c,v 1.13 2011/11/27 18:54:01 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -579,6 +579,50 @@ recfree(struct rec *rec) free(rec->matches); } +/* + * Compile a list of straight-up terms. + * The arguments are re-written into ~[[:<:]]term[[:>:]], or "term" + * surrounded by word boundaries, then pumped through exprterm(). + * Terms are case-insensitive. + * This emulates whatis(1) behaviour. + */ +struct expr * +termcomp(int argc, char *argv[], size_t *tt) +{ + char *buf; + int pos; + struct expr *e, *next; + size_t sz; + + buf = NULL; + e = NULL; + *tt = 0; + + for (pos = 0; pos < argc; pos++) { + sz = strlen(argv[pos]) + 16; + buf = mandoc_realloc(buf, sz); + strlcpy(buf, "~[[:<:]]", sz); + strlcat(buf, argv[pos], sz); + strlcat(buf, "[[:>:]]", sz); + if (NULL == (next = exprterm(buf, 0))) { + free(buf); + exprfree(e); + return(NULL); + } + if (NULL != e) + e->next = next; + e = next; + (*tt)++; + } + + free(buf); + return(e); +} + +/* + * Compile a sequence of logical expressions. + * See apropos.1 for a grammar of this sequence. + */ struct expr * exprcomp(int argc, char *argv[], size_t *tt) { @@ -729,7 +773,7 @@ exprterm(char *buf, int cs) e.mask = TYPE_Nm | TYPE_Nd; if (e.regex) { - i = REG_EXTENDED | REG_NOSUB | cs ? 0 : REG_ICASE; + i = REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE); if (regcomp(&e.re, e.v, i)) return(NULL); } diff --git a/apropos_db.h b/apropos_db.h index 85b4c9e6..8d03e5be 100644 --- a/apropos_db.h +++ b/apropos_db.h @@ -1,4 +1,4 @@ -/* $Id: apropos_db.h,v 1.8 2011/11/26 22:38:11 schwarze Exp $ */ +/* $Id: apropos_db.h,v 1.9 2011/11/27 18:54:01 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -45,6 +45,7 @@ int apropos_search(int, char **, const struct opts *, void (*)(struct res *, size_t, void *)); struct expr *exprcomp(int, char *[], size_t *); void exprfree(struct expr *); +struct expr *termcomp(int, char *[], size_t *); __END_DECLS diff --git a/whatis.1 b/whatis.1 new file mode 100644 index 00000000..a3f60fb8 --- /dev/null +++ b/whatis.1 @@ -0,0 +1,118 @@ +.\" $Id: whatis.1,v 1.1 2011/11/27 18:54:01 kristaps Exp $ +.\" +.\" Copyright (c) 2011 Kristaps Dzonsons +.\" +.\" 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. +.\" +.Dd $Mdocdate: November 27 2011 $ +.Dt WHATIS 1 +.Os +.Sh NAME +.Nm whatis +.Nd search manual page databases +.Sh SYNOPSIS +.Nm +.Op Fl M Ar manpath +.Op Fl m Ar manpath +.Op Fl S Ar arch +.Op Fl s Ar section +.Ar term... +.Sh DESCRIPTION +The +.Nm +utility searches for manuals named or described with +.Ar term +in manual page databases generated by +.Xr mandocdb 8 . +Its arguments are as follows: +.Bl -tag -width Ds +.It Fl M Ar manpath +Use the colon-separated path instead of the default list of paths +searched for +.Xr mandocdb 8 +databases. +Invalid paths, or paths without manual databases, are ignored. +.It Fl m Ar manpath +Prepend the colon-separated paths to the list of paths searched +for +.Xr mandocdb 8 +databases. +Invalid paths, or paths without manual databases, are ignored. +.It Fl S Ar arch +Search only for a particular architecture. +.It Fl s Ar cat +Search only for a manual section. +See +.Xr man 1 +for a listing of manual sections. +.El +.Pp +By default, +.Nm +searches for +.Xr mandocdb 8 +databases in the default paths stipulated by +.Xr man 1 . +Results are sorted by manual title, with output formatted as +.Pp +.D1 title(sec) \- description +.Pp +Where +.Qq title +is the manual's title (note multiple manual names may exist for one +title), +.Qq sec +is the manual section, and +.Qq description +is the manual's short description. +If an architecture is specified for the manual, it is displayed as +.Pp +.D1 title(cat/arch) \- description +.Pp +Resulting manuals may be accessed as +.Pp +.Dl $ man \-s sec title +.Pp +If an architecture is specified in the output, use +.Pp +.Dl $ man \-s sec \-S arch title +.Pp +.Nm +is identical to running +.Xr apropos 1 +as follows: +.Pp +.Dl $ apropos -- -i '~[[:<:]]term[[:>:]]' +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev MANPATH +Colon-separated paths overriding the default list of paths searched for +manual databases. +Invalid paths, or paths without manual databases, are ignored. +Overridden by +.Fl M . +.El +.\" .Sh FILES +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr apropos 1 , +.Xr man 1 , +.Xr mandoc 1 , +.Xr mandocdb 8 +.Sh AUTHORS +The +.Nm +utility was written by +.An Kristaps Dzonsons , +.Mt kristaps@bsd.lv . -- cgit v1.2.3-56-ge451