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

Annotation of mandoc/mandoc.c, Revision 1.14

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

CVSweb