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

Annotation of docbook2mdoc/statistics.c, Revision 1.41

1.41    ! schwarze    1: /* $Id: statistics.c,v 1.40 2019/05/01 12:52:05 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.37      schwarze   17: #include <sys/types.h>
                     18:
1.1       schwarze   19: #include <assert.h>
                     20: #include <ctype.h>
                     21: #include <err.h>
                     22: #include <fcntl.h>
1.2       schwarze   23: #include <getopt.h>
1.1       schwarze   24: #include <stdio.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
                     27: #include <unistd.h>
                     28:
1.37      schwarze   29: #include "xmalloc.h"
                     30:
1.1       schwarze   31: /*
                     32:  * Count parent-child element relations in a corpus of DocBook documents.
                     33:  *
                     34:  * Read absolute or relative input file names from standard input,
                     35:  * one per line.
                     36:  * For each parent-child relation, print the total number of occurrences,
                     37:  * the parent name, and the child name, separated by tab characters
                     38:  * and followed by a newline character.
                     39:  *
                     40:  * Typical usage:
                     41:  * statistics < filenames.txt | sort -n
                     42:  * statistics < filenames.txt | grep '\<listitem\>' | sort -n
1.4       schwarze   43:  *
                     44:  * Relations already fully implemented are excluded by default.
                     45:  * The option -a shows all relations.
                     46:  *
                     47:  * If two arguments (parent and child) are given, a histogram
                     48:  * of the number of children of the kind in each parent is given
                     49:  * in addition to the normal output.
                     50:  *
                     51:  * Example usage:
                     52:  * statistics tgroup colspec < filenames.txt | grep colspec
1.25      schwarze   53:  *
                     54:  * Synchronized with parse.c up to rev. 1.42.
1.1       schwarze   55:  */
                     56:
                     57: struct entry {
                     58:        char    *parent;
                     59:        char    *child;
                     60:        int      count;
                     61: };
                     62:
                     63: static struct entry     *table;
                     64: static size_t            tablesz;
                     65: static size_t            tablei;
                     66:
                     67: static char            **stack;
                     68: static size_t            stacksz;
                     69: static size_t            stacki;
                     70:
1.4       schwarze   71: static const int         nchildsz = 8;
                     72: struct nchild {
                     73:        char    *parent;
                     74:        char    *child;
                     75:        int      freq[nchildsz];
                     76:        int      count;
                     77: };
                     78:
                     79: static struct nchild     nchild;
                     80: static char             *fname;
                     81:
1.1       schwarze   82:
                     83: /*
                     84:  * Count one instance of a parent-child relation.
1.2       schwarze   85:  * Before the special call table_add(NULL, NULL),
                     86:  * mark relations to not be counted;
                     87:  * in that phase, child can be NULL as a wildcard.
1.1       schwarze   88:  */
                     89: static void
                     90: table_add(const char *parent, const char *child)
                     91: {
1.2       schwarze   92:        static int       init_done;
                     93:        size_t           i;
                     94:
                     95:        if (parent == NULL && child == NULL) {
                     96:                init_done = 1;
                     97:                return;
                     98:        }
1.1       schwarze   99:
1.4       schwarze  100:        /* Optional parent-child histogram. */
                    101:
                    102:        if (init_done && parent != NULL && child != NULL &&
                    103:            nchild.parent != NULL && nchild.child != NULL &&
                    104:            strcmp(parent, nchild.parent) == 0 &&
                    105:            strcmp(child, nchild.child) == 0) {
                    106:                if (nchild.count < nchildsz) {
                    107:                        nchild.freq[nchild.count]++;
                    108:                        if (nchild.count > 0)
                    109:                                nchild.freq[nchild.count - 1]--;
                    110:                } else if (nchild.count == nchildsz)
                    111:                        puts(fname);
                    112:                nchild.count++;
                    113:        }
                    114:
1.1       schwarze  115:        /* If the table entry already exists, increment its count. */
                    116:
                    117:        for (i = 0; i < tablei; i++) {
                    118:                if (strcmp(parent, table[i].parent) == 0 &&
1.2       schwarze  119:                    (child == NULL || table[i].child == NULL ||
                    120:                     strcmp(child, table[i].child) == 0)) {
                    121:                        assert(init_done);
                    122:                        if (table[i].count != -1)
                    123:                                table[i].count++;
1.1       schwarze  124:                        return;
                    125:                }
                    126:        }
                    127:
                    128:        /* If the table is full, make room. */
                    129:
                    130:        if (tablei == tablesz) {
                    131:                tablesz += 64;
1.37      schwarze  132:                table = xreallocarray(table, tablesz, sizeof(*table));
1.1       schwarze  133:        }
                    134:
                    135:        /* Add a new entry to the table. */
                    136:
1.37      schwarze  137:        table[tablei].parent = xstrdup(parent);
                    138:        table[tablei].child = child == NULL ? NULL : xstrdup(child);
1.2       schwarze  139:        table[tablei++].count = init_done ? 1 : -1;
1.1       schwarze  140: }
                    141:
                    142: /*
                    143:  * Enter an element.
                    144:  */
                    145: static void
                    146: stack_push(const char *name)
                    147: {
1.4       schwarze  148:        if (nchild.parent != NULL && strcmp(name, nchild.parent) == 0)
                    149:                nchild.count = 0;
                    150:
1.1       schwarze  151:        if (stacki == stacksz) {
                    152:                stacksz += 8;
1.37      schwarze  153:                stack = xreallocarray(stack, stacksz, sizeof(*stack));
1.1       schwarze  154:        }
1.37      schwarze  155:        stack[stacki++] = xstrdup(name);
1.1       schwarze  156: }
                    157:
                    158: /*
                    159:  * Exit an element.
                    160:  */
                    161: static void
                    162: stack_pop(const char *name)
                    163: {
                    164:        if (stacki > 0 && (name == NULL ||
                    165:            strcmp(name, stack[stacki - 1]) == 0))
                    166:                free(stack[--stacki]);
                    167: }
                    168:
                    169: /*
                    170:  * Simplified version from parse.c.
                    171:  */
                    172: static int
                    173: advance(char *b, size_t rlen, size_t *pend, const char *charset)
                    174: {
                    175:        int              space;
                    176:
                    177:        if (*charset == ' ') {
                    178:                space = 1;
                    179:                charset++;
                    180:        } else
                    181:                space = 0;
                    182:
                    183:        while (*pend < rlen) {
                    184:                if (space && isspace((unsigned char)b[*pend]))
                    185:                        break;
                    186:                if (strchr(charset, b[*pend]) != NULL)
                    187:                        break;
                    188:                ++*pend;
                    189:        }
                    190:        if (*pend == rlen) {
                    191:                b[rlen] = '\0';
                    192:                return 1;
                    193:        } else
                    194:                return 0;
                    195: }
                    196:
                    197: /*
                    198:  * Simplified version from parse.c.
                    199:  */
                    200: static void
                    201: parse_file(int fd, char *fname)
                    202: {
                    203:        char             b[4096];
1.3       schwarze  204:        char            *cp;
1.1       schwarze  205:        ssize_t          rsz;   /* Return value from read(2). */
                    206:        size_t           rlen;  /* Number of bytes in b[]. */
                    207:        size_t           poff;  /* Parse offset in b[]. */
                    208:        size_t           pend;  /* Offset of the end of the current word. */
1.26      schwarze  209:        int              in_tag, in_arg, in_quotes, in_doctype, elem_end;
1.1       schwarze  210:
                    211:        rlen = 0;
1.26      schwarze  212:        in_tag = in_arg = in_quotes = in_doctype = 0;
1.1       schwarze  213:        while ((rsz = read(fd, b + rlen, sizeof(b) - rlen - 1)) >= 0) {
                    214:                if ((rlen += rsz) == 0)
                    215:                        break;
                    216:                pend = 0;
                    217:                for (;;) {
                    218:                        if ((poff = pend) == rlen)
                    219:                                break;
                    220:                        if (isspace((unsigned char)b[pend])) {
                    221:                                pend++;
                    222:                                continue;
                    223:                        }
                    224:                        if (in_arg) {
1.5       schwarze  225:                                if (in_quotes == 0 &&
                    226:                                    (b[pend] == '\'' || b[pend] == '"')) {
                    227:                                        in_quotes = b[pend] == '"' ? 2 : 1;
1.1       schwarze  228:                                        pend++;
                    229:                                        continue;
                    230:                                }
                    231:                                if (advance(b, rlen, &pend,
1.5       schwarze  232:                                    in_quotes == 2 ? "\"" :
                    233:                                    in_quotes == 1 ? "'" : " >") && rsz > 0)
1.1       schwarze  234:                                        break;
                    235:                                in_arg = in_quotes = elem_end = 0;
                    236:                                if (b[pend] == '>') {
                    237:                                        in_tag = 0;
                    238:                                        if (pend > 0 && b[pend - 1] == '/') {
                    239:                                                b[pend - 1] = '\0';
                    240:                                                elem_end = 1;
                    241:                                        }
                    242:                                }
                    243:                                b[pend] = '\0';
                    244:                                if (pend < rlen)
                    245:                                        pend++;
                    246:                                if (elem_end)
                    247:                                        stack_pop(NULL);
                    248:                        } else if (in_tag) {
1.26      schwarze  249:                                if (in_doctype && b[pend] == '[') {
                    250:                                        in_tag = in_doctype = 0;
                    251:                                        pend++;
                    252:                                        continue;
                    253:                                }
1.1       schwarze  254:                                if (advance(b, rlen, &pend, " =>") && rsz > 0)
                    255:                                        break;
                    256:                                elem_end = 0;
                    257:                                switch (b[pend]) {
                    258:                                case '>':
                    259:                                        in_tag = 0;
                    260:                                        if (pend > 0 && b[pend - 1] == '/') {
                    261:                                                b[pend - 1] = '\0';
                    262:                                                elem_end = 1;
                    263:                                        }
                    264:                                        break;
                    265:                                case '=':
                    266:                                        in_arg = 1;
                    267:                                        break;
                    268:                                default:
                    269:                                        break;
                    270:                                }
                    271:                                b[pend] = '\0';
                    272:                                if (pend < rlen)
                    273:                                        pend++;
                    274:                                if (elem_end)
                    275:                                        stack_pop(NULL);
                    276:                        } else if (b[poff] == '<') {
                    277:                                if (advance(b, rlen, &pend, " >") && rsz > 0)
                    278:                                        break;
1.3       schwarze  279:                                if (pend > poff + 3 &&
                    280:                                    strncmp(b + poff, "<!--", 4) == 0) {
                    281:                                        /* Skip a comment. */
                    282:                                        cp = strstr(b + pend - 2, "-->");
                    283:                                        if (cp == NULL) {
                    284:                                                pend = rlen;
                    285:                                                if (rsz > 0)
                    286:                                                        break;
                    287:                                        } else
                    288:                                                pend = cp + 3 - b;
                    289:                                        continue;
                    290:                                }
1.1       schwarze  291:                                elem_end = 0;
                    292:                                if (b[pend] != '>')
                    293:                                        in_tag = 1;
                    294:                                else if (pend > 0 && b[pend - 1] == '/') {
                    295:                                        b[pend - 1] = '\0';
                    296:                                        elem_end = 1;
                    297:                                }
                    298:                                b[pend] = '\0';
                    299:                                if (pend < rlen)
                    300:                                        pend++;
                    301:                                if (b[++poff] == '/') {
                    302:                                        elem_end = 1;
                    303:                                        poff++;
1.26      schwarze  304:                                } else if (strcasecmp(b + poff,
                    305:                                    "!DOCTYPE") == 0) {
                    306:                                        in_doctype = 1;
1.1       schwarze  307:                                } else if (b[poff] != '!' && b[poff] != '?') {
                    308:                                        table_add(stacki > 0 ?
1.2       schwarze  309:                                            stack[stacki - 1] : "ROOT",
1.1       schwarze  310:                                            b + poff);
                    311:                                        stack_push(b + poff);
1.25      schwarze  312:                                        if (strcmp(b + poff, "sbr") == 0)
                    313:                                                elem_end = 1;
1.1       schwarze  314:                                }
                    315:                                if (elem_end)
                    316:                                        stack_pop(b + poff);
                    317:                        } else {
                    318:                                advance(b, rlen, &pend, "<");
                    319:                                if (stacki > 0)
                    320:                                        table_add(stack[stacki - 1], "TEXT");
                    321:                        }
                    322:                }
                    323:                assert(poff > 0);
                    324:                rlen -= poff;
1.25      schwarze  325:                memmove(b, b + poff, rlen);
1.1       schwarze  326:        }
                    327:        if (rsz < 0)
                    328:                perror(fname);
                    329: }
                    330:
                    331: int
                    332: main(int argc, char *argv[])
                    333: {
                    334:        size_t           fsz, i;
                    335:        ssize_t          rsz;
1.2       schwarze  336:        int              ch, fd, show_all;
                    337:
                    338:        show_all = 0;
                    339:        while ((ch = getopt(argc, argv, "a")) != -1) {
                    340:                switch (ch) {
                    341:                case 'a':
                    342:                        show_all = 1;
                    343:                        break;
                    344:                default:
                    345:                        return 1;
                    346:                }
                    347:        }
1.4       schwarze  348:        argc -= optind;
                    349:        argv += optind;
                    350:
                    351:        if (argc > 1) {
                    352:                nchild.parent = argv[0];
                    353:                nchild.child = argv[1];
                    354:        }
1.1       schwarze  355:
1.2       schwarze  356:        /* Exclude relations that are already fully implemented. */
                    357:        if (show_all == 0) {
1.33      schwarze  358:                table_add("ROOT", "appendix");
1.27      schwarze  359:                table_add("ROOT", "article");
                    360:                table_add("ROOT", "book");
                    361:                table_add("ROOT", "chapter");
1.33      schwarze  362:                table_add("ROOT", "glossary");
                    363:                table_add("ROOT", "part");
                    364:                table_add("ROOT", "preface");
1.11      schwarze  365:                table_add("ROOT", "refentry");
1.36      schwarze  366:                table_add("ROOT", "reference");
1.33      schwarze  367:                table_add("ROOT", "sect1");
                    368:                table_add("ROOT", "sect2");
1.38      schwarze  369:                table_add("abstract", NULL);
1.12      schwarze  370:                table_add("acronym", "TEXT");
1.41    ! schwarze  371:                table_add("affiliation", "jobtitle");
1.27      schwarze  372:                table_add("affiliation", "orgdiv");
                    373:                table_add("affiliation", "orgname");
1.18      schwarze  374:                table_add("appendix", NULL);
1.24      schwarze  375:                table_add("application", "TEXT");
                    376:                table_add("arg", "option");
1.18      schwarze  377:                table_add("article", NULL);
1.38      schwarze  378:                table_add("articleinfo", "abstract");
1.27      schwarze  379:                table_add("articleinfo", "author");
                    380:                table_add("articleinfo", "authorgroup");
                    381:                table_add("articleinfo", "copyright");
1.24      schwarze  382:                table_add("articleinfo", "date");
1.27      schwarze  383:                table_add("articleinfo", "legalnotice");
1.21      schwarze  384:                table_add("articleinfo", "pubdate");
1.27      schwarze  385:                table_add("articleinfo", "releaseinfo");
                    386:                table_add("articleinfo", "subtitle");
1.21      schwarze  387:                table_add("articleinfo", "title");
1.27      schwarze  388:                table_add("author", "affiliation");
1.20      schwarze  389:                table_add("author", "contrib");
                    390:                table_add("author", "email");
                    391:                table_add("author", "firstname");
                    392:                table_add("author", "othername");
                    393:                table_add("author", "surname");
1.27      schwarze  394:                table_add("author", "TEXT");
1.23      schwarze  395:                table_add("authorgroup", "author");
1.27      schwarze  396:                table_add("authorgroup", "editor");
1.23      schwarze  397:                table_add("authorgroup", "othercredit");
1.16      schwarze  398:                table_add("blockquote", NULL);
1.18      schwarze  399:                table_add("book", NULL);
1.38      schwarze  400:                table_add("bookinfo", "abstract");
1.23      schwarze  401:                table_add("bookinfo", "authorgroup");
1.27      schwarze  402:                table_add("bookinfo", "copyright");
1.23      schwarze  403:                table_add("bookinfo", "legalnotice");
1.21      schwarze  404:                table_add("bookinfo", "pubdate");
1.27      schwarze  405:                table_add("bookinfo", "releaseinfo");
                    406:                table_add("bookinfo", "subtitle");
1.21      schwarze  407:                table_add("bookinfo", "title");
1.32      schwarze  408:                table_add("caption", "TEXT");
1.9       schwarze  409:                table_add("chapter", NULL);
1.23      schwarze  410:                table_add("citerefentry", "manvolnum");
                    411:                table_add("citerefentry", "refentrytitle");
1.24      schwarze  412:                table_add("citetitle", "TEXT");
                    413:                table_add("cmdsynopsis", "arg");
                    414:                table_add("cmdsynopsis", "command");
                    415:                table_add("cmdsynopsis", "group");
1.33      schwarze  416:                table_add("cmdsynopsis", "sbr");
1.12      schwarze  417:                table_add("code", "TEXT");
1.24      schwarze  418:                table_add("command", "TEXT");
1.19      schwarze  419:                table_add("computeroutput", "TEXT");
1.10      schwarze  420:                table_add("constant", "TEXT");
1.27      schwarze  421:                table_add("contrib", "TEXT");
                    422:                table_add("copyright", "holder");
                    423:                table_add("copyright", "year");
1.21      schwarze  424:                table_add("date", "TEXT");
1.27      schwarze  425:                table_add("editor", "affiliation");
                    426:                table_add("editor", "firstname");
                    427:                table_add("editor", "surname");
1.24      schwarze  428:                table_add("email", "TEXT");
1.29      schwarze  429:                table_add("emphasis", "errorname");
                    430:                table_add("emphasis", "function");
1.8       schwarze  431:                table_add("emphasis", "TEXT");
1.6       schwarze  432:                table_add("entry", NULL);
1.12      schwarze  433:                table_add("errorname", "TEXT");
1.32      schwarze  434:                table_add("figure", "mediaobject");
1.33      schwarze  435:                table_add("figure", "title");
1.12      schwarze  436:                table_add("filename", "TEXT");
1.24      schwarze  437:                table_add("firstname", "TEXT");
                    438:                table_add("firstterm", "TEXT");
1.31      schwarze  439:                table_add("footnote", "para");
1.8       schwarze  440:                table_add("funcdef", "function");
                    441:                table_add("funcdef", "TEXT");
1.40      schwarze  442:                table_add("funcparams", "TEXT");
1.8       schwarze  443:                table_add("funcprototype", "funcdef");
                    444:                table_add("funcprototype", "paramdef");
1.40      schwarze  445:                table_add("funcprototype", "void");
1.12      schwarze  446:                table_add("funcsynopsis", "funcprototype");
                    447:                table_add("funcsynopsis", "funcsynopsisinfo");
                    448:                table_add("funcsynopsisinfo", "TEXT");
1.29      schwarze  449:                table_add("function", "replaceable");
1.8       schwarze  450:                table_add("function", "TEXT");
1.17      schwarze  451:                table_add("glossary", "glossdiv");
                    452:                table_add("glossary", "glossentry");
                    453:                table_add("glossdef", "para");
                    454:                table_add("glossdiv", "glossentry");
                    455:                table_add("glossentry", "glossdef");
                    456:                table_add("glossentry", "glossterm");
                    457:                table_add("glossentry", "indexterm");
                    458:                table_add("glosslist", "glossentry");
1.33      schwarze  459:                table_add("glossterm", "emphasis");
1.17      schwarze  460:                table_add("glossterm", "TEXT");
1.24      schwarze  461:                table_add("group", "arg");
1.27      schwarze  462:                table_add("holder", "TEXT");
1.32      schwarze  463:                table_add("imageobject", "imagedata");
1.9       schwarze  464:                table_add("indexterm", "primary");
                    465:                table_add("indexterm", "secondary");
1.6       schwarze  466:                table_add("informaltable", "tgroup");
1.7       schwarze  467:                table_add("itemizedlist", "listitem");
1.41    ! schwarze  468:                table_add("jobtitle", "TEXT");
1.24      schwarze  469:                table_add("keycap", "TEXT");
                    470:                table_add("keycode", "TEXT");
1.39      schwarze  471:                table_add("keycombo", "keycap");
1.24      schwarze  472:                table_add("keysym", "TEXT");
1.18      schwarze  473:                table_add("legalnotice", NULL);
1.15      schwarze  474:                table_add("link", NULL);
1.7       schwarze  475:                table_add("listitem", NULL);
1.12      schwarze  476:                table_add("literal", "TEXT");
1.10      schwarze  477:                table_add("literallayout", NULL);
1.23      schwarze  478:                table_add("manvolnum", "TEXT");
1.19      schwarze  479:                table_add("markup", "TEXT");
1.32      schwarze  480:                table_add("mediaobject", "caption");
                    481:                table_add("mediaobject", "imageobject");
1.30      schwarze  482:                table_add("member", "constant");
                    483:                table_add("member", "emphasis");
                    484:                table_add("member", "function");
                    485:                table_add("member", "property");
                    486:                table_add("member", "symbol");
1.13      schwarze  487:                table_add("member", "TEXT");
1.18      schwarze  488:                table_add("note", NULL);
1.34      schwarze  489:                table_add("olink", "citetitle");
                    490:                table_add("olink", "function");
                    491:                table_add("olink", "TEXT");
1.29      schwarze  492:                table_add("option", "parameter");
                    493:                table_add("option", "replaceable");
1.24      schwarze  494:                table_add("option", "TEXT");
1.7       schwarze  495:                table_add("orderedlist", "listitem");
1.27      schwarze  496:                table_add("orgdiv", "TEXT");
                    497:                table_add("orgname", "TEXT");
                    498:                table_add("othercredit", "affiliation");
1.20      schwarze  499:                table_add("othercredit", "contrib");
                    500:                table_add("othercredit", "email");
                    501:                table_add("othercredit", "firstname");
                    502:                table_add("othercredit", "othername");
                    503:                table_add("othercredit", "surname");
1.24      schwarze  504:                table_add("othername", "TEXT");
1.2       schwarze  505:                table_add("para", NULL);
1.40      schwarze  506:                table_add("paramdef", "funcparams");
1.9       schwarze  507:                table_add("paramdef", "parameter");
                    508:                table_add("paramdef", "TEXT");
                    509:                table_add("parameter", "TEXT");
1.27      schwarze  510:                table_add("part", NULL);
1.24      schwarze  511:                table_add("personname", "firstname");
                    512:                table_add("personname", "surname");
1.27      schwarze  513:                table_add("phrase", "TEXT");
                    514:                table_add("preface", NULL);
1.9       schwarze  515:                table_add("primary", NULL);
1.35      schwarze  516:                table_add("productname", "TEXT");
1.10      schwarze  517:                table_add("programlisting", NULL);
1.24      schwarze  518:                table_add("property", "TEXT");
1.21      schwarze  519:                table_add("pubdate", "TEXT");
1.29      schwarze  520:                table_add("quote", "command");
1.33      schwarze  521:                table_add("quote", "filename");
1.28      schwarze  522:                table_add("quote", "literal");
1.24      schwarze  523:                table_add("quote", "TEXT");
1.23      schwarze  524:                table_add("refentry", "refentryinfo");
1.11      schwarze  525:                table_add("refentry", "refmeta");
                    526:                table_add("refentry", "refnamediv");
                    527:                table_add("refentry", "refsect1");
                    528:                table_add("refentry", "refsynopsisdiv");
1.27      schwarze  529:                table_add("refentryinfo", "author");
1.33      schwarze  530:                table_add("refentryinfo", "authorgroup");
1.27      schwarze  531:                table_add("refentryinfo", "copyright");
1.24      schwarze  532:                table_add("refentryinfo", "date");
1.35      schwarze  533:                table_add("refentryinfo", "productname");
1.23      schwarze  534:                table_add("refentrytitle", "TEXT");
1.36      schwarze  535:                table_add("reference", "refentry");
1.11      schwarze  536:                table_add("refmeta", "manvolnum");
                    537:                table_add("refmeta", "refentrytitle");
1.23      schwarze  538:                table_add("refmeta", "refmiscinfo");
                    539:                table_add("refmiscinfo", "TEXT");
1.11      schwarze  540:                table_add("refname", "TEXT");
                    541:                table_add("refnamediv", "refname");
                    542:                table_add("refnamediv", "refpurpose");
                    543:                table_add("refpurpose", "TEXT");
1.9       schwarze  544:                table_add("refsect1", NULL);
                    545:                table_add("refsect2", NULL);
1.24      schwarze  546:                table_add("refsynopsisdiv", "cmdsynopsis");
1.11      schwarze  547:                table_add("refsynopsisdiv", "funcsynopsis");
1.27      schwarze  548:                table_add("releaseinfo", "TEXT");
1.24      schwarze  549:                table_add("replaceable", "TEXT");
                    550:                table_add("returnvalue", "TEXT");
1.6       schwarze  551:                table_add("row", "entry");
1.10      schwarze  552:                table_add("screen", NULL);
1.9       schwarze  553:                table_add("secondary", NULL);
                    554:                table_add("section", NULL);
                    555:                table_add("sect1", NULL);
                    556:                table_add("sect2", NULL);
                    557:                table_add("sect3", NULL);
                    558:                table_add("sect4", NULL);
1.12      schwarze  559:                table_add("sgmltag", "TEXT");
1.14      schwarze  560:                table_add("simpara", NULL);
1.13      schwarze  561:                table_add("simplelist", "member");
1.27      schwarze  562:                table_add("simplesect", NULL);
1.12      schwarze  563:                table_add("structfield", "TEXT");
                    564:                table_add("structname", "TEXT");
1.30      schwarze  565:                table_add("subscript", "TEXT");
1.27      schwarze  566:                table_add("subtitle", "TEXT");
1.30      schwarze  567:                table_add("superscript", "emphasis");
                    568:                table_add("superscript", "TEXT");
1.24      schwarze  569:                table_add("surname", "TEXT");
1.10      schwarze  570:                table_add("symbol", "TEXT");
1.33      schwarze  571:                table_add("synopsis", "function");
                    572:                table_add("synopsis", "parameter");
                    573:                table_add("synopsis", "type");
1.24      schwarze  574:                table_add("synopsis", "TEXT");
1.22      schwarze  575:                table_add("systemitem", "TEXT");
1.6       schwarze  576:                table_add("table", "tgroup");
                    577:                table_add("table", "title");
                    578:                table_add("tbody", "row");
1.7       schwarze  579:                table_add("term", NULL);
1.6       schwarze  580:                table_add("tgroup", "colspec");
                    581:                table_add("tgroup", "tbody");
                    582:                table_add("tgroup", "thead");
                    583:                table_add("thead", "row");
1.29      schwarze  584:                table_add("title", "acronym");
                    585:                table_add("title", "emphasis");
                    586:                table_add("title", "errorname");
                    587:                table_add("title", "function");
                    588:                table_add("title", "literal");
                    589:                table_add("title", "quote");
                    590:                table_add("title", "trademark");
                    591:                table_add("title", "type");
1.6       schwarze  592:                table_add("title", "TEXT");
1.27      schwarze  593:                table_add("trademark", "TEXT");
1.12      schwarze  594:                table_add("type", "TEXT");
1.15      schwarze  595:                table_add("ulink", NULL);
1.12      schwarze  596:                table_add("userinput", "TEXT");
1.7       schwarze  597:                table_add("variablelist", "varlistentry");
                    598:                table_add("varlistentry", "listitem");
                    599:                table_add("varlistentry", "term");
1.24      schwarze  600:                table_add("varname", "TEXT");
1.27      schwarze  601:                table_add("warning", NULL);
                    602:                table_add("year", "TEXT");
1.2       schwarze  603:        }
                    604:        table_add(NULL, NULL);
                    605:
                    606:        /* Loop over input files. */
1.1       schwarze  607:        fd = -1;
                    608:        fname = NULL;
                    609:        while ((rsz = getline(&fname, &fsz, stdin)) != -1) {
                    610:                if (fname[rsz - 1] == '\n')
                    611:                        fname[--rsz] = '\0';
                    612:                if ((fd = open(fname, O_RDONLY, 0)) == -1)
                    613:                        err(1, "%s", fname);
                    614:                parse_file(fd, fname);
                    615:                close(fd);
                    616:        }
                    617:
                    618:        /* Cleanup and error handling. */
                    619:        free(fname);
                    620:        if (ferror(stdin))
                    621:                err(1, "standard input");
                    622:        if (fd == -1)
                    623:                errx(1, "No input file names found on standard input");
                    624:
                    625:        /* Dump results. */
                    626:        for (i = 0; i < tablei; i++)
1.2       schwarze  627:                if (table[i].count != -1)
                    628:                        printf("%d\t%s\t%s\n", table[i].count,
                    629:                            table[i].parent, table[i].child);
1.4       schwarze  630:
                    631:        /* Optional parent-child histogram. */
                    632:        if (nchild.parent != NULL) {
                    633:                printf("%s %s", nchild.parent, nchild.child);
                    634:                for (i = 0; i < nchildsz; i++)
                    635:                        printf(" %d", nchild.freq[i]);
                    636:                putchar('\n');
                    637:        }
1.1       schwarze  638:        return 0;
                    639: }

CVSweb