Annotation of mandoc/tbl_opts.c, Revision 1.1
1.1 ! kristaps 1: /* $Id: option.c,v 1.5 2009/09/09 12:51:34 kristaps Exp $ */
! 2: /*
! 3: * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
! 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