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

Annotation of src/usr.bin/mandoc/mandoc.c, Revision 1.16

1.16    ! schwarze    1: /*     $Id: mandoc.c,v 1.15 2010/07/16 00:34:33 schwarze Exp $ */
1.1       schwarze    2: /*
1.15      schwarze    3:  * Copyright (c) 2008, 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:  */
1.2       schwarze   17: #include <sys/types.h>
                     18:
1.1       schwarze   19: #include <assert.h>
                     20: #include <ctype.h>
                     21: #include <stdlib.h>
1.4       schwarze   22: #include <stdio.h>
                     23: #include <string.h>
1.5       schwarze   24: #include <time.h>
1.1       schwarze   25:
1.14      schwarze   26: #include "mandoc.h"
1.1       schwarze   27: #include "libmandoc.h"
                     28:
1.14      schwarze   29: static int      a2time(time_t *, const char *, const char *);
1.5       schwarze   30:
                     31:
1.1       schwarze   32: int
1.14      schwarze   33: mandoc_special(char *p)
1.1       schwarze   34: {
1.16    ! schwarze   35:        int              len, i;
        !            36:        char             term;
1.14      schwarze   37:        char            *sv;
1.1       schwarze   38:
1.16    ! schwarze   39:        len = 0;
        !            40:        term = '\0';
1.14      schwarze   41:        sv = p;
                     42:
1.16    ! schwarze   43:        assert('\\' == *p);
        !            44:        p++;
1.1       schwarze   45:
1.16    ! schwarze   46:        switch (*p++) {
        !            47: #if 0
        !            48:        case ('Z'):
        !            49:                /* FALLTHROUGH */
        !            50:        case ('X'):
        !            51:                /* FALLTHROUGH */
        !            52:        case ('x'):
1.1       schwarze   53:                /* FALLTHROUGH */
1.16    ! schwarze   54:        case ('w'):
1.1       schwarze   55:                /* FALLTHROUGH */
1.16    ! schwarze   56:        case ('v'):
1.1       schwarze   57:                /* FALLTHROUGH */
1.16    ! schwarze   58:        case ('S'):
1.14      schwarze   59:                /* FALLTHROUGH */
1.16    ! schwarze   60:        case ('R'):
1.1       schwarze   61:                /* FALLTHROUGH */
1.16    ! schwarze   62:        case ('o'):
1.1       schwarze   63:                /* FALLTHROUGH */
1.16    ! schwarze   64:        case ('N'):
1.1       schwarze   65:                /* FALLTHROUGH */
1.16    ! schwarze   66:        case ('l'):
1.1       schwarze   67:                /* FALLTHROUGH */
1.16    ! schwarze   68:        case ('L'):
1.1       schwarze   69:                /* FALLTHROUGH */
1.16    ! schwarze   70:        case ('H'):
1.13      schwarze   71:                /* FALLTHROUGH */
1.16    ! schwarze   72:        case ('h'):
1.1       schwarze   73:                /* FALLTHROUGH */
1.16    ! schwarze   74:        case ('D'):
1.1       schwarze   75:                /* FALLTHROUGH */
1.16    ! schwarze   76:        case ('C'):
1.1       schwarze   77:                /* FALLTHROUGH */
1.16    ! schwarze   78:        case ('b'):
1.1       schwarze   79:                /* FALLTHROUGH */
1.16    ! schwarze   80:        case ('B'):
1.1       schwarze   81:                /* FALLTHROUGH */
1.16    ! schwarze   82:        case ('a'):
1.14      schwarze   83:                /* FALLTHROUGH */
1.16    ! schwarze   84:        case ('A'):
        !            85:                if (*p++ != '\'')
        !            86:                        return(0);
        !            87:                term = '\'';
        !            88:                break;
        !            89: #endif
1.6       schwarze   90:        case ('s'):
1.16    ! schwarze   91:                if (ASCII_HYPH == *p)
        !            92:                        *p = '-';
        !            93:                if ('+' == *p || '-' == *p)
        !            94:                        p++;
1.6       schwarze   95:
1.16    ! schwarze   96:                i = ('s' != *(p - 1));
1.6       schwarze   97:
1.16    ! schwarze   98:                switch (*p++) {
        !            99:                case ('('):
        !           100:                        len = 2;
        !           101:                        break;
        !           102:                case ('['):
        !           103:                        term = ']';
        !           104:                        break;
        !           105:                case ('\''):
        !           106:                        term = '\'';
        !           107:                        break;
        !           108:                case ('0'):
        !           109:                        i++;
        !           110:                        /* FALLTHROUGH */
        !           111:                default:
        !           112:                        len = 1;
        !           113:                        p--;
        !           114:                        break;
1.6       schwarze  115:                }
                    116:
1.16    ! schwarze  117:                if (ASCII_HYPH == *p)
        !           118:                        *p = '-';
        !           119:                if ('+' == *p || '-' == *p) {
        !           120:                        if (i++)
        !           121:                                return(0);
        !           122:                        p++;
        !           123:                }
        !           124:
        !           125:                if (0 == i)
        !           126:                        return(0);
        !           127:                break;
        !           128: #if 0
        !           129:        case ('Y'):
        !           130:                /* FALLTHROUGH */
        !           131:        case ('V'):
        !           132:                /* FALLTHROUGH */
        !           133:        case ('$'):
        !           134:                /* FALLTHROUGH */
        !           135:        case ('n'):
        !           136:                /* FALLTHROUGH */
        !           137:        case ('k'):
        !           138:                /* FALLTHROUGH */
        !           139: #endif
        !           140:        case ('M'):
        !           141:                /* FALLTHROUGH */
        !           142:        case ('m'):
        !           143:                /* FALLTHROUGH */
1.8       schwarze  144:        case ('f'):
                    145:                /* FALLTHROUGH */
                    146:        case ('F'):
                    147:                /* FALLTHROUGH */
1.1       schwarze  148:        case ('*'):
1.16    ! schwarze  149:                switch (*p++) {
1.1       schwarze  150:                case ('('):
1.16    ! schwarze  151:                        len = 2;
        !           152:                        break;
1.1       schwarze  153:                case ('['):
1.16    ! schwarze  154:                        term = ']';
        !           155:                        break;
1.1       schwarze  156:                default:
1.16    ! schwarze  157:                        len = 1;
        !           158:                        p--;
1.1       schwarze  159:                        break;
                    160:                }
1.16    ! schwarze  161:                break;
1.1       schwarze  162:        case ('('):
1.16    ! schwarze  163:                len = 2;
        !           164:                break;
1.1       schwarze  165:        case ('['):
1.16    ! schwarze  166:                term = ']';
1.1       schwarze  167:                break;
                    168:        default:
1.16    ! schwarze  169:                len = 1;
        !           170:                p--;
        !           171:                break;
1.1       schwarze  172:        }
                    173:
1.16    ! schwarze  174:        if (term) {
        !           175:                for ( ; *p && term != *p; p++)
        !           176:                        if (ASCII_HYPH == *p)
        !           177:                                *p = '-';
        !           178:                return(*p ? (int)(p - sv) : 0);
        !           179:        }
1.1       schwarze  180:
1.16    ! schwarze  181:        for (i = 0; *p && i < len; i++, p++)
        !           182:                if (ASCII_HYPH == *p)
        !           183:                        *p = '-';
        !           184:        return(i == len ? (int)(p - sv) : 0);
1.1       schwarze  185: }
                    186:
