Merge mdocml 1.12.3.
This commit is contained in:
parent
12f8f2b852
commit
603fc4ebb9
|
@ -1,876 +0,0 @@
|
|||
/* $Vendor-Id: apropos_db.c,v 1.31 2012/03/24 01:46:25 kristaps Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <endian.h>
|
||||
# include <db_185.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# include <db.h>
|
||||
#else
|
||||
# include <db.h>
|
||||
#endif
|
||||
|
||||
#include "mandocdb.h"
|
||||
#include "apropos_db.h"
|
||||
#include "mandoc.h"
|
||||
|
||||
#define RESFREE(_x) \
|
||||
do { \
|
||||
free((_x)->file); \
|
||||
free((_x)->cat); \
|
||||
free((_x)->title); \
|
||||
free((_x)->arch); \
|
||||
free((_x)->desc); \
|
||||
free((_x)->matches); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
struct expr {
|
||||
int regex; /* is regex? */
|
||||
int index; /* index in match array */
|
||||
uint64_t mask; /* type-mask */
|
||||
int and; /* is rhs of logical AND? */
|
||||
char *v; /* search value */
|
||||
regex_t re; /* compiled re, if regex */
|
||||
struct expr *next; /* next in sequence */
|
||||
struct expr *subexpr;
|
||||
};
|
||||
|
||||
struct type {
|
||||
uint64_t mask;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct rectree {
|
||||
struct res *node; /* record array for dir tree */
|
||||
int len; /* length of record array */
|
||||
};
|
||||
|
||||
static const struct type types[] = {
|
||||
{ TYPE_An, "An" },
|
||||
{ TYPE_Ar, "Ar" },
|
||||
{ TYPE_At, "At" },
|
||||
{ TYPE_Bsx, "Bsx" },
|
||||
{ TYPE_Bx, "Bx" },
|
||||
{ TYPE_Cd, "Cd" },
|
||||
{ TYPE_Cm, "Cm" },
|
||||
{ TYPE_Dv, "Dv" },
|
||||
{ TYPE_Dx, "Dx" },
|
||||
{ TYPE_Em, "Em" },
|
||||
{ TYPE_Er, "Er" },
|
||||
{ TYPE_Ev, "Ev" },
|
||||
{ TYPE_Fa, "Fa" },
|
||||
{ TYPE_Fl, "Fl" },
|
||||
{ TYPE_Fn, "Fn" },
|
||||
{ TYPE_Fn, "Fo" },
|
||||
{ TYPE_Ft, "Ft" },
|
||||
{ TYPE_Fx, "Fx" },
|
||||
{ TYPE_Ic, "Ic" },
|
||||
{ TYPE_In, "In" },
|
||||
{ TYPE_Lb, "Lb" },
|
||||
{ TYPE_Li, "Li" },
|
||||
{ TYPE_Lk, "Lk" },
|
||||
{ TYPE_Ms, "Ms" },
|
||||
{ TYPE_Mt, "Mt" },
|
||||
{ TYPE_Nd, "Nd" },
|
||||
{ TYPE_Nm, "Nm" },
|
||||
{ TYPE_Nx, "Nx" },
|
||||
{ TYPE_Ox, "Ox" },
|
||||
{ TYPE_Pa, "Pa" },
|
||||
{ TYPE_Rs, "Rs" },
|
||||
{ TYPE_Sh, "Sh" },
|
||||
{ TYPE_Ss, "Ss" },
|
||||
{ TYPE_St, "St" },
|
||||
{ TYPE_Sy, "Sy" },
|
||||
{ TYPE_Tn, "Tn" },
|
||||
{ TYPE_Va, "Va" },
|
||||
{ TYPE_Va, "Vt" },
|
||||
{ TYPE_Xr, "Xr" },
|
||||
{ UINT64_MAX, "any" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static DB *btree_open(void);
|
||||
static int btree_read(const DBT *, const DBT *,
|
||||
const struct mchars *,
|
||||
uint64_t *, recno_t *, char **);
|
||||
static int expreval(const struct expr *, int *);
|
||||
static void exprexec(const struct expr *,
|
||||
const char *, uint64_t, struct res *);
|
||||
static int exprmark(const struct expr *,
|
||||
const char *, uint64_t, int *);
|
||||
static struct expr *exprexpr(int, char *[], int *, int *, size_t *);
|
||||
static struct expr *exprterm(char *, int);
|
||||
static DB *index_open(void);
|
||||
static int index_read(const DBT *, const DBT *, int,
|
||||
const struct mchars *, struct res *);
|
||||
static void norm_string(const char *,
|
||||
const struct mchars *, char **);
|
||||
static size_t norm_utf8(unsigned int, char[7]);
|
||||
static int single_search(struct rectree *, const struct opts *,
|
||||
const struct expr *, size_t terms,
|
||||
struct mchars *, int);
|
||||
|
||||
/*
|
||||
* Open the keyword mandoc-db database.
|
||||
*/
|
||||
static DB *
|
||||
btree_open(void)
|
||||
{
|
||||
BTREEINFO info;
|
||||
DB *db;
|
||||
|
||||
memset(&info, 0, sizeof(BTREEINFO));
|
||||
info.lorder = 4321;
|
||||
info.flags = R_DUP;
|
||||
|
||||
db = dbopen(MANDOC_DB, O_RDONLY, 0, DB_BTREE, &info);
|
||||
if (NULL != db)
|
||||
return(db);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a keyword from the database and normalise it.
|
||||
* Return 0 if the database is insane, else 1.
|
||||
*/
|
||||
static int
|
||||
btree_read(const DBT *k, const DBT *v, const struct mchars *mc,
|
||||
uint64_t *mask, recno_t *rec, char **buf)
|
||||
{
|
||||
uint64_t vbuf[2];
|
||||
|
||||
/* Are our sizes sane? */
|
||||
if (k->size < 2 || sizeof(vbuf) != v->size)
|
||||
return(0);
|
||||
|
||||
/* Is our string nil-terminated? */
|
||||
if ('\0' != ((const char *)k->data)[(int)k->size - 1])
|
||||
return(0);
|
||||
|
||||
norm_string((const char *)k->data, mc, buf);
|
||||
memcpy(vbuf, v->data, v->size);
|
||||
*mask = betoh64(vbuf[0]);
|
||||
*rec = betoh64(vbuf[1]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a Unicode codepoint and produce its UTF-8 encoding.
|
||||
* This isn't the best way to do this, but it works.
|
||||
* The magic numbers are from the UTF-8 packaging.
|
||||
* They're not as scary as they seem: read the UTF-8 spec for details.
|
||||
*/
|
||||
static size_t
|
||||
norm_utf8(unsigned int cp, char out[7])
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (cp <= 0x0000007F) {
|
||||
rc = 1;
|
||||
out[0] = (char)cp;
|
||||
} else if (cp <= 0x000007FF) {
|
||||
rc = 2;
|
||||
out[0] = (cp >> 6 & 31) | 192;
|
||||
out[1] = (cp & 63) | 128;
|
||||
} else if (cp <= 0x0000FFFF) {
|
||||
rc = 3;
|
||||
out[0] = (cp >> 12 & 15) | 224;
|
||||
out[1] = (cp >> 6 & 63) | 128;
|
||||
out[2] = (cp & 63) | 128;
|
||||
} else if (cp <= 0x001FFFFF) {
|
||||
rc = 4;
|
||||
out[0] = (cp >> 18 & 7) | 240;
|
||||
out[1] = (cp >> 12 & 63) | 128;
|
||||
out[2] = (cp >> 6 & 63) | 128;
|
||||
out[3] = (cp & 63) | 128;
|
||||
} else if (cp <= 0x03FFFFFF) {
|
||||
rc = 5;
|
||||
out[0] = (cp >> 24 & 3) | 248;
|
||||
out[1] = (cp >> 18 & 63) | 128;
|
||||
out[2] = (cp >> 12 & 63) | 128;
|
||||
out[3] = (cp >> 6 & 63) | 128;
|
||||
out[4] = (cp & 63) | 128;
|
||||
} else if (cp <= 0x7FFFFFFF) {
|
||||
rc = 6;
|
||||
out[0] = (cp >> 30 & 1) | 252;
|
||||
out[1] = (cp >> 24 & 63) | 128;
|
||||
out[2] = (cp >> 18 & 63) | 128;
|
||||
out[3] = (cp >> 12 & 63) | 128;
|
||||
out[4] = (cp >> 6 & 63) | 128;
|
||||
out[5] = (cp & 63) | 128;
|
||||
} else
|
||||
return(0);
|
||||
|
||||
out[rc] = '\0';
|
||||
return((size_t)rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalise strings from the index and database.
|
||||
* These strings are escaped as defined by mandoc_char(7) along with
|
||||
* other goop in mandoc.h (e.g., soft hyphens).
|
||||
* This function normalises these into a nice UTF-8 string.
|
||||
* Returns 0 if the database is fucked.
|
||||
*/
|
||||
static void
|
||||
norm_string(const char *val, const struct mchars *mc, char **buf)
|
||||
{
|
||||
size_t sz, bsz;
|
||||
char utfbuf[7];
|
||||
const char *seq, *cpp;
|
||||
int len, u, pos;
|
||||
enum mandoc_esc esc;
|
||||
static const char res[] = { '\\', '\t',
|
||||
ASCII_NBRSP, ASCII_HYPH, '\0' };
|
||||
|
||||
/* Pre-allocate by the length of the input */
|
||||
|
||||
bsz = strlen(val) + 1;
|
||||
*buf = mandoc_realloc(*buf, bsz);
|
||||
pos = 0;
|
||||
|
||||
while ('\0' != *val) {
|
||||
/*
|
||||
* Halt on the first escape sequence.
|
||||
* This also halts on the end of string, in which case
|
||||
* we just copy, fallthrough, and exit the loop.
|
||||
*/
|
||||
if ((sz = strcspn(val, res)) > 0) {
|
||||
memcpy(&(*buf)[pos], val, sz);
|
||||
pos += (int)sz;
|
||||
val += (int)sz;
|
||||
}
|
||||
|
||||
if (ASCII_HYPH == *val) {
|
||||
(*buf)[pos++] = '-';
|
||||
val++;
|
||||
continue;
|
||||
} else if ('\t' == *val || ASCII_NBRSP == *val) {
|
||||
(*buf)[pos++] = ' ';
|
||||
val++;
|
||||
continue;
|
||||
} else if ('\\' != *val)
|
||||
break;
|
||||
|
||||
/* Read past the slash. */
|
||||
|
||||
val++;
|
||||
u = 0;
|
||||
|
||||
/*
|
||||
* Parse the escape sequence and see if it's a
|
||||
* predefined character or special character.
|
||||
*/
|
||||
|
||||
esc = mandoc_escape(&val, &seq, &len);
|
||||
if (ESCAPE_ERROR == esc)
|
||||
break;
|
||||
|
||||
/*
|
||||
* XXX - this just does UTF-8, but we need to know
|
||||
* beforehand whether we should do text substitution.
|
||||
*/
|
||||
|
||||
switch (esc) {
|
||||
case (ESCAPE_SPECIAL):
|
||||
if (0 != (u = mchars_spec2cp(mc, seq, len)))
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a Unicode codepoint, try to convert that
|
||||
* to a UTF-8 byte string.
|
||||
*/
|
||||
|
||||
cpp = utfbuf;
|
||||
if (0 == (sz = norm_utf8(u, utfbuf)))
|
||||
continue;
|
||||
|
||||
/* Copy the rendered glyph into the stream. */
|
||||
|
||||
sz = strlen(cpp);
|
||||
bsz += sz;
|
||||
|
||||
*buf = mandoc_realloc(*buf, bsz);
|
||||
|
||||
memcpy(&(*buf)[pos], cpp, sz);
|
||||
pos += (int)sz;
|
||||
}
|
||||
|
||||
(*buf)[pos] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the filename-index mandoc-db database.
|
||||
* Returns NULL if opening failed.
|
||||
*/
|
||||
static DB *
|
||||
index_open(void)
|
||||
{
|
||||
DB *db;
|
||||
|
||||
db = dbopen(MANDOC_IDX, O_RDONLY, 0, DB_RECNO, NULL);
|
||||
if (NULL != db)
|
||||
return(db);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely unpack from an index file record into the structure.
|
||||
* Returns 1 if an entry was unpacked, 0 if the database is insane.
|
||||
*/
|
||||
static int
|
||||
index_read(const DBT *key, const DBT *val, int index,
|
||||
const struct mchars *mc, struct res *rec)
|
||||
{
|
||||
size_t left;
|
||||
char *np, *cp;
|
||||
char type;
|
||||
|
||||
#define INDEX_BREAD(_dst) \
|
||||
do { \
|
||||
if (NULL == (np = memchr(cp, '\0', left))) \
|
||||
return(0); \
|
||||
norm_string(cp, mc, &(_dst)); \
|
||||
left -= (np - cp) + 1; \
|
||||
cp = np + 1; \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
if (0 == (left = val->size))
|
||||
return(0);
|
||||
|
||||
cp = val->data;
|
||||
assert(sizeof(recno_t) == key->size);
|
||||
memcpy(&rec->rec, key->data, key->size);
|
||||
rec->volume = index;
|
||||
|
||||
if ('d' == (type = *cp++))
|
||||
rec->type = RESTYPE_MDOC;
|
||||
else if ('a' == type)
|
||||
rec->type = RESTYPE_MAN;
|
||||
else if ('c' == type)
|
||||
rec->type = RESTYPE_CAT;
|
||||
else
|
||||
return(0);
|
||||
|
||||
left--;
|
||||
INDEX_BREAD(rec->file);
|
||||
INDEX_BREAD(rec->cat);
|
||||
INDEX_BREAD(rec->title);
|
||||
INDEX_BREAD(rec->arch);
|
||||
INDEX_BREAD(rec->desc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search mandocdb databases in paths for expression "expr".
|
||||
* Filter out by "opts".
|
||||
* Call "res" with the results, which may be zero.
|
||||
* Return 0 if there was a database error, else return 1.
|
||||
*/
|
||||
int
|
||||
apropos_search(int pathsz, char **paths, const struct opts *opts,
|
||||
const struct expr *expr, size_t terms, void *arg,
|
||||
size_t *sz, struct res **resp,
|
||||
void (*res)(struct res *, size_t, void *))
|
||||
{
|
||||
struct rectree tree;
|
||||
struct mchars *mc;
|
||||
int i, rc;
|
||||
|
||||
memset(&tree, 0, sizeof(struct rectree));
|
||||
|
||||
rc = 0;
|
||||
mc = mchars_alloc();
|
||||
*sz = 0;
|
||||
*resp = NULL;
|
||||
|
||||
/*
|
||||
* Main loop. Change into the directory containing manpage
|
||||
* databases. Run our expession over each database in the set.
|
||||
*/
|
||||
|
||||
for (i = 0; i < pathsz; i++) {
|
||||
if (chdir(paths[i]))
|
||||
continue;
|
||||
if (single_search(&tree, opts, expr, terms, mc, i))
|
||||
continue;
|
||||
|
||||
resfree(tree.node, tree.len);
|
||||
mchars_free(mc);
|
||||
return(0);
|
||||
}
|
||||
|
||||
(*res)(tree.node, tree.len, arg);
|
||||
*sz = tree.len;
|
||||
*resp = tree.node;
|
||||
mchars_free(mc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
single_search(struct rectree *tree, const struct opts *opts,
|
||||
const struct expr *expr, size_t terms,
|
||||
struct mchars *mc, int vol)
|
||||
{
|
||||
int root, leaf, ch;
|
||||
DBT key, val;
|
||||
DB *btree, *idx;
|
||||
char *buf;
|
||||
struct res *rs;
|
||||
struct res r;
|
||||
uint64_t mask;
|
||||
recno_t rec;
|
||||
|
||||
root = -1;
|
||||
leaf = -1;
|
||||
btree = NULL;
|
||||
idx = NULL;
|
||||
buf = NULL;
|
||||
rs = tree->node;
|
||||
|
||||
memset(&r, 0, sizeof(struct res));
|
||||
|
||||
if (NULL == (btree = btree_open()))
|
||||
return(1);
|
||||
|
||||
if (NULL == (idx = index_open())) {
|
||||
(*btree->close)(btree);
|
||||
return(1);
|
||||
}
|
||||
|
||||
while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) {
|
||||
if ( ! btree_read(&key, &val, mc, &mask, &rec, &buf))
|
||||
break;
|
||||
|
||||
/*
|
||||
* See if this keyword record matches any of the
|
||||
* expressions we have stored.
|
||||
*/
|
||||
if ( ! exprmark(expr, buf, mask, NULL))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* O(log n) scan for prior records. Since a record
|
||||
* number is unbounded, this has decent performance over
|
||||
* a complex hash function.
|
||||
*/
|
||||
|
||||
for (leaf = root; leaf >= 0; )
|
||||
if (rec > rs[leaf].rec &&
|
||||
rs[leaf].rhs >= 0)
|
||||
leaf = rs[leaf].rhs;
|
||||
else if (rec < rs[leaf].rec &&
|
||||
rs[leaf].lhs >= 0)
|
||||
leaf = rs[leaf].lhs;
|
||||
else
|
||||
break;
|
||||
|
||||
/*
|
||||
* If we find a record, see if it has already evaluated
|
||||
* to true. If it has, great, just keep going. If not,
|
||||
* try to evaluate it now and continue anyway.
|
||||
*/
|
||||
|
||||
if (leaf >= 0 && rs[leaf].rec == rec) {
|
||||
if (0 == rs[leaf].matched)
|
||||
exprexec(expr, buf, mask, &rs[leaf]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a new file to examine.
|
||||
* Extract the manpage's metadata from the index
|
||||
* database, then begin partial evaluation.
|
||||
*/
|
||||
|
||||
key.data = &rec;
|
||||
key.size = sizeof(recno_t);
|
||||
|
||||
if (0 != (*idx->get)(idx, &key, &val, 0))
|
||||
break;
|
||||
|
||||
r.lhs = r.rhs = -1;
|
||||
if ( ! index_read(&key, &val, vol, mc, &r))
|
||||
break;
|
||||
|
||||
/* XXX: this should be elsewhere, I guess? */
|
||||
|
||||
if (opts->cat && strcasecmp(opts->cat, r.cat))
|
||||
continue;
|
||||
|
||||
if (opts->arch && *r.arch)
|
||||
if (strcasecmp(opts->arch, r.arch))
|
||||
continue;
|
||||
|
||||
tree->node = rs = mandoc_realloc
|
||||
(rs, (tree->len + 1) * sizeof(struct res));
|
||||
|
||||
memcpy(&rs[tree->len], &r, sizeof(struct res));
|
||||
memset(&r, 0, sizeof(struct res));
|
||||
rs[tree->len].matches =
|
||||
mandoc_calloc(terms, sizeof(int));
|
||||
|
||||
exprexec(expr, buf, mask, &rs[tree->len]);
|
||||
|
||||
/* Append to our tree. */
|
||||
|
||||
if (leaf >= 0) {
|
||||
if (rec > rs[leaf].rec)
|
||||
rs[leaf].rhs = tree->len;
|
||||
else
|
||||
rs[leaf].lhs = tree->len;
|
||||
} else
|
||||
root = tree->len;
|
||||
|
||||
tree->len++;
|
||||
}
|
||||
|
||||
(*btree->close)(btree);
|
||||
(*idx->close)(idx);
|
||||
|
||||
free(buf);
|
||||
RESFREE(&r);
|
||||
return(1 == ch);
|
||||
}
|
||||
|
||||
void
|
||||
resfree(struct res *rec, size_t sz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
RESFREE(&rec[i]);
|
||||
free(rec);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = argc - 1; pos >= 0; pos--) {
|
||||
sz = strlen(argv[pos]) + 18;
|
||||
buf = mandoc_realloc(buf, sz);
|
||||
strlcpy(buf, "Nm~[[:<:]]", sz);
|
||||
strlcat(buf, argv[pos], sz);
|
||||
strlcat(buf, "[[:>:]]", sz);
|
||||
if (NULL == (next = exprterm(buf, 0))) {
|
||||
free(buf);
|
||||
exprfree(e);
|
||||
return(NULL);
|
||||
}
|
||||
next->next = e;
|
||||
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)
|
||||
{
|
||||
int pos, lvl;
|
||||
struct expr *e;
|
||||
|
||||
pos = lvl = 0;
|
||||
*tt = 0;
|
||||
|
||||
e = exprexpr(argc, argv, &pos, &lvl, tt);
|
||||
|
||||
if (0 == lvl && pos >= argc)
|
||||
return(e);
|
||||
|
||||
exprfree(e);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile an array of tokens into an expression.
|
||||
* An informal expression grammar is defined in apropos(1).
|
||||
* Return NULL if we fail doing so. All memory will be cleaned up.
|
||||
* Return the root of the expression sequence if alright.
|
||||
*/
|
||||
static struct expr *
|
||||
exprexpr(int argc, char *argv[], int *pos, int *lvl, size_t *tt)
|
||||
{
|
||||
struct expr *e, *first, *next;
|
||||
int log;
|
||||
|
||||
first = next = NULL;
|
||||
|
||||
for ( ; *pos < argc; (*pos)++) {
|
||||
e = next;
|
||||
|
||||
/*
|
||||
* Close out a subexpression.
|
||||
*/
|
||||
|
||||
if (NULL != e && 0 == strcmp(")", argv[*pos])) {
|
||||
if (--(*lvl) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Small note: if we're just starting, don't let "-a"
|
||||
* and "-o" be considered logical operators: they're
|
||||
* just tokens unless pairwise joining, in which case we
|
||||
* record their existence (or assume "OR").
|
||||
*/
|
||||
log = 0;
|
||||
|
||||
if (NULL != e && 0 == strcmp("-a", argv[*pos]))
|
||||
log = 1;
|
||||
else if (NULL != e && 0 == strcmp("-o", argv[*pos]))
|
||||
log = 2;
|
||||
|
||||
if (log > 0 && ++(*pos) >= argc)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Now we parse the term part. This can begin with
|
||||
* "-i", in which case the expression is case
|
||||
* insensitive.
|
||||
*/
|
||||
|
||||
if (0 == strcmp("(", argv[*pos])) {
|
||||
++(*pos);
|
||||
++(*lvl);
|
||||
next = mandoc_calloc(1, sizeof(struct expr));
|
||||
next->subexpr = exprexpr(argc, argv, pos, lvl, tt);
|
||||
if (NULL == next->subexpr) {
|
||||
free(next);
|
||||
next = NULL;
|
||||
}
|
||||
} else if (0 == strcmp("-i", argv[*pos])) {
|
||||
if (++(*pos) >= argc)
|
||||
goto err;
|
||||
next = exprterm(argv[*pos], 0);
|
||||
} else
|
||||
next = exprterm(argv[*pos], 1);
|
||||
|
||||
if (NULL == next)
|
||||
goto err;
|
||||
|
||||
next->and = log == 1;
|
||||
next->index = (int)(*tt)++;
|
||||
|
||||
/* Append to our chain of expressions. */
|
||||
|
||||
if (NULL == first) {
|
||||
assert(NULL == e);
|
||||
first = next;
|
||||
} else {
|
||||
assert(NULL != e);
|
||||
e->next = next;
|
||||
}
|
||||
}
|
||||
|
||||
return(first);
|
||||
err:
|
||||
exprfree(first);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a terminal expression with the grammar as defined in
|
||||
* apropos(1).
|
||||
* Return NULL if we fail the parse.
|
||||
*/
|
||||
static struct expr *
|
||||
exprterm(char *buf, int cs)
|
||||
{
|
||||
struct expr e;
|
||||
struct expr *p;
|
||||
char *key;
|
||||
int i;
|
||||
|
||||
memset(&e, 0, sizeof(struct expr));
|
||||
|
||||
/* Choose regex or substring match. */
|
||||
|
||||
if (NULL == (e.v = strpbrk(buf, "=~"))) {
|
||||
e.regex = 0;
|
||||
e.v = buf;
|
||||
} else {
|
||||
e.regex = '~' == *e.v;
|
||||
*e.v++ = '\0';
|
||||
}
|
||||
|
||||
/* Determine the record types to search for. */
|
||||
|
||||
e.mask = 0;
|
||||
if (buf < e.v) {
|
||||
while (NULL != (key = strsep(&buf, ","))) {
|
||||
i = 0;
|
||||
while (types[i].mask &&
|
||||
strcmp(types[i].name, key))
|
||||
i++;
|
||||
e.mask |= types[i].mask;
|
||||
}
|
||||
}
|
||||
if (0 == e.mask)
|
||||
e.mask = TYPE_Nm | TYPE_Nd;
|
||||
|
||||
if (e.regex) {
|
||||
i = REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE);
|
||||
if (regcomp(&e.re, e.v, i))
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
e.v = mandoc_strdup(e.v);
|
||||
|
||||
p = mandoc_calloc(1, sizeof(struct expr));
|
||||
memcpy(p, &e, sizeof(struct expr));
|
||||
return(p);
|
||||
}
|
||||
|
||||
void
|
||||
exprfree(struct expr *p)
|
||||
{
|
||||
struct expr *pp;
|
||||
|
||||
while (NULL != p) {
|
||||
if (p->subexpr)
|
||||
exprfree(p->subexpr);
|
||||
if (p->regex)
|
||||
regfree(&p->re);
|
||||
free(p->v);
|
||||
pp = p->next;
|
||||
free(p);
|
||||
p = pp;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exprmark(const struct expr *p, const char *cp,
|
||||
uint64_t mask, int *ms)
|
||||
{
|
||||
|
||||
for ( ; p; p = p->next) {
|
||||
if (p->subexpr) {
|
||||
if (exprmark(p->subexpr, cp, mask, ms))
|
||||
return(1);
|
||||
continue;
|
||||
} else if ( ! (mask & p->mask))
|
||||
continue;
|
||||
|
||||
if (p->regex) {
|
||||
if (regexec(&p->re, cp, 0, NULL, 0))
|
||||
continue;
|
||||
} else if (NULL == strcasestr(cp, p->v))
|
||||
continue;
|
||||
|
||||
if (NULL == ms)
|
||||
return(1);
|
||||
else
|
||||
ms[p->index] = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
expreval(const struct expr *p, int *ms)
|
||||
{
|
||||
int match;
|
||||
|
||||
/*
|
||||
* AND has precedence over OR. Analysis is left-right, though
|
||||
* it doesn't matter because there are no side-effects.
|
||||
* Thus, step through pairwise ANDs and accumulate their Boolean
|
||||
* evaluation. If we encounter a single true AND collection or
|
||||
* standalone term, the whole expression is true (by definition
|
||||
* of OR).
|
||||
*/
|
||||
|
||||
for (match = 0; p && ! match; p = p->next) {
|
||||
/* Evaluate a subexpression, if applicable. */
|
||||
if (p->subexpr && ! ms[p->index])
|
||||
ms[p->index] = expreval(p->subexpr, ms);
|
||||
|
||||
match = ms[p->index];
|
||||
for ( ; p->next && p->next->and; p = p->next) {
|
||||
/* Evaluate a subexpression, if applicable. */
|
||||
if (p->next->subexpr && ! ms[p->next->index])
|
||||
ms[p->next->index] =
|
||||
expreval(p->next->subexpr, ms);
|
||||
match = match && ms[p->next->index];
|
||||
}
|
||||
}
|
||||
|
||||
return(match);
|
||||
}
|
||||
|
||||
/*
|
||||
* First, update the array of terms for which this expression evaluates
|
||||
* to true.
|
||||
* Second, logically evaluate all terms over the updated array of truth
|
||||
* values.
|
||||
* If this evaluates to true, mark the expression as satisfied.
|
||||
*/
|
||||
static void
|
||||
exprexec(const struct expr *e, const char *cp,
|
||||
uint64_t mask, struct res *r)
|
||||
{
|
||||
|
||||
assert(0 == r->matched);
|
||||
exprmark(e, cp, mask, r->matches);
|
||||
r->matched = expreval(e, r->matches);
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/* $Vendor-Id: apropos_db.h,v 1.13 2012/03/24 01:46:25 kristaps Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef APROPOS_H
|
||||
#define APROPOS_H
|
||||
|
||||
enum restype {
|
||||
RESTYPE_MAN, /* man(7) file */
|
||||
RESTYPE_MDOC, /* mdoc(7) file */
|
||||
RESTYPE_CAT /* pre-formatted file */
|
||||
};
|
||||
|
||||
struct res {
|
||||
enum restype type; /* input file type */
|
||||
char *file; /* file in file-system */
|
||||
char *cat; /* category (3p, 3, etc.) */
|
||||
char *title; /* title (FOO, etc.) */
|
||||
char *arch; /* arch (or empty string) */
|
||||
char *desc; /* description (from Nd) */
|
||||
unsigned int rec; /* record in index */
|
||||
/*
|
||||
* The index volume. This indexes into the array of directories
|
||||
* searched for manual page databases.
|
||||
*/
|
||||
unsigned int volume;
|
||||
/*
|
||||
* The following fields are used internally.
|
||||
*
|
||||
* Maintain a binary tree for checking the uniqueness of `rec'
|
||||
* when adding elements to the results array.
|
||||
* Since the results array is dynamic, use offset in the array
|
||||
* instead of a pointer to the structure.
|
||||
*/
|
||||
int lhs;
|
||||
int rhs;
|
||||
int matched; /* expression is true */
|
||||
int *matches; /* partial truth evaluations */
|
||||
};
|
||||
|
||||
struct opts {
|
||||
const char *arch; /* restrict to architecture */
|
||||
const char *cat; /* restrict to manual section */
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct expr;
|
||||
|
||||
int apropos_search(int, char **, const struct opts *,
|
||||
const struct expr *, size_t,
|
||||
void *, size_t *, struct res **,
|
||||
void (*)(struct res *, size_t, void *));
|
||||
struct expr *exprcomp(int, char *[], size_t *);
|
||||
void exprfree(struct expr *);
|
||||
void resfree(struct res *, size_t);
|
||||
struct expr *termcomp(int, char *[], size_t *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /*!APROPOS_H*/
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: arch.in,v 1.12 2012/01/28 14:02:17 joerg Exp $ */
|
||||
/* Id: arch.in,v 1.14 2013/09/16 22:12:57 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
@ -38,9 +38,9 @@ LINE("arm", "ARM")
|
|||
LINE("arm26", "ARM26")
|
||||
LINE("arm32", "ARM32")
|
||||
LINE("armish", "ARMISH")
|
||||
LINE("armv7", "ARMv7")
|
||||
LINE("aviion", "AViiON")
|
||||
LINE("atari", "ATARI")
|
||||
LINE("beagle", "Beagle")
|
||||
LINE("bebox", "BeBox")
|
||||
LINE("cats", "cats")
|
||||
LINE("cesfic", "CESFIC")
|
||||
|
@ -81,6 +81,7 @@ LINE("netwinder", "NetWinder")
|
|||
LINE("news68k", "NeWS68k")
|
||||
LINE("newsmips", "NeWSMIPS")
|
||||
LINE("next68k", "NeXT68k")
|
||||
LINE("octeon", "OCTEON")
|
||||
LINE("ofppc", "OFPPC")
|
||||
LINE("palm", "Palm")
|
||||
LINE("pc532", "PC532")
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
.\" $Vendor-Id: catman.8,v 1.5 2011/12/25 19:35:44 kristaps Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\"
|
||||
.\" 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 December 25, 2011
|
||||
.Dt CATMAN 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm catman
|
||||
.Nd update a man.cgi manpage cache
|
||||
.Sh SYNOPSIS
|
||||
.Nm catman
|
||||
.Op Fl fv
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar manpath
|
||||
.Op Fl m Ar manpath
|
||||
.Op Fl o Ar path
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility updates cached manpages for a jailed
|
||||
.Xr man.cgi 7 .
|
||||
.Pp
|
||||
By default,
|
||||
.Nm
|
||||
searches for
|
||||
.Xr mandocdb 8
|
||||
databases in the default paths stipulated by
|
||||
.Xr man 1
|
||||
and updates the cache in
|
||||
.Pa /var/www/cache/man.cgi .
|
||||
.Pp
|
||||
Its arguments are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl f
|
||||
Force an update to all files.
|
||||
.It Fl v
|
||||
Print each file being updated.
|
||||
.It Fl C Ar file
|
||||
Specify an alternative configuration
|
||||
.Ar file
|
||||
in
|
||||
.Xr man.conf 5
|
||||
format.
|
||||
.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 o Ar path
|
||||
Update into the directory tree under
|
||||
.Ar path .
|
||||
.El
|
||||
.Pp
|
||||
Cache updates occur when a
|
||||
.Xr mandocdb 8
|
||||
database is older than the cached copy unless
|
||||
.Fl f
|
||||
is specified, in which case files are always considered out of date.
|
||||
Cached manual pages are only updated if older than the master copy.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Ds
|
||||
.It Ev MANPATH
|
||||
Colon-separated paths modifying the default list of paths searched for
|
||||
manual databases.
|
||||
Invalid paths, or paths without manual databases, are ignored.
|
||||
Overridden by
|
||||
.Fl M .
|
||||
If
|
||||
.Ev MANPATH
|
||||
begins with a
|
||||
.Sq \&: ,
|
||||
it is appended to the default list;
|
||||
else if it ends with
|
||||
.Sq \&: ,
|
||||
it is prepended to the default list; else if it contains
|
||||
.Sq \&:: ,
|
||||
the default list is inserted between the colons.
|
||||
If none of these conditions are met, it overrides the default list.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
.Xr man.cgi 7 ,
|
||||
.Xr mandocdb 8
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Kristaps Dzonsons ,
|
||||
.Mt kristaps@bsd.lv .
|
|
@ -1,511 +0,0 @@
|
|||
/* $Vendor-Id: catman.c,v 1.10 2012/01/03 15:17:20 kristaps Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include <db_185.h>
|
||||
#else
|
||||
# include <db.h>
|
||||
#endif
|
||||
|
||||
#include "manpath.h"
|
||||
#include "mandocdb.h"
|
||||
|
||||
#define xstrlcpy(_dst, _src, _sz) \
|
||||
do if (strlcpy((_dst), (_src), (_sz)) >= (_sz)) { \
|
||||
fprintf(stderr, "%s: Path too long", (_dst)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (/* CONSTCOND */0)
|
||||
|
||||
#define xstrlcat(_dst, _src, _sz) \
|
||||
do if (strlcat((_dst), (_src), (_sz)) >= (_sz)) { \
|
||||
fprintf(stderr, "%s: Path too long", (_dst)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (/* CONSTCOND */0)
|
||||
|
||||
static int indexhtml(char *, size_t, char *, size_t);
|
||||
static int manup(const struct manpaths *, char *);
|
||||
static int mkpath(char *, mode_t, mode_t);
|
||||
static int treecpy(char *, char *);
|
||||
static int update(char *, char *);
|
||||
static void usage(void);
|
||||
|
||||
static const char *progname;
|
||||
static int verbose;
|
||||
static int force;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
char *aux, *base, *conf_file;
|
||||
struct manpaths dirs;
|
||||
char buf[MAXPATHLEN];
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
progname = argv[0];
|
||||
else
|
||||
++progname;
|
||||
|
||||
aux = base = conf_file = NULL;
|
||||
xstrlcpy(buf, "/var/www/cache/man.cgi", MAXPATHLEN);
|
||||
|
||||
while (-1 != (ch = getopt(argc, argv, "C:fm:M:o:v")))
|
||||
switch (ch) {
|
||||
case ('C'):
|
||||
conf_file = optarg;
|
||||
break;
|
||||
case ('f'):
|
||||
force = 1;
|
||||
break;
|
||||
case ('m'):
|
||||
aux = optarg;
|
||||
break;
|
||||
case ('M'):
|
||||
base = optarg;
|
||||
break;
|
||||
case ('o'):
|
||||
xstrlcpy(buf, optarg, MAXPATHLEN);
|
||||
break;
|
||||
case ('v'):
|
||||
verbose++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 0) {
|
||||
usage();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&dirs, 0, sizeof(struct manpaths));
|
||||
manpath_parse(&dirs, conf_file, base, aux);
|
||||
ch = manup(&dirs, buf);
|
||||
manpath_free(&dirs);
|
||||
return(ch ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s "
|
||||
"[-fv] "
|
||||
"[-C file] "
|
||||
"[-o path] "
|
||||
"[-m manpath] "
|
||||
"[-M manpath]\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
/*
|
||||
* If "src" file doesn't exist (errors out), return -1. Otherwise,
|
||||
* return 1 if "src" is newer (which also happens "dst" doesn't exist)
|
||||
* and 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
isnewer(const char *dst, const char *src)
|
||||
{
|
||||
struct stat s1, s2;
|
||||
|
||||
if (-1 == stat(src, &s1))
|
||||
return(-1);
|
||||
if (force)
|
||||
return(1);
|
||||
|
||||
return(-1 == stat(dst, &s2) ? 1 : s1.st_mtime > s2.st_mtime);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the contents of one file into another.
|
||||
* Returns 0 on failure, 1 on success.
|
||||
*/
|
||||
static int
|
||||
filecpy(const char *dst, const char *src)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int sfd, dfd, rc;
|
||||
ssize_t rsz, wsz;
|
||||
|
||||
sfd = dfd = -1;
|
||||
rc = 0;
|
||||
|
||||
if (-1 == (dfd = open(dst, O_CREAT|O_TRUNC|O_WRONLY, 0644))) {
|
||||
perror(dst);
|
||||
goto out;
|
||||
} else if (-1 == (sfd = open(src, O_RDONLY, 0))) {
|
||||
perror(src);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while ((rsz = read(sfd, buf, BUFSIZ)) > 0)
|
||||
if (-1 == (wsz = write(dfd, buf, (size_t)rsz))) {
|
||||
perror(dst);
|
||||
goto out;
|
||||
} else if (wsz < rsz) {
|
||||
fprintf(stderr, "%s: Short write\n", dst);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rsz < 0)
|
||||
perror(src);
|
||||
else
|
||||
rc = 1;
|
||||
out:
|
||||
if (-1 != sfd)
|
||||
close(sfd);
|
||||
if (-1 != dfd)
|
||||
close(dfd);
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass over the recno database and re-create HTML pages if they're
|
||||
* found to be out of date.
|
||||
* Returns -1 on fatal error, 1 on success.
|
||||
*/
|
||||
static int
|
||||
indexhtml(char *src, size_t ssz, char *dst, size_t dsz)
|
||||
{
|
||||
DB *idx;
|
||||
DBT key, val;
|
||||
int c, rc;
|
||||
unsigned int fl;
|
||||
const char *f;
|
||||
char *d;
|
||||
char fname[MAXPATHLEN];
|
||||
pid_t pid;
|
||||
|
||||
pid = -1;
|
||||
|
||||
xstrlcpy(fname, dst, MAXPATHLEN);
|
||||
xstrlcat(fname, "/", MAXPATHLEN);
|
||||
xstrlcat(fname, MANDOC_IDX, MAXPATHLEN);
|
||||
|
||||
idx = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL);
|
||||
if (NULL == idx) {
|
||||
perror(fname);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
fl = R_FIRST;
|
||||
while (0 == (c = (*idx->seq)(idx, &key, &val, fl))) {
|
||||
fl = R_NEXT;
|
||||
/*
|
||||
* If the record is zero-length, then it's unassigned.
|
||||
* Skip past these.
|
||||
*/
|
||||
if (0 == val.size)
|
||||
continue;
|
||||
|
||||
f = (const char *)val.data + 1;
|
||||
if (NULL == memchr(f, '\0', val.size - 1))
|
||||
break;
|
||||
|
||||
src[(int)ssz] = dst[(int)dsz] = '\0';
|
||||
|
||||
xstrlcat(dst, "/", MAXPATHLEN);
|
||||
xstrlcat(dst, f, MAXPATHLEN);
|
||||
|
||||
xstrlcat(src, "/", MAXPATHLEN);
|
||||
xstrlcat(src, f, MAXPATHLEN);
|
||||
|
||||
if (-1 == (rc = isnewer(dst, src))) {
|
||||
fprintf(stderr, "%s: File missing\n", f);
|
||||
break;
|
||||
} else if (0 == rc)
|
||||
continue;
|
||||
|
||||
d = strrchr(dst, '/');
|
||||
assert(NULL != d);
|
||||
*d = '\0';
|
||||
|
||||
if (-1 == mkpath(dst, 0755, 0755)) {
|
||||
perror(dst);
|
||||
break;
|
||||
}
|
||||
|
||||
*d = '/';
|
||||
|
||||
if ( ! filecpy(dst, src))
|
||||
break;
|
||||
if (verbose)
|
||||
printf("%s\n", dst);
|
||||
}
|
||||
|
||||
(*idx->close)(idx);
|
||||
|
||||
if (c < 0)
|
||||
perror(fname);
|
||||
else if (0 == c)
|
||||
fprintf(stderr, "%s: Corrupt index\n", fname);
|
||||
|
||||
return(1 == c ? 1 : -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy both recno and btree databases into the destination.
|
||||
* Call in to begin recreating HTML files.
|
||||
* Return -1 on fatal error and 1 if the update went well.
|
||||
*/
|
||||
static int
|
||||
update(char *dst, char *src)
|
||||
{
|
||||
size_t dsz, ssz;
|
||||
|
||||
dsz = strlen(dst);
|
||||
ssz = strlen(src);
|
||||
|
||||
xstrlcat(src, "/", MAXPATHLEN);
|
||||
xstrlcat(dst, "/", MAXPATHLEN);
|
||||
|
||||
xstrlcat(src, MANDOC_DB, MAXPATHLEN);
|
||||
xstrlcat(dst, MANDOC_DB, MAXPATHLEN);
|
||||
|
||||
if ( ! filecpy(dst, src))
|
||||
return(-1);
|
||||
if (verbose)
|
||||
printf("%s\n", dst);
|
||||
|
||||
dst[(int)dsz] = src[(int)ssz] = '\0';
|
||||
|
||||
xstrlcat(src, "/", MAXPATHLEN);
|
||||
xstrlcat(dst, "/", MAXPATHLEN);
|
||||
|
||||
xstrlcat(src, MANDOC_IDX, MAXPATHLEN);
|
||||
xstrlcat(dst, MANDOC_IDX, MAXPATHLEN);
|
||||
|
||||
if ( ! filecpy(dst, src))
|
||||
return(-1);
|
||||
if (verbose)
|
||||
printf("%s\n", dst);
|
||||
|
||||
dst[(int)dsz] = src[(int)ssz] = '\0';
|
||||
|
||||
return(indexhtml(src, ssz, dst, dsz));
|
||||
}
|
||||
|
||||
/*
|
||||
* See if btree or recno databases in the destination are out of date
|
||||
* with respect to a single manpath component.
|
||||
* Return -1 on fatal error, 0 if the source is no longer valid (and
|
||||
* shouldn't be listed), and 1 if the update went well.
|
||||
*/
|
||||
static int
|
||||
treecpy(char *dst, char *src)
|
||||
{
|
||||
size_t dsz, ssz;
|
||||
int rc;
|
||||
|
||||
dsz = strlen(dst);
|
||||
ssz = strlen(src);
|
||||
|
||||
xstrlcat(src, "/", MAXPATHLEN);
|
||||
xstrlcat(dst, "/", MAXPATHLEN);
|
||||
|
||||
xstrlcat(src, MANDOC_IDX, MAXPATHLEN);
|
||||
xstrlcat(dst, MANDOC_IDX, MAXPATHLEN);
|
||||
|
||||
if (-1 == (rc = isnewer(dst, src)))
|
||||
return(0);
|
||||
|
||||
dst[(int)dsz] = src[(int)ssz] = '\0';
|
||||
|
||||
if (1 == rc)
|
||||
return(update(dst, src));
|
||||
|
||||
xstrlcat(src, "/", MAXPATHLEN);
|
||||
xstrlcat(dst, "/", MAXPATHLEN);
|
||||
|
||||
xstrlcat(src, MANDOC_DB, MAXPATHLEN);
|
||||
xstrlcat(dst, MANDOC_DB, MAXPATHLEN);
|
||||
|
||||
if (-1 == (rc = isnewer(dst, src)))
|
||||
return(0);
|
||||
else if (rc == 0)
|
||||
return(1);
|
||||
|
||||
dst[(int)dsz] = src[(int)ssz] = '\0';
|
||||
|
||||
return(update(dst, src));
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the destination's file-tree with respect to changes in the
|
||||
* source manpath components.
|
||||
* "Change" is defined by an updated index or btree database.
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
manup(const struct manpaths *dirs, char *base)
|
||||
{
|
||||
char dst[MAXPATHLEN],
|
||||
src[MAXPATHLEN];
|
||||
const char *path;
|
||||
int i, c;
|
||||
size_t sz;
|
||||
FILE *f;
|
||||
|
||||
/* Create the path and file for the catman.conf file. */
|
||||
|
||||
sz = strlen(base);
|
||||
xstrlcpy(dst, base, MAXPATHLEN);
|
||||
xstrlcat(dst, "/etc", MAXPATHLEN);
|
||||
if (-1 == mkpath(dst, 0755, 0755)) {
|
||||
perror(dst);
|
||||
return(0);
|
||||
}
|
||||
|
||||
xstrlcat(dst, "/catman.conf", MAXPATHLEN);
|
||||
if (NULL == (f = fopen(dst, "w"))) {
|
||||
perror(dst);
|
||||
return(0);
|
||||
} else if (verbose)
|
||||
printf("%s\n", dst);
|
||||
|
||||
for (i = 0; i < dirs->sz; i++) {
|
||||
path = dirs->paths[i];
|
||||
dst[(int)sz] = '\0';
|
||||
xstrlcat(dst, path, MAXPATHLEN);
|
||||
if (-1 == mkpath(dst, 0755, 0755)) {
|
||||
perror(dst);
|
||||
break;
|
||||
}
|
||||
|
||||
xstrlcpy(src, path, MAXPATHLEN);
|
||||
if (-1 == (c = treecpy(dst, src)))
|
||||
break;
|
||||
else if (0 == c)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We want to use a relative path here because manpath.h
|
||||
* will realpath() when invoked with man.cgi, and we'll
|
||||
* make sure to chdir() into the cache directory before.
|
||||
*
|
||||
* This allows the cache directory to be in an arbitrary
|
||||
* place, working in both chroot() and non-chroot()
|
||||
* "safe" modes.
|
||||
*/
|
||||
assert('/' == path[0]);
|
||||
fprintf(f, "_whatdb %s/whatis.db\n", path + 1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return(i == dirs->sz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
static int
|
||||
mkpath(char *path, mode_t mode, mode_t dir_mode)
|
||||
{
|
||||
struct stat sb;
|
||||
char *slash;
|
||||
int done, exists;
|
||||
|
||||
slash = path;
|
||||
|
||||
for (;;) {
|
||||
/* LINTED */
|
||||
slash += strspn(slash, "/");
|
||||
/* LINTED */
|
||||
slash += strcspn(slash, "/");
|
||||
|
||||
done = (*slash == '\0');
|
||||
*slash = '\0';
|
||||
|
||||
/* skip existing path components */
|
||||
exists = !stat(path, &sb);
|
||||
if (!done && exists && S_ISDIR(sb.st_mode)) {
|
||||
*slash = '/';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mkdir(path, done ? mode : dir_mode) == 0) {
|
||||
if (mode > 0777 && chmod(path, mode) < 0)
|
||||
return (-1);
|
||||
} else {
|
||||
if (!exists) {
|
||||
/* Not there */
|
||||
return (-1);
|
||||
}
|
||||
if (!S_ISDIR(sb.st_mode)) {
|
||||
/* Is there, but isn't a directory */
|
||||
errno = ENOTDIR;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (done)
|
||||
break;
|
||||
|
||||
*slash = '/';
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -8,7 +8,7 @@ int dummy;
|
|||
|
||||
#else
|
||||
|
||||
/* $NetBSD: compat_fgetln.c,v 1.2 2012/01/30 17:03:01 joerg Exp $ */
|
||||
/* NetBSD: fgetln.c,v 1.3 2006/09/25 07:18:17 lukem Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: lib.in,v 1.13 2012/01/28 23:46:28 joerg Exp $ */
|
||||
/* Id: lib.in,v 1.17 2013/10/13 15:24:03 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
@ -23,10 +23,12 @@
|
|||
* Be sure to escape strings.
|
||||
*/
|
||||
|
||||
LINE("libarchive", "Reading and Writing Streaming Archives Library (libarchive, \\-larchive)")
|
||||
LINE("libalias", "Packet Aliasing Library (libalias, \\-lalias)")
|
||||
LINE("libarchive", "Streaming Archive Library (libarchive, \\-larchive)")
|
||||
LINE("libarm", "ARM Architecture Library (libarm, \\-larm)")
|
||||
LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)")
|
||||
LINE("libbluetooth", "Bluetooth Library (libbluetooth, \\-lbluetooth)")
|
||||
LINE("libbsdxml", "eXpat XML parser library (libbsdxml, \\-lbsdxml)")
|
||||
LINE("libbsm", "Basic Security Module User Library (libbsm, \\-lbsm)")
|
||||
LINE("libc", "Standard C Library (libc, \\-lc)")
|
||||
LINE("libc_r", "Reentrant C\\~Library (libc_r, \\-lc_r)")
|
||||
|
@ -37,18 +39,24 @@ LINE("libcipher", "FreeSec Crypt Library (libcipher, \\-lcipher)")
|
|||
LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)")
|
||||
LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
|
||||
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
|
||||
LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
|
||||
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
|
||||
LINE("libdevstat", "Device Statistics Library (libdevstat, \\-ldevstat)")
|
||||
LINE("libdisk", "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")
|
||||
LINE("libdm", "Device Mapper Library (libdm, \\-ldm)")
|
||||
LINE("libdwarf", "DWARF Access Library (libdwarf, \\-ldwarf)")
|
||||
LINE("libedit", "Command Line Editor Library (libedit, \\-ledit)")
|
||||
LINE("libefi", "EFI Runtime Services Library (libefi, \\-lefi)")
|
||||
LINE("libelf", "ELF Access Library (libelf, \\-lelf)")
|
||||
LINE("libevent", "Event Notification Library (libevent, \\-levent)")
|
||||
LINE("libexecinfo", "Backtrace Information Library (libexecinfo, \\-lexecinfo)")
|
||||
LINE("libfetch", "File Transfer Library for URLs (libfetch, \\-lfetch)")
|
||||
LINE("libfetch", "File Transfer Library (libfetch, \\-lfetch)")
|
||||
LINE("libfsid", "Filesystem Identification Library (libfsid, \\-lfsid)")
|
||||
LINE("libftpio", "FTP Connection Management Library (libftpio, \\-lftpio)")
|
||||
LINE("libform", "Curses Form Library (libform, \\-lform)")
|
||||
LINE("libgeom", "Userland API Library for Kernel GEOM subsystem (libgeom, \\-lgeom)")
|
||||
LINE("libgpib", "General-Purpose Instrument Bus (GPIB) library (libgpib, \\-lgpib)")
|
||||
LINE("libhammer", "HAMMER Filesystem Userland Library (libhammer, \\-lhammer)")
|
||||
LINE("libi386", "i386 Architecture Library (libi386, \\-li386)")
|
||||
LINE("libintl", "Internationalized Message Handling Library (libintl, \\-lintl)")
|
||||
LINE("libipsec", "IPsec Policy Control Library (libipsec, \\-lipsec)")
|
||||
|
@ -56,6 +64,7 @@ LINE("libipx", "IPX Address Conversion Support Library (libipx, \\-lipx)")
|
|||
LINE("libiscsi", "iSCSI protocol library (libiscsi, \\-liscsi)")
|
||||
LINE("libisns", "Internet Storage Name Service Library (libisns, \\-lisns)")
|
||||
LINE("libjail", "Jail Library (libjail, \\-ljail)")
|
||||
LINE("libkcore", "Kernel Memory Core Access Library (libkcore, \\-lkcore)")
|
||||
LINE("libkiconv", "Kernel-side iconv Library (libkiconv, \\-lkiconv)")
|
||||
LINE("libkse", "N:M Threading Library (libkse, \\-lkse)")
|
||||
LINE("libkvm", "Kernel Data Access Library (libkvm, \\-lkvm)")
|
||||
|
@ -76,12 +85,15 @@ LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)")
|
|||
LINE("libpcap", "Capture Library (libpcap, \\-lpcap)")
|
||||
LINE("libpci", "PCI Bus Access Library (libpci, \\-lpci)")
|
||||
LINE("libpmc", "Performance Counters Library (libpmc, \\-lpmc)")
|
||||
LINE("libppath", "Property-List Paths Library (libppath, \\-lppath)")
|
||||
LINE("libposix", "POSIX Compatibility Library (libposix, \\-lposix)")
|
||||
LINE("libposix1e", "POSIX.1e Security API Library (libposix1e, \\-lposix1e)")
|
||||
LINE("libppath", "Property-List Paths Library (libppath, \\-lppath)")
|
||||
LINE("libprop", "Property Container Object Library (libprop, \\-lprop)")
|
||||
LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)")
|
||||
LINE("libpuffs", "puffs Convenience Library (libpuffs, \\-lpuffs)")
|
||||
LINE("libquota", "Disk Quota Access and Control Library (libquota, \\-lquota)")
|
||||
LINE("libradius", "RADIUS Client Library (libradius, \\-lradius)")
|
||||
LINE("librefuse", "File System in Userspace Convenience Library (librefuse, \\-lrefuse)")
|
||||
LINE("libresolv", "DNS Resolver Library (libresolv, \\-lresolv)")
|
||||
LINE("librpcsec_gss", "RPC GSS-API Authentication Library (librpcsec_gss, \\-lrpcsec_gss)")
|
||||
|
@ -91,7 +103,10 @@ LINE("librumpclient", "Clientside Stubs for rump Kernel Remote Protocols (librum
|
|||
LINE("libsaslc", "Simple Authentication and Security Layer client library (libsaslc, \\-lsaslc)")
|
||||
LINE("libsdp", "Bluetooth Service Discovery Protocol User Library (libsdp, \\-lsdp)")
|
||||
LINE("libssp", "Buffer Overflow Protection Library (libssp, \\-lssp)")
|
||||
LINE("libstand", "Standalone Applications Library (libstand, \\-lstand)")
|
||||
LINE("libSystem", "System Library (libSystem, \\-lSystem)")
|
||||
LINE("libtacplus", "TACACS+ Client Library (libtacplus, \\-ltacplus)")
|
||||
LINE("libtcplay", "TrueCrypt-compatible API library (libtcplay, \\-ltcplay)")
|
||||
LINE("libtermcap", "Termcap Access Library (libtermcap, \\-ltermcap)")
|
||||
LINE("libterminfo", "Terminal Information Library (libterminfo, \\-lterminfo)")
|
||||
LINE("libthr", "1:1 Threading Library (libthr, \\-lthr)")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* $Vendor-Id: libmandoc.h,v 1.29 2011/12/02 01:37:14 schwarze Exp $ */
|
||||
/* Id: libmandoc.h,v 1.37 2014/01/05 19:10:56 joerg Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013 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
|
||||
|
@ -29,11 +30,6 @@ enum rofferr {
|
|||
ROFF_ERR /* badness: puke and stop */
|
||||
};
|
||||
|
||||
enum regs {
|
||||
REG_nS = 0, /* nS register */
|
||||
REG__MAX
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct roff;
|
||||
|
@ -42,17 +38,19 @@ struct man;
|
|||
|
||||
void mandoc_msg(enum mandocerr, struct mparse *,
|
||||
int, int, const char *);
|
||||
#if __GNUC__ - 0 >= 4
|
||||
__attribute__((__format__ (__printf__, 5, 6)))
|
||||
#endif
|
||||
void mandoc_vmsg(enum mandocerr, struct mparse *,
|
||||
int, int, const char *, ...);
|
||||
char *mandoc_getarg(struct mparse *, char **, int, int *);
|
||||
char *mandoc_normdate(struct mparse *, char *, int, int);
|
||||
int mandoc_eos(const char *, size_t, int);
|
||||
int mandoc_getcontrol(const char *, int *);
|
||||
int mandoc_eos(const char *, size_t);
|
||||
int mandoc_strntoi(const char *, size_t, int);
|
||||
const char *mandoc_a2msec(const char*);
|
||||
|
||||
void mdoc_free(struct mdoc *);
|
||||
struct mdoc *mdoc_alloc(struct roff *, struct mparse *);
|
||||
struct mdoc *mdoc_alloc(struct roff *, struct mparse *, char *);
|
||||
void mdoc_reset(struct mdoc *);
|
||||
int mdoc_parseln(struct mdoc *, int, char *, int);
|
||||
int mdoc_endparse(struct mdoc *);
|
||||
|
@ -68,17 +66,16 @@ int man_addspan(struct man *, const struct tbl_span *);
|
|||
int man_addeqn(struct man *, const struct eqn *);
|
||||
|
||||
void roff_free(struct roff *);
|
||||
struct roff *roff_alloc(struct mparse *);
|
||||
struct roff *roff_alloc(enum mparset, struct mparse *);
|
||||
void roff_reset(struct roff *);
|
||||
enum rofferr roff_parseln(struct roff *, int,
|
||||
char **, size_t *, int, int *);
|
||||
void roff_endparse(struct roff *);
|
||||
void roff_expand_nr(struct roff *, const char *, int *, size_t,
|
||||
char **, int *, size_t *);
|
||||
int roff_regisset(const struct roff *, enum regs);
|
||||
unsigned int roff_regget(const struct roff *, enum regs);
|
||||
void roff_regunset(struct roff *, enum regs);
|
||||
void roff_setreg(struct roff *, const char *, int, char sign);
|
||||
int roff_getreg(const struct roff *, const char *);
|
||||
char *roff_strdup(const struct roff *, const char *);
|
||||
int roff_getcontrol(const struct roff *,
|
||||
const char *, int *);
|
||||
#if 0
|
||||
char roff_eqndelim(const struct roff *);
|
||||
void roff_openeqn(struct roff *, const char *,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Vendor-Id: man_term.c,v 1.127 2012/01/03 15:16:24 kristaps Exp $ */
|
||||
/* Id: man_term.c,v 1.139 2013/12/22 23:34:13 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 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
|
||||
|
@ -35,8 +35,6 @@
|
|||
|
||||
#define MAXMARGINS 64 /* maximum number of indented scopes */
|
||||
|
||||
/* FIXME: have PD set the default vspace width. */
|
||||
|
||||
struct mtermp {
|
||||
int fl;
|
||||
#define MANT_LITERAL (1 << 0)
|
||||
|
@ -44,12 +42,13 @@ struct mtermp {
|
|||
int lmargincur; /* index of current margin */
|
||||
int lmarginsz; /* actual number of nested margins */
|
||||
size_t offset; /* default offset to visible page */
|
||||
int pardist; /* vert. space before par., unit: [v] */
|
||||
};
|
||||
|
||||
#define DECL_ARGS struct termp *p, \
|
||||
struct mtermp *mt, \
|
||||
const struct man_node *n, \
|
||||
const struct man_meta *m
|
||||
const struct man_meta *meta
|
||||
|
||||
struct termact {
|
||||
int (*pre)(DECL_ARGS);
|
||||
|
@ -66,18 +65,20 @@ static void print_man_node(DECL_ARGS);
|
|||
static void print_man_head(struct termp *, const void *);
|
||||
static void print_man_foot(struct termp *, const void *);
|
||||
static void print_bvspace(struct termp *,
|
||||
const struct man_node *);
|
||||
const struct man_node *, int);
|
||||
|
||||
static int pre_B(DECL_ARGS);
|
||||
static int pre_HP(DECL_ARGS);
|
||||
static int pre_I(DECL_ARGS);
|
||||
static int pre_IP(DECL_ARGS);
|
||||
static int pre_OP(DECL_ARGS);
|
||||
static int pre_PD(DECL_ARGS);
|
||||
static int pre_PP(DECL_ARGS);
|
||||
static int pre_RS(DECL_ARGS);
|
||||
static int pre_SH(DECL_ARGS);
|
||||
static int pre_SS(DECL_ARGS);
|
||||
static int pre_TP(DECL_ARGS);
|
||||
static int pre_UR(DECL_ARGS);
|
||||
static int pre_alternate(DECL_ARGS);
|
||||
static int pre_ft(DECL_ARGS);
|
||||
static int pre_ign(DECL_ARGS);
|
||||
|
@ -91,6 +92,7 @@ static void post_RS(DECL_ARGS);
|
|||
static void post_SH(DECL_ARGS);
|
||||
static void post_SS(DECL_ARGS);
|
||||
static void post_TP(DECL_ARGS);
|
||||
static void post_UR(DECL_ARGS);
|
||||
|
||||
static const struct termact termacts[MAN_MAX] = {
|
||||
{ pre_sp, NULL, MAN_NOTEXT }, /* br */
|
||||
|
@ -122,11 +124,15 @@ static const struct termact termacts[MAN_MAX] = {
|
|||
{ pre_RS, post_RS, 0 }, /* RS */
|
||||
{ pre_ign, NULL, 0 }, /* DT */
|
||||
{ pre_ign, NULL, 0 }, /* UC */
|
||||
{ pre_ign, NULL, 0 }, /* PD */
|
||||
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */
|
||||
{ pre_ign, NULL, 0 }, /* AT */
|
||||
{ pre_in, NULL, MAN_NOTEXT }, /* in */
|
||||
{ pre_ft, NULL, MAN_NOTEXT }, /* ft */
|
||||
{ pre_OP, NULL, 0 }, /* OP */
|
||||
{ pre_literal, NULL, 0 }, /* EX */
|
||||
{ pre_literal, NULL, 0 }, /* EE */
|
||||
{ pre_UR, post_UR, 0 }, /* UR */
|
||||
{ NULL, NULL, 0 }, /* UE */
|
||||
};
|
||||
|
||||
|
||||
|
@ -136,7 +142,7 @@ terminal_man(void *arg, const struct man *man)
|
|||
{
|
||||
struct termp *p;
|
||||
const struct man_node *n;
|
||||
const struct man_meta *m;
|
||||
const struct man_meta *meta;
|
||||
struct mtermp mt;
|
||||
|
||||
p = (struct termp *)arg;
|
||||
|
@ -152,18 +158,19 @@ terminal_man(void *arg, const struct man *man)
|
|||
p->symtab = mchars_alloc();
|
||||
|
||||
n = man_node(man);
|
||||
m = man_meta(man);
|
||||
meta = man_meta(man);
|
||||
|
||||
term_begin(p, print_man_head, print_man_foot, m);
|
||||
term_begin(p, print_man_head, print_man_foot, meta);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
memset(&mt, 0, sizeof(struct mtermp));
|
||||
|
||||
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
|
||||
mt.offset = term_len(p, p->defindent);
|
||||
mt.pardist = 1;
|
||||
|
||||
if (n->child)
|
||||
print_man_nodelist(p, &mt, n->child, m);
|
||||
print_man_nodelist(p, &mt, n->child, meta);
|
||||
|
||||
term_end(p);
|
||||
}
|
||||
|
@ -201,8 +208,9 @@ a2width(const struct termp *p, const char *cp)
|
|||
* first, print it.
|
||||
*/
|
||||
static void
|
||||
print_bvspace(struct termp *p, const struct man_node *n)
|
||||
print_bvspace(struct termp *p, const struct man_node *n, int pardist)
|
||||
{
|
||||
int i;
|
||||
|
||||
term_newln(p);
|
||||
|
||||
|
@ -214,7 +222,8 @@ print_bvspace(struct termp *p, const struct man_node *n)
|
|||
if (NULL == n->prev)
|
||||
return;
|
||||
|
||||
term_vspace(p);
|
||||
for (i = 0; i < pardist; i++)
|
||||
term_vspace(p);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
|
@ -243,7 +252,7 @@ pre_literal(DECL_ARGS)
|
|||
|
||||
term_newln(p);
|
||||
|
||||
if (MAN_nf == n->tok)
|
||||
if (MAN_nf == n->tok || MAN_EX == n->tok)
|
||||
mt->fl |= MANT_LITERAL;
|
||||
else
|
||||
mt->fl &= ~MANT_LITERAL;
|
||||
|
@ -256,13 +265,29 @@ pre_literal(DECL_ARGS)
|
|||
if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin;
|
||||
p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
|
||||
p->trailspace = 0;
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
pre_PD(DECL_ARGS)
|
||||
{
|
||||
|
||||
n = n->child;
|
||||
if (0 == n) {
|
||||
mt->pardist = 1;
|
||||
return(0);
|
||||
}
|
||||
assert(MAN_TEXT == n->type);
|
||||
mt->pardist = atoi(n->string);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
pre_alternate(DECL_ARGS)
|
||||
|
@ -307,7 +332,7 @@ pre_alternate(DECL_ARGS)
|
|||
term_fontrepl(p, font[i]);
|
||||
if (savelit && NULL == nn->next)
|
||||
mt->fl |= MANT_LITERAL;
|
||||
print_man_node(p, mt, nn, m);
|
||||
print_man_node(p, mt, nn, meta);
|
||||
if (nn->next)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
}
|
||||
|
@ -438,28 +463,54 @@ pre_in(DECL_ARGS)
|
|||
static int
|
||||
pre_sp(DECL_ARGS)
|
||||
{
|
||||
char *s;
|
||||
size_t i, len;
|
||||
int neg;
|
||||
|
||||
if ((NULL == n->prev && n->parent)) {
|
||||
if (MAN_SS == n->parent->tok)
|
||||
return(0);
|
||||
if (MAN_SH == n->parent->tok)
|
||||
switch (n->parent->tok) {
|
||||
case (MAN_SH):
|
||||
/* FALLTHROUGH */
|
||||
case (MAN_SS):
|
||||
/* FALLTHROUGH */
|
||||
case (MAN_PP):
|
||||
/* FALLTHROUGH */
|
||||
case (MAN_LP):
|
||||
/* FALLTHROUGH */
|
||||
case (MAN_P):
|
||||
/* FALLTHROUGH */
|
||||
return(0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
neg = 0;
|
||||
switch (n->tok) {
|
||||
case (MAN_br):
|
||||
len = 0;
|
||||
break;
|
||||
default:
|
||||
len = n->child ? a2height(p, n->child->string) : 1;
|
||||
if (NULL == n->child) {
|
||||
len = 1;
|
||||
break;
|
||||
}
|
||||
s = n->child->string;
|
||||
if ('-' == *s) {
|
||||
neg = 1;
|
||||
s++;
|
||||
}
|
||||
len = a2height(p, s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == len)
|
||||
term_newln(p);
|
||||
for (i = 0; i < len; i++)
|
||||
term_vspace(p);
|
||||
else if (neg)
|
||||
p->skipvsp += len;
|
||||
else
|
||||
for (i = 0; i < len; i++)
|
||||
term_vspace(p);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -475,16 +526,19 @@ pre_HP(DECL_ARGS)
|
|||
|
||||
switch (n->type) {
|
||||
case (MAN_BLOCK):
|
||||
print_bvspace(p, n);
|
||||
print_bvspace(p, n, mt->pardist);
|
||||
return(1);
|
||||
case (MAN_BODY):
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->flags |= TERMP_TWOSPACE;
|
||||
break;
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ( ! (MANT_LITERAL & mt->fl)) {
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 2;
|
||||
}
|
||||
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
ival = -1;
|
||||
|
||||
|
@ -514,13 +568,10 @@ post_HP(DECL_ARGS)
|
|||
{
|
||||
|
||||
switch (n->type) {
|
||||
case (MAN_BLOCK):
|
||||
term_flushln(p);
|
||||
break;
|
||||
case (MAN_BODY):
|
||||
term_flushln(p);
|
||||
term_newln(p);
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags &= ~TERMP_TWOSPACE;
|
||||
p->trailspace = 0;
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = p->maxrmargin;
|
||||
break;
|
||||
|
@ -538,7 +589,7 @@ pre_PP(DECL_ARGS)
|
|||
switch (n->type) {
|
||||
case (MAN_BLOCK):
|
||||
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
|
||||
print_bvspace(p, n);
|
||||
print_bvspace(p, n, mt->pardist);
|
||||
break;
|
||||
default:
|
||||
p->offset = mt->offset;
|
||||
|
@ -563,9 +614,10 @@ pre_IP(DECL_ARGS)
|
|||
break;
|
||||
case (MAN_HEAD):
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
break;
|
||||
case (MAN_BLOCK):
|
||||
print_bvspace(p, n);
|
||||
print_bvspace(p, n, mt->pardist);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return(1);
|
||||
|
@ -598,7 +650,7 @@ pre_IP(DECL_ARGS)
|
|||
mt->fl &= ~MANT_LITERAL;
|
||||
|
||||
if (n->child)
|
||||
print_man_node(p, mt, n->child, m);
|
||||
print_man_node(p, mt, n->child, meta);
|
||||
|
||||
if (savelit)
|
||||
mt->fl |= MANT_LITERAL;
|
||||
|
@ -625,10 +677,12 @@ post_IP(DECL_ARGS)
|
|||
case (MAN_HEAD):
|
||||
term_flushln(p);
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->trailspace = 0;
|
||||
p->rmargin = p->maxrmargin;
|
||||
break;
|
||||
case (MAN_BODY):
|
||||
term_newln(p);
|
||||
p->offset = mt->offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -647,12 +701,13 @@ pre_TP(DECL_ARGS)
|
|||
switch (n->type) {
|
||||
case (MAN_HEAD):
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
break;
|
||||
case (MAN_BODY):
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
break;
|
||||
case (MAN_BLOCK):
|
||||
print_bvspace(p, n);
|
||||
print_bvspace(p, n, mt->pardist);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return(1);
|
||||
|
@ -683,7 +738,7 @@ pre_TP(DECL_ARGS)
|
|||
/* Don't print same-line elements. */
|
||||
for (nn = n->child; nn; nn = nn->next)
|
||||
if (nn->line > n->line)
|
||||
print_man_node(p, mt, nn, m);
|
||||
print_man_node(p, mt, nn, meta);
|
||||
|
||||
if (savelit)
|
||||
mt->fl |= MANT_LITERAL;
|
||||
|
@ -694,6 +749,8 @@ pre_TP(DECL_ARGS)
|
|||
case (MAN_BODY):
|
||||
p->offset = mt->offset + len;
|
||||
p->rmargin = p->maxrmargin;
|
||||
p->trailspace = 0;
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -711,12 +768,10 @@ post_TP(DECL_ARGS)
|
|||
switch (n->type) {
|
||||
case (MAN_HEAD):
|
||||
term_flushln(p);
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags &= ~TERMP_TWOSPACE;
|
||||
p->rmargin = p->maxrmargin;
|
||||
break;
|
||||
case (MAN_BODY):
|
||||
term_newln(p);
|
||||
p->offset = mt->offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -728,6 +783,7 @@ post_TP(DECL_ARGS)
|
|||
static int
|
||||
pre_SS(DECL_ARGS)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (n->type) {
|
||||
case (MAN_BLOCK):
|
||||
|
@ -740,11 +796,12 @@ pre_SS(DECL_ARGS)
|
|||
break;
|
||||
if (NULL == n->prev)
|
||||
break;
|
||||
term_vspace(p);
|
||||
for (i = 0; i < mt->pardist; i++)
|
||||
term_vspace(p);
|
||||
break;
|
||||
case (MAN_HEAD):
|
||||
term_fontrepl(p, TERMFONT_BOLD);
|
||||
p->offset = term_len(p, p->defindent/2);
|
||||
p->offset = term_len(p, 3);
|
||||
break;
|
||||
case (MAN_BODY):
|
||||
p->offset = mt->offset;
|
||||
|
@ -779,6 +836,7 @@ post_SS(DECL_ARGS)
|
|||
static int
|
||||
pre_SH(DECL_ARGS)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (n->type) {
|
||||
case (MAN_BLOCK):
|
||||
|
@ -792,7 +850,8 @@ pre_SH(DECL_ARGS)
|
|||
/* If the first macro, no vspae. */
|
||||
if (NULL == n->prev)
|
||||
break;
|
||||
term_vspace(p);
|
||||
for (i = 0; i < mt->pardist; i++)
|
||||
term_vspace(p);
|
||||
break;
|
||||
case (MAN_HEAD):
|
||||
term_fontrepl(p, TERMFONT_BOLD);
|
||||
|
@ -890,6 +949,32 @@ post_RS(DECL_ARGS)
|
|||
mt->lmargincur = mt->lmarginsz;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
pre_UR(DECL_ARGS)
|
||||
{
|
||||
|
||||
return (MAN_HEAD != n->type);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
post_UR(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MAN_BLOCK != n->type)
|
||||
return;
|
||||
|
||||
term_word(p, "<");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
if (NULL != n->child->child)
|
||||
print_man_node(p, mt, n->child->child, meta);
|
||||
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ">");
|
||||
}
|
||||
|
||||
static void
|
||||
print_man_node(DECL_ARGS)
|
||||
{
|
||||
|
@ -910,29 +995,8 @@ print_man_node(DECL_ARGS)
|
|||
term_newln(p);
|
||||
|
||||
term_word(p, n->string);
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If we're in a literal context, make sure that words
|
||||
* togehter on the same line stay together. This is a
|
||||
* POST-printing call, so we check the NEXT word. Since
|
||||
* -man doesn't have nested macros, we don't need to be
|
||||
* more specific than this.
|
||||
*/
|
||||
if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
|
||||
(NULL == n->next ||
|
||||
n->next->line > n->line)) {
|
||||
rm = p->rmargin;
|
||||
rmax = p->maxrmargin;
|
||||
p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_flushln(p);
|
||||
p->rmargin = rm;
|
||||
p->maxrmargin = rmax;
|
||||
}
|
||||
|
||||
if (MAN_EOS & n->flags)
|
||||
p->flags |= TERMP_SENTENCE;
|
||||
return;
|
||||
case (MAN_EQN):
|
||||
term_eqn(p, n->eqn);
|
||||
return;
|
||||
|
@ -954,16 +1018,41 @@ print_man_node(DECL_ARGS)
|
|||
|
||||
c = 1;
|
||||
if (termacts[n->tok].pre)
|
||||
c = (*termacts[n->tok].pre)(p, mt, n, m);
|
||||
c = (*termacts[n->tok].pre)(p, mt, n, meta);
|
||||
|
||||
if (c && n->child)
|
||||
print_man_nodelist(p, mt, n->child, m);
|
||||
print_man_nodelist(p, mt, n->child, meta);
|
||||
|
||||
if (termacts[n->tok].post)
|
||||
(*termacts[n->tok].post)(p, mt, n, m);
|
||||
(*termacts[n->tok].post)(p, mt, n, meta);
|
||||
if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
|
||||
term_fontrepl(p, TERMFONT_NONE);
|
||||
|
||||
out:
|
||||
/*
|
||||
* If we're in a literal context, make sure that words
|
||||
* together on the same line stay together. This is a
|
||||
* POST-printing call, so we check the NEXT word. Since
|
||||
* -man doesn't have nested macros, we don't need to be
|
||||
* more specific than this.
|
||||
*/
|
||||
if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
|
||||
(NULL == n->next || n->next->line > n->line)) {
|
||||
rm = p->rmargin;
|
||||
rmax = p->maxrmargin;
|
||||
p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
if (NULL != n->string && '\0' != *n->string)
|
||||
term_flushln(p);
|
||||
else
|
||||
term_newln(p);
|
||||
if (rm < rmax && n->parent->tok == MAN_HP) {
|
||||
p->offset = rm;
|
||||
p->rmargin = rmax;
|
||||
} else
|
||||
p->rmargin = rm;
|
||||
p->maxrmargin = rmax;
|
||||
}
|
||||
if (MAN_EOS & n->flags)
|
||||
p->flags |= TERMP_SENTENCE;
|
||||
}
|
||||
|
@ -973,10 +1062,10 @@ static void
|
|||
print_man_nodelist(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_man_node(p, mt, n, m);
|
||||
print_man_node(p, mt, n, meta);
|
||||
if ( ! n->next)
|
||||
return;
|
||||
print_man_nodelist(p, mt, n->next, m);
|
||||
print_man_nodelist(p, mt, n->next, meta);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1016,6 +1105,7 @@ print_man_foot(struct termp *p, const void *arg)
|
|||
/* Bottom left corner: manual source. */
|
||||
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
p->offset = 0;
|
||||
p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
|
||||
|
||||
|
@ -1038,6 +1128,7 @@ print_man_foot(struct termp *p, const void *arg)
|
|||
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->trailspace = 0;
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin;
|
||||
|
||||
|
@ -1051,24 +1142,25 @@ print_man_head(struct termp *p, const void *arg)
|
|||
{
|
||||
char buf[BUFSIZ], title[BUFSIZ];
|
||||
size_t buflen, titlen;
|
||||
const struct man_meta *m;
|
||||
const struct man_meta *meta;
|
||||
|
||||
m = (const struct man_meta *)arg;
|
||||
assert(m->title);
|
||||
assert(m->msec);
|
||||
meta = (const struct man_meta *)arg;
|
||||
assert(meta->title);
|
||||
assert(meta->msec);
|
||||
|
||||
if (m->vol)
|
||||
strlcpy(buf, m->vol, BUFSIZ);
|
||||
if (meta->vol)
|
||||
strlcpy(buf, meta->vol, BUFSIZ);
|
||||
else
|
||||
buf[0] = '\0';
|
||||
buflen = term_strlen(p, buf);
|
||||
|
||||
/* Top left corner: manual title and section. */
|
||||
|
||||
snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
|
||||
snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
|
||||
titlen = term_strlen(p, title);
|
||||
|
||||
p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
|
||||
p->trailspace = 1;
|
||||
p->offset = 0;
|
||||
p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
|
||||
(p->maxrmargin -
|
||||
|
@ -1091,6 +1183,7 @@ print_man_head(struct termp *p, const void *arg)
|
|||
/* Top right corner: title and section, again. */
|
||||
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->trailspace = 0;
|
||||
if (p->rmargin + titlen <= p->maxrmargin) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->offset = p->rmargin;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* $Vendor-Id: mandoc.h,v 1.99 2012/02/16 20:51:31 joerg Exp $ */
|
||||
/* Id: mandoc.h,v 1.113 2014/01/02 16:29:55 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2013, 2014 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
|
||||
|
@ -50,6 +51,7 @@ enum mandocerr {
|
|||
MANDOCERR_NOTITLE, /* no title in document */
|
||||
MANDOCERR_UPPERCASE, /* document title should be all caps */
|
||||
MANDOCERR_BADMSEC, /* unknown manual section */
|
||||
MANDOCERR_BADVOLARCH, /* unknown manual volume or arch */
|
||||
MANDOCERR_NODATE, /* date missing, using today's date */
|
||||
MANDOCERR_BADDATE, /* cannot parse date, using it verbatim */
|
||||
MANDOCERR_PROLOGOOO, /* prologue macros out of order */
|
||||
|
@ -61,14 +63,14 @@ enum mandocerr {
|
|||
MANDOCERR_SO, /* .so is fragile, better use ln(1) */
|
||||
MANDOCERR_NAMESECFIRST, /* NAME section must come first */
|
||||
MANDOCERR_BADNAMESEC, /* bad NAME section contents */
|
||||
MANDOCERR_NONAME, /* manual name not yet set */
|
||||
MANDOCERR_SECOOO, /* sections out of conventional order */
|
||||
MANDOCERR_SECREP, /* duplicate section name */
|
||||
MANDOCERR_SECMSEC, /* section not in conventional manual section */
|
||||
MANDOCERR_SECMSEC, /* section header suited to sections ... */
|
||||
|
||||
/* related to macros and nesting */
|
||||
MANDOCERR_MACROOBS, /* skipping obsolete macro */
|
||||
MANDOCERR_IGNPAR, /* skipping paragraph macro */
|
||||
MANDOCERR_MOVEPAR, /* moving paragraph macro out of list */
|
||||
MANDOCERR_IGNNS, /* skipping no-space macro */
|
||||
MANDOCERR_SCOPENEST, /* blocks badly nested */
|
||||
MANDOCERR_CHILD, /* child violates parent syntax */
|
||||
|
@ -129,10 +131,12 @@ enum mandocerr {
|
|||
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
|
||||
MANDOCERR_BADCHAR, /* skipping bad character */
|
||||
MANDOCERR_NAMESC, /* escaped character not allowed in a name */
|
||||
MANDOCERR_NONAME, /* manual name not yet set */
|
||||
MANDOCERR_NOTEXT, /* skipping text before the first section header */
|
||||
MANDOCERR_MACRO, /* skipping unknown macro */
|
||||
MANDOCERR_REQUEST, /* NOT IMPLEMENTED: skipping request */
|
||||
MANDOCERR_ARGCOUNT, /* argument count wrong */
|
||||
MANDOCERR_STRAYTA, /* skipping column outside column list */
|
||||
MANDOCERR_NOSCOPE, /* skipping end of block that is not open */
|
||||
MANDOCERR_SCOPEBROKEN, /* missing end of block */
|
||||
MANDOCERR_SCOPEEXIT, /* scope open on exit */
|
||||
|
@ -141,12 +145,14 @@ enum mandocerr {
|
|||
MANDOCERR_NOARGS, /* macro requires line argument(s) */
|
||||
MANDOCERR_NOBODY, /* macro requires body argument(s) */
|
||||
MANDOCERR_NOARGV, /* macro requires argument(s) */
|
||||
MANDOCERR_NUMERIC, /* request requires a numeric argument */
|
||||
MANDOCERR_LISTTYPE, /* missing list type */
|
||||
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
|
||||
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
|
||||
|
||||
MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
|
||||
|
||||
MANDOCERR_TOOLARGE, /* input too large */
|
||||
MANDOCERR_NOTMANUAL, /* manual isn't really a manual */
|
||||
MANDOCERR_COLUMNS, /* column syntax is inconsistent */
|
||||
MANDOCERR_BADDISP, /* NOT IMPLEMENTED: .Bd -file */
|
||||
|
@ -157,10 +163,17 @@ enum mandocerr {
|
|||
MANDOCERR_NODOCBODY, /* no document body */
|
||||
MANDOCERR_NODOCPROLOG, /* no document prologue */
|
||||
MANDOCERR_MEM, /* static buffer exhausted */
|
||||
|
||||
/* ===== system errors ===== */
|
||||
|
||||
MANDOCERR_SYSOPEN, /* cannot open file */
|
||||
MANDOCERR_SYSSTAT, /* cannot stat file */
|
||||
MANDOCERR_SYSREAD, /* cannot read file */
|
||||
|
||||
MANDOCERR_MAX
|
||||
};
|
||||
|
||||
struct tbl {
|
||||
struct tbl_opts {
|
||||
char tab; /* cell-separator */
|
||||
char decimal; /* decimal point */
|
||||
int linesize;
|
||||
|
@ -175,20 +188,14 @@ struct tbl {
|
|||
int cols; /* number of columns */
|
||||
};
|
||||
|
||||
enum tbl_headt {
|
||||
TBL_HEAD_DATA, /* plug in data from tbl_dat */
|
||||
TBL_HEAD_VERT, /* vertical spacer */
|
||||
TBL_HEAD_DVERT /* double-vertical spacer */
|
||||
};
|
||||
|
||||
/*
|
||||
* The head of a table specifies all of its columns. When formatting a
|
||||
* tbl_span, iterate over these and plug in data from the tbl_span when
|
||||
* appropriate, using tbl_cell as a guide to placement.
|
||||
*/
|
||||
struct tbl_head {
|
||||
enum tbl_headt pos;
|
||||
int ident; /* 0 <= unique id < cols */
|
||||
int vert; /* width of preceding vertical line */
|
||||
struct tbl_head *next;
|
||||
struct tbl_head *prev;
|
||||
};
|
||||
|
@ -203,8 +210,6 @@ enum tbl_cellt {
|
|||
TBL_CELL_DOWN, /* ^ */
|
||||
TBL_CELL_HORIZ, /* _, - */
|
||||
TBL_CELL_DHORIZ, /* = */
|
||||
TBL_CELL_VERT, /* | */
|
||||
TBL_CELL_DVERT, /* || */
|
||||
TBL_CELL_MAX
|
||||
};
|
||||
|
||||
|
@ -213,6 +218,7 @@ enum tbl_cellt {
|
|||
*/
|
||||
struct tbl_cell {
|
||||
struct tbl_cell *next;
|
||||
int vert; /* width of preceding vertical line */
|
||||
enum tbl_cellt pos;
|
||||
size_t spacing;
|
||||
int flags;
|
||||
|
@ -266,7 +272,7 @@ enum tbl_spant {
|
|||
* A row of data in a table.
|
||||
*/
|
||||
struct tbl_span {
|
||||
struct tbl *tbl;
|
||||
struct tbl_opts *opts;
|
||||
struct tbl_head *head;
|
||||
struct tbl_row *layout; /* layout row */
|
||||
struct tbl_dat *first;
|
||||
|
@ -382,11 +388,13 @@ enum mandoc_esc {
|
|||
ESCAPE_FONT, /* a generic font mode */
|
||||
ESCAPE_FONTBOLD, /* bold font mode */
|
||||
ESCAPE_FONTITALIC, /* italic font mode */
|
||||
ESCAPE_FONTBI, /* bold italic font mode */
|
||||
ESCAPE_FONTROMAN, /* roman font mode */
|
||||
ESCAPE_FONTPREV, /* previous font mode */
|
||||
ESCAPE_NUMBERED, /* a numbered glyph */
|
||||
ESCAPE_UNICODE, /* a unicode codepoint */
|
||||
ESCAPE_NOSPACE /* suppress space if the last on a line */
|
||||
ESCAPE_NOSPACE, /* suppress space if the last on a line */
|
||||
ESCAPE_SKIPCHAR /* skip the next character */
|
||||
};
|
||||
|
||||
typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
|
||||
|
@ -413,8 +421,8 @@ int mchars_spec2cp(const struct mchars *,
|
|||
const char *, size_t);
|
||||
const char *mchars_spec2str(const struct mchars *,
|
||||
const char *, size_t, size_t *);
|
||||
struct mparse *mparse_alloc(enum mparset,
|
||||
enum mandoclevel, mandocmsg, void *);
|
||||
struct mparse *mparse_alloc(enum mparset, enum mandoclevel,
|
||||
mandocmsg, void *, char *);
|
||||
void mparse_free(struct mparse *);
|
||||
void mparse_keep(struct mparse *);
|
||||
enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/* $Vendor-Id: mandocdb.h,v 1.6 2012/03/23 02:52:33 kristaps Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MANDOCDB_H
|
||||
#define MANDOCDB_H
|
||||
|
||||
#define MANDOC_DB "mandocdb.db"
|
||||
#define MANDOC_IDX "mandocdb.index"
|
||||
|
||||
#define TYPE_An 0x0000000000000001ULL
|
||||
#define TYPE_Ar 0x0000000000000002ULL
|
||||
#define TYPE_At 0x0000000000000004ULL
|
||||
#define TYPE_Bsx 0x0000000000000008ULL
|
||||
#define TYPE_Bx 0x0000000000000010ULL
|
||||
#define TYPE_Cd 0x0000000000000020ULL
|
||||
#define TYPE_Cm 0x0000000000000040ULL
|
||||
#define TYPE_Dv 0x0000000000000080ULL
|
||||
#define TYPE_Dx 0x0000000000000100ULL
|
||||
#define TYPE_Em 0x0000000000000200ULL
|
||||
#define TYPE_Er 0x0000000000000400ULL
|
||||
#define TYPE_Ev 0x0000000000000800ULL
|
||||
#define TYPE_Fa 0x0000000000001000ULL
|
||||
#define TYPE_Fl 0x0000000000002000ULL
|
||||
#define TYPE_Fn 0x0000000000004000ULL
|
||||
#define TYPE_Ft 0x0000000000008000ULL
|
||||
#define TYPE_Fx 0x0000000000010000ULL
|
||||
#define TYPE_Ic 0x0000000000020000ULL
|
||||
#define TYPE_In 0x0000000000040000ULL
|
||||
#define TYPE_Lb 0x0000000000080000ULL
|
||||
#define TYPE_Li 0x0000000000100000ULL
|
||||
#define TYPE_Lk 0x0000000000200000ULL
|
||||
#define TYPE_Ms 0x0000000000400000ULL
|
||||
#define TYPE_Mt 0x0000000000800000ULL
|
||||
#define TYPE_Nd 0x0000000001000000ULL
|
||||
#define TYPE_Nm 0x0000000002000000ULL
|
||||
#define TYPE_Nx 0x0000000004000000ULL
|
||||
#define TYPE_Ox 0x0000000008000000ULL
|
||||
#define TYPE_Pa 0x0000000010000000ULL
|
||||
#define TYPE_Rs 0x0000000020000000ULL
|
||||
#define TYPE_Sh 0x0000000040000000ULL
|
||||
#define TYPE_Ss 0x0000000080000000ULL
|
||||
#define TYPE_St 0x0000000100000000ULL
|
||||
#define TYPE_Sy 0x0000000200000000ULL
|
||||
#define TYPE_Tn 0x0000000400000000ULL
|
||||
#define TYPE_Va 0x0000000800000000ULL
|
||||
#define TYPE_Vt 0x0000001000000000ULL
|
||||
#define TYPE_Xr 0x0000002000000000ULL
|
||||
|
||||
#endif /*!MANDOCDB_H */
|
|
@ -1,6 +1,7 @@
|
|||
/* $Vendor-Id: mdoc_argv.c,v 1.82 2012/03/23 05:50:24 kristaps Exp $ */
|
||||
/* Id: mdoc_argv.c,v 1.89 2013/12/25 00:50:05 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012 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
|
||||
|
@ -42,8 +43,7 @@ enum argsflag {
|
|||
enum argvflag {
|
||||
ARGV_NONE, /* no args to flag (e.g., -split) */
|
||||
ARGV_SINGLE, /* one arg to flag (e.g., -file xxx) */
|
||||
ARGV_MULTI, /* multiple args (e.g., -column xxx yyy) */
|
||||
ARGV_OPT_SINGLE /* optional arg (e.g., -offset [xxx]) */
|
||||
ARGV_MULTI /* multiple args (e.g., -column xxx yyy) */
|
||||
};
|
||||
|
||||
struct mdocarg {
|
||||
|
@ -57,8 +57,6 @@ static enum margserr args(struct mdoc *, int, int *,
|
|||
static int args_checkpunct(const char *, int);
|
||||
static int argv_multi(struct mdoc *, int,
|
||||
struct mdoc_argv *, int *, char *);
|
||||
static int argv_opt_single(struct mdoc *, int,
|
||||
struct mdoc_argv *, int *, char *);
|
||||
static int argv_single(struct mdoc *, int,
|
||||
struct mdoc_argv *, int *, char *);
|
||||
|
||||
|
@ -69,7 +67,7 @@ static const enum argvflag argvflags[MDOC_ARG_MAX] = {
|
|||
ARGV_NONE, /* MDOC_Unfilled */
|
||||
ARGV_NONE, /* MDOC_Literal */
|
||||
ARGV_SINGLE, /* MDOC_File */
|
||||
ARGV_OPT_SINGLE, /* MDOC_Offset */
|
||||
ARGV_SINGLE, /* MDOC_Offset */
|
||||
ARGV_NONE, /* MDOC_Bullet */
|
||||
ARGV_NONE, /* MDOC_Dash */
|
||||
ARGV_NONE, /* MDOC_Hyphen */
|
||||
|
@ -81,7 +79,7 @@ static const enum argvflag argvflags[MDOC_ARG_MAX] = {
|
|||
ARGV_NONE, /* MDOC_Ohang */
|
||||
ARGV_NONE, /* MDOC_Inset */
|
||||
ARGV_MULTI, /* MDOC_Column */
|
||||
ARGV_OPT_SINGLE, /* MDOC_Width */
|
||||
ARGV_SINGLE, /* MDOC_Width */
|
||||
ARGV_NONE, /* MDOC_Compact */
|
||||
ARGV_NONE, /* MDOC_Std */
|
||||
ARGV_NONE, /* MDOC_Filled */
|
||||
|
@ -146,7 +144,7 @@ static const enum mdocargt args_Bl[] = {
|
|||
};
|
||||
|
||||
static const struct mdocarg mdocargs[MDOC_MAX] = {
|
||||
{ ARGSFL_NONE, NULL }, /* Ap */
|
||||
{ ARGSFL_DELIM, NULL }, /* Ap */
|
||||
{ ARGSFL_NONE, NULL }, /* Dd */
|
||||
{ ARGSFL_NONE, NULL }, /* Dt */
|
||||
{ ARGSFL_NONE, NULL }, /* Os */
|
||||
|
@ -163,7 +161,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
{ ARGSFL_DELIM, NULL }, /* Ad */
|
||||
{ ARGSFL_DELIM, args_An }, /* An */
|
||||
{ ARGSFL_DELIM, NULL }, /* Ar */
|
||||
{ ARGSFL_NONE, NULL }, /* Cd */
|
||||
{ ARGSFL_DELIM, NULL }, /* Cd */
|
||||
{ ARGSFL_DELIM, NULL }, /* Cm */
|
||||
{ ARGSFL_DELIM, NULL }, /* Dv */
|
||||
{ ARGSFL_DELIM, NULL }, /* Er */
|
||||
|
@ -175,7 +173,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
{ ARGSFL_DELIM, NULL }, /* Fn */
|
||||
{ ARGSFL_DELIM, NULL }, /* Ft */
|
||||
{ ARGSFL_DELIM, NULL }, /* Ic */
|
||||
{ ARGSFL_NONE, NULL }, /* In */
|
||||
{ ARGSFL_DELIM, NULL }, /* In */
|
||||
{ ARGSFL_DELIM, NULL }, /* Li */
|
||||
{ ARGSFL_NONE, NULL }, /* Nd */
|
||||
{ ARGSFL_DELIM, NULL }, /* Nm */
|
||||
|
@ -243,7 +241,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
{ ARGSFL_DELIM, NULL }, /* Xc */
|
||||
{ ARGSFL_NONE, NULL }, /* Xo */
|
||||
{ ARGSFL_NONE, NULL }, /* Fo */
|
||||
{ ARGSFL_NONE, NULL }, /* Fc */
|
||||
{ ARGSFL_DELIM, NULL }, /* Fc */
|
||||
{ ARGSFL_NONE, NULL }, /* Oo */
|
||||
{ ARGSFL_DELIM, NULL }, /* Oc */
|
||||
{ ARGSFL_NONE, args_Bk }, /* Bk */
|
||||
|
@ -252,7 +250,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
{ ARGSFL_NONE, NULL }, /* Hf */
|
||||
{ ARGSFL_NONE, NULL }, /* Fr */
|
||||
{ ARGSFL_NONE, NULL }, /* Ud */
|
||||
{ ARGSFL_NONE, NULL }, /* Lb */
|
||||
{ ARGSFL_DELIM, NULL }, /* Lb */
|
||||
{ ARGSFL_NONE, NULL }, /* Lp */
|
||||
{ ARGSFL_DELIM, NULL }, /* Lk */
|
||||
{ ARGSFL_DELIM, NULL }, /* Mt */
|
||||
|
@ -262,7 +260,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
{ ARGSFL_NONE, NULL }, /* %C */
|
||||
{ ARGSFL_NONE, NULL }, /* Es */
|
||||
{ ARGSFL_NONE, NULL }, /* En */
|
||||
{ ARGSFL_NONE, NULL }, /* Dx */
|
||||
{ ARGSFL_DELIM, NULL }, /* Dx */
|
||||
{ ARGSFL_NONE, NULL }, /* %Q */
|
||||
{ ARGSFL_NONE, NULL }, /* br */
|
||||
{ ARGSFL_NONE, NULL }, /* sp */
|
||||
|
@ -277,7 +275,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
|||
* one mandatory value, an optional single value, or no value.
|
||||
*/
|
||||
enum margverr
|
||||
mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
|
||||
mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok,
|
||||
struct mdoc_arg **v, int *pos, char *buf)
|
||||
{
|
||||
char *p, sv;
|
||||
|
@ -344,15 +342,11 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
|
|||
|
||||
switch (argvflags[tmp.arg]) {
|
||||
case (ARGV_SINGLE):
|
||||
if ( ! argv_single(m, line, &tmp, pos, buf))
|
||||
if ( ! argv_single(mdoc, line, &tmp, pos, buf))
|
||||
return(ARGV_ERROR);
|
||||
break;
|
||||
case (ARGV_MULTI):
|
||||
if ( ! argv_multi(m, line, &tmp, pos, buf))
|
||||
return(ARGV_ERROR);
|
||||
break;
|
||||
case (ARGV_OPT_SINGLE):
|
||||
if ( ! argv_opt_single(m, line, &tmp, pos, buf))
|
||||
if ( ! argv_multi(mdoc, line, &tmp, pos, buf))
|
||||
return(ARGV_ERROR);
|
||||
break;
|
||||
case (ARGV_NONE):
|
||||
|
@ -413,14 +407,14 @@ argn_free(struct mdoc_arg *p, int iarg)
|
|||
}
|
||||
|
||||
enum margserr
|
||||
mdoc_zargs(struct mdoc *m, int line, int *pos, char *buf, char **v)
|
||||
mdoc_zargs(struct mdoc *mdoc, int line, int *pos, char *buf, char **v)
|
||||
{
|
||||
|
||||
return(args(m, line, pos, buf, ARGSFL_NONE, v));
|
||||
return(args(mdoc, line, pos, buf, ARGSFL_NONE, v));
|
||||
}
|
||||
|
||||
enum margserr
|
||||
mdoc_args(struct mdoc *m, int line, int *pos,
|
||||
mdoc_args(struct mdoc *mdoc, int line, int *pos,
|
||||
char *buf, enum mdoct tok, char **v)
|
||||
{
|
||||
enum argsflag fl;
|
||||
|
@ -429,7 +423,7 @@ mdoc_args(struct mdoc *m, int line, int *pos,
|
|||
fl = mdocargs[tok].flags;
|
||||
|
||||
if (MDOC_It != tok)
|
||||
return(args(m, line, pos, buf, fl, v));
|
||||
return(args(mdoc, line, pos, buf, fl, v));
|
||||
|
||||
/*
|
||||
* We know that we're in an `It', so it's reasonable to expect
|
||||
|
@ -438,18 +432,18 @@ mdoc_args(struct mdoc *m, int line, int *pos,
|
|||
* safe fall-back into the default behaviour.
|
||||
*/
|
||||
|
||||
for (n = m->last; n; n = n->parent)
|
||||
for (n = mdoc->last; n; n = n->parent)
|
||||
if (MDOC_Bl == n->tok)
|
||||
if (LIST_column == n->norm->Bl.type) {
|
||||
fl = ARGSFL_TABSEP;
|
||||
break;
|
||||
}
|
||||
|
||||
return(args(m, line, pos, buf, fl, v));
|
||||
return(args(mdoc, line, pos, buf, fl, v));
|
||||
}
|
||||
|
||||
static enum margserr
|
||||
args(struct mdoc *m, int line, int *pos,
|
||||
args(struct mdoc *mdoc, int line, int *pos,
|
||||
char *buf, enum argsflag fl, char **v)
|
||||
{
|
||||
char *p, *pp;
|
||||
|
@ -457,17 +451,17 @@ args(struct mdoc *m, int line, int *pos,
|
|||
enum margserr rc;
|
||||
|
||||
if ('\0' == buf[*pos]) {
|
||||
if (MDOC_PPHRASE & m->flags)
|
||||
if (MDOC_PPHRASE & mdoc->flags)
|
||||
return(ARGS_EOLN);
|
||||
/*
|
||||
* If we're not in a partial phrase and the flag for
|
||||
* being a phrase literal is still set, the punctuation
|
||||
* is unterminated.
|
||||
*/
|
||||
if (MDOC_PHRASELIT & m->flags)
|
||||
mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
|
||||
if (MDOC_PHRASELIT & mdoc->flags)
|
||||
mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE);
|
||||
|
||||
m->flags &= ~MDOC_PHRASELIT;
|
||||
mdoc->flags &= ~MDOC_PHRASELIT;
|
||||
return(ARGS_EOLN);
|
||||
}
|
||||
|
||||
|
@ -490,7 +484,7 @@ args(struct mdoc *m, int line, int *pos,
|
|||
pp = NULL;
|
||||
|
||||
/* Scan ahead to unescaped `Ta'. */
|
||||
if ( ! (MDOC_PHRASELIT & m->flags))
|
||||
if ( ! (MDOC_PHRASELIT & mdoc->flags))
|
||||
for (pp = *v; ; pp++) {
|
||||
if (NULL == (pp = strstr(pp, "Ta")))
|
||||
break;
|
||||
|
@ -524,7 +518,7 @@ args(struct mdoc *m, int line, int *pos,
|
|||
|
||||
/* Whitespace check for eoln case... */
|
||||
if ('\0' == *p && ' ' == *(p - 1))
|
||||
mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
|
||||
mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE);
|
||||
|
||||
*pos += (int)(p - *v);
|
||||
|
||||
|
@ -542,22 +536,22 @@ args(struct mdoc *m, int line, int *pos,
|
|||
/* Skip ahead. */ ;
|
||||
|
||||
return(rc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Process a quoted literal. A quote begins with a double-quote
|
||||
* and ends with a double-quote NOT preceded by a double-quote.
|
||||
* Null-terminate the literal in place.
|
||||
* NUL-terminate the literal in place.
|
||||
* Collapse pairs of quotes inside quoted literals.
|
||||
* Whitespace is NOT involved in literal termination.
|
||||
*/
|
||||
|
||||
if (MDOC_PHRASELIT & m->flags || '\"' == buf[*pos]) {
|
||||
if ( ! (MDOC_PHRASELIT & m->flags))
|
||||
if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) {
|
||||
if ( ! (MDOC_PHRASELIT & mdoc->flags))
|
||||
*v = &buf[++(*pos)];
|
||||
|
||||
if (MDOC_PPHRASE & m->flags)
|
||||
m->flags |= MDOC_PHRASELIT;
|
||||
if (MDOC_PPHRASE & mdoc->flags)
|
||||
mdoc->flags |= MDOC_PHRASELIT;
|
||||
|
||||
pairs = 0;
|
||||
for ( ; buf[*pos]; (*pos)++) {
|
||||
|
@ -577,13 +571,13 @@ args(struct mdoc *m, int line, int *pos,
|
|||
buf[*pos - pairs] = '\0';
|
||||
|
||||
if ('\0' == buf[*pos]) {
|
||||
if (MDOC_PPHRASE & m->flags)
|
||||
if (MDOC_PPHRASE & mdoc->flags)
|
||||
return(ARGS_QWORD);
|
||||
mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
|
||||
mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE);
|
||||
return(ARGS_QWORD);
|
||||
}
|
||||
|
||||
m->flags &= ~MDOC_PHRASELIT;
|
||||
mdoc->flags &= ~MDOC_PHRASELIT;
|
||||
buf[(*pos)++] = '\0';
|
||||
|
||||
if ('\0' == buf[*pos])
|
||||
|
@ -593,13 +587,13 @@ args(struct mdoc *m, int line, int *pos,
|
|||
(*pos)++;
|
||||
|
||||
if ('\0' == buf[*pos])
|
||||
mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
|
||||
mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE);
|
||||
|
||||
return(ARGS_QWORD);
|
||||
}
|
||||
|
||||
p = &buf[*pos];
|
||||
*v = mandoc_getarg(m->parse, &p, line, pos);
|
||||
*v = mandoc_getarg(mdoc->parse, &p, line, pos);
|
||||
|
||||
return(ARGS_WORD);
|
||||
}
|
||||
|
@ -655,7 +649,7 @@ args_checkpunct(const char *buf, int i)
|
|||
}
|
||||
|
||||
static int
|
||||
argv_multi(struct mdoc *m, int line,
|
||||
argv_multi(struct mdoc *mdoc, int line,
|
||||
struct mdoc_argv *v, int *pos, char *buf)
|
||||
{
|
||||
enum margserr ac;
|
||||
|
@ -664,7 +658,7 @@ argv_multi(struct mdoc *m, int line,
|
|||
for (v->sz = 0; ; v->sz++) {
|
||||
if ('-' == buf[*pos])
|
||||
break;
|
||||
ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
|
||||
ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
|
||||
if (ARGS_ERROR == ac)
|
||||
return(0);
|
||||
else if (ARGS_EOLN == ac)
|
||||
|
@ -681,16 +675,13 @@ argv_multi(struct mdoc *m, int line,
|
|||
}
|
||||
|
||||
static int
|
||||
argv_opt_single(struct mdoc *m, int line,
|
||||
argv_single(struct mdoc *mdoc, int line,
|
||||
struct mdoc_argv *v, int *pos, char *buf)
|
||||
{
|
||||
enum margserr ac;
|
||||
char *p;
|
||||
|
||||
if ('-' == buf[*pos])
|
||||
return(1);
|
||||
|
||||
ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
|
||||
ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
|
||||
if (ARGS_ERROR == ac)
|
||||
return(0);
|
||||
if (ARGS_EOLN == ac)
|
||||
|
@ -702,27 +693,3 @@ argv_opt_single(struct mdoc *m, int line,
|
|||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
argv_single(struct mdoc *m, int line,
|
||||
struct mdoc_argv *v, int *pos, char *buf)
|
||||
{
|
||||
int ppos;
|
||||
enum margserr ac;
|
||||
char *p;
|
||||
|
||||
ppos = *pos;
|
||||
|
||||
ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
|
||||
if (ARGS_EOLN == ac) {
|
||||
mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTARGVCOUNT);
|
||||
return(0);
|
||||
} else if (ARGS_ERROR == ac)
|
||||
return(0);
|
||||
|
||||
v->sz = 1;
|
||||
v->value = mandoc_malloc(sizeof(char *));
|
||||
v->value[0] = mandoc_strdup(p);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* $Vendor-Id: mdoc_term.c,v 1.238 2011/11/13 13:15:14 schwarze Exp $ */
|
||||
/* Id: mdoc_term.c,v 1.258 2013/12/25 21:24:12 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -41,8 +42,8 @@ struct termpair {
|
|||
|
||||
#define DECL_ARGS struct termp *p, \
|
||||
struct termpair *pair, \
|
||||
const struct mdoc_meta *m, \
|
||||
const struct mdoc_node *n
|
||||
const struct mdoc_meta *meta, \
|
||||
struct mdoc_node *n
|
||||
|
||||
struct termact {
|
||||
int (*pre)(DECL_ARGS);
|
||||
|
@ -69,7 +70,7 @@ static void termp_an_post(DECL_ARGS);
|
|||
static void termp_bd_post(DECL_ARGS);
|
||||
static void termp_bk_post(DECL_ARGS);
|
||||
static void termp_bl_post(DECL_ARGS);
|
||||
static void termp_d1_post(DECL_ARGS);
|
||||
static void termp_fd_post(DECL_ARGS);
|
||||
static void termp_fo_post(DECL_ARGS);
|
||||
static void termp_in_post(DECL_ARGS);
|
||||
static void termp_it_post(DECL_ARGS);
|
||||
|
@ -100,7 +101,6 @@ static int termp_fl_pre(DECL_ARGS);
|
|||
static int termp_fn_pre(DECL_ARGS);
|
||||
static int termp_fo_pre(DECL_ARGS);
|
||||
static int termp_ft_pre(DECL_ARGS);
|
||||
static int termp_igndelim_pre(DECL_ARGS);
|
||||
static int termp_in_pre(DECL_ARGS);
|
||||
static int termp_it_pre(DECL_ARGS);
|
||||
static int termp_li_pre(DECL_ARGS);
|
||||
|
@ -129,8 +129,8 @@ static const struct termact termacts[MDOC_MAX] = {
|
|||
{ termp_sh_pre, termp_sh_post }, /* Sh */
|
||||
{ termp_ss_pre, termp_ss_post }, /* Ss */
|
||||
{ termp_sp_pre, NULL }, /* Pp */
|
||||
{ termp_d1_pre, termp_d1_post }, /* D1 */
|
||||
{ termp_d1_pre, termp_d1_post }, /* Dl */
|
||||
{ termp_d1_pre, termp_bl_post }, /* D1 */
|
||||
{ termp_d1_pre, termp_bl_post }, /* Dl */
|
||||
{ termp_bd_pre, termp_bd_post }, /* Bd */
|
||||
{ NULL, NULL }, /* Ed */
|
||||
{ termp_bl_pre, termp_bl_post }, /* Bl */
|
||||
|
@ -146,7 +146,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
|||
{ NULL, NULL }, /* Ev */
|
||||
{ termp_ex_pre, NULL }, /* Ex */
|
||||
{ termp_fa_pre, NULL }, /* Fa */
|
||||
{ termp_fd_pre, NULL }, /* Fd */
|
||||
{ termp_fd_pre, termp_fd_post }, /* Fd */
|
||||
{ termp_fl_pre, NULL }, /* Fl */
|
||||
{ termp_fn_pre, NULL }, /* Fn */
|
||||
{ termp_ft_pre, NULL }, /* Ft */
|
||||
|
@ -194,12 +194,12 @@ static const struct termact termacts[MDOC_MAX] = {
|
|||
{ termp_quote_pre, termp_quote_post }, /* Eo */
|
||||
{ termp_xx_pre, NULL }, /* Fx */
|
||||
{ termp_bold_pre, NULL }, /* Ms */
|
||||
{ termp_igndelim_pre, NULL }, /* No */
|
||||
{ NULL, NULL }, /* No */
|
||||
{ termp_ns_pre, NULL }, /* Ns */
|
||||
{ termp_xx_pre, NULL }, /* Nx */
|
||||
{ termp_xx_pre, NULL }, /* Ox */
|
||||
{ NULL, NULL }, /* Pc */
|
||||
{ termp_igndelim_pre, termp_pf_post }, /* Pf */
|
||||
{ NULL, termp_pf_post }, /* Pf */
|
||||
{ termp_quote_pre, termp_quote_post }, /* Po */
|
||||
{ termp_quote_pre, termp_quote_post }, /* Pq */
|
||||
{ NULL, NULL }, /* Qc */
|
||||
|
@ -242,7 +242,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
|||
{ NULL, termp____post }, /* %Q */
|
||||
{ termp_sp_pre, NULL }, /* br */
|
||||
{ termp_sp_pre, NULL }, /* sp */
|
||||
{ termp_under_pre, termp____post }, /* %U */
|
||||
{ NULL, termp____post }, /* %U */
|
||||
{ NULL, NULL }, /* Ta */
|
||||
};
|
||||
|
||||
|
@ -251,7 +251,7 @@ void
|
|||
terminal_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
{
|
||||
const struct mdoc_node *n;
|
||||
const struct mdoc_meta *m;
|
||||
const struct mdoc_meta *meta;
|
||||
struct termp *p;
|
||||
|
||||
p = (struct termp *)arg;
|
||||
|
@ -267,12 +267,12 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc)
|
|||
p->symtab = mchars_alloc();
|
||||
|
||||
n = mdoc_node(mdoc);
|
||||
m = mdoc_meta(mdoc);
|
||||
meta = mdoc_meta(mdoc);
|
||||
|
||||
term_begin(p, print_mdoc_head, print_mdoc_foot, m);
|
||||
term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
|
||||
|
||||
if (n->child)
|
||||
print_mdoc_nodelist(p, NULL, m, n->child);
|
||||
print_mdoc_nodelist(p, NULL, meta, n->child);
|
||||
|
||||
term_end(p);
|
||||
}
|
||||
|
@ -282,9 +282,9 @@ static void
|
|||
print_mdoc_nodelist(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_mdoc_node(p, pair, m, n);
|
||||
print_mdoc_node(p, pair, meta, n);
|
||||
if (n->next)
|
||||
print_mdoc_nodelist(p, pair, m, n->next);
|
||||
print_mdoc_nodelist(p, pair, meta, n->next);
|
||||
}
|
||||
|
||||
|
||||
|
@ -293,14 +293,13 @@ static void
|
|||
print_mdoc_node(DECL_ARGS)
|
||||
{
|
||||
int chld;
|
||||
const void *font;
|
||||
struct termpair npair;
|
||||
size_t offset, rmargin;
|
||||
|
||||
chld = 1;
|
||||
offset = p->offset;
|
||||
rmargin = p->rmargin;
|
||||
font = term_fontq(p);
|
||||
n->prev_font = term_fontq(p);
|
||||
|
||||
memset(&npair, 0, sizeof(struct termpair));
|
||||
npair.ppair = pair;
|
||||
|
@ -308,33 +307,16 @@ print_mdoc_node(DECL_ARGS)
|
|||
/*
|
||||
* Keeps only work until the end of a line. If a keep was
|
||||
* invoked in a prior line, revert it to PREKEEP.
|
||||
*
|
||||
* Also let SYNPRETTY sections behave as if they were wrapped
|
||||
* in a `Bk' block.
|
||||
*/
|
||||
|
||||
if (TERMP_KEEP & p->flags || MDOC_SYNPRETTY & n->flags) {
|
||||
if (n->prev && n->prev->line != n->line) {
|
||||
if (TERMP_KEEP & p->flags) {
|
||||
if (n->prev ? (n->prev->lastline != n->line) :
|
||||
(n->parent && n->parent->line != n->line)) {
|
||||
p->flags &= ~TERMP_KEEP;
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
} else if (NULL == n->prev) {
|
||||
if (n->parent && n->parent->line != n->line) {
|
||||
p->flags &= ~TERMP_KEEP;
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Since SYNPRETTY sections aren't "turned off" with `Ek',
|
||||
* we have to intuit whether we should disable formatting.
|
||||
*/
|
||||
|
||||
if ( ! (MDOC_SYNPRETTY & n->flags) &&
|
||||
((n->prev && MDOC_SYNPRETTY & n->prev->flags) ||
|
||||
(n->parent && MDOC_SYNPRETTY & n->parent->flags)))
|
||||
p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
|
||||
|
||||
/*
|
||||
* After the keep flags have been set up, we may now
|
||||
* produce output. Note that some pre-handlers do so.
|
||||
|
@ -359,14 +341,15 @@ print_mdoc_node(DECL_ARGS)
|
|||
default:
|
||||
if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
|
||||
chld = (*termacts[n->tok].pre)
|
||||
(p, &npair, m, n);
|
||||
(p, &npair, meta, n);
|
||||
break;
|
||||
}
|
||||
|
||||
if (chld && n->child)
|
||||
print_mdoc_nodelist(p, &npair, m, n->child);
|
||||
print_mdoc_nodelist(p, &npair, meta, n->child);
|
||||
|
||||
term_fontpopq(p, font);
|
||||
term_fontpopq(p,
|
||||
(ENDBODY_NOT == n->end ? n : n->pending)->prev_font);
|
||||
|
||||
switch (n->type) {
|
||||
case (MDOC_TEXT):
|
||||
|
@ -378,7 +361,7 @@ print_mdoc_node(DECL_ARGS)
|
|||
default:
|
||||
if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
|
||||
break;
|
||||
(void)(*termacts[n->tok].post)(p, &npair, m, n);
|
||||
(void)(*termacts[n->tok].post)(p, &npair, meta, n);
|
||||
|
||||
/*
|
||||
* Explicit end tokens not only call the post
|
||||
|
@ -409,9 +392,9 @@ print_mdoc_node(DECL_ARGS)
|
|||
static void
|
||||
print_mdoc_foot(struct termp *p, const void *arg)
|
||||
{
|
||||
const struct mdoc_meta *m;
|
||||
const struct mdoc_meta *meta;
|
||||
|
||||
m = (const struct mdoc_meta *)arg;
|
||||
meta = (const struct mdoc_meta *)arg;
|
||||
|
||||
term_fontrepl(p, TERMFONT_NONE);
|
||||
|
||||
|
@ -427,25 +410,27 @@ print_mdoc_foot(struct termp *p, const void *arg)
|
|||
|
||||
p->offset = 0;
|
||||
p->rmargin = (p->maxrmargin -
|
||||
term_strlen(p, m->date) + term_len(p, 1)) / 2;
|
||||
term_strlen(p, meta->date) + term_len(p, 1)) / 2;
|
||||
p->trailspace = 1;
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
||||
|
||||
term_word(p, m->os);
|
||||
term_word(p, meta->os);
|
||||
term_flushln(p);
|
||||
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin - term_strlen(p, m->os);
|
||||
p->rmargin = p->maxrmargin - term_strlen(p, meta->os);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
term_word(p, m->date);
|
||||
term_word(p, meta->date);
|
||||
term_flushln(p);
|
||||
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin;
|
||||
p->trailspace = 0;
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
term_word(p, m->os);
|
||||
term_word(p, meta->os);
|
||||
term_flushln(p);
|
||||
|
||||
p->offset = 0;
|
||||
|
@ -459,9 +444,9 @@ print_mdoc_head(struct termp *p, const void *arg)
|
|||
{
|
||||
char buf[BUFSIZ], title[BUFSIZ];
|
||||
size_t buflen, titlen;
|
||||
const struct mdoc_meta *m;
|
||||
const struct mdoc_meta *meta;
|
||||
|
||||
m = (const struct mdoc_meta *)arg;
|
||||
meta = (const struct mdoc_meta *)arg;
|
||||
|
||||
/*
|
||||
* The header is strange. It has three components, which are
|
||||
|
@ -479,20 +464,21 @@ print_mdoc_head(struct termp *p, const void *arg)
|
|||
p->offset = 0;
|
||||
p->rmargin = p->maxrmargin;
|
||||
|
||||
assert(m->vol);
|
||||
strlcpy(buf, m->vol, BUFSIZ);
|
||||
assert(meta->vol);
|
||||
strlcpy(buf, meta->vol, BUFSIZ);
|
||||
buflen = term_strlen(p, buf);
|
||||
|
||||
if (m->arch) {
|
||||
if (meta->arch) {
|
||||
strlcat(buf, " (", BUFSIZ);
|
||||
strlcat(buf, m->arch, BUFSIZ);
|
||||
strlcat(buf, meta->arch, BUFSIZ);
|
||||
strlcat(buf, ")", BUFSIZ);
|
||||
}
|
||||
|
||||
snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
|
||||
snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
|
||||
titlen = term_strlen(p, title);
|
||||
|
||||
p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
|
||||
p->trailspace = 1;
|
||||
p->offset = 0;
|
||||
p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
|
||||
(p->maxrmargin -
|
||||
|
@ -511,6 +497,7 @@ print_mdoc_head(struct termp *p, const void *arg)
|
|||
term_flushln(p);
|
||||
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->trailspace = 0;
|
||||
if (p->rmargin + titlen <= p->maxrmargin) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->offset = p->rmargin;
|
||||
|
@ -727,12 +714,10 @@ termp_it_pre(DECL_ARGS)
|
|||
case (LIST_dash):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_hyphen):
|
||||
if (width < term_len(p, 4))
|
||||
width = term_len(p, 4);
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_enum):
|
||||
if (width < term_len(p, 5))
|
||||
width = term_len(p, 5);
|
||||
if (width < term_len(p, 2))
|
||||
width = term_len(p, 2);
|
||||
break;
|
||||
case (LIST_hang):
|
||||
if (0 == width)
|
||||
|
@ -787,20 +772,26 @@ termp_it_pre(DECL_ARGS)
|
|||
*/
|
||||
|
||||
switch (type) {
|
||||
case (LIST_enum):
|
||||
/*
|
||||
* Weird special case.
|
||||
* Very narrow enum lists actually hang.
|
||||
*/
|
||||
if (width == term_len(p, 2))
|
||||
p->flags |= TERMP_HANG;
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_bullet):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_dash):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_enum):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_hyphen):
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
if (MDOC_HEAD != n->type)
|
||||
break;
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
break;
|
||||
case (LIST_hang):
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
else
|
||||
if (MDOC_HEAD != n->type)
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -812,16 +803,18 @@ termp_it_pre(DECL_ARGS)
|
|||
if (n->next->child &&
|
||||
(MDOC_Bl == n->next->child->tok ||
|
||||
MDOC_Bd == n->next->child->tok))
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
else
|
||||
p->flags |= TERMP_HANG;
|
||||
break;
|
||||
|
||||
p->flags |= TERMP_NOBREAK | TERMP_HANG;
|
||||
p->trailspace = 1;
|
||||
break;
|
||||
case (LIST_tag):
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
|
||||
|
||||
if (MDOC_HEAD != n->type)
|
||||
break;
|
||||
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 2;
|
||||
|
||||
if (NULL == n->next || NULL == n->next->child)
|
||||
p->flags |= TERMP_DANGLE;
|
||||
break;
|
||||
|
@ -829,15 +822,20 @@ termp_it_pre(DECL_ARGS)
|
|||
if (MDOC_HEAD == n->type)
|
||||
break;
|
||||
|
||||
if (NULL == n->next)
|
||||
if (NULL == n->next) {
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
else
|
||||
p->trailspace = 0;
|
||||
} else {
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
case (LIST_diag):
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
if (MDOC_HEAD != n->type)
|
||||
break;
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -989,8 +987,8 @@ termp_it_post(DECL_ARGS)
|
|||
|
||||
p->flags &= ~TERMP_DANGLE;
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
p->flags &= ~TERMP_TWOSPACE;
|
||||
p->flags &= ~TERMP_HANG;
|
||||
p->trailspace = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -999,22 +997,25 @@ static int
|
|||
termp_nm_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_BLOCK == n->type)
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (MDOC_BODY == n->type) {
|
||||
if (NULL == n->child)
|
||||
return(0);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->offset += term_len(p, 1) +
|
||||
(NULL == n->prev->child ? term_strlen(p, m->name) :
|
||||
(NULL == n->prev->child ?
|
||||
term_strlen(p, meta->name) :
|
||||
MDOC_TEXT == n->prev->child->type ?
|
||||
term_strlen(p, n->prev->child->string) :
|
||||
term_strlen(p, n->prev->child->string) :
|
||||
term_len(p, 5));
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (NULL == n->child && NULL == m->name)
|
||||
if (NULL == n->child && NULL == meta->name)
|
||||
return(0);
|
||||
|
||||
if (MDOC_HEAD == n->type)
|
||||
|
@ -1022,9 +1023,10 @@ termp_nm_pre(DECL_ARGS)
|
|||
|
||||
if (MDOC_HEAD == n->type && n->next->child) {
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
p->rmargin = p->offset + term_len(p, 1);
|
||||
if (NULL == n->child) {
|
||||
p->rmargin += term_strlen(p, m->name);
|
||||
p->rmargin += term_strlen(p, meta->name);
|
||||
} else if (MDOC_TEXT == n->child->type) {
|
||||
p->rmargin += term_strlen(p, n->child->string);
|
||||
if (n->child->next)
|
||||
|
@ -1037,7 +1039,7 @@ termp_nm_pre(DECL_ARGS)
|
|||
|
||||
term_fontpush(p, TERMFONT_BOLD);
|
||||
if (NULL == n->child)
|
||||
term_word(p, m->name);
|
||||
term_word(p, meta->name);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -1047,9 +1049,12 @@ static void
|
|||
termp_nm_post(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_HEAD == n->type && n->next->child) {
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
|
||||
} else if (MDOC_HEAD == n->type && n->next->child) {
|
||||
term_flushln(p);
|
||||
p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
|
||||
p->trailspace = 0;
|
||||
} else if (MDOC_BODY == n->type && n->child)
|
||||
term_flushln(p);
|
||||
}
|
||||
|
@ -1375,14 +1380,14 @@ termp_vt_pre(DECL_ARGS)
|
|||
|
||||
if (MDOC_ELEM == n->type) {
|
||||
synopsis_pre(p, n);
|
||||
return(termp_under_pre(p, pair, m, n));
|
||||
return(termp_under_pre(p, pair, meta, n));
|
||||
} else if (MDOC_BLOCK == n->type) {
|
||||
synopsis_pre(p, n);
|
||||
return(1);
|
||||
} else if (MDOC_HEAD == n->type)
|
||||
return(0);
|
||||
|
||||
return(termp_under_pre(p, pair, m, n));
|
||||
return(termp_under_pre(p, pair, meta, n));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1402,7 +1407,16 @@ termp_fd_pre(DECL_ARGS)
|
|||
{
|
||||
|
||||
synopsis_pre(p, n);
|
||||
return(termp_bold_pre(p, pair, m, n));
|
||||
return(termp_bold_pre(p, pair, meta, n));
|
||||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
termp_fd_post(DECL_ARGS)
|
||||
{
|
||||
|
||||
term_newln(p);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1425,6 +1439,8 @@ termp_sh_pre(DECL_ARGS)
|
|||
break;
|
||||
case (MDOC_BODY):
|
||||
p->offset = term_len(p, p->defindent);
|
||||
if (SEC_AUTHORS == n->sec)
|
||||
p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1497,17 +1513,6 @@ termp_d1_pre(DECL_ARGS)
|
|||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
termp_d1_post(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_BLOCK != n->type)
|
||||
return;
|
||||
term_newln(p);
|
||||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
termp_ft_pre(DECL_ARGS)
|
||||
|
@ -1524,6 +1529,7 @@ termp_ft_pre(DECL_ARGS)
|
|||
static int
|
||||
termp_fn_pre(DECL_ARGS)
|
||||
{
|
||||
size_t rmargin = 0;
|
||||
int pretty;
|
||||
|
||||
pretty = MDOC_SYNPRETTY & n->flags;
|
||||
|
@ -1533,11 +1539,24 @@ termp_fn_pre(DECL_ARGS)
|
|||
if (NULL == (n = n->child))
|
||||
return(0);
|
||||
|
||||
if (pretty) {
|
||||
rmargin = p->rmargin;
|
||||
p->rmargin = p->offset + term_len(p, 4);
|
||||
p->flags |= TERMP_NOBREAK | TERMP_HANG;
|
||||
}
|
||||
|
||||
assert(MDOC_TEXT == n->type);
|
||||
term_fontpush(p, TERMFONT_BOLD);
|
||||
term_word(p, n->string);
|
||||
term_fontpop(p);
|
||||
|
||||
if (pretty) {
|
||||
term_flushln(p);
|
||||
p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = rmargin;
|
||||
}
|
||||
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "(");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
@ -1545,6 +1564,8 @@ termp_fn_pre(DECL_ARGS)
|
|||
for (n = n->next; n; n = n->next) {
|
||||
assert(MDOC_TEXT == n->type);
|
||||
term_fontpush(p, TERMFONT_UNDER);
|
||||
if (pretty)
|
||||
p->flags |= TERMP_NBRWORD;
|
||||
term_word(p, n->string);
|
||||
term_fontpop(p);
|
||||
|
||||
|
@ -1560,6 +1581,7 @@ termp_fn_pre(DECL_ARGS)
|
|||
if (pretty) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ";");
|
||||
term_flushln(p);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
@ -1579,20 +1601,16 @@ termp_fa_pre(DECL_ARGS)
|
|||
|
||||
for (nn = n->child; nn; nn = nn->next) {
|
||||
term_fontpush(p, TERMFONT_UNDER);
|
||||
p->flags |= TERMP_NBRWORD;
|
||||
term_word(p, nn->string);
|
||||
term_fontpop(p);
|
||||
|
||||
if (nn->next) {
|
||||
if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ",");
|
||||
}
|
||||
}
|
||||
|
||||
if (n->child && n->next && n->next->tok == MDOC_Fa) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ",");
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -1602,7 +1620,7 @@ static int
|
|||
termp_bd_pre(DECL_ARGS)
|
||||
{
|
||||
size_t tabwidth, rm, rmax;
|
||||
const struct mdoc_node *nn;
|
||||
struct mdoc_node *nn;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
print_bvspace(p, n, n);
|
||||
|
@ -1634,7 +1652,7 @@ termp_bd_pre(DECL_ARGS)
|
|||
p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
|
||||
|
||||
for (nn = n->child; nn; nn = nn->next) {
|
||||
print_mdoc_node(p, pair, m, nn);
|
||||
print_mdoc_node(p, pair, meta, nn);
|
||||
/*
|
||||
* If the printed node flushes its own line, then we
|
||||
* needn't do it here as well. This is hacky, but the
|
||||
|
@ -1751,7 +1769,8 @@ termp_xx_pre(DECL_ARGS)
|
|||
pp = "UNIX";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
term_word(p, pp);
|
||||
|
@ -1765,16 +1784,6 @@ termp_xx_pre(DECL_ARGS)
|
|||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
termp_igndelim_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
p->flags |= TERMP_IGNDELIM;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
termp_pf_post(DECL_ARGS)
|
||||
|
@ -1923,7 +1932,7 @@ termp_quote_pre(DECL_ARGS)
|
|||
case (MDOC_Do):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Dq):
|
||||
term_word(p, "``");
|
||||
term_word(p, "\\(lq");
|
||||
break;
|
||||
case (MDOC_Eo):
|
||||
break;
|
||||
|
@ -1944,7 +1953,7 @@ termp_quote_pre(DECL_ARGS)
|
|||
case (MDOC_So):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Sq):
|
||||
term_word(p, "`");
|
||||
term_word(p, "\\(oq");
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
|
@ -1989,7 +1998,7 @@ termp_quote_post(DECL_ARGS)
|
|||
case (MDOC_Do):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Dq):
|
||||
term_word(p, "''");
|
||||
term_word(p, "\\(rq");
|
||||
break;
|
||||
case (MDOC_Eo):
|
||||
break;
|
||||
|
@ -2010,7 +2019,7 @@ termp_quote_post(DECL_ARGS)
|
|||
case (MDOC_So):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Sq):
|
||||
term_word(p, "'");
|
||||
term_word(p, "\\(cq");
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
|
@ -2023,16 +2032,31 @@ termp_quote_post(DECL_ARGS)
|
|||
static int
|
||||
termp_fo_pre(DECL_ARGS)
|
||||
{
|
||||
size_t rmargin = 0;
|
||||
int pretty;
|
||||
|
||||
pretty = MDOC_SYNPRETTY & n->flags;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
synopsis_pre(p, n);
|
||||
return(1);
|
||||
} else if (MDOC_BODY == n->type) {
|
||||
if (pretty) {
|
||||
rmargin = p->rmargin;
|
||||
p->rmargin = p->offset + term_len(p, 4);
|
||||
p->flags |= TERMP_NOBREAK | TERMP_HANG;
|
||||
}
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "(");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
if (pretty) {
|
||||
term_flushln(p);
|
||||
p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = rmargin;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == n->child)
|
||||
return(0);
|
||||
|
@ -2060,6 +2084,7 @@ termp_fo_post(DECL_ARGS)
|
|||
if (MDOC_SYNPRETTY & n->flags) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ";");
|
||||
term_flushln(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2071,7 +2096,7 @@ termp_bf_pre(DECL_ARGS)
|
|||
|
||||
if (MDOC_HEAD == n->type)
|
||||
return(0);
|
||||
else if (MDOC_BLOCK != n->type)
|
||||
else if (MDOC_BODY != n->type)
|
||||
return(1);
|
||||
|
||||
if (FONT_Em == n->norm->Bf.font)
|
||||
|
@ -2157,25 +2182,24 @@ termp_li_pre(DECL_ARGS)
|
|||
static int
|
||||
termp_lk_pre(DECL_ARGS)
|
||||
{
|
||||
const struct mdoc_node *nn, *sv;
|
||||
const struct mdoc_node *link, *descr;
|
||||
|
||||
term_fontpush(p, TERMFONT_UNDER);
|
||||
if (NULL == (link = n->child))
|
||||
return(0);
|
||||
|
||||
nn = sv = n->child;
|
||||
|
||||
if (NULL == nn || NULL == nn->next)
|
||||
return(1);
|
||||
|
||||
for (nn = nn->next; nn; nn = nn->next)
|
||||
term_word(p, nn->string);
|
||||
|
||||
term_fontpop(p);
|
||||
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ":");
|
||||
if (NULL != (descr = link->next)) {
|
||||
term_fontpush(p, TERMFONT_UNDER);
|
||||
while (NULL != descr) {
|
||||
term_word(p, descr->string);
|
||||
descr = descr->next;
|
||||
}
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, ":");
|
||||
term_fontpop(p);
|
||||
}
|
||||
|
||||
term_fontpush(p, TERMFONT_BOLD);
|
||||
term_word(p, sv->string);
|
||||
term_word(p, link->string);
|
||||
term_fontpop(p);
|
||||
|
||||
return(0);
|
||||
|
@ -2225,9 +2249,9 @@ termp__t_post(DECL_ARGS)
|
|||
*/
|
||||
if (n->parent && MDOC_Rs == n->parent->tok &&
|
||||
n->parent->norm->Rs.quote_T)
|
||||
termp_quote_post(p, pair, m, n);
|
||||
termp_quote_post(p, pair, meta, n);
|
||||
|
||||
termp____post(p, pair, m, n);
|
||||
termp____post(p, pair, meta, n);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
|
@ -2241,7 +2265,7 @@ termp__t_pre(DECL_ARGS)
|
|||
*/
|
||||
if (n->parent && MDOC_Rs == n->parent->tok &&
|
||||
n->parent->norm->Rs.quote_T)
|
||||
return(termp_quote_pre(p, pair, m, n));
|
||||
return(termp_quote_pre(p, pair, meta, n));
|
||||
|
||||
term_fontpush(p, TERMFONT_UNDER);
|
||||
return(1);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Vendor-Id: mdoc_validate.c,v 1.182 2012/03/23 05:50:25 kristaps Exp $ */
|
||||
/* Id: mdoc_validate.c,v 1.198 2013/12/15 21:23:52 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 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
|
||||
|
@ -19,7 +19,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef OSNAME
|
||||
#ifndef OSNAME
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
|
@ -97,17 +97,19 @@ static int post_bl_block_width(POST_ARGS);
|
|||
static int post_bl_block_tag(POST_ARGS);
|
||||
static int post_bl_head(POST_ARGS);
|
||||
static int post_bx(POST_ARGS);
|
||||
static int post_defaults(POST_ARGS);
|
||||
static int post_dd(POST_ARGS);
|
||||
static int post_dt(POST_ARGS);
|
||||
static int post_defaults(POST_ARGS);
|
||||
static int post_literal(POST_ARGS);
|
||||
static int post_eoln(POST_ARGS);
|
||||
static int post_hyph(POST_ARGS);
|
||||
static int post_ignpar(POST_ARGS);
|
||||
static int post_it(POST_ARGS);
|
||||
static int post_lb(POST_ARGS);
|
||||
static int post_literal(POST_ARGS);
|
||||
static int post_nm(POST_ARGS);
|
||||
static int post_ns(POST_ARGS);
|
||||
static int post_os(POST_ARGS);
|
||||
static int post_ignpar(POST_ARGS);
|
||||
static int post_par(POST_ARGS);
|
||||
static int post_prol(POST_ARGS);
|
||||
static int post_root(POST_ARGS);
|
||||
static int post_rs(POST_ARGS);
|
||||
|
@ -141,27 +143,30 @@ static v_post posts_bx[] = { post_bx, NULL };
|
|||
static v_post posts_bool[] = { ebool, NULL };
|
||||
static v_post posts_eoln[] = { post_eoln, NULL };
|
||||
static v_post posts_defaults[] = { post_defaults, NULL };
|
||||
static v_post posts_d1[] = { bwarn_ge1, post_hyph, NULL };
|
||||
static v_post posts_dd[] = { post_dd, post_prol, NULL };
|
||||
static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL };
|
||||
static v_post posts_dt[] = { post_dt, post_prol, NULL };
|
||||
static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
|
||||
static v_post posts_hyph[] = { post_hyph, NULL };
|
||||
static v_post posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL };
|
||||
static v_post posts_it[] = { post_it, NULL };
|
||||
static v_post posts_lb[] = { post_lb, NULL };
|
||||
static v_post posts_nd[] = { berr_ge1, NULL };
|
||||
static v_post posts_nd[] = { berr_ge1, post_hyph, NULL };
|
||||
static v_post posts_nm[] = { post_nm, NULL };
|
||||
static v_post posts_notext[] = { ewarn_eq0, NULL };
|
||||
static v_post posts_ns[] = { post_ns, NULL };
|
||||
static v_post posts_os[] = { post_os, post_prol, NULL };
|
||||
static v_post posts_pp[] = { post_par, ewarn_eq0, NULL };
|
||||
static v_post posts_rs[] = { post_rs, NULL };
|
||||
static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
|
||||
static v_post posts_sp[] = { ewarn_le1, NULL };
|
||||
static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
|
||||
static v_post posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL };
|
||||
static v_post posts_sp[] = { post_par, ewarn_le1, NULL };
|
||||
static v_post posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL };
|
||||
static v_post posts_st[] = { post_st, NULL };
|
||||
static v_post posts_std[] = { post_std, NULL };
|
||||
static v_post posts_text[] = { ewarn_ge1, NULL };
|
||||
static v_post posts_text1[] = { ewarn_eq1, NULL };
|
||||
static v_post posts_vt[] = { post_vt, NULL };
|
||||
static v_post posts_wline[] = { bwarn_ge1, NULL };
|
||||
static v_pre pres_an[] = { pre_an, NULL };
|
||||
static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
|
||||
static v_pre pres_bl[] = { pre_bl, pre_par, NULL };
|
||||
|
@ -169,8 +174,6 @@ static v_pre pres_d1[] = { pre_display, NULL };
|
|||
static v_pre pres_dl[] = { pre_literal, pre_display, NULL };
|
||||
static v_pre pres_dd[] = { pre_dd, NULL };
|
||||
static v_pre pres_dt[] = { pre_dt, NULL };
|
||||
static v_pre pres_er[] = { NULL, NULL };
|
||||
static v_pre pres_fd[] = { NULL, NULL };
|
||||
static v_pre pres_it[] = { pre_it, pre_par, NULL };
|
||||
static v_pre pres_os[] = { pre_os, NULL };
|
||||
static v_pre pres_pp[] = { pre_par, NULL };
|
||||
|
@ -185,8 +188,8 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ pres_os, posts_os }, /* Os */
|
||||
{ pres_sh, posts_sh }, /* Sh */
|
||||
{ pres_ss, posts_ss }, /* Ss */
|
||||
{ pres_pp, posts_notext }, /* Pp */
|
||||
{ pres_d1, posts_wline }, /* D1 */
|
||||
{ pres_pp, posts_pp }, /* Pp */
|
||||
{ pres_d1, posts_d1 }, /* D1 */
|
||||
{ pres_dl, posts_dl }, /* Dl */
|
||||
{ pres_bd, posts_bd }, /* Bd */
|
||||
{ NULL, NULL }, /* Ed */
|
||||
|
@ -199,11 +202,11 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ NULL, NULL }, /* Cd */
|
||||
{ NULL, NULL }, /* Cm */
|
||||
{ NULL, NULL }, /* Dv */
|
||||
{ pres_er, NULL }, /* Er */
|
||||
{ NULL, NULL }, /* Er */
|
||||
{ NULL, NULL }, /* Ev */
|
||||
{ pres_std, posts_std }, /* Ex */
|
||||
{ NULL, NULL }, /* Fa */
|
||||
{ pres_fd, posts_text }, /* Fd */
|
||||
{ NULL, posts_text }, /* Fd */
|
||||
{ NULL, NULL }, /* Fl */
|
||||
{ NULL, NULL }, /* Fn */
|
||||
{ NULL, NULL }, /* Ft */
|
||||
|
@ -221,15 +224,15 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ NULL, posts_vt }, /* Vt */
|
||||
{ NULL, posts_text }, /* Xr */
|
||||
{ NULL, posts_text }, /* %A */
|
||||
{ NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */
|
||||
{ NULL, posts_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */
|
||||
{ NULL, posts_text }, /* %D */
|
||||
{ NULL, posts_text }, /* %I */
|
||||
{ NULL, posts_text }, /* %J */
|
||||
{ NULL, posts_text }, /* %N */
|
||||
{ NULL, posts_text }, /* %O */
|
||||
{ NULL, posts_hyphtext }, /* %N */
|
||||
{ NULL, posts_hyphtext }, /* %O */
|
||||
{ NULL, posts_text }, /* %P */
|
||||
{ NULL, posts_text }, /* %R */
|
||||
{ NULL, posts_text }, /* %T */ /* FIXME: can be used outside Rs/Re. */
|
||||
{ NULL, posts_hyphtext }, /* %R */
|
||||
{ NULL, posts_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */
|
||||
{ NULL, posts_text }, /* %V */
|
||||
{ NULL, NULL }, /* Ac */
|
||||
{ NULL, NULL }, /* Ao */
|
||||
|
@ -269,7 +272,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ NULL, NULL }, /* So */
|
||||
{ NULL, NULL }, /* Sq */
|
||||
{ NULL, posts_bool }, /* Sm */
|
||||
{ NULL, NULL }, /* Sx */
|
||||
{ NULL, posts_hyph }, /* Sx */
|
||||
{ NULL, NULL }, /* Sy */
|
||||
{ NULL, NULL }, /* Tn */
|
||||
{ NULL, NULL }, /* Ux */
|
||||
|
@ -286,7 +289,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ NULL, NULL }, /* Fr */
|
||||
{ NULL, posts_eoln }, /* Ud */
|
||||
{ NULL, posts_lb }, /* Lb */
|
||||
{ NULL, posts_notext }, /* Lp */
|
||||
{ pres_pp, posts_pp }, /* Lp */
|
||||
{ NULL, NULL }, /* Lk */
|
||||
{ NULL, posts_defaults }, /* Mt */
|
||||
{ NULL, NULL }, /* Brq */
|
||||
|
@ -297,8 +300,8 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
|
|||
{ NULL, NULL }, /* En */
|
||||
{ NULL, NULL }, /* Dx */
|
||||
{ NULL, posts_text }, /* %Q */
|
||||
{ NULL, posts_notext }, /* br */
|
||||
{ pres_pp, posts_sp }, /* sp */
|
||||
{ NULL, posts_pp }, /* br */
|
||||
{ NULL, posts_sp }, /* sp */
|
||||
{ NULL, posts_text1 }, /* %U */
|
||||
{ NULL, NULL }, /* Ta */
|
||||
};
|
||||
|
@ -314,12 +317,12 @@ static const enum mdoct rsord[RSORD_MAX] = {
|
|||
MDOC__R,
|
||||
MDOC__N,
|
||||
MDOC__V,
|
||||
MDOC__U,
|
||||
MDOC__P,
|
||||
MDOC__Q,
|
||||
MDOC__D,
|
||||
MDOC__O,
|
||||
MDOC__C,
|
||||
MDOC__U
|
||||
MDOC__D,
|
||||
MDOC__O
|
||||
};
|
||||
|
||||
static const char * const secnames[SEC__MAX] = {
|
||||
|
@ -414,29 +417,29 @@ mdoc_valid_post(struct mdoc *mdoc)
|
|||
}
|
||||
|
||||
static int
|
||||
check_count(struct mdoc *m, enum mdoc_type type,
|
||||
check_count(struct mdoc *mdoc, enum mdoc_type type,
|
||||
enum check_lvl lvl, enum check_ineq ineq, int val)
|
||||
{
|
||||
const char *p;
|
||||
enum mandocerr t;
|
||||
|
||||
if (m->last->type != type)
|
||||
if (mdoc->last->type != type)
|
||||
return(1);
|
||||
|
||||
switch (ineq) {
|
||||
case (CHECK_LT):
|
||||
p = "less than ";
|
||||
if (m->last->nchild < val)
|
||||
if (mdoc->last->nchild < val)
|
||||
return(1);
|
||||
break;
|
||||
case (CHECK_GT):
|
||||
p = "more than ";
|
||||
if (m->last->nchild > val)
|
||||
if (mdoc->last->nchild > val)
|
||||
return(1);
|
||||
break;
|
||||
case (CHECK_EQ):
|
||||
p = "";
|
||||
if (val == m->last->nchild)
|
||||
if (val == mdoc->last->nchild)
|
||||
return(1);
|
||||
break;
|
||||
default:
|
||||
|
@ -445,9 +448,9 @@ check_count(struct mdoc *m, enum mdoc_type type,
|
|||
}
|
||||
|
||||
t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
|
||||
mandoc_vmsg(t, m->parse, m->last->line, m->last->pos,
|
||||
mandoc_vmsg(t, mdoc->parse, mdoc->last->line, mdoc->last->pos,
|
||||
"want %s%d children (have %d)",
|
||||
p, val, m->last->nchild);
|
||||
p, val, mdoc->last->nchild);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -513,7 +516,7 @@ hwarn_le1(POST_ARGS)
|
|||
}
|
||||
|
||||
static void
|
||||
check_args(struct mdoc *m, struct mdoc_node *n)
|
||||
check_args(struct mdoc *mdoc, struct mdoc_node *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -522,34 +525,34 @@ check_args(struct mdoc *m, struct mdoc_node *n)
|
|||
|
||||
assert(n->args->argc);
|
||||
for (i = 0; i < (int)n->args->argc; i++)
|
||||
check_argv(m, n, &n->args->argv[i]);
|
||||
check_argv(mdoc, n, &n->args->argv[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
|
||||
check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)v->sz; i++)
|
||||
check_text(m, v->line, v->pos, v->value[i]);
|
||||
check_text(mdoc, v->line, v->pos, v->value[i]);
|
||||
|
||||
/* FIXME: move to post_std(). */
|
||||
|
||||
if (MDOC_Std == v->arg)
|
||||
if ( ! (v->sz || m->meta.name))
|
||||
mdoc_nmsg(m, n, MANDOCERR_NONAME);
|
||||
if ( ! (v->sz || mdoc->meta.name))
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_NONAME);
|
||||
}
|
||||
|
||||
static void
|
||||
check_text(struct mdoc *m, int ln, int pos, char *p)
|
||||
check_text(struct mdoc *mdoc, int ln, int pos, char *p)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (MDOC_LITERAL & m->flags)
|
||||
if (MDOC_LITERAL & mdoc->flags)
|
||||
return;
|
||||
|
||||
for (cp = p; NULL != (p = strchr(p, '\t')); p++)
|
||||
mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
|
||||
mdoc_pmsg(mdoc, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -733,14 +736,14 @@ pre_bl(PRE_ARGS)
|
|||
/*
|
||||
* Validate the width field. Some list types don't need width
|
||||
* types and should be warned about them. Others should have it
|
||||
* and must also be warned.
|
||||
* and must also be warned. Yet others have a default and need
|
||||
* no warning.
|
||||
*/
|
||||
|
||||
switch (n->norm->Bl.type) {
|
||||
case (LIST_tag):
|
||||
if (n->norm->Bl.width)
|
||||
break;
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
|
||||
if (NULL == n->norm->Bl.width)
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
|
||||
break;
|
||||
case (LIST_column):
|
||||
/* FALLTHROUGH */
|
||||
|
@ -754,6 +757,18 @@ pre_bl(PRE_ARGS)
|
|||
if (n->norm->Bl.width)
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
|
||||
break;
|
||||
case (LIST_bullet):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_dash):
|
||||
/* FALLTHROUGH */
|
||||
case (LIST_hyphen):
|
||||
if (NULL == n->norm->Bl.width)
|
||||
n->norm->Bl.width = "2n";
|
||||
break;
|
||||
case (LIST_enum):
|
||||
if (NULL == n->norm->Bl.width)
|
||||
n->norm->Bl.width = "3n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -874,8 +889,6 @@ pre_sh(PRE_ARGS)
|
|||
|
||||
if (MDOC_BLOCK != n->type)
|
||||
return(1);
|
||||
|
||||
roff_regunset(mdoc->roff, REG_nS);
|
||||
return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
|
||||
}
|
||||
|
||||
|
@ -1111,24 +1124,29 @@ post_nm(POST_ARGS)
|
|||
char buf[BUFSIZ];
|
||||
int c;
|
||||
|
||||
/* If no child specified, make sure we have the meta name. */
|
||||
|
||||
if (NULL == mdoc->last->child && NULL == mdoc->meta.name) {
|
||||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
|
||||
return(1);
|
||||
} else if (mdoc->meta.name)
|
||||
if (NULL != mdoc->meta.name)
|
||||
return(1);
|
||||
|
||||
/* If no meta name, set it from the child. */
|
||||
/* Try to use our children for setting the meta name. */
|
||||
|
||||
buf[0] = '\0';
|
||||
if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
|
||||
if (NULL != mdoc->last->child) {
|
||||
buf[0] = '\0';
|
||||
c = concat(buf, mdoc->last->child, BUFSIZ);
|
||||
} else
|
||||
c = 0;
|
||||
|
||||
switch (c) {
|
||||
case (-1):
|
||||
mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
|
||||
return(0);
|
||||
case (0):
|
||||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
|
||||
mdoc->meta.name = mandoc_strdup("UNKNOWN");
|
||||
break;
|
||||
default:
|
||||
mdoc->meta.name = mandoc_strdup(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(c);
|
||||
mdoc->meta.name = mandoc_strdup(buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -1334,7 +1352,7 @@ post_it(POST_ARGS)
|
|||
static int
|
||||
post_bl_block(POST_ARGS)
|
||||
{
|
||||
struct mdoc_node *n;
|
||||
struct mdoc_node *n, *ni, *nc;
|
||||
|
||||
/*
|
||||
* These are fairly complicated, so we've broken them into two
|
||||
|
@ -1350,13 +1368,42 @@ post_bl_block(POST_ARGS)
|
|||
NULL == n->norm->Bl.width) {
|
||||
if ( ! post_bl_block_tag(mdoc))
|
||||
return(0);
|
||||
assert(n->norm->Bl.width);
|
||||
} else if (NULL != n->norm->Bl.width) {
|
||||
if ( ! post_bl_block_width(mdoc))
|
||||
return(0);
|
||||
} else
|
||||
return(1);
|
||||
assert(n->norm->Bl.width);
|
||||
}
|
||||
|
||||
assert(n->norm->Bl.width);
|
||||
for (ni = n->body->child; ni; ni = ni->next) {
|
||||
if (NULL == ni->body)
|
||||
continue;
|
||||
nc = ni->body->last;
|
||||
while (NULL != nc) {
|
||||
switch (nc->tok) {
|
||||
case (MDOC_Pp):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Lp):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_br):
|
||||
break;
|
||||
default:
|
||||
nc = NULL;
|
||||
continue;
|
||||
}
|
||||
if (NULL == ni->next) {
|
||||
mdoc_nmsg(mdoc, nc, MANDOCERR_MOVEPAR);
|
||||
if ( ! mdoc_node_relink(mdoc, nc))
|
||||
return(0);
|
||||
} else if (0 == n->norm->Bl.comp &&
|
||||
LIST_column != n->norm->Bl.type) {
|
||||
mdoc_nmsg(mdoc, nc, MANDOCERR_IGNPAR);
|
||||
mdoc_node_delete(mdoc, nc);
|
||||
} else
|
||||
break;
|
||||
nc = ni->body->last;
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -1544,32 +1591,71 @@ post_bl_head(POST_ARGS)
|
|||
static int
|
||||
post_bl(POST_ARGS)
|
||||
{
|
||||
struct mdoc_node *n;
|
||||
struct mdoc_node *nparent, *nprev; /* of the Bl block */
|
||||
struct mdoc_node *nblock, *nbody; /* of the Bl */
|
||||
struct mdoc_node *nchild, *nnext; /* of the Bl body */
|
||||
|
||||
if (MDOC_HEAD == mdoc->last->type)
|
||||
return(post_bl_head(mdoc));
|
||||
if (MDOC_BLOCK == mdoc->last->type)
|
||||
nbody = mdoc->last;
|
||||
switch (nbody->type) {
|
||||
case (MDOC_BLOCK):
|
||||
return(post_bl_block(mdoc));
|
||||
if (MDOC_BODY != mdoc->last->type)
|
||||
case (MDOC_HEAD):
|
||||
return(post_bl_head(mdoc));
|
||||
case (MDOC_BODY):
|
||||
break;
|
||||
default:
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (n = mdoc->last->child; n; n = n->next) {
|
||||
switch (n->tok) {
|
||||
case (MDOC_Lp):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Pp):
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_It):
|
||||
/* FALLTHROUGH */
|
||||
case (MDOC_Sm):
|
||||
nchild = nbody->child;
|
||||
while (NULL != nchild) {
|
||||
if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
|
||||
nchild = nchild->next;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
|
||||
return(0);
|
||||
mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
|
||||
|
||||
/*
|
||||
* Move the node out of the Bl block.
|
||||
* First, collect all required node pointers.
|
||||
*/
|
||||
|
||||
nblock = nbody->parent;
|
||||
nprev = nblock->prev;
|
||||
nparent = nblock->parent;
|
||||
nnext = nchild->next;
|
||||
|
||||
/*
|
||||
* Unlink this child.
|
||||
*/
|
||||
|
||||
assert(NULL == nchild->prev);
|
||||
if (0 == --nbody->nchild) {
|
||||
nbody->child = NULL;
|
||||
nbody->last = NULL;
|
||||
assert(NULL == nnext);
|
||||
} else {
|
||||
nbody->child = nnext;
|
||||
nnext->prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Relink this child.
|
||||
*/
|
||||
|
||||
nchild->parent = nparent;
|
||||
nchild->prev = nprev;
|
||||
nchild->next = nblock;
|
||||
|
||||
nblock->prev = nchild;
|
||||
nparent->nchild++;
|
||||
if (NULL == nprev)
|
||||
nparent->child = nchild;
|
||||
else
|
||||
nprev->next = nchild;
|
||||
|
||||
nchild = nnext;
|
||||
}
|
||||
|
||||
return(1);
|
||||
|
@ -1588,10 +1674,16 @@ ebool(struct mdoc *mdoc)
|
|||
|
||||
assert(MDOC_TEXT == mdoc->last->child->type);
|
||||
|
||||
if (0 == strcmp(mdoc->last->child->string, "on"))
|
||||
if (0 == strcmp(mdoc->last->child->string, "on")) {
|
||||
if (MDOC_Sm == mdoc->last->tok)
|
||||
mdoc->flags &= ~MDOC_SMOFF;
|
||||
return(1);
|
||||
if (0 == strcmp(mdoc->last->child->string, "off"))
|
||||
}
|
||||
if (0 == strcmp(mdoc->last->child->string, "off")) {
|
||||
if (MDOC_Sm == mdoc->last->tok)
|
||||
mdoc->flags |= MDOC_SMOFF;
|
||||
return(1);
|
||||
}
|
||||
|
||||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
|
||||
return(1);
|
||||
|
@ -1771,6 +1863,47 @@ post_rs(POST_ARGS)
|
|||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* For some arguments of some macros,
|
||||
* convert all breakable hyphens into ASCII_HYPH.
|
||||
*/
|
||||
static int
|
||||
post_hyph(POST_ARGS)
|
||||
{
|
||||
struct mdoc_node *n, *nch;
|
||||
char *cp;
|
||||
|
||||
n = mdoc->last;
|
||||
switch (n->type) {
|
||||
case (MDOC_HEAD):
|
||||
if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
|
||||
break;
|
||||
return(1);
|
||||
case (MDOC_BODY):
|
||||
if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
|
||||
break;
|
||||
return(1);
|
||||
case (MDOC_ELEM):
|
||||
break;
|
||||
default:
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (nch = n->child; nch; nch = nch->next) {
|
||||
if (MDOC_TEXT != nch->type)
|
||||
continue;
|
||||
cp = nch->string;
|
||||
if (3 > strnlen(cp, 3))
|
||||
continue;
|
||||
while ('\0' != *(++cp))
|
||||
if ('-' == *cp &&
|
||||
isalpha((unsigned char)cp[-1]) &&
|
||||
isalpha((unsigned char)cp[1]))
|
||||
*cp = ASCII_HYPH;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
post_ns(POST_ARGS)
|
||||
{
|
||||
|
@ -1857,10 +1990,13 @@ post_sh_head(POST_ARGS)
|
|||
|
||||
/* The SYNOPSIS gets special attention in other areas. */
|
||||
|
||||
if (SEC_SYNOPSIS == sec)
|
||||
if (SEC_SYNOPSIS == sec) {
|
||||
roff_setreg(mdoc->roff, "nS", 1, '=');
|
||||
mdoc->flags |= MDOC_SYNOPSIS;
|
||||
else
|
||||
} else {
|
||||
roff_setreg(mdoc->roff, "nS", 0, '=');
|
||||
mdoc->flags &= ~MDOC_SYNOPSIS;
|
||||
}
|
||||
|
||||
/* Mark our last section. */
|
||||
|
||||
|
@ -1916,7 +2052,8 @@ post_sh_head(POST_ARGS)
|
|||
break;
|
||||
if (*mdoc->meta.msec == '9')
|
||||
break;
|
||||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC);
|
||||
mandoc_msg(MANDOCERR_SECMSEC, mdoc->parse,
|
||||
mdoc->last->line, mdoc->last->pos, buf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1962,7 +2099,9 @@ pre_par(PRE_ARGS)
|
|||
* block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
|
||||
*/
|
||||
|
||||
if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok)
|
||||
if (MDOC_Pp != mdoc->last->tok &&
|
||||
MDOC_Lp != mdoc->last->tok &&
|
||||
MDOC_br != mdoc->last->tok)
|
||||
return(1);
|
||||
if (MDOC_Bl == n->tok && n->norm->Bl.comp)
|
||||
return(1);
|
||||
|
@ -1976,6 +2115,32 @@ pre_par(PRE_ARGS)
|
|||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
post_par(POST_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_ELEM != mdoc->last->type &&
|
||||
MDOC_BLOCK != mdoc->last->type)
|
||||
return(1);
|
||||
|
||||
if (NULL == mdoc->last->prev) {
|
||||
if (MDOC_Sh != mdoc->last->parent->tok &&
|
||||
MDOC_Ss != mdoc->last->parent->tok)
|
||||
return(1);
|
||||
} else {
|
||||
if (MDOC_Pp != mdoc->last->prev->tok &&
|
||||
MDOC_Lp != mdoc->last->prev->tok &&
|
||||
(MDOC_br != mdoc->last->tok ||
|
||||
(MDOC_sp != mdoc->last->prev->tok &&
|
||||
MDOC_br != mdoc->last->prev->tok)))
|
||||
return(1);
|
||||
}
|
||||
|
||||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
|
||||
mdoc_node_delete(mdoc, mdoc->last);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_literal(PRE_ARGS)
|
||||
{
|
||||
|
@ -2129,9 +2294,9 @@ post_dt(POST_ARGS)
|
|||
free(mdoc->meta.vol);
|
||||
mdoc->meta.vol = mandoc_strdup(cp);
|
||||
} else {
|
||||
/* FIXME: warn about bad arch. */
|
||||
cp = mdoc_a2arch(nn->string);
|
||||
if (NULL == cp) {
|
||||
mdoc_nmsg(mdoc, nn, MANDOCERR_BADVOLARCH);
|
||||
free(mdoc->meta.vol);
|
||||
mdoc->meta.vol = mandoc_strdup(nn->string);
|
||||
} else
|
||||
|
@ -2192,14 +2357,15 @@ post_os(POST_ARGS)
|
|||
n = mdoc->last;
|
||||
|
||||
/*
|
||||
* Set the operating system by way of the `Os' macro. Note that
|
||||
* if an argument isn't provided and -DOSNAME="\"foo\"" is
|
||||
* provided during compilation, this value will be used instead
|
||||
* of filling in "sysname release" from uname().
|
||||
* Set the operating system by way of the `Os' macro.
|
||||
* The order of precedence is:
|
||||
* 1. the argument of the `Os' macro, unless empty
|
||||
* 2. the -Ios=foo command line argument, if provided
|
||||
* 3. -DOSNAME="\"foo\"", if provided during compilation
|
||||
* 4. "sysname release" from uname(3)
|
||||
*/
|
||||
|
||||
if (mdoc->meta.os)
|
||||
free(mdoc->meta.os);
|
||||
free(mdoc->meta.os);
|
||||
|
||||
buf[0] = '\0';
|
||||
if (-1 == (c = concat(buf, n->child, BUFSIZ))) {
|
||||
|
@ -2209,11 +2375,11 @@ post_os(POST_ARGS)
|
|||
|
||||
assert(c);
|
||||
|
||||
/* XXX: yes, these can all be dynamically-adjusted buffers, but
|
||||
* it's really not worth the extra hackery.
|
||||
*/
|
||||
|
||||
if ('\0' == buf[0]) {
|
||||
if (mdoc->defos) {
|
||||
mdoc->meta.os = mandoc_strdup(mdoc->defos);
|
||||
return(1);
|
||||
}
|
||||
#ifdef OSNAME
|
||||
if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ) {
|
||||
mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: msec.in,v 1.6 2010/06/19 20:46:28 kristaps Exp $ */
|
||||
/* Id: msec.in,v 1.6 2010/06/19 20:46:28 kristaps Exp */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Vendor-Id: read.c,v 1.28 2012/02/16 20:51:31 joerg Exp $ */
|
||||
/* Id: read.c,v 1.40 2014/01/02 16:29:55 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2014 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
@ -40,10 +41,6 @@
|
|||
#include "man.h"
|
||||
#include "main.h"
|
||||
|
||||
#ifndef MAP_FILE
|
||||
#define MAP_FILE 0
|
||||
#endif
|
||||
|
||||
#define REPARSE_LIMIT 1000
|
||||
|
||||
struct buf {
|
||||
|
@ -66,14 +63,17 @@ struct mparse {
|
|||
void *arg; /* argument to mmsg */
|
||||
const char *file;
|
||||
struct buf *secondary;
|
||||
char *defos; /* default operating system */
|
||||
};
|
||||
|
||||
static void resize_buf(struct buf *, size_t);
|
||||
static void mparse_buf_r(struct mparse *, struct buf, int);
|
||||
static void mparse_readfd_r(struct mparse *, int, const char *, int);
|
||||
static void pset(const char *, int, struct mparse *);
|
||||
static int read_whole_file(const char *, int, struct buf *, int *);
|
||||
static int read_whole_file(struct mparse *, const char *, int,
|
||||
struct buf *, int *);
|
||||
static void mparse_end(struct mparse *);
|
||||
static void mparse_parse_buffer(struct mparse *, struct buf,
|
||||
const char *);
|
||||
|
||||
static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
|
||||
MANDOCERR_OK,
|
||||
|
@ -94,6 +94,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|||
"no title in document",
|
||||
"document title should be all caps",
|
||||
"unknown manual section",
|
||||
"unknown manual volume or arch",
|
||||
"date missing, using today's date",
|
||||
"cannot parse date, using it verbatim",
|
||||
"prologue macros out of order",
|
||||
|
@ -105,14 +106,14 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|||
".so is fragile, better use ln(1)",
|
||||
"NAME section must come first",
|
||||
"bad NAME section contents",
|
||||
"manual name not yet set",
|
||||
"sections out of conventional order",
|
||||
"duplicate section name",
|
||||
"section not in conventional manual section",
|
||||
"section header suited to sections 2, 3, and 9 only",
|
||||
|
||||
/* related to macros and nesting */
|
||||
"skipping obsolete macro",
|
||||
"skipping paragraph macro",
|
||||
"moving paragraph macro out of list",
|
||||
"skipping no-space macro",
|
||||
"blocks badly nested",
|
||||
"child violates parent syntax",
|
||||
|
@ -173,10 +174,12 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|||
"input stack limit exceeded, infinite loop?",
|
||||
"skipping bad character",
|
||||
"escaped character not allowed in a name",
|
||||
"manual name not yet set",
|
||||
"skipping text before the first section header",
|
||||
"skipping unknown macro",
|
||||
"NOT IMPLEMENTED, please use groff: skipping request",
|
||||
"argument count wrong",
|
||||
"skipping column outside column list",
|
||||
"skipping end of block that is not open",
|
||||
"missing end of block",
|
||||
"scope open on exit",
|
||||
|
@ -184,12 +187,14 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|||
"macro requires line argument(s)",
|
||||
"macro requires body argument(s)",
|
||||
"macro requires argument(s)",
|
||||
"request requires a numeric argument",
|
||||
"missing list type",
|
||||
"line argument(s) will be lost",
|
||||
"body argument(s) will be lost",
|
||||
|
||||
"generic fatal error",
|
||||
|
||||
"input too large",
|
||||
"not a manual",
|
||||
"column syntax is inconsistent",
|
||||
"NOT IMPLEMENTED: .Bd -file",
|
||||
|
@ -200,6 +205,11 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|||
"no document body",
|
||||
"no document prologue",
|
||||
"static buffer exhausted",
|
||||
|
||||
/* system errors */
|
||||
"cannot open file",
|
||||
"cannot stat file",
|
||||
"cannot read file",
|
||||
};
|
||||
|
||||
static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
|
||||
|
@ -247,7 +257,8 @@ pset(const char *buf, int pos, struct mparse *curp)
|
|||
switch (curp->inttype) {
|
||||
case (MPARSE_MDOC):
|
||||
if (NULL == curp->pmdoc)
|
||||
curp->pmdoc = mdoc_alloc(curp->roff, curp);
|
||||
curp->pmdoc = mdoc_alloc(curp->roff, curp,
|
||||
curp->defos);
|
||||
assert(curp->pmdoc);
|
||||
curp->mdoc = curp->pmdoc;
|
||||
return;
|
||||
|
@ -263,7 +274,8 @@ pset(const char *buf, int pos, struct mparse *curp)
|
|||
|
||||
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
|
||||
if (NULL == curp->pmdoc)
|
||||
curp->pmdoc = mdoc_alloc(curp->roff, curp);
|
||||
curp->pmdoc = mdoc_alloc(curp->roff, curp,
|
||||
curp->defos);
|
||||
assert(curp->pmdoc);
|
||||
curp->mdoc = curp->pmdoc;
|
||||
return;
|
||||
|
@ -322,6 +334,15 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we have space for at least
|
||||
* one backslash and one other character
|
||||
* and the trailing NUL byte.
|
||||
*/
|
||||
|
||||
if (pos + 2 >= (int)ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
|
||||
/*
|
||||
* Warn about bogus characters. If you're using
|
||||
* non-ASCII encoding, you're screwing your
|
||||
|
@ -338,26 +359,17 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
|||
mandoc_msg(MANDOCERR_BADCHAR, curp,
|
||||
curp->line, pos, NULL);
|
||||
i++;
|
||||
if (pos >= (int)ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
ln.buf[pos++] = '?';
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Expand registers inline */
|
||||
if ('\\' == blk.buf[i] && 'n' == blk.buf[i + 1]) {
|
||||
roff_expand_nr(curp->roff,
|
||||
blk.buf, &i, blk.sz, &ln.buf, &pos, &ln.sz);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Trailing backslash = a plain char. */
|
||||
|
||||
if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
|
||||
if (pos >= (int)ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
ln.buf[pos++] = blk.buf[i++];
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found escape and at least one other character.
|
||||
* When it's a newline character, skip it.
|
||||
|
@ -395,10 +407,20 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Some other escape sequence, copy & cont. */
|
||||
/* Catch escaped bogus characters. */
|
||||
|
||||
if (pos + 1 >= (int)ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
c = (unsigned char) blk.buf[i+1];
|
||||
|
||||
if ( ! (isascii(c) &&
|
||||
(isgraph(c) || isblank(c)))) {
|
||||
mandoc_msg(MANDOCERR_BADCHAR, curp,
|
||||
curp->line, pos, NULL);
|
||||
i += 2;
|
||||
ln.buf[pos++] = '?';
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Some other escape sequence, copy & cont. */
|
||||
|
||||
ln.buf[pos++] = blk.buf[i++];
|
||||
ln.buf[pos++] = blk.buf[i++];
|
||||
|
@ -474,7 +496,7 @@ rerun:
|
|||
*/
|
||||
if (curp->secondary)
|
||||
curp->secondary->sz -= pos + 1;
|
||||
mparse_readfd_r(curp, -1, ln.buf + of, 1);
|
||||
mparse_readfd(curp, -1, ln.buf + of);
|
||||
if (MANDOCLEVEL_FATAL <= curp->file_status)
|
||||
break;
|
||||
pos = 0;
|
||||
|
@ -554,7 +576,8 @@ rerun:
|
|||
}
|
||||
|
||||
static int
|
||||
read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
|
||||
read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
struct buf *fb, int *with_mmap)
|
||||
{
|
||||
size_t off;
|
||||
ssize_t ssz;
|
||||
|
@ -562,7 +585,10 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
|
|||
#ifdef HAVE_MMAP
|
||||
struct stat st;
|
||||
if (-1 == fstat(fd, &st)) {
|
||||
perror(file);
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSSTAT, curp->file_status,
|
||||
file, 0, 0, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -575,13 +601,15 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
|
|||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
if (st.st_size >= (1U << 31)) {
|
||||
fprintf(stderr, "%s: input too large\n", file);
|
||||
curp->file_status = MANDOCLEVEL_FATAL;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_TOOLARGE,
|
||||
curp->file_status, file, 0, 0, NULL);
|
||||
return(0);
|
||||
}
|
||||
*with_mmap = 1;
|
||||
fb->sz = (size_t)st.st_size;
|
||||
fb->buf = mmap(NULL, fb->sz, PROT_READ,
|
||||
MAP_FILE|MAP_SHARED, fd, 0);
|
||||
fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (fb->buf != MAP_FAILED)
|
||||
return(1);
|
||||
}
|
||||
|
@ -599,7 +627,11 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
|
|||
for (;;) {
|
||||
if (off == fb->sz) {
|
||||
if (fb->sz == (1U << 31)) {
|
||||
fprintf(stderr, "%s: input too large\n", file);
|
||||
curp->file_status = MANDOCLEVEL_FATAL;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_TOOLARGE,
|
||||
curp->file_status,
|
||||
file, 0, 0, NULL);
|
||||
break;
|
||||
}
|
||||
resize_buf(fb, 65536);
|
||||
|
@ -610,7 +642,11 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
|
|||
return(1);
|
||||
}
|
||||
if (ssz == -1) {
|
||||
perror(file);
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSREAD,
|
||||
curp->file_status, file, 0, 0,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
off += (size_t)ssz;
|
||||
|
@ -648,19 +684,25 @@ mparse_end(struct mparse *curp)
|
|||
}
|
||||
|
||||
static void
|
||||
mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file,
|
||||
int re)
|
||||
mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
|
||||
{
|
||||
const char *svfile;
|
||||
static int recursion_depth;
|
||||
|
||||
if (64 < recursion_depth) {
|
||||
mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Line number is per-file. */
|
||||
svfile = curp->file;
|
||||
curp->file = file;
|
||||
curp->line = 1;
|
||||
recursion_depth++;
|
||||
|
||||
mparse_buf_r(curp, blk, 1);
|
||||
|
||||
if (0 == re && MANDOCLEVEL_FATAL > curp->file_status)
|
||||
if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
|
||||
mparse_end(curp);
|
||||
|
||||
curp->file = svfile;
|
||||
|
@ -675,22 +717,25 @@ mparse_readmem(struct mparse *curp, const void *buf, size_t len,
|
|||
blk.buf = UNCONST(buf);
|
||||
blk.sz = len;
|
||||
|
||||
mparse_parse_buffer(curp, blk, file, 0);
|
||||
mparse_parse_buffer(curp, blk, file);
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
static void
|
||||
mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
|
||||
enum mandoclevel
|
||||
mparse_readfd(struct mparse *curp, int fd, const char *file)
|
||||
{
|
||||
struct buf blk;
|
||||
int with_mmap;
|
||||
|
||||
if (-1 == fd)
|
||||
if (-1 == (fd = open(file, O_RDONLY, 0))) {
|
||||
perror(file);
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return;
|
||||
}
|
||||
if (-1 == fd && -1 == (fd = open(file, O_RDONLY, 0))) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSOPEN,
|
||||
curp->file_status,
|
||||
file, 0, 0, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run for each opened file; may be called more than once for
|
||||
* each full parse sequence if the opened file is nested (i.e.,
|
||||
|
@ -698,12 +743,10 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
|
|||
* the parse phase for the file.
|
||||
*/
|
||||
|
||||
if ( ! read_whole_file(file, fd, &blk, &with_mmap)) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return;
|
||||
}
|
||||
if ( ! read_whole_file(curp, file, fd, &blk, &with_mmap))
|
||||
goto out;
|
||||
|
||||
mparse_parse_buffer(curp, blk, file, re);
|
||||
mparse_parse_buffer(curp, blk, file);
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (with_mmap)
|
||||
|
@ -714,18 +757,13 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
|
|||
|
||||
if (STDIN_FILENO != fd && -1 == close(fd))
|
||||
perror(file);
|
||||
}
|
||||
|
||||
enum mandoclevel
|
||||
mparse_readfd(struct mparse *curp, int fd, const char *file)
|
||||
{
|
||||
|
||||
mparse_readfd_r(curp, fd, file, 0);
|
||||
out:
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
struct mparse *
|
||||
mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg)
|
||||
mparse_alloc(enum mparset inttype, enum mandoclevel wlevel,
|
||||
mandocmsg mmsg, void *arg, char *defos)
|
||||
{
|
||||
struct mparse *curp;
|
||||
|
||||
|
@ -737,8 +775,9 @@ mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void
|
|||
curp->mmsg = mmsg;
|
||||
curp->arg = arg;
|
||||
curp->inttype = inttype;
|
||||
curp->defos = defos;
|
||||
|
||||
curp->roff = roff_alloc(curp);
|
||||
curp->roff = roff_alloc(inttype, curp);
|
||||
return(curp);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: st.in,v 1.19 2012/02/26 21:47:09 schwarze Exp $ */
|
||||
/* Id: st.in,v 1.23 2013/12/31 23:29:41 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
@ -34,18 +34,21 @@ LINE("-p1003.1-96", "ISO/IEC 9945-1:1996 (\\(lqPOSIX.1\\(rq)")
|
|||
LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2008", "IEEE Std 1003.1-2008 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2013", "IEEE Std 1003.1-2008/Cor 1-2013 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1", "IEEE Std 1003.1 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1j-2000", "IEEE Std 1003.1j-2000 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX.1b\\(rq)")
|
||||
LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX.1b\\(rq)")
|
||||
LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1c\\(rq)")
|
||||
LINE("-p1003.1d-99", "IEEE Std 1003.1d-1999 (\\(lqPOSIX.1d\\(rq)")
|
||||
LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1g\\(rq)")
|
||||
LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1i\\(rq)")
|
||||
LINE("-p1003.1j-2000", "IEEE Std 1003.1j-2000 (\\(lqPOSIX.1j\\(rq)")
|
||||
LINE("-p1003.1q-2000", "IEEE Std 1003.1q-2000 (\\(lqPOSIX.1q\\(rq)")
|
||||
LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2a-92", "IEEE Std 1003.2a-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
|
||||
LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1387.2", "IEEE Std 1387.2 (\\(lqPOSIX.7.2\\(rq)")
|
||||
LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
|
||||
LINE("-isoC", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO\\~C90, Amendment 1\\(rq)")
|
||||
|
@ -69,11 +72,12 @@ LINE("-xpg4.2", "X/Open Portability Guide Issue\\~4, Version\\~2 (\\(lqXPG4.2\\
|
|||
LINE("-xpg4.3", "X/Open Portability Guide Issue\\~4, Version\\~3 (\\(lqXPG4.3\\(rq)")
|
||||
LINE("-xbd5", "X/Open Base Definitions Issue\\~5 (\\(lqXBD5\\(rq)")
|
||||
LINE("-xcu5", "X/Open Commands and Utilities Issue\\~5 (\\(lqXCU5\\(rq)")
|
||||
LINE("-xsh4.2", "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\\(lqXSH4.2\\(rq)")
|
||||
LINE("-xsh5", "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
|
||||
LINE("-xns5", "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
|
||||
LINE("-xns5.2", "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
|
||||
LINE("-xns5.2d2.0", "X/Open Networking Services Issue\\~5.2 Draft\\~2.0 (\\(lqXNS5.2D2.0\\(rq)")
|
||||
LINE("-xcurses4.2", "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
|
||||
LINE("-susv2", "Version\\~2 of the Single UNIX Specification")
|
||||
LINE("-susv3", "Version\\~3 of the Single UNIX Specification")
|
||||
LINE("-susv2", "Version\\~2 of the Single UNIX Specification (\\(lqSUSv2\\(rq)")
|
||||
LINE("-susv3", "Version\\~3 of the Single UNIX Specification (\\(lqSUSv3\\(rq)")
|
||||
LINE("-svid4", "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: tbl.c,v 1.26 2011/07/25 15:37:00 kristaps Exp $ */
|
||||
/* Id: tbl.c,v 1.27 2013/05/31 22:08:09 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -72,21 +72,21 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
|
|||
struct tbl_node *
|
||||
tbl_alloc(int pos, int line, struct mparse *parse)
|
||||
{
|
||||
struct tbl_node *p;
|
||||
struct tbl_node *tbl;
|
||||
|
||||
p = mandoc_calloc(1, sizeof(struct tbl_node));
|
||||
p->line = line;
|
||||
p->pos = pos;
|
||||
p->parse = parse;
|
||||
p->part = TBL_PART_OPTS;
|
||||
p->opts.tab = '\t';
|
||||
p->opts.linesize = 12;
|
||||
p->opts.decimal = '.';
|
||||
return(p);
|
||||
tbl = mandoc_calloc(1, sizeof(struct tbl_node));
|
||||
tbl->line = line;
|
||||
tbl->pos = pos;
|
||||
tbl->parse = parse;
|
||||
tbl->part = TBL_PART_OPTS;
|
||||
tbl->opts.tab = '\t';
|
||||
tbl->opts.linesize = 12;
|
||||
tbl->opts.decimal = '.';
|
||||
return(tbl);
|
||||
}
|
||||
|
||||
void
|
||||
tbl_free(struct tbl_node *p)
|
||||
tbl_free(struct tbl_node *tbl)
|
||||
{
|
||||
struct tbl_row *rp;
|
||||
struct tbl_cell *cp;
|
||||
|
@ -94,8 +94,8 @@ tbl_free(struct tbl_node *p)
|
|||
struct tbl_dat *dp;
|
||||
struct tbl_head *hp;
|
||||
|
||||
while (NULL != (rp = p->first_row)) {
|
||||
p->first_row = rp->next;
|
||||
while (NULL != (rp = tbl->first_row)) {
|
||||
tbl->first_row = rp->next;
|
||||
while (rp->first) {
|
||||
cp = rp->first;
|
||||
rp->first = cp->next;
|
||||
|
@ -104,8 +104,8 @@ tbl_free(struct tbl_node *p)
|
|||
free(rp);
|
||||
}
|
||||
|
||||
while (NULL != (sp = p->first_span)) {
|
||||
p->first_span = sp->next;
|
||||
while (NULL != (sp = tbl->first_span)) {
|
||||
tbl->first_span = sp->next;
|
||||
while (sp->first) {
|
||||
dp = sp->first;
|
||||
sp->first = dp->next;
|
||||
|
@ -116,12 +116,12 @@ tbl_free(struct tbl_node *p)
|
|||
free(sp);
|
||||
}
|
||||
|
||||
while (NULL != (hp = p->first_head)) {
|
||||
p->first_head = hp->next;
|
||||
while (NULL != (hp = tbl->first_head)) {
|
||||
tbl->first_head = hp->next;
|
||||
free(hp);
|
||||
}
|
||||
|
||||
free(p);
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: tbl_data.c,v 1.24 2011/03/20 16:02:05 kristaps Exp $ */
|
||||
/* Id: tbl_data.c,v 1.28 2014/01/05 18:37:53 joerg Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -49,13 +49,11 @@ getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
|||
cp = dp->layout->first;
|
||||
|
||||
/*
|
||||
* Skip over spanners and vertical lines to data formats, since
|
||||
* Skip over spanners, since
|
||||
* we want to match data with data layout cells in the header.
|
||||
*/
|
||||
|
||||
while (cp && (TBL_CELL_VERT == cp->pos ||
|
||||
TBL_CELL_DVERT == cp->pos ||
|
||||
TBL_CELL_SPAN == cp->pos))
|
||||
while (cp && TBL_CELL_SPAN == cp->pos)
|
||||
cp = cp->next;
|
||||
|
||||
/*
|
||||
|
@ -104,7 +102,7 @@ getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
|||
|
||||
if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
|
||||
tbl->part = TBL_PART_CDATA;
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
assert(*pos - sv >= 0);
|
||||
|
@ -187,7 +185,7 @@ newspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
|
|||
|
||||
dp = mandoc_calloc(1, sizeof(struct tbl_span));
|
||||
dp->line = line;
|
||||
dp->tbl = &tbl->opts;
|
||||
dp->opts = &tbl->opts;
|
||||
dp->layout = rp;
|
||||
dp->head = tbl->first_head;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* $Vendor-Id: tbl_layout.c,v 1.22 2011/09/18 14:14:15 schwarze Exp $ */
|
||||
/* Id: tbl_layout.c,v 1.23 2012/05/27 17:54:54 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012 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
|
||||
|
@ -51,8 +52,7 @@ static const struct tbl_phrase keys[KEYS_MAX] = {
|
|||
{ '^', TBL_CELL_DOWN },
|
||||
{ '-', TBL_CELL_HORIZ },
|
||||
{ '_', TBL_CELL_HORIZ },
|
||||
{ '=', TBL_CELL_DHORIZ },
|
||||
{ '|', TBL_CELL_VERT }
|
||||
{ '=', TBL_CELL_DHORIZ }
|
||||
};
|
||||
|
||||
static int mods(struct tbl_node *, struct tbl_cell *,
|
||||
|
@ -60,10 +60,8 @@ static int mods(struct tbl_node *, struct tbl_cell *,
|
|||
static int cell(struct tbl_node *, struct tbl_row *,
|
||||
int, const char *, int *);
|
||||
static void row(struct tbl_node *, int, const char *, int *);
|
||||
static struct tbl_cell *cell_alloc(struct tbl_node *,
|
||||
struct tbl_row *, enum tbl_cellt);
|
||||
static void head_adjust(const struct tbl_cell *,
|
||||
struct tbl_head *);
|
||||
static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
|
||||
enum tbl_cellt, int vert);
|
||||
|
||||
static int
|
||||
mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
||||
|
@ -80,10 +78,6 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
|||
case (TBL_CELL_HORIZ):
|
||||
/* FALLTHROUGH */
|
||||
case (TBL_CELL_DHORIZ):
|
||||
/* FALLTHROUGH */
|
||||
case (TBL_CELL_VERT):
|
||||
/* FALLTHROUGH */
|
||||
case (TBL_CELL_DVERT):
|
||||
return(1);
|
||||
default:
|
||||
break;
|
||||
|
@ -214,10 +208,17 @@ static int
|
|||
cell(struct tbl_node *tbl, struct tbl_row *rp,
|
||||
int ln, const char *p, int *pos)
|
||||
{
|
||||
int i;
|
||||
int vert, i;
|
||||
enum tbl_cellt c;
|
||||
|
||||
/* Parse the column position (`r', `R', `|', ...). */
|
||||
/* Handle vertical lines. */
|
||||
|
||||
for (vert = 0; '|' == p[*pos]; ++*pos)
|
||||
vert++;
|
||||
while (' ' == p[*pos])
|
||||
(*pos)++;
|
||||
|
||||
/* Parse the column position (`c', `l', `r', ...). */
|
||||
|
||||
for (i = 0; i < KEYS_MAX; i++)
|
||||
if (tolower((unsigned char)p[*pos]) == keys[i].name)
|
||||
|
@ -246,8 +247,6 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
|
|||
return(0);
|
||||
} else if (rp->last)
|
||||
switch (rp->last->pos) {
|
||||
case (TBL_CELL_VERT):
|
||||
case (TBL_CELL_DVERT):
|
||||
case (TBL_CELL_HORIZ):
|
||||
case (TBL_CELL_DHORIZ):
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
|
@ -270,25 +269,16 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
|
|||
|
||||
(*pos)++;
|
||||
|
||||
/* Extra check for the double-vertical. */
|
||||
|
||||
if (TBL_CELL_VERT == c && '|' == p[*pos]) {
|
||||
(*pos)++;
|
||||
c = TBL_CELL_DVERT;
|
||||
}
|
||||
|
||||
/* Disallow adjacent spacers. */
|
||||
|
||||
if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
|
||||
(TBL_CELL_VERT == rp->last->pos ||
|
||||
TBL_CELL_DVERT == rp->last->pos)) {
|
||||
if (vert > 2) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Allocate cell then parse its modifiers. */
|
||||
|
||||
return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos));
|
||||
return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos));
|
||||
}
|
||||
|
||||
|
||||
|
@ -308,11 +298,11 @@ row: /*
|
|||
*/
|
||||
|
||||
rp = mandoc_calloc(1, sizeof(struct tbl_row));
|
||||
if (tbl->last_row) {
|
||||
if (tbl->last_row)
|
||||
tbl->last_row->next = rp;
|
||||
tbl->last_row = rp;
|
||||
} else
|
||||
tbl->last_row = tbl->first_row = rp;
|
||||
else
|
||||
tbl->first_row = rp;
|
||||
tbl->last_row = rp;
|
||||
|
||||
cell:
|
||||
while (isspace((unsigned char)p[*pos]))
|
||||
|
@ -357,7 +347,8 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p)
|
|||
}
|
||||
|
||||
static struct tbl_cell *
|
||||
cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
|
||||
cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos,
|
||||
int vert)
|
||||
{
|
||||
struct tbl_cell *p, *pp;
|
||||
struct tbl_head *h, *hp;
|
||||
|
@ -365,108 +356,35 @@ cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
|
|||
p = mandoc_calloc(1, sizeof(struct tbl_cell));
|
||||
|
||||
if (NULL != (pp = rp->last)) {
|
||||
rp->last->next = p;
|
||||
rp->last = p;
|
||||
} else
|
||||
rp->last = rp->first = p;
|
||||
pp->next = p;
|
||||
h = pp->head->next;
|
||||
} else {
|
||||
rp->first = p;
|
||||
h = tbl->first_head;
|
||||
}
|
||||
rp->last = p;
|
||||
|
||||
p->pos = pos;
|
||||
p->vert = vert;
|
||||
|
||||
/*
|
||||
* This is a little bit complicated. Here we determine the
|
||||
* header the corresponds to a cell. We add headers dynamically
|
||||
* when need be or re-use them, otherwise. As an example, given
|
||||
* the following:
|
||||
*
|
||||
* 1 c || l
|
||||
* 2 | c | l
|
||||
* 3 l l
|
||||
* 3 || c | l |.
|
||||
*
|
||||
* We first add the new headers (as there are none) in (1); then
|
||||
* in (2) we insert the first spanner (as it doesn't match up
|
||||
* with the header); then we re-use the prior data headers,
|
||||
* skipping over the spanners; then we re-use everything and add
|
||||
* a last spanner. Note that VERT headers are made into DVERT
|
||||
* ones.
|
||||
*/
|
||||
|
||||
h = pp ? pp->head->next : tbl->first_head;
|
||||
/* Re-use header. */
|
||||
|
||||
if (h) {
|
||||
/* Re-use data header. */
|
||||
if (TBL_HEAD_DATA == h->pos &&
|
||||
(TBL_CELL_VERT != p->pos &&
|
||||
TBL_CELL_DVERT != p->pos)) {
|
||||
p->head = h;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* Re-use spanner header. */
|
||||
if (TBL_HEAD_DATA != h->pos &&
|
||||
(TBL_CELL_VERT == p->pos ||
|
||||
TBL_CELL_DVERT == p->pos)) {
|
||||
head_adjust(p, h);
|
||||
p->head = h;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* Right-shift headers with a new spanner. */
|
||||
if (TBL_HEAD_DATA == h->pos &&
|
||||
(TBL_CELL_VERT == p->pos ||
|
||||
TBL_CELL_DVERT == p->pos)) {
|
||||
hp = mandoc_calloc(1, sizeof(struct tbl_head));
|
||||
hp->ident = tbl->opts.cols++;
|
||||
hp->prev = h->prev;
|
||||
if (h->prev)
|
||||
h->prev->next = hp;
|
||||
if (h == tbl->first_head)
|
||||
tbl->first_head = hp;
|
||||
h->prev = hp;
|
||||
hp->next = h;
|
||||
head_adjust(p, hp);
|
||||
p->head = hp;
|
||||
return(p);
|
||||
}
|
||||
|
||||
if (NULL != (h = h->next)) {
|
||||
head_adjust(p, h);
|
||||
p->head = h;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* Fall through to default case... */
|
||||
p->head = h;
|
||||
return(p);
|
||||
}
|
||||
|
||||
hp = mandoc_calloc(1, sizeof(struct tbl_head));
|
||||
hp->ident = tbl->opts.cols++;
|
||||
hp->vert = vert;
|
||||
|
||||
if (tbl->last_head) {
|
||||
hp->prev = tbl->last_head;
|
||||
tbl->last_head->next = hp;
|
||||
tbl->last_head = hp;
|
||||
} else
|
||||
tbl->last_head = tbl->first_head = hp;
|
||||
tbl->first_head = hp;
|
||||
tbl->last_head = hp;
|
||||
|
||||
head_adjust(p, hp);
|
||||
p->head = hp;
|
||||
return(p);
|
||||
}
|
||||
|
||||
static void
|
||||
head_adjust(const struct tbl_cell *cellp, struct tbl_head *head)
|
||||
{
|
||||
if (TBL_CELL_VERT != cellp->pos &&
|
||||
TBL_CELL_DVERT != cellp->pos) {
|
||||
head->pos = TBL_HEAD_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TBL_CELL_VERT == cellp->pos)
|
||||
if (TBL_HEAD_DVERT != head->pos)
|
||||
head->pos = TBL_HEAD_VERT;
|
||||
|
||||
if (TBL_CELL_DVERT == cellp->pos)
|
||||
head->pos = TBL_HEAD_DVERT;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Vendor-Id: tbl_opts.c,v 1.12 2011/09/18 14:14:15 schwarze Exp $ */
|
||||
/* Id: tbl_opts.c,v 1.12 2011/09/18 14:14:15 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
.\" $Vendor-Id: whatis.1,v 1.8 2012/03/24 01:54:43 kristaps Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\"
|
||||
.\" 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 March 24, 2012
|
||||
.Dt WHATIS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm whatis
|
||||
.Nd search for manual pages by page names
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar manpath
|
||||
.Op Fl m Ar manpath
|
||||
.Op Fl S Ar arch
|
||||
.Op Fl s Ar section
|
||||
.Ar name ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility searches databases generated by
|
||||
.Xr mandocdb 8
|
||||
for manuals containing the word
|
||||
.Ar name
|
||||
in their page name, ignoring case.
|
||||
It returns the header lines from all matching pages.
|
||||
You can then use the
|
||||
.Xr man 1
|
||||
command to get more information.
|
||||
.Pp
|
||||
By default,
|
||||
.Nm
|
||||
searches for
|
||||
.Xr mandocdb 8
|
||||
databases in the default paths stipulated by
|
||||
.Xr man 1 .
|
||||
If standard output is a TTY, a result may be selected from a list and
|
||||
its manual displayed with the pager.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl C Ar file
|
||||
Specify an alternative configuration
|
||||
.Ar file
|
||||
in
|
||||
.Xr man.conf 5
|
||||
format.
|
||||
.It Fl M Ar manpath
|
||||
Use the colon-separated
|
||||
.Ar manpath
|
||||
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
|
||||
.Ar manpath
|
||||
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
|
||||
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
|
||||
If on a TTY, results are prefixed with a numeric identifier.
|
||||
.Pp
|
||||
.D1 [index] title(cat) \- description
|
||||
.Pp
|
||||
One may choose a manual be entering the index at the prompt.
|
||||
Valid choices are displayed using
|
||||
.Ev MANPAGER ,
|
||||
or failing that ,
|
||||
.Ev PAGER
|
||||
or just
|
||||
.Xr more 1 .
|
||||
Source pages are formatted with
|
||||
.Xr mandoc 1 ;
|
||||
preformatted pages with
|
||||
.Xr cat 1 .
|
||||
.Pp
|
||||
.Nm
|
||||
is identical to running
|
||||
.Xr apropos 1
|
||||
as follows:
|
||||
.Pp
|
||||
.Dl $ apropos -- -i 'Nm~[[:<:]]term[[:>:]]'
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Ds
|
||||
.It Ev MANPAGER
|
||||
Default pager for manuals.
|
||||
If this is unset, falls back to
|
||||
.Ev Pager .
|
||||
.It Ev PAGER
|
||||
The second choice for a manual pager.
|
||||
If this is unset, use
|
||||
.Xr more 1 .
|
||||
.It Ev MANPATH
|
||||
Colon-separated paths modifying the default list of paths searched for
|
||||
manual databases.
|
||||
Invalid paths, or paths without manual databases, are ignored.
|
||||
Overridden by
|
||||
.Fl M .
|
||||
If
|
||||
.Ev MANPATH
|
||||
begins with a
|
||||
.Sq \&: ,
|
||||
it is appended to the default list;
|
||||
else if it ends with
|
||||
.Sq \&: ,
|
||||
it is prepended to the default list; else if it contains
|
||||
.Sq \&:: ,
|
||||
the default list is inserted between the colons.
|
||||
If none of these conditions are met, it overrides the default list.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/etc/man.conf" -compact
|
||||
.It Pa whatis.db
|
||||
name of the
|
||||
.Xr mandocdb 8
|
||||
keyword database
|
||||
.It Pa whatis.index
|
||||
name of the
|
||||
.Xr mandocdb 8
|
||||
filename database
|
||||
.It Pa /etc/man.conf
|
||||
default
|
||||
.Xr man 1
|
||||
configuration file
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr man 1 ,
|
||||
.Xr man.conf 5 ,
|
||||
.Xr mandocdb 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Bx 2 .
|
||||
It was rewritten from scratch as part of the
|
||||
.Xr mandocdb 8
|
||||
project for
|
||||
.Ox 5.1 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.An Bill Joy
|
||||
wrote the original
|
||||
.Bx
|
||||
.Nm
|
||||
in 1979.
|
||||
The current version was written by
|
||||
.An Kristaps Dzonsons ,
|
||||
.Mt kristaps@bsd.lv .
|
Loading…
Reference in New Issue