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

Annotation of docbook2mdoc/reorg.c, Revision 1.6

1.6     ! schwarze    1: /* $Id: reorg.c,v 1.5 2019/05/01 09:02:25 schwarze Exp $ */
1.1       schwarze    2: /*
                      3:  * Copyright (c) 2019 Ingo Schwarze <schwarze@openbsd.org>
                      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 AUTHORS DISCLAIM ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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.3       schwarze   17: #include "string.h"
1.1       schwarze   18:
                     19: #include "node.h"
                     20: #include "reorg.h"
                     21:
                     22: /*
                     23:  * The implementation of the tree reorganizer.
                     24:  */
                     25:
1.2       schwarze   26: static void
1.5       schwarze   27: reorg_root(struct pnode *root, const char *sec)
1.1       schwarze   28: {
1.4       schwarze   29:        struct pnode    *date, *info, *name, *vol, *nc;
1.1       schwarze   30:
1.2       schwarze   31:        if (root == NULL)
1.1       schwarze   32:                return;
                     33:
                     34:        /* Collect prologue information. */
                     35:
                     36:        if ((date = pnode_takefirst(root, NODE_PUBDATE)) == NULL &&
                     37:            (date = pnode_takefirst(root, NODE_DATE)) == NULL) {
                     38:                date = pnode_alloc(NULL);
                     39:                pnode_alloc_text(date, "$Mdocdate" "$");
                     40:        }
                     41:        date->node = NODE_DATE;
                     42:        date->parent = root;
                     43:
                     44:        name = vol = NULL;
                     45:        if ((nc = pnode_findfirst(root, NODE_REFMETA)) != NULL) {
                     46:                name = pnode_takefirst(nc, NODE_REFENTRYTITLE);
                     47:                vol = pnode_takefirst(nc, NODE_MANVOLNUM);
                     48:        }
                     49:        if (name == NULL) {
                     50:                name = pnode_alloc(NULL);
                     51:                name->node = NODE_REFENTRYTITLE;
                     52:                name->parent = root;
                     53:                pnode_alloc_text(name,
                     54:                    pnode_getattr_raw(root, ATTRKEY_ID, "UNKNOWN"));
                     55:        }
1.5       schwarze   56:        if (vol == NULL || sec != NULL) {
                     57:                pnode_unlink(vol);
1.1       schwarze   58:                vol = pnode_alloc(NULL);
                     59:                vol->node = NODE_MANVOLNUM;
                     60:                vol->parent = root;
1.5       schwarze   61:                pnode_alloc_text(vol, sec == NULL ? "1" : sec);
1.1       schwarze   62:        }
                     63:
                     64:        /* Insert prologue information at the beginning. */
                     65:
                     66:        if (pnode_findfirst(root, NODE_REFNAMEDIV) == NULL &&
1.4       schwarze   67:            ((info = pnode_findfirst(root, NODE_BOOKINFO)) != NULL ||
                     68:             (info = pnode_findfirst(root, NODE_REFENTRYINFO)) != NULL)) {
                     69:                if ((nc = pnode_takefirst(info, NODE_ABSTRACT)) != NULL)
                     70:                        TAILQ_INSERT_HEAD(&root->childq, nc, child);
                     71:                if ((nc = pnode_takefirst(info, NODE_TITLE)) != NULL)
                     72:                        TAILQ_INSERT_HEAD(&root->childq, nc, child);
                     73:        }
1.1       schwarze   74:        TAILQ_INSERT_HEAD(&root->childq, vol, child);
                     75:        TAILQ_INSERT_HEAD(&root->childq, name, child);
                     76:        TAILQ_INSERT_HEAD(&root->childq, date, child);
1.2       schwarze   77: }
                     78:
                     79: static void
