rather than(like .Bd -literal does). + Reported by afresh1@ 12 Apr 2016 14:35:45 -0700 + +- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal + space, see for example random(3). Introduced in + http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92 + reported by deraadt@ Mon, 28 Sep 2015 20:14:13 -0600 (MDT) + loc ** exist ** algo ** size * imp * + +- jsg on icb, Nov 3, 2014: + try to guess Xr in man(7) for hyperlinking + +- The tables used to render the three-part page headers actually force + the width of the to the max-width given for . + Not yet sure how to fix that... + Observed by an Anonymous Coward on undeadly.org: + http://undeadly.org/cgi?action=article&sid=20140925064244&pid=1 + loc * exist * algo ** size * imp *** + +- consider whether can be used for Ar Dv Er Ev Fa Va. + from bentley@ Wed, 13 Aug 2014 09:17:55 -0600 + +- generatetags in HTML + idea from florian@ Tue, 7 Apr 2015 00:26:28 +0000 + may be possible to implement with .Lk img://something.png alt_text + +- check https://github.com/trentm/mdocml + +************************************************************************ +* formatting issues: gratuitous differences +************************************************************************ + +- .Fn reopens a new scope after punctuation in mandoc, + but closes its scope for good in groff. + Do we want to change mandoc or groff? + Steffen Nurpmeso Sat, 08 Nov 2014 13:34:59 +0100 + loc * exist ** algo ** size * imp ** + +- In .Bl -enum -width 0n, groff continues one the same line after + the number, mandoc breaks the line. + mail to kristaps@ Mon, 20 Jul 2009 02:21:39 +0200 + loc * exist ** algo ** size * imp ** + +- .Pp between two .It in .Bl -column should produce one, + not two blank lines, see e.g. login.conf(5). + reported by jmc@ Sun, 17 Apr 2011 14:04:58 +0059 + reported again by sthen@ Wed, 18 Jan 2012 02:09:39 +0000 (UTC) + loc * exist *** algo ** size * imp ** + +- If the *first* line after .It is .Pp, break the line right after + the tag, do not pad with space characters before breaking. + See the description of the a, c, and i commands in sed(1). + loc * exist ** algo ** size * imp ** + +- If the first line after .It is .D1, do not assert a blank line + in between, see for example tmux(1). + reported by nicm@ 13 Jan 2011 00:18:57 +0000 + loc * exist ** algo ** size * imp ** + +- Trailing punctuation after .It should trigger EOS spacing. + reported by Nicolas Joly Sat, 17 Nov 2012 11:49:54 +0100 + Probably, this should be fixed somewhere in termp_it_pre(), not sure. + loc * exist ** algo ** size * imp ** + +- .Nx 1.0a + should be "NetBSD 1.0A", not "NetBSD 1.0a", + see OpenBSD ccdconfig(8). + loc * exist * algo * size * imp ** + +- In .Bl -tag, if a tag exceeds the right margin and must be continued + on the next line, it must be indented by -width, not width+1; + see "rule block|pass" in OpenBSD ifconfig(8). + loc * exist *** algo ** size * imp ** + +- When the -width string contains macros, the macros must be rendered + before measuring the width, for example + .Bl -tag -width ".Dv message" + in magic(5), located in src/usr.bin/file, is the same + as -width 7n, not -width 11n. + The same applies to .Bl -column column widths; + reported again by Nicolas Joly Thu, 1 Mar 2012 13:41:26 +0100 via wiz@ 5 Mar + reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200 + loc *** exist *** algo *** size ** imp *** + An easy partial fix would be to just skip the first word if it starts + with a dot, including any following white space, when measuring. + loc * exist * algo * size * imp *** + +- The \& zero-width character counts as output. + That is, when it is alone on a line between two .Pp, + we want three blank lines, not two as in mandoc. + loc ** exist ** algo ** size * imp ** + +- Header lines of excessive length: + Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c + and document it in mdoc(7) and man(7) COMPATIBILITY + found while talking to Chris Bennett + loc * exist * algo * size * imp * + +- Sequences of multiple man(7) paragraphs (.PP, .IP) interspersed + with .ps and .nf/.fi produce execessive blank lines, see libJudy + and graphics/dcmtk. The parser reorg may help with this. + +- trailing whitespace must be ignored even when followed by a font escape, + see for example + makes + \fBdig \fR + operate in batch mode + in dig(1). + loc ** exist ** algo ** size * imp ** + +************************************************************************ +* warning issues +************************************************************************ + +- provide a way in mandoc(1) to warn about broken .Xr links; + probably cannot be on by default in -Tlint because it needs + to access the manpath and mandoc.db(3) after parsing. + asked for by jmc@ Fri, 4 Dec 2015 22:39:40 +0000 + +- Report errors in -O suboption parsing. + loc * exist * algo * size * imp ** + +- warn when .Sh or .Ss contain other macros + Steffen Nurpmeso, savannah.gnu.org/bugs/index.php?45034 + loc * exist * algo * size * imp ** + +- check that MANDOCERR_BADTAB is thrown in the right cases, + i.e. when finding a literal tab character in fill mode, + and possibly change the wording of the warning message + to refer to fill mode, not literal mode + See the mail from Werner LEMBERG on the groff list, + Fri, 14 Feb 2014 18:54:42 +0100 (CET) + loc * exist ** algo ** size * imp ** + +- warn about attempts to call non-callable macros + Steffen Nurpmeso Tue, 11 Nov 2014 22:55:16 +0100 + Note that formatting is inconsistent in groff. + .Fn Po prints "Po()", .Ar Sh prints "file ..." and no "Sh". + Relatively hard because the relevant code is scattered + all over mdoc_macro.c and all subtly different. + loc ** exist ** algo ** size ** imp ** + +- warn about "new sentence, new line" + loc ** exist ** algo *** size * imp ** + +- mandoc_special does not really check the escape sequence, + but just the overall format + loc ** exist ** algo *** size ** imp ** + +- integrate mdoclint into mandoc ("end-of-line whitespace" thread) + from jmc@ Mon, 13 Jul 2009 17:12:09 +0100 + from kristaps@ Mon, 13 Jul 2009 18:34:53 +0200 + from jmc@ Mon, 13 Jul 2009 17:45:37 +0059 + from kristaps@ Mon, 13 Jul 2009 19:02:03 +0200 + (mostly done, check what remains) + +- -Tlint parser errors and warnings to stdout + to tech@mdocml, naddy@ Wed, 28 Sep 2011 11:21:46 +0200 + wait! kristaps@ Sun, 02 Oct 2011 17:12:52 +0200 + +************************************************************************ +* documentation issues +************************************************************************ + +- mention hyphenation rules: + breaking at letter-letter in text mode (not macro args) + proper hyphenation is unimplemented + +- talk about spacing around delimiters + to jmc@, kristaps@ Sat, 23 Apr 2011 17:41:27 +0200 + +- mark macros as: page structure domain, manual domain, general text domain + is this useful? + +- mention /usr/share/misc/mdoc.template in mdoc(7)? + +- Is all the content from http://www.std.com/obi/BSD/doc/usd/28.tbl/tbl + covered in tbl(7)? + +************************************************************************ +* performance issues +************************************************************************ + +- Why are we using MAP_SHARED, not MAP_PRIVATE for mmap(2)? + from kristaps@ Sat, 09 Aug 2014 13:51:36 +0200 + +Several areas can be cleaned up to make mandoc even faster. These are + +- improve hashing mechanism for macros (quite important: performance) + +- improve hashing mechanism for characters (not as important) + +- the PDF file is HUGE: this can be reduced by using relative offsets + +- instead of re-initialising the roff predefined-strings set before each + parse, create a read-only version the first time and copy it + loc * exist ** algo ** size * imp ** + +************************************************************************ +* structural issues +************************************************************************ + +- POSIX says in the documentation of sysconf(3) that PATH_MAX + is allowed to be so large that it is a bad idea to use it + for sizing static buffers. So use dynamic buffers throughout. + See the file test-PATH_MAX.c for details. + Found by Aaron M. Ucko in the GNU Hurd via Bdale Garbee, + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=829624 + +- We use the input line number at several places to distinguish + same-line from different-line input. That plainly doesn't work + with user-defined macros, leading to random breakage. + +- Find better ways to prevent endless loops + in roff(7) macro and string expansion. + +- Finish cleanup of date handling. + Decide which formats should be recognized where. + Update both mdoc(7) and man(7) documentation. + Triggered by Tim van der Molen Tue, 22 Feb 2011 20:30:45 +0100 + +- struct mparse refactoring + Steffen Nurpmeso Thu, 04 Sep 2014 12:50:00 +0200 + +************************************************************************ +* CGI issues +************************************************************************ + + - Enable HTTP compression by detecting gzip encoding and filtering + output through libz. + - Sandbox (see OpenSSH). + - Enable caching support via HTTP 304 and If-Modified-Since. + - Allow for cgi.h to be overridden by CGI environment variables. + Otherwise, binary distributions will inherit the compile-time + behaviour, which is not optimal. + - Have Mac OSX systems automatically disable -static compilation of the + CGI: -static isn't supported. + +************************************************************************ +* to improve in the groff_mdoc(7) macros +************************************************************************ + +- use uname(1) to set doc-default-operating-system at install time + tobimensch Mon, 1 Dec 2014 00:25:07 +0100 Index: vendor/mdocml/20170121/cgi.c =================================================================== --- vendor/mdocml/20170121/cgi.c (nonexistent) +++ vendor/mdocml/20170121/cgi.c (revision 312592) @@ -0,0 +1,1179 @@ +/* $Id: cgi.c,v 1.144 2017/01/21 01:20:31 schwarze Exp $ */ +/* + * Copyright (c) 2011, 2012 Kristaps Dzonsons
+ * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" +#include "man.h" +#include "main.h" +#include "manconf.h" +#include "mansearch.h" +#include "cgi.h" + +/* + * A query as passed to the search function. + */ +struct query { + char *manpath; /* desired manual directory */ + char *arch; /* architecture */ + char *sec; /* manual section */ + char *query; /* unparsed query expression */ + int equal; /* match whole names, not substrings */ +}; + +struct req { + struct query q; + char **p; /* array of available manpaths */ + size_t psz; /* number of available manpaths */ + int isquery; /* QUERY_STRING used, not PATH_INFO */ +}; + +enum focus { + FOCUS_NONE = 0, + FOCUS_QUERY +}; + +static void html_print(const char *); +static void html_putchar(char); +static int http_decode(char *); +static void parse_manpath_conf(struct req *); +static void parse_path_info(struct req *req, const char *path); +static void parse_query_string(struct req *, const char *); +static void pg_error_badrequest(const char *); +static void pg_error_internal(void); +static void pg_index(const struct req *); +static void pg_noresult(const struct req *, const char *); +static void pg_search(const struct req *); +static void pg_searchres(const struct req *, + struct manpage *, size_t); +static void pg_show(struct req *, const char *); +static void resp_begin_html(int, const char *); +static void resp_begin_http(int, const char *); +static void resp_catman(const struct req *, const char *); +static void resp_copy(const char *); +static void resp_end_html(void); +static void resp_format(const struct req *, const char *); +static void resp_searchform(const struct req *, enum focus); +static void resp_show(const struct req *, const char *); +static void set_query_attr(char **, char **); +static int validate_filename(const char *); +static int validate_manpath(const struct req *, const char *); +static int validate_urifrag(const char *); + +static const char *scriptname = SCRIPT_NAME; + +static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; +static const char *const sec_numbers[] = { + "0", "1", "2", "3", "3p", "4", "5", "6", "7", "8", "9" +}; +static const char *const sec_names[] = { + "All Sections", + "1 - General Commands", + "2 - System Calls", + "3 - Library Functions", + "3p - Perl Library", + "4 - Device Drivers", + "5 - File Formats", + "6 - Games", + "7 - Miscellaneous Information", + "8 - System Manager\'s Manual", + "9 - Kernel Developer\'s Manual" +}; +static const int sec_MAX = sizeof(sec_names) / sizeof(char *); + +static const char *const arch_names[] = { + "amd64", "alpha", "armv7", + "hppa", "i386", "landisk", + "loongson", "luna88k", "macppc", "mips64", + "octeon", "sgi", "socppc", "sparc64", + "amiga", "arc", "armish", "arm32", + "atari", "aviion", "beagle", "cats", + "hppa64", "hp300", + "ia64", "mac68k", "mvme68k", "mvme88k", + "mvmeppc", "palm", "pc532", "pegasos", + "pmax", "powerpc", "solbourne", "sparc", + "sun3", "vax", "wgrisc", "x68k", + "zaurus" +}; +static const int arch_MAX = sizeof(arch_names) / sizeof(char *); + +/* + * Print a character, escaping HTML along the way. + * This will pass non-ASCII straight to output: be warned! + */ +static void +html_putchar(char c) +{ + + switch (c) { + case ('"'): + printf("""); + break; + case ('&'): + printf("&"); + break; + case ('>'): + printf(">"); + break; + case ('<'): + printf("<"); + break; + default: + putchar((unsigned char)c); + break; + } +} + +/* + * Call through to html_putchar(). + * Accepts NULL strings. + */ +static void +html_print(const char *p) +{ + + if (NULL == p) + return; + while ('\0' != *p) + html_putchar(*p++); +} + +/* + * Transfer the responsibility for the allocated string *val + * to the query structure. + */ +static void +set_query_attr(char **attr, char **val) +{ + + free(*attr); + if (**val == '\0') { + *attr = NULL; + free(*val); + } else + *attr = *val; + *val = NULL; +} + +/* + * Parse the QUERY_STRING for key-value pairs + * and store the values into the query structure. + */ +static void +parse_query_string(struct req *req, const char *qs) +{ + char *key, *val; + size_t keysz, valsz; + + req->isquery = 1; + req->q.manpath = NULL; + req->q.arch = NULL; + req->q.sec = NULL; + req->q.query = NULL; + req->q.equal = 1; + + key = val = NULL; + while (*qs != '\0') { + + /* Parse one key. */ + + keysz = strcspn(qs, "=;&"); + key = mandoc_strndup(qs, keysz); + qs += keysz; + if (*qs != '=') + goto next; + + /* Parse one value. */ + + valsz = strcspn(++qs, ";&"); + val = mandoc_strndup(qs, valsz); + qs += valsz; + + /* Decode and catch encoding errors. */ + + if ( ! (http_decode(key) && http_decode(val))) + goto next; + + /* Handle key-value pairs. */ + + if ( ! strcmp(key, "query")) + set_query_attr(&req->q.query, &val); + + else if ( ! strcmp(key, "apropos")) + req->q.equal = !strcmp(val, "0"); + + else if ( ! strcmp(key, "manpath")) { +#ifdef COMPAT_OLDURI + if ( ! strncmp(val, "OpenBSD ", 8)) { + val[7] = '-'; + if ('C' == val[8]) + val[8] = 'c'; + } +#endif + set_query_attr(&req->q.manpath, &val); + } + + else if ( ! (strcmp(key, "sec") +#ifdef COMPAT_OLDURI + && strcmp(key, "sektion") +#endif + )) { + if ( ! strcmp(val, "0")) + *val = '\0'; + set_query_attr(&req->q.sec, &val); + } + + else if ( ! strcmp(key, "arch")) { + if ( ! strcmp(val, "default")) + *val = '\0'; + set_query_attr(&req->q.arch, &val); + } + + /* + * The key must be freed in any case. + * The val may have been handed over to the query + * structure, in which case it is now NULL. + */ +next: + free(key); + key = NULL; + free(val); + val = NULL; + + if (*qs != '\0') + qs++; + } +} + +/* + * HTTP-decode a string. The standard explanation is that this turns + * "%4e+foo" into "n foo" in the regular way. This is done in-place + * over the allocated string. + */ +static int +http_decode(char *p) +{ + char hex[3]; + char *q; + int c; + + hex[2] = '\0'; + + q = p; + for ( ; '\0' != *p; p++, q++) { + if ('%' == *p) { + if ('\0' == (hex[0] = *(p + 1))) + return 0; + if ('\0' == (hex[1] = *(p + 2))) + return 0; + if (1 != sscanf(hex, "%x", &c)) + return 0; + if ('\0' == c) + return 0; + + *q = (char)c; + p += 2; + } else + *q = '+' == *p ? ' ' : *p; + } + + *q = '\0'; + return 1; +} + +static void +resp_begin_http(int code, const char *msg) +{ + + if (200 != code) + printf("Status: %d %s\r\n", code, msg); + + printf("Content-Type: text/html; charset=utf-8\r\n" + "Cache-Control: no-cache\r\n" + "Pragma: no-cache\r\n" + "\r\n"); + + fflush(stdout); +} + +static void +resp_copy(const char *filename) +{ + char buf[4096]; + ssize_t sz; + int fd; + + if ((fd = open(filename, O_RDONLY)) != -1) { + fflush(stdout); + while ((sz = read(fd, buf, sizeof(buf))) > 0) + write(STDOUT_FILENO, buf, sz); + close(fd); + } +} + +static void +resp_begin_html(int code, const char *msg) +{ + + resp_begin_http(code, msg); + + printf("\n" + "\n" + "\n" + " \n" + " \n" + " %s \n" + "\n" + "\n", + CSS_DIR, CUSTOMIZE_TITLE); + + resp_copy(MAN_DIR "/header.html"); +} + +static void +resp_end_html(void) +{ + + resp_copy(MAN_DIR "/footer.html"); + + puts("\n" + ""); +} + +static void +resp_searchform(const struct req *req, enum focus focus) +{ + int i; + + printf(""); +} + +static int +validate_urifrag(const char *frag) +{ + + while ('\0' != *frag) { + if ( ! (isalnum((unsigned char)*frag) || + '-' == *frag || '.' == *frag || + '/' == *frag || '_' == *frag)) + return 0; + frag++; + } + return 1; +} + +static int +validate_manpath(const struct req *req, const char* manpath) +{ + size_t i; + + for (i = 0; i < req->psz; i++) + if ( ! strcmp(manpath, req->p[i])) + return 1; + + return 0; +} + +static int +validate_filename(const char *file) +{ + + if ('.' == file[0] && '/' == file[1]) + file += 2; + + return ! (strstr(file, "../") || strstr(file, "/..") || + (strncmp(file, "man", 3) && strncmp(file, "cat", 3))); +} + +static void +pg_index(const struct req *req) +{ + + resp_begin_html(200, NULL); + resp_searchform(req, FOCUS_QUERY); + printf("\n" + "This web interface is documented in the\n" + "man.cgi(8)\n" + "manual, and the\n" + "apropos(1)\n" + "manual explains the query syntax.\n" + "
\n", + scriptname, *scriptname == '\0' ? "" : "/", + scriptname, *scriptname == '\0' ? "" : "/"); + resp_end_html(); +} + +static void +pg_noresult(const struct req *req, const char *msg) +{ + resp_begin_html(200, NULL); + resp_searchform(req, FOCUS_QUERY); + puts(""); + puts(msg); + puts("
"); + resp_end_html(); +} + +static void +pg_error_badrequest(const char *msg) +{ + + resp_begin_html(400, "Bad Request"); + puts("Bad Request
\n" + "\n"); + puts(msg); + printf("Try again from the\n" + "main page.\n" + "
", scriptname); + resp_end_html(); +} + +static void +pg_error_internal(void) +{ + resp_begin_html(500, "Internal Server Error"); + puts("Internal Server Error
"); + resp_end_html(); +} + +static void +pg_searchres(const struct req *req, struct manpage *r, size_t sz) +{ + char *arch, *archend; + const char *sec; + size_t i, iuse; + int archprio, archpriouse; + int prio, priouse; + + for (i = 0; i < sz; i++) { + if (validate_filename(r[i].file)) + continue; + warnx("invalid filename %s in %s database", + r[i].file, req->q.manpath); + pg_error_internal(); + return; + } + + if (req->isquery && sz == 1) { + /* + * If we have just one result, then jump there now + * without any delay. + */ + printf("Status: 303 See Other\r\n"); + printf("Location: http://%s/%s%s%s/%s", + HTTP_HOST, scriptname, + *scriptname == '\0' ? "" : "/", + req->q.manpath, r[0].file); + printf("\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "\r\n"); + return; + } + + resp_begin_html(200, NULL); + resp_searchform(req, + req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY); + + if (sz > 1) { + puts(""); + for (i = 0; i < sz; i++) { + printf("
"); + } + + /* + * In man(1) mode, show one of the pages + * even if more than one is found. + */ + + if (req->q.equal || sz == 1) { + puts("\n" + " "); + } + puts("" + "", + scriptname, *scriptname == '\0' ? "" : "/", + req->q.manpath, r[i].file); + html_print(r[i].names); + printf(" \n" + ""); + html_print(r[i].output); + puts(" \n" + "
"); + iuse = 0; + priouse = 20; + archpriouse = 3; + for (i = 0; i < sz; i++) { + sec = r[i].file; + sec += strcspn(sec, "123456789"); + if (sec[0] == '\0') + continue; + prio = sec_prios[sec[0] - '1']; + if (sec[1] != '/') + prio += 10; + if (req->q.arch == NULL) { + archprio = + ((arch = strchr(sec + 1, '/')) + == NULL) ? 3 : + ((archend = strchr(arch + 1, '/')) + == NULL) ? 0 : + strncmp(arch, "amd64/", + archend - arch) ? 2 : 1; + if (archprio < archpriouse) { + archpriouse = archprio; + priouse = prio; + iuse = i; + continue; + } + if (archprio > archpriouse) + continue; + } + if (prio >= priouse) + continue; + priouse = prio; + iuse = i; + } + resp_show(req, r[iuse].file); + } + + resp_end_html(); +} + +static void +resp_catman(const struct req *req, const char *file) +{ + FILE *f; + char *p; + size_t sz; + ssize_t len; + int i; + int italic, bold; + + if ((f = fopen(file, "r")) == NULL) { + puts("You specified an invalid manual file.
"); + return; + } + + puts("\n" + ""); + + fclose(f); +} + +static void +resp_format(const struct req *req, const char *file) +{ + struct manoutput conf; + struct mparse *mp; + struct roff_man *man; + void *vp; + int fd; + int usepath; + + if (-1 == (fd = open(file, O_RDONLY, 0))) { + puts(""); + + p = NULL; + sz = 0; + + while ((len = getline(&p, &sz, f)) != -1) { + bold = italic = 0; + for (i = 0; i < len - 1; i++) { + /* + * This means that the catpage is out of state. + * Ignore it and keep going (although the + * catpage is bogus). + */ + + if ('\b' == p[i] || '\n' == p[i]) + continue; + + /* + * Print a regular character. + * Close out any bold/italic scopes. + * If we're in back-space mode, make sure we'll + * have something to enter when we backspace. + */ + + if ('\b' != p[i + 1]) { + if (italic) + printf(""); + if (bold) + printf(""); + italic = bold = 0; + html_putchar(p[i]); + continue; + } else if (i + 2 >= len) + continue; + + /* Italic mode. */ + + if ('_' == p[i]) { + if (bold) + printf(""); + if ( ! italic) + printf(""); + bold = 0; + italic = 1; + i += 2; + html_putchar(p[i]); + continue; + } + + /* + * Handle funny behaviour troff-isms. + * These grok'd from the original man2html.c. + */ + + if (('+' == p[i] && 'o' == p[i + 2]) || + ('o' == p[i] && '+' == p[i + 2]) || + ('|' == p[i] && '=' == p[i + 2]) || + ('=' == p[i] && '|' == p[i + 2]) || + ('*' == p[i] && '=' == p[i + 2]) || + ('=' == p[i] && '*' == p[i + 2]) || + ('*' == p[i] && '|' == p[i + 2]) || + ('|' == p[i] && '*' == p[i + 2])) { + if (italic) + printf(""); + if (bold) + printf(""); + italic = bold = 0; + putchar('*'); + i += 2; + continue; + } else if (('|' == p[i] && '-' == p[i + 2]) || + ('-' == p[i] && '|' == p[i + 1]) || + ('+' == p[i] && '-' == p[i + 1]) || + ('-' == p[i] && '+' == p[i + 1]) || + ('+' == p[i] && '|' == p[i + 1]) || + ('|' == p[i] && '+' == p[i + 1])) { + if (italic) + printf(""); + if (bold) + printf(""); + italic = bold = 0; + putchar('+'); + i += 2; + continue; + } + + /* Bold mode. */ + + if (italic) + printf(""); + if ( ! bold) + printf(""); + bold = 1; + italic = 0; + i += 2; + html_putchar(p[i]); + } + + /* + * Clean up the last character. + * We can get to a newline; don't print that. + */ + + if (italic) + printf(""); + if (bold) + printf(""); + + if (i == len - 1 && p[i] != '\n') + html_putchar(p[i]); + + putchar('\n'); + } + free(p); + + puts("\n" + "You specified an invalid manual file.
"); + return; + } + + mchars_alloc(); + mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1, + MANDOCLEVEL_BADARG, NULL, req->q.manpath); + mparse_readfd(mp, fd, file); + close(fd); + + memset(&conf, 0, sizeof(conf)); + conf.fragment = 1; + usepath = strcmp(req->q.manpath, req->p[0]); + mandoc_asprintf(&conf.man, "/%s%s%%N.%%S", + usepath ? req->q.manpath : "", usepath ? "/" : ""); + + mparse_result(mp, &man, NULL); + if (man == NULL) { + warnx("fatal mandoc error: %s/%s", req->q.manpath, file); + pg_error_internal(); + mparse_free(mp); + mchars_free(); + return; + } + + vp = html_alloc(&conf); + + if (man->macroset == MACROSET_MDOC) { + mdoc_validate(man); + html_mdoc(vp, man); + } else { + man_validate(man); + html_man(vp, man); + } + + html_free(vp); + mparse_free(mp); + mchars_free(); + free(conf.man); +} + +static void +resp_show(const struct req *req, const char *file) +{ + + if ('.' == file[0] && '/' == file[1]) + file += 2; + + if ('c' == *file) + resp_catman(req, file); + else + resp_format(req, file); +} + +static void +pg_show(struct req *req, const char *fullpath) +{ + char *manpath; + const char *file; + + if ((file = strchr(fullpath, '/')) == NULL) { + pg_error_badrequest( + "You did not specify a page to show."); + return; + } + manpath = mandoc_strndup(fullpath, file - fullpath); + file++; + + if ( ! validate_manpath(req, manpath)) { + pg_error_badrequest( + "You specified an invalid manpath."); + free(manpath); + return; + } + + /* + * Begin by chdir()ing into the manpath. + * This way we can pick up the database files, which are + * relative to the manpath root. + */ + + if (chdir(manpath) == -1) { + warn("chdir %s", manpath); + pg_error_internal(); + free(manpath); + return; + } + free(manpath); + + if ( ! validate_filename(file)) { + pg_error_badrequest( + "You specified an invalid manual file."); + return; + } + + resp_begin_html(200, NULL); + resp_searchform(req, FOCUS_NONE); + resp_show(req, file); + resp_end_html(); +} + +static void +pg_search(const struct req *req) +{ + struct mansearch search; + struct manpaths paths; + struct manpage *res; + char **argv; + char *query, *rp, *wp; + size_t ressz; + int argc; + + /* + * Begin by chdir()ing into the root of the manpath. + * This way we can pick up the database files, which are + * relative to the manpath root. + */ + + if (chdir(req->q.manpath) == -1) { + warn("chdir %s", req->q.manpath); + pg_error_internal(); + return; + } + + search.arch = req->q.arch; + search.sec = req->q.sec; + search.outkey = "Nd"; + search.argmode = req->q.equal ? ARG_NAME : ARG_EXPR; + search.firstmatch = 1; + + paths.sz = 1; + paths.paths = mandoc_malloc(sizeof(char *)); + paths.paths[0] = mandoc_strdup("."); + + /* + * Break apart at spaces with backslash-escaping. + */ + + argc = 0; + argv = NULL; + rp = query = mandoc_strdup(req->q.query); + for (;;) { + while (isspace((unsigned char)*rp)) + rp++; + if (*rp == '\0') + break; + argv = mandoc_reallocarray(argv, argc + 1, sizeof(char *)); + argv[argc++] = wp = rp; + for (;;) { + if (isspace((unsigned char)*rp)) { + *wp = '\0'; + rp++; + break; + } + if (rp[0] == '\\' && rp[1] != '\0') + rp++; + if (wp != rp) + *wp = *rp; + if (*rp == '\0') + break; + wp++; + rp++; + } + } + + if (0 == mansearch(&search, &paths, argc, argv, &res, &ressz)) + pg_noresult(req, "You entered an invalid query."); + else if (0 == ressz) + pg_noresult(req, "No results found."); + else + pg_searchres(req, res, ressz); + + free(query); + mansearch_free(res, ressz); + free(paths.paths[0]); + free(paths.paths); +} + +int +main(void) +{ + struct req req; + struct itimerval itimer; + const char *path; + const char *querystring; + int i; + + /* Poor man's ReDoS mitigation. */ + + itimer.it_value.tv_sec = 2; + itimer.it_value.tv_usec = 0; + itimer.it_interval.tv_sec = 2; + itimer.it_interval.tv_usec = 0; + if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) { + warn("setitimer"); + pg_error_internal(); + return EXIT_FAILURE; + } + + /* + * First we change directory into the MAN_DIR so that + * subsequent scanning for manpath directories is rooted + * relative to the same position. + */ + + if (chdir(MAN_DIR) == -1) { + warn("MAN_DIR: %s", MAN_DIR); + pg_error_internal(); + return EXIT_FAILURE; + } + + memset(&req, 0, sizeof(struct req)); + req.q.equal = 1; + parse_manpath_conf(&req); + + /* Parse the path info and the query string. */ + + if ((path = getenv("PATH_INFO")) == NULL) + path = ""; + else if (*path == '/') + path++; + + if (*path != '\0') { + parse_path_info(&req, path); + if (req.q.manpath == NULL || access(path, F_OK) == -1) + path = ""; + } else if ((querystring = getenv("QUERY_STRING")) != NULL) + parse_query_string(&req, querystring); + + /* Validate parsed data and add defaults. */ + + if (req.q.manpath == NULL) + req.q.manpath = mandoc_strdup(req.p[0]); + else if ( ! validate_manpath(&req, req.q.manpath)) { + pg_error_badrequest( + "You specified an invalid manpath."); + return EXIT_FAILURE; + } + + if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) { + pg_error_badrequest( + "You specified an invalid architecture."); + return EXIT_FAILURE; + } + + /* Dispatch to the three different pages. */ + + if ('\0' != *path) + pg_show(&req, path); + else if (NULL != req.q.query) + pg_search(&req); + else + pg_index(&req); + + free(req.q.manpath); + free(req.q.arch); + free(req.q.sec); + free(req.q.query); + for (i = 0; i < (int)req.psz; i++) + free(req.p[i]); + free(req.p); + return EXIT_SUCCESS; +} + +/* + * If PATH_INFO is not a file name, translate it to a query. + */ +static void +parse_path_info(struct req *req, const char *path) +{ + char *dir[4]; + int i; + + req->isquery = 0; + req->q.equal = 1; + req->q.manpath = mandoc_strdup(path); + req->q.arch = NULL; + + /* Mandatory manual page name. */ + if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) { + req->q.query = req->q.manpath; + req->q.manpath = NULL; + } else + *req->q.query++ = '\0'; + + /* Optional trailing section. */ + if ((req->q.sec = strrchr(req->q.query, '.')) != NULL) { + if(isdigit((unsigned char)req->q.sec[1])) { + *req->q.sec++ = '\0'; + req->q.sec = mandoc_strdup(req->q.sec); + } else + req->q.sec = NULL; + } + + /* Handle the case of name[.section] only. */ + if (req->q.manpath == NULL) + return; + req->q.query = mandoc_strdup(req->q.query); + + /* Split directory components. */ + dir[i = 0] = req->q.manpath; + while ((dir[i + 1] = strchr(dir[i], '/')) != NULL) { + if (++i == 3) { + pg_error_badrequest( + "You specified too many directory components."); + exit(EXIT_FAILURE); + } + *dir[i]++ = '\0'; + } + + /* Optional manpath. */ + if ((i = validate_manpath(req, req->q.manpath)) == 0) + req->q.manpath = NULL; + else if (dir[1] == NULL) + return; + + /* Optional section. */ + if (strncmp(dir[i], "man", 3) == 0) { + free(req->q.sec); + req->q.sec = mandoc_strdup(dir[i++] + 3); + } + if (dir[i] == NULL) { + if (req->q.manpath == NULL) + free(dir[0]); + return; + } + if (dir[i + 1] != NULL) { + pg_error_badrequest( + "You specified an invalid directory component."); + exit(EXIT_FAILURE); + } + + /* Optional architecture. */ + if (i) { + req->q.arch = mandoc_strdup(dir[i]); + if (req->q.manpath == NULL) + free(dir[0]); + } else + req->q.arch = dir[0]; +} + +/* + * Scan for indexable paths. + */ +static void +parse_manpath_conf(struct req *req) +{ + FILE *fp; + char *dp; + size_t dpsz; + ssize_t len; + + if ((fp = fopen("manpath.conf", "r")) == NULL) { + warn("%s/manpath.conf", MAN_DIR); + pg_error_internal(); + exit(EXIT_FAILURE); + } + + dp = NULL; + dpsz = 0; + + while ((len = getline(&dp, &dpsz, fp)) != -1) { + if (dp[len - 1] == '\n') + dp[--len] = '\0'; + req->p = mandoc_realloc(req->p, + (req->psz + 1) * sizeof(char *)); + if ( ! validate_urifrag(dp)) { + warnx("%s/manpath.conf contains " + "unsafe path \"%s\"", MAN_DIR, dp); + pg_error_internal(); + exit(EXIT_FAILURE); + } + if (strchr(dp, '/') != NULL) { + warnx("%s/manpath.conf contains " + "path with slash \"%s\"", MAN_DIR, dp); + pg_error_internal(); + exit(EXIT_FAILURE); + } + req->p[req->psz++] = dp; + dp = NULL; + dpsz = 0; + } + free(dp); + + if (req->p == NULL) { + warnx("%s/manpath.conf is empty", MAN_DIR); + pg_error_internal(); + exit(EXIT_FAILURE); + } +} Property changes on: vendor/mdocml/20170121/cgi.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/compat_fts.c =================================================================== --- vendor/mdocml/20170121/compat_fts.c (nonexistent) +++ vendor/mdocml/20170121/compat_fts.c (revision 312592) @@ -0,0 +1,708 @@ +#include "config.h" + +#if HAVE_FTS + +int dummy; + +#else + +/* $Id: compat_fts.c,v 1.12 2016/10/18 23:58:12 schwarze Exp $ */ +/* $OpenBSD: fts.c,v 1.56 2016/09/21 04:38:56 guenther Exp $ */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * 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. + */ + +#include+#include + +#include +#include +#include +#include +#include +#include +#include +#include "compat_fts.h" + +#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) + +static FTSENT *fts_alloc(FTS *, const char *, size_t); +static FTSENT *fts_build(FTS *); +static void fts_lfree(FTSENT *); +static void fts_load(FTS *, FTSENT *); +static size_t fts_maxarglen(char * const *); +static void fts_padjust(FTS *, FTSENT *); +static int fts_palloc(FTS *, size_t); +static FTSENT *fts_sort(FTS *, FTSENT *, int); +static unsigned short fts_stat(FTS *, FTSENT *); + +#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) +#ifndef O_DIRECTORY +#define O_DIRECTORY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#define CLR(opt) (sp->fts_options &= ~(opt)) +#define ISSET(opt) (sp->fts_options & (opt)) +#define SET(opt) (sp->fts_options |= (opt)) + +FTS * +fts_open(char * const *argv, int options, + int (*compar)(const FTSENT **, const FTSENT **)) +{ + FTS *sp; + FTSENT *p, *root; + int nitems; + FTSENT *parent, *tmp; + + /* Options check. */ + if (options & ~FTS_OPTIONMASK) { + errno = EINVAL; + return (NULL); + } + + /* At least one path must be specified. */ + if (*argv == NULL) { + errno = EINVAL; + return (NULL); + } + + /* Allocate/initialize the stream */ + if ((sp = calloc(1, sizeof(FTS))) == NULL) + return (NULL); + sp->fts_compar = compar; + sp->fts_options = options; + + /* + * Start out with 1K of path space, and enough, in any case, + * to hold the user's paths. + */ + if (fts_palloc(sp, MAXIMUM(fts_maxarglen(argv), PATH_MAX))) + goto mem1; + + /* Allocate/initialize root's parent. */ + if ((parent = fts_alloc(sp, "", 0)) == NULL) + goto mem2; + parent->fts_level = FTS_ROOTPARENTLEVEL; + + /* Allocate/initialize root(s). */ + for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) { + if ((p = fts_alloc(sp, *argv, strlen(*argv))) == NULL) + goto mem3; + p->fts_level = FTS_ROOTLEVEL; + p->fts_parent = parent; + p->fts_accpath = p->fts_name; + p->fts_info = fts_stat(sp, p); + + /* Command-line "." and ".." are real directories. */ + if (p->fts_info == FTS_DOT) + p->fts_info = FTS_D; + + /* + * If comparison routine supplied, traverse in sorted + * order; otherwise traverse in the order specified. + */ + if (compar) { + p->fts_link = root; + root = p; + } else { + p->fts_link = NULL; + if (root == NULL) + tmp = root = p; + else { + tmp->fts_link = p; + tmp = p; + } + } + } + if (compar && nitems > 1) + root = fts_sort(sp, root, nitems); + + /* + * Allocate a dummy pointer and make fts_read think that we've just + * finished the node before the root(s); set p->fts_info to FTS_INIT + * so that everything about the "current" node is ignored. + */ + if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) + goto mem3; + sp->fts_cur->fts_link = root; + sp->fts_cur->fts_info = FTS_INIT; + + if (nitems == 0) + free(parent); + + return (sp); + +mem3: fts_lfree(root); + free(parent); +mem2: free(sp->fts_path); +mem1: free(sp); + return (NULL); +} + +static void +fts_load(FTS *sp, FTSENT *p) +{ + size_t len; + char *cp; + + /* + * Load the stream structure for the next traversal. Since we don't + * actually enter the directory until after the preorder visit, set + * the fts_accpath field specially so the chdir gets done to the right + * place and the user can access the first node. From fts_open it's + * known that the path will fit. + */ + len = p->fts_pathlen = p->fts_namelen; + memmove(sp->fts_path, p->fts_name, len + 1); + if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { + len = strlen(++cp); + memmove(p->fts_name, cp, len + 1); + p->fts_namelen = len; + } + p->fts_accpath = p->fts_path = sp->fts_path; + sp->fts_dev = p->fts_dev; +} + +int +fts_close(FTS *sp) +{ + FTSENT *freep, *p; + + /* + * This still works if we haven't read anything -- the dummy structure + * points to the root list, so we step through to the end of the root + * list which has a valid parent pointer. + */ + if (sp->fts_cur) { + for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { + freep = p; + p = p->fts_link ? p->fts_link : p->fts_parent; + free(freep); + } + free(p); + } + + /* Free up child linked list, sort array, path buffer, stream ptr.*/ + if (sp->fts_child) + fts_lfree(sp->fts_child); + free(sp->fts_array); + free(sp->fts_path); + free(sp); + + return (0); +} + +/* + * Special case of "/" at the end of the path so that slashes aren't + * appended which would cause paths to be written as "....//foo". + */ +#define NAPPEND(p) \ + (p->fts_path[p->fts_pathlen - 1] == '/' \ + ? p->fts_pathlen - 1 : p->fts_pathlen) + +FTSENT * +fts_read(FTS *sp) +{ + FTSENT *p, *tmp; + int instr; + char *t; + + /* If finished or unrecoverable error, return NULL. */ + if (sp->fts_cur == NULL || ISSET(FTS_STOP)) + return (NULL); + + /* Set current node pointer. */ + p = sp->fts_cur; + + /* Save and zero out user instructions. */ + instr = p->fts_instr; + p->fts_instr = FTS_NOINSTR; + + /* Directory in pre-order. */ + if (p->fts_info == FTS_D) { + /* If skipped or crossed mount point, do post-order visit. */ + if (instr == FTS_SKIP || + (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { + if (sp->fts_child) { + fts_lfree(sp->fts_child); + sp->fts_child = NULL; + } + p->fts_info = FTS_DP; + return (p); + } + + /* + * If haven't read do so. If the read fails, fts_build sets + * FTS_STOP or the fts_info field of the node. + */ + if (sp->fts_child) { + /* nothing */ + } else if ((sp->fts_child = fts_build(sp)) == NULL) { + if (ISSET(FTS_STOP)) + return (NULL); + return (p); + } + p = sp->fts_child; + sp->fts_child = NULL; + goto name; + } + + /* Move to the next node on this level. */ +next: tmp = p; + if ((p = p->fts_link)) { + free(tmp); + + /* + * If reached the top, return to the original directory (or + * the root of the tree), and load the paths for the next root. + */ + if (p->fts_level == FTS_ROOTLEVEL) { + fts_load(sp, p); + return (sp->fts_cur = p); + } + + /* + * User may have called fts_set on the node. If skipped, + * ignore. If followed, get a file descriptor so we can + * get back if necessary. + */ + if (p->fts_instr == FTS_SKIP) + goto next; + +name: t = sp->fts_path + NAPPEND(p->fts_parent); + *t++ = '/'; + memmove(t, p->fts_name, p->fts_namelen + 1); + return (sp->fts_cur = p); + } + + /* Move up to the parent node. */ + p = tmp->fts_parent; + free(tmp); + + if (p->fts_level == FTS_ROOTPARENTLEVEL) { + /* + * Done; free everything up and set errno to 0 so the user + * can distinguish between error and EOF. + */ + free(p); + errno = 0; + return (sp->fts_cur = NULL); + } + + /* NUL terminate the pathname. */ + sp->fts_path[p->fts_pathlen] = '\0'; + + p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; + return (sp->fts_cur = p); +} + +/* + * Fts_set takes the stream as an argument although it's not used in this + * implementation; it would be necessary if anyone wanted to add global + * semantics to fts using fts_set. An error return is allowed for similar + * reasons. + */ +int +fts_set(FTS *sp, FTSENT *p, int instr) +{ + if (instr && instr != FTS_NOINSTR && instr != FTS_SKIP) { + errno = EINVAL; + return (1); + } + p->fts_instr = instr; + return (0); +} + +/* + * This is the tricky part -- do not casually change *anything* in here. The + * idea is to build the linked list of entries that are used by fts_children + * and fts_read. There are lots of special cases. + * + * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is + * set and it's a physical walk (so that symbolic links can't be directories), + * we can do things quickly. First, if it's a 4.4BSD file system, the type + * of the file is in the directory entry. Otherwise, we assume that the number + * of subdirectories in a node is equal to the number of links to the parent. + * The former skips all stat calls. The latter skips stat calls in any leaf + * directories and for any files after the subdirectories in the directory have + * been found, cutting the stat calls by about 2/3. + */ +static FTSENT * +fts_build(FTS *sp) +{ + struct dirent *dp; + FTSENT *p, *head; + FTSENT *cur, *tail; + DIR *dirp; + void *oldaddr; + size_t dlen, len, maxlen; + int nitems, level, doadjust; + int saved_errno; + char *cp; + + /* Set current node pointer. */ + cur = sp->fts_cur; + + /* + * Open the directory for reading. If this fails, we're done. + * If being called from fts_read, set the fts_info field. + */ + if ((dirp = opendir(cur->fts_accpath)) == NULL) { + cur->fts_info = FTS_DNR; + cur->fts_errno = errno; + return (NULL); + } + + /* + * Figure out the max file name length that can be stored in the + * current path -- the inner loop allocates more path as necessary. + * We really wouldn't have to do the maxlen calculations here, we + * could do them in fts_read before returning the path, but it's a + * lot easier here since the length is part of the dirent structure. + * + * If not changing directories set a pointer so that can just append + * each new name into the path. + */ + len = NAPPEND(cur); + cp = sp->fts_path + len; + *cp++ = '/'; + len++; + maxlen = sp->fts_pathlen - len; + + /* + * fts_level is signed so we must prevent it from wrapping + * around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL. + */ + level = cur->fts_level; + if (level < FTS_MAXLEVEL) + level++; + + /* Read the directory, attaching each entry to the `link' pointer. */ + doadjust = 0; + for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { + if (ISDOT(dp->d_name)) + continue; + +#if HAVE_DIRENT_NAMLEN + dlen = dp->d_namlen; +#else + dlen = strlen(dp->d_name); +#endif + + if (!(p = fts_alloc(sp, dp->d_name, dlen))) + goto mem1; + if (dlen >= maxlen) { /* include space for NUL */ + oldaddr = sp->fts_path; + if (fts_palloc(sp, dlen + len + 1)) { + /* + * No more memory for path or structures. Save + * errno, free up the current structure and the + * structures already allocated. + */ +mem1: saved_errno = errno; + free(p); + fts_lfree(head); + (void)closedir(dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + errno = saved_errno; + return (NULL); + } + /* Did realloc() change the pointer? */ + if (oldaddr != sp->fts_path) { + doadjust = 1; + cp = sp->fts_path + len; + } + maxlen = sp->fts_pathlen - len; + } + + p->fts_level = level; + p->fts_parent = sp->fts_cur; + p->fts_pathlen = len + dlen; + if (p->fts_pathlen < len) { + /* + * If we wrap, free up the current structure and + * the structures already allocated, then error + * out with ENAMETOOLONG. + */ + free(p); + fts_lfree(head); + (void)closedir(dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + errno = ENAMETOOLONG; + return (NULL); + } + + /* Build a file name for fts_stat to stat. */ + p->fts_accpath = p->fts_path; + memmove(cp, p->fts_name, p->fts_namelen + 1); + /* Stat it. */ + p->fts_info = fts_stat(sp, p); + + /* We walk in directory order so "ls -f" doesn't get upset. */ + p->fts_link = NULL; + if (head == NULL) + head = tail = p; + else { + tail->fts_link = p; + tail = p; + } + ++nitems; + } + if (dirp) + (void)closedir(dirp); + + /* + * If realloc() changed the address of the path, adjust the + * addresses for the rest of the tree and the dir list. + */ + if (doadjust) + fts_padjust(sp, head); + + /* + * If not changing directories, reset the path back to original + * state. + */ + if (len == sp->fts_pathlen || nitems == 0) + --cp; + *cp = '\0'; + + /* If didn't find anything, return NULL. */ + if (!nitems) { + cur->fts_info = FTS_DP; + return (NULL); + } + + /* Sort the entries. */ + if (sp->fts_compar && nitems > 1) + head = fts_sort(sp, head, nitems); + return (head); +} + +static unsigned short +fts_stat(FTS *sp, FTSENT *p) +{ + FTSENT *t; + dev_t dev; + ino_t ino; + struct stat *sbp; + + /* If user needs stat info, stat buffer already allocated. */ + sbp = p->fts_statp; + + if (lstat(p->fts_accpath, sbp)) { + p->fts_errno = errno; + memset(sbp, 0, sizeof(struct stat)); + return (FTS_NS); + } + + if (S_ISDIR(sbp->st_mode)) { + /* + * Set the device/inode. Used to find cycles and check for + * crossing mount points. Also remember the link count, used + * in fts_build to limit the number of stat calls. It is + * understood that these fields are only referenced if fts_info + * is set to FTS_D. + */ + dev = p->fts_dev = sbp->st_dev; + ino = p->fts_ino = sbp->st_ino; + p->fts_nlink = sbp->st_nlink; + + if (ISDOT(p->fts_name)) + return (FTS_DOT); + + /* + * Cycle detection is done by brute force when the directory + * is first encountered. If the tree gets deep enough or the + * number of symbolic links to directories is high enough, + * something faster might be worthwhile. + */ + for (t = p->fts_parent; + t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) + if (ino == t->fts_ino && dev == t->fts_dev) { + p->fts_cycle = t; + return (FTS_DC); + } + return (FTS_D); + } + if (S_ISLNK(sbp->st_mode)) + return (FTS_SL); + if (S_ISREG(sbp->st_mode)) + return (FTS_F); + return (FTS_DEFAULT); +} + +static FTSENT * +fts_sort(FTS *sp, FTSENT *head, int nitems) +{ + FTSENT **ap, *p; + + /* + * Construct an array of pointers to the structures and call qsort(3). + * Reassemble the array in the order returned by qsort. If unable to + * sort for memory reasons, return the directory entries in their + * current order. Allocate enough space for the current needs plus + * 40 so don't realloc one entry at a time. + */ + if (nitems > sp->fts_nitems) { + struct _ftsent **a; + + sp->fts_nitems = nitems + 40; + if ((a = reallocarray(sp->fts_array, + sp->fts_nitems, sizeof(FTSENT *))) == NULL) { + free(sp->fts_array); + sp->fts_array = NULL; + sp->fts_nitems = 0; + return (head); + } + sp->fts_array = a; + } + for (ap = sp->fts_array, p = head; p; p = p->fts_link) + *ap++ = p; + qsort(sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar); + for (head = *(ap = sp->fts_array); --nitems; ++ap) + ap[0]->fts_link = ap[1]; + ap[0]->fts_link = NULL; + return (head); +} + +static FTSENT * +fts_alloc(FTS *sp, const char *name, size_t namelen) +{ + FTSENT *p; + size_t len; + + len = sizeof(FTSENT) + namelen; + if ((p = calloc(1, len)) == NULL) + return (NULL); + + p->fts_path = sp->fts_path; + p->fts_namelen = namelen; + p->fts_instr = FTS_NOINSTR; + p->fts_statp = malloc(sizeof(struct stat)); + if (p->fts_statp == NULL) { + free(p); + return (NULL); + } + memcpy(p->fts_name, name, namelen); + + return (p); +} + +static void +fts_lfree(FTSENT *head) +{ + FTSENT *p; + + /* Free a linked list of structures. */ + while ((p = head)) { + head = head->fts_link; + free(p); + } +} + +/* + * Allow essentially unlimited paths; find, rm, ls should all work on any tree. + * Most systems will allow creation of paths much longer than PATH_MAX, even + * though the kernel won't resolve them. Add the size (not just what's needed) + * plus 256 bytes so don't realloc the path 2 bytes at a time. + */ +static int +fts_palloc(FTS *sp, size_t more) +{ + char *p; + + /* + * Check for possible wraparound. + */ + more += 256; + if (sp->fts_pathlen + more < sp->fts_pathlen) { + free(sp->fts_path); + sp->fts_path = NULL; + errno = ENAMETOOLONG; + return (1); + } + sp->fts_pathlen += more; + p = realloc(sp->fts_path, sp->fts_pathlen); + if (p == NULL) { + free(sp->fts_path); + sp->fts_path = NULL; + return (1); + } + sp->fts_path = p; + return (0); +} + +/* + * When the path is realloc'd, have to fix all of the pointers in structures + * already returned. + */ +static void +fts_padjust(FTS *sp, FTSENT *head) +{ + FTSENT *p; + char *addr = sp->fts_path; + +#define ADJUST(p) { \ + if ((p)->fts_accpath != (p)->fts_name) { \ + (p)->fts_accpath = \ + (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ + } \ + (p)->fts_path = addr; \ +} + /* Adjust the current set of children. */ + for (p = sp->fts_child; p; p = p->fts_link) + ADJUST(p); + + /* Adjust the rest of the tree, including the current level. */ + for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { + ADJUST(p); + p = p->fts_link ? p->fts_link : p->fts_parent; + } +} + +static size_t +fts_maxarglen(char * const *argv) +{ + size_t len, max; + + for (max = 0; *argv; ++argv) + if ((len = strlen(*argv)) > max) + max = len; + return (max + 1); +} + +#endif Property changes on: vendor/mdocml/20170121/compat_fts.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/compat_fts.h =================================================================== --- vendor/mdocml/20170121/compat_fts.h (nonexistent) +++ vendor/mdocml/20170121/compat_fts.h (revision 312592) @@ -0,0 +1,105 @@ +/* $OpenBSD: fts.h,v 1.14 2012/12/05 23:19:57 deraadt Exp $ */ +/* $NetBSD: fts.h,v 1.7 2012/03/01 16:18:51 hans Exp $ */ + +/* + * Copyright (c) 1989, 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. + * + * @(#)fts.h 8.3 (Berkeley) 8/14/94 + */ + +#ifndef _FTS_H_ +#define _FTS_H_ + +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + size_t fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(); /* compare function */ + +#define FTS_NOCHDIR 0x0004 /* don't change directories */ +#define FTS_PHYSICAL 0x0010 /* physical walk */ +#define FTS_XDEV 0x0040 /* don't cross devices */ +#define FTS_OPTIONMASK 0x0054 /* valid user option mask */ + +#define FTS_STOP 0x2000 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + size_t fts_pathlen; /* strlen(fts_path) */ + size_t fts_namelen; /* strlen(fts_name) */ + + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ + +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 +#define FTS_MAXLEVEL 0x7fffffff + int fts_level; /* depth (-1 to N) */ + +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ + unsigned short fts_info; /* user flags for FTSENT structure */ + +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + unsigned short fts_instr; /* fts_set() instructions */ + + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + + +int fts_close(FTS *); +FTS *fts_open(char * const *, int, + int (*)(const FTSENT **, const FTSENT **)); +FTSENT *fts_read(FTS *); +int fts_set(FTS *, FTSENT *, int); + +#endif /* !_FTS_H_ */ Property changes on: vendor/mdocml/20170121/compat_fts.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/configure =================================================================== --- vendor/mdocml/20170121/configure (nonexistent) +++ vendor/mdocml/20170121/configure (revision 312592) @@ -0,0 +1,474 @@ +#!/bin/sh +# +# $Id: configure,v 1.55 2017/01/12 15:45:05 schwarze Exp $ +# +# Copyright (c) 2014, 2015, 2016 Ingo Schwarze +# +# 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. + +set -e + +[ -w config.log ] && mv config.log config.log.old +[ -w config.h ] && mv config.h config.h.old + +# Output file descriptor usage: +# 1 (stdout): config.h, Makefile.local +# 2 (stderr): original stderr, usually to the console +# 3: config.log + +exec 3> config.log +echo "config.log: writing..." + +# --- default settings ------------------------------------------------- +# Initialize all variables here, +# such that nothing can leak in from the environment. + +MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man" +OSNAME= +UTF8_LOCALE= + +CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | env -i make -sf -` +CFLAGS="-g -W -Wall -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings" +CFLAGS="${CFLAGS} -Wno-unused-parameter" +LDADD= +LDFLAGS= +LD_NANOSLEEP= +LD_OHASH= +STATIC="-static" + +BUILD_CGI=0 +INSTALL_LIBMANDOC=0 + +HAVE_DIRENT_NAMLEN= +HAVE_EFTYPE= +HAVE_ENDIAN= +HAVE_ERR= +HAVE_FTS= +HAVE_FTS_COMPARE_CONST= +HAVE_GETLINE= +HAVE_GETSUBOPT= +HAVE_ISBLANK= +HAVE_MKDTEMP= +HAVE_NANOSLEEP= +HAVE_NTOHL= +HAVE_OHASH= +HAVE_PATH_MAX= +HAVE_PLEDGE= +HAVE_PROGNAME= +HAVE_REALLOCARRAY= +HAVE_REWB_BSD= +HAVE_REWB_SYSV= +HAVE_SANDBOX_INIT= +HAVE_STRCASESTR= +HAVE_STRINGLIST= +HAVE_STRLCAT= +HAVE_STRLCPY= +HAVE_STRPTIME= +HAVE_STRSEP= +HAVE_STRTONUM= +HAVE_SYS_ENDIAN= +HAVE_VASPRINTF= +HAVE_WCHAR= + +PREFIX="/usr/local" +BINDIR= +SBINDIR= +INCLUDEDIR= +LIBDIR= +MANDIR= +HOMEBREWDIR= + +WWWPREFIX="/var/www" +HTDOCDIR= +CGIBINDIR= + +BINM_APROPOS="apropos" +BINM_MAKEWHATIS="makewhatis" +BINM_MAN="man" +BINM_SOELIM="soelim" +BINM_WHATIS="whatis" +MANM_MAN="man" +MANM_MANCONF="man.conf" +MANM_MDOC="mdoc" +MANM_ROFF="roff" +MANM_EQN="eqn" +MANM_TBL="tbl" + +INSTALL="install" +INSTALL_PROGRAM= +INSTALL_LIB= +INSTALL_MAN= +INSTALL_DATA= + +# --- manual settings from configure.local ----------------------------- + +if [ -r ./configure.local ]; then + echo "configure.local: reading..." 1>&2 + echo "configure.local: reading..." 1>&3 + cat ./configure.local 1>&3 + . ./configure.local +else + echo "configure.local: no (fully automatic configuration)" 1>&2 + echo "configure.local: no (fully automatic configuration)" 1>&3 +fi +echo 1>&3 + +# --- tests for config.h ---------------------------------------------- + +COMP="${CC} ${CFLAGS} -Wno-unused -Werror" + +# Check whether this HAVE_ setting is manually overridden. +# If yes, use the override, if no, do not decide anything yet. +# Arguments: lower-case test name, manual value +ismanual() { + [ -z "${3}" ] && return 1 + echo "${1}: manual (HAVE_${2}=${3})" 1>&2 + echo "${1}: manual (HAVE_${2}=${3})" 1>&3 + echo 1>&3 + return 0 +} + +# Run a single autoconfiguration test. +# In case of success, enable the feature. +# In case of failure, do not decide anything yet. +# Arguments: lower-case test name, upper-case test name, additional CFLAGS +singletest() { + cat 1>&3 << __HEREDOC__ +${1}${3}: testing... +${COMP} -o test-${1} test-${1}.c ${3} +__HEREDOC__ + + if ${COMP} -o "test-${1}" "test-${1}.c" ${3} 1>&3 2>&3; then + echo "${1}${3}: ${CC} succeeded" 1>&3 + else + echo "${1}${3}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + + if ./test-${1} 1>&3 2>&3; then + echo "${1}${3}: yes" 1>&2 + echo "${1}${3}: yes" 1>&3 + echo 1>&3 + eval HAVE_${2}=1 + rm "test-${1}" + return 0 + else + echo "${1}${3}: execution failed with $?" 1>&3 + echo 1>&3 + rm "test-${1}" + return 1 + fi +} + +# Run a complete autoconfiguration test, including the check for +# a manual override and disabling the feature on failure. +# Arguments: lower case name, upper case name, additional CFLAGS +runtest() { + eval _manual=\${HAVE_${2}} + ismanual "${1}" "${2}" "${_manual}" && return 0 + singletest "${1}" "${2}" "${3}" && return 0 + echo "${1}${3}: no" 1>&2 + eval HAVE_${2}=0 + return 1 +} + +# Select a UTF-8 locale. +get_locale() { + [ -n "${HAVE_WCHAR}" ] && [ "${HAVE_WCHAR}" -eq 0 ] && return 0 + ismanual UTF8_LOCALE UTF8_LOCALE "$UTF8_LOCALE" && return 0 + echo "UTF8_LOCALE: testing..." 1>&3 + UTF8_LOCALE=`locale -a | grep -i '^en_US\.UTF-*8$' | head -n 1` + if [ -z "${UTF8_LOCALE}" ]; then + UTF8_LOCALE=`locale -a | grep -i '\.UTF-*8' | head -n 1` + [ -n "${UTF8_LOCALE}" ] || return 1 + fi + echo "UTF8_LOCALE=${UTF8_LOCALE}" 1>&2 + echo "UTF8_LOCALE=${UTF8_LOCALE}" 1>&3 + echo 1>&3 + return 0; +} + + +# --- library functions --- +runtest dirent-namlen DIRENT_NAMLEN || true +runtest be32toh ENDIAN || true +runtest be32toh SYS_ENDIAN -DSYS_ENDIAN || true +runtest EFTYPE EFTYPE || true +runtest err ERR || true +runtest getline GETLINE || true +runtest getsubopt GETSUBOPT || true +runtest isblank ISBLANK || true +runtest mkdtemp MKDTEMP || true +runtest ntohl NTOHL || true +runtest PATH_MAX PATH_MAX || true +runtest pledge PLEDGE || true +runtest sandbox_init SANDBOX_INIT || true +runtest progname PROGNAME || true +runtest reallocarray REALLOCARRAY || true +runtest rewb-bsd REWB_BSD || true +runtest rewb-sysv REWB_SYSV || true +runtest strcasestr STRCASESTR || true +runtest stringlist STRINGLIST || true +runtest strlcat STRLCAT || true +runtest strlcpy STRLCPY || true +runtest strptime STRPTIME || true +runtest strsep STRSEP || true +runtest strtonum STRTONUM || true +runtest vasprintf VASPRINTF || true + +if [ ${HAVE_ENDIAN} -eq 0 -a \ + ${HAVE_SYS_ENDIAN} -eq 0 -a \ + ${HAVE_NTOHL} -eq 0 ]; then + echo "FATAL: no endian conversion functions found" 1>&2 + echo "FATAL: no endian conversion functions found" 1>&3 + exit 1 +fi + +if ismanual fts FTS ${HAVE_FTS}; then + HAVE_FTS_COMPARE_CONST=0 +elif runtest fts FTS_COMPARE_CONST -DFTS_COMPARE_CONST; then + HAVE_FTS=1 +else + runtest fts FTS || true +fi + +# --- wide character and locale support --- +if get_locale; then + runtest wchar WCHAR -DUTF8_LOCALE=\"${UTF8_LOCALE}\" || true +else + HAVE_WCHAR=0 + echo "wchar: no (no UTF8_LOCALE)" 1>&2 + echo "wchar: no (no UTF8_LOCALE)" 1>&3 +fi + +# --- nanosleep --- +if [ -n "${LD_NANOSLEEP}" ]; then + runtest nanosleep NANOSLEEP "${LD_NANOSLEEP}" || true +elif singletest nanosleep NANOSLEEP; then + : +elif runtest nanosleep NANOSLEEP "-lrt"; then + LD_NANOSLEEP="-lrt" +fi +if [ "${HAVE_NANOSLEEP}" -eq 0 ]; then + echo "FATAL: nanosleep: no" 1>&2 + echo "FATAL: nanosleep: no" 1>&3 + exit 1 +fi + +# --- ohash --- +if ismanual ohash OHASH "${HAVE_OHASH}"; then + : +elif [ -n "${LD_OHASH}" ]; then + runtest ohash OHASH "${LD_OHASH}" || true +elif singletest ohash OHASH; then + : +elif runtest ohash OHASH "-lutil"; then + LD_OHASH="-lutil" +fi +if [ "${HAVE_OHASH}" -eq 0 ]; then + LD_OHASH= +fi + +# --- LDADD --- +LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_OHASH} -lz" +echo "LDADD=\"${LDADD}\"" 1>&2 +echo "LDADD=\"${LDADD}\"" 1>&3 +echo 1>&3 + +# --- write config.h --- + +exec > config.h + +cat << __HEREDOC__ +#ifdef __cplusplus +#error "Do not use C++. See the INSTALL file." +#endif + +#if !defined(__GNUC__) || (__GNUC__ < 4) +#define __attribute__(x) +#endif + +#if defined(__linux__) || defined(__MINT__) +#define _GNU_SOURCE /* See test-*.c what needs this. */ +#endif + +__HEREDOC__ + +[ ${HAVE_GETLINE} -eq 0 -o ${HAVE_REALLOCARRAY} -eq 0 -o \ + ${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \ + && echo "#include " +[ ${HAVE_VASPRINTF} -eq 0 ] && echo "#include " +[ ${HAVE_GETLINE} -eq 0 ] && echo "#include " + +echo +echo "#define MAN_CONF_FILE \"/etc/${MANM_MANCONF}\"" +echo "#define MANPATH_DEFAULT \"${MANPATH_DEFAULT}\"" +[ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\"" +[ -n "${UTF8_LOCALE}" ] && echo "#define UTF8_LOCALE \"${UTF8_LOCALE}\"" +[ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\"" +[ ${HAVE_EFTYPE} -eq 0 ] && echo "#define EFTYPE EINVAL" +[ ${HAVE_PATH_MAX} -eq 0 ] && echo "#define PATH_MAX 4096" +if [ ${HAVE_ENDIAN} -eq 0 -a ${HAVE_SYS_ENDIAN} -eq 0 ]; then + echo "#define be32toh ntohl" + echo "#define htobe32 htonl" +fi + +cat << __HEREDOC__ +#define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN} +#define HAVE_ENDIAN ${HAVE_ENDIAN} +#define HAVE_ERR ${HAVE_ERR} +#define HAVE_FTS ${HAVE_FTS} +#define HAVE_FTS_COMPARE_CONST ${HAVE_FTS_COMPARE_CONST} +#define HAVE_GETLINE ${HAVE_GETLINE} +#define HAVE_GETSUBOPT ${HAVE_GETSUBOPT} +#define HAVE_ISBLANK ${HAVE_ISBLANK} +#define HAVE_MKDTEMP ${HAVE_MKDTEMP} +#define HAVE_NTOHL ${HAVE_NTOHL} +#define HAVE_PLEDGE ${HAVE_PLEDGE} +#define HAVE_PROGNAME ${HAVE_PROGNAME} +#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY} +#define HAVE_REWB_BSD ${HAVE_REWB_BSD} +#define HAVE_REWB_SYSV ${HAVE_REWB_SYSV} +#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT} +#define HAVE_STRCASESTR ${HAVE_STRCASESTR} +#define HAVE_STRINGLIST ${HAVE_STRINGLIST} +#define HAVE_STRLCAT ${HAVE_STRLCAT} +#define HAVE_STRLCPY ${HAVE_STRLCPY} +#define HAVE_STRPTIME ${HAVE_STRPTIME} +#define HAVE_STRSEP ${HAVE_STRSEP} +#define HAVE_STRTONUM ${HAVE_STRTONUM} +#define HAVE_SYS_ENDIAN ${HAVE_SYS_ENDIAN} +#define HAVE_VASPRINTF ${HAVE_VASPRINTF} +#define HAVE_WCHAR ${HAVE_WCHAR} +#define HAVE_OHASH ${HAVE_OHASH} + +#define BINM_APROPOS "${BINM_APROPOS}" +#define BINM_MAKEWHATIS "${BINM_MAKEWHATIS}" +#define BINM_MAN "${BINM_MAN}" +#define BINM_SOELIM "${BINM_SOELIM}" +#define BINM_WHATIS "${BINM_WHATIS}" + +__HEREDOC__ + +if [ ${HAVE_ERR} -eq 0 ]; then + echo "extern void err(int, const char *, ...);" + echo "extern void errx(int, const char *, ...);" + echo "extern void warn(const char *, ...);" + echo "extern void warnx(const char *, ...);" +fi + +[ ${HAVE_GETLINE} -eq 0 ] && \ + echo "extern ssize_t getline(char **, size_t *, FILE *);" + +[ ${HAVE_GETSUBOPT} -eq 0 ] && \ + echo "extern int getsubopt(char **, char * const *, char **);" + +[ ${HAVE_ISBLANK} -eq 0 ] && \ + echo "extern int isblank(int);" + +[ ${HAVE_MKDTEMP} -eq 0 ] && \ + echo "extern char *mkdtemp(char *);" + +if [ ${HAVE_PROGNAME} -eq 0 ]; then + echo "extern const char *getprogname(void);" + echo "extern void setprogname(const char *);" +fi + +[ ${HAVE_REALLOCARRAY} -eq 0 ] && \ + echo "extern void *reallocarray(void *, size_t, size_t);" + +[ ${HAVE_STRCASESTR} -eq 0 ] && \ + echo "extern char *strcasestr(const char *, const char *);" + +[ ${HAVE_STRLCAT} -eq 0 ] && \ + echo "extern size_t strlcat(char *, const char *, size_t);" + +[ ${HAVE_STRLCPY} -eq 0 ] && \ + echo "extern size_t strlcpy(char *, const char *, size_t);" + +[ ${HAVE_STRSEP} -eq 0 ] && \ + echo "extern char *strsep(char **, const char *);" + +[ ${HAVE_STRTONUM} -eq 0 ] && \ + echo "extern long long strtonum(const char *, long long, long long, const char **);" + +[ ${HAVE_VASPRINTF} -eq 0 ] && \ + echo "extern int vasprintf(char **, const char *, va_list);" + +echo "config.h: written" 1>&2 +echo "config.h: written" 1>&3 + +# --- tests for Makefile.local ----------------------------------------- + +exec > Makefile.local + +[ -z "${BINDIR}" ] && BINDIR="${PREFIX}/bin" +[ -z "${SBINDIR}" ] && SBINDIR="${PREFIX}/sbin" +[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include/mandoc" +[ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib/mandoc" +[ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man" + +[ -z "${HTDOCDIR}" ] && HTDOCDIR="${WWWPREFIX}/htdocs" +[ -z "${CGIBINDIR}" ] && CGIBINDIR="${WWWPREFIX}/cgi-bin" + +[ -z "${INSTALL_PROGRAM}" ] && INSTALL_PROGRAM="${INSTALL} -m 0555" +[ -z "${INSTALL_LIB}" ] && INSTALL_LIB="${INSTALL} -m 0444" +[ -z "${INSTALL_MAN}" ] && INSTALL_MAN="${INSTALL} -m 0444" +[ -z "${INSTALL_DATA}" ] && INSTALL_DATA="${INSTALL} -m 0444" + +BUILD_TARGETS= +[ ${BUILD_CGI} -gt 0 ] && BUILD_TARGETS="cgi-build" +INSTALL_TARGETS= +[ ${INSTALL_LIBMANDOC} -gt 0 ] && INSTALL_TARGETS="lib-install" +[ ${BUILD_CGI} -gt 0 ] && INSTALL_TARGETS="${INSTALL_TARGETS} cgi-install" + +cat << __HEREDOC__ +BUILD_TARGETS = ${BUILD_TARGETS} +INSTALL_TARGETS = ${INSTALL_TARGETS} +CC = ${CC} +CFLAGS = ${CFLAGS} +LDADD = ${LDADD} +LDFLAGS = ${LDFLAGS} +STATIC = ${STATIC} +PREFIX = ${PREFIX} +BINDIR = ${BINDIR} +SBINDIR = ${SBINDIR} +INCLUDEDIR = ${INCLUDEDIR} +LIBDIR = ${LIBDIR} +MANDIR = ${MANDIR} +WWWPREFIX = ${WWWPREFIX} +HTDOCDIR = ${HTDOCDIR} +CGIBINDIR = ${CGIBINDIR} +BINM_APROPOS = ${BINM_APROPOS} +BINM_MAKEWHATIS = ${BINM_MAKEWHATIS} +BINM_MAN = ${BINM_MAN} +BINM_SOELIM = ${BINM_SOELIM} +BINM_WHATIS = ${BINM_WHATIS} +MANM_MAN = ${MANM_MAN} +MANM_MANCONF = ${MANM_MANCONF} +MANM_MDOC = ${MANM_MDOC} +MANM_ROFF = ${MANM_ROFF} +MANM_EQN = ${MANM_EQN} +MANM_TBL = ${MANM_TBL} +INSTALL = ${INSTALL} +INSTALL_PROGRAM = ${INSTALL_PROGRAM} +INSTALL_LIB = ${INSTALL_LIB} +INSTALL_MAN = ${INSTALL_MAN} +INSTALL_DATA = ${INSTALL_DATA} +__HEREDOC__ + +echo "Makefile.local: written" 1>&2 +echo "Makefile.local: written" 1>&3 + +exit 0 Property changes on: vendor/mdocml/20170121/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/mdocml/20170121/configure.local.example =================================================================== --- vendor/mdocml/20170121/configure.local.example (nonexistent) +++ vendor/mdocml/20170121/configure.local.example (revision 312592) @@ -0,0 +1,269 @@ +# $Id: configure.local.example,v 1.22 2016/11/19 15:24:51 schwarze Exp $ +# +# Copyright (c) 2014, 2015, 2016 Ingo Schwarze +# +# 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. + +# For all settings documented in this file, there are reasonable +# defaults and/or the ./configure script attempts autodetection. +# Consequently, you only need to create a file ./configure.local +# and put any of these settings into it if ./configure autodetection +# fails or if you want to make different choices for other reasons. + +# If autodetection fails, please tell . + +# We recommend that you write ./configure.local from scratch and +# only put the lines there you need. This file contains examples. +# It is not intended as a template to be copied as a whole. + +# --- user settings relevant for all builds ---------------------------- + +# For -Tutf8 and -Tlocale operation, mandoc(1) requires +# providing setlocale(3) and providing wcwidth(3) and +# putwchar(3) with a wchar_t storing UCS-4 values. Theoretically, +# the latter should be tested with the __STDC_ISO_10646__ feature +# macro. In practice, many headers do not provide that +# macro even though they treat wchar_t as UCS-4. So the automatic +# test only checks that wchar_t is wide enough, that is, at least +# four bytes. + +# The following line forces multi-byte support. +# If your C library does not treat wchar_t as UCS-4, the UTF-8 output +# mode will print garbage. + +HAVE_WCHAR=1 + +# The following line disables multi-byte support. +# The output modes -Tutf8 and -Tlocale will be the same as -Tascii. + +HAVE_WCHAR=0 + +# For -Tutf8 mode, mandoc needs to set an arbitrary locale having +# a UTF-8 character set. If autodetection of a suitable locale +# fails or selects an undesirable locale, you can manually choose +# the locale for -Tutf8 mode: + +UTF8_LOCALE=en_US.UTF-8 + +# When man(1) or apropos(1) is called without -m and -M options, +# MANPATH is not set in the environment, and man.conf(5) is not +# available, manuals are searched for in the following directory +# trees by default. + +MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man" + +# In manual pages written in the mdoc(7) language, the operating system +# version is displayed in the page footer line. If an operating system +# is specified as an argument to the .Os macro, that is always used. +# If the .Os macro has no argument and an operation system is specified +# with the mandoc(1) -Ios= command line option, that is used. +# Otherwise, the uname(3) library function is called at runtime to find +# the name of the operating system. +# If you do not want uname(3) to be called but instead want a fixed +# string to be used, use the following line: + +OSNAME="OpenBSD 6.0" + +# The following installation directories are used. +# It is possible to set only one or a few of these variables, +# there is no need to copy the whole block. +# Even if you set PREFIX to something else, the other variables +# pick it up without copying them all over. + +PREFIX="/usr/local" +BINDIR="${PREFIX}/bin" +SBINDIR="${PREFIX}/sbin" +MANDIR="${PREFIX}/man" + +# Some distributions may want to avoid naming conflicts +# with the configuration files of other man(1) implementations. +# This changes the name of the installed section 5 manual page as well. +MANM_MANCONF="mandoc.conf" # default is "man.conf" + +# Some distributions may want to avoid naming conflicts among manuals. +# If you want to change the names of installed section 7 manual pages, +# the following alternative names are suggested. +# The suffix ".7" will automatically be appended. +# It is possible to set only one or a few of these variables, +# there is no need to copy the whole block. + +MANM_MAN="mandoc_man" # default is "man" +MANM_MDOC="mandoc_mdoc" # default is "mdoc" +MANM_ROFF="mandoc_roff" # default is "roff" +MANM_EQN="mandoc_eqn" # default is "eqn" +MANM_TBL="mandoc_tbl" # default is "tbl" + +# Some distributions may want to avoid naming conflicts with +# other man(1), apropos(1), makewhatis(8), or soelim(1) utilities. +# If you want to change the names of binary programs, +# the following alternative names are suggested. +# Using different names is possible as well. +# This changes the names of the installed section 1 and section 8 +# manual pages as well. +# It is possible to set only one or two of these variables, +# there is no need to copy the whole block. + +BINM_MAN=mman # default is "man" +BINM_APROPOS=mapropos # default is "apropos" +BINM_WHATIS=mwhatis # default is "whatis" +BINM_MAKEWHATIS=mandocdb # default is "makewhatis" +BINM_SOELIM=msoelim # default is "soelim" + +# Before falling back to the bundled version of the ohash(3) hashing +# library, autoconfiguration tries the following linker flag to +# link against your system version. If you do have ohash(3) on +# your system but it needs different linker flags, set the following +# variable to specify the required linker flags. + +LD_OHASH="-lutil" + +# When library autodetection decides to use -L/usr/local/lib, +# -I/usr/local/include is automatically added to CFLAGS. +# If you manually set LD_OHASH to something including -L/usr/local/lib, +# chances are you will also need the following line: + +CFLAGS="${CFLAGS} -I/usr/local/include" + +# Some platforms may need an additional linker flag for nanosleep(2). +# If none is needed or it is -lrt, it is autodetected. +# Otherwise, set the following variable. + +LD_NANOSLEEP="-lrt" + +# Some platforms might need additional linker flags to link against +# libmandoc that are not autodetected, though no such cases are +# currently known. + +LDADD="-lm" + +# Some systems may want to set additional linker flags for all the +# binaries, not only for those using libmandoc, for example for +# hardening options. + +LDFLAGS="-Wl,-z,relro" + +# It is possible to change the utility program used for installation +# and the modes files are installed with. The defaults are: + +INSTALL="install" +INSTALL_PROGRAM="${INSTALL} -m 0555" +INSTALL_LIB="${INSTALL} -m 0444" +INSTALL_MAN="${INSTALL} -m 0444" +INSTALL_DATA="${INSTALL} -m 0444" + +# When using the "homebrew" package manager on Mac OS X, the actual +# manuals are located in a so-called "cellar" and only symlinked +# into the manual trees. To allow mandoc to follow such symlinks, +# you have to specify the physical location of the cellar as returned +# by realpath(3), for example: + +PREFIX="/usr/local" +HOMEBREWDIR="${PREFIX}/Cellar" + +# --- user settings for the mandoc(3) library -------------------------- + +# By default, libmandoc.a is not installed. It is almost never needed +# because there is almost no non-mandoc software out there using this +# library. The one notable exception is NetBSD apropos(1). +# So, when building for the NetBSD base system - but not for NetBSD +# ports nor for pkgsrc! - you may want the following: + +INSTALL_LIBMANDOC=1 + +# The following settings are only used when INSTALL_LIBMANDOC is set. + +INCLUDEDIR="${PREFIX}/include/mandoc" +LIBDIR="${PREFIX}/lib/mandoc" + +# --- user settings related to man.cgi --------------------------------- + +# By default, building man.cgi(8) is disabled. To enable it, copy +# cgi.h.example to cgi.h, edit it, and use the following line. + +BUILD_CGI=1 + +# The remaining settings in this section are only relevant if BUILD_CGI +# is enabled. Otherwise, they have no effect either way. + +# By default, man.cgi(8) is linked statically. +# Some systems do not support static linking, for example Mac OS X. +# In that case, use the following line: + +STATIC= + +# Some systems, for example Linux, require -pthread for static linking: + +STATIC="-static -pthread" + +# Some directories. +# This works just like PREFIX, see above. + +WWWPREFIX="/var/www" +HTDOCDIR="${WWWPREFIX}/htdocs" +CGIBINDIR="${WWWPREFIX}/cgi-bin" + +# --- settings that rarely need to be touched -------------------------- + +# Do not set these variables unless you really need to. + +# You can manually override the compiler to be used. +# But that's rarely useful because ./configure asks your make(1) +# which compiler to use, and that answer will hardly be wrong. + +CC=cc + +# IBM AIX may need: + +CC=xlc + +# The default compiler flags are: + +CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings" + +# IBM AIX xlc does not support -W; in that case, please use: + +CFLAGS="-g" + +# In rare cases, it may be required to skip individual automatic tests. +# Each of the following variables can be set to 0 (test will not be run +# and will be regarded as failed) or 1 (test will not be run and will +# be regarded as successful). + +HAVE_DIRENT_NAMLEN=0 +HAVE_ENDIAN=0 +HAVE_EFTYPE=0 +HAVE_ERR=0 +HAVE_FTS=0 # Setting this implies HAVE_FTS_COMPARE_CONST=0. +HAVE_FTS_COMPARE_CONST=0 # Setting this implies HAVE_FTS=1. +HAVE_GETLINE=0 +HAVE_GETSUBOPT=0 +HAVE_ISBLANK=0 +HAVE_MKDTEMP=0 +HAVE_NTOHL=0 +HAVE_OHASH=0 +HAVE_PATH_MAX=0 +HAVE_PLEDGE=0 +HAVE_PROGNAME=0 +HAVE_REALLOCARRAY=0 +HAVE_REWB_BSD=0 +HAVE_REWB_SYSV=0 +HAVE_STRCASESTR=0 +HAVE_STRINGLIST=0 +HAVE_STRLCAT=0 +HAVE_STRLCPY=0 +HAVE_STRPTIME=0 +HAVE_STRSEP=0 +HAVE_STRTONUM=0 +HAVE_SYS_ENDIAN=0 +HAVE_VASPRINTF=0 +HAVE_WCHAR=0 Index: vendor/mdocml/20170121/dba.c =================================================================== --- vendor/mdocml/20170121/dba.c (nonexistent) +++ vendor/mdocml/20170121/dba.c (revision 312592) @@ -0,0 +1,508 @@ +/* $Id: dba.c,v 1.9 2017/01/15 15:28:55 schwarze Exp $ */ +/* + * Copyright (c) 2016, 2017 Ingo Schwarze + * + * 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. + * + * Allocation-based version of the mandoc database, for read-write access. + * The interface is defined in "dba.h". + */ +#include "config.h" + +#include +#if HAVE_ENDIAN +#include +#elif HAVE_SYS_ENDIAN +#include +#elif HAVE_NTOHL +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mandoc_ohash.h" +#include "mansearch.h" +#include "dba_write.h" +#include "dba_array.h" +#include "dba.h" + +struct macro_entry { + struct dba_array *pages; + char value[]; +}; + +static void *prepend(const char *, char); +static void dba_pages_write(struct dba_array *); +static int compare_names(const void *, const void *); +static int compare_strings(const void *, const void *); + +static struct macro_entry + *get_macro_entry(struct ohash *, const char *, int32_t); +static void dba_macros_write(struct dba_array *); +static void dba_macro_write(struct ohash *); +static int compare_entries(const void *, const void *); + + +/*** top-level functions **********************************************/ + +struct dba * +dba_new(int32_t npages) +{ + struct dba *dba; + struct ohash *macro; + int32_t im; + + dba = mandoc_malloc(sizeof(*dba)); + dba->pages = dba_array_new(npages, DBA_GROW); + dba->macros = dba_array_new(MACRO_MAX, 0); + for (im = 0; im < MACRO_MAX; im++) { + macro = mandoc_malloc(sizeof(*macro)); + mandoc_ohash_init(macro, 4, + offsetof(struct macro_entry, value)); + dba_array_set(dba->macros, im, macro); + } + return dba; +} + +void +dba_free(struct dba *dba) +{ + struct dba_array *page; + struct ohash *macro; + struct macro_entry *entry; + unsigned int slot; + + dba_array_FOREACH(dba->macros, macro) { + for (entry = ohash_first(macro, &slot); entry != NULL; + entry = ohash_next(macro, &slot)) { + dba_array_free(entry->pages); + free(entry); + } + ohash_delete(macro); + free(macro); + } + dba_array_free(dba->macros); + + dba_array_undel(dba->pages); + dba_array_FOREACH(dba->pages, page) { + dba_array_free(dba_array_get(page, DBP_NAME)); + dba_array_free(dba_array_get(page, DBP_SECT)); + dba_array_free(dba_array_get(page, DBP_ARCH)); + free(dba_array_get(page, DBP_DESC)); + dba_array_free(dba_array_get(page, DBP_FILE)); + dba_array_free(page); + } + dba_array_free(dba->pages); + + free(dba); +} + +/* + * Write the complete mandoc database to disk; the format is: + * - One integer each for magic and version. + * - One pointer each to the macros table and to the final magic. + * - The pages table. + * - The macros table. + * - And at the very end, the magic integer again. + */ +int +dba_write(const char *fname, struct dba *dba) +{ + int save_errno; + int32_t pos_end, pos_macros, pos_macros_ptr; + + if (dba_open(fname) == -1) + return -1; + dba_int_write(MANDOCDB_MAGIC); + dba_int_write(MANDOCDB_VERSION); + pos_macros_ptr = dba_skip(1, 2); + dba_pages_write(dba->pages); + pos_macros = dba_tell(); + dba_macros_write(dba->macros); + pos_end = dba_tell(); + dba_int_write(MANDOCDB_MAGIC); + dba_seek(pos_macros_ptr); + dba_int_write(pos_macros); + dba_int_write(pos_end); + if (dba_close() == -1) { + save_errno = errno; + unlink(fname); + errno = save_errno; + return -1; + } + return 0; +} + + +/*** functions for handling pages *************************************/ + +/* + * Create a new page and append it to the pages table. + */ +struct dba_array * +dba_page_new(struct dba_array *pages, const char *arch, + const char *desc, const char *file, enum form form) +{ + struct dba_array *page, *entry; + + page = dba_array_new(DBP_MAX, 0); + entry = dba_array_new(1, DBA_STR | DBA_GROW); + dba_array_add(page, entry); + entry = dba_array_new(1, DBA_STR | DBA_GROW); + dba_array_add(page, entry); + if (arch != NULL && *arch != '\0') { + entry = dba_array_new(1, DBA_STR | DBA_GROW); + dba_array_add(entry, (void *)arch); + } else + entry = NULL; + dba_array_add(page, entry); + dba_array_add(page, mandoc_strdup(desc)); + entry = dba_array_new(1, DBA_STR | DBA_GROW); + dba_array_add(entry, prepend(file, form)); + dba_array_add(page, entry); + dba_array_add(pages, page); + return page; +} + +/* + * Add a section, architecture, or file name to an existing page. + * Passing the NULL pointer for the architecture makes the page MI. + * In that case, any earlier or later architectures are ignored. + */ +void +dba_page_add(struct dba_array *page, int32_t ie, const char *str) +{ + struct dba_array *entries; + char *entry; + + entries = dba_array_get(page, ie); + if (ie == DBP_ARCH) { + if (entries == NULL) + return; + if (str == NULL || *str == '\0') { + dba_array_free(entries); + dba_array_set(page, DBP_ARCH, NULL); + return; + } + } + if (*str == '\0') + return; + dba_array_FOREACH(entries, entry) { + if (ie == DBP_FILE && *entry < ' ') + entry++; + if (strcmp(entry, str) == 0) + return; + } + dba_array_add(entries, (void *)str); +} + +/* + * Add an additional name to an existing page. + */ +void +dba_page_alias(struct dba_array *page, const char *name, uint64_t mask) +{ + struct dba_array *entries; + char *entry; + char maskbyte; + + if (*name == '\0') + return; + maskbyte = mask & NAME_MASK; + entries = dba_array_get(page, DBP_NAME); + dba_array_FOREACH(entries, entry) { + if (strcmp(entry + 1, name) == 0) { + *entry |= maskbyte; + return; + } + } + dba_array_add(entries, prepend(name, maskbyte)); +} + +/* + * Return a pointer to a temporary copy of instr with inbyte prepended. + */ +static void * +prepend(const char *instr, char inbyte) +{ + static char *outstr = NULL; + static size_t outlen = 0; + size_t newlen; + + newlen = strlen(instr) + 1; + if (newlen > outlen) { + outstr = mandoc_realloc(outstr, newlen + 1); + outlen = newlen; + } + *outstr = inbyte; + memcpy(outstr + 1, instr, newlen); + return outstr; +} + +/* + * Write the pages table to disk; the format is: + * - One integer containing the number of pages. + * - For each page, five pointers to the names, sections, + * architectures, description, and file names of the page. + * MI pages write 0 instead of the architecture pointer. + * - One list each for names, sections, architectures, descriptions and + * file names. The description for each page ends with a NUL byte. + * For all the other lists, each string ends with a NUL byte, + * and the last string for a page ends with two NUL bytes. + * - To assure alignment of following integers, + * the end is padded with NUL bytes up to a multiple of four bytes. + */ +static void +dba_pages_write(struct dba_array *pages) +{ + struct dba_array *page, *entry; + int32_t pos_pages, pos_end; + + pos_pages = dba_array_writelen(pages, 5); + dba_array_FOREACH(pages, page) { + dba_array_setpos(page, DBP_NAME, dba_tell()); + entry = dba_array_get(page, DBP_NAME); + dba_array_sort(entry, compare_names); + dba_array_writelst(entry); + } + dba_array_FOREACH(pages, page) { + dba_array_setpos(page, DBP_SECT, dba_tell()); + entry = dba_array_get(page, DBP_SECT); + dba_array_sort(entry, compare_strings); + dba_array_writelst(entry); + } + dba_array_FOREACH(pages, page) { + if ((entry = dba_array_get(page, DBP_ARCH)) != NULL) { + dba_array_setpos(page, DBP_ARCH, dba_tell()); + dba_array_sort(entry, compare_strings); + dba_array_writelst(entry); + } else + dba_array_setpos(page, DBP_ARCH, 0); + } + dba_array_FOREACH(pages, page) { + dba_array_setpos(page, DBP_DESC, dba_tell()); + dba_str_write(dba_array_get(page, DBP_DESC)); + } + dba_array_FOREACH(pages, page) { + dba_array_setpos(page, DBP_FILE, dba_tell()); + dba_array_writelst(dba_array_get(page, DBP_FILE)); + } + pos_end = dba_align(); + dba_seek(pos_pages); + dba_array_FOREACH(pages, page) + dba_array_writepos(page); + dba_seek(pos_end); +} + +static int +compare_names(const void *vp1, const void *vp2) +{ + const char *cp1, *cp2; + int diff; + + cp1 = *(char **)vp1; + cp2 = *(char **)vp2; + return (diff = *cp2 - *cp1) ? diff : + strcasecmp(cp1 + 1, cp2 + 1); +} + +static int +compare_strings(const void *vp1, const void *vp2) +{ + const char *cp1, *cp2; + + cp1 = *(char **)vp1; + cp2 = *(char **)vp2; + return strcmp(cp1, cp2); +} + +/*** functions for handling macros ************************************/ + +/* + * In the hash table for a single macro, look up an entry by + * the macro value or add an empty one if it doesn't exist yet. + */ +static struct macro_entry * +get_macro_entry(struct ohash *macro, const char *value, int32_t np) +{ + struct macro_entry *entry; + size_t len; + unsigned int slot; + + slot = ohash_qlookup(macro, value); + if ((entry = ohash_find(macro, slot)) == NULL) { + len = strlen(value) + 1; + entry = mandoc_malloc(sizeof(*entry) + len); + memcpy(&entry->value, value, len); + entry->pages = dba_array_new(np, DBA_GROW); + ohash_insert(macro, slot, entry); + } + return entry; +} + +/* + * In addition to get_macro_entry(), add multiple page references, + * converting them from the on-disk format (byte offsets in the file) + * to page pointers in memory. + */ +void +dba_macro_new(struct dba *dba, int32_t im, const char *value, + const int32_t *pp) +{ + struct macro_entry *entry; + const int32_t *ip; + int32_t np; + + np = 0; + for (ip = pp; *ip; ip++) + np++; + + entry = get_macro_entry(dba_array_get(dba->macros, im), value, np); + for (ip = pp; *ip; ip++) + dba_array_add(entry->pages, dba_array_get(dba->pages, + be32toh(*ip) / 5 / sizeof(*ip) - 1)); +} + +/* + * In addition to get_macro_entry(), add one page reference, + * directly taking the in-memory page pointer as an argument. + */ +void +dba_macro_add(struct dba_array *macros, int32_t im, const char *value, + struct dba_array *page) +{ + struct macro_entry *entry; + + if (*value == '\0') + return; + entry = get_macro_entry(dba_array_get(macros, im), value, 1); + dba_array_add(entry->pages, page); +} + +/* + * Write the macros table to disk; the format is: + * - The number of macro tables (actually, MACRO_MAX). + * - That number of pointers to the individual macro tables. + * - The individual macro tables. + */ +static void +dba_macros_write(struct dba_array *macros) +{ + struct ohash *macro; + int32_t im, pos_macros, pos_end; + + pos_macros = dba_array_writelen(macros, 1); + im = 0; + dba_array_FOREACH(macros, macro) { + dba_array_setpos(macros, im++, dba_tell()); + dba_macro_write(macro); + } + pos_end = dba_tell(); + dba_seek(pos_macros); + dba_array_writepos(macros); + dba_seek(pos_end); +} + +/* + * Write one individual macro table to disk; the format is: + * - The number of entries in the table. + * - For each entry, two pointers, the first one to the value + * and the second one to the list of pages. + * - A list of values, each ending in a NUL byte. + * - To assure alignment of following integers, + * padding with NUL bytes up to a multiple of four bytes. + * - A list of pointers to pages, each list ending in a 0 integer. + */ +static void +dba_macro_write(struct ohash *macro) +{ + struct macro_entry **entries, *entry; + struct dba_array *page; + int32_t *kpos, *dpos; + unsigned int ie, ne, slot; + int use; + int32_t addr, pos_macro, pos_end; + + /* Temporary storage for filtering and sorting. */ + + ne = ohash_entries(macro); + entries = mandoc_reallocarray(NULL, ne, sizeof(*entries)); + kpos = mandoc_reallocarray(NULL, ne, sizeof(*kpos)); + dpos = mandoc_reallocarray(NULL, ne, sizeof(*dpos)); + + /* Build a list of non-empty entries and sort it. */ + + ne = 0; + for (entry = ohash_first(macro, &slot); entry != NULL; + entry = ohash_next(macro, &slot)) { + use = 0; + dba_array_FOREACH(entry->pages, page) + if (dba_array_getpos(page)) + use = 1; + if (use) + entries[ne++] = entry; + } + qsort(entries, ne, sizeof(*entries), compare_entries); + + /* Number of entries, and space for the pointer pairs. */ + + dba_int_write(ne); + pos_macro = dba_skip(2, ne); + + /* String table. */ + + for (ie = 0; ie < ne; ie++) { + kpos[ie] = dba_tell(); + dba_str_write(entries[ie]->value); + } + dba_align(); + + /* Pages table. */ + + for (ie = 0; ie < ne; ie++) { + dpos[ie] = dba_tell(); + dba_array_FOREACH(entries[ie]->pages, page) + if ((addr = dba_array_getpos(page))) + dba_int_write(addr); + dba_int_write(0); + } + pos_end = dba_tell(); + + /* Fill in the pointer pairs. */ + + dba_seek(pos_macro); + for (ie = 0; ie < ne; ie++) { + dba_int_write(kpos[ie]); + dba_int_write(dpos[ie]); + } + dba_seek(pos_end); + + free(entries); + free(kpos); + free(dpos); +} + +static int +compare_entries(const void *vp1, const void *vp2) +{ + const struct macro_entry *ep1, *ep2; + + ep1 = *(struct macro_entry **)vp1; + ep2 = *(struct macro_entry **)vp2; + return strcmp(ep1->value, ep2->value); +} Property changes on: vendor/mdocml/20170121/dba.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba.h =================================================================== --- vendor/mdocml/20170121/dba.h (nonexistent) +++ vendor/mdocml/20170121/dba.h (revision 312592) @@ -0,0 +1,50 @@ +/* $Id: dba.h,v 1.2 2016/08/17 20:46:56 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Public interface of the allocation-based version + * of the mandoc database, for read-write access. + * To be used by dba.c, dba_read.c, and makewhatis(8). + */ + +#define DBP_NAME 0 +#define DBP_SECT 1 +#define DBP_ARCH 2 +#define DBP_DESC 3 +#define DBP_FILE 4 +#define DBP_MAX 5 + +struct dba_array; + +struct dba { + struct dba_array *pages; + struct dba_array *macros; +}; + + +struct dba *dba_new(int32_t); +void dba_free(struct dba *); +struct dba *dba_read(const char *); +int dba_write(const char *, struct dba *); + +struct dba_array *dba_page_new(struct dba_array *, const char *, + const char *, const char *, enum form); +void dba_page_add(struct dba_array *, int32_t, const char *); +void dba_page_alias(struct dba_array *, const char *, uint64_t); + +void dba_macro_new(struct dba *, int32_t, + const char *, const int32_t *); +void dba_macro_add(struct dba_array *, int32_t, + const char *, struct dba_array *); Property changes on: vendor/mdocml/20170121/dba.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba_array.c =================================================================== --- vendor/mdocml/20170121/dba_array.c (nonexistent) +++ vendor/mdocml/20170121/dba_array.c (revision 312592) @@ -0,0 +1,188 @@ +/* $Id: dba_array.c,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Allocation-based arrays for the mandoc database, for read-write access. + * The interface is defined in "dba_array.h". + */ +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "dba_write.h" +#include "dba_array.h" + +struct dba_array { + void **ep; /* Array of entries. */ + int32_t *em; /* Array of map positions. */ + int flags; + int32_t ea; /* Entries allocated. */ + int32_t eu; /* Entries used (including deleted). */ + int32_t ed; /* Entries deleted. */ + int32_t ec; /* Currently active entry. */ + int32_t pos; /* Map position of this array. */ +}; + + +struct dba_array * +dba_array_new(int32_t ea, int flags) +{ + struct dba_array *array; + + assert(ea > 0); + array = mandoc_malloc(sizeof(*array)); + array->ep = mandoc_reallocarray(NULL, ea, sizeof(*array->ep)); + array->em = mandoc_reallocarray(NULL, ea, sizeof(*array->em)); + array->ea = ea; + array->eu = 0; + array->ed = 0; + array->ec = 0; + array->flags = flags; + array->pos = 0; + return array; +} + +void +dba_array_free(struct dba_array *array) +{ + int32_t ie; + + if (array == NULL) + return; + if (array->flags & DBA_STR) + for (ie = 0; ie < array->eu; ie++) + free(array->ep[ie]); + free(array->ep); + free(array->em); + free(array); +} + +void +dba_array_set(struct dba_array *array, int32_t ie, void *entry) +{ + assert(ie >= 0); + assert(ie < array->ea); + assert(ie <= array->eu); + if (ie == array->eu) + array->eu++; + if (array->flags & DBA_STR) + entry = mandoc_strdup(entry); + array->ep[ie] = entry; + array->em[ie] = 0; +} + +void +dba_array_add(struct dba_array *array, void *entry) +{ + if (array->eu == array->ea) { + assert(array->flags & DBA_GROW); + array->ep = mandoc_reallocarray(array->ep, + 2, sizeof(*array->ep) * array->ea); + array->em = mandoc_reallocarray(array->em, + 2, sizeof(*array->em) * array->ea); + array->ea *= 2; + } + dba_array_set(array, array->eu, entry); +} + +void * +dba_array_get(struct dba_array *array, int32_t ie) +{ + if (ie < 0 || ie >= array->eu || array->em[ie] == -1) + return NULL; + return array->ep[ie]; +} + +void +dba_array_start(struct dba_array *array) +{ + array->ec = array->eu; +} + +void * +dba_array_next(struct dba_array *array) +{ + if (array->ec < array->eu) + array->ec++; + else + array->ec = 0; + while (array->ec < array->eu && array->em[array->ec] == -1) + array->ec++; + return array->ec < array->eu ? array->ep[array->ec] : NULL; +} + +void +dba_array_del(struct dba_array *array) +{ + if (array->ec < array->eu && array->em[array->ec] != -1) { + array->em[array->ec] = -1; + array->ed++; + } +} + +void +dba_array_undel(struct dba_array *array) +{ + memset(array->em, 0, sizeof(*array->em) * array->eu); +} + +void +dba_array_setpos(struct dba_array *array, int32_t ie, int32_t pos) +{ + array->em[ie] = pos; +} + +int32_t +dba_array_getpos(struct dba_array *array) +{ + return array->pos; +} + +void +dba_array_sort(struct dba_array *array, dba_compare_func func) +{ + assert(array->ed == 0); + qsort(array->ep, array->eu, sizeof(*array->ep), func); +} + +int32_t +dba_array_writelen(struct dba_array *array, int32_t nmemb) +{ + dba_int_write(array->eu - array->ed); + return dba_skip(nmemb, array->eu - array->ed); +} + +void +dba_array_writepos(struct dba_array *array) +{ + int32_t ie; + + array->pos = dba_tell(); + for (ie = 0; ie < array->eu; ie++) + if (array->em[ie] != -1) + dba_int_write(array->em[ie]); +} + +void +dba_array_writelst(struct dba_array *array) +{ + const char *str; + + dba_array_FOREACH(array, str) + dba_str_write(str); + dba_char_write('\0'); +} Property changes on: vendor/mdocml/20170121/dba_array.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba_array.h =================================================================== --- vendor/mdocml/20170121/dba_array.h (nonexistent) +++ vendor/mdocml/20170121/dba_array.h (revision 312592) @@ -0,0 +1,47 @@ +/* $Id: dba_array.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Public interface for allocation-based arrays + * for the mandoc database, for read-write access. + * To be used by dba*.c and by makewhatis(8). + */ + +struct dba_array; + +#define DBA_STR 0x01 /* Map contains strings, not pointers. */ +#define DBA_GROW 0x02 /* Allow the array to grow. */ + +#define dba_array_FOREACH(a, e) \ + dba_array_start(a); \ + while (((e) = dba_array_next(a)) != NULL) + +typedef int dba_compare_func(const void *, const void *); + +struct dba_array *dba_array_new(int32_t, int); +void dba_array_free(struct dba_array *); +void dba_array_set(struct dba_array *, int32_t, void *); +void dba_array_add(struct dba_array *, void *); +void *dba_array_get(struct dba_array *, int32_t); +void dba_array_start(struct dba_array *); +void *dba_array_next(struct dba_array *); +void dba_array_del(struct dba_array *); +void dba_array_undel(struct dba_array *); +void dba_array_setpos(struct dba_array *, int32_t, int32_t); +int32_t dba_array_getpos(struct dba_array *); +void dba_array_sort(struct dba_array *, dba_compare_func); +int32_t dba_array_writelen(struct dba_array *, int32_t); +void dba_array_writepos(struct dba_array *); +void dba_array_writelst(struct dba_array *); Property changes on: vendor/mdocml/20170121/dba_array.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba_read.c =================================================================== --- vendor/mdocml/20170121/dba_read.c (nonexistent) +++ vendor/mdocml/20170121/dba_read.c (revision 312592) @@ -0,0 +1,72 @@ +/* $Id: dba_read.c,v 1.4 2016/08/17 20:46:56 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Function to read the mandoc database from disk into RAM, + * such that data can be added or removed. + * The interface is defined in "dba.h". + * This file is seperate from dba.c because this also uses "dbm.h". + */ +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mansearch.h" +#include "dba_array.h" +#include "dba.h" +#include "dbm.h" + + +struct dba * +dba_read(const char *fname) +{ + struct dba *dba; + struct dba_array *page; + struct dbm_page *pdata; + struct dbm_macro *mdata; + const char *cp; + int32_t im, ip, iv, npages; + + if (dbm_open(fname) == -1) + return NULL; + npages = dbm_page_count(); + dba = dba_new(npages < 128 ? 128 : npages); + for (ip = 0; ip < npages; ip++) { + pdata = dbm_page_get(ip); + page = dba_page_new(dba->pages, pdata->arch, + pdata->desc, pdata->file + 1, *pdata->file); + for (cp = pdata->name; *cp != '\0'; cp = strchr(cp, '\0') + 1) + dba_page_add(page, DBP_NAME, cp); + for (cp = pdata->sect; *cp != '\0'; cp = strchr(cp, '\0') + 1) + dba_page_add(page, DBP_SECT, cp); + if ((cp = pdata->arch) != NULL) + while (*(cp = strchr(cp, '\0') + 1) != '\0') + dba_page_add(page, DBP_ARCH, cp); + cp = pdata->file; + while (*(cp = strchr(cp, '\0') + 1) != '\0') + dba_page_add(page, DBP_FILE, cp); + } + for (im = 0; im < MACRO_MAX; im++) { + for (iv = 0; iv < dbm_macro_count(im); iv++) { + mdata = dbm_macro_get(im, iv); + dba_macro_new(dba, im, mdata->value, mdata->pp); + } + } + dbm_close(); + return dba; +} Property changes on: vendor/mdocml/20170121/dba_read.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba_write.c =================================================================== --- vendor/mdocml/20170121/dba_write.c (nonexistent) +++ vendor/mdocml/20170121/dba_write.c (revision 312592) @@ -0,0 +1,127 @@ +/* $Id: dba_write.c,v 1.3 2016/08/05 23:15:08 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Low-level functions for serializing allocation-based data to disk. + * The interface is defined in "dba_write.h". + */ +#include "config.h" + +#include +#if HAVE_ENDIAN +#include +#elif HAVE_SYS_ENDIAN +#include +#elif HAVE_NTOHL +#include +#endif +#if HAVE_ERR +#include +#endif +#include +#include +#include +#include + +#include "dba_write.h" + +static FILE *ofp; + + +int +dba_open(const char *fname) +{ + ofp = fopen(fname, "w"); + return ofp == NULL ? -1 : 0; +} + +int +dba_close(void) +{ + return fclose(ofp) == EOF ? -1 : 0; +} + +int32_t +dba_tell(void) +{ + long pos; + + if ((pos = ftell(ofp)) == -1) + err(1, "ftell"); + if (pos >= INT32_MAX) { + errno = EOVERFLOW; + err(1, "ftell = %ld", pos); + } + return pos; +} + +void +dba_seek(int32_t pos) +{ + if (fseek(ofp, pos, SEEK_SET) == -1) + err(1, "fseek(%d)", pos); +} + +int32_t +dba_align(void) +{ + int32_t pos; + + pos = dba_tell(); + while (pos & 3) { + dba_char_write('\0'); + pos++; + } + return pos; +} + +int32_t +dba_skip(int32_t nmemb, int32_t sz) +{ + const int32_t out[5] = {0, 0, 0, 0, 0}; + int32_t i, pos; + + assert(sz >= 0); + assert(nmemb > 0); + assert(nmemb <= 5); + pos = dba_tell(); + for (i = 0; i < sz; i++) + if (nmemb - fwrite(&out, sizeof(out[0]), nmemb, ofp)) + err(1, "fwrite"); + return pos; +} + +void +dba_char_write(int c) +{ + if (putc(c, ofp) == EOF) + err(1, "fputc"); +} + +void +dba_str_write(const char *str) +{ + if (fputs(str, ofp) == EOF) + err(1, "fputs"); + dba_char_write('\0'); +} + +void +dba_int_write(int32_t i) +{ + i = htobe32(i); + if (fwrite(&i, sizeof(i), 1, ofp) != 1) + err(1, "fwrite"); +} Property changes on: vendor/mdocml/20170121/dba_write.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dba_write.h =================================================================== --- vendor/mdocml/20170121/dba_write.h (nonexistent) +++ vendor/mdocml/20170121/dba_write.h (revision 312592) @@ -0,0 +1,30 @@ +/* $Id: dba_write.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Internal interface to low-level functions + * for serializing allocation-based data to disk. + * For use by dba_array.c and dba.c only. + */ + +int dba_open(const char *); +int dba_close(void); +int32_t dba_tell(void); +void dba_seek(int32_t); +int32_t dba_align(void); +int32_t dba_skip(int32_t, int32_t); +void dba_char_write(int); +void dba_str_write(const char *); +void dba_int_write(int32_t); Property changes on: vendor/mdocml/20170121/dba_write.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dbm.c =================================================================== --- vendor/mdocml/20170121/dbm.c (nonexistent) +++ vendor/mdocml/20170121/dbm.c (revision 312592) @@ -0,0 +1,480 @@ +/* $Id: dbm.c,v 1.5 2016/10/18 22:27:25 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Map-based version of the mandoc database, for read-only access. + * The interface is defined in "dbm.h". + */ +#include "config.h" + +#include +#if HAVE_ENDIAN +#include +#elif HAVE_SYS_ENDIAN +#include +#elif HAVE_NTOHL +#include +#endif +#if HAVE_ERR +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "mansearch.h" +#include "dbm_map.h" +#include "dbm.h" + +struct macro { + int32_t value; + int32_t pages; +}; + +struct page { + int32_t name; + int32_t sect; + int32_t arch; + int32_t desc; + int32_t file; +}; + +enum iter { + ITER_NONE = 0, + ITER_NAME, + ITER_SECT, + ITER_ARCH, + ITER_DESC, + ITER_MACRO +}; + +static struct macro *macros[MACRO_MAX]; +static int32_t nvals[MACRO_MAX]; +static struct page *pages; +static int32_t npages; +static enum iter iteration; + +static struct dbm_res page_bytitle(enum iter, const struct dbm_match *); +static struct dbm_res page_byarch(const struct dbm_match *); +static struct dbm_res page_bymacro(int32_t, const struct dbm_match *); +static char *macro_bypage(int32_t, int32_t); + + +/*** top level functions **********************************************/ + +/* + * Open a disk-based mandoc database for read-only access. + * Map the pages and macros[] arrays. + * Return 0 on success. Return -1 and set errno on failure. + */ +int +dbm_open(const char *fname) +{ + const int32_t *mp, *ep; + int32_t im; + + if (dbm_map(fname) == -1) + return -1; + + if ((npages = be32toh(*dbm_getint(4))) < 0) { + warnx("dbm_open(%s): Invalid number of pages: %d", + fname, npages); + goto fail; + } + pages = (struct page *)dbm_getint(5); + + if ((mp = dbm_get(*dbm_getint(2))) == NULL) { + warnx("dbm_open(%s): Invalid offset of macros array", fname); + goto fail; + } + if (be32toh(*mp) != MACRO_MAX) { + warnx("dbm_open(%s): Invalid number of macros: %d", + fname, be32toh(*mp)); + goto fail; + } + for (im = 0; im < MACRO_MAX; im++) { + if ((ep = dbm_get(*++mp)) == NULL) { + warnx("dbm_open(%s): Invalid offset of macro %d", + fname, im); + goto fail; + } + nvals[im] = be32toh(*ep); + macros[im] = (struct macro *)++ep; + } + return 0; + +fail: + dbm_unmap(); + errno = EFTYPE; + return -1; +} + +void +dbm_close(void) +{ + dbm_unmap(); +} + + +/*** functions for handling pages *************************************/ + +int32_t +dbm_page_count(void) +{ + return npages; +} + +/* + * Give the caller pointers to the data for one manual page. + */ +struct dbm_page * +dbm_page_get(int32_t ip) +{ + static struct dbm_page res; + + assert(ip >= 0); + assert(ip < npages); + res.name = dbm_get(pages[ip].name); + if (res.name == NULL) + res.name = "(NULL)"; + res.sect = dbm_get(pages[ip].sect); + if (res.sect == NULL) + res.sect = "(NULL)"; + res.arch = pages[ip].arch ? dbm_get(pages[ip].arch) : NULL; + res.desc = dbm_get(pages[ip].desc); + if (res.desc == NULL) + res.desc = "(NULL)"; + res.file = dbm_get(pages[ip].file); + if (res.file == NULL) + res.file = " (NULL)"; + res.addr = dbm_addr(pages + ip); + return &res; +} + +/* + * Functions to start filtered iterations over manual pages. + */ +void +dbm_page_byname(const struct dbm_match *match) +{ + assert(match != NULL); + page_bytitle(ITER_NAME, match); +} + +void +dbm_page_bysect(const struct dbm_match *match) +{ + assert(match != NULL); + page_bytitle(ITER_SECT, match); +} + +void +dbm_page_byarch(const struct dbm_match *match) +{ + assert(match != NULL); + page_byarch(match); +} + +void +dbm_page_bydesc(const struct dbm_match *match) +{ + assert(match != NULL); + page_bytitle(ITER_DESC, match); +} + +void +dbm_page_bymacro(int32_t im, const struct dbm_match *match) +{ + assert(im >= 0); + assert(im < MACRO_MAX); + assert(match != NULL); + page_bymacro(im, match); +} + +/* + * Return the number of the next manual page in the current iteration. + */ +struct dbm_res +dbm_page_next(void) +{ + struct dbm_res res = {-1, 0}; + + switch(iteration) { + case ITER_NONE: + return res; + case ITER_ARCH: + return page_byarch(NULL); + case ITER_MACRO: + return page_bymacro(0, NULL); + default: + return page_bytitle(iteration, NULL); + } +} + +/* + * Functions implementing the iteration over manual pages. + */ +static struct dbm_res +page_bytitle(enum iter arg_iter, const struct dbm_match *arg_match) +{ + static const struct dbm_match *match; + static const char *cp; + static int32_t ip; + struct dbm_res res = {-1, 0}; + + assert(arg_iter == ITER_NAME || arg_iter == ITER_DESC || + arg_iter == ITER_SECT); + + /* Initialize for a new iteration. */ + + if (arg_match != NULL) { + iteration = arg_iter; + match = arg_match; + switch (iteration) { + case ITER_NAME: + cp = dbm_get(pages[0].name); + break; + case ITER_SECT: + cp = dbm_get(pages[0].sect); + break; + case ITER_DESC: + cp = dbm_get(pages[0].desc); + break; + default: + abort(); + } + if (cp == NULL) { + iteration = ITER_NONE; + match = NULL; + cp = NULL; + ip = npages; + } else + ip = 0; + return res; + } + + /* Search for a name. */ + + while (ip < npages) { + if (iteration == ITER_NAME) + cp++; + if (dbm_match(match, cp)) + break; + cp = strchr(cp, '\0') + 1; + if (iteration == ITER_DESC) + ip++; + else if (*cp == '\0') { + cp++; + ip++; + } + } + + /* Reached the end without a match. */ + + if (ip == npages) { + iteration = ITER_NONE; + match = NULL; + cp = NULL; + return res; + } + + /* Found a match; save the quality for later retrieval. */ + + res.page = ip; + res.bits = iteration == ITER_NAME ? cp[-1] : 0; + + /* Skip the remaining names of this page. */ + + if (++ip < npages) { + do { + cp++; + } while (cp[-1] != '\0' || + (iteration != ITER_DESC && cp[-2] != '\0')); + } + return res; +} + +static struct dbm_res +page_byarch(const struct dbm_match *arg_match) +{ + static const struct dbm_match *match; + struct dbm_res res = {-1, 0}; + static int32_t ip; + const char *cp; + + /* Initialize for a new iteration. */ + + if (arg_match != NULL) { + iteration = ITER_ARCH; + match = arg_match; + ip = 0; + return res; + } + + /* Search for an architecture. */ + + for ( ; ip < npages; ip++) + if (pages[ip].arch) + for (cp = dbm_get(pages[ip].arch); + *cp != '\0'; + cp = strchr(cp, '\0') + 1) + if (dbm_match(match, cp)) { + res.page = ip++; + return res; + } + + /* Reached the end without a match. */ + + iteration = ITER_NONE; + match = NULL; + return res; +} + +static struct dbm_res +page_bymacro(int32_t arg_im, const struct dbm_match *arg_match) +{ + static const struct dbm_match *match; + static const int32_t *pp; + static const char *cp; + static int32_t im, iv; + struct dbm_res res = {-1, 0}; + + assert(im >= 0); + assert(im < MACRO_MAX); + + /* Initialize for a new iteration. */ + + if (arg_match != NULL) { + iteration = ITER_MACRO; + match = arg_match; + im = arg_im; + cp = nvals[im] ? dbm_get(macros[im]->value) : NULL; + pp = NULL; + iv = -1; + return res; + } + if (iteration != ITER_MACRO) + return res; + + /* Find the next matching macro value. */ + + while (pp == NULL || *pp == 0) { + if (++iv == nvals[im]) { + iteration = ITER_NONE; + return res; + } + if (iv) + cp = strchr(cp, '\0') + 1; + if (dbm_match(match, cp)) + pp = dbm_get(macros[im][iv].pages); + } + + /* Found a matching page. */ + + res.page = (struct page *)dbm_get(*pp++) - pages; + return res; +} + + +/*** functions for handling macros ************************************/ + +int32_t +dbm_macro_count(int32_t im) +{ + assert(im >= 0); + assert(im < MACRO_MAX); + return nvals[im]; +} + +struct dbm_macro * +dbm_macro_get(int32_t im, int32_t iv) +{ + static struct dbm_macro macro; + + assert(im >= 0); + assert(im < MACRO_MAX); + assert(iv >= 0); + assert(iv < nvals[im]); + macro.value = dbm_get(macros[im][iv].value); + macro.pp = dbm_get(macros[im][iv].pages); + return ¯o; +} + +/* + * Filtered iteration over macro entries. + */ +void +dbm_macro_bypage(int32_t im, int32_t ip) +{ + assert(im >= 0); + assert(im < MACRO_MAX); + assert(ip != 0); + macro_bypage(im, ip); +} + +char * +dbm_macro_next(void) +{ + return macro_bypage(MACRO_MAX, 0); +} + +static char * +macro_bypage(int32_t arg_im, int32_t arg_ip) +{ + static const int32_t *pp; + static int32_t im, ip, iv; + + /* Initialize for a new iteration. */ + + if (arg_im < MACRO_MAX && arg_ip != 0) { + im = arg_im; + ip = arg_ip; + pp = dbm_get(macros[im]->pages); + iv = 0; + return NULL; + } + if (im >= MACRO_MAX) + return NULL; + + /* Search for the next value. */ + + while (iv < nvals[im]) { + if (*pp == ip) + break; + if (*pp == 0) + iv++; + pp++; + } + + /* Reached the end without a match. */ + + if (iv == nvals[im]) { + im = MACRO_MAX; + ip = 0; + pp = NULL; + return NULL; + } + + /* Found a match; skip the remaining pages of this entry. */ + + if (++iv < nvals[im]) + while (*pp++ != 0) + continue; + + return dbm_get(macros[im][iv - 1].value); +} Property changes on: vendor/mdocml/20170121/dbm.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dbm.h =================================================================== --- vendor/mdocml/20170121/dbm.h (nonexistent) +++ vendor/mdocml/20170121/dbm.h (revision 312592) @@ -0,0 +1,68 @@ +/* $Id: dbm.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Public interface for the map-based version + * of the mandoc database, for read-only access. + * To be used by dbm*.c, dba_read.c, and man(1) and apropos(1). + */ + +enum dbm_mtype { + DBM_EXACT = 0, + DBM_SUB, + DBM_REGEX +}; + +struct dbm_match { + regex_t *re; + const char *str; + enum dbm_mtype type; +}; + +struct dbm_res { + int32_t page; + int32_t bits; +}; + +struct dbm_page { + const char *name; + const char *sect; + const char *arch; + const char *desc; + const char *file; + int32_t addr; +}; + +struct dbm_macro { + const char *value; + const int32_t *pp; +}; + +int dbm_open(const char *); +void dbm_close(void); + +int32_t dbm_page_count(void); +struct dbm_page *dbm_page_get(int32_t); +void dbm_page_byname(const struct dbm_match *); +void dbm_page_bysect(const struct dbm_match *); +void dbm_page_byarch(const struct dbm_match *); +void dbm_page_bydesc(const struct dbm_match *); +void dbm_page_bymacro(int32_t, const struct dbm_match *); +struct dbm_res dbm_page_next(void); + +int32_t dbm_macro_count(int32_t); +struct dbm_macro *dbm_macro_get(int32_t, int32_t); +void dbm_macro_bypage(int32_t, int32_t); +char *dbm_macro_next(void); Property changes on: vendor/mdocml/20170121/dbm.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dbm_map.c =================================================================== --- vendor/mdocml/20170121/dbm_map.c (nonexistent) +++ vendor/mdocml/20170121/dbm_map.c (revision 312592) @@ -0,0 +1,194 @@ +/* $Id: dbm_map.c,v 1.7 2016/10/22 10:09:27 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Low-level routines for the map-based version + * of the mandoc database, for read-only access. + * The interface is defined in "dbm_map.h". + */ +#include "config.h" + +#include +#include +#include + +#if HAVE_ENDIAN +#include +#elif HAVE_SYS_ENDIAN +#include +#elif HAVE_NTOHL +#include +#endif +#if HAVE_ERR +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "mansearch.h" +#include "dbm_map.h" +#include "dbm.h" + +static struct stat st; +static char *dbm_base; +static int ifd; +static int32_t max_offset; + +/* + * Open a disk-based database for read-only access. + * Validate the file format as far as it is not mandoc-specific. + * Return 0 on success. Return -1 and set errno on failure. + */ +int +dbm_map(const char *fname) +{ + int save_errno; + const int32_t *magic; + + if ((ifd = open(fname, O_RDONLY)) == -1) + return -1; + if (fstat(ifd, &st) == -1) + goto fail; + if (st.st_size < 5) { + warnx("dbm_map(%s): File too short", fname); + errno = EFTYPE; + goto fail; + } + if (st.st_size > INT32_MAX) { + errno = EFBIG; + goto fail; + } + if ((dbm_base = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, + ifd, 0)) == MAP_FAILED) + goto fail; + magic = dbm_getint(0); + if (be32toh(*magic) != MANDOCDB_MAGIC) { + if (strncmp(dbm_base, "SQLite format 3", 15)) + warnx("dbm_map(%s): " + "Bad initial magic %x (expected %x)", + fname, be32toh(*magic), MANDOCDB_MAGIC); + else + warnx("dbm_map(%s): " + "Obsolete format based on SQLite 3", + fname); + errno = EFTYPE; + goto fail; + } + magic = dbm_getint(1); + if (be32toh(*magic) != MANDOCDB_VERSION) { + warnx("dbm_map(%s): Bad version number %d (expected %d)", + fname, be32toh(*magic), MANDOCDB_VERSION); + errno = EFTYPE; + goto fail; + } + max_offset = be32toh(*dbm_getint(3)) + sizeof(int32_t); + if (st.st_size != max_offset) { + warnx("dbm_map(%s): Inconsistent file size %lld (expected %d)", + fname, (long long)st.st_size, max_offset); + errno = EFTYPE; + goto fail; + } + if ((magic = dbm_get(*dbm_getint(3))) == NULL) { + errno = EFTYPE; + goto fail; + } + if (be32toh(*magic) != MANDOCDB_MAGIC) { + warnx("dbm_map(%s): Bad final magic %x (expected %x)", + fname, be32toh(*magic), MANDOCDB_MAGIC); + errno = EFTYPE; + goto fail; + } + return 0; + +fail: + save_errno = errno; + close(ifd); + errno = save_errno; + return -1; +} + +void +dbm_unmap(void) +{ + if (munmap(dbm_base, st.st_size) == -1) + warn("dbm_unmap: munmap"); + if (close(ifd) == -1) + warn("dbm_unmap: close"); + dbm_base = (char *)-1; +} + +/* + * Take a raw integer as it was read from the database. + * Interpret it as an offset into the database file + * and return a pointer to that place in the file. + */ +void * +dbm_get(int32_t offset) +{ + offset = be32toh(offset); + if (offset < 0) { + warnx("dbm_get: Database corrupt: offset %d", offset); + return NULL; + } + if (offset >= max_offset) { + warnx("dbm_get: Database corrupt: offset %d > %d", + offset, max_offset); + return NULL; + } + return dbm_base + offset; +} + +/* + * Assume the database starts with some integers. + * Assume they are numbered starting from 0, increasing. + * Get a pointer to one with the number "offset". + */ +int32_t * +dbm_getint(int32_t offset) +{ + return (int32_t *)dbm_base + offset; +} + +/* + * The reverse of dbm_get(). + * Take pointer into the database file + * and convert it to the raw integer + * that would be used to refer to that place in the file. + */ +int32_t +dbm_addr(const void *p) +{ + return htobe32((char *)p - dbm_base); +} + +int +dbm_match(const struct dbm_match *match, const char *str) +{ + switch (match->type) { + case DBM_EXACT: + return strcmp(str, match->str) == 0; + case DBM_SUB: + return strcasestr(str, match->str) != NULL; + case DBM_REGEX: + return regexec(match->re, str, 0, NULL, 0) == 0; + default: + abort(); + } +} Property changes on: vendor/mdocml/20170121/dbm_map.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/dbm_map.h =================================================================== --- vendor/mdocml/20170121/dbm_map.h (nonexistent) +++ vendor/mdocml/20170121/dbm_map.h (revision 312592) @@ -0,0 +1,29 @@ +/* $Id: dbm_map.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */ +/* + * Copyright (c) 2016 Ingo Schwarze + * + * 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. + * + * Private interface for low-level routines for the map-based version + * of the mandoc database, for read-only access. + * To be used by dbm*.c only. + */ + +struct dbm_match; + +int dbm_map(const char *); +void dbm_unmap(void); +void *dbm_get(int32_t); +int32_t *dbm_getint(int32_t); +int32_t dbm_addr(const void *); +int dbm_match(const struct dbm_match *, const char *); Property changes on: vendor/mdocml/20170121/dbm_map.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/demandoc.c =================================================================== --- vendor/mdocml/20170121/demandoc.c (nonexistent) +++ vendor/mdocml/20170121/demandoc.c (revision 312592) @@ -0,0 +1,263 @@ +/* $Id: demandoc.c,v 1.28 2017/01/10 13:47:00 schwarze Exp $ */ +/* + * Copyright (c) 2011 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "roff.h" +#include "man.h" +#include "mdoc.h" +#include "mandoc.h" + +static void pline(int, int *, int *, int); +static void pman(const struct roff_node *, int *, int *, int); +static void pmandoc(struct mparse *, int, const char *, int); +static void pmdoc(const struct roff_node *, int *, int *, int); +static void pstring(const char *, int, int *, int); +static void usage(void); + +static const char *progname; + +int +main(int argc, char *argv[]) +{ + struct mparse *mp; + int ch, fd, i, list; + extern int optind; + + if (argc < 1) + progname = "demandoc"; + else if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + ++progname; + + mp = NULL; + list = 0; + + while (-1 != (ch = getopt(argc, argv, "ikm:pw"))) + switch (ch) { + case ('i'): + /* FALLTHROUGH */ + case ('k'): + /* FALLTHROUGH */ + case ('m'): + /* FALLTHROUGH */ + case ('p'): + break; + case ('w'): + list = 1; + break; + default: + usage(); + return (int)MANDOCLEVEL_BADARG; + } + + argc -= optind; + argv += optind; + + mchars_alloc(); + mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, NULL); + assert(mp); + + if (argc < 1) + pmandoc(mp, STDIN_FILENO, " ", list); + + for (i = 0; i < argc; i++) { + mparse_reset(mp); + if ((fd = mparse_open(mp, argv[i])) == -1) { + perror(argv[i]); + continue; + } + pmandoc(mp, fd, argv[i], list); + } + + mparse_free(mp); + mchars_free(); + return (int)MANDOCLEVEL_OK; +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: %s [-w] [files...]\n", progname); +} + +static void +pmandoc(struct mparse *mp, int fd, const char *fn, int list) +{ + struct roff_man *man; + int line, col; + + mparse_readfd(mp, fd, fn); + close(fd); + mparse_result(mp, &man, NULL); + line = 1; + col = 0; + + if (man == NULL) + return; + if (man->macroset == MACROSET_MDOC) { + mdoc_validate(man); + pmdoc(man->first->child, &line, &col, list); + } else { + man_validate(man); + pman(man->first->child, &line, &col, list); + } + + if ( ! list) + putchar('\n'); +} + +/* + * Strip the escapes out of a string, emitting the results. + */ +static void +pstring(const char *p, int col, int *colp, int list) +{ + enum mandoc_esc esc; + const char *start, *end; + int emit; + + /* + * Print as many column spaces til we achieve parity with the + * input document. + */ + +again: + if (list && '\0' != *p) { + while (isspace((unsigned char)*p)) + p++; + + while ('\'' == *p || '(' == *p || '"' == *p) + p++; + + emit = isalpha((unsigned char)p[0]) && + isalpha((unsigned char)p[1]); + + for (start = p; '\0' != *p; p++) + if ('\\' == *p) { + p++; + esc = mandoc_escape(&p, NULL, NULL); + if (ESCAPE_ERROR == esc) + return; + emit = 0; + } else if (isspace((unsigned char)*p)) + break; + + end = p - 1; + + while (end > start) + if ('.' == *end || ',' == *end || + '\'' == *end || '"' == *end || + ')' == *end || '!' == *end || + '?' == *end || ':' == *end || + ';' == *end) + end--; + else + break; + + if (emit && end - start >= 1) { + for ( ; start <= end; start++) + if (ASCII_HYPH == *start) + putchar('-'); + else + putchar((unsigned char)*start); + putchar('\n'); + } + + if (isspace((unsigned char)*p)) + goto again; + + return; + } + + while (*colp < col) { + putchar(' '); + (*colp)++; + } + + /* + * Print the input word, skipping any special characters. + */ + while ('\0' != *p) + if ('\\' == *p) { + p++; + esc = mandoc_escape(&p, NULL, NULL); + if (ESCAPE_ERROR == esc) + break; + } else { + putchar((unsigned char )*p++); + (*colp)++; + } +} + +static void +pline(int line, int *linep, int *col, int list) +{ + + if (list) + return; + + /* + * Print out as many lines as needed to reach parity with the + * original input. + */ + + while (*linep < line) { + putchar('\n'); + (*linep)++; + } + + *col = 0; +} + +static void +pmdoc(const struct roff_node *p, int *line, int *col, int list) +{ + + for ( ; p; p = p->next) { + if (NODE_LINE & p->flags) + pline(p->line, line, col, list); + if (ROFFT_TEXT == p->type) + pstring(p->string, p->pos, col, list); + if (p->child) + pmdoc(p->child, line, col, list); + } +} + +static void +pman(const struct roff_node *p, int *line, int *col, int list) +{ + + for ( ; p; p = p->next) { + if (NODE_LINE & p->flags) + pline(p->line, line, col, list); + if (ROFFT_TEXT == p->type) + pstring(p->string, p->pos, col, list); + if (p->child) + pman(p->child, line, col, list); + } +} Property changes on: vendor/mdocml/20170121/demandoc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/eqn_html.c =================================================================== --- vendor/mdocml/20170121/eqn_html.c (nonexistent) +++ vendor/mdocml/20170121/eqn_html.c (revision 312592) @@ -0,0 +1,186 @@ +/* $Id: eqn_html.c,v 1.11 2017/01/17 01:47:51 schwarze Exp $ */ +/* + * Copyright (c) 2011, 2014 Kristaps Dzonsons + * Copyright (c) 2017 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include + +#include "mandoc.h" +#include "out.h" +#include "html.h" + +static void +eqn_box(struct html *p, const struct eqn_box *bp) +{ + struct tag *post, *row, *cell, *t; + const struct eqn_box *child, *parent; + size_t i, j, rows; + + if (NULL == bp) + return; + + post = NULL; + + /* + * Special handling for a matrix, which is presented to us in + * column order, but must be printed in row-order. + */ + if (EQN_MATRIX == bp->type) { + if (NULL == bp->first) + goto out; + if (EQN_LIST != bp->first->type) { + eqn_box(p, bp->first); + goto out; + } + if (NULL == (parent = bp->first->first)) + goto out; + /* Estimate the number of rows, first. */ + if (NULL == (child = parent->first)) + goto out; + for (rows = 0; NULL != child; rows++) + child = child->next; + /* Print row-by-row. */ + post = print_otag(p, TAG_MTABLE, ""); + for (i = 0; i < rows; i++) { + parent = bp->first->first; + row = print_otag(p, TAG_MTR, ""); + while (NULL != parent) { + child = parent->first; + for (j = 0; j < i; j++) { + if (NULL == child) + break; + child = child->next; + } + cell = print_otag(p, TAG_MTD, ""); + /* + * If we have no data for this + * particular cell, then print a + * placeholder and continue--don't puke. + */ + if (NULL != child) + eqn_box(p, child->first); + print_tagq(p, cell); + parent = parent->next; + } + print_tagq(p, row); + } + goto out; + } + + switch (bp->pos) { + case (EQNPOS_TO): + post = print_otag(p, TAG_MOVER, ""); + break; + case (EQNPOS_SUP): + post = print_otag(p, TAG_MSUP, ""); + break; + case (EQNPOS_FROM): + post = print_otag(p, TAG_MUNDER, ""); + break; + case (EQNPOS_SUB): + post = print_otag(p, TAG_MSUB, ""); + break; + case (EQNPOS_OVER): + post = print_otag(p, TAG_MFRAC, ""); + break; + case (EQNPOS_FROMTO): + post = print_otag(p, TAG_MUNDEROVER, ""); + break; + case (EQNPOS_SUBSUP): + post = print_otag(p, TAG_MSUBSUP, ""); + break; + case (EQNPOS_SQRT): + post = print_otag(p, TAG_MSQRT, ""); + break; + default: + break; + } + + if (bp->top || bp->bottom) { + assert(NULL == post); + if (bp->top && NULL == bp->bottom) + post = print_otag(p, TAG_MOVER, ""); + else if (bp->top && bp->bottom) + post = print_otag(p, TAG_MUNDEROVER, ""); + else if (bp->bottom) + post = print_otag(p, TAG_MUNDER, ""); + } + + if (EQN_PILE == bp->type) { + assert(NULL == post); + if (bp->first != NULL && bp->first->type == EQN_LIST) + post = print_otag(p, TAG_MTABLE, ""); + } else if (bp->type == EQN_LIST && + bp->parent && bp->parent->type == EQN_PILE) { + assert(NULL == post); + post = print_otag(p, TAG_MTR, ""); + print_otag(p, TAG_MTD, ""); + } + + if (NULL != bp->text) { + assert(NULL == post); + post = print_otag(p, TAG_MI, ""); + print_text(p, bp->text); + } else if (NULL == post) { + if (NULL != bp->left || NULL != bp->right) + post = print_otag(p, TAG_MFENCED, "??", + "open", bp->left == NULL ? "" : bp->left, + "close", bp->right == NULL ? "" : bp->right); + if (NULL == post) + post = print_otag(p, TAG_MROW, ""); + else + print_otag(p, TAG_MROW, ""); + } + + eqn_box(p, bp->first); + +out: + if (NULL != bp->bottom) { + t = print_otag(p, TAG_MO, ""); + print_text(p, bp->bottom); + print_tagq(p, t); + } + if (NULL != bp->top) { + t = print_otag(p, TAG_MO, ""); + print_text(p, bp->top); + print_tagq(p, t); + } + + if (NULL != post) + print_tagq(p, post); + + eqn_box(p, bp->next); +} + +void +print_eqn(struct html *p, const struct eqn *ep) +{ + struct tag *t; + + t = print_otag(p, TAG_MATH, "c", "eqn"); + + p->flags |= HTML_NONOSPACE; + eqn_box(p, ep->root); + p->flags &= ~HTML_NONOSPACE; + + print_tagq(p, t); +} Property changes on: vendor/mdocml/20170121/eqn_html.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/html.c =================================================================== --- vendor/mdocml/20170121/html.c (nonexistent) +++ vendor/mdocml/20170121/html.c (revision 312592) @@ -0,0 +1,898 @@ +/* $Id: html.c,v 1.200 2017/01/21 02:29:57 schwarze Exp $ */ +/* + * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons + * Copyright (c) 2011-2015, 2017 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mandoc.h" +#include "mandoc_aux.h" +#include "out.h" +#include "html.h" +#include "manconf.h" +#include "main.h" + +struct htmldata { + const char *name; + int flags; +#define HTML_NOSTACK (1 << 0) +#define HTML_AUTOCLOSE (1 << 1) +#define HTML_NLBEFORE (1 << 2) +#define HTML_NLBEGIN (1 << 3) +#define HTML_NLEND (1 << 4) +#define HTML_NLAFTER (1 << 5) +#define HTML_NLAROUND (HTML_NLBEFORE | HTML_NLAFTER) +#define HTML_NLINSIDE (HTML_NLBEGIN | HTML_NLEND) +#define HTML_NLALL (HTML_NLAROUND | HTML_NLINSIDE) +#define HTML_INDENT (1 << 6) +#define HTML_NOINDENT (1 << 7) +}; + +static const struct htmldata htmltags[TAG_MAX] = { + {"html", HTML_NLALL}, + {"head", HTML_NLALL | HTML_INDENT}, + {"body", HTML_NLALL}, + {"meta", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, + {"title", HTML_NLAROUND}, + {"div", HTML_NLAROUND}, + {"h1", HTML_NLAROUND}, + {"h2", HTML_NLAROUND}, + {"span", 0}, + {"link", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, + {"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, + {"a", 0}, + {"table", HTML_NLALL | HTML_INDENT}, + {"tbody", HTML_NLALL | HTML_INDENT}, + {"col", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL}, + {"tr", HTML_NLALL | HTML_INDENT}, + {"td", HTML_NLAROUND}, + {"li", HTML_NLAROUND | HTML_INDENT}, + {"ul", HTML_NLALL | HTML_INDENT}, + {"ol", HTML_NLALL | HTML_INDENT}, + {"dl", HTML_NLALL | HTML_INDENT}, + {"dt", HTML_NLAROUND}, + {"dd", HTML_NLAROUND | HTML_INDENT}, + {"pre", HTML_NLALL | HTML_NOINDENT}, + {"b", 0}, + {"i", 0}, + {"code", 0}, + {"small", 0}, + {"style", HTML_NLALL | HTML_INDENT}, + {"math", HTML_NLALL | HTML_INDENT}, + {"mrow", 0}, + {"mi", 0}, + {"mo", 0}, + {"msup", 0}, + {"msub", 0}, + {"msubsup", 0}, + {"mfrac", 0}, + {"msqrt", 0}, + {"mfenced", 0}, + {"mtable", 0}, + {"mtr", 0}, + {"mtd", 0}, + {"munderover", 0}, + {"munder", 0}, + {"mover", 0}, +}; + +static const char *const roffscales[SCALE_MAX] = { + "cm", /* SCALE_CM */ + "in", /* SCALE_IN */ + "pc", /* SCALE_PC */ + "pt", /* SCALE_PT */ + "em", /* SCALE_EM */ + "em", /* SCALE_MM */ + "ex", /* SCALE_EN */ + "ex", /* SCALE_BU */ + "em", /* SCALE_VS */ + "ex", /* SCALE_FS */ +}; + +static void a2width(const char *, struct roffsu *); +static void print_byte(struct html *, char); +static void print_endline(struct html *); +static void print_endword(struct html *); +static void print_indent(struct html *); +static void print_word(struct html *, const char *); + +static void print_ctag(struct html *, struct tag *); +static int print_escape(struct html *, char); +static int print_encode(struct html *, const char *, const char *, int); +static void print_href(struct html *, const char *, const char *, int); +static void print_metaf(struct html *, enum mandoc_esc); + + +void * +html_alloc(const struct manoutput *outopts) +{ + struct html *h; + + h = mandoc_calloc(1, sizeof(struct html)); + + h->tags.head = NULL; + h->style = outopts->style; + h->base_man = outopts->man; + h->base_includes = outopts->includes; + if (outopts->fragment) + h->oflags |= HTML_FRAGMENT; + + return h; +} + +void +html_free(void *p) +{ + struct tag *tag; + struct html *h; + + h = (struct html *)p; + + while ((tag = h->tags.head) != NULL) { + h->tags.head = tag->next; + free(tag); + } + + free(h); +} + +void +print_gen_head(struct html *h) +{ + struct tag *t; + + print_otag(h, TAG_META, "?", "charset", "utf-8"); + + /* + * Print a default style-sheet. + */ + + t = print_otag(h, TAG_STYLE, ""); + print_text(h, "table.head, table.foot { width: 100%; }"); + print_endline(h); + print_text(h, "td.head-rtitle, td.foot-os { text-align: right; }"); + print_endline(h); + print_text(h, "td.head-vol { text-align: center; }"); + print_endline(h); + print_text(h, "div.Pp { margin: 1ex 0ex; }"); + print_tagq(h, t); + + if (h->style) + print_otag(h, TAG_LINK, "?h??", "rel", "stylesheet", + h->style, "type", "text/css", "media", "all"); +} + +static void +print_metaf(struct html *h, enum mandoc_esc deco) +{ + enum htmlfont font; + + switch (deco) { + case ESCAPE_FONTPREV: + font = h->metal; + break; + case ESCAPE_FONTITALIC: + font = HTMLFONT_ITALIC; + break; + case ESCAPE_FONTBOLD: + font = HTMLFONT_BOLD; + break; + case ESCAPE_FONTBI: + font = HTMLFONT_BI; + break; + case ESCAPE_FONT: + case ESCAPE_FONTROMAN: + font = HTMLFONT_NONE; + break; + default: + abort(); + } + + if (h->metaf) { + print_tagq(h, h->metaf); + h->metaf = NULL; + } + + h->metal = h->metac; + h->metac = font; + + switch (font) { + case HTMLFONT_ITALIC: + h->metaf = print_otag(h, TAG_I, ""); + break; + case HTMLFONT_BOLD: + h->metaf = print_otag(h, TAG_B, ""); + break; + case HTMLFONT_BI: + h->metaf = print_otag(h, TAG_B, ""); + print_otag(h, TAG_I, ""); + break; + default: + break; + } +} + +int +html_strlen(const char *cp) +{ + size_t rsz; + int skip, sz; + + /* + * Account for escaped sequences within string length + * calculations. This follows the logic in term_strlen() as we + * must calculate the width of produced strings. + * Assume that characters are always width of "1". This is + * hacky, but it gets the job done for approximation of widths. + */ + + sz = 0; + skip = 0; + while (1) { + rsz = strcspn(cp, "\\"); + if (rsz) { + cp += rsz; + if (skip) { + skip = 0; + rsz--; + } + sz += rsz; + } + if ('\0' == *cp) + break; + cp++; + switch (mandoc_escape(&cp, NULL, NULL)) { + case ESCAPE_ERROR: + return sz; + case ESCAPE_UNICODE: + case ESCAPE_NUMBERED: + case ESCAPE_SPECIAL: + case ESCAPE_OVERSTRIKE: + if (skip) + skip = 0; + else + sz++; + break; + case ESCAPE_SKIPCHAR: + skip = 1; + break; + default: + break; + } + } + return sz; +} + +static int +print_escape(struct html *h, char c) +{ + + switch (c) { + case '<': + print_word(h, "<"); + break; + case '>': + print_word(h, ">"); + break; + case '&': + print_word(h, "&"); + break; + case '"': + print_word(h, """); + break; + case ASCII_NBRSP: + print_word(h, " "); + break; + case ASCII_HYPH: + print_byte(h, '-'); + break; + case ASCII_BREAK: + break; + default: + return 0; + } + return 1; +} + +static int +print_encode(struct html *h, const char *p, const char *pend, int norecurse) +{ + char numbuf[16]; + size_t sz; + int c, len, nospace; + const char *seq; + enum mandoc_esc esc; + static const char rejs[9] = { '\\', '<', '>', '&', '"', + ASCII_NBRSP, ASCII_HYPH, ASCII_BREAK, '\0' }; + + if (pend == NULL) + pend = strchr(p, '\0'); + + nospace = 0; + + while (p < pend) { + if (HTML_SKIPCHAR & h->flags && '\\' != *p) { + h->flags &= ~HTML_SKIPCHAR; + p++; + continue; + } + + for (sz = strcspn(p, rejs); sz-- && p < pend; p++) + if (*p == ' ') + print_endword(h); + else + print_byte(h, *p); + + if (p >= pend) + break; + + if (print_escape(h, *p++)) + continue; + + esc = mandoc_escape(&p, &seq, &len); + if (ESCAPE_ERROR == esc) + break; + + switch (esc) { + case ESCAPE_FONT: + case ESCAPE_FONTPREV: + case ESCAPE_FONTBOLD: + case ESCAPE_FONTITALIC: + case ESCAPE_FONTBI: + case ESCAPE_FONTROMAN: + if (0 == norecurse) + print_metaf(h, esc); + continue; + case ESCAPE_SKIPCHAR: + h->flags |= HTML_SKIPCHAR; + continue; + default: + break; + } + + if (h->flags & HTML_SKIPCHAR) { + h->flags &= ~HTML_SKIPCHAR; + continue; + } + + switch (esc) { + case ESCAPE_UNICODE: + /* Skip past "u" header. */ + c = mchars_num2uc(seq + 1, len - 1); + break; + case ESCAPE_NUMBERED: + c = mchars_num2char(seq, len); + if (c < 0) + continue; + break; + case ESCAPE_SPECIAL: + c = mchars_spec2cp(seq, len); + if (c <= 0) + continue; + break; + case ESCAPE_NOSPACE: + if ('\0' == *p) + nospace = 1; + continue; + case ESCAPE_OVERSTRIKE: + if (len == 0) + continue; + c = seq[len - 1]; + break; + default: + continue; + } + if ((c < 0x20 && c != 0x09) || + (c > 0x7E && c < 0xA0)) + c = 0xFFFD; + if (c > 0x7E) { + (void)snprintf(numbuf, sizeof(numbuf), "%d;", c); + print_word(h, numbuf); + } else if (print_escape(h, c) == 0) + print_byte(h, c); + } + + return nospace; +} + +static void +print_href(struct html *h, const char *name, const char *sec, int man) +{ + const char *p, *pp; + + pp = man ? h->base_man : h->base_includes; + while ((p = strchr(pp, '%')) != NULL) { + print_encode(h, pp, p, 1); + if (man && p[1] == 'S') { + if (sec == NULL) + print_byte(h, '1'); + else + print_encode(h, sec, NULL, 1); + } else if ((man && p[1] == 'N') || + (man == 0 && p[1] == 'I')) + print_encode(h, name, NULL, 1); + else + print_encode(h, p, p + 2, 1); + pp = p + 2; + } + if (*pp != '\0') + print_encode(h, pp, NULL, 1); +} + +struct tag * +print_otag(struct html *h, enum htmltag tag, const char *fmt, ...) +{ + va_list ap; + struct roffsu mysu, *su; + char numbuf[16]; + struct tag *t; + const char *attr; + char *s; + double v; + int i, have_style, tflags; + + tflags = htmltags[tag].flags; + + /* Push this tags onto the stack of open scopes. */ + + if ((tflags & HTML_NOSTACK) == 0) { + t = mandoc_malloc(sizeof(struct tag)); + t->tag = tag; + t->next = h->tags.head; + h->tags.head = t; + } else + t = NULL; + + if (tflags & HTML_NLBEFORE) + print_endline(h); + if (h->col == 0) + print_indent(h); + else if ((h->flags & HTML_NOSPACE) == 0) { + if (h->flags & HTML_KEEP) + print_word(h, " "); + else { + if (h->flags & HTML_PREKEEP) + h->flags |= HTML_KEEP; + print_endword(h); + } + } + + if ( ! (h->flags & HTML_NONOSPACE)) + h->flags &= ~HTML_NOSPACE; + else + h->flags |= HTML_NOSPACE; + + /* Print out the tag name and attributes. */ + + print_byte(h, '<'); + print_word(h, htmltags[tag].name); + + va_start(ap, fmt); + + have_style = 0; + while (*fmt != '\0') { + if (*fmt == 's') { + print_word(h, " style=\""); + have_style = 1; + fmt++; + break; + } + s = va_arg(ap, char *); + switch (*fmt++) { + case 'c': + attr = "class"; + break; + case 'h': + attr = "href"; + break; + case 'i': + attr = "id"; + break; + case '?': + attr = s; + s = va_arg(ap, char *); + break; + default: + abort(); + } + print_byte(h, ' '); + print_word(h, attr); + print_byte(h, '='); + print_byte(h, '"'); + switch (*fmt) { + case 'M': + print_href(h, s, va_arg(ap, char *), 1); + fmt++; + break; + case 'I': + print_href(h, s, NULL, 0); + fmt++; + break; + case 'R': + print_byte(h, '#'); + fmt++; + /* FALLTHROUGH */ + default: + print_encode(h, s, NULL, 1); + break; + } + print_byte(h, '"'); + } + + /* Print out styles. */ + + s = NULL; + su = &mysu; + while (*fmt != '\0') { + + /* First letter: input argument type. */ + + switch (*fmt++) { + case 'h': + i = va_arg(ap, int); + SCALE_HS_INIT(su, i); + break; + case 's': + s = va_arg(ap, char *); + break; + case 'u': + su = va_arg(ap, struct roffsu *); + break; + case 'v': + i = va_arg(ap, int); + SCALE_VS_INIT(su, i); + break; + case 'w': + s = va_arg(ap, char *); + a2width(s, su); + break; + default: + abort(); + } + + /* Second letter: style name. */ + + switch (*fmt++) { + case 'b': + attr = "margin-bottom"; + break; + case 'h': + attr = "height"; + break; + case 'i': + attr = "text-indent"; + break; + case 'l': + attr = "margin-left"; + break; + case 't': + attr = "margin-top"; + break; + case 'w': + attr = "width"; + break; + case 'W': + attr = "min-width"; + break; + case '?': + print_word(h, s); + print_byte(h, ':'); + print_byte(h, ' '); + print_word(h, va_arg(ap, char *)); + print_byte(h, ';'); + if (*fmt != '\0') + print_byte(h, ' '); + continue; + default: + abort(); + } + v = su->scale; + if (su->unit == SCALE_MM && (v /= 100.0) == 0.0) + v = 1.0; + else if (su->unit == SCALE_BU) + v /= 24.0; + print_word(h, attr); + print_byte(h, ':'); + print_byte(h, ' '); + (void)snprintf(numbuf, sizeof(numbuf), "%.2f", v); + print_word(h, numbuf); + print_word(h, roffscales[su->unit]); + print_byte(h, ';'); + if (*fmt != '\0') + print_byte(h, ' '); + } + if (have_style) + print_byte(h, '"'); + + va_end(ap); + + /* Accommodate for "well-formed" singleton escaping. */ + + if (HTML_AUTOCLOSE & htmltags[tag].flags) + print_byte(h, '/'); + + print_byte(h, '>'); + + if (tflags & HTML_NLBEGIN) + print_endline(h); + else + h->flags |= HTML_NOSPACE; + + if (tflags & HTML_INDENT) + h->indent++; + if (tflags & HTML_NOINDENT) + h->noindent++; + + return t; +} + +static void +print_ctag(struct html *h, struct tag *tag) +{ + int tflags; + + /* + * Remember to close out and nullify the current + * meta-font and table, if applicable. + */ + if (tag == h->metaf) + h->metaf = NULL; + if (tag == h->tblt) + h->tblt = NULL; + + tflags = htmltags[tag->tag].flags; + + if (tflags & HTML_INDENT) + h->indent--; + if (tflags & HTML_NOINDENT) + h->noindent--; + if (tflags & HTML_NLEND) + print_endline(h); + print_indent(h); + print_byte(h, '<'); + print_byte(h, '/'); + print_word(h, htmltags[tag->tag].name); + print_byte(h, '>'); + if (tflags & HTML_NLAFTER) + print_endline(h); + + h->tags.head = tag->next; + free(tag); +} + +void +print_gen_decls(struct html *h) +{ + print_word(h, ""); + print_endline(h); +} + +void +print_text(struct html *h, const char *word) +{ + if (h->col && (h->flags & HTML_NOSPACE) == 0) { + if ( ! (HTML_KEEP & h->flags)) { + if (HTML_PREKEEP & h->flags) + h->flags |= HTML_KEEP; + print_endword(h); + } else + print_word(h, " "); + } + + assert(NULL == h->metaf); + switch (h->metac) { + case HTMLFONT_ITALIC: + h->metaf = print_otag(h, TAG_I, ""); + break; + case HTMLFONT_BOLD: + h->metaf = print_otag(h, TAG_B, ""); + break; + case HTMLFONT_BI: + h->metaf = print_otag(h, TAG_B, ""); + print_otag(h, TAG_I, ""); + break; + default: + print_indent(h); + break; + } + + assert(word); + if ( ! print_encode(h, word, NULL, 0)) { + if ( ! (h->flags & HTML_NONOSPACE)) + h->flags &= ~HTML_NOSPACE; + h->flags &= ~HTML_NONEWLINE; + } else + h->flags |= HTML_NOSPACE | HTML_NONEWLINE; + + if (h->metaf) { + print_tagq(h, h->metaf); + h->metaf = NULL; + } + + h->flags &= ~HTML_IGNDELIM; +} + +void +print_tagq(struct html *h, const struct tag *until) +{ + struct tag *tag; + + while ((tag = h->tags.head) != NULL) { + print_ctag(h, tag); + if (until && tag == until) + return; + } +} + +void +print_stagq(struct html *h, const struct tag *suntil) +{ + struct tag *tag; + + while ((tag = h->tags.head) != NULL) { + if (suntil && tag == suntil) + return; + print_ctag(h, tag); + } +} + +void +print_paragraph(struct html *h) +{ + struct tag *t; + + t = print_otag(h, TAG_DIV, "c", "Pp"); + print_tagq(h, t); +} + + +/*********************************************************************** + * Low level output functions. + * They implement line breaking using a short static buffer. + ***********************************************************************/ + +/* + * Buffer one HTML output byte. + * If the buffer is full, flush and deactivate it and start a new line. + * If the buffer is inactive, print directly. + */ +static void +print_byte(struct html *h, char c) +{ + if ((h->flags & HTML_BUFFER) == 0) { + putchar(c); + h->col++; + return; + } + + if (h->col + h->bufcol < sizeof(h->buf)) { + h->buf[h->bufcol++] = c; + return; + } + + putchar('\n'); + h->col = 0; + print_indent(h); + putchar(' '); + putchar(' '); + fwrite(h->buf, h->bufcol, 1, stdout); + putchar(c); + h->col = (h->indent + 1) * 2 + h->bufcol + 1; + h->bufcol = 0; + h->flags &= ~HTML_BUFFER; +} + +/* + * If something was printed on the current output line, end it. + * Not to be called right after print_indent(). + */ +static void +print_endline(struct html *h) +{ + if (h->col == 0) + return; + + if (h->bufcol) { + putchar(' '); + fwrite(h->buf, h->bufcol, 1, stdout); + h->bufcol = 0; + } + putchar('\n'); + h->col = 0; + h->flags |= HTML_NOSPACE; + h->flags &= ~HTML_BUFFER; +} + +/* + * Flush the HTML output buffer. + * If it is inactive, activate it. + */ +static void +print_endword(struct html *h) +{ + if (h->noindent) { + print_byte(h, ' '); + return; + } + + if ((h->flags & HTML_BUFFER) == 0) { + h->col++; + h->flags |= HTML_BUFFER; + } else if (h->bufcol) { + putchar(' '); + fwrite(h->buf, h->bufcol, 1, stdout); + h->col += h->bufcol + 1; + } + h->bufcol = 0; +} + +/* + * If at the beginning of a new output line, + * perform indentation and mark the line as containing output. + * Make sure to really produce some output right afterwards, + * but do not use print_otag() for producing it. + */ +static void +print_indent(struct html *h) +{ + size_t i; + + if (h->col) + return; + + if (h->noindent == 0) { + h->col = h->indent * 2; + for (i = 0; i < h->col; i++) + putchar(' '); + } + h->flags &= ~HTML_NOSPACE; +} + +/* + * Print or buffer some characters + * depending on the current HTML output buffer state. + */ +static void +print_word(struct html *h, const char *cp) +{ + while (*cp != '\0') + print_byte(h, *cp++); +} + +/* + * Calculate the scaling unit passed in a `-width' argument. This uses + * either a native scaling unit (e.g., 1i, 2m) or the string length of + * the value. + */ +static void +a2width(const char *p, struct roffsu *su) +{ + if (a2roffsu(p, su, SCALE_MAX) < 2) { + su->unit = SCALE_EN; + su->scale = html_strlen(p); + } else if (su->scale < 0.0) + su->scale = 0.0; +} Property changes on: vendor/mdocml/20170121/html.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/html.h =================================================================== --- vendor/mdocml/20170121/html.h (nonexistent) +++ vendor/mdocml/20170121/html.h (revision 312592) @@ -0,0 +1,131 @@ +/* $Id: html.h,v 1.78 2017/01/19 16:59:30 schwarze Exp $ */ +/* + * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons + * Copyright (c) 2017 Ingo Schwarze + * + * 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. + */ + +enum htmltag { + TAG_HTML, + TAG_HEAD, + TAG_BODY, + TAG_META, + TAG_TITLE, + TAG_DIV, + TAG_H1, + TAG_H2, + TAG_SPAN, + TAG_LINK, + TAG_BR, + TAG_A, + TAG_TABLE, + TAG_TBODY, + TAG_COL, + TAG_TR, + TAG_TD, + TAG_LI, + TAG_UL, + TAG_OL, + TAG_DL, + TAG_DT, + TAG_DD, + TAG_PRE, + TAG_B, + TAG_I, + TAG_CODE, + TAG_SMALL, + TAG_STYLE, + TAG_MATH, + TAG_MROW, + TAG_MI, + TAG_MO, + TAG_MSUP, + TAG_MSUB, + TAG_MSUBSUP, + TAG_MFRAC, + TAG_MSQRT, + TAG_MFENCED, + TAG_MTABLE, + TAG_MTR, + TAG_MTD, + TAG_MUNDEROVER, + TAG_MUNDER, + TAG_MOVER, + TAG_MAX +}; + +enum htmlfont { + HTMLFONT_NONE = 0, + HTMLFONT_BOLD, + HTMLFONT_ITALIC, + HTMLFONT_BI, + HTMLFONT_MAX +}; + +struct tag { + struct tag *next; + enum htmltag tag; +}; + +struct tagq { + struct tag *head; +}; + +struct html { + int flags; +#define HTML_NOSPACE (1 << 0) /* suppress next space */ +#define HTML_IGNDELIM (1 << 1) +#define HTML_KEEP (1 << 2) +#define HTML_PREKEEP (1 << 3) +#define HTML_NONOSPACE (1 << 4) /* never add spaces */ +#define HTML_LITERAL (1 << 5) /* literal (e.g., ) context */ +#define HTML_SKIPCHAR (1 << 6) /* skip the next character */ +#define HTML_NOSPLIT (1 << 7) /* do not break line before .An */ +#define HTML_SPLIT (1 << 8) /* break line before .An */ +#define HTML_NONEWLINE (1 << 9) /* No line break in nofill mode. */ +#define HTML_BUFFER (1 << 10) /* Collect a word to see if it fits. */ + size_t indent; /* current output indentation level */ + int noindent; /* indent disabled by*/ + size_t col; /* current output byte position */ + size_t bufcol; /* current buf byte position */ + char buf[80]; /* output buffer */ + struct tagq tags; /* stack of open tags */ + struct rofftbl tbl; /* current table */ + struct tag *tblt; /* current open table scope */ + char *base_man; /* base for manpage href */ + char *base_includes; /* base for include href */ + char *style; /* style-sheet URI */ + struct tag *metaf; /* current open font scope */ + enum htmlfont metal; /* last used font */ + enum htmlfont metac; /* current font mode */ + int oflags; /* output options */ +#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */ +}; + + +struct tbl_span; +struct eqn; + +void print_gen_decls(struct html *); +void print_gen_head(struct html *); +struct tag *print_otag(struct html *, enum htmltag, const char *, ...); +void print_tagq(struct html *, const struct tag *); +void print_stagq(struct html *, const struct tag *); +void print_text(struct html *, const char *); +void print_tblclose(struct html *); +void print_tbl(struct html *, const struct tbl_span *); +void print_eqn(struct html *, const struct eqn *); +void print_paragraph(struct html *); + +int html_strlen(const char *); Property changes on: vendor/mdocml/20170121/html.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/lib.in =================================================================== --- vendor/mdocml/20170121/lib.in (nonexistent) +++ vendor/mdocml/20170121/lib.in (revision 312592) @@ -0,0 +1,125 @@ +/* $Id: lib.in,v 1.19 2016/11/23 20:22:13 schwarze Exp $ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons+ * Copyright (c) 2009, 2012 Joerg Sonnenberger + * + * 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. + */ + +/* + * These are all possible .Lb strings. When a new library is added, add + * its short-string to the left-hand side and formatted string to the + * right-hand side. + * + * Be sure to escape strings. + */ + +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)") +LINE("libcalendar", "Calendar Arithmetic Library (libcalendar, \\-lcalendar)") +LINE("libcam", "Common Access Method User Library (libcam, \\-lcam)") +LINE("libcdk", "Curses Development Kit Library (libcdk, \\-lcdk)") +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 (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)") +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)") +LINE("libm", "Math Library (libm, \\-lm)") +LINE("libm68k", "m68k Architecture Library (libm68k, \\-lm68k)") +LINE("libmagic", "Magic Number Recognition Library (libmagic, \\-lmagic)") +LINE("libmandoc", "Mandoc Macro Compiler Library (libmandoc, \\-lmandoc)") +LINE("libmd", "Message Digest (MD4, MD5, etc.) Support Library (libmd, \\-lmd)") +LINE("libmemstat", "Kernel Memory Allocator Statistics Library (libmemstat, \\-lmemstat)") +LINE("libmenu", "Curses Menu Library (libmenu, \\-lmenu)") +LINE("libmj", "Minimalist JSON library (libmj, \\-lmj)") +LINE("libnetgraph", "Netgraph User Library (libnetgraph, \\-lnetgraph)") +LINE("libnetpgp", "Netpgp Signing, Verification, Encryption and Decryption (libnetpgp, \\-lnetpgp)") +LINE("libnetpgpverify", "Netpgp Verification (libnetpgpverify, \\-lnetpgpverify)") +LINE("libnpf", "NPF Packet Filter Library (libnpf, \\-lnpf)") +LINE("libossaudio", "OSS Audio Emulation Library (libossaudio, \\-lossaudio)") +LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)") +LINE("libpanel", "Z-order for curses windows (libpanel, \\-lpanel)") +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("libproc", "Process Manipulation Library (libproc, \\-lproc)") +LINE("libprop", "Property Container Object Library (libprop, \\-lprop)") +LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)") +LINE("libpthread_dbg", "POSIX Debug Threads Library (libpthread_dbg, \\-lpthread_dbg)") +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)") +LINE("librpcsvc", "RPC Service Library (librpcsvc, \\-lrpcsvc)") +LINE("librt", "POSIX Real\\-time Library (librt, \\-lrt)") +LINE("librtld_db", "Debugging interface to the runtime linker Library (librtld_db, \\-lrtld_db)") +LINE("librumpclient", "Clientside Stubs for rump Kernel Remote Protocols (librumpclient, \\-lrumpclient)") +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)") +LINE("libufs", "UFS File System Access Library (libufs, \\-lufs)") +LINE("libugidfw", "File System Firewall Interface Library (libugidfw, \\-lugidfw)") +LINE("libulog", "User Login Record Library (libulog, \\-lulog)") +LINE("libusbhid", "USB Human Interface Devices Library (libusbhid, \\-lusbhid)") +LINE("libutil", "System Utilities Library (libutil, \\-lutil)") +LINE("libvgl", "Video Graphics Library (libvgl, \\-lvgl)") +LINE("libx86_64", "x86_64 Architecture Library (libx86_64, \\-lx86_64)") +LINE("libz", "Compression Library (libz, \\-lz)") Property changes on: vendor/mdocml/20170121/lib.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/libmandoc.h =================================================================== --- vendor/mdocml/20170121/libmandoc.h (nonexistent) +++ vendor/mdocml/20170121/libmandoc.h (revision 312592) @@ -0,0 +1,82 @@ +/* $Id: libmandoc.h,v 1.64 2016/07/19 13:36:13 schwarze Exp $ */ +/* + * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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. + */ + +enum rofferr { + ROFF_CONT, /* continue processing line */ + ROFF_RERUN, /* re-run roff interpreter with offset */ + ROFF_APPEND, /* re-run main parser, appending next line */ + ROFF_REPARSE, /* re-run main parser on the result */ + ROFF_SO, /* include another file */ + ROFF_IGN, /* ignore current line */ + ROFF_TBL, /* a table row was successfully parsed */ + ROFF_EQN /* an equation was successfully parsed */ +}; + +struct buf { + char *buf; + size_t sz; +}; + + +struct mparse; +struct tbl_span; +struct eqn; +struct roff; +struct roff_man; + +void mandoc_msg(enum mandocerr, struct mparse *, + int, int, const char *); +void mandoc_vmsg(enum mandocerr, struct mparse *, + int, int, const char *, ...) + __attribute__((__format__ (printf, 5, 6))); +char *mandoc_getarg(struct mparse *, char **, int, int *); +char *mandoc_normdate(struct mparse *, char *, int, int); +int mandoc_eos(const char *, size_t); +int mandoc_strntoi(const char *, size_t, int); +const char *mandoc_a2msec(const char*); + +void mdoc_hash_init(void); +int mdoc_parseln(struct roff_man *, int, char *, int); +void mdoc_endparse(struct roff_man *); + +void man_hash_init(void); +int man_parseln(struct roff_man *, int, char *, int); +void man_endparse(struct roff_man *); + +int preconv_cue(const struct buf *, size_t); +int preconv_encode(struct buf *, size_t *, + struct buf *, size_t *, int *); + +void roff_free(struct roff *); +struct roff *roff_alloc(struct mparse *, int); +void roff_reset(struct roff *); +void roff_man_free(struct roff_man *); +struct roff_man *roff_man_alloc(struct roff *, struct mparse *, + const char *, int); +void roff_man_reset(struct roff_man *); +enum rofferr roff_parseln(struct roff *, int, struct buf *, int *); +void roff_endparse(struct roff *); +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 *); +int roff_getformat(const struct roff *); + +const struct tbl_span *roff_span(const struct roff *); +const struct eqn *roff_eqn(const struct roff *); Property changes on: vendor/mdocml/20170121/libmandoc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/main.c =================================================================== --- vendor/mdocml/20170121/main.c (nonexistent) +++ vendor/mdocml/20170121/main.c (revision 312592) @@ -0,0 +1,1102 @@ +/* $Id: main.c,v 1.279 2017/01/09 17:49:57 schwarze Exp $ */ +/* + * Copyright (c) 2008-2012 Kristaps Dzonsons + * Copyright (c) 2010-2012, 2014-2017 Ingo Schwarze + * Copyright (c) 2010 Joerg Sonnenberger + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include +#include /* MACHINE */ +#include + +#include +#include +#if HAVE_ERR +#include +#endif +#include +#include +#include +#if HAVE_SANDBOX_INIT +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" +#include "man.h" +#include "tag.h" +#include "main.h" +#include "manconf.h" +#include "mansearch.h" + +enum outmode { + OUTMODE_DEF = 0, + OUTMODE_FLN, + OUTMODE_LST, + OUTMODE_ALL, + OUTMODE_INT, + OUTMODE_ONE +}; + +enum outt { + OUTT_ASCII = 0, /* -Tascii */ + OUTT_LOCALE, /* -Tlocale */ + OUTT_UTF8, /* -Tutf8 */ + OUTT_TREE, /* -Ttree */ + OUTT_MAN, /* -Tman */ + OUTT_HTML, /* -Thtml */ + OUTT_LINT, /* -Tlint */ + OUTT_PS, /* -Tps */ + OUTT_PDF /* -Tpdf */ +}; + +struct curparse { + struct mparse *mp; + enum mandoclevel wlevel; /* ignore messages below this */ + int wstop; /* stop after a file with a warning */ + enum outt outtype; /* which output to use */ + void *outdata; /* data for output */ + struct manoutput *outopts; /* output options */ +}; + + +int mandocdb(int, char *[]); + +static int fs_lookup(const struct manpaths *, + size_t ipath, const char *, + const char *, const char *, + struct manpage **, size_t *); +static void fs_search(const struct mansearch *, + const struct manpaths *, int, char**, + struct manpage **, size_t *); +static int koptions(int *, char *); +static int moptions(int *, char *); +static void mmsg(enum mandocerr, enum mandoclevel, + const char *, int, int, const char *); +static void outdata_alloc(struct curparse *); +static void parse(struct curparse *, int, const char *); +static void passthrough(const char *, int, int); +static pid_t spawn_pager(struct tag_files *); +static int toptions(struct curparse *, char *); +static void usage(enum argmode) __attribute__((noreturn)); +static int woptions(struct curparse *, char *); + +static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; +static char help_arg[] = "help"; +static char *help_argv[] = {help_arg, NULL}; +static enum mandoclevel rc; + + +int +main(int argc, char *argv[]) +{ + struct manconf conf; + struct curparse curp; + struct mansearch search; + struct tag_files *tag_files; + const char *progname; + char *auxpaths; + char *defos; + unsigned char *uc; + struct manpage *res, *resp; + char *conf_file, *defpaths; + const char *sec; + size_t i, sz; + int prio, best_prio; + enum outmode outmode; + int fd; + int show_usage; + int options; + int use_pager; + int status, signum; + int c; + pid_t pager_pid, tc_pgid, man_pgid, pid; + +#if HAVE_PROGNAME + progname = getprogname(); +#else + if (argc < 1) + progname = mandoc_strdup("mandoc"); + else if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + ++progname; + setprogname(progname); +#endif + + if (strncmp(progname, "mandocdb", 8) == 0 || + strcmp(progname, BINM_MAKEWHATIS) == 0) + return mandocdb(argc, argv); + +#if HAVE_PLEDGE + if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + +#if HAVE_SANDBOX_INIT + if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) + errx((int)MANDOCLEVEL_SYSERR, "sandbox_init"); +#endif + + /* Search options. */ + + memset(&conf, 0, sizeof(conf)); + conf_file = defpaths = NULL; + auxpaths = NULL; + + memset(&search, 0, sizeof(struct mansearch)); + search.outkey = "Nd"; + + if (strcmp(progname, BINM_MAN) == 0) + search.argmode = ARG_NAME; + else if (strcmp(progname, BINM_APROPOS) == 0) + search.argmode = ARG_EXPR; + else if (strcmp(progname, BINM_WHATIS) == 0) + search.argmode = ARG_WORD; + else if (strncmp(progname, "help", 4) == 0) + search.argmode = ARG_NAME; + else + search.argmode = ARG_FILE; + + /* Parser and formatter options. */ + + memset(&curp, 0, sizeof(struct curparse)); + curp.outtype = OUTT_LOCALE; + curp.wlevel = MANDOCLEVEL_BADARG; + curp.outopts = &conf.output; + options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1; + defos = NULL; + + use_pager = 1; + tag_files = NULL; + show_usage = 0; + outmode = OUTMODE_DEF; + + while (-1 != (c = getopt(argc, argv, + "aC:cfhI:iK:klM:m:O:S:s:T:VW:w"))) { + switch (c) { + case 'a': + outmode = OUTMODE_ALL; + break; + case 'C': + conf_file = optarg; + break; + case 'c': + use_pager = 0; + break; + case 'f': + search.argmode = ARG_WORD; + break; + case 'h': + conf.output.synopsisonly = 1; + use_pager = 0; + outmode = OUTMODE_ALL; + break; + case 'I': + if (strncmp(optarg, "os=", 3)) { + warnx("-I %s: Bad argument", optarg); + return (int)MANDOCLEVEL_BADARG; + } + if (defos) { + warnx("-I %s: Duplicate argument", optarg); + return (int)MANDOCLEVEL_BADARG; + } + defos = mandoc_strdup(optarg + 3); + break; + case 'i': + outmode = OUTMODE_INT; + break; + case 'K': + if ( ! koptions(&options, optarg)) + return (int)MANDOCLEVEL_BADARG; + break; + case 'k': + search.argmode = ARG_EXPR; + break; + case 'l': + search.argmode = ARG_FILE; + outmode = OUTMODE_ALL; + break; + case 'M': + defpaths = optarg; + break; + case 'm': + auxpaths = optarg; + break; + case 'O': + search.outkey = optarg; + while (optarg != NULL) + manconf_output(&conf.output, + strsep(&optarg, ",")); + break; + case 'S': + search.arch = optarg; + break; + case 's': + search.sec = optarg; + break; + case 'T': + if ( ! toptions(&curp, optarg)) + return (int)MANDOCLEVEL_BADARG; + break; + case 'W': + if ( ! woptions(&curp, optarg)) + return (int)MANDOCLEVEL_BADARG; + break; + case 'w': + outmode = OUTMODE_FLN; + break; + default: + show_usage = 1; + break; + } + } + + if (show_usage) + usage(search.argmode); + + /* Postprocess options. */ + + if (outmode == OUTMODE_DEF) { + switch (search.argmode) { + case ARG_FILE: + outmode = OUTMODE_ALL; + use_pager = 0; + break; + case ARG_NAME: + outmode = OUTMODE_ONE; + break; + default: + outmode = OUTMODE_LST; + break; + } + } + + if (outmode == OUTMODE_FLN || + outmode == OUTMODE_LST || + !isatty(STDOUT_FILENO)) + use_pager = 0; + +#if HAVE_PLEDGE + if (!use_pager) + if (pledge("stdio rpath flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + + /* Parse arguments. */ + + if (argc > 0) { + argc -= optind; + argv += optind; + } + resp = NULL; + + /* + * Quirks for help(1) + * and for a man(1) section argument without -s. + */ + + if (search.argmode == ARG_NAME) { + if (*progname == 'h') { + if (argc == 0) { + argv = help_argv; + argc = 1; + } + } else if (argc > 1 && + ((uc = (unsigned char *)argv[0]) != NULL) && + ((isdigit(uc[0]) && (uc[1] == '\0' || + (isalpha(uc[1]) && uc[2] == '\0'))) || + (uc[0] == 'n' && uc[1] == '\0'))) { + search.sec = (char *)uc; + argv++; + argc--; + } + if (search.arch == NULL) + search.arch = getenv("MACHINE"); +#ifdef MACHINE + if (search.arch == NULL) + search.arch = MACHINE; +#endif + } + + rc = MANDOCLEVEL_OK; + + /* man(1), whatis(1), apropos(1) */ + + if (search.argmode != ARG_FILE) { + if (search.argmode == ARG_NAME && + outmode == OUTMODE_ONE) + search.firstmatch = 1; + + /* Access the mandoc database. */ + + manconf_parse(&conf, conf_file, defpaths, auxpaths); + if ( ! mansearch(&search, &conf.manpath, + argc, argv, &res, &sz)) + usage(search.argmode); + + if (sz == 0) { + if (search.argmode == ARG_NAME) + fs_search(&search, &conf.manpath, + argc, argv, &res, &sz); + else + warnx("nothing appropriate"); + } + + if (sz == 0) { + rc = MANDOCLEVEL_BADARG; + goto out; + } + + /* + * For standard man(1) and -a output mode, + * prepare for copying filename pointers + * into the program parameter array. + */ + + if (outmode == OUTMODE_ONE) { + argc = 1; + best_prio = 20; + } else if (outmode == OUTMODE_ALL) + argc = (int)sz; + + /* Iterate all matching manuals. */ + + resp = res; + for (i = 0; i < sz; i++) { + if (outmode == OUTMODE_FLN) + puts(res[i].file); + else if (outmode == OUTMODE_LST) + printf("%s - %s\n", res[i].names, + res[i].output == NULL ? "" : + res[i].output); + else if (outmode == OUTMODE_ONE) { + /* Search for the best section. */ + sec = res[i].file; + sec += strcspn(sec, "123456789"); + if (sec[0] == '\0') + continue; + prio = sec_prios[sec[0] - '1']; + if (sec[1] != '/') + prio += 10; + if (prio >= best_prio) + continue; + best_prio = prio; + resp = res + i; + } + } + + /* + * For man(1), -a and -i output mode, fall through + * to the main mandoc(1) code iterating files + * and running the parsers on each of them. + */ + + if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST) + goto out; + } + + /* mandoc(1) */ + +#if HAVE_PLEDGE + if (use_pager) { + if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } +#endif + + if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) + return (int)MANDOCLEVEL_BADARG; + + mchars_alloc(); + curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos); + + /* + * Conditionally start up the lookaside buffer before parsing. + */ + if (OUTT_MAN == curp.outtype) + mparse_keep(curp.mp); + + if (argc < 1) { + if (use_pager) + tag_files = tag_init(); + parse(&curp, STDIN_FILENO, " "); + } + + while (argc > 0) { + fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv); + if (fd != -1) { + if (use_pager) { + tag_files = tag_init(); + use_pager = 0; + } + + if (resp == NULL) + parse(&curp, fd, *argv); + else if (resp->form == FORM_SRC) { + /* For .so only; ignore failure. */ + chdir(conf.manpath.paths[resp->ipath]); + parse(&curp, fd, resp->file); + } else + passthrough(resp->file, fd, + conf.output.synopsisonly); + + if (argc > 1 && curp.outtype <= OUTT_UTF8) { + if (curp.outdata == NULL) + outdata_alloc(&curp); + terminal_sepline(curp.outdata); + } + } else if (rc < MANDOCLEVEL_ERROR) + rc = MANDOCLEVEL_ERROR; + + if (MANDOCLEVEL_OK != rc && curp.wstop) + break; + + if (resp != NULL) + resp++; + else + argv++; + if (--argc) + mparse_reset(curp.mp); + } + + if (curp.outdata != NULL) { + switch (curp.outtype) { + case OUTT_HTML: + html_free(curp.outdata); + break; + case OUTT_UTF8: + case OUTT_LOCALE: + case OUTT_ASCII: + ascii_free(curp.outdata); + break; + case OUTT_PDF: + case OUTT_PS: + pspdf_free(curp.outdata); + break; + default: + break; + } + } + mparse_free(curp.mp); + mchars_free(); + +out: + if (search.argmode != ARG_FILE) { + manconf_free(&conf); + mansearch_free(res, sz); + } + + free(defos); + + /* + * When using a pager, finish writing both temporary files, + * fork it, wait for the user to close it, and clean up. + */ + + if (tag_files != NULL) { + fclose(stdout); + tag_write(); + man_pgid = getpgid(0); + tag_files->tcpgid = man_pgid == getpid() ? + getpgid(getppid()) : man_pgid; + pager_pid = 0; + signum = SIGSTOP; + for (;;) { + + /* Stop here until moved to the foreground. */ + + tc_pgid = tcgetpgrp(tag_files->ofd); + if (tc_pgid != man_pgid) { + if (tc_pgid == pager_pid) { + (void)tcsetpgrp(tag_files->ofd, + man_pgid); + if (signum == SIGTTIN) + continue; + } else + tag_files->tcpgid = tc_pgid; + kill(0, signum); + continue; + } + + /* Once in the foreground, activate the pager. */ + + if (pager_pid) { + (void)tcsetpgrp(tag_files->ofd, pager_pid); + kill(pager_pid, SIGCONT); + } else + pager_pid = spawn_pager(tag_files); + + /* Wait for the pager to stop or exit. */ + + while ((pid = waitpid(pager_pid, &status, + WUNTRACED)) == -1 && errno == EINTR) + continue; + + if (pid == -1) { + warn("wait"); + rc = MANDOCLEVEL_SYSERR; + break; + } + if (!WIFSTOPPED(status)) + break; + + signum = WSTOPSIG(status); + } + tag_unlink(); + } + + return (int)rc; +} + +static void +usage(enum argmode argmode) +{ + + switch (argmode) { + case ARG_FILE: + fputs("usage: mandoc [-acfhkl] [-I os=name] " + "[-K encoding] [-mformat] [-O option]\n" + "\t [-T output] [-W level] [file ...]\n", stderr); + break; + case ARG_NAME: + fputs("usage: man [-acfhklw] [-C file] [-I os=name] " + "[-K encoding] [-M path] [-m path]\n" + "\t [-O option=value] [-S subsection] [-s section] " + "[-T output] [-W level]\n" + "\t [section] name ...\n", stderr); + break; + case ARG_WORD: + fputs("usage: whatis [-acfhklw] [-C file] " + "[-M path] [-m path] [-O outkey] [-S arch]\n" + "\t [-s section] name ...\n", stderr); + break; + case ARG_EXPR: + fputs("usage: apropos [-acfhklw] [-C file] " + "[-M path] [-m path] [-O outkey] [-S arch]\n" + "\t [-s section] expression ...\n", stderr); + break; + } + exit((int)MANDOCLEVEL_BADARG); +} + +static int +fs_lookup(const struct manpaths *paths, size_t ipath, + const char *sec, const char *arch, const char *name, + struct manpage **res, size_t *ressz) +{ + glob_t globinfo; + struct manpage *page; + char *file; + int globres; + enum form form; + + form = FORM_SRC; + mandoc_asprintf(&file, "%s/man%s/%s.%s", + paths->paths[ipath], sec, name, sec); + if (access(file, R_OK) != -1) + goto found; + free(file); + + mandoc_asprintf(&file, "%s/cat%s/%s.0", + paths->paths[ipath], sec, name); + if (access(file, R_OK) != -1) { + form = FORM_CAT; + goto found; + } + free(file); + + if (arch != NULL) { + mandoc_asprintf(&file, "%s/man%s/%s/%s.%s", + paths->paths[ipath], sec, arch, name, sec); + if (access(file, R_OK) != -1) + goto found; + free(file); + } + + mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*", + paths->paths[ipath], sec, name); + globres = glob(file, 0, NULL, &globinfo); + if (globres != 0 && globres != GLOB_NOMATCH) + warn("%s: glob", file); + free(file); + if (globres == 0) + file = mandoc_strdup(*globinfo.gl_pathv); + globfree(&globinfo); + if (globres != 0) + return 0; + +found: + warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s", + name, sec, BINM_MAKEWHATIS, paths->paths[ipath]); + *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); + page = *res + (*ressz - 1); + page->file = file; + page->names = NULL; + page->output = NULL; + page->ipath = ipath; + page->bits = NAME_FILE & NAME_MASK; + page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; + page->form = form; + return 1; +} + +static void +fs_search(const struct mansearch *cfg, const struct manpaths *paths, + int argc, char **argv, struct manpage **res, size_t *ressz) +{ + const char *const sections[] = + {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"}; + const size_t nsec = sizeof(sections)/sizeof(sections[0]); + + size_t ipath, isec, lastsz; + + assert(cfg->argmode == ARG_NAME); + + *res = NULL; + *ressz = lastsz = 0; + while (argc) { + for (ipath = 0; ipath < paths->sz; ipath++) { + if (cfg->sec != NULL) { + if (fs_lookup(paths, ipath, cfg->sec, + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } else for (isec = 0; isec < nsec; isec++) + if (fs_lookup(paths, ipath, sections[isec], + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } + if (*ressz == lastsz) + warnx("No entry for %s in the manual.", *argv); + lastsz = *ressz; + argv++; + argc--; + } +} + +static void +parse(struct curparse *curp, int fd, const char *file) +{ + enum mandoclevel rctmp; + struct roff_man *man; + + /* Begin by parsing the file itself. */ + + assert(file); + assert(fd >= 0); + + rctmp = mparse_readfd(curp->mp, fd, file); + if (fd != STDIN_FILENO) + close(fd); + if (rc < rctmp) + rc = rctmp; + + /* + * With -Wstop and warnings or errors of at least the requested + * level, do not produce output. + */ + + if (rctmp != MANDOCLEVEL_OK && curp->wstop) + return; + + if (curp->outdata == NULL) + outdata_alloc(curp); + + mparse_result(curp->mp, &man, NULL); + + /* Execute the out device, if it exists. */ + + if (man == NULL) + return; + if (man->macroset == MACROSET_MDOC) { + mdoc_validate(man); + switch (curp->outtype) { + case OUTT_HTML: + html_mdoc(curp->outdata, man); + break; + case OUTT_TREE: + tree_mdoc(curp->outdata, man); + break; + case OUTT_MAN: + man_mdoc(curp->outdata, man); + break; + case OUTT_PDF: + case OUTT_ASCII: + case OUTT_UTF8: + case OUTT_LOCALE: + case OUTT_PS: + terminal_mdoc(curp->outdata, man); + break; + default: + break; + } + } + if (man->macroset == MACROSET_MAN) { + man_validate(man); + switch (curp->outtype) { + case OUTT_HTML: + html_man(curp->outdata, man); + break; + case OUTT_TREE: + tree_man(curp->outdata, man); + break; + case OUTT_MAN: + man_man(curp->outdata, man); + break; + case OUTT_PDF: + case OUTT_ASCII: + case OUTT_UTF8: + case OUTT_LOCALE: + case OUTT_PS: + terminal_man(curp->outdata, man); + break; + default: + break; + } + } + mparse_updaterc(curp->mp, &rc); +} + +static void +outdata_alloc(struct curparse *curp) +{ + switch (curp->outtype) { + case OUTT_HTML: + curp->outdata = html_alloc(curp->outopts); + break; + case OUTT_UTF8: + curp->outdata = utf8_alloc(curp->outopts); + break; + case OUTT_LOCALE: + curp->outdata = locale_alloc(curp->outopts); + break; + case OUTT_ASCII: + curp->outdata = ascii_alloc(curp->outopts); + break; + case OUTT_PDF: + curp->outdata = pdf_alloc(curp->outopts); + break; + case OUTT_PS: + curp->outdata = ps_alloc(curp->outopts); + break; + default: + break; + } +} + +static void +passthrough(const char *file, int fd, int synopsis_only) +{ + const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"; + const char synr[] = "SYNOPSIS"; + + FILE *stream; + const char *syscall; + char *line, *cp; + size_t linesz; + ssize_t len, written; + int print; + + line = NULL; + linesz = 0; + + if (fflush(stdout) == EOF) { + syscall = "fflush"; + goto fail; + } + + if ((stream = fdopen(fd, "r")) == NULL) { + close(fd); + syscall = "fdopen"; + goto fail; + } + + print = 0; + while ((len = getline(&line, &linesz, stream)) != -1) { + cp = line; + if (synopsis_only) { + if (print) { + if ( ! isspace((unsigned char)*cp)) + goto done; + while (isspace((unsigned char)*cp)) { + cp++; + len--; + } + } else { + if (strcmp(cp, synb) == 0 || + strcmp(cp, synr) == 0) + print = 1; + continue; + } + } + for (; len > 0; len -= written) { + if ((written = write(STDOUT_FILENO, cp, len)) != -1) + continue; + fclose(stream); + syscall = "write"; + goto fail; + } + } + + if (ferror(stream)) { + fclose(stream); + syscall = "getline"; + goto fail; + } + +done: + free(line); + fclose(stream); + return; + +fail: + free(line); + warn("%s: SYSERR: %s", file, syscall); + if (rc < MANDOCLEVEL_SYSERR) + rc = MANDOCLEVEL_SYSERR; +} + +static int +koptions(int *options, char *arg) +{ + + if ( ! strcmp(arg, "utf-8")) { + *options |= MPARSE_UTF8; + *options &= ~MPARSE_LATIN1; + } else if ( ! strcmp(arg, "iso-8859-1")) { + *options |= MPARSE_LATIN1; + *options &= ~MPARSE_UTF8; + } else if ( ! strcmp(arg, "us-ascii")) { + *options &= ~(MPARSE_UTF8 | MPARSE_LATIN1); + } else { + warnx("-K %s: Bad argument", arg); + return 0; + } + return 1; +} + +static int +moptions(int *options, char *arg) +{ + + if (arg == NULL) + /* nothing to do */; + else if (0 == strcmp(arg, "doc")) + *options |= MPARSE_MDOC; + else if (0 == strcmp(arg, "andoc")) + /* nothing to do */; + else if (0 == strcmp(arg, "an")) + *options |= MPARSE_MAN; + else { + warnx("-m %s: Bad argument", arg); + return 0; + } + + return 1; +} + +static int +toptions(struct curparse *curp, char *arg) +{ + + if (0 == strcmp(arg, "ascii")) + curp->outtype = OUTT_ASCII; + else if (0 == strcmp(arg, "lint")) { + curp->outtype = OUTT_LINT; + curp->wlevel = MANDOCLEVEL_WARNING; + } else if (0 == strcmp(arg, "tree")) + curp->outtype = OUTT_TREE; + else if (0 == strcmp(arg, "man")) + curp->outtype = OUTT_MAN; + else if (0 == strcmp(arg, "html")) + curp->outtype = OUTT_HTML; + else if (0 == strcmp(arg, "utf8")) + curp->outtype = OUTT_UTF8; + else if (0 == strcmp(arg, "locale")) + curp->outtype = OUTT_LOCALE; + else if (0 == strcmp(arg, "xhtml")) + curp->outtype = OUTT_HTML; + else if (0 == strcmp(arg, "ps")) + curp->outtype = OUTT_PS; + else if (0 == strcmp(arg, "pdf")) + curp->outtype = OUTT_PDF; + else { + warnx("-T %s: Bad argument", arg); + return 0; + } + + return 1; +} + +static int +woptions(struct curparse *curp, char *arg) +{ + char *v, *o; + const char *toks[7]; + + toks[0] = "stop"; + toks[1] = "all"; + toks[2] = "warning"; + toks[3] = "error"; + toks[4] = "unsupp"; + toks[5] = "fatal"; + toks[6] = NULL; + + while (*arg) { + o = arg; + switch (getsubopt(&arg, (char * const *)toks, &v)) { + case 0: + curp->wstop = 1; + break; + case 1: + case 2: + curp->wlevel = MANDOCLEVEL_WARNING; + break; + case 3: + curp->wlevel = MANDOCLEVEL_ERROR; + break; + case 4: + curp->wlevel = MANDOCLEVEL_UNSUPP; + break; + case 5: + curp->wlevel = MANDOCLEVEL_BADARG; + break; + default: + warnx("-W %s: Bad argument", o); + return 0; + } + } + + return 1; +} + +static void +mmsg(enum mandocerr t, enum mandoclevel lvl, + const char *file, int line, int col, const char *msg) +{ + const char *mparse_msg; + + fprintf(stderr, "%s: %s:", getprogname(), + file == NULL ? " " : file); + + if (line) + fprintf(stderr, "%d:%d:", line, col + 1); + + fprintf(stderr, " %s", mparse_strlevel(lvl)); + + if (NULL != (mparse_msg = mparse_strerror(t))) + fprintf(stderr, ": %s", mparse_msg); + + if (msg) + fprintf(stderr, ": %s", msg); + + fputc('\n', stderr); +} + +static pid_t +spawn_pager(struct tag_files *tag_files) +{ + const struct timespec timeout = { 0, 100000000 }; /* 0.1s */ +#define MAX_PAGER_ARGS 16 + char *argv[MAX_PAGER_ARGS]; + const char *pager; + char *cp; + size_t cmdlen; + int argc; + pid_t pager_pid; + + pager = getenv("MANPAGER"); + if (pager == NULL || *pager == '\0') + pager = getenv("PAGER"); + if (pager == NULL || *pager == '\0') + pager = "more -s"; + cp = mandoc_strdup(pager); + + /* + * Parse the pager command into words. + * Intentionally do not do anything fancy here. + */ + + argc = 0; + while (argc + 4 < MAX_PAGER_ARGS) { + argv[argc++] = cp; + cp = strchr(cp, ' '); + if (cp == NULL) + break; + *cp++ = '\0'; + while (*cp == ' ') + cp++; + if (*cp == '\0') + break; + } + + /* For less(1), use the tag file. */ + + if ((cmdlen = strlen(argv[0])) >= 4) { + cp = argv[0] + cmdlen - 4; + if (strcmp(cp, "less") == 0) { + argv[argc++] = mandoc_strdup("-T"); + argv[argc++] = tag_files->tfn; + } + } + argv[argc++] = tag_files->ofn; + argv[argc] = NULL; + + switch (pager_pid = fork()) { + case -1: + err((int)MANDOCLEVEL_SYSERR, "fork"); + case 0: + break; + default: + (void)setpgid(pager_pid, 0); + (void)tcsetpgrp(tag_files->ofd, pager_pid); +#if HAVE_PLEDGE + if (pledge("stdio rpath tmppath tty proc", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + tag_files->pager_pid = pager_pid; + return pager_pid; + } + + /* The child process becomes the pager. */ + + if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) + err((int)MANDOCLEVEL_SYSERR, "pager stdout"); + close(tag_files->ofd); + close(tag_files->tfd); + + /* Do not start the pager before controlling the terminal. */ + + while (tcgetpgrp(STDOUT_FILENO) != getpid()) + nanosleep(&timeout, NULL); + + execvp(argv[0], argv); + err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]); +} Property changes on: vendor/mdocml/20170121/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/main.h =================================================================== --- vendor/mdocml/20170121/main.h (nonexistent) +++ vendor/mdocml/20170121/main.h (revision 312592) @@ -0,0 +1,51 @@ +/* $Id: main.h,v 1.26 2016/07/15 19:33:01 schwarze Exp $ */ +/* + * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons + * Copyright (c) 2014, 2015 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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. + */ + +struct roff_man; +struct manoutput; + +/* + * Definitions for main.c-visible output device functions, e.g., -Thtml + * and -Tascii. Note that ascii_alloc() is named as such in + * anticipation of latin1_alloc() and so on, all of which map into the + * terminal output routines with different character settings. + */ + +void *html_alloc(const struct manoutput *); +void html_mdoc(void *, const struct roff_man *); +void html_man(void *, const struct roff_man *); +void html_free(void *); + +void tree_mdoc(void *, const struct roff_man *); +void tree_man(void *, const struct roff_man *); + +void man_mdoc(void *, const struct roff_man *); +void man_man(void *, const struct roff_man *); + +void *locale_alloc(const struct manoutput *); +void *utf8_alloc(const struct manoutput *); +void *ascii_alloc(const struct manoutput *); +void ascii_free(void *); + +void *pdf_alloc(const struct manoutput *); +void *ps_alloc(const struct manoutput *); +void pspdf_free(void *); + +void terminal_mdoc(void *, const struct roff_man *); +void terminal_man(void *, const struct roff_man *); +void terminal_sepline(void *); Property changes on: vendor/mdocml/20170121/main.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/makewhatis.8 =================================================================== --- vendor/mdocml/20170121/makewhatis.8 (nonexistent) +++ vendor/mdocml/20170121/makewhatis.8 (revision 312592) @@ -0,0 +1,215 @@ +.\" $Id: makewhatis.8,v 1.4 2016/07/19 22:40:33 schwarze Exp $ +.\" +.\" Copyright (c) 2011, 2012 Kristaps Dzonsons +.\" Copyright (c) 2011, 2012 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: July 19 2016 $ +.Dt MAKEWHATIS 8 +.Os +.Sh NAME +.Nm makewhatis +.Nd index UNIX manuals +.Sh SYNOPSIS +.Nm +.Op Fl aDnpQ +.Op Fl T Cm utf8 +.Op Fl C Ar file +.Nm +.Op Fl aDnpQ +.Op Fl T Cm utf8 +.Ar dir ... +.Nm +.Op Fl DnpQ +.Op Fl T Cm utf8 +.Fl d Ar dir +.Op Ar +.Nm +.Op Fl Dnp +.Op Fl T Cm utf8 +.Fl u Ar dir +.Op Ar +.Nm +.Op Fl DQ +.Fl t Ar +.Sh DESCRIPTION +The +.Nm +utility extracts keywords from +.Ux +manuals and indexes them in a database for fast retrieval by +.Xr apropos 1 , +.Xr whatis 1 , +and +.Xr man 1 Ns 's +.Fl k +option. +.Pp +By default, +.Nm +creates a database in each +.Ar dir +using the files +.Sm off +.Sy man Ar section Li / +.Op Ar arch Li / +.Ar title . section +.Sm on +and +.Sm off +.Sy cat Ar section Li / +.Op Ar arch Li / +.Ar title . Sy 0 +.Sm on +in that directory. +Existing databases are replaced. +If +.Ar dir +is not provided, +.Nm +uses the default paths stipulated by +.Xr man.conf 5 . +.Pp +The arguments are as follows: +.Bl -tag -width "-C file" +.It Fl a +Use all directories and files found below +.Ar dir ... . +.It Fl C Ar file +Specify an alternative configuration +.Ar file +in +.Xr man.conf 5 +format. +.It Fl D +Display all files added or removed to the index. +With a second +.Fl D , +also show all keywords added for each file. +.It Fl d Ar dir +Merge (remove and re-add) +.Ar +to the database in +.Ar dir . +.It Fl n +Do not create or modify any database; scan and parse only, +and print manual page names and descriptions to standard output. +.It Fl p +Print warnings about potential problems with manual pages +to the standard error output. +.It Fl Q +Quickly build reduced-size databases +by reading only the NAME sections of manuals. +The resulting databases will usually contain names and descriptions only. +.It Fl T Cm utf8 +Use UTF-8 encoding instead of ASCII for strings stored in the databases. +.It Fl t Ar +Check the given +.Ar files +for potential problems. +Implies +.Fl a , +.Fl n , +and +.Fl p . +All diagnostic messages are printed to the standard output; +the standard error output is not used. +.It Fl u Ar dir +Remove +.Ar +from the database in +.Ar dir . +.El +.Pp +If fatal parse errors are encountered while parsing, the offending file +is printed to stderr, omitted from the index, and the parse continues +with the next input file. +.Sh FILES +.Bl -tag -width Ds +.It Pa mandoc.db +A database of manpages relative to the directory of the file. +This file is portable across architectures and systems, so long as the +manpage hierarchy it indexes does not change. +.It Pa /etc/man.conf +The default +.Xr man 1 +configuration file. +.El +.Sh EXIT STATUS +The +.Nm +utility exits with one of the following values: +.Pp +.Bl -tag -width Ds -compact +.It 0 +No errors occurred. +.It 5 +Invalid command line arguments were specified. +No input files have been read. +.It 6 +An operating system error occurred, for example memory exhaustion or an +error accessing input files. +Such errors cause +.Nm +to exit at once, possibly in the middle of parsing or formatting a file. +The output databases are corrupt and should be removed. +.El +.Sh SEE ALSO +.Xr apropos 1 , +.Xr man 1 , +.Xr whatis 1 , +.Xr man.conf 5 +.Sh HISTORY +A +.Nm +utility first appeared in +.Bx 2 . +It was rewritten in +.Xr perl 1 +for +.Ox 2.7 +and in C for +.Ox 5.6 . +.Pp +The +.Ar dir +argument first appeared in +.Nx 1.0 ; +the options +.Fl dpt +in +.Ox 2.7 ; +the option +.Fl u +in +.Ox 3.4 ; +and the options +.Fl aCDnQT +in +.Ox 5.6 . +.Sh AUTHORS +.An -nosplit +.An Bill Joy +wrote the original +.Bx +.Nm +in February 1979, +.An Marc Espie +started the Perl version in 2000, +and the current version of +.Nm +was written by +.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv +and +.An Ingo Schwarze Aq Mt schwarze@openbsd.org . Property changes on: vendor/mdocml/20170121/makewhatis.8 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man.1 =================================================================== --- vendor/mdocml/20170121/man.1 (nonexistent) +++ vendor/mdocml/20170121/man.1 (revision 312592) @@ -0,0 +1,435 @@ +.\" $Id: man.1,v 1.20 2017/01/06 01:34:57 schwarze Exp $ +.\" +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre +.\" Copyright (c) 2010, 2011, 2014, 2015 Ingo Schwarze +.\" +.\" 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. +.\" +.\" @(#)man.1 8.2 (Berkeley) 1/2/94 +.\" +.Dd $Mdocdate: January 6 2017 $ +.Dt MAN 1 +.Os +.Sh NAME +.Nm man +.Nd display manual pages +.Sh SYNOPSIS +.Nm man +.Op Fl acfhklw +.Op Fl C Ar file +.Op Fl I Cm os Ns = Ns Ar name +.Op Fl K Ar encoding +.Op Fl M Ar path +.Op Fl m Ar path +.Op Fl O Ar option Ns = Ns Ar value +.Op Fl S Ar subsection +.Op Fl s Ar section +.Op Fl T Ar output +.Op Fl W Ar level +.Op Ar section +.Ar name ... +.Sh DESCRIPTION +The +.Nm +utility +displays the +manual pages entitled +.Ar name . +Pages may be selected according to +a specific category +.Pq Ar section +or +machine architecture +.Pq Ar subsection . +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a +Display all matching manual pages. +Normally, only the first page found is displayed. +.It Fl C Ar file +Use the specified +.Ar file +instead of the default configuration file. +This permits users to configure their own manual environment. +See +.Xr man.conf 5 +for a description of the contents of this file. +.It Fl c +Copy the manual page to the standard output instead of using +.Xr more 1 +to paginate it. +This is done by default if the standard output is not a terminal device. +.It Fl f +A synonym for +.Xr whatis 1 . +It searches for +.Ar name +in manual page names and displays the header lines from all matching pages. +The search is case insensitive and matches whole words only. +This overrides any earlier +.Fl k +and +.Fl l +options. +.It Fl h +Display only the SYNOPSIS lines of the requested manual pages. +Implies +.Fl a +and +.Fl c . +.It Fl I Cm os Ns = Ns Ar name +Override the default operating system +.Ar name +for the +.Xr mdoc 7 +.Ic \&Os +and for the +.Xr man 7 +.Ic \&TH +macro. +.It Fl K Ar encoding +Specify the input encoding. +The supported +.Ar encoding +arguments are +.Cm us-ascii , +.Cm iso-8859-1 , +and +.Cm utf-8 . +By default, the encoding is automatically detected as described in the +.Xr mandoc 1 +manual. +.It Fl k +A synonym for +.Xr apropos 1 . +Instead of +.Ar name , +an expression can be provided using the syntax described in the +.Xr apropos 1 +manual. +By default, it displays the header lines of all matching pages. +This overrides any earlier +.Fl f +and +.Fl l +options. +.It Fl l +A synonym for +.Xr mandoc 1 +.Fl a . +The +.Ar name +arguments are interpreted as filenames. +No search is done and +.Ar file , +.Ar path , +.Ar section , +and +.Ar subsection +are ignored. +This overrides any earlier +.Fl f , +.Fl k , +and +.Fl w +options. +.It Fl M Ar path +Override the list of standard directories which +.Nm +searches for manual pages. +The supplied +.Ar path +must be a colon +.Pq Ql \&: +separated list of directories. +This search path may also be set using the environment variable +.Ev MANPATH . +.It Fl m Ar path +Augment the list of standard directories which +.Nm +searches for manual pages. +The supplied +.Ar path +must be a colon +.Pq Ql \&: +separated list of directories. +These directories will be searched before the standard directories or +the directories specified using the +.Fl M +option or the +.Ev MANPATH +environment variable. +.It Fl O Ar option Ns = Ns Ar value +Comma-separated output options. +For each output format, the available options are described in the +.Xr mandoc 1 +manual. +.It Fl S Ar subsection +Restricts the directories that +.Nm +will search to those of a specific +.Xr machine 1 +architecture. +.Ar subsection +is case insensitive. +.Pp +By default manual pages for all architectures are installed. +Therefore this option can be used to view pages for one +architecture whilst using another. +.Pp +This option overrides the +.Ev MACHINE +environment variable. +.It Oo Fl s Oc Ar section +Only select manuals from the specified +.Ar section . +The currently available sections are: +.Pp +.Bl -tag -width "localXXX" -offset indent -compact +.It 1 +General commands +.Pq tools and utilities . +.It 2 +System calls and error numbers. +.It 3 +Library functions. +.It 3p +.Xr perl 1 +programmer's reference guide. +.It 4 +Device drivers. +.It 5 +File formats. +.It 6 +Games. +.It 7 +Miscellaneous information. +.It 8 +System maintenance and operation commands. +.It 9 +Kernel internals. +.El +.It Fl T Ar output +Select the output format. +The default is +.Cm locale . +The other output modes +.Cm ascii , +.Cm html , +.Cm lint , +.Cm man , +.Cm pdf , +.Cm ps , +.Cm tree , +and +.Cm utf8 +are described in the +.Xr mandoc 1 +manual. +.It Fl W Ar level +Specify the minimum message +.Ar level +to be reported on the standard error output and to affect the exit status. +The +.Ar level +can be +.Cm warning , +.Cm error , +or +.Cm unsupp ; +.Cm all +is an alias for +.Cm warning . +By default, +.Nm +is silent. +See the +.Xr mandoc 1 +manual for details. +.It Fl w +List the pathnames of the manual pages which +.Nm +would display for the specified +.Ar section +and +.Ar name +combination. +.El +.Pp +Guidelines for writing +man pages can be found in +.Xr mdoc 7 . +.Pp +If both a formatted and an unformatted version of the same manual page, +for example +.Pa cat1/foo.0 +and +.Pa man1/foo.1 , +exist in the same directory, and at least one of them is selected, +only the newer one is used. +However, if both the +.Fl a +and the +.Fl w +options are specified, both file names are printed. +.Sh ENVIRONMENT +.Bl -tag -width MANPATHX +.It Ev MACHINE +As some manual pages are intended only for specific architectures, +.Nm +searches any subdirectories, +with the same name as the current architecture, +in every directory which it searches. +Machine specific areas are checked before general areas. +The current machine type may be overridden by setting the environment +variable +.Ev MACHINE +to the name of a specific architecture, +or with the +.Fl S +option. +.Ev MACHINE +is case insensitive. +.It Ev MANPAGER +Any non-empty value of the environment variable +.Ev MANPAGER +will be used instead of the standard pagination program, +.Xr more 1 . +If +.Xr less 1 +is used, the interactive +.Ic :t +command can be used to go to the definitions of various terms, for +example command line options, command modifiers, internal commands, +environment variables, function names, preprocessor macros, +.Xr errno 2 +values, and some other emphasized words. +Some terms may have defining text at more than one place. +In that case, the +.Xr less 1 +interactive commands +.Ic t +and +.Ic T +can be used to move to the next and to the previous place providing +information about the term last searched for with +.Ic :t . +.It Ev MANPATH +The standard search path used by +.Nm +may be overridden by specifying a path in the +.Ev MANPATH +environment +variable. +The format of the path is a colon +.Pq Ql \&: +separated list of directories. +.It Ev PAGER +Specifies the pagination program to use when +.Ev MANPAGER +is not defined. +If neither PAGER nor MANPAGER is defined, +.Xr more 1 +.Fl s +will be used. +.El +.Sh FILES +.Bl -tag -width /etc/man.conf -compact +.It Pa /etc/man.conf +default man configuration file +.El +.Sh EXIT STATUS +.Ex -std man +.Sh SEE ALSO +.Xr apropos 1 , +.Xr intro 1 , +.Xr whatis 1 , +.Xr whereis 1 , +.Xr intro 2 , +.Xr intro 3 , +.Xr intro 4 , +.Xr intro 5 , +.Xr man.conf 5 , +.Xr intro 6 , +.Xr intro 7 , +.Xr mdoc 7 , +.Xr intro 8 , +.Xr intro 9 +.Sh STANDARDS +The +.Nm +utility is compliant with the +.St -p1003.1-2008 +specification. +.Pp +The flags +.Op Fl aCcfhIKlMmOSsTWw , +as well as the environment variables +.Ev MACHINE , +.Ev MANPAGER , +and +.Ev MANPATH , +are extensions to that specification. +.Sh HISTORY +A +.Nm +command first appeared in +.At v3 . +.Pp +The +.Fl w +option first appeared in +.At v7 ; +.Fl f +and +.Fl k +in +.Bx 4 ; +.Fl M +in +.Bx 4.3 ; +.Fl a +in +.Bx 4.3 Tahoe ; +.Fl c +and +.Fl m +in +.Bx 4.3 Reno ; +.Fl h +in +.Bx 4.3 Net/2 ; +.Fl C +in +.Nx 1.0 ; +and +.Fl s +and +.Fl S +in +.Ox 2.3 . Property changes on: vendor/mdocml/20170121/man.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man.c =================================================================== --- vendor/mdocml/20170121/man.c (nonexistent) +++ vendor/mdocml/20170121/man.c (revision 312592) @@ -0,0 +1,369 @@ +/* $Id: man.c,v 1.167 2017/01/10 13:47:00 schwarze Exp $ */ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze + * Copyright (c) 2011 Joerg Sonnenberger + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "man.h" +#include "libmandoc.h" +#include "roff_int.h" +#include "libman.h" + +const char *const __man_macronames[MAN_MAX] = { + "br", "TH", "SH", "SS", + "TP", "LP", "PP", "P", + "IP", "HP", "SM", "SB", + "BI", "IB", "BR", "RB", + "R", "B", "I", "IR", + "RI", "sp", "nf", + "fi", "RE", "RS", "DT", + "UC", "PD", "AT", "in", + "ft", "OP", "EX", "EE", + "UR", "UE", "ll" + }; + +const char * const *man_macronames = __man_macronames; + +static void man_descope(struct roff_man *, int, int); +static int man_ptext(struct roff_man *, int, char *, int); +static int man_pmacro(struct roff_man *, int, char *, int); + + +int +man_parseln(struct roff_man *man, int ln, char *buf, int offs) +{ + + if (man->last->type != ROFFT_EQN || ln > man->last->line) + man->flags |= MAN_NEWLINE; + + return roff_getcontrol(man->roff, buf, &offs) ? + man_pmacro(man, ln, buf, offs) : + man_ptext(man, ln, buf, offs); +} + +static void +man_descope(struct roff_man *man, int line, int offs) +{ + /* + * Co-ordinate what happens with having a next-line scope open: + * first close out the element scope (if applicable), then close + * out the block scope (also if applicable). + */ + + if (man->flags & MAN_ELINE) { + man->flags &= ~MAN_ELINE; + man_unscope(man, man->last->parent); + } + if ( ! (man->flags & MAN_BLINE)) + return; + man->flags &= ~MAN_BLINE; + man_unscope(man, man->last->parent); + roff_body_alloc(man, line, offs, man->last->tok); +} + +static int +man_ptext(struct roff_man *man, int line, char *buf, int offs) +{ + int i; + + /* Literal free-form text whitespace is preserved. */ + + if (man->flags & MAN_LITERAL) { + roff_word_alloc(man, line, offs, buf + offs); + man_descope(man, line, offs); + return 1; + } + + for (i = offs; buf[i] == ' '; i++) + /* Skip leading whitespace. */ ; + + /* + * Blank lines are ignored right after headings + * but add a single vertical space elsewhere. + */ + + if (buf[i] == '\0') { + /* Allocate a blank entry. */ + if (man->last->tok != MAN_SH && + man->last->tok != MAN_SS) { + roff_elem_alloc(man, line, offs, MAN_sp); + man->next = ROFF_NEXT_SIBLING; + } + return 1; + } + + /* + * Warn if the last un-escaped character is whitespace. Then + * strip away the remaining spaces (tabs stay!). + */ + + i = (int)strlen(buf); + assert(i); + + if (' ' == buf[i - 1] || '\t' == buf[i - 1]) { + if (i > 1 && '\\' != buf[i - 2]) + mandoc_msg(MANDOCERR_SPACE_EOL, man->parse, + line, i - 1, NULL); + + for (--i; i && ' ' == buf[i]; i--) + /* Spin back to non-space. */ ; + + /* Jump ahead of escaped whitespace. */ + i += '\\' == buf[i] ? 2 : 1; + + buf[i] = '\0'; + } + roff_word_alloc(man, line, offs, buf + offs); + + /* + * End-of-sentence check. If the last character is an unescaped + * EOS character, then flag the node as being the end of a + * sentence. The front-end will know how to interpret this. + */ + + assert(i); + if (mandoc_eos(buf, (size_t)i)) + man->last->flags |= NODE_EOS; + + man_descope(man, line, offs); + return 1; +} + +static int +man_pmacro(struct roff_man *man, int ln, char *buf, int offs) +{ + struct roff_node *n; + const char *cp; + int tok; + int i, ppos; + int bline; + char mac[5]; + + ppos = offs; + + /* + * Copy the first word into a nil-terminated buffer. + * Stop when a space, tab, escape, or eoln is encountered. + */ + + i = 0; + while (i < 4 && strchr(" \t\\", buf[offs]) == NULL) + mac[i++] = buf[offs++]; + + mac[i] = '\0'; + + tok = (i > 0 && i < 4) ? man_hash_find(mac) : TOKEN_NONE; + + if (tok == TOKEN_NONE) { + mandoc_msg(MANDOCERR_MACRO, man->parse, + ln, ppos, buf + ppos - 1); + return 1; + } + + /* Skip a leading escape sequence or tab. */ + + switch (buf[offs]) { + case '\\': + cp = buf + offs + 1; + mandoc_escape(&cp, NULL, NULL); + offs = cp - buf; + break; + case '\t': + offs++; + break; + default: + break; + } + + /* Jump to the next non-whitespace word. */ + + while (buf[offs] && buf[offs] == ' ') + offs++; + + /* + * Trailing whitespace. Note that tabs are allowed to be passed + * into the parser as "text", so we only warn about spaces here. + */ + + if (buf[offs] == '\0' && buf[offs - 1] == ' ') + mandoc_msg(MANDOCERR_SPACE_EOL, man->parse, + ln, offs - 1, NULL); + + /* + * Some macros break next-line scopes; otherwise, remember + * whether we are in next-line scope for a block head. + */ + + man_breakscope(man, tok); + bline = man->flags & MAN_BLINE; + + /* Call to handler... */ + + assert(man_macros[tok].fp); + (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf); + + /* In quick mode (for mandocdb), abort after the NAME section. */ + + if (man->quick && tok == MAN_SH) { + n = man->last; + if (n->type == ROFFT_BODY && + strcmp(n->prev->child->string, "NAME")) + return 2; + } + + /* + * If we are in a next-line scope for a block head, + * close it out now and switch to the body, + * unless the next-line scope is allowed to continue. + */ + + if ( ! bline || man->flags & MAN_ELINE || + man_macros[tok].flags & MAN_NSCOPED) + return 1; + + assert(man->flags & MAN_BLINE); + man->flags &= ~MAN_BLINE; + + man_unscope(man, man->last->parent); + roff_body_alloc(man, ln, ppos, man->last->tok); + return 1; +} + +void +man_breakscope(struct roff_man *man, int tok) +{ + struct roff_node *n; + + /* + * An element next line scope is open, + * and the new macro is not allowed inside elements. + * Delete the element that is being broken. + */ + + if (man->flags & MAN_ELINE && (tok == TOKEN_NONE || + ! (man_macros[tok].flags & MAN_NSCOPED))) { + n = man->last; + assert(n->type != ROFFT_TEXT); + if (man_macros[n->tok].flags & MAN_NSCOPED) + n = n->parent; + + mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, + n->line, n->pos, "%s breaks %s", + tok == TOKEN_NONE ? "TS" : man_macronames[tok], + man_macronames[n->tok]); + + roff_node_delete(man, n); + man->flags &= ~MAN_ELINE; + } + + /* + * Weird special case: + * Switching fill mode closes section headers. + */ + + if (man->flags & MAN_BLINE && + (tok == MAN_nf || tok == MAN_fi) && + (man->last->tok == MAN_SH || man->last->tok == MAN_SS)) { + n = man->last; + man_unscope(man, n); + roff_body_alloc(man, n->line, n->pos, n->tok); + man->flags &= ~MAN_BLINE; + } + + /* + * A block header next line scope is open, + * and the new macro is not allowed inside block headers. + * Delete the block that is being broken. + */ + + if (man->flags & MAN_BLINE && (tok == TOKEN_NONE || + man_macros[tok].flags & MAN_BSCOPE)) { + n = man->last; + if (n->type == ROFFT_TEXT) + n = n->parent; + if ( ! (man_macros[n->tok].flags & MAN_BSCOPE)) + n = n->parent; + + assert(n->type == ROFFT_HEAD); + n = n->parent; + assert(n->type == ROFFT_BLOCK); + assert(man_macros[n->tok].flags & MAN_SCOPED); + + mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, + n->line, n->pos, "%s breaks %s", + tok == TOKEN_NONE ? "TS" : man_macronames[tok], + man_macronames[n->tok]); + + roff_node_delete(man, n); + man->flags &= ~MAN_BLINE; + } +} + +const struct mparse * +man_mparse(const struct roff_man *man) +{ + + assert(man && man->parse); + return man->parse; +} + +void +man_state(struct roff_man *man, struct roff_node *n) +{ + + switch(n->tok) { + case MAN_nf: + case MAN_EX: + if (man->flags & MAN_LITERAL && ! (n->flags & NODE_VALID)) + mandoc_msg(MANDOCERR_NF_SKIP, man->parse, + n->line, n->pos, "nf"); + man->flags |= MAN_LITERAL; + break; + case MAN_fi: + case MAN_EE: + if ( ! (man->flags & MAN_LITERAL) && + ! (n->flags & NODE_VALID)) + mandoc_msg(MANDOCERR_FI_SKIP, man->parse, + n->line, n->pos, "fi"); + man->flags &= ~MAN_LITERAL; + break; + default: + break; + } + man->last->flags |= NODE_VALID; +} + +void +man_validate(struct roff_man *man) +{ + + man->last = man->first; + man_node_validate(man); + man->flags &= ~MAN_LITERAL; +} Property changes on: vendor/mdocml/20170121/man.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man.conf.5 =================================================================== --- vendor/mdocml/20170121/man.conf.5 (nonexistent) +++ vendor/mdocml/20170121/man.conf.5 (revision 312592) @@ -0,0 +1,131 @@ +.\" $Id: man.conf.5,v 1.4 2016/12/28 22:52:17 schwarze Exp $ +.\" +.\" Copyright (c) 2015 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: December 28 2016 $ +.Dt MAN.CONF 5 +.Os +.Sh NAME +.Nm man.conf +.Nd configuration file for man +.Sh DESCRIPTION +This is the configuration file +for the +.Xr man 1 , +.Xr apropos 1 , +and +.Xr makewhatis 8 +utilities. +Its presence, and all directives, are optional. +.Pp +This file is an ASCII text file. +Leading whitespace on lines, lines starting with +.Sq # , +and blank lines are ignored. +Words are separated by whitespace. +The first word on each line is the name of a configuration directive. +.Pp +The following directives are supported: +.Bl -tag -width Ds +.It Ic manpath Ar path +Override the default search +.Ar path +for +.Xr man 1 , +.Xr apropos 1 , +and +.Xr makewhatis 8 . +It can be used multiple times to specify multiple paths, +with the order determining the manual page search order. +.Pp +Each path is a tree containing subdirectories +whose names consist of the strings +.Sq man +and/or +.Sq cat +followed by the names of sections, usually single digits. +The former are supposed to contain unformatted manual pages in +.Xr mdoc 7 +and/or +.Xr man 7 +format; file names should end with the name of the section +preceded by a dot. +The latter should contain preformatted manual pages; +file names should end with +.Ql .0 . +.Pp +Creating a +.Xr mandoc.db 5 +database with +.Xr makewhatis 8 +in each directory configured with +.Ic manpath +is recommended and necessary for +.Xr apropos 1 +to work, but not strictly required for +.Xr man 1 . +.It Ic output Ar option Op Ar value +Configure the default value of an output option. +These directives are overridden by the +.Fl O +command line options of the same names. +For details, see the +.Xr mandoc 1 +manual. +.Pp +.Bl -column fragment integer "ascii, utf8" -compact +.It Ar option Ta Ar value Ta used by Fl T Ta purpose +.It Ta Ta Ta +.It Ic fragment Ta none Ta Cm html Ta print only body +.It Ic includes Ta string Ta Cm html Ta path to header files +.It Ic indent Ta integer Ta Cm ascii , utf8 Ta left margin +.It Ic man Ta string Ta Cm html Ta path for \&Xr links +.It Ic paper Ta string Ta Cm ps , pdf Ta paper size +.It Ic style Ta string Ta Cm html Ta CSS file +.It Ic width Ta integer Ta Cm ascii , utf8 Ta right margin +.El +.It Ic _whatdb Ar path Ns Cm /whatis.db +This directive provides the same functionality as +.Ic manpath , +but using a historic and misleading syntax. +It is kept for backward compatibility for now, +but will eventually be removed. +.El +.Sh FILES +.Pa /etc/man.conf +.Sh EXAMPLES +The following configuration file reproduces the defaults: +installing it is equivalent to not having a +.Nm +file at all. +.Bd -literal -offset indent +manpath /usr/share/man +manpath /usr/X11R6/man +manpath /usr/local/man +.Ed +.Sh SEE ALSO +.Xr apropos 1 , +.Xr man 1 , +.Xr makewhatis 8 +.Sh HISTORY +A relatively complicated +.Nm +file format first appeared in +.Bx 4.3 Reno . +For +.Ox 5.8 , +it was redesigned from scratch, aiming for simplicity. +.Sh AUTHORS +.An Ingo Schwarze Aq Mt schwarze@openbsd.org Property changes on: vendor/mdocml/20170121/man.conf.5 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man_hash.c =================================================================== --- vendor/mdocml/20170121/man_hash.c (nonexistent) +++ vendor/mdocml/20170121/man_hash.c (revision 312592) @@ -0,0 +1,103 @@ +/* $Id: man_hash.c,v 1.35 2016/07/15 18:03:45 schwarze Exp $ */ +/* + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons + * Copyright (c) 2015 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include + +#include "mandoc.h" +#include "roff.h" +#include "man.h" +#include "libmandoc.h" +#include "libman.h" + +#define HASH_DEPTH 6 + +#define HASH_ROW(x) do { \ + if (isupper((unsigned char)(x))) \ + (x) -= 65; \ + else \ + (x) -= 97; \ + (x) *= HASH_DEPTH; \ + } while (/* CONSTCOND */ 0) + +/* + * Lookup table is indexed first by lower-case first letter (plus one + * for the period, which is stored in the last row), then by lower or + * uppercase second letter. Buckets correspond to the index of the + * macro (the integer value of the enum stored as a char to save a bit + * of space). + */ +static unsigned char table[26 * HASH_DEPTH]; + + +void +man_hash_init(void) +{ + int i, j, x; + + if (*table != '\0') + return; + + memset(table, UCHAR_MAX, sizeof(table)); + + for (i = 0; i < (int)MAN_MAX; i++) { + x = man_macronames[i][0]; + + assert(isalpha((unsigned char)x)); + + HASH_ROW(x); + + for (j = 0; j < HASH_DEPTH; j++) + if (UCHAR_MAX == table[x + j]) { + table[x + j] = (unsigned char)i; + break; + } + + assert(j < HASH_DEPTH); + } +} + +int +man_hash_find(const char *tmp) +{ + int x, y, i; + int tok; + + if ('\0' == (x = tmp[0])) + return TOKEN_NONE; + if ( ! (isalpha((unsigned char)x))) + return TOKEN_NONE; + + HASH_ROW(x); + + for (i = 0; i < HASH_DEPTH; i++) { + if (UCHAR_MAX == (y = table[x + i])) + return TOKEN_NONE; + + tok = y; + if (0 == strcmp(tmp, man_macronames[tok])) + return tok; + } + + return TOKEN_NONE; +} Property changes on: vendor/mdocml/20170121/man_hash.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man_html.c =================================================================== --- vendor/mdocml/20170121/man_html.c (nonexistent) +++ vendor/mdocml/20170121/man_html.c (revision 312592) @@ -0,0 +1,616 @@ +/* $Id: man_html.c,v 1.129 2017/01/21 01:20:32 schwarze Exp $ */ +/* + * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons + * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "roff.h" +#include "man.h" +#include "out.h" +#include "html.h" +#include "main.h" + +/* TODO: preserve ident widths. */ +/* FIXME: have PD set the default vspace width. */ + +#define INDENT 5 + +#define MAN_ARGS const struct roff_meta *man, \ + const struct roff_node *n, \ + struct mhtml *mh, \ + struct html *h + +struct mhtml { + int fl; +#define MANH_LITERAL (1 << 0) /* literal context */ +}; + +struct htmlman { + int (*pre)(MAN_ARGS); + int (*post)(MAN_ARGS); +}; + +static void print_bvspace(struct html *, + const struct roff_node *); +static void print_man_head(MAN_ARGS); +static void print_man_nodelist(MAN_ARGS); +static void print_man_node(MAN_ARGS); +static int a2width(const struct roff_node *, + struct roffsu *); +static int man_B_pre(MAN_ARGS); +static int man_HP_pre(MAN_ARGS); +static int man_IP_pre(MAN_ARGS); +static int man_I_pre(MAN_ARGS); +static int man_OP_pre(MAN_ARGS); +static int man_PP_pre(MAN_ARGS); +static int man_RS_pre(MAN_ARGS); +static int man_SH_pre(MAN_ARGS); +static int man_SM_pre(MAN_ARGS); +static int man_SS_pre(MAN_ARGS); +static int man_UR_pre(MAN_ARGS); +static int man_alt_pre(MAN_ARGS); +static int man_br_pre(MAN_ARGS); +static int man_ign_pre(MAN_ARGS); +static int man_in_pre(MAN_ARGS); +static int man_literal_pre(MAN_ARGS); +static void man_root_post(MAN_ARGS); +static void man_root_pre(MAN_ARGS); + +static const struct htmlman mans[MAN_MAX] = { + { man_br_pre, NULL }, /* br */ + { NULL, NULL }, /* TH */ + { man_SH_pre, NULL }, /* SH */ + { man_SS_pre, NULL }, /* SS */ + { man_IP_pre, NULL }, /* TP */ + { man_PP_pre, NULL }, /* LP */ + { man_PP_pre, NULL }, /* PP */ + { man_PP_pre, NULL }, /* P */ + { man_IP_pre, NULL }, /* IP */ + { man_HP_pre, NULL }, /* HP */ + { man_SM_pre, NULL }, /* SM */ + { man_SM_pre, NULL }, /* SB */ + { man_alt_pre, NULL }, /* BI */ + { man_alt_pre, NULL }, /* IB */ + { man_alt_pre, NULL }, /* BR */ + { man_alt_pre, NULL }, /* RB */ + { NULL, NULL }, /* R */ + { man_B_pre, NULL }, /* B */ + { man_I_pre, NULL }, /* I */ + { man_alt_pre, NULL }, /* IR */ + { man_alt_pre, NULL }, /* RI */ + { man_br_pre, NULL }, /* sp */ + { man_literal_pre, NULL }, /* nf */ + { man_literal_pre, NULL }, /* fi */ + { NULL, NULL }, /* RE */ + { man_RS_pre, NULL }, /* RS */ + { man_ign_pre, NULL }, /* DT */ + { man_ign_pre, NULL }, /* UC */ + { man_ign_pre, NULL }, /* PD */ + { man_ign_pre, NULL }, /* AT */ + { man_in_pre, NULL }, /* in */ + { man_ign_pre, NULL }, /* ft */ + { man_OP_pre, NULL }, /* OP */ + { man_literal_pre, NULL }, /* EX */ + { man_literal_pre, NULL }, /* EE */ + { man_UR_pre, NULL }, /* UR */ + { NULL, NULL }, /* UE */ + { man_ign_pre, NULL }, /* ll */ +}; + + +/* + * Printing leading vertical space before a block. + * This is used for the paragraph macros. + * The rules are pretty simple, since there's very little nesting going + * on here. Basically, if we're the first within another block (SS/SH), + * then don't emit vertical space. If we are (RS), then do. If not the + * first, print it. + */ +static void +print_bvspace(struct html *h, const struct roff_node *n) +{ + + if (n->body && n->body->child) + if (n->body->child->type == ROFFT_TBL) + return; + + if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) + if (NULL == n->prev) + return; + + print_paragraph(h); +} + +void +html_man(void *arg, const struct roff_man *man) +{ + struct mhtml mh; + struct html *h; + struct tag *t; + + memset(&mh, 0, sizeof(mh)); + h = (struct html *)arg; + + if ((h->oflags & HTML_FRAGMENT) == 0) { + print_gen_decls(h); + print_otag(h, TAG_HTML, ""); + t = print_otag(h, TAG_HEAD, ""); + print_man_head(&man->meta, man->first, &mh, h); + print_tagq(h, t); + print_otag(h, TAG_BODY, ""); + } + + man_root_pre(&man->meta, man->first, &mh, h); + t = print_otag(h, TAG_DIV, "c", "manual-text"); + print_man_nodelist(&man->meta, man->first->child, &mh, h); + print_tagq(h, t); + man_root_post(&man->meta, man->first, &mh, h); + print_tagq(h, NULL); +} + +static void +print_man_head(MAN_ARGS) +{ + char *cp; + + print_gen_head(h); + mandoc_asprintf(&cp, "%s(%s)", man->title, man->msec); + print_otag(h, TAG_TITLE, ""); + print_text(h, cp); + free(cp); +} + +static void +print_man_nodelist(MAN_ARGS) +{ + + while (n != NULL) { + print_man_node(man, n, mh, h); + n = n->next; + } +} + +static void +print_man_node(MAN_ARGS) +{ + int child; + struct tag *t; + + child = 1; + t = h->tags.head; + + switch (n->type) { + case ROFFT_TEXT: + if ('\0' == *n->string) { + print_paragraph(h); + return; + } + if (n->flags & NODE_LINE && (*n->string == ' ' || + (n->prev != NULL && mh->fl & MANH_LITERAL && + ! (h->flags & HTML_NONEWLINE)))) + print_otag(h, TAG_BR, ""); + print_text(h, n->string); + return; + case ROFFT_EQN: + print_eqn(h, n->eqn); + break; + case ROFFT_TBL: + /* + * This will take care of initialising all of the table + * state data for the first table, then tearing it down + * for the last one. + */ + print_tbl(h, n->span); + return; + default: + /* + * Close out scope of font prior to opening a macro + * scope. + */ + if (HTMLFONT_NONE != h->metac) { + h->metal = h->metac; + h->metac = HTMLFONT_NONE; + } + + /* + * Close out the current table, if it's open, and unset + * the "meta" table state. This will be reopened on the + * next table element. + */ + if (h->tblt) { + print_tblclose(h); + t = h->tags.head; + } + if (mans[n->tok].pre) + child = (*mans[n->tok].pre)(man, n, mh, h); + break; + } + + if (child && n->child) + print_man_nodelist(man, n->child, mh, h); + + /* This will automatically close out any font scope. */ + print_stagq(h, t); + + switch (n->type) { + case ROFFT_EQN: + break; + default: + if (mans[n->tok].post) + (*mans[n->tok].post)(man, n, mh, h); + break; + } +} + +static int +a2width(const struct roff_node *n, struct roffsu *su) +{ + + if (n->type != ROFFT_TEXT) + return 0; + if (a2roffsu(n->string, su, SCALE_EN)) + return 1; + + return 0; +} + +static void +man_root_pre(MAN_ARGS) +{ + struct tag *t, *tt; + char *title; + + assert(man->title); + assert(man->msec); + mandoc_asprintf(&title, "%s(%s)", man->title, man->msec); + + t = print_otag(h, TAG_TABLE, "c", "head"); + print_otag(h, TAG_TBODY, ""); + tt = print_otag(h, TAG_TR, ""); + + print_otag(h, TAG_TD, "c", "head-ltitle"); + print_text(h, title); + print_stagq(h, tt); + + print_otag(h, TAG_TD, "c", "head-vol"); + if (NULL != man->vol) + print_text(h, man->vol); + print_stagq(h, tt); + + print_otag(h, TAG_TD, "c", "head-rtitle"); + print_text(h, title); + print_tagq(h, t); + free(title); +} + +static void +man_root_post(MAN_ARGS) +{ + struct tag *t, *tt; + + t = print_otag(h, TAG_TABLE, "c", "foot"); + tt = print_otag(h, TAG_TR, ""); + + print_otag(h, TAG_TD, "c", "foot-date"); + print_text(h, man->date); + print_stagq(h, tt); + + print_otag(h, TAG_TD, "c", "foot-os"); + if (man->os) + print_text(h, man->os); + print_tagq(h, t); +} + + +static int +man_br_pre(MAN_ARGS) +{ + struct roffsu su; + + SCALE_VS_INIT(&su, 1); + + if (MAN_sp == n->tok) { + if (NULL != (n = n->child)) + if ( ! a2roffsu(n->string, &su, SCALE_VS)) + su.scale = 1.0; + } else + su.scale = 0.0; + + print_otag(h, TAG_DIV, "suh", &su); + + /* So the div isn't empty: */ + print_text(h, "\\~"); + + return 0; +} + +static int +man_SH_pre(MAN_ARGS) +{ + if (n->type == ROFFT_BLOCK) { + mh->fl &= ~MANH_LITERAL; + return 1; + } else if (n->type == ROFFT_BODY) + return 1; + + print_otag(h, TAG_H1, "c", "Sh"); + return 1; +} + +static int +man_alt_pre(MAN_ARGS) +{ + const struct roff_node *nn; + int i, savelit; + enum htmltag fp; + struct tag *t; + + if ((savelit = mh->fl & MANH_LITERAL)) + print_otag(h, TAG_BR, ""); + + mh->fl &= ~MANH_LITERAL; + + for (i = 0, nn = n->child; nn; nn = nn->next, i++) { + t = NULL; + switch (n->tok) { + case MAN_BI: + fp = i % 2 ? TAG_I : TAG_B; + break; + case MAN_IB: + fp = i % 2 ? TAG_B : TAG_I; + break; + case MAN_RI: + fp = i % 2 ? TAG_I : TAG_MAX; + break; + case MAN_IR: + fp = i % 2 ? TAG_MAX : TAG_I; + break; + case MAN_BR: + fp = i % 2 ? TAG_MAX : TAG_B; + break; + case MAN_RB: + fp = i % 2 ? TAG_B : TAG_MAX; + break; + default: + abort(); + } + + if (i) + h->flags |= HTML_NOSPACE; + + if (TAG_MAX != fp) + t = print_otag(h, fp, ""); + + print_man_node(man, nn, mh, h); + + if (t) + print_tagq(h, t); + } + + if (savelit) + mh->fl |= MANH_LITERAL; + + return 0; +} + +static int +man_SM_pre(MAN_ARGS) +{ + print_otag(h, TAG_SMALL, ""); + if (MAN_SB == n->tok) + print_otag(h, TAG_B, ""); + return 1; +} + +static int +man_SS_pre(MAN_ARGS) +{ + if (n->type == ROFFT_BLOCK) { + mh->fl &= ~MANH_LITERAL; + return 1; + } else if (n->type == ROFFT_BODY) + return 1; + + print_otag(h, TAG_H2, "c", "Ss"); + return 1; +} + +static int +man_PP_pre(MAN_ARGS) +{ + + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type == ROFFT_BLOCK) + print_bvspace(h, n); + + return 1; +} + +static int +man_IP_pre(MAN_ARGS) +{ + const struct roff_node *nn; + + if (n->type == ROFFT_BODY) { + print_otag(h, TAG_DD, "c", "It-tag"); + return 1; + } else if (n->type != ROFFT_HEAD) { + print_otag(h, TAG_DL, "c", "Bl-tag"); + return 1; + } + + /* FIXME: width specification. */ + + print_otag(h, TAG_DT, "c", "It-tag"); + + /* For IP, only print the first header element. */ + + if (MAN_IP == n->tok && n->child) + print_man_node(man, n->child, mh, h); + + /* For TP, only print next-line header elements. */ + + if (MAN_TP == n->tok) { + nn = n->child; + while (NULL != nn && 0 == (NODE_LINE & nn->flags)) + nn = nn->next; + while (NULL != nn) { + print_man_node(man, nn, mh, h); + nn = nn->next; + } + } + + return 0; +} + +static int +man_HP_pre(MAN_ARGS) +{ + struct roffsu sum, sui; + const struct roff_node *np; + + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type != ROFFT_BLOCK) + return 1; + + np = n->head->child; + + if (np == NULL || !a2width(np, &sum)) + SCALE_HS_INIT(&sum, INDENT); + + sui.unit = sum.unit; + sui.scale = -sum.scale; + + print_bvspace(h, n); + print_otag(h, TAG_DIV, "csului", "Pp", &sum, &sui); + return 1; +} + +static int +man_OP_pre(MAN_ARGS) +{ + struct tag *tt; + + print_text(h, "["); + h->flags |= HTML_NOSPACE; + tt = print_otag(h, TAG_SPAN, "c", "Op"); + + if (NULL != (n = n->child)) { + print_otag(h, TAG_B, ""); + print_text(h, n->string); + } + + print_stagq(h, tt); + + if (NULL != n && NULL != n->next) { + print_otag(h, TAG_I, ""); + print_text(h, n->next->string); + } + + print_stagq(h, tt); + h->flags |= HTML_NOSPACE; + print_text(h, "]"); + return 0; +} + +static int +man_B_pre(MAN_ARGS) +{ + print_otag(h, TAG_B, ""); + return 1; +} + +static int +man_I_pre(MAN_ARGS) +{ + print_otag(h, TAG_I, ""); + return 1; +} + +static int +man_literal_pre(MAN_ARGS) +{ + + if (MAN_fi == n->tok || MAN_EE == n->tok) { + print_otag(h, TAG_BR, ""); + mh->fl &= ~MANH_LITERAL; + } else + mh->fl |= MANH_LITERAL; + + return 0; +} + +static int +man_in_pre(MAN_ARGS) +{ + print_otag(h, TAG_BR, ""); + return 0; +} + +static int +man_ign_pre(MAN_ARGS) +{ + + return 0; +} + +static int +man_RS_pre(MAN_ARGS) +{ + struct roffsu su; + + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type == ROFFT_BODY) + return 1; + + SCALE_HS_INIT(&su, INDENT); + if (n->head->child) + a2width(n->head->child, &su); + + print_otag(h, TAG_DIV, "sul", &su); + return 1; +} + +static int +man_UR_pre(MAN_ARGS) +{ + n = n->child; + assert(n->type == ROFFT_HEAD); + if (n->child != NULL) { + assert(n->child->type == ROFFT_TEXT); + print_otag(h, TAG_A, "ch", "Lk", n->child->string); + } + + assert(n->next->type == ROFFT_BODY); + if (n->next->child != NULL) + n = n->next; + + print_man_nodelist(man, n->child, mh, h); + + return 0; +} Property changes on: vendor/mdocml/20170121/man_html.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man_macro.c =================================================================== --- vendor/mdocml/20170121/man_macro.c (nonexistent) +++ vendor/mdocml/20170121/man_macro.c (revision 312592) @@ -0,0 +1,413 @@ +/* $Id: man_macro.c,v 1.115 2017/01/10 13:47:00 schwarze Exp $ */ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons + * Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze + * Copyright (c) 2013 Franco Fichtner + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include + +#include "mandoc.h" +#include "roff.h" +#include "man.h" +#include "libmandoc.h" +#include "roff_int.h" +#include "libman.h" + +static void blk_close(MACRO_PROT_ARGS); +static void blk_exp(MACRO_PROT_ARGS); +static void blk_imp(MACRO_PROT_ARGS); +static void in_line_eoln(MACRO_PROT_ARGS); +static int man_args(struct roff_man *, int, + int *, char *, char **); +static void rew_scope(struct roff_man *, int); + +const struct man_macro __man_macros[MAN_MAX] = { + { in_line_eoln, MAN_NSCOPED }, /* br */ + { in_line_eoln, MAN_BSCOPE }, /* TH */ + { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */ + { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */ + { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TP */ + { blk_imp, MAN_BSCOPE }, /* LP */ + { blk_imp, MAN_BSCOPE }, /* PP */ + { blk_imp, MAN_BSCOPE }, /* P */ + { blk_imp, MAN_BSCOPE }, /* IP */ + { blk_imp, MAN_BSCOPE }, /* HP */ + { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SM */ + { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SB */ + { in_line_eoln, 0 }, /* BI */ + { in_line_eoln, 0 }, /* IB */ + { in_line_eoln, 0 }, /* BR */ + { in_line_eoln, 0 }, /* RB */ + { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* R */ + { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* B */ + { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */ + { in_line_eoln, 0 }, /* IR */ + { in_line_eoln, 0 }, /* RI */ + { in_line_eoln, MAN_NSCOPED }, /* sp */ + { in_line_eoln, MAN_NSCOPED }, /* nf */ + { in_line_eoln, MAN_NSCOPED }, /* fi */ + { blk_close, MAN_BSCOPE }, /* RE */ + { blk_exp, MAN_BSCOPE }, /* RS */ + { in_line_eoln, 0 }, /* DT */ + { in_line_eoln, 0 }, /* UC */ + { in_line_eoln, MAN_NSCOPED }, /* PD */ + { in_line_eoln, 0 }, /* AT */ + { in_line_eoln, 0 }, /* in */ + { in_line_eoln, 0 }, /* ft */ + { in_line_eoln, 0 }, /* OP */ + { in_line_eoln, MAN_BSCOPE }, /* EX */ + { in_line_eoln, MAN_BSCOPE }, /* EE */ + { blk_exp, MAN_BSCOPE }, /* UR */ + { blk_close, MAN_BSCOPE }, /* UE */ + { in_line_eoln, 0 }, /* ll */ +}; + +const struct man_macro * const man_macros = __man_macros; + + +void +man_unscope(struct roff_man *man, const struct roff_node *to) +{ + struct roff_node *n; + + to = to->parent; + n = man->last; + while (n != to) { + + /* Reached the end of the document? */ + + if (to == NULL && ! (n->flags & NODE_VALID)) { + if (man->flags & (MAN_BLINE | MAN_ELINE) && + man_macros[n->tok].flags & MAN_SCOPED) { + mandoc_vmsg(MANDOCERR_BLK_LINE, + man->parse, n->line, n->pos, + "EOF breaks %s", + man_macronames[n->tok]); + if (man->flags & MAN_ELINE) + man->flags &= ~MAN_ELINE; + else { + assert(n->type == ROFFT_HEAD); + n = n->parent; + man->flags &= ~MAN_BLINE; + } + man->last = n; + n = n->parent; + roff_node_delete(man, man->last); + continue; + } + if (n->type == ROFFT_BLOCK && + man_macros[n->tok].fp == blk_exp) + mandoc_msg(MANDOCERR_BLK_NOEND, + man->parse, n->line, n->pos, + man_macronames[n->tok]); + } + + /* + * We might delete the man->last node + * in the post-validation phase. + * Save a pointer to the parent such that + * we know where to continue the iteration. + */ + + man->last = n; + n = n->parent; + man->last->flags |= NODE_VALID; + } + + /* + * If we ended up at the parent of the node we were + * supposed to rewind to, that means the target node + * got deleted, so add the next node we parse as a child + * of the parent instead of as a sibling of the target. + */ + + man->next = (man->last == to) ? + ROFF_NEXT_CHILD : ROFF_NEXT_SIBLING; +} + +/* + * Rewinding entails ascending the parse tree until a coherent point, + * for example, the `SH' macro will close out any intervening `SS' + * scopes. When a scope is closed, it must be validated and actioned. + */ +static void +rew_scope(struct roff_man *man, int tok) +{ + struct roff_node *n; + + /* Preserve empty paragraphs before RS. */ + + n = man->last; + if (tok == MAN_RS && n->child == NULL && + (n->tok == MAN_P || n->tok == MAN_PP || n->tok == MAN_LP)) + return; + + for (;;) { + if (n->type == ROFFT_ROOT) + return; + if (n->flags & NODE_VALID) { + n = n->parent; + continue; + } + if (n->type != ROFFT_BLOCK) { + if (n->parent->type == ROFFT_ROOT) { + man_unscope(man, n); + return; + } else { + n = n->parent; + continue; + } + } + if (tok != MAN_SH && (n->tok == MAN_SH || + (tok != MAN_SS && (n->tok == MAN_SS || + man_macros[n->tok].fp == blk_exp)))) + return; + man_unscope(man, n); + n = man->last; + } +} + + +/* + * Close out a generic explicit macro. + */ +void +blk_close(MACRO_PROT_ARGS) +{ + int ntok; + const struct roff_node *nn; + char *p; + int nrew, target; + + nrew = 1; + switch (tok) { + case MAN_RE: + ntok = MAN_RS; + if ( ! man_args(man, line, pos, buf, &p)) + break; + for (nn = man->last->parent; nn; nn = nn->parent) + if (nn->tok == ntok && nn->type == ROFFT_BLOCK) + nrew++; + target = strtol(p, &p, 10); + if (*p != '\0') + mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, + line, p - buf, "RE ... %s", p); + if (target == 0) + target = 1; + nrew -= target; + if (nrew < 1) { + mandoc_vmsg(MANDOCERR_RE_NOTOPEN, man->parse, + line, ppos, "RE %d", target); + return; + } + break; + case MAN_UE: + ntok = MAN_UR; + break; + default: + abort(); + } + + for (nn = man->last->parent; nn; nn = nn->parent) + if (nn->tok == ntok && nn->type == ROFFT_BLOCK && ! --nrew) + break; + + if (nn == NULL) { + mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse, + line, ppos, man_macronames[tok]); + rew_scope(man, MAN_PP); + } else { + line = man->last->line; + ppos = man->last->pos; + ntok = man->last->tok; + man_unscope(man, nn); + + /* Move a trailing paragraph behind the block. */ + + if (ntok == MAN_LP || ntok == MAN_PP || ntok == MAN_P) { + *pos = strlen(buf); + blk_imp(man, ntok, line, ppos, pos, buf); + } + } +} + +void +blk_exp(MACRO_PROT_ARGS) +{ + struct roff_node *head; + char *p; + int la; + + rew_scope(man, tok); + roff_block_alloc(man, line, ppos, tok); + head = roff_head_alloc(man, line, ppos, tok); + + la = *pos; + if (man_args(man, line, pos, buf, &p)) + roff_word_alloc(man, line, la, p); + + if (buf[*pos] != '\0') + mandoc_vmsg(MANDOCERR_ARG_EXCESS, + man->parse, line, *pos, "%s ... %s", + man_macronames[tok], buf + *pos); + + man_unscope(man, head); + roff_body_alloc(man, line, ppos, tok); +} + +/* + * Parse an implicit-block macro. These contain a ROFFT_HEAD and a + * ROFFT_BODY contained within a ROFFT_BLOCK. Rules for closing out other + * scopes, such as `SH' closing out an `SS', are defined in the rew + * routines. + */ +void +blk_imp(MACRO_PROT_ARGS) +{ + int la; + char *p; + struct roff_node *n; + + rew_scope(man, tok); + n = roff_block_alloc(man, line, ppos, tok); + if (n->tok == MAN_SH || n->tok == MAN_SS) + man->flags &= ~MAN_LITERAL; + n = roff_head_alloc(man, line, ppos, tok); + + /* Add line arguments. */ + + for (;;) { + la = *pos; + if ( ! man_args(man, line, pos, buf, &p)) + break; + roff_word_alloc(man, line, la, p); + } + + /* + * For macros having optional next-line scope, + * keep the head open if there were no arguments. + * For `TP', always keep the head open. + */ + + if (man_macros[tok].flags & MAN_SCOPED && + (tok == MAN_TP || n == man->last)) { + man->flags |= MAN_BLINE; + return; + } + + /* Close out the head and open the body. */ + + man_unscope(man, n); + roff_body_alloc(man, line, ppos, tok); +} + +void +in_line_eoln(MACRO_PROT_ARGS) +{ + int la; + char *p; + struct roff_node *n; + + roff_elem_alloc(man, line, ppos, tok); + n = man->last; + + for (;;) { + if (buf[*pos] != '\0' && (tok == MAN_br || + tok == MAN_fi || tok == MAN_nf)) { + mandoc_vmsg(MANDOCERR_ARG_SKIP, + man->parse, line, *pos, "%s %s", + man_macronames[tok], buf + *pos); + break; + } + if (buf[*pos] != '\0' && man->last != n && + (tok == MAN_PD || tok == MAN_ft || tok == MAN_sp)) { + mandoc_vmsg(MANDOCERR_ARG_EXCESS, + man->parse, line, *pos, "%s ... %s", + man_macronames[tok], buf + *pos); + break; + } + la = *pos; + if ( ! man_args(man, line, pos, buf, &p)) + break; + if (man_macros[tok].flags & MAN_JOIN && + man->last->type == ROFFT_TEXT) + roff_word_append(man, p); + else + roff_word_alloc(man, line, la, p); + } + + /* + * Append NODE_EOS in case the last snipped argument + * ends with a dot, e.g. `.IR syslog (3).' + */ + + if (n != man->last && + mandoc_eos(man->last->string, strlen(man->last->string))) + man->last->flags |= NODE_EOS; + + /* + * If no arguments are specified and this is MAN_SCOPED (i.e., + * next-line scoped), then set our mode to indicate that we're + * waiting for terms to load into our context. + */ + + if (n == man->last && man_macros[tok].flags & MAN_SCOPED) { + assert( ! (man_macros[tok].flags & MAN_NSCOPED)); + man->flags |= MAN_ELINE; + return; + } + + assert(man->last->type != ROFFT_ROOT); + man->next = ROFF_NEXT_SIBLING; + + /* Rewind our element scope. */ + + for ( ; man->last; man->last = man->last->parent) { + man_state(man, man->last); + if (man->last == n) + break; + } +} + +void +man_endparse(struct roff_man *man) +{ + + man_unscope(man, man->first); + man->flags &= ~MAN_LITERAL; +} + +static int +man_args(struct roff_man *man, int line, int *pos, char *buf, char **v) +{ + char *start; + + assert(*pos); + *v = start = buf + *pos; + assert(' ' != *start); + + if ('\0' == *start) + return 0; + + *v = mandoc_getarg(man->parse, v, line, pos); + return 1; +} Property changes on: vendor/mdocml/20170121/man_macro.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/man_term.c =================================================================== --- vendor/mdocml/20170121/man_term.c (nonexistent) +++ vendor/mdocml/20170121/man_term.c (revision 312592) @@ -0,0 +1,1177 @@ +/* $Id: man_term.c,v 1.188 2017/01/10 13:47:00 schwarze Exp $ */ +/* + * Copyright (c) 2008-2012 Kristaps Dzonsons + * Copyright (c) 2010-2015 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "man.h" +#include "out.h" +#include "term.h" +#include "main.h" + +#define MAXMARGINS 64 /* maximum number of indented scopes */ + +struct mtermp { + int fl; +#define MANT_LITERAL (1 << 0) + int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */ + 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, \ + struct roff_node *n, \ + const struct roff_meta *meta + +struct termact { + int (*pre)(DECL_ARGS); + void (*post)(DECL_ARGS); + int flags; +#define MAN_NOTEXT (1 << 0) /* Never has text children. */ +}; + +static void print_man_nodelist(DECL_ARGS); +static void print_man_node(DECL_ARGS); +static void print_man_head(struct termp *, + const struct roff_meta *); +static void print_man_foot(struct termp *, + const struct roff_meta *); +static void print_bvspace(struct termp *, + const struct roff_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); +static int pre_in(DECL_ARGS); +static int pre_literal(DECL_ARGS); +static int pre_ll(DECL_ARGS); +static int pre_sp(DECL_ARGS); + +static void post_IP(DECL_ARGS); +static void post_HP(DECL_ARGS); +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 */ + { NULL, NULL, 0 }, /* TH */ + { pre_SH, post_SH, 0 }, /* SH */ + { pre_SS, post_SS, 0 }, /* SS */ + { pre_TP, post_TP, 0 }, /* TP */ + { pre_PP, NULL, 0 }, /* LP */ + { pre_PP, NULL, 0 }, /* PP */ + { pre_PP, NULL, 0 }, /* P */ + { pre_IP, post_IP, 0 }, /* IP */ + { pre_HP, post_HP, 0 }, /* HP */ + { NULL, NULL, 0 }, /* SM */ + { pre_B, NULL, 0 }, /* SB */ + { pre_alternate, NULL, 0 }, /* BI */ + { pre_alternate, NULL, 0 }, /* IB */ + { pre_alternate, NULL, 0 }, /* BR */ + { pre_alternate, NULL, 0 }, /* RB */ + { NULL, NULL, 0 }, /* R */ + { pre_B, NULL, 0 }, /* B */ + { pre_I, NULL, 0 }, /* I */ + { pre_alternate, NULL, 0 }, /* IR */ + { pre_alternate, NULL, 0 }, /* RI */ + { pre_sp, NULL, MAN_NOTEXT }, /* sp */ + { pre_literal, NULL, 0 }, /* nf */ + { pre_literal, NULL, 0 }, /* fi */ + { NULL, NULL, 0 }, /* RE */ + { pre_RS, post_RS, 0 }, /* RS */ + { pre_ign, NULL, 0 }, /* DT */ + { pre_ign, NULL, MAN_NOTEXT }, /* UC */ + { 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 */ + { pre_ll, NULL, MAN_NOTEXT }, /* ll */ +}; + + +void +terminal_man(void *arg, const struct roff_man *man) +{ + struct termp *p; + struct roff_node *n; + struct mtermp mt; + + p = (struct termp *)arg; + p->overstep = 0; + p->rmargin = p->maxrmargin = p->defrmargin; + p->tabwidth = term_len(p, 5); + + 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; + + n = man->first->child; + if (p->synopsisonly) { + while (n != NULL) { + if (n->tok == MAN_SH && + n->child->child->type == ROFFT_TEXT && + !strcmp(n->child->child->string, "SYNOPSIS")) { + if (n->child->next->child != NULL) + print_man_nodelist(p, &mt, + n->child->next->child, + &man->meta); + term_newln(p); + break; + } + n = n->next; + } + } else { + if (p->defindent == 0) + p->defindent = 7; + term_begin(p, print_man_head, print_man_foot, &man->meta); + p->flags |= TERMP_NOSPACE; + if (n != NULL) + print_man_nodelist(p, &mt, n, &man->meta); + term_end(p); + } +} + +/* + * Printing leading vertical space before a block. + * This is used for the paragraph macros. + * The rules are pretty simple, since there's very little nesting going + * on here. Basically, if we're the first within another block (SS/SH), + * then don't emit vertical space. If we are (RS), then do. If not the + * first, print it. + */ +static void +print_bvspace(struct termp *p, const struct roff_node *n, int pardist) +{ + int i; + + term_newln(p); + + if (n->body && n->body->child) + if (n->body->child->type == ROFFT_TBL) + return; + + if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) + if (NULL == n->prev) + return; + + for (i = 0; i < pardist; i++) + term_vspace(p); +} + + +static int +pre_ign(DECL_ARGS) +{ + + return 0; +} + +static int +pre_ll(DECL_ARGS) +{ + + term_setwidth(p, n->child != NULL ? n->child->string : NULL); + return 0; +} + +static int +pre_I(DECL_ARGS) +{ + + term_fontrepl(p, TERMFONT_UNDER); + return 1; +} + +static int +pre_literal(DECL_ARGS) +{ + + term_newln(p); + + if (MAN_nf == n->tok || MAN_EX == n->tok) + mt->fl |= MANT_LITERAL; + else + mt->fl &= ~MANT_LITERAL; + + /* + * Unlike .IP and .TP, .HP does not have a HEAD. + * So in case a second call to term_flushln() is needed, + * indentation has to be set up explicitly. + */ + if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) { + p->offset = p->rmargin; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + p->flags |= TERMP_NOSPACE; + } + + return 0; +} + +static int +pre_PD(DECL_ARGS) +{ + struct roffsu su; + + n = n->child; + if (n == NULL) { + mt->pardist = 1; + return 0; + } + assert(n->type == ROFFT_TEXT); + if (a2roffsu(n->string, &su, SCALE_VS)) + mt->pardist = term_vspan(p, &su); + return 0; +} + +static int +pre_alternate(DECL_ARGS) +{ + enum termfont font[2]; + struct roff_node *nn; + int savelit, i; + + switch (n->tok) { + case MAN_RB: + font[0] = TERMFONT_NONE; + font[1] = TERMFONT_BOLD; + break; + case MAN_RI: + font[0] = TERMFONT_NONE; + font[1] = TERMFONT_UNDER; + break; + case MAN_BR: + font[0] = TERMFONT_BOLD; + font[1] = TERMFONT_NONE; + break; + case MAN_BI: + font[0] = TERMFONT_BOLD; + font[1] = TERMFONT_UNDER; + break; + case MAN_IR: + font[0] = TERMFONT_UNDER; + font[1] = TERMFONT_NONE; + break; + case MAN_IB: + font[0] = TERMFONT_UNDER; + font[1] = TERMFONT_BOLD; + break; + default: + abort(); + } + + savelit = MANT_LITERAL & mt->fl; + mt->fl &= ~MANT_LITERAL; + + for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) { + term_fontrepl(p, font[i]); + if (savelit && NULL == nn->next) + mt->fl |= MANT_LITERAL; + assert(nn->type == ROFFT_TEXT); + term_word(p, nn->string); + if (nn->flags & NODE_EOS) + p->flags |= TERMP_SENTENCE; + if (nn->next) + p->flags |= TERMP_NOSPACE; + } + + return 0; +} + +static int +pre_B(DECL_ARGS) +{ + + term_fontrepl(p, TERMFONT_BOLD); + return 1; +} + +static int +pre_OP(DECL_ARGS) +{ + + term_word(p, "["); + p->flags |= TERMP_NOSPACE; + + if (NULL != (n = n->child)) { + term_fontrepl(p, TERMFONT_BOLD); + term_word(p, n->string); + } + if (NULL != n && NULL != n->next) { + term_fontrepl(p, TERMFONT_UNDER); + term_word(p, n->next->string); + } + + term_fontrepl(p, TERMFONT_NONE); + p->flags |= TERMP_NOSPACE; + term_word(p, "]"); + return 0; +} + +static int +pre_ft(DECL_ARGS) +{ + const char *cp; + + if (NULL == n->child) { + term_fontlast(p); + return 0; + } + + cp = n->child->string; + switch (*cp) { + case '4': + case '3': + case 'B': + term_fontrepl(p, TERMFONT_BOLD); + break; + case '2': + case 'I': + term_fontrepl(p, TERMFONT_UNDER); + break; + case 'P': + term_fontlast(p); + break; + case '1': + case 'C': + case 'R': + term_fontrepl(p, TERMFONT_NONE); + break; + default: + break; + } + return 0; +} + +static int +pre_in(DECL_ARGS) +{ + struct roffsu su; + const char *cp; + size_t v; + int less; + + term_newln(p); + + if (NULL == n->child) { + p->offset = mt->offset; + return 0; + } + + cp = n->child->string; + less = 0; + + if ('-' == *cp) + less = -1; + else if ('+' == *cp) + less = 1; + else + cp--; + + if ( ! a2roffsu(++cp, &su, SCALE_EN)) + return 0; + + v = (term_hspan(p, &su) + 11) / 24; + + if (less < 0) + p->offset -= p->offset > v ? v : p->offset; + else if (less > 0) + p->offset += v; + else + p->offset = v; + if (p->offset > SHRT_MAX) + p->offset = term_len(p, p->defindent); + + return 0; +} + +static int +pre_sp(DECL_ARGS) +{ + struct roffsu su; + int i, len; + + if ((NULL == n->prev && n->parent)) { + switch (n->parent->tok) { + case MAN_SH: + case MAN_SS: + case MAN_PP: + case MAN_LP: + case MAN_P: + return 0; + default: + break; + } + } + + if (n->tok == MAN_br) + len = 0; + else if (n->child == NULL) + len = 1; + else { + if ( ! a2roffsu(n->child->string, &su, SCALE_VS)) + su.scale = 1.0; + len = term_vspan(p, &su); + } + + if (len == 0) + term_newln(p); + else if (len < 0) + p->skipvsp -= len; + else + for (i = 0; i < len; i++) + term_vspace(p); + + /* + * Handle an explicit break request in the same way + * as an overflowing line. + */ + + if (p->flags & TERMP_BRIND) { + p->offset = p->rmargin; + p->rmargin = p->maxrmargin; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + } + + return 0; +} + +static int +pre_HP(DECL_ARGS) +{ + struct roffsu su; + const struct roff_node *nn; + int len; + + switch (n->type) { + case ROFFT_BLOCK: + print_bvspace(p, n, mt->pardist); + return 1; + case ROFFT_BODY: + break; + default: + return 0; + } + + if ( ! (MANT_LITERAL & mt->fl)) { + p->flags |= TERMP_NOBREAK | TERMP_BRIND; + p->trailspace = 2; + } + + /* Calculate offset. */ + + if ((nn = n->parent->head->child) != NULL && + a2roffsu(nn->string, &su, SCALE_EN)) { + len = term_hspan(p, &su) / 24; + if (len < 0 && (size_t)(-len) > mt->offset) + len = -mt->offset; + else if (len > SHRT_MAX) + len = term_len(p, p->defindent); + mt->lmargin[mt->lmargincur] = len; + } else + len = mt->lmargin[mt->lmargincur]; + + p->offset = mt->offset; + p->rmargin = mt->offset + len; + return 1; +} + +static void +post_HP(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_BODY: + term_newln(p); + + /* + * Compatibility with a groff bug. + * The .HP macro uses the undocumented .tag request + * which causes a line break and cancels no-space + * mode even if there isn't any output. + */ + + if (n->child == NULL) + term_vspace(p); + + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + p->trailspace = 0; + p->offset = mt->offset; + p->rmargin = p->maxrmargin; + break; + default: + break; + } +} + +static int +pre_PP(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_BLOCK: + mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); + print_bvspace(p, n, mt->pardist); + break; + default: + p->offset = mt->offset; + break; + } + + return n->type != ROFFT_HEAD; +} + +static int +pre_IP(DECL_ARGS) +{ + struct roffsu su; + const struct roff_node *nn; + int len, savelit; + + switch (n->type) { + case ROFFT_BODY: + p->flags |= TERMP_NOSPACE; + break; + case ROFFT_HEAD: + p->flags |= TERMP_NOBREAK; + p->trailspace = 1; + break; + case ROFFT_BLOCK: + print_bvspace(p, n, mt->pardist); + /* FALLTHROUGH */ + default: + return 1; + } + + /* Calculate the offset from the optional second argument. */ + if ((nn = n->parent->head->child) != NULL && + (nn = nn->next) != NULL && + a2roffsu(nn->string, &su, SCALE_EN)) { + len = term_hspan(p, &su) / 24; + if (len < 0 && (size_t)(-len) > mt->offset) + len = -mt->offset; + else if (len > SHRT_MAX) + len = term_len(p, p->defindent); + mt->lmargin[mt->lmargincur] = len; + } else + len = mt->lmargin[mt->lmargincur]; + + switch (n->type) { + case ROFFT_HEAD: + p->offset = mt->offset; + p->rmargin = mt->offset + len; + + savelit = MANT_LITERAL & mt->fl; + mt->fl &= ~MANT_LITERAL; + + if (n->child) + print_man_node(p, mt, n->child, meta); + + if (savelit) + mt->fl |= MANT_LITERAL; + + return 0; + case ROFFT_BODY: + p->offset = mt->offset + len; + p->rmargin = p->maxrmargin; + break; + default: + break; + } + + return 1; +} + +static void +post_IP(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_HEAD: + term_flushln(p); + p->flags &= ~TERMP_NOBREAK; + p->trailspace = 0; + p->rmargin = p->maxrmargin; + break; + case ROFFT_BODY: + term_newln(p); + p->offset = mt->offset; + break; + default: + break; + } +} + +static int +pre_TP(DECL_ARGS) +{ + struct roffsu su; + struct roff_node *nn; + int len, savelit; + + switch (n->type) { + case ROFFT_HEAD: + p->flags |= TERMP_NOBREAK | TERMP_BRTRSP; + p->trailspace = 1; + break; + case ROFFT_BODY: + p->flags |= TERMP_NOSPACE; + break; + case ROFFT_BLOCK: + print_bvspace(p, n, mt->pardist); + /* FALLTHROUGH */ + default: + return 1; + } + + /* Calculate offset. */ + + if ((nn = n->parent->head->child) != NULL && + nn->string != NULL && ! (NODE_LINE & nn->flags) && + a2roffsu(nn->string, &su, SCALE_EN)) { + len = term_hspan(p, &su) / 24; + if (len < 0 && (size_t)(-len) > mt->offset) + len = -mt->offset; + else if (len > SHRT_MAX) + len = term_len(p, p->defindent); + mt->lmargin[mt->lmargincur] = len; + } else + len = mt->lmargin[mt->lmargincur]; + + switch (n->type) { + case ROFFT_HEAD: + p->offset = mt->offset; + p->rmargin = mt->offset + len; + + savelit = MANT_LITERAL & mt->fl; + mt->fl &= ~MANT_LITERAL; + + /* Don't print same-line elements. */ + nn = n->child; + while (NULL != nn && 0 == (NODE_LINE & nn->flags)) + nn = nn->next; + + while (NULL != nn) { + print_man_node(p, mt, nn, meta); + nn = nn->next; + } + + if (savelit) + mt->fl |= MANT_LITERAL; + return 0; + case ROFFT_BODY: + p->offset = mt->offset + len; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP); + break; + default: + break; + } + + return 1; +} + +static void +post_TP(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_HEAD: + term_flushln(p); + break; + case ROFFT_BODY: + term_newln(p); + p->offset = mt->offset; + break; + default: + break; + } +} + +static int +pre_SS(DECL_ARGS) +{ + int i; + + switch (n->type) { + case ROFFT_BLOCK: + mt->fl &= ~MANT_LITERAL; + mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); + mt->offset = term_len(p, p->defindent); + + /* + * No vertical space before the first subsection + * and after an empty subsection. + */ + + do { + n = n->prev; + } while (n != NULL && n->tok != TOKEN_NONE && + termacts[n->tok].flags & MAN_NOTEXT); + if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL)) + break; + + for (i = 0; i < mt->pardist; i++) + term_vspace(p); + break; + case ROFFT_HEAD: + term_fontrepl(p, TERMFONT_BOLD); + p->offset = term_len(p, 3); + p->rmargin = mt->offset; + p->trailspace = mt->offset; + p->flags |= TERMP_NOBREAK | TERMP_BRIND; + break; + case ROFFT_BODY: + p->offset = mt->offset; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + break; + default: + break; + } + + return 1; +} + +static void +post_SS(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_HEAD: + term_newln(p); + break; + case ROFFT_BODY: + term_newln(p); + break; + default: + break; + } +} + +static int +pre_SH(DECL_ARGS) +{ + int i; + + switch (n->type) { + case ROFFT_BLOCK: + mt->fl &= ~MANT_LITERAL; + mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); + mt->offset = term_len(p, p->defindent); + + /* + * No vertical space before the first section + * and after an empty section. + */ + + do { + n = n->prev; + } while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT); + if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL)) + break; + + for (i = 0; i < mt->pardist; i++) + term_vspace(p); + break; + case ROFFT_HEAD: + term_fontrepl(p, TERMFONT_BOLD); + p->offset = 0; + p->rmargin = mt->offset; + p->trailspace = mt->offset; + p->flags |= TERMP_NOBREAK | TERMP_BRIND; + break; + case ROFFT_BODY: + p->offset = mt->offset; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + break; + default: + break; + } + + return 1; +} + +static void +post_SH(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_HEAD: + term_newln(p); + break; + case ROFFT_BODY: + term_newln(p); + break; + default: + break; + } +} + +static int +pre_RS(DECL_ARGS) +{ + struct roffsu su; + + switch (n->type) { + case ROFFT_BLOCK: + term_newln(p); + return 1; + case ROFFT_HEAD: + return 0; + default: + break; + } + + n = n->parent->head; + n->aux = SHRT_MAX + 1; + if (n->child == NULL) + n->aux = mt->lmargin[mt->lmargincur]; + else if (a2roffsu(n->child->string, &su, SCALE_EN)) + n->aux = term_hspan(p, &su) / 24; + if (n->aux < 0 && (size_t)(-n->aux) > mt->offset) + n->aux = -mt->offset; + else if (n->aux > SHRT_MAX) + n->aux = term_len(p, p->defindent); + + mt->offset += n->aux; + p->offset = mt->offset; + p->rmargin = p->maxrmargin; + + if (++mt->lmarginsz < MAXMARGINS) + mt->lmargincur = mt->lmarginsz; + + mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); + return 1; +} + +static void +post_RS(DECL_ARGS) +{ + + switch (n->type) { + case ROFFT_BLOCK: + return; + case ROFFT_HEAD: + return; + default: + term_newln(p); + break; + } + + mt->offset -= n->parent->head->aux; + p->offset = mt->offset; + + if (--mt->lmarginsz < MAXMARGINS) + mt->lmargincur = mt->lmarginsz; +} + +static int +pre_UR(DECL_ARGS) +{ + + return n->type != ROFFT_HEAD; +} + +static void +post_UR(DECL_ARGS) +{ + + if (n->type != ROFFT_BLOCK) + 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) +{ + size_t rm, rmax; + int c; + + switch (n->type) { + case ROFFT_TEXT: + /* + * If we have a blank line, output a vertical space. + * If we have a space as the first character, break + * before printing the line's data. + */ + if ('\0' == *n->string) { + term_vspace(p); + return; + } else if (' ' == *n->string && NODE_LINE & n->flags) + term_newln(p); + + term_word(p, n->string); + goto out; + + case ROFFT_EQN: + if ( ! (n->flags & NODE_LINE)) + p->flags |= TERMP_NOSPACE; + term_eqn(p, n->eqn); + if (n->next != NULL && ! (n->next->flags & NODE_LINE)) + p->flags |= TERMP_NOSPACE; + return; + case ROFFT_TBL: + if (p->tbl.cols == NULL) + term_vspace(p); + term_tbl(p, n->span); + return; + default: + break; + } + + if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) + term_fontrepl(p, TERMFONT_NONE); + + c = 1; + if (termacts[n->tok].pre) + c = (*termacts[n->tok].pre)(p, mt, n, meta); + + if (c && n->child) + print_man_nodelist(p, mt, n->child, meta); + + if (termacts[n->tok].post) + (*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 (mt->fl & MANT_LITERAL && + ! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) && + (n->next == NULL || n->next->flags & NODE_LINE)) { + rm = p->rmargin; + rmax = p->maxrmargin; + p->rmargin = p->maxrmargin = TERM_MAXMARGIN; + p->flags |= TERMP_NOSPACE; + if (n->string != NULL && *n->string != '\0') + 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 (NODE_EOS & n->flags) + p->flags |= TERMP_SENTENCE; +} + + +static void +print_man_nodelist(DECL_ARGS) +{ + + while (n != NULL) { + print_man_node(p, mt, n, meta); + n = n->next; + } +} + +static void +print_man_foot(struct termp *p, const struct roff_meta *meta) +{ + char *title; + size_t datelen, titlen; + + assert(meta->title); + assert(meta->msec); + assert(meta->date); + + term_fontrepl(p, TERMFONT_NONE); + + if (meta->hasbody) + term_vspace(p); + + /* + * Temporary, undocumented option to imitate mdoc(7) output. + * In the bottom right corner, use the operating system + * instead of the title. + */ + + if ( ! p->mdocstyle) { + if (meta->hasbody) { + term_vspace(p); + term_vspace(p); + } + mandoc_asprintf(&title, "%s(%s)", + meta->title, meta->msec); + } else if (meta->os) { + title = mandoc_strdup(meta->os); + } else { + title = mandoc_strdup(""); + } + datelen = term_strlen(p, meta->date); + + /* Bottom left corner: operating system. */ + + p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; + p->trailspace = 1; + p->offset = 0; + p->rmargin = p->maxrmargin > datelen ? + (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0; + + if (meta->os) + term_word(p, meta->os); + term_flushln(p); + + /* At the bottom in the middle: manual date. */ + + p->offset = p->rmargin; + titlen = term_strlen(p, title); + p->rmargin = p->maxrmargin > titlen ? p->maxrmargin - titlen : 0; + p->flags |= TERMP_NOSPACE; + + term_word(p, meta->date); + term_flushln(p); + + /* Bottom right corner: manual title and section. */ + + p->flags &= ~TERMP_NOBREAK; + p->flags |= TERMP_NOSPACE; + p->trailspace = 0; + p->offset = p->rmargin; + p->rmargin = p->maxrmargin; + + term_word(p, title); + term_flushln(p); + free(title); +} + +static void +print_man_head(struct termp *p, const struct roff_meta *meta) +{ + const char *volume; + char *title; + size_t vollen, titlen; + + assert(meta->title); + assert(meta->msec); + + volume = NULL == meta->vol ? "" : meta->vol; + vollen = term_strlen(p, volume); + + /* Top left corner: manual title and section. */ + + mandoc_asprintf(&title, "%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) + vollen < p->maxrmargin ? + (p->maxrmargin - vollen + term_len(p, 1)) / 2 : + vollen < p->maxrmargin ? p->maxrmargin - vollen : 0; + + term_word(p, title); + term_flushln(p); + + /* At the top in the middle: manual volume. */ + + p->flags |= TERMP_NOSPACE; + p->offset = p->rmargin; + p->rmargin = p->offset + vollen + titlen < p->maxrmargin ? + p->maxrmargin - titlen : p->maxrmargin; + + term_word(p, volume); + term_flushln(p); + + /* 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; + p->rmargin = p->maxrmargin; + term_word(p, title); + term_flushln(p); + } + + p->flags &= ~TERMP_NOSPACE; + p->offset = 0; + p->rmargin = p->maxrmargin; + + /* + * Groff prints three blank lines before the content. + * Do the same, except in the temporary, undocumented + * mode imitating mdoc(7) output. + */ + + term_vspace(p); + if ( ! p->mdocstyle) { + term_vspace(p); + term_vspace(p); + } + free(title); +} Property changes on: vendor/mdocml/20170121/man_term.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc.1 =================================================================== --- vendor/mdocml/20170121/mandoc.1 (nonexistent) +++ vendor/mdocml/20170121/mandoc.1 (revision 312592) @@ -0,0 +1,1842 @@ +.\" $Id: mandoc.1,v 1.171 2017/01/21 02:32:39 schwarze Exp $ +.\" +.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons +.\" Copyright (c) 2012, 2014-2017 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 21 2017 $ +.Dt MANDOC 1 +.Os +.Sh NAME +.Nm mandoc +.Nd format and display UNIX manuals +.Sh SYNOPSIS +.Nm mandoc +.Op Fl acfhkl +.Op Fl I Cm os Ns = Ns Ar name +.Op Fl K Ar encoding +.Op Fl m Ns Ar format +.Op Fl O Ar option +.Op Fl T Ar output +.Op Fl W Ar level +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility formats +.Ux +manual pages for display. +.Pp +By default, +.Nm +reads +.Xr mdoc 7 +or +.Xr man 7 +text from stdin, implying +.Fl m Ns Cm andoc , +and produces +.Fl T Cm locale +output. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a +If the standard output is a terminal device and +.Fl c +is not specified, use +.Xr more 1 +to paginate the output, just like +.Xr man 1 +would. +.It Fl c +Copy the formatted manual pages to the standard output without using +.Xr more 1 +to paginate them. +This is the default. +It can be specified to override +.Fl a . +.It Fl f +A synonym for +.Xr whatis 1 . +This overrides any earlier +.Fl k +and +.Fl l +options. +.It Fl h +Display only the SYNOPSIS lines. +Implies +.Fl c . +.It Fl I Cm os Ns = Ns Ar name +Override the default operating system +.Ar name +for the +.Xr mdoc 7 +.Sq \&Os +and for the +.Xr man 7 +.Sq \&TH +macro. +.It Fl K Ar encoding +Specify the input encoding. +The supported +.Ar encoding +arguments are +.Cm us-ascii , +.Cm iso-8859-1 , +and +.Cm utf-8 . +If not specified, autodetection uses the first match: +.Bl -tag -width iso-8859-1 +.It Cm utf-8 +if the first three bytes of the input file +are the UTF-8 byte order mark (BOM, 0xefbbbf) +.It Ar encoding +if the first or second line of the input file matches the +.Sy emacs +mode line format +.Pp +.D1 .\e" -*- Oo ...; Oc coding: Ar encoding ; No -*- +.It Cm utf-8 +if the first non-ASCII byte in the file introduces a valid UTF-8 sequence +.It Cm iso-8859-1 +otherwise +.El +.It Fl k +A synonym for +.Xr apropos 1 . +This overrides any earlier +.Fl f +and +.Fl l +options. +.It Fl l +A synonym for +.Fl a . +Also reverts any earlier +.Fl f +and +.Fl k +options. +.It Fl m Ns Ar format +Input format. +See +.Sx Input Formats +for available formats. +Defaults to +.Fl m Ns Cm andoc . +.It Fl O Ar option +Comma-separated output options. +.It Fl T Ar output +Output format. +See +.Sx Output Formats +for available formats. +Defaults to +.Fl T Cm locale . +.It Fl W Ar level +Specify the minimum message +.Ar level +to be reported on the standard error output and to affect the exit status. +The +.Ar level +can be +.Cm warning , +.Cm error , +or +.Cm unsupp ; +.Cm all +is an alias for +.Cm warning . +By default, +.Nm +is silent. +See +.Sx EXIT STATUS +and +.Sx DIAGNOSTICS +for details. +.Pp +The special option +.Fl W Cm stop +tells +.Nm +to exit after parsing a file that causes warnings or errors of at least +the requested level. +No formatted output will be produced from that file. +If both a +.Ar level +and +.Cm stop +are requested, they can be joined with a comma, for example +.Fl W Cm error , Ns Cm stop . +.It Ar file +Read input from zero or more files. +If unspecified, reads from stdin. +If multiple files are specified, +.Nm +will halt with the first failed parse. +.El +.Pp +In +.Fl f +and +.Fl k +mode, +.Nm +also supports the options +.Fl CMmOSsw +described in the +.Xr apropos 1 +manual. +.Ss Input Formats +The +.Nm +utility accepts +.Xr mdoc 7 +and +.Xr man 7 +input with +.Fl m Ns Cm doc +and +.Fl m Ns Cm an , +respectively. +The +.Xr mdoc 7 +format is +.Em strongly +recommended; +.Xr man 7 +should only be used for legacy manuals. +.Pp +A third option, +.Fl m Ns Cm andoc , +which is also the default, determines encoding on-the-fly: if the first +non-comment macro is +.Sq \&Dd +or +.Sq \&Dt , +the +.Xr mdoc 7 +parser is used; otherwise, the +.Xr man 7 +parser is used. +.Pp +If multiple +files are specified with +.Fl m Ns Cm andoc , +each has its file-type determined this way. +If multiple files are +specified and +.Fl m Ns Cm doc +or +.Fl m Ns Cm an +is specified, then this format is used exclusively. +.Ss Output Formats +The +.Nm +utility accepts the following +.Fl T +arguments, which correspond to output modes: +.Bl -tag -width "-T locale" +.It Fl T Cm ascii +Produce 7-bit ASCII output. +See +.Sx ASCII Output . +.It Fl T Cm html +Produce HTML5, CSS1, and MathML output. +See +.Sx HTML Output . +.It Fl T Cm lint +Parse only: produce no output. +Implies +.Fl W Cm warning . +.It Fl T Cm locale +Encode output using the current locale. +This is the default. +See +.Sx Locale Output . +.It Fl T Cm man +Produce +.Xr man 7 +format output. +See +.Sx Man Output . +.It Fl T Cm pdf +Produce PDF output. +See +.Sx PDF Output . +.It Fl T Cm ps +Produce PostScript output. +See +.Sx PostScript Output . +.It Fl T Cm tree +Produce an indented parse tree. +See +.Sx Syntax tree output . +.It Fl T Cm utf8 +Encode output in the UTF\-8 multi-byte format. +See +.Sx UTF\-8 Output . +.It Fl T Cm xhtml +This is a synonym for +.Fl T Cm html . +.El +.Pp +If multiple input files are specified, these will be processed by the +corresponding filter in-order. +.Ss ASCII Output +Output produced by +.Fl T Cm ascii +is rendered in standard 7-bit ASCII documented in +.Xr ascii 7 . +.Pp +Font styles are applied by using back-spaced encoding such that an +underlined character +.Sq c +is rendered as +.Sq _ Ns \e[bs] Ns c , +where +.Sq \e[bs] +is the back-space character number 8. +Emboldened characters are rendered as +.Sq c Ns \e[bs] Ns c . +.Pp +The special characters documented in +.Xr mandoc_char 7 +are rendered best-effort in an ASCII equivalent. +.Pp +Output width is limited to 78 visible columns unless literal input lines +exceed this limit. +.Pp +The following +.Fl O +arguments are accepted: +.Bl -tag -width Ds +.It Cm indent Ns = Ns Ar indent +The left margin for normal text is set to +.Ar indent +blank characters instead of the default of five for +.Xr mdoc 7 +and seven for +.Xr man 7 . +Increasing this is not recommended; it may result in degraded formatting, +for example overfull lines or ugly line breaks. +.It Cm width Ns = Ns Ar width +The output width is set to +.Ar width , +which will normalise to \(>=58. +.El +.Ss HTML Output +Output produced by +.Fl T Cm html +conforms to HTML5 using optional self-closing tags. +Default styles use only CSS1. +Equations rendered from +.Xr eqn 7 +blocks use MathML. +.Pp +The +.Pa mandoc.css +file documents style-sheet classes available for customising output. +If a style-sheet is not specified with +.Fl O Cm style , +.Fl T Cm html +defaults to simple output (via an embedded style-sheet) +readable in any graphical or text-based web +browser. +.Pp +Special characters are rendered in decimal-encoded UTF\-8. +.Pp +The following +.Fl O +arguments are accepted: +.Bl -tag -width Ds +.It Cm fragment +Omit the declaration and the , , and +elements and only emit the subtree below the element. +The +.Cm style +argument will be ignored. +This is useful when embedding manual content within existing documents. +.It Cm includes Ns = Ns Ar fmt +The string +.Ar fmt , +for example, +.Ar ../src/%I.html , +is used as a template for linked header files (usually via the +.Sq \&In +macro). +Instances of +.Sq \&%I +are replaced with the include filename. +The default is not to present a +hyperlink. +.It Cm man Ns = Ns Ar fmt +The string +.Ar fmt , +for example, +.Ar ../html%S/%N.%S.html , +is used as a template for linked manuals (usually via the +.Sq \&Xr +macro). +Instances of +.Sq \&%N +and +.Sq %S +are replaced with the linked manual's name and section, respectively. +If no section is included, section 1 is assumed. +The default is not to +present a hyperlink. +.It Cm style Ns = Ns Ar style.css +The file +.Ar style.css +is used for an external style-sheet. +This must be a valid absolute or +relative URI. +.El +.Ss Locale Output +Locale-depending output encoding is triggered with +.Fl T Cm locale . +This is the default. +.Pp +This option is not available on all systems: systems without locale +support, or those whose internal representation is not natively UCS-4, +will fall back to +.Fl T Cm ascii . +See +.Sx ASCII Output +for font style specification and available command-line arguments. +.Ss Man Output +Translate input format into +.Xr man 7 +output format. +This is useful for distributing manual sources to legacy systems +lacking +.Xr mdoc 7 +formatters. +.Pp +If +.Xr mdoc 7 +is passed as input, it is translated into +.Xr man 7 . +If the input format is +.Xr man 7 , +the input is copied to the output, expanding any +.Xr roff 7 +.Sq so +requests. +The parser is also run, and as usual, the +.Fl W +level controls which +.Sx DIAGNOSTICS +are displayed before copying the input to the output. +.Ss PDF Output +PDF-1.1 output may be generated by +.Fl T Cm pdf . +See +.Sx PostScript Output +for +.Fl O +arguments and defaults. +.Ss PostScript Output +PostScript +.Qq Adobe-3.0 +Level-2 pages may be generated by +.Fl T Cm ps . +Output pages default to letter sized and are rendered in the Times font +family, 11-point. +Margins are calculated as 1/9 the page length and width. +Line-height is 1.4m. +.Pp +Special characters are rendered as in +.Sx ASCII Output . +.Pp +The following +.Fl O +arguments are accepted: +.Bl -tag -width Ds +.It Cm paper Ns = Ns Ar name +The paper size +.Ar name +may be one of +.Ar a3 , +.Ar a4 , +.Ar a5 , +.Ar legal , +or +.Ar letter . +You may also manually specify dimensions as +.Ar NNxNN , +width by height in millimetres. +If an unknown value is encountered, +.Ar letter +is used. +.El +.Ss UTF\-8 Output +Use +.Fl T Cm utf8 +to force a UTF\-8 locale. +See +.Sx Locale Output +for details and options. +.Ss Syntax tree output +Use +.Fl T Cm tree +to show a human readable representation of the syntax tree. +It is useful for debugging the source code of manual pages. +The exact format is subject to change, so don't write parsers for it. +.Pp +The first paragraph shows meta data found in the +.Xr mdoc 7 +prologue, on the +.Xr man 7 +.Ic \&TH +line, or the fallbacks used. +.Pp +In the tree dump, each output line shows one syntax tree node. +Child nodes are indented with respect to their parent node. +The columns are: +.Pp +.Bl -enum -compact +.It +For macro nodes, the macro name; for text and +.Xr tbl 7 +nodes, the content. +There is a special format for +.Xr eqn 7 +nodes. +.It +Node type (text, elem, block, head, body, body-end, tail, tbl, eqn). +.It +Flags: +.Bl -dash -compact +.It +An opening parenthesis if the node is an opening delimiter. +.It +An asterisk if the node starts a new input line. +.It +The input line number (starting at one). +.It +A colon. +.It +The input column number (starting at one). +.It +A closing parenthesis if the node is a closing delimiter. +.It +A full stop if the node ends a sentence. +.It +NOSRC if the node is not in the input file, +but automatically generated from macros. +.It +NOPRT if the node is not supposed to generate output +for any output format. +.El +.El +.Sh ENVIRONMENT +.Bl -tag -width MANPAGER +.It Ev MANPAGER +Any non-empty value of the environment variable +.Ev MANPAGER +will be used instead of the standard pagination program, +.Xr more 1 . +.It Ev PAGER +Specifies the pagination program to use when +.Ev MANPAGER +is not defined. +If neither PAGER nor MANPAGER is defined, +.Xr more 1 +.Fl s +will be used. +.El +.Sh EXIT STATUS +The +.Nm +utility exits with one of the following values, controlled by the message +.Ar level +associated with the +.Fl W +option: +.Pp +.Bl -tag -width Ds -compact +.It 0 +No warnings or errors occurred, or those that did were ignored because +they were lower than the requested +.Ar level . +.It 2 +At least one warning occurred, but no error, and +.Fl W Cm warning +was specified. +.It 3 +At least one parsing error occurred, +but no unsupported feature was encountered, and +.Fl W Cm error +or +.Fl W Cm warning +was specified. +.It 4 +At least one unsupported feature was encountered, and +.Fl W Cm unsupp , +.Fl W Cm error +or +.Fl W Cm warning +was specified. +.It 5 +Invalid command line arguments were specified. +No input files have been read. +.It 6 +An operating system error occurred, for example exhaustion +of memory, file descriptors, or process table entries. +Such errors cause +.Nm +to exit at once, possibly in the middle of parsing or formatting a file. +.El +.Pp +Note that selecting +.Fl T Cm lint +output mode implies +.Fl W Cm warning . +.Sh EXAMPLES +To page manuals to the terminal: +.Pp +.Dl $ mandoc \-W all,stop mandoc.1 2\*(Gt&1 | less +.Dl $ mandoc mandoc.1 mdoc.3 mdoc.7 | less +.Pp +To produce HTML manuals with +.Pa mandoc.css +as the style-sheet: +.Pp +.Dl $ mandoc \-T html -O style=mandoc.css mdoc.7 \*(Gt mdoc.7.html +.Pp +To check over a large set of manuals: +.Pp +.Dl $ mandoc \-T lint \(gafind /usr/src -name \e*\e.[1-9]\(ga +.Pp +To produce a series of PostScript manuals for A4 paper: +.Pp +.Dl $ mandoc \-T ps \-O paper=a4 mdoc.7 man.7 \*(Gt manuals.ps +.Pp +Convert a modern +.Xr mdoc 7 +manual to the older +.Xr man 7 +format, for use on systems lacking an +.Xr mdoc 7 +parser: +.Pp +.Dl $ mandoc \-T man foo.mdoc \*(Gt foo.man +.Sh DIAGNOSTICS +Messages displayed by +.Nm +follow this format: +.Pp +.D1 Nm Ns : Ar file : Ns Ar line : Ns Ar column : level : message : macro args +.Pp +Line and column numbers start at 1. +Both are omitted for messages referring to an input file as a whole. +Macro names and arguments are omitted where meaningless. +Fatal messages about invalid command line arguments +or operating system errors, for example when memory is exhausted, +may also omit the +.Ar file +and +.Ar level +fields. +.Pp +Message levels have the following meanings: +.Bl -tag -width "warning" +.It Cm unsupp +An input file uses unsupported low-level +.Xr roff 7 +features. +The output may be incomplete and/or misformatted, +so using GNU troff instead of +.Nm +to process the file may be preferable. +.It Cm error +An input file contains invalid syntax that cannot be safely interpreted. +By discarding part of the input or inserting missing tokens, +the parser is able to continue, and the error does not prevent +generation of formatted output, but typically, preparing that +output involves information loss, broken document structure +or unintended formatting, no matter whether +.Nm +or GNU troff is used. +In many cases, the output of +.Nm +and GNU troff is identical, but in some, +.Nm +is more resilient than GNU troff with respect to malformed input. +.Pp +Non-existent or unreadable input files are also reported on the +.Cm error +level. +In that case, the parser cannot even be started and no output +is produced from those input files. +.It Cm warning +An input file uses obsolete, discouraged or non-portable syntax. +All the same, the meaning of the input is unambiguous and a correct +rendering can be produced. +Documents causing warnings may render poorly when using other +formatting tools instead of +.Nm . +.El +.Pp +Messages of the +.Cm warning , +.Cm error , +and +.Cm unsupp +levels except those about non-existent or unreadable input files +are hidden unless their level, or a lower level, is requested using a +.Fl W +option or +.Fl T Cm lint +output mode. +.Ss Warnings related to the document prologue +.Bl -ohang +.It Sy "missing manual title, using UNTITLED" +.Pq mdoc +A +.Ic \&Dt +macro has no arguments, or there is no +.Ic \&Dt +macro before the first non-prologue macro. +.It Sy "missing manual title, using \(dq\(dq" +.Pq man +There is no +.Ic \&TH +macro, or it has no arguments. +.It Sy "lower case character in document title" +.Pq mdoc , man +The title is still used as given in the +.Ic \&Dt +or +.Ic \&TH +macro. +.It Sy "missing manual section, using \(dq\(dq" +.Pq mdoc , man +A +.Ic \&Dt +or +.Ic \&TH +macro lacks the mandatory section argument. +.It Sy "unknown manual section" +.Pq mdoc +The section number in a +.Ic \&Dt +line is invalid, but still used. +.It Sy "missing date, using today's date" +.Pq mdoc, man +The document was parsed as +.Xr mdoc 7 +and it has no +.Ic \&Dd +macro, or the +.Ic \&Dd +macro has no arguments or only empty arguments; +or the document was parsed as +.Xr man 7 +and it has no +.Ic \&TH +macro, or the +.Ic \&TH +macro has less than three arguments or its third argument is empty. +.It Sy "cannot parse date, using it verbatim" +.Pq mdoc , man +The date given in a +.Ic \&Dd +or +.Ic \&TH +macro does not follow the conventional format. +.It Sy "missing Os macro, using \(dq\(dq" +.Pq mdoc +The default or current system is not shown in this case. +.It Sy "duplicate prologue macro" +.Pq mdoc +One of the prologue macros occurs more than once. +The last instance overrides all previous ones. +.It Sy "late prologue macro" +.Pq mdoc +A +.Ic \&Dd +or +.Ic \&Os +macro occurs after some non-prologue macro, but still takes effect. +.It Sy "skipping late title macro" +.Pq mdoc +The +.Ic \&Dt +macro appears after the first non-prologue macro. +Traditional formatters cannot handle this because +they write the page header before parsing the document body. +Even though this technical restriction does not apply to +.Nm , +traditional semantics is preserved. +The late macro is discarded including its arguments. +.It Sy "prologue macros out of order" +.Pq mdoc +The prologue macros are not given in the conventional order +.Ic \&Dd , +.Ic \&Dt , +.Ic \&Os . +All three macros are used even when given in another order. +.El +.Ss Warnings regarding document structure +.Bl -ohang +.It Sy ".so is fragile, better use ln(1)" +.Pq roff +Including files only works when the parser program runs with the correct +current working directory. +.It Sy "no document body" +.Pq mdoc , man +The document body contains neither text nor macros. +An empty document is shown, consisting only of a header and a footer line. +.It Sy "content before first section header" +.Pq mdoc , man +Some macros or text precede the first +.Ic \&Sh +or +.Ic \&SH +section header. +The offending macros and text are parsed and added to the top level +of the syntax tree, outside any section block. +.It Sy "first section is not NAME" +.Pq mdoc +The argument of the first +.Ic \&Sh +macro is not +.Sq NAME . +This may confuse +.Xr makewhatis 8 +and +.Xr apropos 1 . +.It Sy "NAME section without Nm before Nd" +.Pq mdoc +The NAME section does not contain any +.Ic \&Nm +child macro before the first +.Ic \&Nd +macro. +.It Sy "NAME section without description" +.Pq mdoc +The NAME section lacks the mandatory +.Ic \&Nd +child macro. +.It Sy "description not at the end of NAME" +.Pq mdoc +The NAME section does contain an +.Ic \&Nd +child macro, but other content follows it. +.It Sy "bad NAME section content" +.Pq mdoc +The NAME section contains plain text or macros other than +.Ic \&Nm +and +.Ic \&Nd . +.It Sy "missing comma before name" +.Pq mdoc +The NAME section contains an +.Ic \&Nm +macro that is neither the first one nor preceded by a comma. +.It Sy "missing description line, using \(dq\(dq" +.Pq mdoc +The +.Ic \&Nd +macro lacks the required argument. +The title line of the manual will end after the dash. +.It Sy "sections out of conventional order" +.Pq mdoc +A standard section occurs after another section it usually precedes. +All section titles are used as given, +and the order of sections is not changed. +.It Sy "duplicate section title" +.Pq mdoc +The same standard section title occurs more than once. +.It Sy "unexpected section" +.Pq mdoc +A standard section header occurs in a section of the manual +where it normally isn't useful. +.It Sy "unusual Xr order" +.Pq mdoc +In the SEE ALSO section, an +.Ic \&Xr +macro with a lower section number follows one with a higher number, +or two +.Ic \&Xr +macros referring to the same section are out of alphabetical order. +.It Sy "unusual Xr punctuation" +.Pq mdoc +In the SEE ALSO section, punctuation between two +.Ic \&Xr +macros differs from a single comma, or there is trailing punctuation +after the last +.Ic \&Xr +macro. +.It Sy "AUTHORS section without An macro" +.Pq mdoc +An AUTHORS sections contains no +.Ic \&An +macros, or only empty ones. +Probably, there are author names lacking markup. +.El +.Ss "Warnings related to macros and nesting" +.Bl -ohang +.It Sy "obsolete macro" +.Pq mdoc +See the +.Xr mdoc 7 +manual for replacements. +.It Sy "macro neither callable nor escaped" +.Pq mdoc +The name of a macro that is not callable appears on a macro line. +It is printed verbatim. +If the intention is to call it, move it to its own input line; +otherwise, escape it by prepending +.Sq \e& . +.It Sy "skipping paragraph macro" +In +.Xr mdoc 7 +documents, this happens +.Bl -dash -compact +.It +at the beginning and end of sections and subsections +.It +right before non-compact lists and displays +.It +at the end of items in non-column, non-compact lists +.It +and for multiple consecutive paragraph macros. +.El +In +.Xr man 7 +documents, it happens +.Bl -dash -compact +.It +for empty +.Ic \&P , +.Ic \&PP , +and +.Ic \&LP +macros +.It +for +.Ic \&IP +macros having neither head nor body arguments +.It +for +.Ic \&br +or +.Ic \&sp +right after +.Ic \&SH +or +.Ic \&SS +.El +.It Sy "moving paragraph macro out of list" +.Pq mdoc +A list item in a +.Ic \&Bl +list contains a trailing paragraph macro. +The paragraph macro is moved after the end of the list. +.It Sy "skipping no-space macro" +.Pq mdoc +An input line begins with an +.Ic \&Ns +macro. +The macro is ignored. +.It Sy "blocks badly nested" +.Pq mdoc +If two blocks intersect, one should completely contain the other. +Otherwise, rendered output is likely to look strange in any output +format, and rendering in SGML-based output formats is likely to be +outright wrong because such languages do not support badly nested +blocks at all. +Typical examples of badly nested blocks are +.Qq Ic \&Ao \&Bo \&Ac \&Bc +and +.Qq Ic \&Ao \&Bq \&Ac . +In these examples, +.Ic \&Ac +breaks +.Ic \&Bo +and +.Ic \&Bq , +respectively. +.It Sy "nested displays are not portable" +.Pq mdoc +A +.Ic \&Bd , +.Ic \&D1 , +or +.Ic \&Dl +display occurs nested inside another +.Ic \&Bd +display. +This works with +.Nm , +but fails with most other implementations. +.It Sy "moving content out of list" +.Pq mdoc +A +.Ic \&Bl +list block contains text or macros before the first +.Ic \&It +macro. +The offending children are moved before the beginning of the list. +.It Sy "fill mode already enabled, skipping" +.Pq man +A +.Ic \&fi +request occurs even though the document is still in fill mode, +or already switched back to fill mode. +It has no effect. +.It Sy "fill mode already disabled, skipping" +.Pq man +An +.Ic \&nf +request occurs even though the document already switched to no-fill mode +and did not switch back to fill mode yet. +It has no effect. +.It Sy "line scope broken" +.Pq man +While parsing the next-line scope of the previous macro, +another macro is found that prematurely terminates the previous one. +The previous, interrupted macro is deleted from the parse tree. +.El +.Ss "Warnings related to missing arguments" +.Bl -ohang +.It Sy "skipping empty request" +.Pq roff , eqn +The macro name is missing from a macro definition request, +or an +.Xr eqn 7 +control statement or operation keyword lacks its required argument. +.It Sy "conditional request controls empty scope" +.Pq roff +A conditional request is only useful if any of the following +follows it on the same logical input line: +.Bl -dash -compact +.It +The +.Sq \e{ +keyword to open a multi-line scope. +.It +A request or macro or some text, resulting in a single-line scope. +.It +The immediate end of the logical line without any intervening whitespace, +resulting in next-line scope. +.El +Here, a conditional request is followed by trailing whitespace only, +and there is no other content on its logical input line. +Note that it doesn't matter whether the logical input line is split +across multiple physical input lines using +.Sq \e +line continuation characters. +This is one of the rare cases +where trailing whitespace is syntactically significant. +The conditional request controls a scope containing whitespace only, +so it is unlikely to have a significant effect, +except that it may control a following +.Ic \&el +clause. +.It Sy "skipping empty macro" +.Pq mdoc +The indicated macro has no arguments and hence no effect. +.It Sy "empty block" +.Pq mdoc , man +A +.Ic \&Bd , +.Ic \&Bk , +.Ic \&Bl , +.Ic \&D1 , +.Ic \&Dl , +.Ic \&RS , +or +.Ic \&UR +block contains nothing in its body and will produce no output. +.It Sy "empty argument, using 0n" +.Pq mdoc +The required width is missing after +.Ic \&Bd +or +.Ic \&Bl +.Fl offset +or +.Fl width. +.It Sy "missing display type, using -ragged" +.Pq mdoc +The +.Ic \&Bd +macro is invoked without the required display type. +.It Sy "list type is not the first argument" +.Pq mdoc +In a +.Ic \&Bl +macro, at least one other argument precedes the type argument. +The +.Nm +utility copes with any argument order, but some other +.Xr mdoc 7 +implementations do not. +.It Sy "missing -width in -tag list, using 8n" +.Pq mdoc +Every +.Ic \&Bl +macro having the +.Fl tag +argument requires +.Fl width , +too. +.It Sy "missing utility name, using \(dq\(dq" +.Pq mdoc +The +.Ic \&Ex Fl std +macro is called without an argument before +.Ic \&Nm +has first been called with an argument. +.It Sy "missing function name, using \(dq\(dq" +.Pq mdoc +The +.Ic \&Fo +macro is called without an argument. +No function name is printed. +.It Sy "empty head in list item" +.Pq mdoc +In a +.Ic \&Bl +.Fl diag , +.Fl hang , +.Fl inset , +.Fl ohang , +or +.Fl tag +list, an +.Ic \&It +macro lacks the required argument. +The item head is left empty. +.It Sy "empty list item" +.Pq mdoc +In a +.Ic \&Bl +.Fl bullet , +.Fl dash , +.Fl enum , +or +.Fl hyphen +list, an +.Ic \&It +block is empty. +An empty list item is shown. +.It Sy "missing font type, using \efR" +.Pq mdoc +A +.Ic \&Bf +macro has no argument. +It switches to the default font. +.It Sy "unknown font type, using \efR" +.Pq mdoc +The +.Ic \&Bf +argument is invalid. +The default font is used instead. +.It Sy "nothing follows prefix" +.Pq mdoc +A +.Ic \&Pf +macro has no argument, or only one argument and no macro follows +on the same input line. +This defeats its purpose; in particular, spacing is not suppressed +before the text or macros following on the next input line. +.It Sy "empty reference block" +.Pq mdoc +An +.Ic \&Rs +macro is immediately followed by an +.Ic \&Re +macro on the next input line. +Such an empty block does not produce any output. +.It Sy "missing section argument" +.Pq mdoc +An +.Ic \&Xr +macro lacks its second, section number argument. +The first argument, i.e. the name, is printed, but without subsequent +parentheses. +.It Sy "missing -std argument, adding it" +.Pq mdoc +An +.Ic \&Ex +or +.Ic \&Rv +macro lacks the required +.Fl std +argument. +The +.Nm +utility assumes +.Fl std +even when it is not specified, but other implementations may not. +.It Sy "missing option string, using \(dq\(dq" +.Pq man +The +.Ic \&OP +macro is invoked without any argument. +An empty pair of square brackets is shown. +.It Sy "missing resource identifier, using \(dq\(dq" +.Pq man +The +.Ic \&UR +macro is invoked without any argument. +An empty pair of angle brackets is shown. +.It Sy "missing eqn box, using \(dq\(dq" +.Pq eqn +A diacritic mark or a binary operator is found, +but there is nothing to the left of it. +An empty box is inserted. +.El +.Ss "Warnings related to bad macro arguments" +.Bl -ohang +.It Sy "unterminated quoted argument" +.Pq roff +Macro arguments can be enclosed in double quote characters +such that space characters and macro names contained in the quoted +argument need not be escaped. +The closing quote of the last argument of a macro can be omitted. +However, omitting it is not recommended because it makes the code +harder to read. +.It Sy "duplicate argument" +.Pq mdoc +A +.Ic \&Bd +or +.Ic \&Bl +macro has more than one +.Fl compact , +more than one +.Fl offset , +or more than one +.Fl width +argument. +All but the last instances of these arguments are ignored. +.It Sy "skipping duplicate argument" +.Pq mdoc +An +.Ic \&An +macro has more than one +.Fl split +or +.Fl nosplit +argument. +All but the first of these arguments are ignored. +.It Sy "skipping duplicate display type" +.Pq mdoc +A +.Ic \&Bd +macro has more than one type argument; the first one is used. +.It Sy "skipping duplicate list type" +.Pq mdoc +A +.Ic \&Bl +macro has more than one type argument; the first one is used. +.It Sy "skipping -width argument" +.Pq mdoc +A +.Ic \&Bl +.Fl column , +.Fl diag , +.Fl ohang , +.Fl inset , +or +.Fl item +list has a +.Fl width +argument. +That has no effect. +.It Sy "wrong number of cells" +In a line of a +.Ic \&Bl Fl column +list, the number of tabs or +.Ic \&Ta +macros is less than the number expected from the list header line +or exceeds the expected number by more than one. +Missing cells remain empty, and all cells exceeding the number of +columns are joined into one single cell. +.It Sy "unknown AT&T UNIX version" +.Pq mdoc +An +.Ic \&At +macro has an invalid argument. +It is used verbatim, with +.Qq "AT&T UNIX " +prefixed to it. +.It Sy "comma in function argument" +.Pq mdoc +An argument of an +.Ic \&Fa +or +.Ic \&Fn +macro contains a comma; it should probably be split into two arguments. +.It Sy "parenthesis in function name" +.Pq mdoc +The first argument of an +.Ic \&Fc +or +.Ic \&Fn +macro contains an opening or closing parenthesis; that's probably wrong, +parentheses are added automatically. +.It Sy "invalid content in Rs block" +.Pq mdoc +An +.Ic \&Rs +block contains plain text or non-% macros. +The bogus content is left in the syntax tree. +Formatting may be poor. +.It Sy "invalid Boolean argument" +.Pq mdoc +An +.Ic \&Sm +macro has an argument other than +.Cm on +or +.Cm off . +The invalid argument is moved out of the macro, which leaves the macro +empty, causing it to toggle the spacing mode. +.It Sy "unknown font, skipping request" +.Pq man , tbl +A +.Xr roff 7 +.Ic \&ft +request or a +.Xr tbl 7 +.Ic \&f +layout modifier has an unknown +.Ar font +argument. +.It Sy "odd number of characters in request" +.Pq roff +A +.Ic \&tr +request contains an odd number of characters. +The last character is mapped to the blank character. +.El +.Ss "Warnings related to plain text" +.Bl -ohang +.It Sy "blank line in fill mode, using .sp" +.Pq mdoc +The meaning of blank input lines is only well-defined in non-fill mode: +In fill mode, line breaks of text input lines are not supposed to be +significant. +However, for compatibility with groff, blank lines in fill mode +are replaced with +.Ic \&sp +requests. +.It Sy "tab in filled text" +.Pq mdoc , man +The meaning of tab characters is only well-defined in non-fill mode: +In fill mode, whitespace is not supposed to be significant +on text input lines. +As an implementation dependent choice, tab characters on text lines +are passed through to the formatters in any case. +Given that the text before the tab character will be filled, +it is hard to predict which tab stop position the tab will advance to. +.It Sy "whitespace at end of input line" +.Pq mdoc , man , roff +Whitespace at the end of input lines is almost never semantically +significant \(em but in the odd case where it might be, it is +extremely confusing when reviewing and maintaining documents. +.It Sy "bad comment style" +.Pq roff +Comment lines start with a dot, a backslash, and a double-quote character. +The +.Nm +utility treats the line as a comment line even without the backslash, +but leaving out the backslash might not be portable. +.It Sy "invalid escape sequence" +.Pq roff +An escape sequence has an invalid opening argument delimiter, lacks the +closing argument delimiter, or the argument has too few characters. +If the argument is incomplete, +.Ic \e* +and +.Ic \en +expand to an empty string, +.Ic \eB +to the digit +.Sq 0 , +and +.Ic \ew +to the length of the incomplete argument. +All other invalid escape sequences are ignored. +.It Sy "undefined string, using \(dq\(dq" +.Pq roff +If a string is used without being defined before, +its value is implicitly set to the empty string. +However, defining strings explicitly before use +keeps the code more readable. +.El +.Ss "Warnings related to tables" +.Bl -ohang +.It Sy "tbl line starts with span" +.Pq tbl +The first cell in a table layout line is a horizontal span +.Pq Sq Cm s . +Data provided for this cell is ignored, and nothing is printed in the cell. +.It Sy "tbl column starts with span" +.Pq tbl +The first line of a table layout specification +requests a vertical span +.Pq Sq Cm ^ . +Data provided for this cell is ignored, and nothing is printed in the cell. +.It Sy "skipping vertical bar in tbl layout" +.Pq tbl +A table layout specification contains more than two consecutive vertical bars. +A double bar is printed, all additional bars are discarded. +.El +.Ss "Errors related to tables" +.Bl -ohang +.It Sy "non-alphabetic character in tbl options" +.Pq tbl +The table options line contains a character other than a letter, +blank, or comma where the beginning of an option name is expected. +The character is ignored. +.It Sy "skipping unknown tbl option" +.Pq tbl +The table options line contains a string of letters that does not +match any known option name. +The word is ignored. +.It Sy "missing tbl option argument" +.Pq tbl +A table option that requires an argument is not followed by an +opening parenthesis, or the opening parenthesis is immediately +followed by a closing parenthesis. +The option is ignored. +.It Sy "wrong tbl option argument size" +.Pq tbl +A table option argument contains an invalid number of characters. +Both the option and the argument are ignored. +.It Sy "empty tbl layout" +.Pq tbl +A table layout specification is completely empty, +specifying zero lines and zero columns. +As a fallback, a single left-justified column is used. +.It Sy "invalid character in tbl layout" +.Pq tbl +A table layout specification contains a character that can neither +be interpreted as a layout key character nor as a layout modifier, +or a modifier precedes the first key. +The invalid character is discarded. +.It Sy "unmatched parenthesis in tbl layout" +.Pq tbl +A table layout specification contains an opening parenthesis, +but no matching closing parenthesis. +The rest of the input line, starting from the parenthesis, has no effect. +.It Sy "tbl without any data cells" +.Pq tbl +A table does not contain any data cells. +It will probably produce no output. +.It Sy "ignoring data in spanned tbl cell" +.Pq tbl +A table cell is marked as a horizontal span +.Pq Sq Cm s +or vertical span +.Pq Sq Cm ^ +in the table layout, but it contains data. +The data is ignored. +.It Sy "ignoring extra tbl data cells" +.Pq tbl +A data line contains more cells than the corresponding layout line. +The data in the extra cells is ignored. +.It Sy "data block open at end of tbl" +.Pq tbl +A data block is opened with +.Cm T{ , +but never closed with a matching +.Cm T} . +The remaining data lines of the table are all put into one cell, +and any remaining cells stay empty. +.El +.Ss "Errors related to roff, mdoc, and man code" +.Bl -ohang +.It Sy "input stack limit exceeded, infinite loop?" +.Pq roff +Explicit recursion limits are implemented for the following features, +in order to prevent infinite loops: +.Bl -dash -compact +.It +expansion of nested escape sequences +including expansion of strings and number registers, +.It +expansion of nested user-defined macros, +.It +and +.Ic \&so +file inclusion. +.El +When a limit is hit, the output is incorrect, typically losing +some content, but the parser can continue. +.It Sy "skipping bad character" +.Pq mdoc , man , roff +The input file contains a byte that is not a printable +.Xr ascii 7 +character. +The message mentions the character number. +The offending byte is replaced with a question mark +.Pq Sq \&? . +Consider editing the input file to replace the byte with an ASCII +transliteration of the intended character. +.It Sy "skipping unknown macro" +.Pq mdoc , man , roff +The first identifier on a request or macro line is neither recognized as a +.Xr roff 7 +request, nor as a user-defined macro, nor, respectively, as an +.Xr mdoc 7 +or +.Xr man 7 +macro. +It may be mistyped or unsupported. +The request or macro is discarded including its arguments. +.It Sy "skipping insecure request" +.Pq roff +An input file attempted to run a shell command +or to read or write an external file. +Such attempts are denied for security reasons. +.It Sy "skipping item outside list" +.Pq mdoc , eqn +An +.Ic \&It +macro occurs outside any +.Ic \&Bl +list, or an +.Xr eqn 7 +.Ic above +delimiter occurs outside any pile. +It is discarded including its arguments. +.It Sy "skipping column outside column list" +.Pq mdoc +A +.Ic \&Ta +macro occurs outside any +.Ic \&Bl Fl column +block. +It is discarded including its arguments. +.It Sy "skipping end of block that is not open" +.Pq mdoc , man , eqn , tbl , roff +Various syntax elements can only be used to explicitly close blocks +that have previously been opened. +An +.Xr mdoc 7 +block closing macro, a +.Xr man 7 +.Ic \&RE +or +.Ic \&UE +macro, an +.Xr eqn 7 +right delimiter or closing brace, or the end of an equation, table, or +.Xr roff 7 +conditional request is encountered but no matching block is open. +The offending request or macro is discarded. +.It Sy "fewer RS blocks open, skipping" +.Pq man +The +.Ic \&RE +macro is invoked with an argument, but less than the specified number of +.Ic \&RS +blocks is open. +The +.Ic \&RE +macro is discarded. +.It Sy "inserting missing end of block" +.Pq mdoc , tbl +Various +.Xr mdoc 7 +macros as well as tables require explicit closing by dedicated macros. +A block that doesn't support bad nesting +ends before all of its children are properly closed. +The open child nodes are closed implicitly. +.It Sy "appending missing end of block" +.Pq mdoc , man , eqn , tbl , roff +At the end of the document, an explicit +.Xr mdoc 7 +block, a +.Xr man 7 +next-line scope or +.Ic \&RS +or +.Ic \&UR +block, an equation, table, or +.Xr roff 7 +conditional or ignore block is still open. +The open block is closed implicitly. +.It Sy "escaped character not allowed in a name" +.Pq roff +Macro, string and register identifiers consist of printable, +non-whitespace ASCII characters. +Escape sequences and characters and strings expressed in terms of them +cannot form part of a name. +The first argument of an +.Ic \&am , +.Ic \&as , +.Ic \&de , +.Ic \&ds , +.Ic \&nr , +or +.Ic \&rr +request, or any argument of an +.Ic \&rm +request, or the name of a request or user defined macro being called, +is terminated by an escape sequence. +In the cases of +.Ic \&as , +.Ic \&ds , +and +.Ic \&nr , +the request has no effect at all. +In the cases of +.Ic \&am , +.Ic \&de , +.Ic \&rr , +and +.Ic \&rm , +what was parsed up to this point is used as the arguments to the request, +and the rest of the input line is discarded including the escape sequence. +When parsing for a request or a user-defined macro name to be called, +only the escape sequence is discarded. +The characters preceding it are used as the request or macro name, +the characters following it are used as the arguments to the request or macro. +.It Sy "NOT IMPLEMENTED: Bd -file" +.Pq mdoc +For security reasons, the +.Ic \&Bd +macro does not support the +.Fl file +argument. +By requesting the inclusion of a sensitive file, a malicious document +might otherwise trick a privileged user into inadvertently displaying +the file on the screen, revealing the file content to bystanders. +The argument is ignored including the file name following it. +.It Sy "skipping display without arguments" +.Pq mdoc +A +.Ic \&Bd +block macro does not have any arguments. +The block is discarded, and the block content is displayed in +whatever mode was active before the block. +.It Sy "missing list type, using -item" +.Pq mdoc +A +.Ic \&Bl +macro fails to specify the list type. +.It Sy "missing manual name, using \(dq\(dq" +.Pq mdoc +The first call to +.Ic \&Nm , +or any call in the NAME section, lacks the required argument. +.It Sy "uname(3) system call failed, using UNKNOWN" +.Pq mdoc +The +.Ic \&Os +macro is called without arguments, and the +.Xr uname 3 +system call failed. +As a workaround, +.Nm +can be compiled with +.Sm off +.Fl D Cm OSNAME=\(dq\e\(dq Ar string Cm \e\(dq\(dq . +.Sm on +.It Sy "unknown standard specifier" +.Pq mdoc +An +.Ic \&St +macro has an unknown argument and is discarded. +.It Sy "skipping request without numeric argument" +.Pq roff , eqn +An +.Ic \&it +request or an +.Xr eqn 7 +.Ic \&size +or +.Ic \&gsize +statement has a non-numeric or negative argument or no argument at all. +The invalid request or statement is ignored. +.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq" +.Pq roff +For security reasons, +.Nm +allows +.Ic \&so +file inclusion requests only with relative paths +and only without ascending to any parent directory. +By requesting the inclusion of a sensitive file, a malicious document +might otherwise trick a privileged user into inadvertently displaying +the file on the screen, revealing the file content to bystanders. +.Nm +only shows the path as it appears behind +.Ic \&so . +.It Sy ".so request failed" +.Pq roff +Servicing a +.Ic \&so +request requires reading an external file, but the file could not be +opened. +.Nm +only shows the path as it appears behind +.Ic \&so . +.It Sy "skipping all arguments" +.Pq mdoc , man , eqn , roff +An +.Xr mdoc 7 +.Ic \&Bt , +.Ic \&Ed , +.Ic \&Ef , +.Ic \&Ek , +.Ic \&El , +.Ic \&Lp , +.Ic \&Pp , +.Ic \&Re , +.Ic \&Rs , +or +.Ic \&Ud +macro, an +.Ic \&It +macro in a list that don't support item heads, a +.Xr man 7 +.Ic \&LP , +.Ic \&P , +or +.Ic \&PP +macro, an +.Xr eqn 7 +.Ic \&EQ +or +.Ic \&EN +macro, or a +.Xr roff 7 +.Ic \&br , +.Ic \&fi , +or +.Ic \&nf +request or +.Sq \&.. +block closing request is invoked with at least one argument. +All arguments are ignored. +.It Sy "skipping excess arguments" +.Pq mdoc , man , roff +A macro or request is invoked with too many arguments: +.Bl -dash -offset 2n -width 2n -compact +.It +.Ic \&Fo , +.Ic \&PD , +.Ic \&RS , +.Ic \&UR , +.Ic \&ft , +or +.Ic \&sp +with more than one argument +.It +.Ic \&An +with another argument after +.Fl split +or +.Fl nosplit +.It +.Ic \&RE +with more than one argument or with a non-integer argument +.It +.Ic \&OP +or a request of the +.Ic \&de +family with more than two arguments +.It +.Ic \&Dt +with more than three arguments +.It +.Ic \&TH +with more than five arguments +.It +.Ic \&Bd , +.Ic \&Bk , +or +.Ic \&Bl +with invalid arguments +.El +The excess arguments are ignored. +.El +.Ss Unsupported features +.Bl -ohang +.It Sy "input too large" +.Pq mdoc , man +Currently, +.Nm +cannot handle input files larger than its arbitrary size limit +of 2^31 bytes (2 Gigabytes). +Since useful manuals are always small, this is not a problem in practice. +Parsing is aborted as soon as the condition is detected. +.It Sy "unsupported control character" +.Pq roff +An ASCII control character supported by other +.Xr roff 7 +implementations but not by +.Nm +was found in an input file. +It is replaced by a question mark. +.It Sy "unsupported roff request" +.Pq roff +An input file contains a +.Xr roff 7 +request supported by GNU troff or Heirloom troff but not by +.Nm , +and it is likely that this will cause information loss +or considerable misformatting. +.It Sy "eqn delim option in tbl" +.Pq eqn , tbl +The options line of a table defines equation delimiters. +Any equation source code contained in the table will be printed unformatted. +.It Sy "unsupported table layout modifier" +.Pq tbl +A table layout specification contains an +.Sq Cm m +modifier. +The modifier is discarded. +.It Sy "ignoring macro in table" +.Pq tbl , mdoc , man +A table contains an invocation of an +.Xr mdoc 7 +or +.Xr man 7 +macro or of an undefined macro. +The macro is ignored, and its arguments are handled +as if they were a text line. +.El +.Sh SEE ALSO +.Xr apropos 1 , +.Xr man 1 , +.Xr eqn 7 , +.Xr man 7 , +.Xr mandoc_char 7 , +.Xr mdoc 7 , +.Xr roff 7 , +.Xr tbl 7 +.Sh AUTHORS +.An -nosplit +The +.Nm +utility was written by +.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv +and is maintained by +.An Ingo Schwarze Aq Mt schwarze@openbsd.org . Property changes on: vendor/mdocml/20170121/mandoc.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc.3 =================================================================== --- vendor/mdocml/20170121/mandoc.3 (nonexistent) +++ vendor/mdocml/20170121/mandoc.3 (revision 312592) @@ -0,0 +1,702 @@ +.\" $Id: mandoc.3,v 1.38 2017/01/09 01:37:03 schwarze Exp $ +.\" +.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons +.\" Copyright (c) 2010-2017 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 9 2017 $ +.Dt MANDOC 3 +.Os +.Sh NAME +.Nm mandoc , +.Nm deroff , +.Nm mandocmsg , +.Nm man_mparse , +.Nm man_validate , +.Nm mdoc_validate , +.Nm mparse_alloc , +.Nm mparse_free , +.Nm mparse_getkeep , +.Nm mparse_keep , +.Nm mparse_open , +.Nm mparse_readfd , +.Nm mparse_reset , +.Nm mparse_result , +.Nm mparse_strerror , +.Nm mparse_strlevel , +.Nm mparse_updaterc +.Nd mandoc macro compiler library +.Sh SYNOPSIS +.In sys/types.h +.In mandoc.h +.Pp +.Fd "#define ASCII_NBRSP" +.Fd "#define ASCII_HYPH" +.Fd "#define ASCII_BREAK" +.Ft struct mparse * +.Fo mparse_alloc +.Fa "int options" +.Fa "enum mandoclevel wlevel" +.Fa "mandocmsg mmsg" +.Fa "char *defos" +.Fc +.Ft void +.Fo (*mandocmsg) +.Fa "enum mandocerr errtype" +.Fa "enum mandoclevel level" +.Fa "const char *file" +.Fa "int line" +.Fa "int col" +.Fa "const char *msg" +.Fc +.Ft void +.Fo mparse_free +.Fa "struct mparse *parse" +.Fc +.Ft const char * +.Fo mparse_getkeep +.Fa "const struct mparse *parse" +.Fc +.Ft void +.Fo mparse_keep +.Fa "struct mparse *parse" +.Fc +.Ft int +.Fo mparse_open +.Fa "struct mparse *parse" +.Fa "const char *fname" +.Fc +.Ft "enum mandoclevel" +.Fo mparse_readfd +.Fa "struct mparse *parse" +.Fa "int fd" +.Fa "const char *fname" +.Fc +.Ft void +.Fo mparse_reset +.Fa "struct mparse *parse" +.Fc +.Ft void +.Fo mparse_result +.Fa "struct mparse *parse" +.Fa "struct roff_man **man" +.Fa "char **sodest" +.Fc +.Ft "const char *" +.Fo mparse_strerror +.Fa "enum mandocerr" +.Fc +.Ft "const char *" +.Fo mparse_strlevel +.Fa "enum mandoclevel" +.Fc +.Ft void +.Fo mparse_updaterc +.Fa "struct mparse *parse" +.Fa "enum mandoclevel *rc" +.Fc +.In roff.h +.Ft void +.Fo deroff +.Fa "char **dest" +.Fa "const struct roff_node *node" +.Fc +.In sys/types.h +.In mandoc.h +.In mdoc.h +.Vt extern const char * const * mdoc_argnames; +.Vt extern const char * const * mdoc_macronames; +.Ft void +.Fo mdoc_validate +.Fa "struct roff_man *mdoc" +.Fc +.In sys/types.h +.In mandoc.h +.In man.h +.Vt extern const char * const * man_macronames; +.Ft "const struct mparse *" +.Fo man_mparse +.Fa "const struct roff_man *man" +.Fc +.Ft void +.Fo man_validate +.Fa "struct roff_man *man" +.Fc +.Sh DESCRIPTION +The +.Nm mandoc +library parses a +.Ux +manual into an abstract syntax tree (AST). +.Ux +manuals are composed of +.Xr mdoc 7 +or +.Xr man 7 , +and may be mixed with +.Xr roff 7 , +.Xr tbl 7 , +and +.Xr eqn 7 +invocations. +.Pp +The following describes a general parse sequence: +.Bl -enum +.It +initiate a parsing sequence with +.Xr mchars_alloc 3 +and +.Fn mparse_alloc ; +.It +open a file with +.Xr open 2 +or +.Fn mparse_open ; +.It +parse it with +.Fn mparse_readfd ; +.It +close it with +.Xr close 2 ; +.It +retrieve the syntax tree with +.Fn mparse_result ; +.It +depending on whether the +.Fa macroset +member of the returned +.Vt struct roff_man +is +.Dv MACROSET_MDOC +or +.Dv MACROSET_MAN , +validate it with +.Fn mdoc_validate +or +.Fn man_validate , +respectively; +.It +if information about the validity of the input is needed, fetch it with +.Fn mparse_updaterc ; +.It +iterate over parse nodes with starting from the +.Fa first +member of the returned +.Vt struct roff_man ; +.It +free all allocated memory with +.Fn mparse_free +and +.Xr mchars_free 3 , +or invoke +.Fn mparse_reset +and go back to step 2 to parse new files. +.El +.Sh REFERENCE +This section documents the functions, types, and variables available +via +.In mandoc.h , +with the exception of those documented in +.Xr mandoc_escape 3 +and +.Xr mchars_alloc 3 . +.Ss Types +.Bl -ohang +.It Vt "enum mandocerr" +An error or warning message during parsing. +.It Vt "enum mandoclevel" +A classification of an +.Vt "enum mandocerr" +as regards system operation. +See the DIAGNOSTICS section in +.Xr mandoc 1 +regarding the meanings of the levels. +.It Vt "struct mparse" +An opaque pointer to a running parse sequence. +Created with +.Fn mparse_alloc +and freed with +.Fn mparse_free . +This may be used across parsed input if +.Fn mparse_reset +is called between parses. +.It Vt "mandocmsg" +A prototype for a function to handle error and warning +messages emitted by the parser. +.El +.Ss Functions +.Bl -ohang +.It Fn deroff +Obtain a text-only representation of a +.Vt struct roff_node , +including text contained in its child nodes. +To be used on children of the +.Fa first +member of +.Vt struct roff_man . +When it is no longer needed, the pointer returned from +.Fn deroff +can be passed to +.Xr free 3 . +.It Fn man_mparse +Get the parser used for the current output. +Declared in +.In man.h , +implemented in +.Pa man.c . +.It Fn man_validate +Validate the +.Dv MACROSET_MAN +parse tree obtained with +.Fn mparse_result . +Declared in +.In man.h , +implemented in +.Pa man.c . +.It Fn mdoc_validate +Validate the +.Dv MACROSET_MDOC +parse tree obtained with +.Fn mparse_result . +Declared in +.In mdoc.h , +implemented in +.Pa mdoc.c . +.It Fn mparse_alloc +Allocate a parser. +The arguments have the following effect: +.Bl -tag -offset 5n -width inttype +.It Ar options +When the +.Dv MPARSE_MDOC +or +.Dv MPARSE_MAN +bit is set, only that parser is used. +Otherwise, the document type is automatically detected. +.Pp +When the +.Dv MPARSE_SO +bit is set, +.Xr roff 7 +.Ic \&so +file inclusion requests are always honoured. +Otherwise, if the request is the only content in an input file, +only the file name is remembered, to be returned in the +.Fa sodest +argument of +.Fn mparse_result . +.Pp +When the +.Dv MPARSE_QUICK +bit is set, parsing is aborted after the NAME section. +This is for example useful in +.Xr makewhatis 8 +.Fl Q +to quickly build minimal databases. +.It Ar wlevel +Can be set to +.Dv MANDOCLEVEL_BADARG , +.Dv MANDOCLEVEL_ERROR , +or +.Dv MANDOCLEVEL_WARNING . +Messages below the selected level will be suppressed. +.It Ar mmsg +A callback function to handle errors and warnings. +See +.Pa main.c +for an example. +If printing of error messages is not desired, +.Dv NULL +may be passed. +.It Ar defos +A default string for the +.Xr mdoc 7 +.Sq \&Os +macro, overriding the +.Dv OSNAME +preprocessor definition and the results of +.Xr uname 3 . +Passing +.Dv NULL +sets no default. +.El +.Pp +The same parser may be used for multiple files so long as +.Fn mparse_reset +is called between parses. +.Fn mparse_free +must be called to free the memory allocated by this function. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_free +Free all memory allocated by +.Fn mparse_alloc . +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_getkeep +Acquire the keep buffer. +Must follow a call of +.Fn mparse_keep . +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_keep +Instruct the parser to retain a copy of its parsed input. +This can be acquired with subsequent +.Fn mparse_getkeep +calls. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_open +Open the file for reading. +If that fails and +.Fa fname +does not already end in +.Ql .gz , +try again after appending +.Ql .gz . +Save the information whether the file is zipped or not. +Return a file descriptor open for reading or -1 on failure. +It can be passed to +.Fn mparse_readfd +or used directly. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_readfd +Parse a file descriptor opened with +.Xr open 2 +or +.Fn mparse_open . +Pass the associated filename in +.Va fname . +This function may be called multiple times with different parameters; however, +.Xr close 2 +and +.Fn mparse_reset +should be invoked between parses. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_reset +Reset a parser so that +.Fn mparse_readfd +may be used again. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_result +Obtain the result of a parse. +One of the two pointers will be filled in. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_strerror +Return a statically-allocated string representation of an error code. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_strlevel +Return a statically-allocated string representation of a level code. +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.It Fn mparse_updaterc +If the highest warning or error level that occurred during the current +.Fa parse +is higher than +.Pf * Fa rc , +update +.Pf * Fa rc +accordingly. +This is useful after calling +.Fn mdoc_validate +or +.Fn man_validate . +Declared in +.In mandoc.h , +implemented in +.Pa read.c . +.El +.Ss Variables +.Bl -ohang +.It Va man_macronames +The string representation of a +.Xr man 7 +macro as indexed by +.Vt "enum mant" . +.It Va mdoc_argnames +The string representation of an +.Xr mdoc 7 +macro argument as indexed by +.Vt "enum mdocargt" . +.It Va mdoc_macronames +The string representation of an +.Xr mdoc 7 +macro as indexed by +.Vt "enum mdoct" . +.El +.Sh IMPLEMENTATION NOTES +This section consists of structural documentation for +.Xr mdoc 7 +and +.Xr man 7 +syntax trees and strings. +.Ss Man and Mdoc Strings +Strings may be extracted from mdoc and man meta-data, or from text +nodes (MDOC_TEXT and MAN_TEXT, respectively). +These strings have special non-printing formatting cues embedded in the +text itself, as well as +.Xr roff 7 +escapes preserved from input. +Implementing systems will need to handle both situations to produce +human-readable text. +In general, strings may be assumed to consist of 7-bit ASCII characters. +.Pp +The following non-printing characters may be embedded in text strings: +.Bl -tag -width Ds +.It Dv ASCII_NBRSP +A non-breaking space character. +.It Dv ASCII_HYPH +A soft hyphen. +.It Dv ASCII_BREAK +A breakable zero-width space. +.El +.Pp +Escape characters are also passed verbatim into text strings. +An escape character is a sequence of characters beginning with the +backslash +.Pq Sq \e . +To construct human-readable text, these should be intercepted with +.Xr mandoc_escape 3 +and converted with one the functions described in +.Xr mchars_alloc 3 . +.Ss Man Abstract Syntax Tree +This AST is governed by the ontological rules dictated in +.Xr man 7 +and derives its terminology accordingly. +.Pp +The AST is composed of +.Vt struct roff_node +nodes with element, root and text types as declared by the +.Va type +field. +Each node also provides its parse point (the +.Va line , +.Va pos , +and +.Va sec +fields), its position in the tree (the +.Va parent , +.Va child , +.Va next +and +.Va prev +fields) and some type-specific data. +.Pp +The tree itself is arranged according to the following normal form, +where capitalised non-terminals represent nodes. +.Pp +.Bl -tag -width "ELEMENTXX" -compact +.It ROOT +\(<- mnode+ +.It mnode +\(<- ELEMENT | TEXT | BLOCK +.It BLOCK +\(<- HEAD BODY +.It HEAD +\(<- mnode* +.It BODY +\(<- mnode* +.It ELEMENT +\(<- ELEMENT | TEXT* +.It TEXT +\(<- [[:ascii:]]* +.El +.Pp +The only elements capable of nesting other elements are those with +next-line scope as documented in +.Xr man 7 . +.Ss Mdoc Abstract Syntax Tree +This AST is governed by the ontological +rules dictated in +.Xr mdoc 7 +and derives its terminology accordingly. +.Qq In-line +elements described in +.Xr mdoc 7 +are described simply as +.Qq elements . +.Pp +The AST is composed of +.Vt struct roff_node +nodes with block, head, body, element, root and text types as declared +by the +.Va type +field. +Each node also provides its parse point (the +.Va line , +.Va pos , +and +.Va sec +fields), its position in the tree (the +.Va parent , +.Va child , +.Va last , +.Va next +and +.Va prev +fields) and some type-specific data, in particular, for nodes generated +from macros, the generating macro in the +.Va tok +field. +.Pp +The tree itself is arranged according to the following normal form, +where capitalised non-terminals represent nodes. +.Pp +.Bl -tag -width "ELEMENTXX" -compact +.It ROOT +\(<- mnode+ +.It mnode +\(<- BLOCK | ELEMENT | TEXT +.It BLOCK +\(<- HEAD [TEXT] (BODY [TEXT])+ [TAIL [TEXT]] +.It ELEMENT +\(<- TEXT* +.It HEAD +\(<- mnode* +.It BODY +\(<- mnode* [ENDBODY mnode*] +.It TAIL +\(<- mnode* +.It TEXT +\(<- [[:ascii:]]* +.El +.Pp +Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of +the BLOCK production: these refer to punctuation marks. +Furthermore, although a TEXT node will generally have a non-zero-length +string, in the specific case of +.Sq \&.Bd \-literal , +an empty line will produce a zero-length string. +Multiple body parts are only found in invocations of +.Sq \&Bl \-column , +where a new body introduces a new phrase. +.Pp +The +.Xr mdoc 7 +syntax tree accommodates for broken block structures as well. +The ENDBODY node is available to end the formatting associated +with a given block before the physical end of that block. +It has a non-null +.Va end +field, is of the BODY +.Va type , +has the same +.Va tok +as the BLOCK it is ending, and has a +.Va pending +field pointing to that BLOCK's BODY node. +It is an indirect child of that BODY node +and has no children of its own. +.Pp +An ENDBODY node is generated when a block ends while one of its child +blocks is still open, like in the following example: +.Bd -literal -offset indent +\&.Ao ao +\&.Bo bo ac +\&.Ac bc +\&.Bc end +.Ed +.Pp +This example results in the following block structure: +.Bd -literal -offset indent +BLOCK Ao + HEAD Ao + BODY Ao + TEXT ao + BLOCK Bo, pending -> Ao + HEAD Bo + BODY Bo + TEXT bo + TEXT ac + ENDBODY Ao, pending -> Ao + TEXT bc +TEXT end +.Ed +.Pp +Here, the formatting of the +.Sq \&Ao +block extends from TEXT ao to TEXT ac, +while the formatting of the +.Sq \&Bo +block extends from TEXT bo to TEXT bc. +It renders as follows in +.Fl T Ns Cm ascii +mode: +.Pp +.Dl bc] end +.Pp +Support for badly-nested blocks is only provided for backward +compatibility with some older +.Xr mdoc 7 +implementations. +Using badly-nested blocks is +.Em strongly discouraged ; +for example, the +.Fl T Ns Cm html +and +.Fl T Ns Cm xhtml +front-ends to +.Xr mandoc 1 +are unable to render them in any meaningful way. +Furthermore, behaviour when encountering badly-nested blocks is not +consistent across troff implementations, especially when using multiple +levels of badly-nested blocks. +.Sh SEE ALSO +.Xr mandoc 1 , +.Xr man.cgi 3 , +.Xr mandoc_escape 3 , +.Xr mandoc_headers 3 , +.Xr mandoc_malloc 3 , +.Xr mansearch 3 , +.Xr mchars_alloc 3 , +.Xr tbl 3 , +.Xr eqn 7 , +.Xr man 7 , +.Xr mandoc_char 7 , +.Xr mdoc 7 , +.Xr roff 7 , +.Xr tbl 7 +.Sh AUTHORS +.An -nosplit +The +.Nm +library was written by +.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv +and is maintained by +.An Ingo Schwarze Aq Mt schwarze@openbsd.org . Property changes on: vendor/mdocml/20170121/mandoc.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc.css =================================================================== --- vendor/mdocml/20170121/mandoc.css (nonexistent) +++ vendor/mdocml/20170121/mandoc.css (revision 312592) @@ -0,0 +1,173 @@ +/* $Id: mandoc.css,v 1.13 2017/01/21 02:29:57 schwarze Exp $ */ +/* + * Standard style sheet for mandoc(1) -Thtml and man.cgi(8). + */ + +/* Global defaults. */ + +html { max-width: 100ex; } +body { font-family: Helvetica,Arial,sans-serif; } +table { margin-top: 0em; + margin-bottom: 0em; } +td { vertical-align: top; } +ul, ol, dl { margin-top: 0em; + margin-bottom: 0em; } +li, dt { margin-top: 1em; } + +/* Search form and search results. */ + +fieldset { border: thin solid silver; + border-radius: 1em; + text-align: center; } +input[name=expr] { + width: 25%; } + +table.results { margin-top: 1em; + margin-left: 2em; + font-size: smaller; } + +/* Header and footer lines. */ + +table.head { width: 100%; + border-bottom: 1px dotted #808080; + margin-bottom: 1em; + font-size: smaller; } +td.head-vol { text-align: center; } +td.head-rtitle { + text-align: right; } +span.Nd { } + +table.foot { width: 100%; + border-top: 1px dotted #808080; + margin-top: 1em; + font-size: smaller; } +td.foot-os { text-align: right; } + +/* Sections and paragraphs. */ + +div.manual-text { + margin-left: 5ex; } +h1.Sh { margin-top: 2ex; + margin-bottom: 1ex; + margin-left: -4ex; + font-size: 110%; } +h2.Ss { margin-top: 2ex; + margin-bottom: 1ex; + margin-left: -2ex; + font-size: 105%; } +div.Pp { margin: 1ex 0ex; } +a.Sx { } +a.Xr { } + +/* Displays and lists. */ + +div.Bd { } +div.D1 { margin-left: 5ex; } + +ul.Bl-bullet { list-style-type: disc; + padding-left: 1em; } +li.It-bullet { } +ul.Bl-dash { list-style-type: none; + padding-left: 0em; } +li.It-dash:before { + content: "\2014 "; } +ul.Bl-item { list-style-type: none; + padding-left: 0em; } +li.It-item { } + +ol.Bl-enum { padding-left: 2em; } +li.It-enum { } + +dl.Bl-diag { } +dt.It-diag { } +dd.It-diag { } +b.It-diag { font-style: normal; } +dl.Bl-hang { } +dt.It-hang { } +dd.It-hang { } +dl.Bl-inset { } +dt.It-inset { } +dd.It-inset { } +dl.Bl-ohang { } +dt.It-ohang { } +dd.It-ohang { margin-left: 0ex; } +dl.Bl-tag { } +dt.It-tag { } +dd.It-tag { } + +table.Bl-column { } +tr.It-column { } +td.It-column { margin-top: 1em; } + +span.Rs { } +span.RsA { } +i.RsB { font-weight: normal; } +span.RsC { } +span.RsD { } +i.RsI { font-weight: normal; } +i.RsJ { font-weight: normal; } +span.RsN { } +span.RsO { } +span.RsP { } +span.RsQ { } +span.RsR { } +span.RsT { text-decoration: underline; } +a.RsU { } +span.RsV { } + +span.eqn { } +table.tbl { } + +/* Semantic markup for command line utilities. */ + +table.Nm { } +b.Nm { font-style: normal; } +b.Fl { font-style: normal; } +b.Cm { font-style: normal; } +i.Ar { font-weight: normal; } +span.Op { } +b.Ic { font-style: normal; } +code.Ev { font-style: normal; + font-weight: normal; + font-family: monospace; } +i.Pa { font-weight: normal; } + +/* Semantic markup for function libraries. */ + +span.Lb { } +b.In { font-style: normal; } +a.In { } +b.Fd { font-style: normal; } +i.Ft { font-weight: normal; } +b.Fn { font-style: normal; } +i.Fa { font-weight: normal; } +i.Vt { font-weight: normal; } +i.Va { font-weight: normal; } +code.Dv { font-style: normal; + font-weight: normal; + font-family: monospace; } +code.Er { font-style: normal; + font-weight: normal; + font-family: monospace; } + +/* Various semantic markup. */ + +span.An { } +a.Lk { } +a.Mt { } +b.Cd { font-style: normal; } +i.Ad { font-weight: normal; } +b.Ms { font-style: normal; } +a.Ux { } + +/* Physical markup. */ + +.No { font-style: normal; + font-weight: normal; } +.Em { font-style: italic; + font-weight: normal; } +.Sy { font-style: normal; + font-weight: bold; } +.Li { font-style: normal; + font-weight: normal; + font-family: monospace; } Property changes on: vendor/mdocml/20170121/mandoc.css ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/css \ No newline at end of property Index: vendor/mdocml/20170121/mandoc.db.5 =================================================================== --- vendor/mdocml/20170121/mandoc.db.5 (nonexistent) +++ vendor/mdocml/20170121/mandoc.db.5 (revision 312592) @@ -0,0 +1,228 @@ +.\" $Id: mandoc.db.5,v 1.5 2016/08/01 12:27:15 schwarze Exp $ +.\" +.\" Copyright (c) 2014, 2016 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: August 1 2016 $ +.Dt MANDOC.DB 5 +.Os +.Sh NAME +.Nm mandoc.db +.Nd manual page database +.Sh DESCRIPTION +The +.Nm +file format is used to store information about installed manual +pages to facilitate semantic searching for manuals. +Each manual page tree contains its own +.Nm +file; see +.Sx FILES +for examples. +.Pp +Such database files are generated by +.Xr makewhatis 8 +and used by +.Xr man 1 , +.Xr apropos 1 +and +.Xr whatis 1 . +.Pp +The file format uses three datatypes: +.Pp +.Bl -dash -compact -offset 2n -width 1n +.It +32-bit signed integer numbers in big endian (network) byte ordering +.It +NUL-terminated strings +.It +lists of NUL-terminated strings, terminated by a second NUL character +.El +.Pp +Numbers are aligned to four-byte boundaries; where they follow +strings or lists of strings, padding with additional NUL characters +occurs. +Some, but not all, numbers point to positions in the file. +These pointers are measured in bytes, and the first byte of the +file is considered to be byte 0. +.Pp +Each file consists of: +.Pp +.Bl -dash -compact -offset 2n -width 1n +.It +One magic number, 0x3a7d0cdb. +.It +One version number, currently 1. +.It +One pointer to the macros table. +.It +One pointer to the final magic number. +.It +The pages table (variable length). +.It +The macros table (variable length). +.It +The magic number once again, 0x3a7d0cdb. +.El +.Pp +The pages table contains one entry for each physical manual page +file, no matter how many hard and soft links it may have in the +file system. +The pages table consists of: +.Pp +.Bl -dash -compact -offset 2n -width 1n +.It +The number of pages in the database. +.It +For each page: +.Bl -dash -compact -offset 2n -width 1n +.It +One pointer to the list of names. +.It +One pointer to the list of sections. +.It +One pointer to the list of architectures +or 0 if the page is machine-independent. +.It +One pointer to the one-line description string. +.It +One pointer to the list of filenames. +.El +.It +For each page, the list of names. +Each name is preceded by a single byte indicating the sources of the name. +The meaning of the bits is: +.Bl -dash -compact -offset 2n -width 1n +.It +0x10: The name appears in a filename. +.It +0x08: The name appears in a header line, i.e. in a .Dt or .TH macro. +.It +0x04: The name is the first one in the title line, i.e. it appears +in the first .Nm macro in the NAME section. +.It +0x02: The name appears in any .Nm macro in the NAME section. +.It +0x01: The name appears in an .Nm block in the SYNOPSIS section. +.El +.It +For each page, the list of sections. +Each section is given as a string, not as a number. +.It +For each architecture-dependent page, the list of architectures. +.It +For each page, the one-line description string taken from the .Nd macro. +.It +For each page, the list of filenames relative to the root of the +respective manpath. +This list includes hard links, soft links, and links simulated +with .so +.Xr roff 7 +requests. +The first filename is preceded by a single byte +having the following significance: +.Bl -dash -compact -offset 2n -width 1n +.It +.Dv FORM_SRC No = 0x01 : +The file format is +.Xr mdoc 7 +or +.Xr man 7 . +.It +.Dv FORM_CAT No = 0x02 : +The manual page is preformatted. +.El +.It +Zero to three NUL bytes for padding. +.El +.Pp +The macros table consists of: +.Pp +.Bl -dash -compact -offset 2n -width 1n +.It +The number of different macro keys, currently 36. +The ordering of macros is defined in +.In mansearch.h +and the significance of the macro keys is documented in +.Xr apropos 1 . +.It +For each macro key, one pointer to the respective macro table. +.It +For each macro key, the macro table (variable length). +.El +.Pp +Each macro table consists of: +.Pp +.Bl -dash -compact -offset 2n -width 1n +.It +The number of entries in the table. +.It +For each entry: +.Bl -dash -compact -offset 2n -width 1n +.It +One pointer to the value of the macro key. +Each value is a string of text taken from some macro invocation. +.It +One pointer to the list of pages. +.El +.It +For each entry, the value of the macro key. +.It +Zero to three NUL bytes for padding. +.It +For each entry, one or more pointers to pages in the pages table, +pointing to the pointer to the list of names, +followed by the number 0. +.El +.Sh FILES +.Bl -tag -width /usr/share/man/mandoc.db -compact +.It Pa /usr/share/man/mandoc.db +The manual page database for the base system. +.It Pa /usr/X11R6/man/mandoc.db +The same for the +.Xr X 7 +Window System. +.It Pa /usr/local/man/mandoc.db +The same for +.Xr packages 7 . +.El +.Pp +A program to dump +.Nm +files in a human-readable format suitable for +.Xr diff 1 +is provided in the directory +.Pa /usr/src/regress/usr.bin/mandoc/db/dbm_dump/ . +.Sh SEE ALSO +.Xr apropos 1 , +.Xr man 1 , +.Xr whatis 1 , +.Xr makewhatis 8 +.Sh HISTORY +A manual page database +.Pa /usr/lib/whatis +first appeared in +.Bx 2 . +The present format first appeared in +.Ox 6.1 . +.Sh AUTHORS +.An -nosplit +The original version of +.Xr makewhatis 8 +was written by +.An Bill Joy +in 1979. +The present database format was designed by +.An Ingo Schwarze Aq Mt schwarze@openbsd.org +in 2016. Property changes on: vendor/mdocml/20170121/mandoc.db.5 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc.h =================================================================== --- vendor/mdocml/20170121/mandoc.h (nonexistent) +++ vendor/mdocml/20170121/mandoc.h (revision 312592) @@ -0,0 +1,438 @@ +/* $Id: mandoc.h,v 1.213 2017/01/09 01:37:03 schwarze Exp $ */ +/* + * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons + * Copyright (c) 2010-2017 Ingo Schwarze + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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. + */ + +#define ASCII_NBRSP 31 /* non-breaking space */ +#define ASCII_HYPH 30 /* breakable hyphen */ +#define ASCII_BREAK 29 /* breakable zero-width space */ + +/* + * Status level. This refers to both internal status (i.e., whilst + * running, when warnings/errors are reported) and an indicator of a + * threshold of when to halt (when said internal state exceeds the + * threshold). + */ +enum mandoclevel { + MANDOCLEVEL_OK = 0, + MANDOCLEVEL_RESERVED, + MANDOCLEVEL_WARNING, /* warnings: syntax, whitespace, etc. */ + MANDOCLEVEL_ERROR, /* input has been thrown away */ + MANDOCLEVEL_UNSUPP, /* input needs unimplemented features */ + MANDOCLEVEL_BADARG, /* bad argument in invocation */ + MANDOCLEVEL_SYSERR, /* system error */ + MANDOCLEVEL_MAX +}; + +/* + * All possible things that can go wrong within a parse, be it libroff, + * libmdoc, or libman. + */ +enum mandocerr { + MANDOCERR_OK, + + MANDOCERR_WARNING, /* ===== start of warnings ===== */ + + /* related to the prologue */ + MANDOCERR_DT_NOTITLE, /* missing manual title, using UNTITLED: line */ + MANDOCERR_TH_NOTITLE, /* missing manual title, using "": [macro] */ + MANDOCERR_TITLE_CASE, /* lower case character in document title */ + MANDOCERR_MSEC_MISSING, /* missing manual section, using "": macro */ + MANDOCERR_MSEC_BAD, /* unknown manual section: Dt ... section */ + MANDOCERR_DATE_MISSING, /* missing date, using today's date */ + MANDOCERR_DATE_BAD, /* cannot parse date, using it verbatim: date */ + MANDOCERR_OS_MISSING, /* missing Os macro, using "" */ + MANDOCERR_PROLOG_REP, /* duplicate prologue macro: macro */ + MANDOCERR_PROLOG_LATE, /* late prologue macro: macro */ + MANDOCERR_DT_LATE, /* skipping late title macro: Dt args */ + MANDOCERR_PROLOG_ORDER, /* prologue macros out of order: macros */ + + /* related to document structure */ + MANDOCERR_SO, /* .so is fragile, better use ln(1): so path */ + MANDOCERR_DOC_EMPTY, /* no document body */ + MANDOCERR_SEC_BEFORE, /* content before first section header: macro */ + MANDOCERR_NAMESEC_FIRST, /* first section is not NAME: Sh title */ + MANDOCERR_NAMESEC_NONM, /* NAME section without Nm before Nd */ + MANDOCERR_NAMESEC_NOND, /* NAME section without description */ + MANDOCERR_NAMESEC_ND, /* description not at the end of NAME */ + MANDOCERR_NAMESEC_BAD, /* bad NAME section content: macro */ + MANDOCERR_NAMESEC_PUNCT, /* missing comma before name: Nm name */ + MANDOCERR_ND_EMPTY, /* missing description line, using "" */ + MANDOCERR_SEC_ORDER, /* sections out of conventional order: Sh title */ + MANDOCERR_SEC_REP, /* duplicate section title: Sh title */ + MANDOCERR_SEC_MSEC, /* unexpected section: Sh title for ... only */ + MANDOCERR_XR_ORDER, /* unusual Xr order: ... after ... */ + MANDOCERR_XR_PUNCT, /* unusual Xr punctuation: ... after ... */ + MANDOCERR_AN_MISSING, /* AUTHORS section without An macro */ + + /* related to macros and nesting */ + MANDOCERR_MACRO_OBS, /* obsolete macro: macro */ + MANDOCERR_MACRO_CALL, /* macro neither callable nor escaped: macro */ + MANDOCERR_PAR_SKIP, /* skipping paragraph macro: macro ... */ + MANDOCERR_PAR_MOVE, /* moving paragraph macro out of list: macro */ + MANDOCERR_NS_SKIP, /* skipping no-space macro */ + MANDOCERR_BLK_NEST, /* blocks badly nested: macro ... */ + MANDOCERR_BD_NEST, /* nested displays are not portable: macro ... */ + MANDOCERR_BL_MOVE, /* moving content out of list: macro */ + MANDOCERR_FI_SKIP, /* fill mode already enabled, skipping: fi */ + MANDOCERR_NF_SKIP, /* fill mode already disabled, skipping: nf */ + MANDOCERR_BLK_LINE, /* line scope broken: macro breaks macro */ + + /* related to missing arguments */ + MANDOCERR_REQ_EMPTY, /* skipping empty request: request */ + MANDOCERR_COND_EMPTY, /* conditional request controls empty scope */ + MANDOCERR_MACRO_EMPTY, /* skipping empty macro: macro */ + MANDOCERR_BLK_EMPTY, /* empty block: macro */ + MANDOCERR_ARG_EMPTY, /* empty argument, using 0n: macro arg */ + MANDOCERR_BD_NOTYPE, /* missing display type, using -ragged: Bd */ + MANDOCERR_BL_LATETYPE, /* list type is not the first argument: Bl arg */ + MANDOCERR_BL_NOWIDTH, /* missing -width in -tag list, using 6n */ + MANDOCERR_EX_NONAME, /* missing utility name, using "": Ex */ + MANDOCERR_FO_NOHEAD, /* missing function name, using "": Fo */ + MANDOCERR_IT_NOHEAD, /* empty head in list item: Bl -type It */ + MANDOCERR_IT_NOBODY, /* empty list item: Bl -type It */ + MANDOCERR_BF_NOFONT, /* missing font type, using \fR: Bf */ + MANDOCERR_BF_BADFONT, /* unknown font type, using \fR: Bf font */ + MANDOCERR_PF_SKIP, /* nothing follows prefix: Pf arg */ + MANDOCERR_RS_EMPTY, /* empty reference block: Rs */ + MANDOCERR_XR_NOSEC, /* missing section argument: Xr arg */ + MANDOCERR_ARG_STD, /* missing -std argument, adding it: macro */ + MANDOCERR_OP_EMPTY, /* missing option string, using "": OP */ + MANDOCERR_UR_NOHEAD, /* missing resource identifier, using "": UR */ + MANDOCERR_EQN_NOBOX, /* missing eqn box, using "": op */ + + /* related to bad arguments */ + MANDOCERR_ARG_QUOTE, /* unterminated quoted argument */ + MANDOCERR_ARG_REP, /* duplicate argument: macro arg */ + MANDOCERR_AN_REP, /* skipping duplicate argument: An -arg */ + MANDOCERR_BD_REP, /* skipping duplicate display type: Bd -type */ + MANDOCERR_BL_REP, /* skipping duplicate list type: Bl -type */ + MANDOCERR_BL_SKIPW, /* skipping -width argument: Bl -type */ + MANDOCERR_BL_COL, /* wrong number of cells */ + MANDOCERR_AT_BAD, /* unknown AT&T UNIX version: At version */ + MANDOCERR_FA_COMMA, /* comma in function argument: arg */ + MANDOCERR_FN_PAREN, /* parenthesis in function name: arg */ + MANDOCERR_RS_BAD, /* invalid content in Rs block: macro */ + MANDOCERR_SM_BAD, /* invalid Boolean argument: macro arg */ + MANDOCERR_FT_BAD, /* unknown font, skipping request: ft font */ + MANDOCERR_TR_ODD, /* odd number of characters in request: tr char */ + + /* related to plain text */ + MANDOCERR_FI_BLANK, /* blank line in fill mode, using .sp */ + MANDOCERR_FI_TAB, /* tab in filled text */ + MANDOCERR_SPACE_EOL, /* whitespace at end of input line */ + MANDOCERR_COMMENT_BAD, /* bad comment style */ + MANDOCERR_ESC_BAD, /* invalid escape sequence: esc */ + MANDOCERR_STR_UNDEF, /* undefined string, using "": name */ + + /* related to tables */ + MANDOCERR_TBLLAYOUT_SPAN, /* tbl line starts with span */ + MANDOCERR_TBLLAYOUT_DOWN, /* tbl column starts with span */ + MANDOCERR_TBLLAYOUT_VERT, /* skipping vertical bar in tbl layout */ + + MANDOCERR_ERROR, /* ===== start of errors ===== */ + + /* related to tables */ + MANDOCERR_TBLOPT_ALPHA, /* non-alphabetic character in tbl options */ + MANDOCERR_TBLOPT_BAD, /* skipping unknown tbl option: option */ + MANDOCERR_TBLOPT_NOARG, /* missing tbl option argument: option */ + MANDOCERR_TBLOPT_ARGSZ, /* wrong tbl option argument size: option */ + MANDOCERR_TBLLAYOUT_NONE, /* empty tbl layout */ + MANDOCERR_TBLLAYOUT_CHAR, /* invalid character in tbl layout: char */ + MANDOCERR_TBLLAYOUT_PAR, /* unmatched parenthesis in tbl layout */ + MANDOCERR_TBLDATA_NONE, /* tbl without any data cells */ + MANDOCERR_TBLDATA_SPAN, /* ignoring data in spanned tbl cell: data */ + MANDOCERR_TBLDATA_EXTRA, /* ignoring extra tbl data cells: data */ + MANDOCERR_TBLDATA_BLK, /* data block open at end of tbl: macro */ + + /* related to document structure and macros */ + MANDOCERR_FILE, /* cannot open file */ + MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */ + MANDOCERR_CHAR_BAD, /* skipping bad character: number */ + MANDOCERR_MACRO, /* skipping unknown macro: macro */ + MANDOCERR_REQ_INSEC, /* skipping insecure request: request */ + MANDOCERR_IT_STRAY, /* skipping item outside list: It ... */ + MANDOCERR_TA_STRAY, /* skipping column outside column list: Ta */ + MANDOCERR_BLK_NOTOPEN, /* skipping end of block that is not open */ + MANDOCERR_RE_NOTOPEN, /* fewer RS blocks open, skipping: RE arg */ + MANDOCERR_BLK_BROKEN, /* inserting missing end of block: macro ... */ + MANDOCERR_BLK_NOEND, /* appending missing end of block: macro */ + + /* related to request and macro arguments */ + MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */ + MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */ + MANDOCERR_BD_NOARG, /* skipping display without arguments: Bd */ + MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */ + MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */ + MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */ + MANDOCERR_ST_BAD, /* unknown standard specifier: St standard */ + MANDOCERR_IT_NONUM, /* skipping request without numeric argument */ + MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */ + MANDOCERR_SO_FAIL, /* .so request failed */ + MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */ + MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */ + MANDOCERR_DIVZERO, /* divide by zero */ + + MANDOCERR_UNSUPP, /* ===== start of unsupported features ===== */ + + MANDOCERR_TOOLARGE, /* input too large */ + MANDOCERR_CHAR_UNSUPP, /* unsupported control character: number */ + MANDOCERR_REQ_UNSUPP, /* unsupported roff request: request */ + MANDOCERR_TBLOPT_EQN, /* eqn delim option in tbl: arg */ + MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */ + MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */ + + MANDOCERR_MAX +}; + +struct tbl_opts { + char tab; /* cell-separator */ + char decimal; /* decimal point */ + int opts; +#define TBL_OPT_CENTRE (1 << 0) +#define TBL_OPT_EXPAND (1 << 1) +#define TBL_OPT_BOX (1 << 2) +#define TBL_OPT_DBOX (1 << 3) +#define TBL_OPT_ALLBOX (1 << 4) +#define TBL_OPT_NOKEEP (1 << 5) +#define TBL_OPT_NOSPACE (1 << 6) +#define TBL_OPT_NOWARN (1 << 7) + int cols; /* number of columns */ + int lvert; /* width of left vertical line */ + int rvert; /* width of right vertical line */ +}; + +enum tbl_cellt { + TBL_CELL_CENTRE, /* c, C */ + TBL_CELL_RIGHT, /* r, R */ + TBL_CELL_LEFT, /* l, L */ + TBL_CELL_NUMBER, /* n, N */ + TBL_CELL_SPAN, /* s, S */ + TBL_CELL_LONG, /* a, A */ + TBL_CELL_DOWN, /* ^ */ + TBL_CELL_HORIZ, /* _, - */ + TBL_CELL_DHORIZ, /* = */ + TBL_CELL_MAX +}; + +/* + * A cell in a layout row. + */ +struct tbl_cell { + struct tbl_cell *next; + int vert; /* width of subsequent vertical line */ + enum tbl_cellt pos; + size_t spacing; + int col; /* column number, starting from 0 */ + int flags; +#define TBL_CELL_TALIGN (1 << 0) /* t, T */ +#define TBL_CELL_BALIGN (1 << 1) /* d, D */ +#define TBL_CELL_BOLD (1 << 2) /* fB, B, b */ +#define TBL_CELL_ITALIC (1 << 3) /* fI, I, i */ +#define TBL_CELL_EQUAL (1 << 4) /* e, E */ +#define TBL_CELL_UP (1 << 5) /* u, U */ +#define TBL_CELL_WIGN (1 << 6) /* z, Z */ +#define TBL_CELL_WMAX (1 << 7) /* x, X */ +}; + +/* + * A layout row. + */ +struct tbl_row { + struct tbl_row *next; + struct tbl_cell *first; + struct tbl_cell *last; + int vert; /* width of left vertical line */ +}; + +enum tbl_datt { + TBL_DATA_NONE, /* has no data */ + TBL_DATA_DATA, /* consists of data/string */ + TBL_DATA_HORIZ, /* horizontal line */ + TBL_DATA_DHORIZ, /* double-horizontal line */ + TBL_DATA_NHORIZ, /* squeezed horizontal line */ + TBL_DATA_NDHORIZ /* squeezed double-horizontal line */ +}; + +/* + * A cell within a row of data. The "string" field contains the actual + * string value that's in the cell. The rest is layout. + */ +struct tbl_dat { + struct tbl_cell *layout; /* layout cell */ + int spans; /* how many spans follow */ + struct tbl_dat *next; + char *string; /* data (NULL if not TBL_DATA_DATA) */ + enum tbl_datt pos; +}; + +enum tbl_spant { + TBL_SPAN_DATA, /* span consists of data */ + TBL_SPAN_HORIZ, /* span is horizontal line */ + TBL_SPAN_DHORIZ /* span is double horizontal line */ +}; + +/* + * A row of data in a table. + */ +struct tbl_span { + struct tbl_opts *opts; + struct tbl_row *layout; /* layout row */ + struct tbl_dat *first; + struct tbl_dat *last; + struct tbl_span *prev; + struct tbl_span *next; + int line; /* parse line */ + enum tbl_spant pos; +}; + +enum eqn_boxt { + EQN_ROOT, /* root of parse tree */ + EQN_TEXT, /* text (number, variable, whatever) */ + EQN_SUBEXPR, /* nested `eqn' subexpression */ + EQN_LIST, /* list (braces, etc.) */ + EQN_LISTONE, /* singleton list */ + EQN_PILE, /* vertical pile */ + EQN_MATRIX /* pile of piles */ +}; + +enum eqn_fontt { + EQNFONT_NONE = 0, + EQNFONT_ROMAN, + EQNFONT_BOLD, + EQNFONT_FAT, + EQNFONT_ITALIC, + EQNFONT__MAX +}; + +enum eqn_post { + EQNPOS_NONE = 0, + EQNPOS_SUP, + EQNPOS_SUBSUP, + EQNPOS_SUB, + EQNPOS_TO, + EQNPOS_FROM, + EQNPOS_FROMTO, + EQNPOS_OVER, + EQNPOS_SQRT, + EQNPOS__MAX +}; + +enum eqn_pilet { + EQNPILE_NONE = 0, + EQNPILE_PILE, + EQNPILE_CPILE, + EQNPILE_RPILE, + EQNPILE_LPILE, + EQNPILE_COL, + EQNPILE_CCOL, + EQNPILE_RCOL, + EQNPILE_LCOL, + EQNPILE__MAX +}; + + /* + * A "box" is a parsed mathematical expression as defined by the eqn.7 + * grammar. + */ +struct eqn_box { + int size; /* font size of expression */ +#define EQN_DEFSIZE INT_MIN + enum eqn_boxt type; /* type of node */ + struct eqn_box *first; /* first child node */ + struct eqn_box *last; /* last child node */ + struct eqn_box *next; /* node sibling */ + struct eqn_box *prev; /* node sibling */ + struct eqn_box *parent; /* node sibling */ + char *text; /* text (or NULL) */ + char *left; /* fence left-hand */ + char *right; /* fence right-hand */ + char *top; /* expression over-symbol */ + char *bottom; /* expression under-symbol */ + size_t args; /* arguments in parent */ + size_t expectargs; /* max arguments in parent */ + enum eqn_post pos; /* position of next box */ + enum eqn_fontt font; /* font of box */ + enum eqn_pilet pile; /* equation piling */ +}; + +/* + * An equation consists of a tree of expressions starting at a given + * line and position. + */ +struct eqn { + char *name; /* identifier (or NULL) */ + struct eqn_box *root; /* root mathematical expression */ + int ln; /* invocation line */ + int pos; /* invocation position */ +}; + +/* + * Parse options. + */ +#define MPARSE_MDOC 1 /* assume -mdoc */ +#define MPARSE_MAN 2 /* assume -man */ +#define MPARSE_SO 4 /* honour .so requests */ +#define MPARSE_QUICK 8 /* abort the parse early */ +#define MPARSE_UTF8 16 /* accept UTF-8 input */ +#define MPARSE_LATIN1 32 /* accept ISO-LATIN-1 input */ + +enum mandoc_esc { + ESCAPE_ERROR = 0, /* bail! unparsable escape */ + ESCAPE_IGNORE, /* escape to be ignored */ + ESCAPE_SPECIAL, /* a regular special character */ + 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_SKIPCHAR, /* skip the next character */ + ESCAPE_OVERSTRIKE /* overstrike all chars in the argument */ +}; + +typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel, + const char *, int, int, const char *); + + +struct mparse; +struct roff_man; + +enum mandoc_esc mandoc_escape(const char **, const char **, int *); +void mchars_alloc(void); +void mchars_free(void); +int mchars_num2char(const char *, size_t); +const char *mchars_uc2str(int); +int mchars_num2uc(const char *, size_t); +int mchars_spec2cp(const char *, size_t); +const char *mchars_spec2str(const char *, size_t, size_t *); +struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg, const char *); +void mparse_free(struct mparse *); +void mparse_keep(struct mparse *); +int mparse_open(struct mparse *, const char *); +enum mandoclevel mparse_readfd(struct mparse *, int, const char *); +enum mandoclevel mparse_readmem(struct mparse *, void *, size_t, + const char *); +void mparse_reset(struct mparse *); +void mparse_result(struct mparse *, + struct roff_man **, char **); +const char *mparse_getkeep(const struct mparse *); +const char *mparse_strerror(enum mandocerr); +const char *mparse_strlevel(enum mandoclevel); +void mparse_updaterc(struct mparse *, enum mandoclevel *); Property changes on: vendor/mdocml/20170121/mandoc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc_aux.h =================================================================== --- vendor/mdocml/20170121/mandoc_aux.h (nonexistent) +++ vendor/mdocml/20170121/mandoc_aux.h (revision 312592) @@ -0,0 +1,26 @@ +/* $Id: mandoc_aux.h,v 1.5 2016/07/19 13:36:13 schwarze Exp $ */ +/* + * Copyright (c) 2009, 2011 Kristaps Dzonsons + * Copyright (c) 2014 Ingo Schwarze + * + * 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. + */ + +int mandoc_asprintf(char **, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void *mandoc_calloc(size_t, size_t); +void *mandoc_malloc(size_t); +void *mandoc_realloc(void *, size_t); +void *mandoc_reallocarray(void *, size_t, size_t); +char *mandoc_strdup(const char *); +char *mandoc_strndup(const char *, size_t); Property changes on: vendor/mdocml/20170121/mandoc_aux.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandoc_html.3 =================================================================== --- vendor/mdocml/20170121/mandoc_html.3 (nonexistent) +++ vendor/mdocml/20170121/mandoc_html.3 (revision 312592) @@ -0,0 +1,340 @@ +.\" $Id: mandoc_html.3,v 1.3 2017/01/17 15:32:44 schwarze Exp $ +.\" +.\" Copyright (c) 2014, 2017 Ingo Schwarze +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 17 2017 $ +.Dt MANDOC_HTML 3 +.Os +.Sh NAME +.Nm mandoc_html +.Nd internals of the mandoc HTML formatter +.Sh SYNOPSIS +.In "html.h" +.Ft void +.Fn print_gen_decls "struct html *h" +.Ft void +.Fn print_gen_head "struct html *h" +.Ft struct tag * +.Fo print_otag +.Fa "struct html *h" +.Fa "enum htmltag tag" +.Fa "const char *fmt" +.Fa ... +.Fc +.Ft void +.Fo print_tagq +.Fa "struct html *h" +.Fa "const struct tag *until" +.Fc +.Ft void +.Fo print_stagq +.Fa "struct html *h" +.Fa "const struct tag *suntil" +.Fc +.Ft void +.Fo print_text +.Fa "struct html *h" +.Fa "const char *word" +.Fc +.Sh DESCRIPTION +The mandoc HTML formatter is not a formal library. +However, as it is compiled into more than one program, in particular +.Xr mandoc 1 +and +.Xr man.cgi 8 , +and because it may be security-critical in some contexts, +some documentation is useful to help to use it correctly and +to prevent XSS vulnerabilities. +.Pp +The formatter produces HTML output on the standard output. +Since proper escaping is usually required and best taken care of +at one central place, the language-specific formatters +.Po +.Pa *_html.c , +see +.Sx FILES +.Pc +are not supposed to print directly to +.Dv stdout +using functions like +.Xr printf 3 , +.Xr putc 3 , +.Xr puts 3 , +or +.Xr write 2 . +Instead, they are expected to use the output functions declared in +.Pa html.h +and implemented as part of the main HTML formatting engine in +.Pa html.c . +.Ss Data structures +These structures are declared in +.Pa html.h . +.Bl -tag -width Ds +.It Vt struct html +Internal state of the HTML formatter. +.It Vt struct tag +One entry for the LIFO stack of HTML elements. +Members are +.Fa "enum htmltag tag" +and +.Fa "struct tag *next" . +.El +.Ss Private interface functions +The function +.Fn print_gen_decls +prints the opening +.Ao Pf \&? Ic xml ? Ac +and +.Aq Pf \&! Ic DOCTYPE +declarations required for the current document type. +.Pp +The function +.Fn print_gen_head +prints the opening +.Aq Ic META +and +.Aq Ic LINK +elements for the document +.Aq Ic HEAD , +using the +.Fa style +member of +.Fa h +unless that is +.Dv NULL . +It uses +.Fn print_otag +which takes care of properly encoding attributes, +which is relevant for the +.Fa style +link in particular. +.Pp +The function +.Fn print_otag +prints the start tag of an HTML element with the name +.Fa tag , +optionally including the attributes specified by +.Fa fmt . +If +.Fa fmt +is the empty string, no attributes are written. +Each letter of +.Fa fmt +specifies one attribute to write. +Most attributes require one +.Va char * +argument which becomes the value of the attribute. +The arguments have to be given in the same order as the attribute letters. +.Bl -tag -width 1n -offset indent +.It Cm c +Print a +.Cm class +attribute. +.It Cm h +Print a +.Cm href +attribute. +This attribute letter can optionally be followed by a modifier letter. +If followed by +.Cm R , +it formats the link as a local one by prefixing a +.Sq # +character. +If followed by +.Cm I , +it interpretes the argument as a header file name +and generates a link using the +.Xr mandoc 1 +.Fl O Cm includes +option. +If followed by +.Cm M , +it takes two arguments instead of one, a manual page name and +section, and formats them as a link to a manual page using the +.Xr mandoc 1 +.Fl O Cm man +option. +.It Cm i +Print an +.Cm id +attribute. +.It Cm \&? +Print an arbitrary attribute. +This format letter requires two +.Vt char * +arguments, the attribute name and the value. +.It Cm s +Print a +.Cm style +attribute. +If present, it must be the last format letter. +In contrast to the other format letters, this one does not yet +print the value and does not require an argument. +Instead, the rest of the format string consists of pairs of +argument type letters and style name letters. +.El +.Pp +Argument type letters each require on argument as follows: +.Bl -tag -width 1n -offset indent +.It Cm h +Requires one +.Vt int +argument, interpreted as a horizontal length in units of +.Dv SCALE_EN . +.It Cm s +Requires one +.Vt char * +argument, used as a style value. +.It Cm u +Requires one +.Vt struct roffsu * +argument, used as a length. +.It Cm v +Requires one +.Vt int +argument, interpreted as a vertical length in units of +.Dv SCALE_VS . +.It Cm w +Requires one +.Vt char * +argument, interpreted as an +.Xr mdoc 7 Ns -style +width specifier. +.El +.Pp +Style name letters decide what to do with the preceding argument: +.Bl -tag -width 1n -offset indent +.It Cm b +Set +.Cm margin-bottom +to the given length. +.It Cm h +Set +.Cm height +to the given length. +.It Cm i +Set +.Cm text-indent +to the given length. +.It Cm l +Set +.Cm margin-left +to the given length. +.It Cm t +Set +.Cm margin-top +to the given length. +.It Cm w +Set +.Cm width +to the given length. +.It Cm W +Set +.Cm min-width +to the given length. +.It Cm \&? +The special pair +.Cm s? +requires two +.Vt char * +arguments. +The first is the style name, the second its value. +.El +.Pp +.Fn print_otag +uses the private function +.Fn print_encode +to take care of HTML encoding. +If required by the element type, it remembers in +.Fa h +that the element is open. +The function +.Fn print_tagq +is used to close out all open elements up to and including +.Fa until ; +.Fn print_stagq +is a variant to close out all open elements up to but excluding +.Fa suntil . +.Pp +The function +.Fn print_text +prints HTML element content. +It uses the private function +.Fn print_encode +to take care of HTML encoding. +If the document has requested a non-standard font, for example using a +.Xr roff 7 +.Ic \ef +font escape sequence, +.Fn print_text +wraps +.Fa word +in an HTML font selection element using the +.Fn print_otag +and +.Fn print_tagq +functions. +.Pp +The functions +.Fn html_strlen , +.Fn print_eqn , +.Fn print_tbl , +and +.Fn print_tblclose +are not yet documented. +.Sh FILES +.Bl -tag -width mandoc_aux.c -compact +.It Pa main.h +declarations of public functions for use by the main program, +not yet documented +.It Pa html.h +declarations of data types and private functions +for use by language-specific HTML formatters +.It Pa html.c +main HTML formatting engine and utility functions +.It Pa mdoc_html.c +.Xr mdoc 7 +HTML formatter +.It Pa man_html.c +.Xr man 7 +HTML formatter +.It Pa tbl_html.c +.Xr tbl 7 +HTML formatter +.It Pa eqn_html.c +.Xr eqn 7 +HTML formatter +.It Pa out.h +declarations of data types and private functions +for shared use by all mandoc formatters, +not yet documented +.It Pa out.c +private functions for shared use by all mandoc formatters +.It Pa mandoc_aux.h +declarations of common mandoc utility functions, see +.Xr mandoc 3 +.It Pa mandoc_aux.c +implementation of common mandoc utility functions +.El +.Sh SEE ALSO +.Xr mandoc 1 , +.Xr mandoc 3 , +.Xr man.cgi 8 +.Sh AUTHORS +.An -nosplit +The mandoc HTML formatter was written by +.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv . +This manual was written by +.An Ingo Schwarze Aq Mt schwarze@openbsd.org . Property changes on: vendor/mdocml/20170121/mandoc_html.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/mdocml/20170121/mandocdb.c =================================================================== --- vendor/mdocml/20170121/mandocdb.c (nonexistent) +++ vendor/mdocml/20170121/mandocdb.c (revision 312592) @@ -0,0 +1,2274 @@ +/* $Id: mandocdb.c,v 1.237 2017/01/11 17:39:53 schwarze Exp $ */ +/* + * Copyright (c) 2011, 2012 Kristaps Dzonsons + * Copyright (c) 2011-2017 Ingo Schwarze + * Copyright (c) 2016 Ed Maste + * + * 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 AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include +#include +#include + +#include +#include +#if HAVE_ERR +#include +#endif +#include +#include +#if HAVE_FTS +#include