1*6167eca2Schristos /* Id: tbl_opts.c,v 1.24 2018/12/14 05:18:03 schwarze Exp */
2c0d9444aSjoerg /*
3b1e8115bSjoerg * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
45c413d0cSchristos * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
5c0d9444aSjoerg *
6c0d9444aSjoerg * Permission to use, copy, modify, and distribute this software for any
7c0d9444aSjoerg * purpose with or without fee is hereby granted, provided that the above
8c0d9444aSjoerg * copyright notice and this permission notice appear in all copies.
9c0d9444aSjoerg *
10c0d9444aSjoerg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11c0d9444aSjoerg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12c0d9444aSjoerg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13c0d9444aSjoerg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14c0d9444aSjoerg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15c0d9444aSjoerg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16c0d9444aSjoerg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17c0d9444aSjoerg */
18c09c2a7bSnakayama #include "config.h"
195c413d0cSchristos
205c413d0cSchristos #include <sys/types.h>
21c09c2a7bSnakayama
22c0d9444aSjoerg #include <ctype.h>
23c0d9444aSjoerg #include <stdio.h>
24c0d9444aSjoerg #include <stdlib.h>
25c0d9444aSjoerg #include <string.h>
26c0d9444aSjoerg
27c0d9444aSjoerg #include "mandoc.h"
28*6167eca2Schristos #include "tbl.h"
299c655dd9Sjoerg #include "libmandoc.h"
30*6167eca2Schristos #include "tbl_int.h"
31c0d9444aSjoerg
325c413d0cSchristos #define KEY_DPOINT 0
335c413d0cSchristos #define KEY_DELIM 1
345c413d0cSchristos #define KEY_LINESIZE 2
355c413d0cSchristos #define KEY_TAB 3
36c0d9444aSjoerg
37c0d9444aSjoerg struct tbl_phrase {
38c0d9444aSjoerg const char *name;
39c0d9444aSjoerg int key;
40c0d9444aSjoerg };
41c0d9444aSjoerg
425c413d0cSchristos static const struct tbl_phrase keys[] = {
435c413d0cSchristos {"decimalpoint", 0},
445c413d0cSchristos {"delim", 0},
455c413d0cSchristos {"linesize", 0},
465c413d0cSchristos {"tab", 0},
475c413d0cSchristos {"allbox", TBL_OPT_ALLBOX | TBL_OPT_BOX},
485c413d0cSchristos {"box", TBL_OPT_BOX},
495c413d0cSchristos {"frame", TBL_OPT_BOX},
505c413d0cSchristos {"center", TBL_OPT_CENTRE},
515c413d0cSchristos {"centre", TBL_OPT_CENTRE},
525c413d0cSchristos {"doublebox", TBL_OPT_DBOX},
535c413d0cSchristos {"doubleframe", TBL_OPT_DBOX},
545c413d0cSchristos {"expand", TBL_OPT_EXPAND},
555c413d0cSchristos {"nokeep", TBL_OPT_NOKEEP},
565c413d0cSchristos {"nospaces", TBL_OPT_NOSPACE},
575c413d0cSchristos {"nowarn", TBL_OPT_NOWARN},
58c0d9444aSjoerg };
59c0d9444aSjoerg
605c413d0cSchristos #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
61c0d9444aSjoerg
625c413d0cSchristos static void arg(struct tbl_node *, int, const char *, int *, int);
635c413d0cSchristos
645c413d0cSchristos
655c413d0cSchristos static void
arg(struct tbl_node * tbl,int ln,const char * p,int * pos,int key)665c413d0cSchristos arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
67c0d9444aSjoerg {
685c413d0cSchristos int len, want;
69c0d9444aSjoerg
705c413d0cSchristos while (p[*pos] == ' ' || p[*pos] == '\t')
71c0d9444aSjoerg (*pos)++;
72c0d9444aSjoerg
735c413d0cSchristos /* Arguments are enclosed in parentheses. */
74c0d9444aSjoerg
755c413d0cSchristos len = 0;
765c413d0cSchristos if (p[*pos] == '(') {
775c413d0cSchristos (*pos)++;
785c413d0cSchristos while (p[*pos + len] != ')')
795c413d0cSchristos len++;
80c0d9444aSjoerg }
81c0d9444aSjoerg
82c0d9444aSjoerg switch (key) {
835c413d0cSchristos case KEY_DELIM:
84*6167eca2Schristos mandoc_msg(MANDOCERR_TBLOPT_EQN,
855c413d0cSchristos ln, *pos, "%.*s", len, p + *pos);
865c413d0cSchristos want = 2;
87c0d9444aSjoerg break;
885c413d0cSchristos case KEY_TAB:
895c413d0cSchristos want = 1;
905c413d0cSchristos if (len == want)
915c413d0cSchristos tbl->opts.tab = p[*pos];
92c0d9444aSjoerg break;
935c413d0cSchristos case KEY_LINESIZE:
945c413d0cSchristos want = 0;
95c0d9444aSjoerg break;
965c413d0cSchristos case KEY_DPOINT:
975c413d0cSchristos want = 1;
985c413d0cSchristos if (len == want)
995c413d0cSchristos tbl->opts.decimal = p[*pos];
100c0d9444aSjoerg break;
101c0d9444aSjoerg default:
102c0d9444aSjoerg abort();
103c0d9444aSjoerg }
104c0d9444aSjoerg
1055c413d0cSchristos if (len == 0)
106*6167eca2Schristos mandoc_msg(MANDOCERR_TBLOPT_NOARG, ln, *pos,
107*6167eca2Schristos "%s", keys[key].name);
1085c413d0cSchristos else if (want && len != want)
109*6167eca2Schristos mandoc_msg(MANDOCERR_TBLOPT_ARGSZ, ln, *pos,
110*6167eca2Schristos "%s want %d have %d", keys[key].name, want, len);
111c0d9444aSjoerg
1125c413d0cSchristos *pos += len;
1135c413d0cSchristos if (p[*pos] == ')')
1145c413d0cSchristos (*pos)++;
115c0d9444aSjoerg }
116c0d9444aSjoerg
1175c413d0cSchristos /*
1185c413d0cSchristos * Parse one line of options up to the semicolon.
1195c413d0cSchristos * Each option can be preceded by blanks and/or commas,
1205c413d0cSchristos * and some options are followed by arguments.
1215c413d0cSchristos */
1225c413d0cSchristos void
tbl_option(struct tbl_node * tbl,int ln,const char * p,int * offs)1235c413d0cSchristos tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
124c0d9444aSjoerg {
1255c413d0cSchristos int i, pos, len;
126c0d9444aSjoerg
1275c413d0cSchristos pos = *offs;
1285c413d0cSchristos for (;;) {
1295c413d0cSchristos while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
1305c413d0cSchristos pos++;
131c0d9444aSjoerg
1325c413d0cSchristos if (p[pos] == ';') {
1335c413d0cSchristos *offs = pos + 1;
134c0d9444aSjoerg return;
135c0d9444aSjoerg }
136c0d9444aSjoerg
1375c413d0cSchristos /* Parse one option name. */
138c0d9444aSjoerg
1395c413d0cSchristos len = 0;
1405c413d0cSchristos while (isalpha((unsigned char)p[pos + len]))
1415c413d0cSchristos len++;
142c0d9444aSjoerg
1435c413d0cSchristos if (len == 0) {
144*6167eca2Schristos mandoc_msg(MANDOCERR_TBLOPT_ALPHA,
145*6167eca2Schristos ln, pos, "%c", p[pos]);
1465c413d0cSchristos pos++;
147c0d9444aSjoerg continue;
1485c413d0cSchristos }
149c0d9444aSjoerg
1505c413d0cSchristos /* Look up the option name. */
151c0d9444aSjoerg
1525c413d0cSchristos i = 0;
1535c413d0cSchristos while (i < KEY_MAXKEYS &&
1545c413d0cSchristos (strncasecmp(p + pos, keys[i].name, len) ||
1555c413d0cSchristos keys[i].name[len] != '\0'))
1565c413d0cSchristos i++;
1575c413d0cSchristos
1585c413d0cSchristos if (i == KEY_MAXKEYS) {
159*6167eca2Schristos mandoc_msg(MANDOCERR_TBLOPT_BAD,
1605c413d0cSchristos ln, pos, "%.*s", len, p + pos);
1615c413d0cSchristos pos += len;
1625c413d0cSchristos continue;
1635c413d0cSchristos }
1645c413d0cSchristos
1655c413d0cSchristos /* Handle the option. */
1665c413d0cSchristos
1675c413d0cSchristos pos += len;
168c0d9444aSjoerg if (keys[i].key)
169c0d9444aSjoerg tbl->opts.opts |= keys[i].key;
1705c413d0cSchristos else
1715c413d0cSchristos arg(tbl, ln, p, &pos, i);
172c0d9444aSjoerg }
173c0d9444aSjoerg }
174