Return to mdoc_validate.c CVS log | Up to [cvsweb.bsd.lv] / mandoc |
version 1.104, 2010/07/01 22:56:17 | version 1.111, 2010/07/19 11:11:54 | ||
---|---|---|---|
|
|
||
/* $Id$ */ | /* $Id$ */ | ||
/* | /* | ||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> | * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> | ||
* | * | ||
* Permission to use, copy, modify, and distribute this software for any | * Permission to use, copy, modify, and distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | * purpose with or without fee is hereby granted, provided that the above | ||
|
|
||
#include "libmandoc.h" | #include "libmandoc.h" | ||
/* FIXME: .Bl -diag can't have non-text children in HEAD. */ | /* FIXME: .Bl -diag can't have non-text children in HEAD. */ | ||
/* TODO: ignoring Pp (it's superfluous in some invocations). */ | |||
#define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n | #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n | ||
#define POST_ARGS struct mdoc *mdoc | #define POST_ARGS struct mdoc *mdoc | ||
|
|
||
/* Assign list type. */ | /* Assign list type. */ | ||
if (LIST__NONE != lt && n->data.Bl->type == LIST__NONE) | if (LIST__NONE != lt && n->data.Bl->type == LIST__NONE) { | ||
n->data.Bl->type = lt; | n->data.Bl->type = lt; | ||
/* Set column information, too. */ | |||
if (LIST_column == lt) { | |||
n->data.Bl->ncols = | |||
n->args->argv[i].sz; | |||
n->data.Bl->cols = (const char **) | |||
n->args->argv[i].value; | |||
} | |||
} | |||
/* The list type should come first. */ | /* The list type should come first. */ | ||
|
|
||
pre_an(PRE_ARGS) | pre_an(PRE_ARGS) | ||
{ | { | ||
if (NULL == n->args || 1 == n->args->argc) | if (NULL == n->args) | ||
return(1); | return(1); | ||
mdoc_vmsg(mdoc, MANDOCERR_SYNTARGCOUNT, | if (n->args->argc > 1) | ||
n->line, n->pos, | if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGCOUNT)) | ||
"line arguments == 1 (have %d)", | return(0); | ||
n->args->argc); | |||
return(0); | if (MDOC_Split == n->args->argv[0].arg) | ||
n->data.An.auth = AUTH_split; | |||
else if (MDOC_Nosplit == n->args->argv[0].arg) | |||
n->data.An.auth = AUTH_nosplit; | |||
else | |||
abort(); | |||
return(1); | |||
} | } | ||
|
|
||
static int | static int | ||
post_bf(POST_ARGS) | post_bf(POST_ARGS) | ||
{ | { | ||
char *p; | struct mdoc_node *np; | ||
struct mdoc_node *head; | int arg; | ||
if (MDOC_BLOCK != mdoc->last->type) | /* | ||
return(1); | * Unlike other data pointers, these are "housed" by the HEAD | ||
* element, which contains the goods. | |||
*/ | |||
head = mdoc->last->head; | if (MDOC_HEAD != mdoc->last->type) { | ||
if (ENDBODY_NOT != mdoc->last->end) { | |||
assert(mdoc->last->pending); | |||
np = mdoc->last->pending->parent->head; | |||
} else if (MDOC_BLOCK != mdoc->last->type) { | |||
np = mdoc->last->parent->head; | |||
} else | |||
np = mdoc->last->head; | |||
if (mdoc->last->args && head->child) { | assert(np); | ||
/* FIXME: this should provide a default. */ | assert(MDOC_HEAD == np->type); | ||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SYNTARGVCOUNT); | assert(MDOC_Bf == np->tok); | ||
return(0); | assert(np->data.Bf); | ||
} else if (mdoc->last->args) | mdoc->last->data.Bf = np->data.Bf; | ||
return(1); | return(1); | ||
} | |||
if (NULL == head->child || MDOC_TEXT != head->child->type) { | np = mdoc->last; | ||
/* FIXME: this should provide a default. */ | assert(MDOC_BLOCK == np->parent->type); | ||
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SYNTARGVCOUNT); | assert(MDOC_Bf == np->parent->tok); | ||
np->data.Bf = mandoc_calloc(1, sizeof(struct mdoc_bf)); | |||
/* | |||
* Cannot have both argument and parameter. | |||
* If neither is specified, let it through with a warning. | |||
*/ | |||
if (np->parent->args && np->child) { | |||
mdoc_nmsg(mdoc, np, MANDOCERR_SYNTARGVCOUNT); | |||
return(0); | return(0); | ||
} else if (NULL == np->parent->args && NULL == np->child) | |||
return(mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE)); | |||
/* Extract argument into data. */ | |||
if (np->parent->args) { | |||
arg = np->parent->args->argv[0].arg; | |||
if (MDOC_Emphasis == arg) | |||
np->data.Bf->font = FONT_Em; | |||
else if (MDOC_Literal == arg) | |||
np->data.Bf->font = FONT_Li; | |||
else if (MDOC_Symbolic == arg) | |||
np->data.Bf->font = FONT_Sy; | |||
else | |||
abort(); | |||
return(1); | |||
} | } | ||
p = head->child->string; | /* Extract parameter into data. */ | ||
if (0 == strcmp(p, "Em")) | if (0 == strcmp(np->child->string, "Em")) | ||
return(1); | np->data.Bf->font = FONT_Em; | ||
else if (0 == strcmp(p, "Li")) | else if (0 == strcmp(np->child->string, "Li")) | ||
return(1); | np->data.Bf->font = FONT_Li; | ||
else if (0 == strcmp(p, "Sy")) | else if (0 == strcmp(np->child->string, "Sy")) | ||
return(1); | np->data.Bf->font = FONT_Sy; | ||
else if ( ! mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE)) | |||
return(0); | |||
mdoc_nmsg(mdoc, head, MANDOCERR_FONTTYPE); | return(1); | ||
return(0); | |||
} | } | ||
|
|
||
static int | static int | ||
post_an(POST_ARGS) | post_an(POST_ARGS) | ||
{ | { | ||
struct mdoc_node *np; | |||
if (mdoc->last->args) { | np = mdoc->last; | ||
if (NULL == mdoc->last->child) | if (AUTH__NONE != np->data.An.auth && np->child) | ||
return(1); | return(mdoc_nmsg(mdoc, np, MANDOCERR_ARGCOUNT)); | ||
return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGCOUNT)); | if (AUTH__NONE != np->data.An.auth || np->child) | ||
} | |||
if (mdoc->last->child) | |||
return(1); | return(1); | ||
return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS)); | return(mdoc_nmsg(mdoc, np, MANDOCERR_NOARGS)); | ||
} | } | ||
|
|
||
if (NULL == mdoc->last->head->child) | if (NULL == mdoc->last->head->child) | ||
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS)) | if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS)) | ||
return(0); | return(0); | ||
if (NULL == mdoc->last->body->child) | |||
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY)) | |||
return(0); | |||
break; | break; | ||
case (LIST_bullet): | case (LIST_bullet): | ||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||
|
|
||
case (LIST_enum): | case (LIST_enum): | ||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||
case (LIST_hyphen): | case (LIST_hyphen): | ||
if (NULL == mdoc->last->body->child) | |||
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY)) | |||
return(0); | |||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||
case (LIST_item): | case (LIST_item): | ||
if (mdoc->last->head->child) | if (mdoc->last->head->child) | ||
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST)) | if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST)) | ||
return(0); | return(0); | ||
if (NULL == mdoc->last->body->child) | |||
if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY)) | |||
return(0); | |||
break; | break; | ||
case (LIST_column): | case (LIST_column): | ||
cols = -1; | cols = (int)n->data.Bl->ncols; | ||
for (i = 0; i < (int)n->args->argc; i++) | |||
if (MDOC_Column == n->args->argv[i].arg) { | |||
cols = (int)n->args->argv[i].sz; | |||
break; | |||
} | |||
assert(-1 != cols); | |||
assert(NULL == mdoc->last->head->child); | assert(NULL == mdoc->last->head->child); | ||
if (NULL == mdoc->last->body->child) | if (NULL == mdoc->last->body->child) | ||
|
|
||
n = mdoc->last->parent; | n = mdoc->last->parent; | ||
if (LIST_column == n->data.Bl->type) { | if (LIST_column == n->data.Bl->type) { | ||
for (i = 0; i < (int)n->args->argc; i++) | if (n->data.Bl->ncols && mdoc->last->nchild) { | ||
if (MDOC_Column == n->args->argv[i].arg) | |||
break; | |||
assert(i < (int)n->args->argc); | |||
if (n->args->argv[i].sz && mdoc->last->nchild) { | |||
mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS); | mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS); | ||
return(0); | return(0); | ||
} | } |