]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/mandoc/tbl_opts.c
Pull in r356809 from upstream llvm trunk (by Eli Friedman):
[FreeBSD/FreeBSD.git] / contrib / mandoc / tbl_opts.c
1 /*      $Id: tbl_opts.c,v 1.21 2015/09/26 00:54:04 schwarze Exp $ */
2 /*
3  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #include "config.h"
19
20 #include <sys/types.h>
21
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "mandoc.h"
28 #include "libmandoc.h"
29 #include "libroff.h"
30
31 #define KEY_DPOINT      0
32 #define KEY_DELIM       1
33 #define KEY_LINESIZE    2
34 #define KEY_TAB         3
35
36 struct  tbl_phrase {
37         const char      *name;
38         int              key;
39 };
40
41 static  const struct tbl_phrase keys[] = {
42         {"decimalpoint", 0},
43         {"delim",        0},
44         {"linesize",     0},
45         {"tab",          0},
46         {"allbox",       TBL_OPT_ALLBOX | TBL_OPT_BOX},
47         {"box",          TBL_OPT_BOX},
48         {"frame",        TBL_OPT_BOX},
49         {"center",       TBL_OPT_CENTRE},
50         {"centre",       TBL_OPT_CENTRE},
51         {"doublebox",    TBL_OPT_DBOX},
52         {"doubleframe",  TBL_OPT_DBOX},
53         {"expand",       TBL_OPT_EXPAND},
54         {"nokeep",       TBL_OPT_NOKEEP},
55         {"nospaces",     TBL_OPT_NOSPACE},
56         {"nowarn",       TBL_OPT_NOWARN},
57 };
58
59 #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
60
61 static  void     arg(struct tbl_node *, int, const char *, int *, int);
62
63
64 static void
65 arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
66 {
67         int              len, want;
68
69         while (p[*pos] == ' ' || p[*pos] == '\t')
70                 (*pos)++;
71
72         /* Arguments are enclosed in parentheses. */
73
74         len = 0;
75         if (p[*pos] == '(') {
76                 (*pos)++;
77                 while (p[*pos + len] != ')')
78                         len++;
79         }
80
81         switch (key) {
82         case KEY_DELIM:
83                 mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
84                     ln, *pos, "%.*s", len, p + *pos);
85                 want = 2;
86                 break;
87         case KEY_TAB:
88                 want = 1;
89                 if (len == want)
90                         tbl->opts.tab = p[*pos];
91                 break;
92         case KEY_LINESIZE:
93                 want = 0;
94                 break;
95         case KEY_DPOINT:
96                 want = 1;
97                 if (len == want)
98                         tbl->opts.decimal = p[*pos];
99                 break;
100         default:
101                 abort();
102         }
103
104         if (len == 0)
105                 mandoc_msg(MANDOCERR_TBLOPT_NOARG,
106                     tbl->parse, ln, *pos, keys[key].name);
107         else if (want && len != want)
108                 mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
109                     tbl->parse, ln, *pos, "%s want %d have %d",
110                     keys[key].name, want, len);
111
112         *pos += len;
113         if (p[*pos] == ')')
114                 (*pos)++;
115 }
116
117 /*
118  * Parse one line of options up to the semicolon.
119  * Each option can be preceded by blanks and/or commas,
120  * and some options are followed by arguments.
121  */
122 void
123 tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
124 {
125         int              i, pos, len;
126
127         pos = *offs;
128         for (;;) {
129                 while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
130                         pos++;
131
132                 if (p[pos] == ';') {
133                         *offs = pos + 1;
134                         return;
135                 }
136
137                 /* Parse one option name. */
138
139                 len = 0;
140                 while (isalpha((unsigned char)p[pos + len]))
141                         len++;
142
143                 if (len == 0) {
144                         mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
145                             tbl->parse, ln, pos, "%c", p[pos]);
146                         pos++;
147                         continue;
148                 }
149
150                 /* Look up the option name. */
151
152                 i = 0;
153                 while (i < KEY_MAXKEYS &&
154                     (strncasecmp(p + pos, keys[i].name, len) ||
155                      keys[i].name[len] != '\0'))
156                         i++;
157
158                 if (i == KEY_MAXKEYS) {
159                         mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
160                             ln, pos, "%.*s", len, p + pos);
161                         pos += len;
162                         continue;
163                 }
164
165                 /* Handle the option. */
166
167                 pos += len;
168                 if (keys[i].key)
169                         tbl->opts.opts |= keys[i].key;
170                 else
171                         arg(tbl, ln, p, &pos, i);
172         }
173 }