summaryrefslogtreecommitdiffstats
path: root/src/descriptions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/descriptions.c')
-rw-r--r--src/descriptions.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/descriptions.c b/src/descriptions.c
new file mode 100644
index 0000000..009a50b
--- /dev/null
+++ b/src/descriptions.c
@@ -0,0 +1,161 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+
+#include "manconfig.h"
+#include "descriptions.h"
+
+/* Parse the description in a whatis line returned by find_name() into a
+ * sequence of names and whatis descriptions.
+ */
+struct page_description *parse_descriptions (const char *base,
+ const char *whatis)
+{
+ const char *sep, *nextsep;
+ struct page_description *desc = NULL, *head = NULL;
+ int seen_base = 0;
+
+ if (!whatis)
+ return NULL;
+
+ 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 (!desc)
+ /* 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);
+
+ /* 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. */
+ if (head) {
+ desc->next = xmalloc (sizeof *desc);
+ desc = desc->next;
+ } else {
+ desc = xmalloc (sizeof *desc);
+ head = desc;
+ }
+ desc->name = name; /* steal memory */
+ desc->whatis = dash ? trim_spaces (dash + 3) : NULL;
+ desc->next = NULL;
+
+ if (base && STREQ (base, desc->name))
+ seen_base = 1;
+ }
+
+ 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) {
+ if (head) {
+ desc->next = xmalloc (sizeof *desc);
+ desc = desc->next;
+ desc->whatis =
+ head->whatis ? xstrdup (head->whatis) : NULL;
+ } else {
+ desc = xmalloc (sizeof *desc);
+ head = desc;
+ desc->whatis = NULL;
+ }
+ desc->name = xstrdup (base);
+ desc->next = NULL;
+ }
+
+ return head;
+}
+
+/* Free a description list and all its contents. */
+void free_descriptions (struct page_description *head)
+{
+ struct page_description *desc = head, *prev;
+
+ while (desc) {
+ free (desc->name);
+ free (desc->whatis);
+ prev = desc;
+ desc = desc->next;
+ free (prev);
+ }
+}