Annotation of mandoc/tbl_opts.c, Revision 1.2
1.2 ! kristaps 1: /* $Id: tbl_opts.c,v 1.1 2010/12/28 13:46:07 kristaps Exp $ */
1.1 kristaps 2: /*
1.2 ! kristaps 3: * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <stdio.h>
18: #include <stdlib.h>
19: #include <string.h>
20:
21: #include "libroff.h"
22:
23: enum tbl_ident {
24: KEY_CENTRE = 0,
25: KEY_DELIM,
26: KEY_EXPAND,
27: KEY_BOX,
28: KEY_DBOX,
29: KEY_ALLBOX,
30: KEY_TAB,
31: KEY_LINESIZE,
32: KEY_NOKEEP,
33: KEY_DPOINT,
34: KEY_NOSPACE,
35: KEY_FRAME,
36: KEY_DFRAME,
37: KEY_MAX
38: };
39:
40: struct tbl_phrase {
41: const char *name;
42: int key;
43: enum tbl_ident ident;
44: };
45:
46: /* Handle Commonwealth/American spellings. */
47: #define KEY_MAXKEYS 14
48:
49: static const struct tbl_phrase keys[KEY_MAXKEYS] = {
50: { "center", TBL_OPT_CENTRE, KEY_CENTRE},
51: { "centre", TBL_OPT_CENTRE, KEY_CENTRE},
52: { "delim", 0, KEY_DELIM},
53: { "expand", TBL_OPT_EXPAND, KEY_EXPAND},
54: { "box", TBL_OPT_BOX, KEY_BOX},
55: { "doublebox", TBL_OPT_DBOX, KEY_DBOX},
56: { "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX},
57: { "frame", TBL_OPT_BOX, KEY_FRAME},
58: { "doubleframe", TBL_OPT_DBOX, KEY_DFRAME},
59: { "tab", 0, KEY_TAB},
60: { "linesize", 0, KEY_LINESIZE},
61: { "nokeep", TBL_OPT_NOKEEP, KEY_NOKEEP},
62: { "decimalpoint", 0, KEY_DPOINT},
63: { "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE},
64: };
65:
66: static int arg(struct tbl *, int, const char *, int *, int);
67: static int opt(struct tbl *, int, const char *, int *);
68:
69: static int
70: arg(struct tbl *tbl, int ln, const char *p, int *pos, int key)
71: {
72: int sv;
73:
74: again:
75: sv = *pos;
76:
77: switch (tbl_next(tbl, p, pos)) {
78: case (TBL_TOK_OPENPAREN):
79: break;
80: case (TBL_TOK_SPACE):
81: /* FALLTHROUGH */
82: case (TBL_TOK_TAB):
83: goto again;
84: default:
85: return(0);
86: }
87:
88: sv = *pos;
89:
90: switch (tbl_next(tbl, p, pos)) {
91: case (TBL_TOK__MAX):
92: break;
93: default:
94: return(0);
95: }
96:
97: switch (key) {
98: case (KEY_DELIM):
99: /* FIXME: cache this value. */
100: if (2 != strlen(tbl->buf))
101: return(0);
102: tbl->delims[0] = tbl->buf[0];
103: tbl->delims[1] = tbl->buf[1];
104: break;
105: case (KEY_TAB):
106: /* FIXME: cache this value. */
107: if (1 != strlen(tbl->buf))
108: return(0);
109: tbl->tab = tbl->buf[0];
110: break;
111: case (KEY_LINESIZE):
112: if ((tbl->linesize = atoi(tbl->buf)) <= 0)
113: return(0);
114: break;
115: case (KEY_DPOINT):
116: /* FIXME: cache this value. */
117: if (1 != strlen(tbl->buf))
118: return(0);
119: tbl->decimal = tbl->buf[0];
120: break;
121: default:
122: abort();
123: }
124:
125: sv = *pos;
126:
127: switch (tbl_next(tbl, p, pos)) {
128: case (TBL_TOK_CLOSEPAREN):
129: break;
130: default:
131: return(0);
132: }
133:
134: return(1);
135: }
136:
137:
138: static int
139: opt(struct tbl *tbl, int ln, const char *p, int *pos)
140: {
141: int i, sv;
142:
143: again:
144: sv = *pos;
145:
146: /*
147: * EBNF describing this section:
148: *
149: * options ::= option_list [:space:]* [;][\n]
150: * option_list ::= option option_tail
151: * option_tail ::= [:space:]+ option_list |
152: * ::= epsilon
153: * option ::= [:alpha:]+ args
154: * args ::= [:space:]* [(] [:alpha:]+ [)]
155: */
156:
157: switch (tbl_next(tbl, p, pos)) {
158: case (TBL_TOK__MAX):
159: break;
160: case (TBL_TOK_SPACE):
161: /* FALLTHROUGH */
162: case (TBL_TOK_TAB):
163: goto again;
164: case (TBL_TOK_SEMICOLON):
165: tbl->part = TBL_PART_LAYOUT;
166: return(1);
167: default:
168: return(0);
169: }
170:
171: for (i = 0; i < KEY_MAXKEYS; i++) {
172: /* FIXME: hashtable this? */
173: if (strcasecmp(tbl->buf, keys[i].name))
174: continue;
175: if (keys[i].key)
176: tbl->opts |= keys[i].key;
177: else if ( ! arg(tbl, ln, p, pos, keys[i].ident))
178: return(0);
179:
180: break;
181: }
182:
183: if (KEY_MAXKEYS == i)
184: return(0);
185:
186: return(opt(tbl, ln, p, pos));
187: }
188:
189: int
190: tbl_option(struct tbl *tbl, int ln, const char *p)
191: {
192: int pos;
193:
194: pos = 0;
195: return(opt(tbl, ln, p, &pos));
196: }
CVSweb