1.3       schwarze   80: reorg_refentry(struct pnode *n)
                     81: {
                     82:        struct pnode    *info, *meta, *nc, *title;
                     83:        struct pnode    *match, *later;
                     84:
                     85:        /* Collect nodes that remained behind from the prologue. */
                     86:
                     87:        meta = NULL;
                     88:        info = pnode_takefirst(n, NODE_BOOKINFO);
                     89:        if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) {
                     90:                pnode_unlink(info);
                     91:                info = NULL;
                     92:        }
                     93:        if (info == NULL) {
                     94:                info = pnode_takefirst(n, NODE_REFENTRYINFO);
                     95:                if (info != NULL && TAILQ_FIRST(&info->childq) == NULL) {
                     96:                        pnode_unlink(info);
                     97:                        info = NULL;
                     98:                }
                     99:                if (info == NULL)
                    100:                        info = pnode_takefirst(n, NODE_INFO);
                    101:                meta = pnode_takefirst(n, NODE_REFMETA);
                    102:                if (meta != NULL && TAILQ_FIRST(&meta->childq) == NULL) {
                    103:                        pnode_unlink(meta);
                    104:                        meta = NULL;
                    105:                }
                    106:        }
                    107:        if (info == NULL && meta == NULL)
                    108:                return;
                    109:
                    110:        /*
                    111:         * Find the best place to put this information.
                    112:         * Use the last existing AUTHORS node, if any.
                    113:         * Otherwise, put it behind all standard sections that
                    114:         * conventionally precede AUTHORS, and also behind any
                    115:         * non-standard sections that follow the last of these,
                    116:         * but before the next standard section.
                    117:         */
                    118:
                    119:        match = later = NULL;
                    120:        TAILQ_FOREACH(nc, &n->childq, child) {
                    121:                switch (nc->node) {
                    122:                case NODE_REFENTRY:
                    123:                case NODE_REFNAMEDIV:
                    124:                case NODE_REFSYNOPSISDIV:
                    125:                        later = NULL;
                    126:                        continue;
                    127:                case NODE_APPENDIX:
                    128:                case NODE_INDEX:
                    129:                        if (later == NULL)
                    130:                                later = nc;
                    131:                        continue;
                    132:                default:
                    133:                        break;
                    134:                }
                    135:                if ((title = pnode_findfirst(nc, NODE_TITLE)) == NULL ||
                    136:                    (title = TAILQ_FIRST(&title->childq)) == NULL ||
                    137:                    title->node != NODE_TEXT)
                    138:                        continue;
                    139:                if (strcasecmp(title->b, "AUTHORS") == 0 ||
                    140:                    strcasecmp(title->b, "AUTHOR") == 0)
                    141:                        match = nc;
                    142:                else if (strcasecmp(title->b, "NAME") == 0 ||
                    143:                    strcasecmp(title->b, "SYNOPSIS") == 0 ||
                    144:                    strcasecmp(title->b, "DESCRIPTION") == 0 ||
                    145:                    strcasecmp(title->b, "RETURN VALUES") == 0 ||
                    146:                    strcasecmp(title->b, "ENVIRONMENT") == 0 ||
                    147:                    strcasecmp(title->b, "FILES") == 0 ||
                    148:                    strcasecmp(title->b, "EXIT STATUS") == 0 ||
                    149:                    strcasecmp(title->b, "EXAMPLES") == 0 ||
                    150:                    strcasecmp(title->b, "DIAGNOSTICS") == 0 ||
                    151:                    strcasecmp(title->b, "ERRORS") == 0 ||
                    152:                    strcasecmp(title->b, "SEE ALSO") == 0 ||
                    153:                    strcasecmp(title->b, "STANDARDS") == 0 ||
                    154:                    strcasecmp(title->b, "HISTORY") == 0)
                    155:                        later = NULL;
                    156:                else if ((strcasecmp(title->b, "CAVEATS") == 0 ||
                    157:                    strcasecmp(title->b, "BUGS") == 0) &&
                    158:                    later == NULL)
                    159:                        later = nc;
                    160:        }
                    161:
                    162:        /*
                    163:         * If no AUTHORS section was found, create one from scratch,
                    164:         * and insert that at the place selected earlier.
                    165:         */
                    166:
                    167:        if (match == NULL) {
                    168:                match = pnode_alloc(NULL);
                    169:                match->node = NODE_SECTION;
                    170:                match->flags |= NFLAG_SPC;
                    171:                match->parent = n;
                    172:                nc = pnode_alloc(match);
                    173:                nc->node = NODE_TITLE;
                    174:                nc->flags |= NFLAG_SPC;
                    175:                nc = pnode_alloc_text(nc, "AUTHORS");
                    176:                nc->flags |= NFLAG_SPC;
                    177:                if (later == NULL)
                    178:                        TAILQ_INSERT_TAIL(&n->childq, match, child);
                    179:                else
                    180:                        TAILQ_INSERT_BEFORE(later, match, child);
                    181:        }
                    182:
                    183:        /*
                    184:         * Dump the stuff excised at the beginning
                    185:         * into this AUTHORS section.
                    186:         */
                    187:
                    188:        if (info != NULL)
                    189:                TAILQ_INSERT_TAIL(&match->childq, info, child);
                    190:        if (meta != NULL)
                    191:                TAILQ_INSERT_TAIL(&match->childq, meta, child);
                    192: }
                    193:
                    194: static void
