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

Annotation of mandoc/man.c, Revision 1.133

1.133   ! schwarze    1: /*     $Id: man.c,v 1.132 2014/07/07 19:18:15 schwarze Exp $ */
1.1       kristaps    2: /*
1.102     schwarze    3:  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.123     schwarze    4:  * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
1.124     schwarze    5:  * Copyright (c) 2011 Joerg Sonnenberger <joerg@netbsd.org>
1.1       kristaps    6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
1.18      kristaps    8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
1.1       kristaps   10:  *
1.18      kristaps   11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1       kristaps   18:  */
1.47      kristaps   19: #ifdef HAVE_CONFIG_H
                     20: #include "config.h"
                     21: #endif
                     22:
1.41      kristaps   23: #include <sys/types.h>
                     24:
1.1       kristaps   25: #include <assert.h>
1.126     schwarze   26: #include <ctype.h>
1.1       kristaps   27: #include <stdarg.h>
                     28: #include <stdlib.h>
                     29: #include <stdio.h>
                     30: #include <string.h>
                     31:
1.105     kristaps   32: #include "man.h"
1.74      kristaps   33: #include "mandoc.h"
1.125     schwarze   34: #include "mandoc_aux.h"
1.1       kristaps   35: #include "libman.h"
1.45      kristaps   36: #include "libmandoc.h"
1.1       kristaps   37:
1.129     schwarze   38: const  char *const __man_macronames[MAN_MAX] = {
1.21      kristaps   39:        "br",           "TH",           "SH",           "SS",
1.129     schwarze   40:        "TP",           "LP",           "PP",           "P",
1.1       kristaps   41:        "IP",           "HP",           "SM",           "SB",
                     42:        "BI",           "IB",           "BR",           "RB",
1.11      kristaps   43:        "R",            "B",            "I",            "IR",
1.92      kristaps   44:        "RI",           "na",           "sp",           "nf",
                     45:        "fi",           "RE",           "RS",           "DT",
                     46:        "UC",           "PD",           "AT",           "in",
1.120     schwarze   47:        "ft",           "OP",           "EX",           "EE",
1.128     schwarze   48:        "UR",           "UE",           "ll"
1.1       kristaps   49:        };
                     50:
                     51: const  char * const *man_macronames = __man_macronames;
                     52:
1.129     schwarze   53: static struct man_node *man_node_alloc(struct man *, int, int,
1.53      kristaps   54:                                enum man_type, enum mant);
1.129     schwarze   55: static int              man_node_append(struct man *,
1.1       kristaps   56:                                struct man_node *);
1.54      kristaps   57: static void             man_node_free(struct man_node *);
1.129     schwarze   58: static void             man_node_unlink(struct man *,
1.54      kristaps   59:                                struct man_node *);
1.72      kristaps   60: static int              man_ptext(struct man *, int, char *, int);
1.79      kristaps   61: static int              man_pmacro(struct man *, int, char *, int);
1.2       kristaps   62: static void             man_free1(struct man *);
1.45      kristaps   63: static void             man_alloc1(struct man *);
1.94      kristaps   64: static int              man_descope(struct man *, int, int);
1.1       kristaps   65:
                     66:
                     67: const struct man_node *
1.119     schwarze   68: man_node(const struct man *man)
1.1       kristaps   69: {
                     70:
1.119     schwarze   71:        assert( ! (MAN_HALT & man->flags));
                     72:        return(man->first);
1.1       kristaps   73: }
                     74:
                     75: const struct man_meta *
1.119     schwarze   76: man_meta(const struct man *man)
1.1       kristaps   77: {
                     78:
1.119     schwarze   79:        assert( ! (MAN_HALT & man->flags));
                     80:        return(&man->meta);
1.1       kristaps   81: }
                     82:
1.45      kristaps   83: void
1.1       kristaps   84: man_reset(struct man *man)
                     85: {
                     86:
1.2       kristaps   87:        man_free1(man);
1.45      kristaps   88:        man_alloc1(man);
1.1       kristaps   89: }
                     90:
                     91: void
                     92: man_free(struct man *man)
                     93: {
                     94:
1.2       kristaps   95:        man_free1(man);
1.1       kristaps   96:        free(man);
                     97: }
                     98:
                     99: struct man *
