man_macro.c revision 698f87a48e2e945bfe5493ce168e0d0ae1cedd5c
/* $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "man.h"
#include "mandoc.h"
#include "libmandoc.h"
#include "libman.h"
enum rew {
};
static int blk_close(MACRO_PROT_ARGS);
static int blk_exp(MACRO_PROT_ARGS);
static int blk_imp(MACRO_PROT_ARGS);
static int in_line_eoln(MACRO_PROT_ARGS);
int *, char *, char **);
const struct man_node *);
const struct man_node *);
{ in_line_eoln, 0 }, /* BI */
{ in_line_eoln, 0 }, /* IB */
{ in_line_eoln, 0 }, /* BR */
{ in_line_eoln, 0 }, /* RB */
{ in_line_eoln, 0 }, /* IR */
{ in_line_eoln, 0 }, /* RI */
{ blk_close, 0 }, /* RE */
{ in_line_eoln, 0 }, /* DT */
{ in_line_eoln, 0 }, /* UC */
{ in_line_eoln, 0 }, /* PD */
{ in_line_eoln, 0 }, /* AT */
{ in_line_eoln, 0 }, /* in */
{ in_line_eoln, 0 }, /* ft */
{ in_line_eoln, 0 }, /* OP */
{ blk_close, 0 }, /* UE */
};
/*
* Warn when "n" is an explicit non-roff macro.
*/
static void
{
return;
return;
return;
}
/*
* Rewind scope. If a code "er" != MANDOCERR_MAX has been provided, it
* will be used if an explicit block scope is being closed out.
*/
int
{
struct man_node *n;
/* LINTED */
/*
* Save the parent here, because we may delete the
* man->last node in the post-validation phase and reset
* it to man->last->parent, causing a step in the closing
* out to be lost.
*/
if ( ! man_valid_post(man))
return(0);
}
if ( ! man_valid_post(man))
return(0);
return(1);
}
static enum rew
{
return(REW_REWIND);
}
/*
* There are three scope levels: scoped to the root (all), scoped to the
* section (all less sections), and scoped to subsections (all less
* sections and subsections).
*/
static enum rew
{
enum rew c;
/* We cannot progress beyond the root ever. */
return(REW_HALT);
/* Normal nodes shouldn't go to the level of the root. */
return(REW_REWIND);
/* Already-validated nodes should be closed out. */
return(REW_NOHALT);
/* First: rewind to ourselves. */
return(REW_HALT);
else
return(REW_REWIND);
}
/*
* Next follow the implicit scope-smashings as defined by man.7:
* section, sub-section, etc.
*/
switch (tok) {
case (MAN_SH):
break;
case (MAN_SS):
/* Rewind to a section, if a block. */
return(c);
break;
case (MAN_RS):
/* Preserve empty paragraphs before RS. */
return(REW_HALT);
/* Rewind to a subsection, if a block. */
return(c);
/* Rewind to a section, if a block. */
return(c);
break;
default:
/* Rewind to an offsetter, if a block. */
return(c);
/* Rewind to a subsection, if a block. */
return(c);
/* Rewind to a section, if a block. */
return(c);
break;
}
return(REW_NOHALT);
}
/*
* 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 int
{
struct man_node *n;
enum rew c;
/* LINTED */
/*
* Whether we should stop immediately (REW_HALT), stop
* and rewind until this point (REW_REWIND), or keep
* rewinding (REW_NOHALT).
*/
if (REW_HALT == c)
return(1);
if (REW_REWIND == c)
break;
}
/*
* Rewind until the current point. Warn if we're a roff
* instruction that's mowing over explicit scopes.
*/
assert(n);
}
/*
* Close out a generic explicit macro.
*/
/* ARGSUSED */
int
{
switch (tok) {
case (MAN_RE):
break;
case (MAN_UE):
break;
default:
abort();
/* NOTREACHED */
}
break;
return(0);
} else
return(1);
}
/* ARGSUSED */
int
{
struct man_node *n;
int la;
char *p;
/* Close out prior implicit scopes. */
return(0);
return(0);
return(0);
for (;;) {
break;
return(0);
}
continue;
break;
}
}
/*
* Parse an implicit-block macro. These contain a MAN_HEAD and a
* MAN_BODY contained within a MAN_BLOCK. Rules for closing out other
* scopes, such as `SH' closing out an `SS', are defined in the rew
* routines.
*/
/* ARGSUSED */
int
{
int la;
char *p;
struct man_node *n;
/* Close out prior scopes. */
return(0);
return(0);
/* Allocate new block & head scope. */
return(0);
return(0);
/* Add line arguments. */
for (;;) {
break;
return(0);
}
/* Close out head and open body (unless MAN_SCOPE). */
/* If we're forcing scope (`TP'), keep it open. */
return(1);
return(1);
}
}
return(0);
}
/* ARGSUSED */
int
{
int la;
char *p;
struct man_node *n;
return(0);
for (;;) {
break;
return(0);
}
/*
* Append MAN_EOS in case the last snipped argument
* ends with a dot, e.g. `.IR syslog (3).'
*/
/*
* 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.
*/
return(1);
}
/* Set ignorable context, if applicable. */
}
/*
* Rewind our element scope. Note that when TH is pruned, we'll
* be back at the root, so make sure that we don't clobber as
* its sibling.
*/
break;
break;
if ( ! man_valid_post(man))
return(0);
}
/*
* Same here regarding whether we're back at the root.
*/
return(0);
return(1);
}
int
{
}
static int
{
char *start;
if ('\0' == *start)
return(0);
return(1);
}