2019-03-29 13:13:30 +00:00
|
|
|
/* $Id: tbl_opts.c,v 1.24 2018/12/14 05:18:03 schwarze Exp $ */
|
2012-10-18 09:55:16 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
2015-03-02 16:45:41 +00:00
|
|
|
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
2012-10-18 09:55:16 +00:00
|
|
|
*
|
|
|
|
* 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 "config.h"
|
2014-12-02 07:34:06 +00:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
2012-10-18 09:55:16 +00:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "mandoc.h"
|
2019-03-29 13:13:30 +00:00
|
|
|
#include "tbl.h"
|
2012-10-18 09:55:16 +00:00
|
|
|
#include "libmandoc.h"
|
2019-03-29 13:13:30 +00:00
|
|
|
#include "tbl_int.h"
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
#define KEY_DPOINT 0
|
|
|
|
#define KEY_DELIM 1
|
|
|
|
#define KEY_LINESIZE 2
|
|
|
|
#define KEY_TAB 3
|
2012-10-18 09:55:16 +00:00
|
|
|
|
|
|
|
struct tbl_phrase {
|
|
|
|
const char *name;
|
|
|
|
int key;
|
|
|
|
};
|
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
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},
|
2012-10-18 09:55:16 +00:00
|
|
|
};
|
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
#define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
static void arg(struct tbl_node *, int, const char *, int *, int);
|
2014-11-22 18:08:25 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
|
2012-10-18 09:55:16 +00:00
|
|
|
{
|
2015-03-02 16:45:41 +00:00
|
|
|
int len, want;
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
while (p[*pos] == ' ' || p[*pos] == '\t')
|
2012-10-18 09:55:16 +00:00
|
|
|
(*pos)++;
|
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
/* Arguments are enclosed in parentheses. */
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
len = 0;
|
|
|
|
if (p[*pos] == '(') {
|
|
|
|
(*pos)++;
|
|
|
|
while (p[*pos + len] != ')')
|
|
|
|
len++;
|
2012-10-18 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (key) {
|
2014-11-22 18:08:25 +00:00
|
|
|
case KEY_DELIM:
|
2019-03-29 13:13:30 +00:00
|
|
|
mandoc_msg(MANDOCERR_TBLOPT_EQN,
|
2015-03-02 16:45:41 +00:00
|
|
|
ln, *pos, "%.*s", len, p + *pos);
|
|
|
|
want = 2;
|
2012-10-18 09:55:16 +00:00
|
|
|
break;
|
2014-11-22 18:08:25 +00:00
|
|
|
case KEY_TAB:
|
2015-03-02 16:45:41 +00:00
|
|
|
want = 1;
|
|
|
|
if (len == want)
|
|
|
|
tbl->opts.tab = p[*pos];
|
|
|
|
break;
|
2014-11-22 18:08:25 +00:00
|
|
|
case KEY_LINESIZE:
|
2015-03-02 16:45:41 +00:00
|
|
|
want = 0;
|
|
|
|
break;
|
2014-11-22 18:08:25 +00:00
|
|
|
case KEY_DPOINT:
|
2015-03-02 16:45:41 +00:00
|
|
|
want = 1;
|
|
|
|
if (len == want)
|
|
|
|
tbl->opts.decimal = p[*pos];
|
|
|
|
break;
|
2012-10-18 09:55:16 +00:00
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
if (len == 0)
|
2019-03-29 13:13:30 +00:00
|
|
|
mandoc_msg(MANDOCERR_TBLOPT_NOARG, ln, *pos,
|
|
|
|
"%s", keys[key].name);
|
2015-03-02 16:45:41 +00:00
|
|
|
else if (want && len != want)
|
2019-03-29 13:13:30 +00:00
|
|
|
mandoc_msg(MANDOCERR_TBLOPT_ARGSZ, ln, *pos,
|
|
|
|
"%s want %d have %d", keys[key].name, want, len);
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
*pos += len;
|
|
|
|
if (p[*pos] == ')')
|
|
|
|
(*pos)++;
|
2012-10-18 09:55:16 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
/*
|
|
|
|
* Parse one line of options up to the semicolon.
|
|
|
|
* Each option can be preceded by blanks and/or commas,
|
|
|
|
* and some options are followed by arguments.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
|
2012-10-18 09:55:16 +00:00
|
|
|
{
|
2015-03-02 16:45:41 +00:00
|
|
|
int i, pos, len;
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
pos = *offs;
|
|
|
|
for (;;) {
|
|
|
|
while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
|
|
|
|
pos++;
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
if (p[pos] == ';') {
|
|
|
|
*offs = pos + 1;
|
|
|
|
return;
|
|
|
|
}
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
/* Parse one option name. */
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
len = 0;
|
|
|
|
while (isalpha((unsigned char)p[pos + len]))
|
|
|
|
len++;
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
if (len == 0) {
|
2019-03-29 13:13:30 +00:00
|
|
|
mandoc_msg(MANDOCERR_TBLOPT_ALPHA,
|
|
|
|
ln, pos, "%c", p[pos]);
|
2015-03-02 16:45:41 +00:00
|
|
|
pos++;
|
|
|
|
continue;
|
|
|
|
}
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
/* Look up the option name. */
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
i = 0;
|
|
|
|
while (i < KEY_MAXKEYS &&
|
|
|
|
(strncasecmp(p + pos, keys[i].name, len) ||
|
|
|
|
keys[i].name[len] != '\0'))
|
|
|
|
i++;
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
if (i == KEY_MAXKEYS) {
|
2019-03-29 13:13:30 +00:00
|
|
|
mandoc_msg(MANDOCERR_TBLOPT_BAD,
|
2015-03-02 16:45:41 +00:00
|
|
|
ln, pos, "%.*s", len, p + pos);
|
|
|
|
pos += len;
|
2012-10-18 09:55:16 +00:00
|
|
|
continue;
|
2015-03-02 16:45:41 +00:00
|
|
|
}
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
/* Handle the option. */
|
2012-10-18 09:55:16 +00:00
|
|
|
|
2015-03-02 16:45:41 +00:00
|
|
|
pos += len;
|
2014-11-22 18:08:25 +00:00
|
|
|
if (keys[i].key)
|
2012-10-18 09:55:16 +00:00
|
|
|
tbl->opts.opts |= keys[i].key;
|
2015-03-02 16:45:41 +00:00
|
|
|
else
|
|
|
|
arg(tbl, ln, p, &pos, i);
|
2012-10-18 09:55:16 +00:00
|
|
|
}
|
|
|
|
}
|