diff options
Diffstat (limited to 'src/descriptions.c')
-rw-r--r-- | src/descriptions.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/descriptions.c b/src/descriptions.c new file mode 100644 index 0000000..de2dfb9 --- /dev/null +++ b/src/descriptions.c @@ -0,0 +1,163 @@ +/* + * descriptions.c: manipulate man page descriptions + * + * Copyright (C) 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 Colin Watson. + * + * This file is part of man-db. + * + * man-db is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * man-db is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with man-db; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <stdbool.h> +#include <string.h> +#include <stdlib.h> + +#include "gl_array_list.h" +#include "gl_xlist.h" +#include "xalloc.h" +#include "xstrndup.h" + +#include "manconfig.h" + +#include "debug.h" +#include "util.h" + +#include "descriptions.h" + +/* Free a page description. */ +static void page_description_free (const void *value) +{ + struct page_description *desc = (struct page_description *) value; + + free (desc->name); + free (desc->whatis); + free (desc); +} + +/* Parse the description in a whatis line returned by find_name() into a + * list of names and whatis descriptions. + */ +gl_list_t parse_descriptions (const char *base, const char *whatis) +{ + const char *sep, *nextsep; + gl_list_t descs; + bool seen_base = false; + + descs = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, + page_description_free, true); + + if (!whatis) + return descs; + + sep = whatis; + + while (sep) { + char *record; + size_t length; + const char *dash; + char *names; + const char *token; + + /* Use a while loop so that we skip over things like the + * result of double line breaks. + */ + while (*sep == 0x11 || *sep == ' ') + ++sep; + nextsep = strchr (sep, 0x11); + + /* Get this record as a null-terminated string. */ + if (nextsep) + length = (size_t) (nextsep - sep); + else + length = strlen (sep); + if (length == 0) + break; + + record = xstrndup (sep, length); + debug ("record = '%s'\n", record); + + /* Split the record into name and whatis description. */ + dash = strstr (record, " - "); + if (dash) + names = xstrndup (record, dash - record); + else if (!gl_list_size (descs)) + /* Some pages have a NAME section with just the page + * name and no whatis. We might as well include + * this. + */ + names = xstrdup (record); + else + /* Once at least one record has been seen, further + * cases where there is no whatis usually amount to + * garbage following the useful records, and can + * cause problems due to false WHATIS_MAN entries in + * the database. On the whole it seems best to + * ignore these. + */ + goto next; + + for (token = strtok (names, ","); token; + token = strtok (NULL, ",")) { + char *name = trim_spaces (token); + struct page_description *desc; + + /* Skip name tokens containing whitespace. They are + * almost never useful as manual page names. + */ + if (strpbrk (name, " \t") != NULL) { + free (name); + continue; + } + + /* Allocate new description node. */ + desc = xmalloc (sizeof *desc); + desc->name = name; /* steal memory */ + desc->whatis = dash ? trim_spaces (dash + 3) : NULL; + gl_list_add_last (descs, desc); + + if (base && STREQ (base, desc->name)) + seen_base = true; + } + + free (names); +next: + free (record); + + sep = nextsep; + } + + /* If it isn't there already, add the base name onto the returned + * list. + */ + if (base && !seen_base) { + struct page_description *desc = xmalloc (sizeof *desc); + + desc->name = xstrdup (base); + desc->whatis = NULL; + if (gl_list_size (descs)) { + const struct page_description *first = + gl_list_get_at (descs, 0); + if (first->whatis) + desc->whatis = xstrdup (first->whatis); + } + gl_list_add_last (descs, desc); + } + + return descs; +} |