1.4       schwarze  187:
                    188: void *
                    189: mandoc_calloc(size_t num, size_t size)
                    190: {
                    191:        void            *ptr;
                    192:
                    193:        ptr = calloc(num, size);
                    194:        if (NULL == ptr) {
                    195:                perror(NULL);
                    196:                exit(EXIT_FAILURE);
                    197:        }
                    198:
                    199:        return(ptr);
                    200: }
                    201:
                    202:
                    203: void *
                    204: mandoc_malloc(size_t size)
                    205: {
                    206:        void            *ptr;
                    207:
                    208:        ptr = malloc(size);
                    209:        if (NULL == ptr) {
                    210:                perror(NULL);
                    211:                exit(EXIT_FAILURE);
                    212:        }
                    213:
                    214:        return(ptr);
                    215: }
                    216:
                    217:
                    218: void *
                    219: mandoc_realloc(void *ptr, size_t size)
                    220: {
                    221:
                    222:        ptr = realloc(ptr, size);
                    223:        if (NULL == ptr) {
                    224:                perror(NULL);
                    225:                exit(EXIT_FAILURE);
                    226:        }
                    227:
                    228:        return(ptr);
                    229: }
                    230:
                    231:
                    232: char *
                    233: mandoc_strdup(const char *ptr)
                    234: {
                    235:        char            *p;
                    236:
                    237:        p = strdup(ptr);
                    238:        if (NULL == p) {
                    239:                perror(NULL);
                    240:                exit(EXIT_FAILURE);
                    241:        }
                    242:
                    243:        return(p);
                    244: }
