[BACK]Return to mdoc_state.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

File: [cvsweb.bsd.lv] / mandoc / mdoc_state.c (download)

Revision 1.16, Sun Jan 19 18:02:00 2020 UTC (4 years, 3 months ago) by schwarze
Branch: MAIN
Changes since 1.15: +2 -1 lines

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term.  Please only use it when automatic tagging does
not work.  Manual page authors will not be required to add the new
macro; using it remains optional.  HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful.  Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.

/*	$Id: mdoc_state.c,v 1.16 2020/01/19 18:02:00 schwarze Exp $ */
/*
 * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <sys/types.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "libmandoc.h"
#include "roff_int.h"
#include "libmdoc.h"

#define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n

typedef	void	(*state_handler)(STATE_ARGS);

static	void	 state_bl(STATE_ARGS);
static	void	 state_sh(STATE_ARGS);
static	void	 state_sm(STATE_ARGS);

static	const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
	NULL,		/* Dd */
	NULL,		/* Dt */
	NULL,		/* Os */
	state_sh,	/* Sh */
	NULL,		/* Ss */
	NULL,		/* Pp */
	NULL,		/* D1 */
	NULL,		/* Dl */
	NULL,		/* Bd */
	NULL,		/* Ed */
	state_bl,	/* Bl */
	NULL,		/* El */
	NULL,		/* It */
	NULL,		/* Ad */
	NULL,		/* An */
	NULL,		/* Ap */
	NULL,		/* Ar */
	NULL,		/* Cd */
	NULL,		/* Cm */
	NULL,		/* Dv */
	NULL,		/* Er */
	NULL,		/* Ev */
	NULL,		/* Ex */
	NULL,		/* Fa */
	NULL,		/* Fd */
	NULL,		/* Fl */
	NULL,		/* Fn */
	NULL,		/* Ft */
	NULL,		/* Ic */
	NULL,		/* In */
	NULL,		/* Li */
	NULL,		/* Nd */
	NULL,		/* Nm */
	NULL,		/* Op */
	NULL,		/* Ot */
	NULL,		/* Pa */
	NULL,		/* Rv */
	NULL,		/* St */
	NULL,		/* Va */
	NULL,		/* Vt */
	NULL,		/* Xr */
	NULL,		/* %A */
	NULL,		/* %B */
	NULL,		/* %D */
	NULL,		/* %I */
	NULL,		/* %J */
	NULL,		/* %N */
	NULL,		/* %O */
	NULL,		/* %P */
	NULL,		/* %R */
	NULL,		/* %T */
	NULL,		/* %V */
	NULL,		/* Ac */
	NULL,		/* Ao */
	NULL,		/* Aq */
	NULL,		/* At */
	NULL,		/* Bc */
	NULL,		/* Bf */
	NULL,		/* Bo */
	NULL,		/* Bq */
	NULL,		/* Bsx */
	NULL,		/* Bx */
	NULL,		/* Db */
	NULL,		/* Dc */
	NULL,		/* Do */
	NULL,		/* Dq */
	NULL,		/* Ec */
	NULL,		/* Ef */
	NULL,		/* Em */
	NULL,		/* Eo */
	NULL,		/* Fx */
	NULL,		/* Ms */
	NULL,		/* No */
	NULL,		/* Ns */
	NULL,		/* Nx */
	NULL,		/* Ox */
	NULL,		/* Pc */
	NULL,		/* Pf */
	NULL,		/* Po */
	NULL,		/* Pq */
	NULL,		/* Qc */
	NULL,		/* Ql */
	NULL,		/* Qo */
	NULL,		/* Qq */
	NULL,		/* Re */
	NULL,		/* Rs */
	NULL,		/* Sc */
	NULL,		/* So */
	NULL,		/* Sq */
	state_sm,	/* Sm */
	NULL,		/* Sx */
	NULL,		/* Sy */
	NULL,		/* Tn */
	NULL,		/* Ux */
	NULL,		/* Xc */
	NULL,		/* Xo */
	NULL,		/* Fo */
	NULL,		/* Fc */
	NULL,		/* Oo */
	NULL,		/* Oc */
	NULL,		/* Bk */
	NULL,		/* Ek */
	NULL,		/* Bt */
	NULL,		/* Hf */
	NULL,		/* Fr */
	NULL,		/* Ud */
	NULL,		/* Lb */
	NULL,		/* Lp */
	NULL,		/* Lk */
	NULL,		/* Mt */
	NULL,		/* Brq */
	NULL,		/* Bro */
	NULL,		/* Brc */
	NULL,		/* %C */
	NULL,		/* Es */
	NULL,		/* En */
	NULL,		/* Dx */
	NULL,		/* %Q */
	NULL,		/* %U */
	NULL,		/* Ta */
	NULL,		/* Tg */
};


void
mdoc_state(struct roff_man *mdoc, struct roff_node *n)
{
	state_handler handler;

	if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
		return;

	assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
	if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
		mdoc->flags |= MDOC_PBODY;

	handler = state_handlers[n->tok - MDOC_Dd];
	if (*handler)
		(*handler)(mdoc, n);
}

static void
state_bl(STATE_ARGS)
{
	struct mdoc_arg	*args;
	size_t		 i;

	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
		return;

	args = n->parent->args;
	for (i = 0; i < args->argc; i++) {
		switch(args->argv[i].arg) {
		case MDOC_Diag:
			n->norm->Bl.type = LIST_diag;
			return;
		case MDOC_Column:
			n->norm->Bl.type = LIST_column;
			return;
		default:
			break;
		}
	}
}

static void
state_sh(STATE_ARGS)
{
	struct roff_node *nch;
	char		 *secname;

	if (n->type != ROFFT_HEAD)
		return;

	if ( ! (n->flags & NODE_VALID)) {
		secname = NULL;
		deroff(&secname, n);

		/*
		 * Set the section attribute for the BLOCK, HEAD,
		 * and HEAD children; the latter can only be TEXT
		 * nodes, so no recursion is needed.  For other
		 * nodes, including the .Sh BODY, this is done
		 * when allocating the node data structures, but
		 * for .Sh BLOCK and HEAD, the section is still
		 * unknown at that time.
		 */

		n->sec = n->parent->sec = secname == NULL ?
		    SEC_CUSTOM : mdoc_a2sec(secname);
		for (nch = n->child; nch != NULL; nch = nch->next)
			nch->sec = n->sec;
		free(secname);
	}

	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
		roff_setreg(mdoc->roff, "nS", 1, '=');
		mdoc->flags |= MDOC_SYNOPSIS;
	} else {
		roff_setreg(mdoc->roff, "nS", 0, '=');
		mdoc->flags &= ~MDOC_SYNOPSIS;
	}
}

static void
state_sm(STATE_ARGS)
{

	if (n->child == NULL)
		mdoc->flags ^= MDOC_SMOFF;
	else if ( ! strcmp(n->child->string, "on"))
		mdoc->flags &= ~MDOC_SMOFF;
	else if ( ! strcmp(n->child->string, "off"))
		mdoc->flags |= MDOC_SMOFF;
}