1.123     schwarze  100: man_alloc(struct roff *roff, struct mparse *parse, int quick)
1.1       kristaps  101: {
                    102:        struct man      *p;
                    103:
1.45      kristaps  104:        p = mandoc_calloc(1, sizeof(struct man));
1.2       kristaps  105:
1.40      kristaps  106:        man_hash_init();
1.104     kristaps  107:        p->parse = parse;
1.123     schwarze  108:        p->quick = quick;
1.108     kristaps  109:        p->roff = roff;
1.45      kristaps  110:
                    111:        man_alloc1(p);
1.1       kristaps  112:        return(p);
                    113: }
                    114:
                    115: int
1.119     schwarze  116: man_endparse(struct man *man)
1.1       kristaps  117: {
                    118:
1.119     schwarze  119:        assert( ! (MAN_HALT & man->flags));
                    120:        if (man_macroend(man))
1.3       kristaps  121:                return(1);
1.119     schwarze  122:        man->flags |= MAN_HALT;
1.3       kristaps  123:        return(0);
1.1       kristaps  124: }
                    125:
                    126: int
1.119     schwarze  127: man_parseln(struct man *man, int ln, char *buf, int offs)
1.1       kristaps  128: {
                    129:
1.119     schwarze  130:        man->flags |= MAN_NEWLINE;
1.97      kristaps  131:
1.119     schwarze  132:        assert( ! (MAN_HALT & man->flags));
1.107     kristaps  133:
1.119     schwarze  134:        return (roff_getcontrol(man->roff, buf, &offs) ?
1.129     schwarze  135:            man_pmacro(man, ln, buf, offs) :
                    136:            man_ptext(man, ln, buf, offs));
1.1       kristaps  137: }
                    138:
1.2       kristaps  139: static void
                    140: man_free1(struct man *man)
                    141: {
                    142:
                    143:        if (man->first)
1.54      kristaps  144:                man_node_delete(man, man->first);
1.2       kristaps  145:        if (man->meta.title)
                    146:                free(man->meta.title);
1.6       kristaps  147:        if (man->meta.source)
                    148:                free(man->meta.source);
1.102     schwarze  149:        if (man->meta.date)
                    150:                free(man->meta.date);
1.2       kristaps  151:        if (man->meta.vol)
                    152:                free(man->meta.vol);
1.68      kristaps  153:        if (man->meta.msec)
                    154:                free(man->meta.msec);
1.2       kristaps  155: }
                    156:
1.45      kristaps  157: static void
1.119     schwarze  158: man_alloc1(struct man *man)
1.2       kristaps  159: {
                    160:
1.119     schwarze  161:        memset(&man->meta, 0, sizeof(struct man_meta));
                    162:        man->flags = 0;
                    163:        man->last = mandoc_calloc(1, sizeof(struct man_node));
                    164:        man->first = man->last;
                    165:        man->last->type = MAN_ROOT;
                    166:        man->last->tok = MAN_MAX;
                    167:        man->next = MAN_NEXT_CHILD;
1.2       kristaps  168: }
                    169:
                    170:
1.1       kristaps  171: static int
                    172: man_node_append(struct man *man, struct man_node *p)
                    173: {
                    174:
                    175:        assert(man->last);
                    176:        assert(man->first);
                    177:        assert(MAN_ROOT != p->type);
                    178:
                    179:        switch (man->next) {
1.129     schwarze  180:        case MAN_NEXT_SIBLING:
1.1       kristaps  181:                man->last->next = p;
                    182:                p->prev = man->last;
                    183:                p->parent = man->last->parent;
                    184:                break;
1.129     schwarze  185:        case MAN_NEXT_CHILD:
1.1       kristaps  186:                man->last->child = p;
                    187:                p->parent = man->last;
                    188:                break;
                    189:        default:
                    190:                abort();
                    191:                /* NOTREACHED */
                    192:        }
1.129     schwarze  193:
1.54      kristaps  194:        assert(p->parent);
1.22      kristaps  195:        p->parent->nchild++;
1.1       kristaps  196:
1.29      kristaps  197:        if ( ! man_valid_pre(man, p))
                    198:                return(0);
                    199:
                    200:        switch (p->type) {
1.129     schwarze  201:        case MAN_HEAD:
1.29      kristaps  202:                assert(MAN_BLOCK == p->parent->type);
                    203:                p->parent->head = p;
                    204:                break;
1.129     schwarze  205:        case MAN_TAIL:
1.106     kristaps  206:                assert(MAN_BLOCK == p->parent->type);
                    207:                p->parent->tail = p;
                    208:                break;
1.129     schwarze  209:        case MAN_BODY:
1.29      kristaps  210:                assert(MAN_BLOCK == p->parent->type);
                    211:                p->parent->body = p;
                    212:                break;
                    213:        default:
                    214:                break;
                    215:        }
                    216:
1.2       kristaps  217:        man->last = p;
                    218:
1.1       kristaps  219:        switch (p->type) {
1.129     schwarze  220:        case MAN_TBL:
1.94      kristaps  221:                /* FALLTHROUGH */
1.129     schwarze  222:        case MAN_TEXT:
1.2       kristaps  223:                if ( ! man_valid_post(man))
                    224:                        return(0);
1.1       kristaps  225:                break;
                    226:        default:
                    227:                break;
                    228:        }
                    229:
                    230:        return(1);
                    231: }
                    232:
                    233: static struct man_node *
1.129     schwarze  234: man_node_alloc(struct man *man, int line, int pos,
1.97      kristaps  235:                enum man_type type, enum mant tok)
1.1       kristaps  236: {
                    237:        struct man_node *p;
                    238:
1.45      kristaps  239:        p = mandoc_calloc(1, sizeof(struct man_node));
1.1       kristaps  240:        p->line = line;
                    241:        p->pos = pos;
                    242:        p->type = type;
1.16      kristaps  243:        p->tok = tok;
1.97      kristaps  244:
1.119     schwarze  245:        if (MAN_NEWLINE & man->flags)
1.97      kristaps  246:                p->flags |= MAN_LINE;
1.119     schwarze  247:        man->flags &= ~MAN_NEWLINE;
1.1       kristaps  248:        return(p);
                    249: }
                    250:
                    251: int
1.119     schwarze  252: man_elem_alloc(struct man *man, int line, int pos, enum mant tok)
1.1       kristaps  253: {
                    254:        struct man_node *p;
                    255:
1.119     schwarze  256:        p = man_node_alloc(man, line, pos, MAN_ELEM, tok);
                    257:        if ( ! man_node_append(man, p))
1.106     kristaps  258:                return(0);
1.119     schwarze  259:        man->next = MAN_NEXT_CHILD;
1.106     kristaps  260:        return(1);
                    261: }
                    262:
                    263: int
1.119     schwarze  264: man_tail_alloc(struct man *man, int line, int pos, enum mant tok)
1.106     kristaps  265: {
                    266:        struct man_node *p;
                    267:
1.119     schwarze  268:        p = man_node_alloc(man, line, pos, MAN_TAIL, tok);
                    269:        if ( ! man_node_append(man, p))
1.30      kristaps  270:                return(0);
1.119     schwarze  271:        man->next = MAN_NEXT_CHILD;
1.30      kristaps  272:        return(1);
1.1       kristaps  273: }
                    274:
                    275: int
1.119     schwarze  276: man_head_alloc(struct man *man, int line, int pos, enum mant tok)
1.29      kristaps  277: {
                    278:        struct man_node *p;
                    279:
1.119     schwarze  280:        p = man_node_alloc(man, line, pos, MAN_HEAD, tok);
                    281:        if ( ! man_node_append(man, p))
1.29      kristaps  282:                return(0);
1.119     schwarze  283:        man->next = MAN_NEXT_CHILD;
1.29      kristaps  284:        return(1);
                    285: }
                    286:
                    287: int
