#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mandoc.h"
#include "tbl.h"
#include "libmandoc.h"
#include "tbl_int.h"
#define KEY_DPOINT 0
#define KEY_DELIM 1
#define KEY_LINESIZE 2
#define KEY_TAB 3
struct tbl_phrase {
const char *name;
int key;
};
static const struct tbl_phrase keys[] = {
{"decimalpoint", 0},
{"delim", 0},
{"linesize", 0},
{"tab", 0},
{"allbox", TBL_OPT_ALLBOX | TBL_OPT_BOX},
{"box", TBL_OPT_BOX},
{"frame", TBL_OPT_BOX},
{"center", TBL_OPT_CENTRE},
{"centre", TBL_OPT_CENTRE},
{"doublebox", TBL_OPT_DBOX},
{"doubleframe", TBL_OPT_DBOX},
{"expand", TBL_OPT_EXPAND},
{"nokeep", TBL_OPT_NOKEEP},
{"nospaces", TBL_OPT_NOSPACE},
{"nowarn", TBL_OPT_NOWARN},
};
#define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
static void arg(struct tbl_node *, int, const char *, int *, int);
static void
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
{
int len, want;
while (p[*pos] == ' ' || p[*pos] == '\t')
(*pos)++;
len = 0;
if (p[*pos] == '(') {
(*pos)++;
while (p[*pos + len] != ')')
len++;
}
switch (key) {
case KEY_DELIM:
mandoc_msg(MANDOCERR_TBLOPT_EQN,
ln, *pos, "%.*s", len, p + *pos);
want = 2;
break;
case KEY_TAB:
want = 1;
if (len == want)
tbl->opts.tab = p[*pos];
break;
case KEY_LINESIZE:
want = 0;
break;
case KEY_DPOINT:
want = 1;
if (len == want)
tbl->opts.decimal = p[*pos];
break;
default:
abort();
}
if (len == 0)
mandoc_msg(MANDOCERR_TBLOPT_NOARG, ln, *pos,
"%s", keys[key].name);
else if (want && len != want)
mandoc_msg(MANDOCERR_TBLOPT_ARGSZ, ln, *pos,
"%s want %d have %d", keys[key].name, want, len);
*pos += len;
if (p[*pos] == ')')
(*pos)++;
}
void
tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
{
int i, pos, len;
pos = *offs;
for (;;) {
while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
pos++;
if (p[pos] == ';') {
*offs = pos + 1;
return;
}
len = 0;
while (isalpha((unsigned char)p[pos + len]))
len++;
if (len == 0) {
mandoc_msg(MANDOCERR_TBLOPT_ALPHA,
ln, pos, "%c", p[pos]);
pos++;
continue;
}
i = 0;
while (i < KEY_MAXKEYS &&
(strncasecmp(p + pos, keys[i].name, len) ||
keys[i].name[len] != '\0'))
i++;
if (i == KEY_MAXKEYS) {
mandoc_msg(MANDOCERR_TBLOPT_BAD,
ln, pos, "%.*s", len, p + pos);
pos += len;
continue;
}
pos += len;
if (keys[i].key)
tbl->opts.opts |= keys[i].key;
else
arg(tbl, ln, p, &pos, i);
}
}