]> git.cameronkatri.com Git - mandoc.git/blobdiff - main.c
Explain how to transform markup for the terminal when not using a
[mandoc.git] / main.c
diff --git a/main.c b/main.c
index 03092ef69a78a583cdcb542f6f17f08584233f15..7f1411a6fbcccaa60e3cbbd5542566f6938c2c84 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.293 2017/06/24 14:38:32 schwarze Exp $ */
+/*     $Id: main.c,v 1.301 2017/07/26 10:21:55 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2012, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -43,6 +43,7 @@
 
 #include "mandoc_aux.h"
 #include "mandoc.h"
+#include "mandoc_xr.h"
 #include "roff.h"
 #include "mdoc.h"
 #include "man.h"
@@ -86,11 +87,12 @@ struct      curparse {
 
 int                      mandocdb(int, char *[]);
 
+static void              check_xr(const char *);
 static int               fs_lookup(const struct manpaths *,
                                size_t ipath, const char *,
                                const char *, const char *,
                                struct manpage **, size_t *);
-static void              fs_search(const struct mansearch *,
+static int               fs_search(const struct mansearch *,
                                const struct manpaths *, int, char**,
                                struct manpage **, size_t *);
 static int               koptions(int *, char *);
@@ -109,6 +111,7 @@ static      const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
 static char              help_arg[] = "help";
 static char             *help_argv[] = {help_arg, NULL};
 static enum mandoclevel  rc;
+static FILE             *mmsg_stream;
 
 
 int
@@ -188,6 +191,7 @@ main(int argc, char *argv[])
        curp.mmin = MANDOCERR_MAX;
        curp.outopts = &conf.output;
        options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
+       mmsg_stream = stderr;
 
        use_pager = 1;
        tag_files = NULL;
@@ -474,7 +478,7 @@ main(int argc, char *argv[])
                                parse(&curp, fd, *argv);
                        else if (resp->form == FORM_SRC) {
                                /* For .so only; ignore failure. */
-                               chdir(conf.manpath.paths[resp->ipath]);
+                               (void)chdir(conf.manpath.paths[resp->ipath]);
                                parse(&curp, fd, resp->file);
                        } else
                                passthrough(resp->file, fd,
@@ -517,6 +521,7 @@ main(int argc, char *argv[])
                        break;
                }
        }
+       mandoc_xr_free();
        mparse_free(curp.mp);
        mchars_free();
 
@@ -660,12 +665,23 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
        if (globres == 0)
                file = mandoc_strdup(*globinfo.gl_pathv);
        globfree(&globinfo);
-       if (globres != 0)
+       if (globres == 0)
+               goto found;
+       if (res != NULL || ipath + 1 != paths->sz)
                return 0;
 
+       mandoc_asprintf(&file, "%s.%s", name, sec);
+       globres = access(file, R_OK);
+       free(file);
+       return globres != -1;
+
 found:
        warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s",
            name, sec, BINM_MAKEWHATIS, paths->paths[ipath]);
+       if (res == NULL) {
+               free(file);
+               return 1;
+       }
        *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
        page = *res + (*ressz - 1);
        page->file = file;
@@ -678,7 +694,7 @@ found:
        return 1;
 }
 
-static void
+static int
 fs_search(const struct mansearch *cfg, const struct manpaths *paths,
        int argc, char **argv, struct manpage **res, size_t *ressz)
 {
@@ -690,7 +706,8 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
 
        assert(cfg->argmode == ARG_NAME);
 
-       *res = NULL;
+       if (res != NULL)
+               *res = NULL;
        *ressz = lastsz = 0;
        while (argc) {
                for (ipath = 0; ipath < paths->sz; ipath++) {
@@ -698,19 +715,20 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
                                if (fs_lookup(paths, ipath, cfg->sec,
                                    cfg->arch, *argv, res, ressz) &&
                                    cfg->firstmatch)
-                                       return;
+                                       return 1;
                        } else for (isec = 0; isec < nsec; isec++)
                                if (fs_lookup(paths, ipath, sections[isec],
                                    cfg->arch, *argv, res, ressz) &&
                                    cfg->firstmatch)
-                                       return;
+                                       return 1;
                }
-               if (*ressz == lastsz)
+               if (res != NULL && *ressz == lastsz)
                        warnx("No entry for %s in the manual.", *argv);
                lastsz = *ressz;
                argv++;
                argc--;
        }