1.119     schwarze  288: man_body_alloc(struct man *man, int line, int pos, enum mant tok)
1.29      kristaps  289: {
                    290:        struct man_node *p;
                    291:
1.119     schwarze  292:        p = man_node_alloc(man, line, pos, MAN_BODY, tok);
                    293:        if ( ! man_node_append(man, p))
1.29      kristaps  294:                return(0);
1.119     schwarze  295:        man->next = MAN_NEXT_CHILD;
1.29      kristaps  296:        return(1);
                    297: }
                    298:
                    299: int
1.119     schwarze  300: man_block_alloc(struct man *man, int line, int pos, enum mant tok)
1.29      kristaps  301: {
                    302:        struct man_node *p;
                    303:
1.119     schwarze  304:        p = man_node_alloc(man, line, pos, MAN_BLOCK, tok);
                    305:        if ( ! man_node_append(man, p))
1.29      kristaps  306:                return(0);
1.119     schwarze  307:        man->next = MAN_NEXT_CHILD;
1.29      kristaps  308:        return(1);
                    309: }
                    310:
1.61      kristaps  311: int
1.119     schwarze  312: man_word_alloc(struct man *man, int line, int pos, const char *word)
1.1       kristaps  313: {
1.31      kristaps  314:        struct man_node *n;
1.1       kristaps  315:
1.119     schwarze  316:        n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX);
                    317:        n->string = roff_strdup(man->roff, word);
1.31      kristaps  318:
1.119     schwarze  319:        if ( ! man_node_append(man, n))
1.30      kristaps  320:                return(0);
1.61      kristaps  321:
1.119     schwarze  322:        man->next = MAN_NEXT_SIBLING;
1.30      kristaps  323:        return(1);
1.1       kristaps  324: }
                    325:
1.54      kristaps  326: /*
                    327:  * Free all of the resources held by a node.  This does NOT unlink a
                    328:  * node from its context; for that, see man_node_unlink().
                    329:  */
                    330: static void
1.1       kristaps  331: man_node_free(struct man_node *p)
                    332: {
                    333:
                    334:        if (p->string)
                    335:                free(p->string);
                    336:        free(p);
                    337: }
                    338:
                    339: void
1.119     schwarze  340: man_node_delete(struct man *man, struct man_node *p)
1.1       kristaps  341: {
                    342:
1.54      kristaps  343:        while (p->child)
1.119     schwarze  344:                man_node_delete(man, p->child);
1.54      kristaps  345:
1.119     schwarze  346:        man_node_unlink(man, p);
1.1       kristaps  347:        man_node_free(p);
                    348: }
                    349:
1.101     kristaps  350: int
1.119     schwarze  351: man_addeqn(struct man *man, const struct eqn *ep)
1.101     kristaps  352: {
                    353:        struct man_node *n;
                    354:
1.119     schwarze  355:        assert( ! (MAN_HALT & man->flags));
1.101     kristaps  356:
1.119     schwarze  357:        n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
1.101     kristaps  358:        n->eqn = ep;
                    359:
1.119     schwarze  360:        if ( ! man_node_append(man, n))
1.101     kristaps  361:                return(0);
                    362:
1.119     schwarze  363:        man->next = MAN_NEXT_SIBLING;
                    364:        return(man_descope(man, ep->ln, ep->pos));
1.101     kristaps  365: }
1.1       kristaps  366:
1.94      kristaps  367: int
1.119     schwarze  368: man_addspan(struct man *man, const struct tbl_span *sp)
1.94      kristaps  369: {
1.100     kristaps  370:        struct man_node *n;
1.94      kristaps  371:
1.119     schwarze  372:        assert( ! (MAN_HALT & man->flags));
1.100     kristaps  373:
1.119     schwarze  374:        n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
1.100     kristaps  375:        n->span = sp;
                    376:
1.119     schwarze  377:        if ( ! man_node_append(man, n))
1.94      kristaps  378:                return(0);
1.100     kristaps  379:
1.119     schwarze  380:        man->next = MAN_NEXT_SIBLING;
                    381:        return(man_descope(man, sp->line, 0));
1.94      kristaps  382: }
                    383:
                    384: static int
