[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.6

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