1.2       schwarze  195: default_title(struct pnode *n, const char *title)
                    196: {
                    197:        struct pnode    *nc;
                    198:
                    199:        if (n->parent == NULL)
                    200:                return;
                    201:
                    202:        TAILQ_FOREACH(nc, &n->childq, child)
                    203:                if (nc->node == NODE_TITLE)
                    204:                        return;
                    205:
                    206:        nc = pnode_alloc(NULL);
                    207:        nc->node = NODE_TITLE;
                    208:        nc->parent = n;
                    209:        TAILQ_INSERT_HEAD(&n->childq, nc, child);
                    210:        pnode_alloc_text(nc, title);
                    211: }
                    212:
                    213: static void
1.6     ! schwarze  214: reorg_function(struct pnode *n)
        !           215: {
        !           216:        struct pnode    *nc;
        !           217:        size_t           sz;
        !           218:
        !           219:        if ((nc = TAILQ_FIRST(&n->childq)) != NULL &&
        !           220:            nc->node == NODE_TEXT &&
        !           221:            TAILQ_NEXT(nc, child) == NULL &&
        !           222:            (sz = strlen(nc->b)) > 2 &&
        !           223:            nc->b[sz - 2] == '(' && nc->b[sz - 1] == ')')
        !           224:                nc->b[sz - 2] = '\0';
        !           225: }
        !           226:
        !           227: static void
1.2       schwarze  228: reorg_recurse(struct pnode *n)
                    229: {
                    230:        struct pnode    *nc;
                    231:
                    232:        if (n == NULL)
                    233:                return;
                    234:
                    235:        switch (n->node) {
1.4       schwarze  236:        case NODE_ABSTRACT:
                    237:                default_title(n, "Abstract");
                    238:                n->node = NODE_SECTION;
                    239:                break;
1.2       schwarze  240:        case NODE_APPENDIX:
1.3       schwarze  241:                if (n->parent == NULL)
                    242:                        reorg_refentry(n);
1.2       schwarze  243:                default_title(n, "Appendix");
                    244:                break;
                    245:        case NODE_CAUTION:
                    246:                default_title(n, "Caution");
                    247:                n->node = NODE_NOTE;
1.6     ! schwarze  248:                break;
        !           249:        case NODE_FUNCTION:
        !           250:                reorg_function(n);
1.2       schwarze  251:                break;
                    252:        case NODE_LEGALNOTICE:
                    253:                default_title(n, "Legal Notice");
                    254:                n->node = NODE_SIMPLESECT;
                    255:                break;
                    256:        case NODE_NOTE:
                    257:                default_title(n, "Note");
                    258:                break;
                    259:        case NODE_PREFACE:
1.3       schwarze  260:                if (n->parent == NULL)
                    261:                        reorg_refentry(n);
1.2       schwarze  262:                default_title(n, "Preface");
                    263:                n->node = NODE_SECTION;
                    264:                break;
1.3       schwarze  265:        case NODE_REFENTRY:
                    266:                reorg_refentry(n);
                    267:                break;
1.2       schwarze  268:        case NODE_SECTION:
1.3       schwarze  269:                if (n->parent == NULL)
                    270:                        reorg_refentry(n);
                    271:                /* FALLTHROUGH */
1.2       schwarze  272:        case NODE_SIMPLESECT:
                    273:                default_title(n, "Untitled");
                    274:                break;
                    275:        case NODE_TIP:
                    276:                default_title(n, "Tip");
                    277:                n->node = NODE_NOTE;
                    278:                break;
                    279:        case NODE_WARNING:
                    280:                default_title(n, "Warning");
                    281:                n->node = NODE_NOTE;
                    282:                break;
                    283:        default:
                    284:                break;
                    285:        }
                    286:
                    287:        TAILQ_FOREACH(nc, &n->childq, child)
                    288:                reorg_recurse(nc);
                    289: }
                    290:
                    291: void
1.5       schwarze  292: ptree_reorg(struct ptree *tree, const char *sec)
1.2       schwarze  293: {
1.5       schwarze  294:        reorg_root(tree->root, sec);
1.2       schwarze  295:        reorg_recurse(tree->root);
1.1       schwarze  296: }

CVSweb