+       return 0;
 }
 
 static void
@@ -747,6 +765,7 @@ parse(struct curparse *curp, int fd, const char *file)
 
        if (man == NULL)
                return;
+       mandoc_xr_reset();
        if (man->macroset == MACROSET_MDOC) {
                if (curp->outtype != OUTT_TREE || !curp->outopts->noval)
                        mdoc_validate(man);
@@ -798,9 +817,46 @@ parse(struct curparse *curp, int fd, const char *file)
                        break;
                }
        }
+       if (curp->mmin < MANDOCERR_STYLE)
+               check_xr(file);
        mparse_updaterc(curp->mp, &rc);
 }
 
+static void
+check_xr(const char *file)
+{
+       static struct manpaths   paths;
+       struct mansearch         search;
+       struct mandoc_xr        *xr;
+       char                    *cp;
+       size_t                   sz;
+
+       if (paths.sz == 0)
+               manpath_base(&paths);
+
+       for (xr = mandoc_xr_get(); xr != NULL; xr = xr->next) {
+               if (xr->line == -1)
+                       continue;
+               search.arch = NULL;
+               search.sec = xr->sec;
+               search.outkey = NULL;
+               search.argmode = ARG_NAME;
+               search.firstmatch = 1;
+               if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz))
+                       continue;
+               if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz))
+                       continue;
+               if (xr->count == 1)
+                       mandoc_asprintf(&cp, "Xr %s %s", xr->name, xr->sec);
+               else
+                       mandoc_asprintf(&cp, "Xr %s %s (%d times)",
+                           xr->name, xr->sec, xr->count);
+               mmsg(MANDOCERR_XR_BAD, MANDOCLEVEL_STYLE,
+                   file, xr->line, xr->pos + 1, cp);
+               free(cp);
+       }
+}
+
 static void
 outdata_alloc(struct curparse *curp)
 {
@@ -940,6 +996,7 @@ toptions(struct curparse *curp, char *arg)
        else if (0 == strcmp(arg, "lint")) {
                curp->outtype = OUTT_LINT;
                curp->mmin = MANDOCERR_BASE;
+               mmsg_stream = stdout;
        } else if (0 == strcmp(arg, "tree"))
                curp->outtype = OUTT_TREE;
        else if (0 == strcmp(arg, "man"))
@@ -1029,22 +1086,21 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
 {
        const char      *mparse_msg;
 
-       fprintf(stderr, "%s: %s:", getprogname(),
+       fprintf(mmsg_stream, "%s: %s:", getprogname(),
            file == NULL ? "<stdin>" : file);
 
        if (line)
-               fprintf(stderr, "%d:%d:", line, col + 1);
+               fprintf(mmsg_stream, "%d:%d:", line, col + 1);
 
-       fprintf(stderr, " %s",
-           t < MANDOCERR_STYLE ? "BASE" : mparse_strlevel(lvl));
+       fprintf(mmsg_stream, " %s", mparse_strlevel(lvl));
 
        if ((mparse_msg = mparse_strerror(t)) != NULL)
-               fprintf(stderr, ": %s", mparse_msg);
+               fprintf(mmsg_stream, ": %s", mparse_msg);
 
        if (msg)
-               fprintf(stderr, ": %s", msg);
+               fprintf(mmsg_stream, ": %s", msg);
 
-       fputc('\n', stderr);
+       fputc('\n', mmsg_stream);
 }
 
 static pid_t