diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-06-26 17:56:44 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-06-26 17:56:44 +0000 |
commit | b8356f8ddb7db759bb2d0127e1d696abbc40a6b7 (patch) | |
tree | c6440ef0074ad1cb8ade3e95a121ba58e421aa40 | |
parent | 3d32c5d68dc8f6ddc0ced4e6c6b8148e0c22c1cb (diff) |
merge release 1.10.2
* bug fixes:
- interaction of ASCII_HYPH with special chars (found by Ulrich Spoerlein)
- handling of roff conditionals (found by Ulrich Spoerlein)
- .Bd -offset will no more default to 6n
* maintenance:
- more caching of .Bd and .Bl arguments for efficiency
- deconstify man(7) validation routines
- add FreeBSD library names (provided by Ulrich Spoerlein)
* start PostScript font-switching
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/lib.in | 29 | ||||
-rw-r--r-- | usr.bin/mandoc/libman.h | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/libmandoc.h | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/main.c | 8 | ||||
-rw-r--r-- | usr.bin/mandoc/man_validate.c | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.1 | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.c | 86 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 8 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc.7 | 25 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc.c | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc.h | 29 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_action.c | 185 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_argv.c | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_html.c | 70 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_term.c | 161 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_validate.c | 184 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.7 | 19 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 97 | ||||
-rw-r--r-- | usr.bin/mandoc/term.c | 9 | ||||
-rw-r--r-- | usr.bin/mandoc/term.h | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/term_ps.c | 203 |
22 files changed, 673 insertions, 494 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 965fab9ad32..d6847a8cc83 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.40 2010/06/10 22:50:10 schwarze Exp $ +# $OpenBSD: Makefile,v 1.41 2010/06/26 17:56:43 schwarze Exp $ .include <bsd.own.mk> -VERSION=1.10.1 +VERSION=1.10.2 CFLAGS+=-DVERSION=\"${VERSION}\" CFLAGS+=-W -Wall -Wstrict-prototypes diff --git a/usr.bin/mandoc/lib.in b/usr.bin/mandoc/lib.in index 5a51a34c590..05ea04cfcbf 100644 --- a/usr.bin/mandoc/lib.in +++ b/usr.bin/mandoc/lib.in @@ -1,6 +1,6 @@ -/* $Id: lib.in,v 1.4 2010/05/15 22:04:31 schwarze Exp $ */ +/* $Id: lib.in,v 1.5 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,25 +27,42 @@ LINE("libarchive", "Reading and Writing Streaming Archives Library (libarchive, LINE("libarm", "ARM Architecture Library (libarm, \\-larm)") LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)") LINE("libbluetooth", "Bluetooth Library (libbluetooth, \\-lbluetooth)") +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("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("libedit", "Command Line Editor Library (libedit, \\-ledit)") LINE("libelf", "ELF Parsing Library (libelf, \\-lelf)") LINE("libevent", "Event Notification Library (libevent, \\-levent)") LINE("libfetch", "File Transfer Library for URLs (libfetch, \\-lfetch)") 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("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("libjail", "Jail Library (libjail, \\-ljail)") +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("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("libnetgraph", "Netgraph User Library (libnetgraph, \\-lnetgraph)") LINE("libnetpgp", "Netpgp signing, verification, encryption and decryption (libnetpgp, \\-lnetpgp)") LINE("libossaudio", "OSS Audio Emulation Library (libossaudio, \\-lossaudio)") LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)") @@ -58,11 +75,19 @@ LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)") LINE("libpuffs", "puffs Convenience Library (libpuffs, \\-lpuffs)") 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("libsdp", "Bluetooth Service Discovery Protocol User Library (libsdp, \\-lsdp)") LINE("libssp", "Buffer Overflow Protection Library (libssp, \\-lssp)") 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)") diff --git a/usr.bin/mandoc/libman.h b/usr.bin/mandoc/libman.h index 2b8333ae9be..d187aba5c5e 100644 --- a/usr.bin/mandoc/libman.h +++ b/usr.bin/mandoc/libman.h @@ -1,6 +1,6 @@ -/* $Id: libman.h,v 1.21 2010/05/24 02:27:31 schwarze Exp $ */ +/* $Id: libman.h,v 1.22 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -79,7 +79,7 @@ int man_args(struct man *, int, int *, char *, char **); int man_vmsg(struct man *, enum mandocerr, int, int, const char *, ...); int man_valid_post(struct man *); -int man_valid_pre(struct man *, const struct man_node *); +int man_valid_pre(struct man *, struct man_node *); int man_action_post(struct man *); int man_action_pre(struct man *, struct man_node *); int man_unscope(struct man *, diff --git a/usr.bin/mandoc/libmandoc.h b/usr.bin/mandoc/libmandoc.h index 4ceac4bfe37..9001dc797d7 100644 --- a/usr.bin/mandoc/libmandoc.h +++ b/usr.bin/mandoc/libmandoc.h @@ -1,6 +1,6 @@ -/* $Id: libmandoc.h,v 1.5 2010/05/26 02:39:58 schwarze Exp $ */ +/* $Id: libmandoc.h,v 1.6 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,7 @@ __BEGIN_DECLS -int mandoc_special(const char *); +int mandoc_special(char *); void *mandoc_calloc(size_t, size_t); char *mandoc_strdup(const char *); void *mandoc_malloc(size_t); diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 91566c31aa3..129ebac3aec 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,6 +1,6 @@ -/* $Id: main.c,v 1.36 2010/06/10 22:50:10 schwarze Exp $ */ +/* $Id: main.c,v 1.37 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -98,6 +98,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "unterminated quoted string", "argument requires the width argument", "superfluous width argument", + "ignoring argument", "bad date argument", "bad width argument", "unknown manual section", @@ -132,12 +133,13 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "macro requires argument(s)", "no title in document", "missing list type", + "missing display type", "line argument(s) will be lost", "body argument(s) will be lost", "column syntax is inconsistent", "missing font type", - "missing display type", "displays may not be nested", + "unsupported display type", "no scope to rewind: syntax violated", "scope broken, syntax violated", "line scope broken, syntax violated", diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c index b36b9c1d9e2..8658846720a 100644 --- a/usr.bin/mandoc/man_validate.c +++ b/usr.bin/mandoc/man_validate.c @@ -1,6 +1,6 @@ -/* $Id: man_validate.c,v 1.26 2010/05/26 02:39:58 schwarze Exp $ */ +/* $Id: man_validate.c,v 1.27 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,7 @@ #include "libman.h" #include "libmandoc.h" -#define CHKARGS struct man *m, const struct man_node *n +#define CHKARGS struct man *m, struct man_node *n typedef int (*v_check)(CHKARGS); @@ -97,7 +97,7 @@ static const struct man_valid man_valids[MAN_MAX] = { int -man_valid_pre(struct man *m, const struct man_node *n) +man_valid_pre(struct man *m, struct man_node *n) { v_check *cp; @@ -200,7 +200,7 @@ check_title(CHKARGS) static int check_text(CHKARGS) { - const char *p; + char *p; int pos, c; assert(n->string); diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1 index 4cd7d651ce6..4d9398f9e19 100644 --- a/usr.bin/mandoc/mandoc.1 +++ b/usr.bin/mandoc/mandoc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mandoc.1,v 1.31 2010/06/10 22:50:10 schwarze Exp $ +.\" $OpenBSD: mandoc.1,v 1.32 2010/06/26 17:56:43 schwarze Exp $ .\" .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 10 2010 $ +.Dd $Mdocdate: June 26 2010 $ .Dt MANDOC 1 .Os .Sh NAME @@ -348,7 +348,7 @@ cause rendered documents to appear as they do in .Pp Special characters are rendered in decimal-encoded UTF-8. .Ss PostScript Output -PostScript Level 1 pages may be generated by +PostScript Level 2 pages may be generated by .Fl T Ns Cm ps . Output pages are US-letter sized (215.9 x 279.4 mm) and rendered in fixed, 10-point Courier font. diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c index e83a98aa8ab..b652e5e2190 100644 --- a/usr.bin/mandoc/mandoc.c +++ b/usr.bin/mandoc/mandoc.c @@ -1,6 +1,6 @@ -/* $Id: mandoc.c,v 1.13 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mandoc.c,v 1.14 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,20 +23,42 @@ #include <string.h> #include <time.h> +#include "mandoc.h" #include "libmandoc.h" -static int a2time(time_t *, const char *, const char *); +static int a2time(time_t *, const char *, const char *); +static int spec_norm(char *, int); + + +/* + * "Normalise" a special string by converting its ASCII_HYPH entries + * into actual hyphens. + */ +static int +spec_norm(char *p, int sz) +{ + int i; + + for (i = 0; i < sz; i++) + if (ASCII_HYPH == p[i]) + p[i] = '-'; + + return(sz); +} int -mandoc_special(const char *p) +mandoc_special(char *p) { int terminator; /* Terminator for \s. */ int lim; /* Limit for N in \s. */ int c, i; + char *sv; + sv = p; + if ('\\' != *p++) - return(0); + return(spec_norm(sv, 0)); switch (*p) { case ('\''): @@ -45,6 +67,8 @@ mandoc_special(const char *p) /* FALLTHROUGH */ case ('q'): /* FALLTHROUGH */ + case (ASCII_HYPH): + /* FALLTHROUGH */ case ('-'): /* FALLTHROUGH */ case ('~'): @@ -68,12 +92,12 @@ mandoc_special(const char *p) case (':'): /* FALLTHROUGH */ case ('c'): - return(2); + /* FALLTHROUGH */ case ('e'): - return(2); + return(spec_norm(sv, 2)); case ('s'): if ('\0' == *++p) - return(2); + return(spec_norm(sv, 2)); c = 2; terminator = 0; @@ -103,21 +127,21 @@ mandoc_special(const char *p) if (*p == '\'') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 0; terminator = 1; ++p; ++c; } else if (*p == '[') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 0; terminator = 2; ++p; ++c; } else if (*p == '(') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 2; terminator = 3; ++p; @@ -127,7 +151,7 @@ mandoc_special(const char *p) /* TODO: needs to handle floating point. */ if ( ! isdigit((u_char)*p)) - return(0); + return(spec_norm(sv, 0)); for (i = 0; isdigit((u_char)*p); i++) { if (lim && i >= lim) @@ -138,52 +162,52 @@ mandoc_special(const char *p) if (terminator && terminator < 3) { if (1 == terminator && *p != '\'') - return(0); + return(spec_norm(sv, 0)); if (2 == terminator && *p != ']') - return(0); + return(spec_norm(sv, 0)); ++p; ++c; } - return(c); + return(spec_norm(sv, c)); case ('f'): /* FALLTHROUGH */ case ('F'): /* FALLTHROUGH */ case ('*'): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); switch (*p) { case ('('): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - return(4); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + return(spec_norm(sv, 4)); case ('['): for (c = 3, p++; *p && ']' != *p; p++, c++) - if ( ! isgraph((u_char)*p)) + if (isspace((u_char)*p)) break; - return(*p == ']' ? c : 0); + return(spec_norm(sv, *p == ']' ? c : 0)); default: break; } - return(3); + return(spec_norm(sv, 3)); case ('('): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - return(4); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + return(spec_norm(sv, 4)); case ('['): break; default: - return(0); + return(spec_norm(sv, 0)); } for (c = 3, p++; *p && ']' != *p; p++, c++) - if ( ! isgraph((u_char)*p)) + if (isspace((u_char)*p)) break; - return(*p == ']' ? c : 0); + return(spec_norm(sv, *p == ']' ? c : 0)); } diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index 6e1efa9e14e..696da7ce450 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -1,4 +1,4 @@ -/* $Id: mandoc.h,v 1.6 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mandoc.h,v 1.7 2010/06/26 17:56:43 schwarze Exp $ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -36,7 +36,9 @@ enum mandocerr { MANDOCERR_BADESCAPE, /* bad escape sequence */ MANDOCERR_BADQUOTE, /* unterminated quoted string */ MANDOCERR_NOWIDTHARG, /* argument requires the width argument */ + /* FIXME: merge with MANDOCERR_IGNARGV. */ MANDOCERR_WIDTHARG, /* superfluous width argument */ + MANDOCERR_IGNARGV, /* macro ignoring argv */ MANDOCERR_BADDATE, /* bad date argument */ MANDOCERR_BADWIDTH, /* bad width argument */ MANDOCERR_BADMSEC, /* unknown manual section */ @@ -74,6 +76,7 @@ enum mandocerr { MANDOCERR_NOARGV, /* macro requires argument(s) */ MANDOCERR_NOTITLE, /* no title in document */ MANDOCERR_LISTTYPE, /* missing list type */ + MANDOCERR_DISPTYPE, /* missing display type */ MANDOCERR_ARGSLOST, /* line argument(s) will be lost */ MANDOCERR_BODYLOST, /* body argument(s) will be lost */ #define MANDOCERR_ERROR MANDOCERR_BODYLOST @@ -82,9 +85,8 @@ enum mandocerr { /* FIXME: this should be a MANDOCERR_ERROR */ MANDOCERR_FONTTYPE, /* missing font type */ /* FIXME: this should be a MANDOCERR_ERROR */ - MANDOCERR_DISPTYPE, /* missing display type */ - /* FIXME: this should be a MANDOCERR_ERROR */ MANDOCERR_NESTEDDISP, /* displays may not be nested */ + MANDOCERR_BADDISP, /* unsupported display type */ MANDOCERR_SYNTNOSCOPE, /* request scope close w/none open */ MANDOCERR_SYNTSCOPE, /* scope broken, syntax violated */ MANDOCERR_SYNTLINESCOPE, /* line scope broken, syntax violated */ diff --git a/usr.bin/mandoc/mdoc.7 b/usr.bin/mandoc/mdoc.7 index aebf9c5417a..cba102ea04c 100644 --- a/usr.bin/mandoc/mdoc.7 +++ b/usr.bin/mandoc/mdoc.7 @@ -1,4 +1,4 @@ -.\" $Id: mdoc.7,v 1.35 2010/06/08 00:11:47 schwarze Exp $ +.\" $Id: mdoc.7,v 1.36 2010/06/26 17:56:43 schwarze Exp $ .\" .\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 8 2010 $ +.Dd $Mdocdate: June 26 2010 $ .Dt MDOC 7 .Os .Sh NAME @@ -1094,10 +1094,7 @@ As a scaling unit following the syntax described in As the calculated string length of the opaque string. .El .Pp -If unset, it will revert to the value of -.Ar 8n -as described in -.Sx Scaling Widths . +If not provided an argument, it will be ignored. .It Fl compact Do not assert a vertical space before the block. .It Fl file Ar file @@ -2169,6 +2166,9 @@ Heirloom troff, the other significant troff implementation accepting .Pp .Bl -dash -compact .It +Old groff fails to assert a newline before +.Sx \&Bd Fl ragged compact . +.It groff behaves inconsistently when encountering .Pf non- Sx \&Fa children of @@ -2243,16 +2243,15 @@ In quoted literals, groff allowed pair-wise double-quotes to produce a standalone double-quote in formatted output. This idiosyncratic behaviour is not applicable in mandoc. .It -Display types +Display offsets .Sx \&Bd -.Fl center +.Fl offset Ar center and -.Fl right -are aliases for -.Fl left -in mandoc. Furthermore, the +.Fl offset Ar right +are disregarded in mandoc. +Furthermore, the .Fl file Ar file -argument is ignored. +argument is not supported in mandoc. Lastly, since text is not right-justified in mandoc (or even groff), .Fl ragged and diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c index aec75eae499..d0e60ef0980 100644 --- a/usr.bin/mandoc/mdoc.c +++ b/usr.bin/mandoc/mdoc.c @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.56 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mdoc.c,v 1.57 2010/06/26 17:56:43 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -564,7 +564,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs) */ if (MDOC_Bl == n->tok && MDOC_BODY == n->type && - LIST_column == n->data.list) { + LIST_column == n->data.Bl.type) { /* `Bl' is open without any children. */ m->flags |= MDOC_FREECOL; return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf)); @@ -573,7 +573,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs) if (MDOC_It == n->tok && MDOC_BLOCK == n->type && NULL != n->parent && MDOC_Bl == n->parent->tok && - LIST_column == n->parent->data.list) { + LIST_column == n->parent->data.Bl.type) { /* `Bl' has block-level `It' children. */ m->flags |= MDOC_FREECOL; return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf)); @@ -779,7 +779,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs) */ if (MDOC_Bl == n->tok && MDOC_BODY == n->type && - LIST_column == n->data.list) { + LIST_column == n->data.Bl.type) { m->flags |= MDOC_FREECOL; if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf)) goto err; @@ -795,7 +795,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs) if (MDOC_It == n->tok && MDOC_BLOCK == n->type && NULL != n->parent && MDOC_Bl == n->parent->tok && - LIST_column == n->parent->data.list) { + LIST_column == n->parent->data.Bl.type) { m->flags |= MDOC_FREECOL; if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf)) goto err; diff --git a/usr.bin/mandoc/mdoc.h b/usr.bin/mandoc/mdoc.h index 80e04579da4..dc51b4e92a6 100644 --- a/usr.bin/mandoc/mdoc.h +++ b/usr.bin/mandoc/mdoc.h @@ -1,6 +1,6 @@ -/* $Id: mdoc.h,v 1.27 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mdoc.h,v 1.28 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -263,6 +263,28 @@ enum mdoc_list { LIST_tag }; +enum mdoc_disp { + DISP__NONE = 0, + DISP_centred, + DISP_ragged, + DISP_unfilled, + DISP_filled, + DISP_literal +}; + +struct mdoc_bd { + const char *offs; /* -offset */ + enum mdoc_disp type; /* -ragged, etc. */ + int comp; /* -compact */ +}; + +struct mdoc_bl { + const char *width; /* -width */ + const char *offs; /* -offset */ + enum mdoc_list type; /* -tag, -enum, etc. */ + int comp; /* -compact */ +}; + /* Node in AST. */ struct mdoc_node { struct mdoc_node *parent; /* parent AST node */ @@ -288,7 +310,8 @@ struct mdoc_node { char *string; /* TEXT */ union { - enum mdoc_list list; /* for `Bl' nodes */ + struct mdoc_bl Bl; + struct mdoc_bd Bd; } data; }; diff --git a/usr.bin/mandoc/mdoc_action.c b/usr.bin/mandoc/mdoc_action.c index dbb100c3123..9aafbdfe9df 100644 --- a/usr.bin/mandoc/mdoc_action.c +++ b/usr.bin/mandoc/mdoc_action.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_action.c,v 1.40 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mdoc_action.c,v 1.41 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -64,9 +64,7 @@ static int post_st(POST_ARGS); static int post_std(POST_ARGS); static int pre_bd(PRE_ARGS); -static int pre_bl(PRE_ARGS); static int pre_dl(PRE_ARGS); -static int pre_offset(PRE_ARGS); static const struct actions mdoc_actions[MDOC_MAX] = { { NULL, NULL }, /* Ap */ @@ -80,7 +78,7 @@ static const struct actions mdoc_actions[MDOC_MAX] = { { pre_dl, post_display }, /* Dl */ { pre_bd, post_display }, /* Bd */ { NULL, NULL }, /* Ed */ - { pre_bl, post_bl }, /* Bl */ + { NULL, post_bl }, /* Bl */ { NULL, NULL }, /* El */ { NULL, NULL }, /* It */ { NULL, NULL }, /* Ad */ @@ -629,33 +627,34 @@ static int post_bl_tagwidth(POST_ARGS) { struct mdoc_node *nn; - size_t sz; + size_t sz, ssz; int i; char buf[NUMSIZ]; - /* Defaults to ten ens. */ - - sz = 10; /* XXX: make this a macro value. */ + sz = 10; for (nn = n->body->child; nn; nn = nn->next) { - if (MDOC_It == nn->tok) - break; - } + if (MDOC_It != nn->tok) + continue; - if (nn) { assert(MDOC_BLOCK == nn->type); nn = nn->head->child; - if (MDOC_TEXT != nn->type) { - sz = mdoc_macro2len(nn->tok); - if (sz == 0) { - if ( ! mdoc_nmsg(m, n, MANDOCERR_NOWIDTHARG)) - return(0); - sz = 10; - } - } else + + if (MDOC_TEXT == nn->type) { sz = strlen(nn->string) + 1; + break; + } + + if (0 != (ssz = mdoc_macro2len(nn->tok))) + sz = ssz; + else if ( ! mdoc_nmsg(m, n, MANDOCERR_NOWIDTHARG)) + return(0); + + break; } + /* Defaults to ten ens. */ + snprintf(buf, NUMSIZ, "%zun", sz); /* @@ -663,19 +662,21 @@ post_bl_tagwidth(POST_ARGS) * We're guaranteed that a MDOC_Width doesn't already exist. */ - nn = n; - assert(nn->args); - i = (int)(nn->args->argc)++; - - nn->args->argv = mandoc_realloc(nn->args->argv, - nn->args->argc * sizeof(struct mdoc_argv)); - - nn->args->argv[i].arg = MDOC_Width; - nn->args->argv[i].line = n->line; - nn->args->argv[i].pos = n->pos; - nn->args->argv[i].sz = 1; - nn->args->argv[i].value = mandoc_malloc(sizeof(char *)); - nn->args->argv[i].value[0] = mandoc_strdup(buf); + assert(n->args); + i = (int)(n->args->argc)++; + + n->args->argv = mandoc_realloc(n->args->argv, + n->args->argc * sizeof(struct mdoc_argv)); + + n->args->argv[i].arg = MDOC_Width; + n->args->argv[i].line = n->line; + n->args->argv[i].pos = n->pos; + n->args->argv[i].sz = 1; + n->args->argv[i].value = mandoc_malloc(sizeof(char *)); + n->args->argv[i].value[0] = mandoc_strdup(buf); + + /* Set our width! */ + n->data.Bl.width = n->args->argv[i].value[0]; return(1); } @@ -692,36 +693,35 @@ post_bl_width(POST_ARGS) int i; enum mdoct tok; char buf[NUMSIZ]; - char *p; - - if (NULL == n->args) - return(1); - - for (i = 0; i < (int)n->args->argc; i++) - if (MDOC_Width == n->args->argv[i].arg) - break; - - if (i == (int)n->args->argc) - return(1); - p = n->args->argv[i].value[0]; /* * If the value to -width is a macro, then we re-write it to be * the macro's width as set in share/tmac/mdoc/doc-common. */ - if (0 == strcmp(p, "Ds")) + if (0 == strcmp(n->data.Bl.width, "Ds")) width = 6; - else if (MDOC_MAX == (tok = mdoc_hash_find(p))) + else if (MDOC_MAX == (tok = mdoc_hash_find(n->data.Bl.width))) return(1); else if (0 == (width = mdoc_macro2len(tok))) return(mdoc_nmsg(m, n, MANDOCERR_BADWIDTH)); /* The value already exists: free and reallocate it. */ + assert(n->args); + + for (i = 0; i < (int)n->args->argc; i++) + if (MDOC_Width == n->args->argv[i].arg) + break; + + assert(i < (int)n->args->argc); + snprintf(buf, NUMSIZ, "%zun", width); free(n->args->argv[i].value[0]); n->args->argv[i].value[0] = mandoc_strdup(buf); + + /* Set our width! */ + n->data.Bl.width = n->args->argv[i].value[0]; return(1); } @@ -737,7 +737,9 @@ post_bl_head(POST_ARGS) int i, c; struct mdoc_node *np, *nn, *nnp; - if (NULL == n->child) + if (LIST_column != n->data.Bl.type) + return(1); + else if (NULL == n->child) return(1); np = n->parent; @@ -747,8 +749,7 @@ post_bl_head(POST_ARGS) if (MDOC_Column == np->args->argv[c].arg) break; - if (c == (int)np->args->argc) - return(1); + assert(c < (int)np->args->argc); assert(0 == np->args->argv[c].sz); /* @@ -778,7 +779,8 @@ post_bl_head(POST_ARGS) static int post_bl(POST_ARGS) { - int i, r, len; + struct mdoc_node *nn; + const char *ww; if (MDOC_HEAD == n->type) return(post_bl_head(m, n)); @@ -793,21 +795,27 @@ post_bl(POST_ARGS) * rewritten into real lengths). */ - len = (int)(n->args ? n->args->argc : 0); + ww = n->data.Bl.width; - for (r = i = 0; i < len; i++) { - if (MDOC_Tag == n->args->argv[i].arg) - r |= 1 << 0; - if (MDOC_Width == n->args->argv[i].arg) - r |= 1 << 1; - } - - if (r & (1 << 0) && ! (r & (1 << 1))) { + if (LIST_tag == n->data.Bl.type && NULL == n->data.Bl.width) { if ( ! post_bl_tagwidth(m, n)) return(0); - } else if (r & (1 << 1)) + } else if (NULL != n->data.Bl.width) { if ( ! post_bl_width(m, n)) return(0); + } else + return(1); + + assert(n->data.Bl.width); + + /* If it has changed, propogate new width to children. */ + + if (ww == n->data.Bl.width) + return(1); + + for (nn = n->child; nn; nn = nn->next) + if (MDOC_Bl == nn->tok) + nn->data.Bl.width = n->data.Bl.width; return(1); } @@ -827,7 +835,6 @@ post_pa(POST_ARGS) np = n; m->next = MDOC_NEXT_CHILD; - /* XXX: make into macro value. */ if ( ! mdoc_word_alloc(m, n->line, n->pos, "~")) return(0); m->last = np; @@ -933,61 +940,17 @@ pre_dl(PRE_ARGS) } -/* ARGSUSED */ -static int -pre_offset(PRE_ARGS) -{ - int i; - - /* - * Make sure that an empty offset produces an 8n length space as - * stipulated by mdoc.samples. - */ - - for (i = 0; n->args && i < (int)n->args->argc; i++) { - if (MDOC_Offset != n->args->argv[i].arg) - continue; - if (n->args->argv[i].sz) - break; - assert(1 == n->args->refcnt); - /* If no value set, length of <string>. */ - n->args->argv[i].sz++; - n->args->argv[i].value = mandoc_malloc(sizeof(char *)); - n->args->argv[i].value[0] = mandoc_strdup("8n"); - break; - } - - return(1); -} - - -static int -pre_bl(PRE_ARGS) -{ - - if (MDOC_BLOCK == n->type) - return(pre_offset(m, n)); - return(1); -} - - static int pre_bd(PRE_ARGS) { - int i; - if (MDOC_BLOCK == n->type) - return(pre_offset(m, n)); if (MDOC_BODY != n->type) return(1); - /* Enter literal context if `Bd -literal' or `-unfilled'. */ - - for (n = n->parent, i = 0; i < (int)n->args->argc; i++) - if (MDOC_Literal == n->args->argv[i].arg) - m->flags |= MDOC_LITERAL; - else if (MDOC_Unfilled == n->args->argv[i].arg) - m->flags |= MDOC_LITERAL; + if (DISP_literal == n->data.Bd.type) + m->flags |= MDOC_LITERAL; + if (DISP_unfilled == n->data.Bd.type) + m->flags |= MDOC_LITERAL; return(1); } diff --git a/usr.bin/mandoc/mdoc_argv.c b/usr.bin/mandoc/mdoc_argv.c index ef98643e148..a556aa1d768 100644 --- a/usr.bin/mandoc/mdoc_argv.c +++ b/usr.bin/mandoc/mdoc_argv.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_argv.c,v 1.30 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mdoc_argv.c,v 1.31 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -355,7 +355,7 @@ mdoc_args(struct mdoc *m, int line, int *pos, if (MDOC_Bl == n->tok) break; - if (n && LIST_column == n->data.list) { + if (n && LIST_column == n->data.Bl.type) { fl |= ARGS_TABSEP; fl &= ~ARGS_DELIM; } diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c index bf7fc126b9c..4fac42a6faa 100644 --- a/usr.bin/mandoc/mdoc_html.c +++ b/usr.bin/mandoc/mdoc_html.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_html.c,v 1.21 2010/06/08 00:11:47 schwarze Exp $ */ +/* $Id: mdoc_html.c,v 1.22 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1031,11 +1031,13 @@ mdoc_it_pre(MDOC_ARGS) if (MDOC_BLOCK != n->type) bl = bl->parent; - type = bl->data.list; + SCALE_HS_INIT(&offs, 0); - /* Set default width and offset. */ + type = bl->data.Bl.type; + comp = bl->data.Bl.comp; - SCALE_HS_INIT(&offs, 0); + if (bl->data.Bl.offs) + a2offs(bl->data.Bl.offs, &offs); switch (type) { case (LIST_enum): @@ -1052,23 +1054,15 @@ mdoc_it_pre(MDOC_ARGS) break; } - /* Get width, offset, and compact arguments. */ + if (bl->data.Bl.width) + a2width(bl->data.Bl.width, &width); wp = -1; - for (comp = i = 0; bl->args && i < (int)bl->args->argc; i++) + for (i = 0; bl->args && i < (int)bl->args->argc; i++) switch (bl->args->argv[i].arg) { case (MDOC_Column): wp = i; /* Save for later. */ break; - case (MDOC_Width): - a2width(bl->args->argv[i].value[0], &width); - break; - case (MDOC_Offset): - a2offs(bl->args->argv[i].value[0], &offs); - break; - case (MDOC_Compact): - comp = 1; - break; default: break; } @@ -1119,7 +1113,7 @@ mdoc_bl_pre(MDOC_ARGS) return(0); if (MDOC_BLOCK != n->type) return(1); - if (LIST_enum != n->data.list) + if (LIST_enum != n->data.Bl.type) return(1); ord = malloc(sizeof(struct ord)); @@ -1143,7 +1137,7 @@ mdoc_bl_post(MDOC_ARGS) if (MDOC_BLOCK != n->type) return; - if (LIST_enum != n->data.list) + if (LIST_enum != n->data.Bl.type) return; ord = h->ords.head; @@ -1349,42 +1343,19 @@ static int mdoc_bd_pre(MDOC_ARGS) { struct htmlpair tag[2]; - int type, comp, i; - const struct mdoc_node *bl, *nn; + int comp; + const struct mdoc_node *nn; struct roffsu su; - if (MDOC_BLOCK == n->type) - bl = n; - else if (MDOC_HEAD == n->type) + if (MDOC_HEAD == n->type) return(0); - else - bl = n->parent; SCALE_VS_INIT(&su, 0); - type = comp = 0; - for (i = 0; bl->args && i < (int)bl->args->argc; i++) - switch (bl->args->argv[i].arg) { - case (MDOC_Offset): - a2offs(bl->args->argv[i].value[0], &su); - break; - case (MDOC_Compact): - comp = 1; - break; - case (MDOC_Centred): - /* FALLTHROUGH */ - case (MDOC_Ragged): - /* FALLTHROUGH */ - case (MDOC_Filled): - /* FALLTHROUGH */ - case (MDOC_Unfilled): - /* FALLTHROUGH */ - case (MDOC_Literal): - type = bl->args->argv[i].arg; - break; - default: - break; - } + if (n->data.Bd.offs) + a2offs(n->data.Bd.offs, &su); + + comp = n->data.Bd.comp; /* FIXME: -centered, etc. formatting. */ /* FIXME: does not respect -offset ??? */ @@ -1411,7 +1382,8 @@ mdoc_bd_pre(MDOC_ARGS) return(1); } - if (MDOC_Unfilled != type && MDOC_Literal != type) + if (DISP_unfilled != n->data.Bd.type && + DISP_literal != n->data.Bd.type) return(1); PAIR_CLASS_INIT(&tag[0], "lit"); diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c index bbdae2807e0..00d8d9ab19d 100644 --- a/usr.bin/mandoc/mdoc_term.c +++ b/usr.bin/mandoc/mdoc_term.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_term.c,v 1.87 2010/06/10 22:50:10 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.88 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -48,15 +48,12 @@ struct termact { void (*post)(DECL_ARGS); }; -static size_t a2width(const struct mdoc_argv *, int); +static size_t a2width(const char *); static size_t a2height(const struct mdoc_node *); -static size_t a2offs(const struct mdoc_argv *); +static size_t a2offs(const char *); static int arg_hasattr(int, const struct mdoc_node *); -static int arg_getattrs(const int *, int *, size_t, - const struct mdoc_node *); static int arg_getattr(int, const struct mdoc_node *); -static int arg_disptype(const struct mdoc_node *); static void print_bvspace(struct termp *, const struct mdoc_node *, const struct mdoc_node *); @@ -473,62 +470,33 @@ a2height(const struct mdoc_node *n) static size_t -a2width(const struct mdoc_argv *arg, int pos) +a2width(const char *v) { struct roffsu su; - assert(arg->value[pos]); - if ( ! a2roffsu(arg->value[pos], &su, SCALE_MAX)) - SCALE_HS_INIT(&su, strlen(arg->value[pos])); + assert(v); + if ( ! a2roffsu(v, &su, SCALE_MAX)) + SCALE_HS_INIT(&su, strlen(v)); return(term_hspan(&su)); } -static int -arg_disptype(const struct mdoc_node *n) -{ - int i, len; - - assert(MDOC_BLOCK == n->type); - - len = (int)(n->args ? n->args->argc : 0); - - for (i = 0; i < len; i++) - switch (n->args->argv[i].arg) { - case (MDOC_Centred): - /* FALLTHROUGH */ - case (MDOC_Ragged): - /* FALLTHROUGH */ - case (MDOC_Filled): - /* FALLTHROUGH */ - case (MDOC_Unfilled): - /* FALLTHROUGH */ - case (MDOC_Literal): - return(n->args->argv[i].arg); - default: - break; - } - - return(-1); -} - - static size_t -a2offs(const struct mdoc_argv *arg) +a2offs(const char *v) { struct roffsu su; - if ('\0' == arg->value[0][0]) + if ('\0' == *v) return(0); - else if (0 == strcmp(arg->value[0], "left")) + else if (0 == strcmp(v, "left")) return(0); - else if (0 == strcmp(arg->value[0], "indent")) + else if (0 == strcmp(v, "indent")) return(INDENT + 1); - else if (0 == strcmp(arg->value[0], "indent-two")) + else if (0 == strcmp(v, "indent-two")) return((INDENT + 1) * 2); - else if ( ! a2roffsu(arg->value[0], &su, SCALE_MAX)) - SCALE_HS_INIT(&su, strlen(arg->value[0])); + else if ( ! a2roffsu(v, &su, SCALE_MAX)) + SCALE_HS_INIT(&su, strlen(v)); return(term_hspan(&su)); } @@ -548,39 +516,21 @@ arg_hasattr(int arg, const struct mdoc_node *n) /* * Get the index of an argument in a node's argument list or -1 if it - * does not exist. See arg_getattrs(). + * does not exist. */ static int arg_getattr(int v, const struct mdoc_node *n) { - int val; - - return(arg_getattrs(&v, &val, 1, n) ? val : -1); -} - - -/* - * Walk through the argument list for a node and fill an array "vals" - * with the positions of the argument structures listed in "keys". - * Return the number of elements that were written into "vals", which - * can be zero. - */ -static int -arg_getattrs(const int *keys, int *vals, - size_t sz, const struct mdoc_node *n) -{ - int i, j, k; + int i; if (NULL == n->args) return(0); - for (k = i = 0; i < (int)n->args->argc; i++) - for (j = 0; j < (int)sz; j++) - if (n->args->argv[i].arg == keys[j]) { - vals[j] = i; - k++; - } - return(k); + for (i = 0; i < (int)n->args->argc; i++) + if (n->args->argv[i].arg == v) + return(i); + + return(-1); } @@ -597,7 +547,10 @@ print_bvspace(struct termp *p, const struct mdoc_node *nn; term_newln(p); - if (arg_hasattr(MDOC_Compact, bl)) + + if (MDOC_Bd == bl->tok && bl->data.Bd.comp) + return; + if (MDOC_Bl == bl->tok && bl->data.Bl.comp) return; /* Do not vspace directly after Ss/Sh. */ @@ -616,13 +569,13 @@ print_bvspace(struct termp *p, /* A `-column' does not assert vspace within the list. */ - if (MDOC_Bl == bl->tok && LIST_column == bl->data.list) + if (MDOC_Bl == bl->tok && LIST_column == bl->data.Bl.type) if (n->prev && MDOC_It == n->prev->tok) return; /* A `-diag' without body does not vspace. */ - if (MDOC_Bl == bl->tok && LIST_diag == bl->data.list) + if (MDOC_Bl == bl->tok && LIST_diag == bl->data.Bl.type) if (n->prev && MDOC_It == n->prev->tok) { assert(n->prev->body); if (NULL == n->prev->body->child) @@ -666,7 +619,7 @@ termp_it_pre(DECL_ARGS) { const struct mdoc_node *bl, *nn; char buf[7]; - int i, keys[3], vals[3]; + int i, col; size_t width, offset, ncols, dcol; enum mdoc_list type; @@ -676,18 +629,7 @@ termp_it_pre(DECL_ARGS) } bl = n->parent->parent->parent; - - /* Get list width, offset, and list type from argument list. */ - - keys[0] = MDOC_Width; - keys[1] = MDOC_Offset; - keys[2] = MDOC_Column; - - vals[0] = vals[1] = vals[2] = -1; - - arg_getattrs(keys, vals, 3, bl); - - type = bl->data.list; + type = bl->data.Bl.type; /* * First calculate width and offset. This is pretty easy unless @@ -697,13 +639,16 @@ termp_it_pre(DECL_ARGS) width = offset = 0; - if (vals[1] >= 0) - offset = a2offs(&bl->args->argv[vals[1]]); + if (bl->data.Bl.offs) + offset = a2offs(bl->data.Bl.offs); switch (type) { case (LIST_column): if (MDOC_HEAD == n->type) break; + + col = arg_getattr(MDOC_Column, bl); + /* * Imitate groff's column handling: * - For each earlier column, add its width. @@ -713,7 +658,7 @@ termp_it_pre(DECL_ARGS) * column. * - For more than 5 columns, add only one column. */ - ncols = bl->args->argv[vals[2]].sz; + ncols = bl->args->argv[col].sz; /* LINTED */ dcol = ncols < 5 ? 4 : ncols == 5 ? 3 : 1; @@ -726,8 +671,7 @@ termp_it_pre(DECL_ARGS) nn->prev && i < (int)ncols; nn = nn->prev, i++) offset += dcol + a2width - (&bl->args->argv[vals[2]], i); - + (bl->args->argv[col].value[i]); /* * When exceeding the declared number of columns, leave @@ -742,10 +686,10 @@ termp_it_pre(DECL_ARGS) * Use the declared column widths, extended as explained * in the preceding paragraph. */ - width = a2width(&bl->args->argv[vals[2]], i) + dcol; + width = a2width(bl->args->argv[col].value[i]) + dcol; break; default: - if (vals[0] < 0) + if (NULL == bl->data.Bl.width) break; /* @@ -753,7 +697,8 @@ termp_it_pre(DECL_ARGS) * number for buffering single arguments. See the above * handling for column for how this changes. */ - width = a2width(&bl->args->argv[vals[0]], 0) + 2; + assert(bl->data.Bl.width); + width = a2width(bl->data.Bl.width) + 2; break; } @@ -1015,7 +960,7 @@ termp_it_post(DECL_ARGS) if (MDOC_BLOCK == n->type) return; - type = n->parent->parent->parent->data.list; + type = n->parent->parent->parent->data.Bl.type; switch (type) { case (LIST_item): @@ -1628,7 +1573,6 @@ static int termp_bd_pre(DECL_ARGS) { size_t tabwidth; - int i, type; size_t rm, rmax; const struct mdoc_node *nn; @@ -1638,13 +1582,8 @@ termp_bd_pre(DECL_ARGS) } else if (MDOC_HEAD == n->type) return(0); - nn = n->parent; - - type = arg_disptype(nn); - assert(-1 != type); - - if (-1 != (i = arg_getattr(MDOC_Offset, nn))) - p->offset += a2offs(&nn->args->argv[i]); + if (n->data.Bd.offs) + p->offset += a2offs(n->data.Bd.offs); /* * If -ragged or -filled are specified, the block does nothing @@ -1654,7 +1593,8 @@ termp_bd_pre(DECL_ARGS) * lines are allowed. */ - if (MDOC_Literal != type && MDOC_Unfilled != type) + if (DISP_literal != n->data.Bd.type && + DISP_unfilled != n->data.Bd.type) return(1); tabwidth = p->tabwidth; @@ -1671,8 +1611,8 @@ termp_bd_pre(DECL_ARGS) NULL == nn->next) term_flushln(p); } - p->tabwidth = tabwidth; + p->tabwidth = tabwidth; p->rmargin = rm; p->maxrmargin = rmax; return(0); @@ -1683,19 +1623,16 @@ termp_bd_pre(DECL_ARGS) static void termp_bd_post(DECL_ARGS) { - int type; size_t rm, rmax; if (MDOC_BODY != n->type) return; - type = arg_disptype(n->parent); - assert(-1 != type); - rm = p->rmargin; rmax = p->maxrmargin; - if (MDOC_Literal == type || MDOC_Unfilled == type) + if (DISP_literal == n->data.Bd.type || + DISP_unfilled == n->data.Bd.type) p->rmargin = p->maxrmargin = TERM_MAXMARGIN; p->flags |= TERMP_NOSPACE; diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c index 7d336d05567..2baad2bc213 100644 --- a/usr.bin/mandoc/mdoc_validate.c +++ b/usr.bin/mandoc/mdoc_validate.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.60 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.61 2010/06/26 17:56:43 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -43,12 +43,10 @@ struct valids { static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type); static int check_stdarg(PRE_ARGS); -static int check_text(struct mdoc *, int, int, const char *); +static int check_text(struct mdoc *, int, int, char *); static int check_argv(struct mdoc *, - const struct mdoc_node *, - const struct mdoc_argv *); -static int check_args(struct mdoc *, - const struct mdoc_node *); + struct mdoc_node *, struct mdoc_argv *); +static int check_args(struct mdoc *, struct mdoc_node *); static int err_child_lt(struct mdoc *, const char *, int); static int warn_child_lt(struct mdoc *, const char *, int); static int err_child_gt(struct mdoc *, const char *, int); @@ -273,7 +271,7 @@ mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n) { v_pre *p; int line, pos; - const char *tp; + char *tp; if (MDOC_TEXT == n->type) { tp = n->string; @@ -415,7 +413,7 @@ check_stdarg(PRE_ARGS) static int -check_args(struct mdoc *m, const struct mdoc_node *n) +check_args(struct mdoc *m, struct mdoc_node *n) { int i; @@ -432,8 +430,7 @@ check_args(struct mdoc *m, const struct mdoc_node *n) static int -check_argv(struct mdoc *m, const struct mdoc_node *n, - const struct mdoc_argv *v) +check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v) { int i; @@ -453,7 +450,7 @@ check_argv(struct mdoc *m, const struct mdoc_node *n, static int -check_text(struct mdoc *mdoc, int line, int pos, const char *p) +check_text(struct mdoc *mdoc, int line, int pos, char *p) { int c; @@ -531,15 +528,17 @@ pre_display(PRE_ARGS) static int pre_bl(PRE_ARGS) { - int i, width, offs, cmpt, dupl; + int i, comp, dup; + const char *offs, *width; enum mdoc_list lt; if (MDOC_BLOCK != n->type) { assert(n->parent); assert(MDOC_BLOCK == n->parent->type); assert(MDOC_Bl == n->parent->tok); - assert(LIST__NONE != n->parent->data.list); - n->data.list = n->parent->data.list; + assert(LIST__NONE != n->parent->data.Bl.type); + memcpy(&n->data.Bl, &n->parent->data.Bl, + sizeof(struct mdoc_bl)); return(1); } @@ -549,13 +548,13 @@ pre_bl(PRE_ARGS) * ones. If we find no list type, we default to LIST_item. */ - assert(LIST__NONE == n->data.list); - offs = width = cmpt = -1; + assert(LIST__NONE == n->data.Bl.type); /* LINTED */ for (i = 0; n->args && i < (int)n->args->argc; i++) { lt = LIST__NONE; - dupl = 0; + dup = comp = 0; + width = offs = NULL; switch (n->args->argv[i].arg) { /* Set list types. */ case (MDOC_Bullet): @@ -593,43 +592,54 @@ pre_bl(PRE_ARGS) break; /* Set list arguments. */ case (MDOC_Compact): - if (cmpt >= 0) - dupl++; - cmpt = i; + dup = n->data.Bl.comp; + comp = 1; break; case (MDOC_Width): - if (width >= 0) - dupl++; - width = i; + dup = (NULL != n->data.Bl.width); + width = n->args->argv[i].value[0]; break; case (MDOC_Offset): - if (offs >= 0) - dupl++; - offs = i; + /* NB: this can be empty! */ + if (n->args->argv[i].sz) { + offs = n->args->argv[i].value[0]; + dup = (NULL != n->data.Bl.offs); + break; + } + if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV)) + return(0); break; } /* Check: duplicate auxiliary arguments. */ - if (dupl) - if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP)) - return(0); + if (dup && ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP)) + return(0); + + if (comp && ! dup) + n->data.Bl.comp = comp; + if (offs && ! dup) + n->data.Bl.offs = offs; + if (width && ! dup) + n->data.Bl.width = width; /* Check: multiple list types. */ - if (LIST__NONE != lt && n->data.list != LIST__NONE) + if (LIST__NONE != lt && n->data.Bl.type != LIST__NONE) if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP)) return(0); /* Assign list type. */ - if (LIST__NONE != lt && n->data.list == LIST__NONE) - n->data.list = lt; + if (LIST__NONE != lt && n->data.Bl.type == LIST__NONE) + n->data.Bl.type = lt; /* The list type should come first. */ - if (n->data.list == LIST__NONE) - if (width >= 0 || offs >= 0 || cmpt >= 0) + if (n->data.Bl.type == LIST__NONE) + if (n->data.Bl.width || + n->data.Bl.offs || + n->data.Bl.comp) if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST)) return(0); @@ -638,10 +648,10 @@ pre_bl(PRE_ARGS) /* Allow lists to default to LIST_item. */ - if (LIST__NONE == n->data.list) { + if (LIST__NONE == n->data.Bl.type) { if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE)) return(0); - n->data.list = LIST_item; + n->data.Bl.type = LIST_item; } /* @@ -650,9 +660,9 @@ pre_bl(PRE_ARGS) * and must also be warned. */ - switch (n->data.list) { + switch (n->data.Bl.type) { case (LIST_tag): - if (width >= 0) + if (n->data.Bl.width) break; if (mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG)) break; @@ -666,7 +676,7 @@ pre_bl(PRE_ARGS) case (LIST_inset): /* FALLTHROUGH */ case (LIST_item): - if (width < 0) + if (NULL == n->data.Bl.width) break; if (mdoc_nmsg(mdoc, n, MANDOCERR_WIDTHARG)) break; @@ -682,43 +692,97 @@ pre_bl(PRE_ARGS) static int pre_bd(PRE_ARGS) { - int i, type, err; + int i, dup, comp; + enum mdoc_disp dt; + const char *offs; - if (MDOC_BLOCK != n->type) + if (MDOC_BLOCK != n->type) { + assert(n->parent); + assert(MDOC_BLOCK == n->parent->type); + assert(MDOC_Bd == n->parent->tok); + assert(DISP__NONE != n->parent->data.Bd.type); + memcpy(&n->data.Bd, &n->parent->data.Bd, + sizeof(struct mdoc_bd)); return(1); - if (NULL == n->args) { - mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE); - return(0); } - /* Make sure that only one type of display is specified. */ + assert(DISP__NONE == n->data.Bd.type); /* LINTED */ - for (i = 0, err = type = 0; ! err && - i < (int)n->args->argc; i++) + for (i = 0; n->args && i < (int)n->args->argc; i++) { + dt = DISP__NONE; + dup = comp = 0; + offs = NULL; + switch (n->args->argv[i].arg) { case (MDOC_Centred): - /* FALLTHROUGH */ + dt = DISP_centred; + break; case (MDOC_Ragged): - /* FALLTHROUGH */ + dt = DISP_ragged; + break; case (MDOC_Unfilled): - /* FALLTHROUGH */ + dt = DISP_unfilled; + break; case (MDOC_Filled): - /* FALLTHROUGH */ + dt = DISP_filled; + break; case (MDOC_Literal): - if (0 == type++) + dt = DISP_literal; + break; + case (MDOC_File): + mdoc_nmsg(mdoc, n, MANDOCERR_BADDISP); + return(0); + case (MDOC_Offset): + /* NB: this can be empty! */ + if (n->args->argv[i].sz) { + offs = n->args->argv[i].value[0]; + dup = (NULL != n->data.Bd.offs); break; - if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP)) + } + if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV)) return(0); break; - default: + case (MDOC_Compact): + comp = 1; + dup = n->data.Bd.comp; break; + default: + abort(); + /* NOTREACHED */ } - if (type) - return(1); - mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE); - return(0); + /* Check whether we have duplicates. */ + + if (dup && ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP)) + return(0); + + /* Make our auxiliary assignments. */ + + if (offs && ! dup) + n->data.Bd.offs = offs; + if (comp && ! dup) + n->data.Bd.comp = comp; + + /* Check whether a type has already been assigned. */ + + if (DISP__NONE != dt && n->data.Bd.type != DISP__NONE) + if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP)) + return(0); + + /* Make our type assignment. */ + + if (DISP__NONE != dt && n->data.Bd.type == DISP__NONE) + n->data.Bd.type = dt; + } + + if (DISP__NONE == n->data.Bd.type) { + if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE)) + return(0); + n->data.Bd.type = DISP_ragged; + } + + return(1); } @@ -976,7 +1040,7 @@ post_it(POST_ARGS) return(1); n = mdoc->last->parent->parent; - lt = n->data.list; + lt = n->data.Bl.type; if (LIST__NONE == lt) { mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE); @@ -1068,7 +1132,7 @@ post_bl_head(POST_ARGS) assert(mdoc->last->parent); n = mdoc->last->parent; - if (LIST_column == n->data.list) { + if (LIST_column == n->data.Bl.type) { for (i = 0; i < (int)n->args->argc; i++) if (MDOC_Column == n->args->argv[i].arg) break; diff --git a/usr.bin/mandoc/roff.7 b/usr.bin/mandoc/roff.7 index 65fca6dbb95..a2303dbad7d 100644 --- a/usr.bin/mandoc/roff.7 +++ b/usr.bin/mandoc/roff.7 @@ -1,4 +1,4 @@ -.\" $Id: roff.7,v 1.4 2010/06/06 20:30:08 schwarze Exp $ +.\" $Id: roff.7,v 1.5 2010/06/26 17:56:43 schwarze Exp $ .\" .\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 6 2010 $ +.Dd $Mdocdate: June 26 2010 $ .Dt ROFF 7 .Os .Sh NAME @@ -173,8 +173,19 @@ BODY... BODY .Ed .Pp -COND is a conditional (for the time being, this always evaluates to -false). +COND is a conditional statement. +roff allows for complicated conditionals; mandoc is much simpler. +At this time, mandoc supports only +.Sq n , +evaluating to true; +and +.Sq t , +.Sq e , +and +.Sq o , +evaluating to false. +All other invocations are read up to the next end of line or space and +evaluate as false. .Pp If the BODY section is begun by an escaped brace .Sq \e{ , diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 1169b559bad..b20c3a98d9d 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.4 2010/06/06 20:30:08 schwarze Exp $ */ +/* $Id: roff.c,v 1.5 2010/06/26 17:56:43 schwarze Exp $ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -103,6 +103,7 @@ static enum rofferr roff_ccond(ROFF_ARGS); static enum rofferr roff_cond(ROFF_ARGS); static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); +static enum roffrule roff_evalcond(const char *, int *); static enum rofferr roff_line(ROFF_ARGS); /* See roff_hash_find() */ @@ -621,11 +622,21 @@ roff_cond_sub(ROFF_ARGS) { enum rofft t; enum roffrule rr; + struct roffnode *l; ppos = pos; rr = r->last->rule; - roff_cond_text(r, tok, bufp, szp, ln, ppos, pos, offs); + /* + * Clean out scope. If we've closed ourselves, then don't + * continue. + */ + + l = r->last; + roffnode_cleanscope(r); + + if (l != r->last) + return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); if (ROFF_MAX == (t = roff_parse(*bufp, &pos))) return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); @@ -674,12 +685,37 @@ roff_cond_text(ROFF_ARGS) } +static enum roffrule +roff_evalcond(const char *v, int *pos) +{ + + switch (v[*pos]) { + case ('n'): + (*pos)++; + return(ROFFRULE_ALLOW); + case ('e'): + /* FALLTHROUGH */ + case ('o'): + /* FALLTHROUGH */ + case ('t'): + (*pos)++; + return(ROFFRULE_DENY); + default: + break; + } + + while (v[*pos] && ' ' != v[*pos]) + (*pos)++; + return(ROFFRULE_DENY); +} + + /* ARGSUSED */ static enum rofferr roff_cond(ROFF_ARGS) { - int cpos; /* position of the condition */ int sv; + enum roffrule rule; /* Stack overflow! */ @@ -688,20 +724,22 @@ roff_cond(ROFF_ARGS) return(ROFF_ERR); } - cpos = pos; + /* First, evaluate the conditional. */ - if (ROFF_if == tok || ROFF_ie == tok) { - /* - * Read ahead past the conditional. FIXME: this does - * not work, as conditionals don't end on whitespace, - * but are parsed according to a formal grammar. It's - * good enough for now, however. - */ - while ((*bufp)[pos] && ' ' != (*bufp)[pos]) - pos++; - } + if (ROFF_el == tok) { + /* + * An `.el' will get the value of the current rstack + * entry set in prior `ie' calls or defaults to DENY. + */ + if (r->rstackpos < 0) + rule = ROFFRULE_DENY; + else + rule = r->rstack[r->rstackpos]; + } else + rule = roff_evalcond(*bufp, &pos); sv = pos; + while (' ' == (*bufp)[pos]) pos++; @@ -711,30 +749,18 @@ roff_cond(ROFF_ARGS) * really doing anything. Warn about this. It's probably * wrong. */ + if ('\0' == (*bufp)[pos] && sv != pos) { - if ( ! (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL)) - return(ROFF_ERR); - return(ROFF_IGN); + if ((*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL)) + return(ROFF_IGN); + return(ROFF_ERR); } if ( ! roffnode_push(r, tok, ln, ppos)) return(ROFF_ERR); - /* XXX: Implement more conditionals. */ + r->last->rule = rule; - if (ROFF_if == tok || ROFF_ie == tok) - r->last->rule = 'n' == (*bufp)[cpos] ? - ROFFRULE_ALLOW : ROFFRULE_DENY; - else if (ROFF_el == tok) { - /* - * An `.el' will get the value of the current rstack - * entry set in prior `ie' calls or defaults to DENY. - */ - if (r->rstackpos < 0) - r->last->rule = ROFFRULE_DENY; - else - r->last->rule = r->rstack[r->rstackpos]; - } if (ROFF_ie == tok) { /* * An if-else will put the NEGATION of the current @@ -746,9 +772,18 @@ roff_cond(ROFF_ARGS) else r->rstack[r->rstackpos] = ROFFRULE_DENY; } + + /* If the parent has false as its rule, then so do we. */ + if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) r->last->rule = ROFFRULE_DENY; + /* + * Determine scope. If we're invoked with "\{" trailing the + * conditional, then we're in a multiline scope. Else our scope + * expires on the next line. + */ + r->last->endspan = 1; if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) { diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index cc3d22722c8..7a465e8a744 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -1,6 +1,6 @@ -/* $Id: term.c,v 1.37 2010/06/10 22:50:10 schwarze Exp $ */ +/* $Id: term.c,v 1.38 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -599,10 +599,7 @@ encode(struct termp *p, const char *word, size_t sz) * character by character. */ - if (TERMTYPE_PS == p->type) { - buffera(p, word, sz); - return; - } else if (TERMFONT_NONE == (f = term_fonttop(p))) { + if (TERMFONT_NONE == (f = term_fonttop(p))) { buffera(p, word, sz); return; } diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index 1183164a78c..5b4aa3b4a58 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -1,6 +1,6 @@ -/* $Id: term.h,v 1.20 2010/06/10 22:50:10 schwarze Exp $ */ +/* $Id: term.h,v 1.21 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -50,6 +50,8 @@ struct termp_ps { size_t psmargsz; /* margin buf size */ size_t psmargcur; /* current pos in margin buf */ size_t pspage; /* current page */ + char last; /* character buffer */ + enum termfont lastf; /* last set font */ }; struct termp { diff --git a/usr.bin/mandoc/term_ps.c b/usr.bin/mandoc/term_ps.c index 8d887c74d4a..e5b4710eb3b 100644 --- a/usr.bin/mandoc/term_ps.c +++ b/usr.bin/mandoc/term_ps.c @@ -1,6 +1,6 @@ -/* $Id: term_ps.c,v 1.1 2010/06/10 22:50:10 schwarze Exp $ */ +/* $Id: term_ps.c,v 1.2 2010/06/26 17:56:43 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> + * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -53,13 +53,18 @@ } \ } while (/* CONSTCOND */ 0) + static void ps_letter(struct termp *, char); static void ps_begin(struct termp *); static void ps_end(struct termp *); static void ps_advance(struct termp *, size_t); static void ps_endline(struct termp *); +static void ps_fclose(struct termp *); +static void ps_pclose(struct termp *); +static void ps_pletter(struct termp *, char); static void ps_printf(struct termp *, const char *, ...); static void ps_putchar(struct termp *, char); +static void ps_setfont(struct termp *, enum termfont); void * @@ -161,6 +166,8 @@ ps_end(struct termp *p) * well as just one. */ + assert(0 == p->engine.ps.psstate); + assert('\0' == p->engine.ps.last); assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]); printf("%s", p->engine.ps.psmarg); printf("showpage\n"); @@ -172,68 +179,60 @@ static void ps_begin(struct termp *p) { - /* - * Emit the standard PostScript prologue, set our initial page - * position, then run pageopen() on the initial page. + /* + * Print margins into margin buffer. Nothing gets output to the + * screen yet, so we don't need to initialise the primary state. */ - printf("%s\n", "%!PS"); - printf("%s\n", "/Courier"); - printf("%s\n", "10 selectfont"); - - p->engine.ps.psstate = 0; - if (p->engine.ps.psmarg) { assert(p->engine.ps.psmargsz); p->engine.ps.psmarg[0] = '\0'; } p->engine.ps.psmargcur = 0; - - /* - * Now dump the margins into our margin buffer. If we don't do - * this, we'd break any current state to run the header and - * footer with each and evern new page. - */ - + p->engine.ps.psstate = PS_MARGINS; p->engine.ps.pscol = PS_CHAR_LEFT; p->engine.ps.psrow = PS_CHAR_TOPMARG; - p->engine.ps.psstate |= PS_MARGINS; + ps_setfont(p, TERMFONT_NONE); (*p->headf)(p, p->argf); (*p->endline)(p); - p->engine.ps.psstate &= ~PS_MARGINS; - assert(0 == p->engine.ps.psstate); - p->engine.ps.pscol = PS_CHAR_LEFT; p->engine.ps.psrow = PS_CHAR_BOTMARG; - p->engine.ps.psstate |= PS_MARGINS; (*p->footf)(p, p->argf); (*p->endline)(p); p->engine.ps.psstate &= ~PS_MARGINS; + assert(0 == p->engine.ps.psstate); + assert(p->engine.ps.psmarg); + assert('\0' != p->engine.ps.psmarg[0]); + /* + * Print header and initialise page state. Following this, + * stuff gets printed to the screen, so make sure we're sane. + */ + + printf("%s\n", "%!PS"); + ps_setfont(p, TERMFONT_NONE); p->engine.ps.pscol = PS_CHAR_LEFT; p->engine.ps.psrow = PS_CHAR_TOP; - - assert(p->engine.ps.psmarg); - assert('\0' != p->engine.ps.psmarg[0]); } static void -ps_letter(struct termp *p, char c) +ps_pletter(struct termp *p, char c) { + /* + * If we're not in a PostScript "word" context, then open one + * now at the current cursor. + */ + if ( ! (PS_INLINE & p->engine.ps.psstate)) { - /* - * If we're not in a PostScript "word" context, then - * open one now at the current cursor. - */ ps_printf(p, "%zu %zu moveto\n(", p->engine.ps.pscol, p->engine.ps.psrow); @@ -260,21 +259,118 @@ ps_letter(struct termp *p, char c) } /* Write the character and adjust where we are on the page. */ + ps_putchar(p, c); p->engine.ps.pscol += PS_CHAR_WIDTH; } static void -ps_advance(struct termp *p, size_t len) +ps_pclose(struct termp *p) { - if (PS_INLINE & p->engine.ps.psstate) { - /* Dump out any existing line scope. */ - ps_printf(p, ") show\n"); - p->engine.ps.psstate &= ~PS_INLINE; + /* + * Spit out that we're exiting a word context (this is a + * "partial close" because we don't check the last-char buffer + * or anything). + */ + + if ( ! (PS_INLINE & p->engine.ps.psstate)) + return; + + ps_printf(p, ") show\n"); + p->engine.ps.psstate &= ~PS_INLINE; +} + + +static void +ps_fclose(struct termp *p) +{ + + /* + * Strong closure: if we have a last-char, spit it out after + * checking that we're in the right font mode. This will of + * course open a new scope, if applicable. + * + * Following this, close out any scope that's open. + */ + + if ('\0' != p->engine.ps.last) { + if (p->engine.ps.lastf != TERMFONT_NONE) { + ps_pclose(p); + ps_setfont(p, TERMFONT_NONE); + } + ps_pletter(p, p->engine.ps.last); + p->engine.ps.last = '\0'; } + if ( ! (PS_INLINE & p->engine.ps.psstate)) + return; + + ps_pclose(p); +} + + +static void +ps_letter(struct termp *p, char c) +{ + char cc; + + /* + * State machine dictates whether to buffer the last character + * or not. Basically, encoded words are detected by checking if + * we're an "8" and switching on the buffer. Then we put "8" in + * our buffer, and on the next charater, flush both character + * and buffer. Thus, "regular" words are detected by having a + * regular character and a regular buffer character. + */ + + if ('\0' == p->engine.ps.last) { + assert(8 != c); + p->engine.ps.last = c; + return; + } else if (8 == p->engine.ps.last) { + assert(8 != c); + p->engine.ps.last = '\0'; + } else if (8 == c) { + assert(8 != p->engine.ps.last); + if ('_' == p->engine.ps.last) { + if (p->engine.ps.lastf != TERMFONT_UNDER) { + ps_pclose(p); + ps_setfont(p, TERMFONT_UNDER); + } + } else if (p->engine.ps.lastf != TERMFONT_BOLD) { + ps_pclose(p); + ps_setfont(p, TERMFONT_BOLD); + } + p->engine.ps.last = c; + return; + } else { + if (p->engine.ps.lastf != TERMFONT_NONE) { + ps_pclose(p); + ps_setfont(p, TERMFONT_NONE); + } + cc = p->engine.ps.last; + p->engine.ps.last = c; + c = cc; + } + + ps_pletter(p, c); +} + + +static void +ps_advance(struct termp *p, size_t len) +{ + + /* + * Advance some spaces. This can probably be made smarter, + * i.e., to have multiple space-separated words in the same + * scope, but this is easier: just close out the current scope + * and readjust our column settings. + */ + + ps_fclose(p); p->engine.ps.pscol += len ? len * PS_CHAR_WIDTH : 0; } @@ -283,14 +379,24 @@ static void ps_endline(struct termp *p) { - if (PS_INLINE & p->engine.ps.psstate) { - ps_printf(p, ") show\n"); - p->engine.ps.psstate &= ~PS_INLINE; - } + /* Close out any scopes we have open: we're at eoln. */ + + ps_fclose(p); + + /* + * If we're in the margin, don't try to recalculate our current + * row. XXX: if the column tries to be fancy with multiple + * lines, we'll do nasty stuff. + */ if (PS_MARGINS & p->engine.ps.psstate) return; + /* + * Put us down a line. If we're at the page bottom, spit out a + * showpage and restart our row. + */ + p->engine.ps.pscol = PS_CHAR_LEFT; if (p->engine.ps.psrow >= PS_CHAR_HEIGHT + PS_CHAR_BOT) { p->engine.ps.psrow -= PS_CHAR_HEIGHT; @@ -302,3 +408,20 @@ ps_endline(struct termp *p) printf("showpage\n"); p->engine.ps.psrow = PS_CHAR_TOP; } + + +static void +ps_setfont(struct termp *p, enum termfont f) +{ + + if (TERMFONT_BOLD == f) + ps_printf(p, "/Courier-Bold\n"); + else if (TERMFONT_UNDER == f) + ps_printf(p, "/Courier-Oblique\n"); + else + ps_printf(p, "/Courier\n"); + + ps_printf(p, "10 selectfont\n"); + p->engine.ps.lastf = f; +} + |