1.5       schwarze  245:
                    246:
                    247: static int
                    248: a2time(time_t *t, const char *fmt, const char *p)
                    249: {
                    250:        struct tm        tm;
                    251:        char            *pp;
                    252:
                    253:        memset(&tm, 0, sizeof(struct tm));
                    254:
                    255:        pp = strptime(p, fmt, &tm);
                    256:        if (NULL != pp && '\0' == *pp) {
                    257:                *t = mktime(&tm);
                    258:                return(1);
                    259:        }
                    260:
                    261:        return(0);
                    262: }
                    263:
                    264:
                    265: /*
                    266:  * Convert from a manual date string (see mdoc(7) and man(7)) into a
                    267:  * date according to the stipulated date type.
                    268:  */
                    269: time_t
                    270: mandoc_a2time(int flags, const char *p)
                    271: {
                    272:        time_t           t;
                    273:
                    274:        if (MTIME_MDOCDATE & flags) {
                    275:                if (0 == strcmp(p, "$" "Mdocdate$"))
                    276:                        return(time(NULL));
                    277:                if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
                    278:                        return(t);
                    279:        }
                    280:
                    281:        if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags)
                    282:                if (a2time(&t, "%b %d, %Y", p))
                    283:                        return(t);
                    284:
                    285:        if (MTIME_ISO_8601 & flags)
                    286:                if (a2time(&t, "%Y-%m-%d", p))
                    287:                        return(t);
                    288:
                    289:        if (MTIME_REDUCED & flags) {
                    290:                if (a2time(&t, "%d, %Y", p))
                    291:                        return(t);
                    292:                if (a2time(&t, "%Y", p))
                    293:                        return(t);
                    294:        }
                    295:
                    296:        return(0);
                    297: }
                    298:
1.9       schwarze  299:
                    300: int
1.15      schwarze  301: mandoc_eos(const char *p, size_t sz, int enclosed)
1.9       schwarze  302: {
1.15      schwarze  303:        const char *q;
1.16    ! schwarze  304:        int found;
1.9       schwarze  305:
1.10      schwarze  306:        if (0 == sz)
                    307:                return(0);
1.9       schwarze  308:
1.11      schwarze  309:        /*
                    310:         * End-of-sentence recognition must include situations where
                    311:         * some symbols, such as `)', allow prior EOS punctuation to
                    312:         * propogate outward.
                    313:         */
                    314:
1.16    ! schwarze  315:        found = 0;
        !           316:        for (q = p + (int)sz - 1; q >= p; q--) {
1.15      schwarze  317:                switch (*q) {
1.11      schwarze  318:                case ('\"'):
                    319:                        /* FALLTHROUGH */
                    320:                case ('\''):
                    321:                        /* FALLTHROUGH */
                    322:                case (']'):
                    323:                        /* FALLTHROUGH */
                    324:                case (')'):
1.15      schwarze  325:                        if (0 == found)
                    326:                                enclosed = 1;
1.11      schwarze  327:                        break;
                    328:                case ('.'):
                    329:                        /* FALLTHROUGH */
                    330:                case ('!'):
                    331:                        /* FALLTHROUGH */
                    332:                case ('?'):
1.15      schwarze  333:                        found = 1;
                    334:                        break;
1.11      schwarze  335:                default:
1.15      schwarze  336:                        return(found && (!enclosed || isalnum(*q)));
1.11      schwarze  337:                }
1.9       schwarze  338:        }
                    339:
1.15      schwarze  340:        return(found && !enclosed);
1.12      schwarze  341: }
                    342:
                    343:
                    344: int
                    345: mandoc_hyph(const char *start, const char *c)
                    346: {
                    347:
                    348:        /*
                    349:         * Choose whether to break at a hyphenated character.  We only
                    350:         * do this if it's free-standing within a word.
                    351:         */
                    352:
                    353:        /* Skip first/last character of buffer. */
                    354:        if (c == start || '\0' == *(c + 1))
                    355:                return(0);
                    356:        /* Skip first/last character of word. */
                    357:        if ('\t' == *(c + 1) || '\t' == *(c - 1))
                    358:                return(0);
                    359:        if (' ' == *(c + 1) || ' ' == *(c - 1))
                    360:                return(0);
                    361:        /* Skip double invocations. */
                    362:        if ('-' == *(c + 1) || '-' == *(c - 1))
                    363:                return(0);
                    364:        /* Skip escapes. */
                    365:        if ('\\' == *(c - 1))
                    366:                return(0);
                    367:
                    368:        return(1);
1.9       schwarze  369: }