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

1.11    ! schwarze    1: /*     $Id: mandoc.c,v 1.10 2010/05/15 09:20:01 schwarze Exp $ */
1.1       schwarze    2: /*
                      3:  * Copyright (c) 2008, 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:  */
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:
                     26: #include "libmandoc.h"
                     27:
1.5       schwarze   28: static int      a2time(time_t *, const char *, const char *);
                     29:
                     30:
1.1       schwarze   31: int
                     32: mandoc_special(const char *p)
                     33: {
1.6       schwarze   34:        int              terminator;    /* Terminator for \s. */
                     35:        int              lim;           /* Limit for N in \s. */
                     36:        int              c, i;
1.1       schwarze   37:
                     38:        if ('\\' != *p++)
                     39:                return(0);
                     40:
                     41:        switch (*p) {
                     42:        case ('\''):
                     43:                /* FALLTHROUGH */
                     44:        case ('`'):
                     45:                /* FALLTHROUGH */
                     46:        case ('q'):
                     47:                /* FALLTHROUGH */
                     48:        case ('-'):
                     49:                /* FALLTHROUGH */
                     50:        case ('~'):
                     51:                /* FALLTHROUGH */
                     52:        case ('^'):
                     53:                /* FALLTHROUGH */
                     54:        case ('%'):
                     55:                /* FALLTHROUGH */
                     56:        case ('0'):
                     57:                /* FALLTHROUGH */
                     58:        case (' '):
                     59:                /* FALLTHROUGH */
                     60:        case ('|'):
                     61:                /* FALLTHROUGH */
                     62:        case ('&'):
                     63:                /* FALLTHROUGH */
                     64:        case ('.'):
                     65:                /* FALLTHROUGH */
                     66:        case (':'):
                     67:                /* FALLTHROUGH */
1.3       schwarze   68:        case ('c'):
                     69:                return(2);
1.1       schwarze   70:        case ('e'):
                     71:                return(2);
1.6       schwarze   72:        case ('s'):
                     73:                if ('\0' == *++p)
                     74:                        return(2);
                     75:
                     76:                c = 2;
                     77:                terminator = 0;
                     78:                lim = 1;
                     79:
                     80:                if (*p == '\'') {
                     81:                        lim = 0;
                     82:                        terminator = 1;
                     83:                        ++p;
                     84:                        ++c;
                     85:                } else if (*p == '[') {
                     86:                        lim = 0;
                     87:                        terminator = 2;
                     88:                        ++p;
                     89:                        ++c;
                     90:                } else if (*p == '(') {
                     91:                        lim = 2;
                     92:                        terminator = 3;
                     93:                        ++p;
                     94:                        ++c;
                     95:                }
                     96:
                     97:                if (*p == '+' || *p == '-') {
                     98:                        ++p;
                     99:                        ++c;
                    100:                }
                    101:
                    102:                if (*p == '\'') {
                    103:                        if (terminator)
                    104:                                return(0);
                    105:                        lim = 0;
                    106:                        terminator = 1;
                    107:                        ++p;
                    108:                        ++c;
                    109:                } else if (*p == '[') {
                    110:                        if (terminator)
                    111:                                return(0);
                    112:                        lim = 0;
                    113:                        terminator = 2;
                    114:                        ++p;
                    115:                        ++c;
                    116:                } else if (*p == '(') {
                    117:                        if (terminator)
                    118:                                return(0);
                    119:                        lim = 2;
                    120:                        terminator = 3;
                    121:                        ++p;
                    122:                        ++c;
                    123:                }
                    124:
                    125:                /* TODO: needs to handle floating point. */
                    126:
                    127:                if ( ! isdigit((u_char)*p))
                    128:                        return(0);
                    129:
                    130:                for (i = 0; isdigit((u_char)*p); i++) {
                    131:                        if (lim && i >= lim)
                    132:                                break;
                    133:                        ++p;
                    134:                        ++c;
                    135:                }
                    136:
                    137:                if (terminator && terminator < 3) {
                    138:                        if (1 == terminator && *p != '\'')
                    139:                                return(0);
                    140:                        if (2 == terminator && *p != ']')
                    141:                                return(0);
                    142:                        ++p;
                    143:                        ++c;
                    144:                }
                    145:
                    146:                return(c);
1.8       schwarze  147:        case ('f'):
                    148:                /* FALLTHROUGH */
                    149:        case ('F'):
                    150:                /* FALLTHROUGH */
1.1       schwarze  151:        case ('*'):
                    152:                if (0 == *++p || ! isgraph((u_char)*p))
                    153:                        return(0);
                    154:                switch (*p) {
                    155:                case ('('):
                    156:                        if (0 == *++p || ! isgraph((u_char)*p))
                    157:                                return(0);
                    158:                        return(4);
                    159:                case ('['):
                    160:                        for (c = 3, p++; *p && ']' != *p; p++, c++)
                    161:                                if ( ! isgraph((u_char)*p))
                    162:                                        break;
                    163:                        return(*p == ']' ? c : 0);
                    164:                default:
                    165:                        break;
                    166:                }
                    167:                return(3);
                    168:        case ('('):
                    169:                if (0 == *++p || ! isgraph((u_char)*p))
                    170:                        return(0);
                    171:                if (0 == *++p || ! isgraph((u_char)*p))
                    172:                        return(0);
                    173:                return(4);
                    174:        case ('['):
                    175:                break;
                    176:        default:
                    177:                return(0);
                    178:        }
                    179:
                    180:        for (c = 3, p++; *p && ']' != *p; p++, c++)
                    181:                if ( ! isgraph((u_char)*p))
                    182:                        break;
                    183:
                    184:        return(*p == ']' ? c : 0);
                    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
                    301: mandoc_eos(const char *p, size_t sz)
                    302: {
                    303:
1.10      schwarze  304:        if (0 == sz)
                    305:                return(0);
1.9       schwarze  306:
1.11    ! schwarze  307:        /*
        !           308:         * End-of-sentence recognition must include situations where
        !           309:         * some symbols, such as `)', allow prior EOS punctuation to
        !           310:         * propogate outward.
        !           311:         */
        !           312:
        !           313:        for ( ; sz; sz--) {
        !           314:                switch (p[(int)sz - 1]) {
        !           315:                case ('\"'):
        !           316:                        /* FALLTHROUGH */
        !           317:                case ('\''):
        !           318:                        /* FALLTHROUGH */
        !           319:                case (']'):
        !           320:                        /* FALLTHROUGH */
        !           321:                case (')'):
        !           322:                        break;
        !           323:                case ('.'):
        !           324:                        /* Escaped periods. */
        !           325:                        if (sz > 1 && '\\' == p[(int)sz - 2])
        !           326:                                return(0);
        !           327:                        /* FALLTHROUGH */
        !           328:                case ('!'):
        !           329:                        /* FALLTHROUGH */
        !           330:                case ('?'):
        !           331:                        return(1);
        !           332:                default:
1.9       schwarze  333:                        return(0);
1.11    ! schwarze  334:                }
1.9       schwarze  335:        }
                    336:
1.11    ! schwarze  337:        return(0);
1.9       schwarze  338: }