1.119     schwarze  385: man_descope(struct man *man, int line, int offs)
1.94      kristaps  386: {
                    387:        /*
                    388:         * Co-ordinate what happens with having a next-line scope open:
                    389:         * first close out the element scope (if applicable), then close
                    390:         * out the block scope (also if applicable).
                    391:         */
                    392:
1.119     schwarze  393:        if (MAN_ELINE & man->flags) {
                    394:                man->flags &= ~MAN_ELINE;
1.132     schwarze  395:                if ( ! man_unscope(man, man->last->parent))
1.94      kristaps  396:                        return(0);
                    397:        }
                    398:
1.119     schwarze  399:        if ( ! (MAN_BLINE & man->flags))
1.94      kristaps  400:                return(1);
1.119     schwarze  401:        man->flags &= ~MAN_BLINE;
1.94      kristaps  402:
1.132     schwarze  403:        if ( ! man_unscope(man, man->last->parent))
1.94      kristaps  404:                return(0);
1.119     schwarze  405:        return(man_body_alloc(man, line, offs, man->last->tok));
1.94      kristaps  406: }
                    407:
1.1       kristaps  408: static int
1.119     schwarze  409: man_ptext(struct man *man, int line, char *buf, int offs)
1.1       kristaps  410: {
1.61      kristaps  411:        int              i;
1.60      kristaps  412:
1.35      kristaps  413:        /* Literal free-form text whitespace is preserved. */
                    414:
1.119     schwarze  415:        if (MAN_LITERAL & man->flags) {
                    416:                if ( ! man_word_alloc(man, line, offs, buf + offs))
1.35      kristaps  417:                        return(0);
1.119     schwarze  418:                return(man_descope(man, line, offs));
1.35      kristaps  419:        }
                    420:
1.72      kristaps  421:        for (i = offs; ' ' == buf[i]; i++)
1.31      kristaps  422:                /* Skip leading whitespace. */ ;
1.48      kristaps  423:
1.121     schwarze  424:        /*
                    425:         * Blank lines are ignored right after headings
                    426:         * but add a single vertical space elsewhere.
                    427:         */
                    428:
1.49      kristaps  429:        if ('\0' == buf[i]) {
1.61      kristaps  430:                /* Allocate a blank entry. */
1.121     schwarze  431:                if (MAN_SH != man->last->tok &&
                    432:                    MAN_SS != man->last->tok) {
                    433:                        if ( ! man_elem_alloc(man, line, offs, MAN_sp))
                    434:                                return(0);
                    435:                        man->next = MAN_NEXT_SIBLING;
                    436:                }
1.118     schwarze  437:                return(1);
1.31      kristaps  438:        }
                    439:
1.129     schwarze  440:        /*
1.63      kristaps  441:         * Warn if the last un-escaped character is whitespace. Then
1.129     schwarze  442:         * strip away the remaining spaces (tabs stay!).
1.63      kristaps  443:         */
1.29      kristaps  444:
1.61      kristaps  445:        i = (int)strlen(buf);
                    446:        assert(i);
1.49      kristaps  447:
1.63      kristaps  448:        if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
1.64      kristaps  449:                if (i > 1 && '\\' != buf[i - 2])
1.131     schwarze  450:                        mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
                    451:                            line, i - 1, NULL);
1.63      kristaps  452:
                    453:                for (--i; i && ' ' == buf[i]; i--)
                    454:                        /* Spin back to non-space. */ ;
                    455:
                    456:                /* Jump ahead of escaped whitespace. */
                    457:                i += '\\' == buf[i] ? 2 : 1;
                    458:
                    459:                buf[i] = '\0';
                    460:        }
1.49      kristaps  461:
1.119     schwarze  462:        if ( ! man_word_alloc(man, line, offs, buf + offs))
1.1       kristaps  463:                return(0);
1.65      kristaps  464:
                    465:        /*
                    466:         * End-of-sentence check.  If the last character is an unescaped
                    467:         * EOS character, then flag the node as being the end of a
                    468:         * sentence.  The front-end will know how to interpret this.
                    469:         */
