[BACK]Return to tbl_layout.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mandoc

Annotation of src/usr.bin/mandoc/tbl_layout.c, Revision 1.1

1.1     ! schwarze    1: /*     $Id: layout.c,v 1.7 2009/09/11 13:24:04 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 <sys/queue.h>
        !            18: #include <sys/types.h>
        !            19:
        !            20: #include <assert.h>
        !            21: #include <ctype.h>
        !            22: #include <stdlib.h>
        !            23: #include <string.h>
        !            24:
        !            25: #include "tbl_extern.h"
        !            26:
        !            27: struct tbl_phrase {
        !            28:        char             name;
        !            29:        enum tbl_cellt   key;
        !            30: };
        !            31:
        !            32: #define        KEYS_MAX         17
        !            33:
        !            34: static const struct tbl_phrase keys[KEYS_MAX] = {
        !            35:        { 'c',           TBL_CELL_CENTRE },
        !            36:        { 'C',           TBL_CELL_CENTRE },
        !            37:        { 'r',           TBL_CELL_RIGHT },
        !            38:        { 'R',           TBL_CELL_RIGHT },
        !            39:        { 'l',           TBL_CELL_LEFT },
        !            40:        { 'L',           TBL_CELL_LEFT },
        !            41:        { 'n',           TBL_CELL_NUMBER },
        !            42:        { 'N',           TBL_CELL_NUMBER },
        !            43:        { 's',           TBL_CELL_SPAN },
        !            44:        { 'S',           TBL_CELL_SPAN },
        !            45:        { 'a',           TBL_CELL_LONG },
        !            46:        { 'A',           TBL_CELL_LONG },
        !            47:        { '^',           TBL_CELL_DOWN },
        !            48:        { '-',           TBL_CELL_HORIZ },
        !            49:        { '_',           TBL_CELL_HORIZ },
        !            50:        { '=',           TBL_CELL_DHORIZ },
        !            51:        { '|',           TBL_CELL_VERT }
        !            52: };
        !            53:
        !            54: static int             mods(struct tbl *, struct tbl_cell *,
        !            55:                                const char *, int,
        !            56:                                const char *, int, int);
        !            57: static int             cell(struct tbl *, struct tbl_row *,
        !            58:                                const char *, int, int);
        !            59: static int             row(struct tbl *, const char *,
        !            60:                                int, const char *, int *);
        !            61:
        !            62:
        !            63: static int
        !            64: mods(struct tbl *tbl, struct tbl_cell *cp, const char *p,
        !            65:                int pp, const char *f, int ln, int pos)
        !            66: {
        !            67:        char             buf[5];
        !            68:        int              i;
        !            69:
        !            70:        /*
        !            71:         * XXX: since, at least for now, modifiers are non-conflicting
        !            72:         * (are separable by value, regardless of position), we let
        !            73:         * modifiers come in any order.  The existing tbl doesn't let
        !            74:         * this happen.
        !            75:         */
        !            76:
        !            77:        if (0 == p[pp])
        !            78:                return(1);
        !            79:
        !            80:        /* Parse numerical spacing from modifier string. */
        !            81:
        !            82:        if (isdigit((u_char)p[pp])) {
        !            83:                for (i = 0; i < 4; i++) {
        !            84:                        if ( ! isdigit((u_char)p[pp + i]))
        !            85:                                break;
        !            86:                        buf[i] = p[pp + i];
        !            87:                }
        !            88:                buf[i] = 0;
        !            89:
        !            90:                /* No greater than 4 digits. */
        !            91:
        !            92:                if (4 == i)
        !            93:                        return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
        !            94:
        !            95:                /*
        !            96:                 * We can't change the spacing in any subsequent layout
        !            97:                 * definitions.  FIXME: I don't think we can change the
        !            98:                 * spacing for a column at all, after it's already been
        !            99:                 * initialised.
        !           100:                 */
        !           101:
        !           102:                if (TBL_PART_CLAYOUT != tbl->part)
        !           103:                        cp->spacing = atoi(buf);
        !           104:                else if ( ! tbl_warnx(tbl, ERR_SYNTAX, f, ln, pos + pp))
        !           105:                        return(0);
        !           106:
        !           107:                /* Continue parsing modifiers. */
        !           108:
        !           109:                return(mods(tbl, cp, p, pp + i, f, ln, pos));
        !           110:        }
        !           111:
        !           112:        /* TODO: GNU has many more extensions. */
        !           113:
        !           114:        switch (p[pp]) {
        !           115:        case ('z'):
        !           116:                /* FALLTHROUGH */
        !           117:        case ('Z'):
        !           118:                cp->flags |= TBL_CELL_WIGN;
        !           119:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           120:        case ('u'):
        !           121:                /* FALLTHROUGH */
        !           122:        case ('U'):
        !           123:                cp->flags |= TBL_CELL_UP;
        !           124:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           125:        case ('e'):
        !           126:                /* FALLTHROUGH */
        !           127:        case ('E'):
        !           128:                cp->flags |= TBL_CELL_EQUAL;
        !           129:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           130:        case ('t'):
        !           131:                /* FALLTHROUGH */
        !           132:        case ('T'):
        !           133:                cp->flags |= TBL_CELL_TALIGN;
        !           134:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           135:        case ('d'):
        !           136:                /* FALLTHROUGH */
        !           137:        case ('D'):
        !           138:                cp->flags |= TBL_CELL_BALIGN;
        !           139:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           140:        case ('f'):
        !           141:                pp++;
        !           142:                /* FALLTHROUGH */
        !           143:        case ('B'):
        !           144:                /* FALLTHROUGH */
        !           145:        case ('I'):
        !           146:                /* FALLTHROUGH */
        !           147:        case ('b'):
        !           148:                /* FALLTHROUGH */
        !           149:        case ('i'):
        !           150:                break;
        !           151:        default:
        !           152:                return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
        !           153:        }
        !           154:
        !           155:        switch (p[pp]) {
        !           156:        case ('b'):
        !           157:                /* FALLTHROUGH */
        !           158:        case ('B'):
        !           159:                cp->flags |= TBL_CELL_BOLD;
        !           160:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           161:        case ('i'):
        !           162:                /* FALLTHROUGH */
        !           163:        case ('I'):
        !           164:                cp->flags |= TBL_CELL_ITALIC;
        !           165:                return(mods(tbl, cp, p, pp + 1, f, ln, pos));
        !           166:        default:
        !           167:                break;
        !           168:        }
        !           169:
        !           170:        return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
        !           171: }
        !           172:
        !           173:
        !           174: static int
        !           175: cell(struct tbl *tbl, struct tbl_row *rp,
        !           176:                const char *f, int ln, int pos)
        !           177: {
        !           178:        struct tbl_cell *cp;
        !           179:        const char      *p;
        !           180:        int              j, i;
        !           181:        enum tbl_cellt   c;
        !           182:
        !           183:        /* Parse the column position (`r', `R', `|', ...). */
        !           184:
        !           185:        c = TBL_CELL_MAX;
        !           186:        for (p = tbl_last(), i = 0; i < KEYS_MAX; i++) {
        !           187:                if (keys[i].name != p[0])
        !           188:                        continue;
        !           189:                c = keys[i].key;
        !           190:                break;
        !           191:        }
        !           192:
        !           193:        if (i == KEYS_MAX)
        !           194:                return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos));
        !           195:
        !           196:        /* Extra check for the double-vertical. */
        !           197:
        !           198:        if (TBL_CELL_VERT == c && '|' == p[1]) {
        !           199:                j = 2;
        !           200:                c = TBL_CELL_DVERT;
        !           201:        } else
        !           202:                j = 1;
        !           203:
        !           204:        /* Disallow subsequent spacers. */
        !           205:
        !           206:        /* LINTED */
        !           207:        cp = TAILQ_LAST(&rp->cell, tbl_cellh);
        !           208:
        !           209:        if (cp && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
        !           210:                        (TBL_CELL_VERT == cp->pos ||
        !           211:                         TBL_CELL_DVERT == cp->pos))
        !           212:                return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos));
        !           213:
        !           214:        /* Allocate cell then parse its modifiers. */
        !           215:
        !           216:        if (NULL == (cp = tbl_cell_alloc(rp, c)))
        !           217:                return(0);
        !           218:        return(mods(tbl, cp, p, j, f, ln, pos));
        !           219: }
        !           220:
        !           221:
        !           222: static int
        !           223: row(struct tbl *tbl, const char *f, int ln,
        !           224:                const char *p, int *pos)
        !           225: {
        !           226:        struct tbl_row  *rp;
        !           227:        int              sv;
        !           228:
        !           229:        rp = tbl_row_alloc(tbl);
        !           230: again:
        !           231:        sv = *pos;
        !           232:
        !           233:        /*
        !           234:         * EBNF describing this section:
        !           235:         *
        !           236:         * row          ::= row_list [:space:]* [.]?[\n]
        !           237:         * row_list     ::= [:space:]* row_elem row_tail
        !           238:         * row_tail     ::= [:space:]*[,] row_list |
        !           239:         *                  epsilon
        !           240:         * row_elem     ::= [\t\ ]*[:alpha:]+
        !           241:         */
        !           242:
        !           243:        switch (tbl_next(p, pos)) {
        !           244:        case (TBL_TOK_TAB):
        !           245:                /* FALLTHROUGH */
        !           246:        case (TBL_TOK_SPACE):
        !           247:                goto again;
        !           248:        case (TBL_TOK_WORD):
        !           249:                if ( ! cell(tbl, rp, f, ln, sv))
        !           250:                        return(0);
        !           251:                goto again;
        !           252:        case (TBL_TOK_COMMA):
        !           253:                if (NULL == TAILQ_FIRST(&rp->cell))
        !           254:                        return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
        !           255:                return(row(tbl, f, ln, p, pos));
        !           256:        case (TBL_TOK_PERIOD):
        !           257:                if (NULL == TAILQ_FIRST(&rp->cell))
        !           258:                        return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
        !           259:                tbl->part = TBL_PART_DATA;
        !           260:                break;
        !           261:        case (TBL_TOK_NIL):
        !           262:                if (NULL == TAILQ_FIRST(&rp->cell))
        !           263:                        return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
        !           264:                break;
        !           265:        default:
        !           266:                return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
        !           267:        }
        !           268:
        !           269:        return(1);
        !           270: }
        !           271:
        !           272:
        !           273: int
        !           274: tbl_layout(struct tbl *tbl, const char *f, int ln, const char *p)
        !           275: {
        !           276:        int              pos;
        !           277:
        !           278:        pos = 0;
        !           279:        return(row(tbl, f, ln, p, &pos));
        !           280: }