xref: /titanic_51/usr/src/cmd/mandoc/tbl_opts.c (revision 260e9a87725c090ba5835b1f9f0b62fa2f96036f)
1*260e9a87SYuri Pankov /*	$Id: tbl_opts.c,v 1.20 2015/01/28 17:32:07 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*260e9a87SYuri Pankov  * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore  *
695c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore  *
1095c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1195c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1295c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1395c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1795c635efSGarrett D'Amore  */
1895c635efSGarrett D'Amore #include "config.h"
19*260e9a87SYuri Pankov 
20*260e9a87SYuri Pankov #include <sys/types.h>
2195c635efSGarrett D'Amore 
2295c635efSGarrett D'Amore #include <ctype.h>
2395c635efSGarrett D'Amore #include <stdio.h>
2495c635efSGarrett D'Amore #include <stdlib.h>
2595c635efSGarrett D'Amore #include <string.h>
2695c635efSGarrett D'Amore 
2795c635efSGarrett D'Amore #include "mandoc.h"
2895c635efSGarrett D'Amore #include "libmandoc.h"
2995c635efSGarrett D'Amore #include "libroff.h"
3095c635efSGarrett D'Amore 
31*260e9a87SYuri Pankov #define	KEY_DPOINT	0
32*260e9a87SYuri Pankov #define	KEY_DELIM	1
33*260e9a87SYuri Pankov #define	KEY_LINESIZE	2
34*260e9a87SYuri Pankov #define	KEY_TAB		3
3595c635efSGarrett D'Amore 
3695c635efSGarrett D'Amore struct	tbl_phrase {
3795c635efSGarrett D'Amore 	const char	*name;
3895c635efSGarrett D'Amore 	int		 key;
3995c635efSGarrett D'Amore };
4095c635efSGarrett D'Amore 
41*260e9a87SYuri Pankov static	const struct tbl_phrase keys[] = {
42*260e9a87SYuri Pankov 	{"decimalpoint", 0},
43*260e9a87SYuri Pankov 	{"delim",	 0},
44*260e9a87SYuri Pankov 	{"linesize",	 0},
45*260e9a87SYuri Pankov 	{"tab",		 0},
46*260e9a87SYuri Pankov 	{"allbox",	 TBL_OPT_ALLBOX | TBL_OPT_BOX},
47*260e9a87SYuri Pankov 	{"box",		 TBL_OPT_BOX},
48*260e9a87SYuri Pankov 	{"frame",	 TBL_OPT_BOX},
49*260e9a87SYuri Pankov 	{"center",	 TBL_OPT_CENTRE},
50*260e9a87SYuri Pankov 	{"centre",	 TBL_OPT_CENTRE},
51*260e9a87SYuri Pankov 	{"doublebox",	 TBL_OPT_DBOX},
52*260e9a87SYuri Pankov 	{"doubleframe",  TBL_OPT_DBOX},
53*260e9a87SYuri Pankov 	{"expand",	 TBL_OPT_EXPAND},
54*260e9a87SYuri Pankov 	{"nokeep",	 TBL_OPT_NOKEEP},
55*260e9a87SYuri Pankov 	{"nospaces",	 TBL_OPT_NOSPACE},
56*260e9a87SYuri Pankov 	{"nowarn",	 TBL_OPT_NOWARN},
5795c635efSGarrett D'Amore };
5895c635efSGarrett D'Amore 
59*260e9a87SYuri Pankov #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
6095c635efSGarrett D'Amore 
61*260e9a87SYuri Pankov static	void	 arg(struct tbl_node *, int, const char *, int *, int);
62*260e9a87SYuri Pankov 
63*260e9a87SYuri Pankov 
64*260e9a87SYuri Pankov static void
65*260e9a87SYuri Pankov arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
6695c635efSGarrett D'Amore {
67*260e9a87SYuri Pankov 	int		 len, want;
6895c635efSGarrett D'Amore 
69*260e9a87SYuri Pankov 	while (p[*pos] == ' ' || p[*pos] == '\t')
7095c635efSGarrett D'Amore 		(*pos)++;
7195c635efSGarrett D'Amore 
72*260e9a87SYuri Pankov 	/* Arguments are enclosed in parentheses. */
7395c635efSGarrett D'Amore 
74*260e9a87SYuri Pankov 	len = 0;
75*260e9a87SYuri Pankov 	if (p[*pos] == '(') {
76*260e9a87SYuri Pankov 		(*pos)++;
77*260e9a87SYuri Pankov 		while (p[*pos + len] != ')')
78*260e9a87SYuri Pankov 			len++;
7995c635efSGarrett D'Amore 	}
8095c635efSGarrett D'Amore 
8195c635efSGarrett D'Amore 	switch (key) {
82*260e9a87SYuri Pankov 	case KEY_DELIM:
83*260e9a87SYuri Pankov 		mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
84*260e9a87SYuri Pankov 		    ln, *pos, "%.*s", len, p + *pos);
85*260e9a87SYuri Pankov 		want = 2;
8695c635efSGarrett D'Amore 		break;
87*260e9a87SYuri Pankov 	case KEY_TAB:
88*260e9a87SYuri Pankov 		want = 1;
89*260e9a87SYuri Pankov 		if (len == want)
90*260e9a87SYuri Pankov 			tbl->opts.tab = p[*pos];
9195c635efSGarrett D'Amore 		break;
92*260e9a87SYuri Pankov 	case KEY_LINESIZE:
93*260e9a87SYuri Pankov 		want = 0;
9495c635efSGarrett D'Amore 		break;
95*260e9a87SYuri Pankov 	case KEY_DPOINT:
96*260e9a87SYuri Pankov 		want = 1;
97*260e9a87SYuri Pankov 		if (len == want)
98*260e9a87SYuri Pankov 			tbl->opts.decimal = p[*pos];
9995c635efSGarrett D'Amore 		break;
10095c635efSGarrett D'Amore 	default:
10195c635efSGarrett D'Amore 		abort();
10295c635efSGarrett D'Amore 		/* NOTREACHED */
10395c635efSGarrett D'Amore 	}
10495c635efSGarrett D'Amore 
105*260e9a87SYuri Pankov 	if (len == 0)
106*260e9a87SYuri Pankov 		mandoc_msg(MANDOCERR_TBLOPT_NOARG,
107*260e9a87SYuri Pankov 		    tbl->parse, ln, *pos, keys[key].name);
108*260e9a87SYuri Pankov 	else if (want && len != want)
109*260e9a87SYuri Pankov 		mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
110*260e9a87SYuri Pankov 		    tbl->parse, ln, *pos, "%s want %d have %d",
111*260e9a87SYuri Pankov 		    keys[key].name, want, len);
11295c635efSGarrett D'Amore 
113*260e9a87SYuri Pankov 	*pos += len;
114*260e9a87SYuri Pankov 	if (p[*pos] == ')')
115*260e9a87SYuri Pankov 		(*pos)++;
11695c635efSGarrett D'Amore }
11795c635efSGarrett D'Amore 
118*260e9a87SYuri Pankov /*
119*260e9a87SYuri Pankov  * Parse one line of options up to the semicolon.
120*260e9a87SYuri Pankov  * Each option can be preceded by blanks and/or commas,
121*260e9a87SYuri Pankov  * and some options are followed by arguments.
122*260e9a87SYuri Pankov  */
123*260e9a87SYuri Pankov void
124*260e9a87SYuri Pankov tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
12595c635efSGarrett D'Amore {
126*260e9a87SYuri Pankov 	int		 i, pos, len;
12795c635efSGarrett D'Amore 
128*260e9a87SYuri Pankov 	pos = *offs;
129*260e9a87SYuri Pankov 	for (;;) {
130*260e9a87SYuri Pankov 		while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
131*260e9a87SYuri Pankov 			pos++;
13295c635efSGarrett D'Amore 
133*260e9a87SYuri Pankov 		if (p[pos] == ';') {
134*260e9a87SYuri Pankov 			*offs = pos + 1;
13595c635efSGarrett D'Amore 			return;
13695c635efSGarrett D'Amore 		}
13795c635efSGarrett D'Amore 
138*260e9a87SYuri Pankov 		/* Parse one option name. */
13995c635efSGarrett D'Amore 
140*260e9a87SYuri Pankov 		len = 0;
141*260e9a87SYuri Pankov 		while (isalpha((unsigned char)p[pos + len]))
142*260e9a87SYuri Pankov 			len++;
14395c635efSGarrett D'Amore 
144*260e9a87SYuri Pankov 		if (len == 0) {
145*260e9a87SYuri Pankov 			mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
146*260e9a87SYuri Pankov 			    tbl->parse, ln, pos, "%c", p[pos]);
147*260e9a87SYuri Pankov 			pos++;
14895c635efSGarrett D'Amore 			continue;
149*260e9a87SYuri Pankov 		}
15095c635efSGarrett D'Amore 
151*260e9a87SYuri Pankov 		/* Look up the option name. */
15295c635efSGarrett D'Amore 
153*260e9a87SYuri Pankov 		i = 0;
154*260e9a87SYuri Pankov 		while (i < KEY_MAXKEYS &&
155*260e9a87SYuri Pankov 		    (strncasecmp(p + pos, keys[i].name, len) ||
156*260e9a87SYuri Pankov 		     keys[i].name[len] != '\0'))
157*260e9a87SYuri Pankov 			i++;
158*260e9a87SYuri Pankov 
159*260e9a87SYuri Pankov 		if (i == KEY_MAXKEYS) {
160*260e9a87SYuri Pankov 			mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
161*260e9a87SYuri Pankov 			    ln, pos, "%.*s", len, p + pos);
162*260e9a87SYuri Pankov 			pos += len;
163*260e9a87SYuri Pankov 			continue;
164*260e9a87SYuri Pankov 		}
165*260e9a87SYuri Pankov 
166*260e9a87SYuri Pankov 		/* Handle the option. */
167*260e9a87SYuri Pankov 
168*260e9a87SYuri Pankov 		pos += len;
16995c635efSGarrett D'Amore 		if (keys[i].key)
17095c635efSGarrett D'Amore 			tbl->opts.opts |= keys[i].key;
171*260e9a87SYuri Pankov 		else
172*260e9a87SYuri Pankov 			arg(tbl, ln, p, &pos, i);
17395c635efSGarrett D'Amore 	}
17495c635efSGarrett D'Amore }
175