1.67      kristaps  470:
1.65      kristaps  471:        assert(i);
1.122     schwarze  472:        if (mandoc_eos(buf, (size_t)i))
1.119     schwarze  473:                man->last->flags |= MAN_EOS;
1.31      kristaps  474:
1.119     schwarze  475:        return(man_descope(man, line, offs));
1.1       kristaps  476: }
                    477:
1.96      kristaps  478: static int
1.119     schwarze  479: man_pmacro(struct man *man, int ln, char *buf, int offs)
1.1       kristaps  480: {
1.107     kristaps  481:        int              i, ppos;
1.53      kristaps  482:        enum mant        tok;
1.34      kristaps  483:        char             mac[5];
                    484:        struct man_node *n;
1.1       kristaps  485:
1.107     kristaps  486:        if ('"' == buf[offs]) {
1.131     schwarze  487:                mandoc_msg(MANDOCERR_COMMENT_BAD, man->parse,
                    488:                    ln, offs, NULL);
1.107     kristaps  489:                return(1);
                    490:        } else if ('\0' == buf[offs])
1.46      kristaps  491:                return(1);
1.1       kristaps  492:
1.107     kristaps  493:        ppos = offs;
1.9       kristaps  494:
1.56      kristaps  495:        /*
1.107     kristaps  496:         * Copy the first word into a nil-terminated buffer.
                    497:         * Stop copying when a tab, space, or eoln is encountered.
1.56      kristaps  498:         */
1.62      kristaps  499:
1.107     kristaps  500:        i = 0;
1.129     schwarze  501:        while (i < 4 && '\0' != buf[offs] && ' ' != buf[offs] &&
                    502:            '\t' != buf[offs])
1.107     kristaps  503:                mac[i++] = buf[offs++];
1.10      kristaps  504:
1.107     kristaps  505:        mac[i] = '\0';
1.1       kristaps  506:
1.107     kristaps  507:        tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
1.1       kristaps  508:
1.87      schwarze  509:        if (MAN_MAX == tok) {
1.129     schwarze  510:                mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln, ppos,
                    511:                    "%s", buf + ppos - 1);
1.12      kristaps  512:                return(1);
1.1       kristaps  513:        }
                    514:
                    515:        /* The macro is sane.  Jump to the next word. */
                    516:
1.107     kristaps  517:        while (buf[offs] && ' ' == buf[offs])
                    518:                offs++;
1.1       kristaps  519:
1.129     schwarze  520:        /*
1.62      kristaps  521:         * Trailing whitespace.  Note that tabs are allowed to be passed
                    522:         * into the parser as "text", so we only warn about spaces here.
                    523:         */
1.48      kristaps  524:
1.107     kristaps  525:        if ('\0' == buf[offs] && ' ' == buf[offs - 1])
1.131     schwarze  526:                mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
                    527:                    ln, offs - 1, NULL);
1.48      kristaps  528:
1.129     schwarze  529:        /*
1.90      kristaps  530:         * Remove prior ELINE macro, as it's being clobbered by a new
1.51      kristaps  531:         * macro.  Note that NSCOPED macros do not close out ELINE
                    532:         * macros---they don't print text---so we let those slip by.
1.50      kristaps  533:         */
1.34      kristaps  534:
1.53      kristaps  535:        if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
1.119     schwarze  536:                        man->flags & MAN_ELINE) {
                    537:                n = man->last;
1.90      kristaps  538:                assert(MAN_TEXT != n->type);
1.51      kristaps  539:
1.90      kristaps  540:                /* Remove repeated NSCOPED macros causing ELINE. */
1.51      kristaps  541:
1.90      kristaps  542:                if (MAN_NSCOPED & man_macros[n->tok].flags)
                    543:                        n = n->parent;
1.51      kristaps  544:
1.133   ! schwarze  545:                mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
1.113     schwarze  546:                    n->pos, "%s breaks %s", man_macronames[tok],
                    547:                    man_macronames[n->tok]);
