version 1.5, 2011/01/02 10:10:57 |
version 1.13, 2014/04/20 16:46:05 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2009, 2010, 2011 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 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
*/ |
*/ |
|
#ifdef HAVE_CONFIG_H |
|
#include "config.h" |
|
#endif |
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "mandoc.h" |
#include "mandoc.h" |
|
#include "libmandoc.h" |
#include "libroff.h" |
#include "libroff.h" |
|
|
enum tbl_ident { |
enum tbl_ident { |
Line 57 struct tbl_phrase { |
|
Line 62 struct tbl_phrase { |
|
static const struct tbl_phrase keys[KEY_MAXKEYS] = { |
static const struct tbl_phrase keys[KEY_MAXKEYS] = { |
{ "center", TBL_OPT_CENTRE, KEY_CENTRE}, |
{ "center", TBL_OPT_CENTRE, KEY_CENTRE}, |
{ "centre", TBL_OPT_CENTRE, KEY_CENTRE}, |
{ "centre", TBL_OPT_CENTRE, KEY_CENTRE}, |
{ "delim", 0, KEY_DELIM}, |
{ "delim", 0, KEY_DELIM}, |
{ "expand", TBL_OPT_EXPAND, KEY_EXPAND}, |
{ "expand", TBL_OPT_EXPAND, KEY_EXPAND}, |
{ "box", TBL_OPT_BOX, KEY_BOX}, |
{ "box", TBL_OPT_BOX, KEY_BOX}, |
{ "doublebox", TBL_OPT_DBOX, KEY_DBOX}, |
{ "doublebox", TBL_OPT_DBOX, KEY_DBOX}, |
{ "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX}, |
{ "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX}, |
{ "frame", TBL_OPT_BOX, KEY_FRAME}, |
{ "frame", TBL_OPT_BOX, KEY_FRAME}, |
{ "doubleframe", TBL_OPT_DBOX, KEY_DFRAME}, |
{ "doubleframe", TBL_OPT_DBOX, KEY_DFRAME}, |
Line 71 static const struct tbl_phrase keys[KEY_MAXKEYS] = { |
|
Line 76 static const struct tbl_phrase keys[KEY_MAXKEYS] = { |
|
{ "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE}, |
{ "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE}, |
}; |
}; |
|
|
static int arg(struct tbl_node *, int, |
static int arg(struct tbl_node *, int, |
const char *, int *, int); |
const char *, int *, enum tbl_ident); |
static void opt(struct tbl_node *, int, |
static void opt(struct tbl_node *, int, |
const char *, int *); |
const char *, int *); |
|
|
|
|
static int |
static int |
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key) |
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key) |
{ |
{ |
int i; |
int i; |
char buf[KEY_MAXNUMSZ]; |
char buf[KEY_MAXNUMSZ]; |
Line 88 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
Line 94 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
/* Arguments always begin with a parenthesis. */ |
/* Arguments always begin with a parenthesis. */ |
|
|
if ('(' != p[*pos]) { |
if ('(' != p[*pos]) { |
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, |
|
ln, *pos, NULL); |
return(0); |
return(0); |
} |
} |
|
|
Line 101 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
Line 108 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
*/ |
*/ |
|
|
switch (key) { |
switch (key) { |
case (KEY_DELIM): |
case KEY_DELIM: |
if ('\0' == (tbl->opts.delims[0] = p[(*pos)++])) { |
if ('\0' == p[(*pos)++]) { |
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, |
|
ln, *pos - 1, NULL); |
return(0); |
return(0); |
} |
} |
|
|
if ('\0' == (tbl->opts.delims[1] = p[(*pos)++])) { |
if ('\0' == p[(*pos)++]) { |
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, |
|
ln, *pos - 1, NULL); |
return(0); |
return(0); |
} |
} |
break; |
break; |
case (KEY_TAB): |
case KEY_TAB: |
if ('\0' != (tbl->opts.tab = p[(*pos)++])) |
if ('\0' != (tbl->opts.tab = p[(*pos)++])) |
break; |
break; |
|
|
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, |
|
ln, *pos - 1, NULL); |
return(0); |
return(0); |
case (KEY_LINESIZE): |
case KEY_LINESIZE: |
for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) { |
for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) { |
buf[i] = p[*pos]; |
buf[i] = p[*pos]; |
if ( ! isdigit((unsigned char)buf[i])) |
if ( ! isdigit((unsigned char)buf[i])) |
Line 131 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
Line 141 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
break; |
break; |
} |
} |
|
|
(*tbl->msg)(MANDOCERR_TBL, tbl->data, ln, *pos, NULL); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL); |
return(0); |
return(0); |
case (KEY_DPOINT): |
case KEY_DPOINT: |
if ('\0' != (tbl->opts.decimal = p[(*pos)++])) |
if ('\0' != (tbl->opts.decimal = p[(*pos)++])) |
break; |
break; |
|
|
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, |
|
ln, *pos - 1, NULL); |
return(0); |
return(0); |
default: |
default: |
abort(); |
abort(); |
Line 149 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
Line 160 arg(struct tbl_node *tbl, int ln, const char *p, int * |
|
if (')' == p[(*pos)++]) |
if (')' == p[(*pos)++]) |
return(1); |
return(1); |
|
|
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos - 1, NULL); |
return(0); |
return(0); |
} |
} |
|
|
|
|
* options ::= option_list [:space:]* [;][\n] |
* options ::= option_list [:space:]* [;][\n] |
* option_list ::= option option_tail |
* option_list ::= option option_tail |
* option_tail ::= [:space:]+ option_list | |
* option_tail ::= [:space:]+ option_list | |
* ::= epsilon |
* ::= epsilon |
* option ::= [:alpha:]+ args |
* option ::= [:alpha:]+ args |
* args ::= [:space:]* [(] [:alpha:]+ [)] |
* args ::= [:space:]* [(] [:alpha:]+ [)] |
*/ |
*/ |
|
|
/* Copy up to first non-alpha character. */ |
/* Copy up to first non-alpha character. */ |
|
|
for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) { |
for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) { |
buf[i] = tolower(p[*pos]); |
buf[i] = (char)tolower((unsigned char)p[*pos]); |
if ( ! isalpha((unsigned char)buf[i])) |
if ( ! isalpha((unsigned char)buf[i])) |
break; |
break; |
} |
} |
|
|
/* Exit if buffer is empty (or overrun). */ |
/* Exit if buffer is empty (or overrun). */ |
|
|
if (KEY_MAXNAME == i || 0 == i) { |
if (KEY_MAXNAME == i || 0 == i) { |
TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos); |
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL); |
return; |
return; |
} |
} |
|
|
|
|
while (isspace((unsigned char)p[*pos])) |
while (isspace((unsigned char)p[*pos])) |
(*pos)++; |
(*pos)++; |
|
|
/* |
/* |
* Look through all of the available keys to find one that |
* Look through all of the available keys to find one that |
* matches the input. FIXME: hashtable this. |
* matches the input. FIXME: hashtable this. |
*/ |
*/ |
|
|
* of the sequence altogether. |
* of the sequence altogether. |
*/ |
*/ |
|
|
if (keys[i].key) |
if (keys[i].key) |
tbl->opts.opts |= keys[i].key; |
tbl->opts.opts |= keys[i].key; |
else if ( ! arg(tbl, ln, p, pos, keys[i].ident)) |
else if ( ! arg(tbl, ln, p, pos, keys[i].ident)) |
return; |
return; |
|
|
break; |
break; |
} |
} |
|
|
/* |
/* |
* Allow us to recover from bad options by continuing to another |
* Allow us to recover from bad options by continuing to another |
* parse sequence. |
* parse sequence. |
*/ |
*/ |
|
|
if (KEY_MAXKEYS == i) |
if (KEY_MAXKEYS == i) |
TBL_MSG(tbl, MANDOCERR_TBLOPT, ln, sv); |
mandoc_msg(MANDOCERR_TBLOPT, tbl->parse, ln, sv, NULL); |
|
|
goto again; |
goto again; |
/* NOTREACHED */ |
/* NOTREACHED */ |