xref: /netbsd-src/external/bsd/mdocml/dist/tbl_opts.c (revision 6167eca2d062f3691f8b22e3b8ea212d6dde852a)
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