1.34      kristaps  548:
1.119     schwarze  549:                man_node_delete(man, n);
                    550:                man->flags &= ~MAN_ELINE;
1.113     schwarze  551:        }
                    552:
                    553:        /*
                    554:         * Remove prior BLINE macro that is being clobbered.
                    555:         */
1.119     schwarze  556:        if ((man->flags & MAN_BLINE) &&
1.113     schwarze  557:            (MAN_BSCOPE & man_macros[tok].flags)) {
1.119     schwarze  558:                n = man->last;
1.114     joerg     559:
                    560:                /* Might be a text node like 8 in
                    561:                 * .TP 8
                    562:                 * .SH foo
                    563:                 */
                    564:                if (MAN_TEXT == n->type)
                    565:                        n = n->parent;
1.113     schwarze  566:
                    567:                /* Remove element that didn't end BLINE, if any. */
                    568:                if ( ! (MAN_BSCOPE & man_macros[n->tok].flags))
                    569:                        n = n->parent;
                    570:
                    571:                assert(MAN_HEAD == n->type);
                    572:                n = n->parent;
                    573:                assert(MAN_BLOCK == n->type);
                    574:                assert(MAN_SCOPED & man_macros[n->tok].flags);
                    575:
1.133   ! schwarze  576:                mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
1.113     schwarze  577:                    n->pos, "%s breaks %s", man_macronames[tok],
                    578:                    man_macronames[n->tok]);
                    579:
1.119     schwarze  580:                man_node_delete(man, n);
                    581:                man->flags &= ~MAN_BLINE;
1.34      kristaps  582:        }
                    583:
1.59      kristaps  584:        /*
                    585:         * Save the fact that we're in the next-line for a block.  In
                    586:         * this way, embedded roff instructions can "remember" state
                    587:         * when they exit.
                    588:         */
                    589:
1.119     schwarze  590:        if (MAN_BLINE & man->flags)
                    591:                man->flags |= MAN_BPLINE;
1.59      kristaps  592:
                    593:        /* Call to handler... */
1.1       kristaps  594:
1.53      kristaps  595:        assert(man_macros[tok].fp);
1.119     schwarze  596:        if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
1.1       kristaps  597:                goto err;
1.123     schwarze  598:
                    599:        /* In quick mode (for mandocdb), abort after the NAME section. */
                    600:
1.130     schwarze  601:        if (man->quick && MAN_SH == tok) {
                    602:                n = man->last;
                    603:                if (MAN_BODY == n->type &&
                    604:                    strcmp(n->prev->child->string, "NAME"))
                    605:                        return(2);
                    606:        }
1.1       kristaps  607:
1.129     schwarze  608:        /*
1.50      kristaps  609:         * We weren't in a block-line scope when entering the
                    610:         * above-parsed macro, so return.
                    611:         */
                    612:
1.119     schwarze  613:        if ( ! (MAN_BPLINE & man->flags)) {
1.129     schwarze  614:                man->flags &= ~MAN_ILINE;
1.29      kristaps  615:                return(1);
1.50      kristaps  616:        }
1.119     schwarze  617:        man->flags &= ~MAN_BPLINE;
1.50      kristaps  618:
                    619:        /*
                    620:         * If we're in a block scope, then allow this macro to slip by
                    621:         * without closing scope around it.
                    622:         */
                    623:
1.119     schwarze  624:        if (MAN_ILINE & man->flags) {
                    625:                man->flags &= ~MAN_ILINE;
1.50      kristaps  626:                return(1);
                    627:        }
1.29      kristaps  628:
1.129     schwarze  629:        /*
1.29      kristaps  630:         * If we've opened a new next-line element scope, then return
                    631:         * now, as the next line will close out the block scope.
                    632:         */
                    633:
1.119     schwarze  634:        if (MAN_ELINE & man->flags)
1.29      kristaps  635:                return(1);
                    636:
                    637:        /* Close out the block scope opened in the prior line.  */
1.11      kristaps  638:
1.119     schwarze  639:        assert(MAN_BLINE & man->flags);
                    640:        man->flags &= ~MAN_BLINE;
