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

Annotation of src/usr.bin/mandoc/out.c, Revision 1.3

1.3     ! schwarze    1: /*     $Id: out.c,v 1.2 2009/10/27 21:40:07 schwarze Exp $ */
1.1       schwarze    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/types.h>
                     18:
1.2       schwarze   19: #include <assert.h>
1.1       schwarze   20: #include <ctype.h>
                     21: #include <stdio.h>
                     22: #include <stdlib.h>
1.2       schwarze   23: #include <string.h>
                     24: #include <time.h>
1.1       schwarze   25:
                     26: #include "out.h"
                     27:
1.3     ! schwarze   28: /* See a2roffdeco(). */
        !            29: #define        C2LIM(c, l) do { \
        !            30:        (l) = 1; \
        !            31:        if ('[' == (c) || '\'' == (c)) \
        !            32:                (l) = 0; \
        !            33:        else if ('(' == (c)) \
        !            34:                (l) = 2; } \
        !            35:        while (/* CONSTCOND */ 0)
        !            36:
        !            37: /* See a2roffdeco(). */
        !            38: #define        C2TERM(c, t) do { \
        !            39:        (t) = 0; \
        !            40:        if ('\'' == (c)) \
        !            41:                (t) = 1; \
        !            42:        else if ('[' == (c)) \
        !            43:                (t) = 2; \
        !            44:        else if ('(' == (c)) \
        !            45:                (t) = 3; } \
        !            46:        while (/* CONSTCOND */ 0)
        !            47:
1.1       schwarze   48: /*
                     49:  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
                     50:  * units are documented in groff.7, mdoc.7, man.7.
                     51:  */
                     52: int
                     53: a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
                     54: {
                     55:        char             buf[BUFSIZ], hasd;
                     56:        int              i;
                     57:        enum roffscale   unit;
                     58:
                     59:        if ('\0' == *src)
                     60:                return(0);
                     61:
                     62:        i = hasd = 0;
                     63:
                     64:        switch (*src) {
                     65:        case ('+'):
                     66:                src++;
                     67:                break;
                     68:        case ('-'):
                     69:                buf[i++] = *src++;
                     70:                break;
                     71:        default:
                     72:                break;
                     73:        }
                     74:
                     75:        if ('\0' == *src)
                     76:                return(0);
                     77:
                     78:        while (i < BUFSIZ) {
                     79:                if ( ! isdigit((u_char)*src)) {
                     80:                        if ('.' != *src)
                     81:                                break;
                     82:                        else if (hasd)
                     83:                                break;
                     84:                        else
                     85:                                hasd = 1;
                     86:                }
                     87:                buf[i++] = *src++;
                     88:        }
                     89:
                     90:        if (BUFSIZ == i || (*src && *(src + 1)))
                     91:                return(0);
                     92:
                     93:        buf[i] = '\0';
                     94:
                     95:        switch (*src) {
                     96:        case ('c'):
                     97:                unit = SCALE_CM;
                     98:                break;
                     99:        case ('i'):
                    100:                unit = SCALE_IN;
                    101:                break;
                    102:        case ('P'):
                    103:                unit = SCALE_PC;
                    104:                break;
                    105:        case ('p'):
                    106:                unit = SCALE_PT;
                    107:                break;
                    108:        case ('f'):
                    109:                unit = SCALE_FS;
                    110:                break;
                    111:        case ('v'):
                    112:                unit = SCALE_VS;
                    113:                break;
                    114:        case ('m'):
                    115:                unit = SCALE_EM;
                    116:                break;
                    117:        case ('\0'):
                    118:                if (SCALE_MAX == def)
                    119:                        return(0);
                    120:                unit = SCALE_BU;
                    121:                break;
                    122:        case ('u'):
                    123:                unit = SCALE_BU;
                    124:                break;
                    125:        case ('M'):
                    126:                unit = SCALE_MM;
                    127:                break;
                    128:        case ('n'):
                    129:                unit = SCALE_EN;
                    130:                break;
                    131:        default:
                    132:                return(0);
                    133:        }
                    134:
                    135:        if ((dst->scale = atof(buf)) < 0)
                    136:                dst->scale = 0;
                    137:        dst->unit = unit;
                    138:        dst->pt = hasd;
                    139:
                    140:        return(1);
                    141: }
1.2       schwarze  142:
                    143:
                    144: /*
                    145:  * Correctly writes the time in nroff form, which differs from standard
                    146:  * form in that a space isn't printed in lieu of the extra %e field for
                    147:  * single-digit dates.
                    148:  */
                    149: void
                    150: time2a(time_t t, char *dst, size_t sz)
                    151: {
                    152:        struct tm        tm;
                    153:        char             buf[5];
                    154:        char            *p;
                    155:        size_t           nsz;
                    156:
                    157:        assert(sz > 1);
                    158:        localtime_r(&t, &tm);
                    159:
                    160:        p = dst;
                    161:        nsz = 0;
                    162:
                    163:        dst[0] = '\0';
                    164:
                    165:        if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
                    166:                return;
                    167:
                    168:        p += (int)nsz;
                    169:        sz -= nsz;
                    170:
                    171:        if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
                    172:                return;
                    173:
                    174:        nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
                    175:
                    176:        if (nsz >= sz)
                    177:                return;
                    178:
                    179:        p += (int)nsz;
                    180:        sz -= nsz;
                    181:
                    182:        (void)strftime(p, sz, "%Y", &tm);
                    183: }
                    184:
1.3     ! schwarze  185:
        !           186: /*
        !           187:  * Returns length of parsed string (the leading "\" should NOT be
        !           188:  * included).  This can be zero if the current character is the nil
        !           189:  * terminator.  "d" is set to the type of parsed decorator, which may
        !           190:  * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
        !           191:  */
        !           192: int
        !           193: a2roffdeco(enum roffdeco *d,
        !           194:                const char **word, size_t *sz)
        !           195: {
        !           196:        int              j, type, term, lim;
        !           197:        const char      *wp, *sp;
        !           198:
        !           199:        *d = DECO_NONE;
        !           200:        wp = *word;
        !           201:        type = 1;
        !           202:
        !           203:        switch (*wp) {
        !           204:        case ('\0'):
        !           205:                return(0);
        !           206:
        !           207:        case ('('):
        !           208:                if ('\0' == *(++wp))
        !           209:                        return(1);
        !           210:                if ('\0' == *(wp + 1))
        !           211:                        return(2);
        !           212:
        !           213:                *d = DECO_SPECIAL;
        !           214:                *sz = 2;
        !           215:                *word = wp;
        !           216:                return(3);
        !           217:
        !           218:        case ('*'):
        !           219:                switch (*(++wp)) {
        !           220:                case ('\0'):
        !           221:                        return(1);
        !           222:
        !           223:                case ('('):
        !           224:                        if ('\0' == *(++wp))
        !           225:                                return(2);
        !           226:                        if ('\0' == *(wp + 1))
        !           227:                                return(3);
        !           228:
        !           229:                        *d = DECO_RESERVED;
        !           230:                        *sz = 2;
        !           231:                        *word = wp;
        !           232:                        return(4);
        !           233:
        !           234:                case ('['):
        !           235:                        type = 0;
        !           236:                        break;
        !           237:
        !           238:                default:
        !           239:                        *d = DECO_RESERVED;
        !           240:                        *sz = 1;
        !           241:                        *word = wp;
        !           242:                        return(2);
        !           243:                }
        !           244:                break;
        !           245:
        !           246:        case ('s'):
        !           247:                sp = wp;
        !           248:                if ('\0' == *(++wp))
        !           249:                        return(1);
        !           250:
        !           251:                C2LIM(*wp, lim);
        !           252:                C2TERM(*wp, term);
        !           253:
        !           254:                if (term)
        !           255:                        wp++;
        !           256:
        !           257:                *word = wp;
        !           258:
        !           259:                if (*wp == '+' || *wp == '-')
        !           260:                        ++wp;
        !           261:
        !           262:                switch (*wp) {
        !           263:                case ('\''):
        !           264:                        /* FALLTHROUGH */
        !           265:                case ('['):
        !           266:                        /* FALLTHROUGH */
        !           267:                case ('('):
        !           268:                        if (term)
        !           269:                                return((int)(wp - sp));
        !           270:
        !           271:                        C2LIM(*wp, lim);
        !           272:                        C2TERM(*wp, term);
        !           273:                        wp++;
        !           274:                        break;
        !           275:                default:
        !           276:                        break;
        !           277:                }
        !           278:
        !           279:                if ( ! isdigit((u_char)*wp))
        !           280:                        return((int)(wp - sp));
        !           281:
        !           282:                for (j = 0; isdigit((u_char)*wp); j++) {
        !           283:                        if (lim && j >= lim)
        !           284:                                break;
        !           285:                        ++wp;
        !           286:                }
        !           287:
        !           288:                if (term && term < 3) {
        !           289:                        if (1 == term && *wp != '\'')
        !           290:                                return((int)(wp - sp));
        !           291:                        if (2 == term && *wp != ']')
        !           292:                                return((int)(wp - sp));
        !           293:                        ++wp;
        !           294:                }
        !           295:
        !           296:                *d = DECO_SIZE;
        !           297:                return((int)(wp - sp));
        !           298:
        !           299:        case ('f'):
        !           300:                switch (*(++wp)) {
        !           301:                case ('\0'):
        !           302:                        return(1);
        !           303:                case ('3'):
        !           304:                        /* FALLTHROUGH */
        !           305:                case ('B'):
        !           306:                        *d = DECO_BOLD;
        !           307:                        break;
        !           308:                case ('2'):
        !           309:                        /* FALLTHROUGH */
        !           310:                case ('I'):
        !           311:                        *d = DECO_ITALIC;
        !           312:                        break;
        !           313:                case ('P'):
        !           314:                        *d = DECO_PREVIOUS;
        !           315:                        break;
        !           316:                case ('1'):
        !           317:                        /* FALLTHROUGH */
        !           318:                case ('R'):
        !           319:                        *d = DECO_ROMAN;
        !           320:                        break;
        !           321:                default:
        !           322:                        break;
        !           323:                }
        !           324:
        !           325:                return(2);
        !           326:
        !           327:        case ('['):
        !           328:                break;
        !           329:
        !           330:        case ('c'):
        !           331:                *d = DECO_NOSPACE;
        !           332:                *sz = 1;
        !           333:                return(1);
        !           334:
        !           335:        default:
        !           336:                *d = DECO_SPECIAL;
        !           337:                *word = wp;
        !           338:                *sz = 1;
        !           339:                return(1);
        !           340:        }
        !           341:
        !           342:        *word = ++wp;
        !           343:        for (j = 0; *wp && ']' != *wp; wp++, j++)
        !           344:                /* Loop... */ ;
        !           345:
        !           346:        if ('\0' == *wp)
        !           347:                return(j + 1);
        !           348:
        !           349:        *d = type ? DECO_SPECIAL : DECO_RESERVED;
        !           350:        *sz = (size_t)j;
        !           351:        return (j + 2);
        !           352: }