[BACK]Return to tbl_layout.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/tbl_layout.c, Revision 1.1

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

CVSweb