1.11      kristaps  641:
1.132     schwarze  642:        if ( ! man_unscope(man, man->last->parent))
1.29      kristaps  643:                return(0);
1.119     schwarze  644:        return(man_body_alloc(man, ln, ppos, man->last->tok));
1.1       kristaps  645:
                    646: err:   /* Error out. */
                    647:
1.119     schwarze  648:        man->flags |= MAN_HALT;
1.1       kristaps  649:        return(0);
                    650: }
1.51      kristaps  651:
1.54      kristaps  652: /*
1.119     schwarze  653:  * Unlink a node from its context.  If "man" is provided, the last parse
1.54      kristaps  654:  * point will also be adjusted accordingly.
                    655:  */
                    656: static void
1.119     schwarze  657: man_node_unlink(struct man *man, struct man_node *n)
1.51      kristaps  658: {
                    659:
1.54      kristaps  660:        /* Adjust siblings. */
                    661:
                    662:        if (n->prev)
1.51      kristaps  663:                n->prev->next = n->next;
1.54      kristaps  664:        if (n->next)
                    665:                n->next->prev = n->prev;
                    666:
                    667:        /* Adjust parent. */
                    668:
                    669:        if (n->parent) {
                    670:                n->parent->nchild--;
                    671:                if (n->parent->child == n)
                    672:                        n->parent->child = n->prev ? n->prev : n->next;
                    673:        }
                    674:
                    675:        /* Adjust parse point, if applicable. */
                    676:
1.119     schwarze  677:        if (man && man->last == n) {
1.54      kristaps  678:                /*XXX: this can occur when bailing from validation. */
                    679:                /*assert(NULL == n->next);*/
                    680:                if (n->prev) {
1.119     schwarze  681:                        man->last = n->prev;
                    682:                        man->next = MAN_NEXT_SIBLING;
1.54      kristaps  683:                } else {
1.119     schwarze  684:                        man->last = n->parent;
                    685:                        man->next = MAN_NEXT_CHILD;
1.51      kristaps  686:                }
                    687:        }
                    688:
1.119     schwarze  689:        if (man && man->first == n)
                    690:                man->first = NULL;
1.112     kristaps  691: }
                    692:
                    693: const struct mparse *
1.119     schwarze  694: man_mparse(const struct man *man)
1.112     kristaps  695: {
                    696:
1.119     schwarze  697:        assert(man && man->parse);
                    698:        return(man->parse);
1.126     schwarze  699: }
                    700:
                    701: void
                    702: man_deroff(char **dest, const struct man_node *n)
                    703: {
                    704:        char    *cp;
                    705:        size_t   sz;
                    706:
                    707:        if (MAN_TEXT != n->type) {
                    708:                for (n = n->child; n; n = n->next)
                    709:                        man_deroff(dest, n);
                    710:                return;
                    711:        }
                    712:
1.127     schwarze  713:        /* Skip leading whitespace and escape sequences. */
1.126     schwarze  714:
1.127     schwarze  715:        cp = n->string;
                    716:        while ('\0' != *cp) {
                    717:                if ('\\' == *cp) {
                    718:                        cp++;
                    719:                        mandoc_escape((const char **)&cp, NULL, NULL);
                    720:                } else if (isspace((unsigned char)*cp))
                    721:                        cp++;
                    722:                else
1.126     schwarze  723:                        break;
1.127     schwarze  724:        }
1.126     schwarze  725:
                    726:        /* Skip trailing whitespace. */
                    727:
                    728:        for (sz = strlen(cp); sz; sz--)
                    729:                if (0 == isspace((unsigned char)cp[sz-1]))
                    730:                        break;
                    731:
                    732:        /* Skip empty strings. */
                    733:
                    734:        if (0 == sz)
                    735:                return;
                    736:
                    737:        if (NULL == *dest) {
                    738:                *dest = mandoc_strndup(cp, sz);
                    739:                return;
                    740:        }
                    741:
                    742:        mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp);
                    743:        free(*dest);
                    744:        *dest = cp;
1.23      kristaps  745: }

CVSweb