summaryrefslogtreecommitdiff
path: root/librarian/rarian-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'librarian/rarian-main.c')
-rw-r--r--librarian/rarian-main.c630
1 files changed, 630 insertions, 0 deletions
diff --git a/librarian/rarian-main.c b/librarian/rarian-main.c
new file mode 100644
index 0000000..f550be0
--- /dev/null
+++ b/librarian/rarian-main.c
@@ -0,0 +1,630 @@
+/*
+ * rarian-main.c
+ * This file is part of Rarian
+ *
+ * Copyright (C) 2006 - Don Scorgie
+ *
+ * Rarian is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Rarian 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include "config.h"
+
+#include "rarian.h"
+#include "rarian-reg-utils.h"
+#include "rarian-language.h"
+#include "rarian-utils.h"
+#if ENABLE_OMF_READ
+#include "rarian-omf.h"
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+/* Internal structures and lists */
+
+typedef struct _Link Link;
+
+
+struct _Link
+{
+ union {
+ RrnReg *reg;
+ RrnSect *sect;
+ } reg;
+ Link *next;
+ Link *prev;
+};
+
+static Link * head = NULL;
+static Link * tail = NULL;
+
+static Link *orphans_head = NULL;
+static Link *orphans_tail = NULL;
+
+/* Function Prototypes */
+
+static void rrn_init (void);
+static void scan_directories (void);
+static void scan_directory (char *dir);
+static void process_file (char *filename);
+static void process_section (char *filename);
+static void insert_orphans (void);
+static void reverse_children (void);
+static void process_locale_dirs (char * dir);
+#if ENABLE_OMF_READ
+static void process_omf_dir (char *dir);
+#endif
+
+void
+rrn_set_language (char *lang_code)
+{
+ if (head) {
+ rrn_shutdown ();
+ }
+ rrn_language_init (lang_code);
+ rrn_init ();
+}
+
+static void
+rrn_init (void)
+{
+ scan_directories ();
+
+ return;
+}
+
+void
+rrn_for_each (RrnForeachFunc funct, void * user_data)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+
+ iter = head;
+
+ while (iter) {
+ int res;
+ res = funct (iter->reg.reg, user_data);
+ if (res == FALSE)
+ break;
+ iter = iter->next;
+ }
+
+ return;
+}
+
+void rrn_for_each_in_category (RrnForeachFunc funct, char * category,
+ void *user_data)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+ int res;
+ char **cats;
+
+ cats = iter->reg.reg->categories;
+ while (cats && *cats) {
+ if (!strcmp(*cats, category)) {
+ res = funct (iter->reg.reg, user_data);
+ if (res == FALSE)
+ break;
+ }
+ cats++;
+ }
+ iter = iter->next;
+ }
+
+ return;
+
+}
+
+RrnReg *
+rrn_find_entry_from_uri (char *uri)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+
+ if (!strcmp(iter->reg.reg->uri, uri))
+ return iter->reg.reg;
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+static void
+scan_directories (void)
+{
+ char *cur_path = NULL;
+
+#if ENABLE_INSTALL
+ char *path = NULL;
+ char *first_colon = NULL;
+ char *next_colon = NULL;
+ char *home_dir = NULL;
+ char *home_data_dir = NULL;
+ char *home_env = NULL;
+
+ home_env = getenv ("XDG_DATA_HOME");
+ if (home_env)
+ home_data_dir = strdup(home_env);
+
+ if (!home_data_dir || !strcmp (home_data_dir, "")) {
+ home_dir = getenv ("HOME");
+ if (!home_dir || !strcmp (home_dir, "")) {
+ fprintf (stderr, "Warning: HOME dir is not defined."
+ " Skipping check of XDG_DATA_HOME");
+ goto past;
+ }
+ home_data_dir = malloc (sizeof(char) * (strlen(home_dir)+14));
+ sprintf (home_data_dir, "%s/.local/share", home_dir);
+ }
+
+ /* Reuse home_dir. Bad.*/
+ home_dir = malloc (sizeof (char) * (strlen(home_data_dir)+6));
+
+ sprintf (home_dir, "%s/help", home_data_dir);
+
+#if ENABLE_OMF_READ
+ process_omf_dir (home_data_dir);
+#endif
+
+ free (home_data_dir);
+
+ process_locale_dirs (home_dir);
+ scan_directory (home_dir);
+
+ free (home_dir);
+
+past:
+ path = getenv ("XDG_DATA_DIRS");
+
+ if (!path || !strcmp (path, "")) {
+ path = "/usr/local/share/:/usr/share/";
+ }
+ cur_path = path;
+
+ do {
+ char *int_path = NULL;
+ char *check_path = NULL;
+ first_colon = strchr (cur_path, ':');
+ if (first_colon)
+ int_path = rrn_strndup (cur_path, (first_colon-cur_path));
+ else
+ int_path = strdup (cur_path);
+ check_path = malloc (sizeof(char)*(strlen(int_path)+6));
+ sprintf (check_path, "%s/help", int_path);
+#if ENABLE_OMF_READ
+ process_omf_dir (int_path);
+#endif
+ process_locale_dirs (check_path);
+
+ scan_directory (check_path);
+ if (int_path && *int_path) {
+ free (int_path);
+ }
+ if (check_path) {
+ free (check_path);
+ }
+ cur_path = first_colon+1;
+ } while (first_colon);
+#else
+ cur_path = "data/sk-import";
+ process_locale_dirs (cur_path);
+ scan_directory (cur_path);
+#endif
+ reverse_children ();
+}
+
+static void
+process_locale_dirs (char * dir)
+{
+ DIR *dirp = NULL;
+ char **paths_to_check = NULL;
+ char **iter = NULL;
+
+ paths_to_check = rrn_language_get_dirs (dir);
+ iter = paths_to_check;
+
+ while (*iter) {
+ scan_directory (*iter);
+ free (*iter);
+ iter++;
+ }
+ free (paths_to_check);
+
+}
+
+static void
+scan_directory (char *dir)
+{
+ DIR * dirp = NULL;
+ struct dirent * dp = NULL;
+ struct stat buf;
+ char *path = NULL;
+ dirp = opendir (dir);
+
+ if (access (dir, R_OK)) {
+ return;
+ }
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ char *full_name = NULL;
+ full_name = malloc (sizeof(char)*(strlen (dp->d_name) + strlen(dir) + 2));
+
+ sprintf (full_name, "%s/%s", dir, dp->d_name);
+ stat(full_name,&buf);
+
+ if (S_ISREG(buf.st_mode)) {
+ char *suffix = NULL;
+
+ suffix = strrchr (full_name, '.');
+ if (!strcmp (suffix, ".document")) {
+ process_file (full_name);
+ } else if (!strcmp (suffix, ".section")) {
+ process_section (full_name);
+ }
+ } else if (S_ISDIR(buf.st_mode) && strcmp (dp->d_name, ".") &&
+ strcmp (dp->d_name, "..") &&
+ strcmp (dp->d_name, "LOCALE")) {
+
+ scan_directory (full_name);
+ }
+ free (full_name);
+ } else {
+ goto done;
+ }
+ }
+
+done:
+ insert_orphans ();
+ closedir (dirp);
+ free (path);
+}
+
+static int
+handle_duplicate (RrnReg *reg)
+{
+ Link *iter;
+
+ iter = head;
+
+ while (iter) {
+ if ((iter->reg.reg->heritage && reg->heritage &&
+ !strcmp (iter->reg.reg->heritage, reg->heritage)) ||
+ !strcmp (iter->reg.reg->identifier, reg->identifier)) {
+ if (iter->reg.reg->lang && reg->lang &&
+ rrn_language_use (iter->reg.reg->lang, reg->lang)) {
+ rrn_reg_free (iter->reg.reg);
+ iter->reg.reg = reg;
+ }
+ return TRUE;
+ }
+ iter = iter->next;
+ }
+
+ return FALSE;
+
+}
+
+#if ENABLE_OMF_READ
+static void
+process_omf_dir (char *dir)
+{
+ char *path;
+ DIR * dirp = NULL;
+ char **langs = NULL;
+ char **langs_iter = NULL;
+ int lang_found = FALSE;
+ int lang_count = 0;
+ char *tmp = NULL;
+
+ struct dirent * dp = NULL;
+ struct stat buf;
+
+ langs = rrn_language_get_langs ();
+ path = malloc (sizeof(char) * (strlen (dir)+6));
+
+ sprintf (path, "%s/omf", dir);
+
+ if (access (path, R_OK)) {
+ return;
+ }
+
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ lang_count++;
+ if (!strcmp (*langs_iter, "C")) {
+ lang_found = TRUE;
+ }
+ langs_iter++;
+ }
+ if (!lang_found) {
+ char **tmp;
+ int i = 0;
+ tmp = malloc (sizeof (char *) * (lang_count+2));
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ tmp[i] = strdup (*langs_iter);
+ i++;
+ langs_iter++;
+ }
+ tmp[i] = strdup ("C");
+ i++;
+ tmp[i] = NULL;
+ langs = tmp;
+ }
+
+
+ dirp = opendir (path);
+
+ while (1) {
+ if ((dp = readdir(dirp)) != NULL) {
+ char *full_name;
+ full_name = malloc (sizeof(char) * (strlen(path) + strlen(dp->d_name) + 5));
+ sprintf (full_name, "%s/%s", path, dp->d_name);
+ stat(full_name,&buf);
+ free (full_name);
+ if (S_ISDIR(buf.st_mode) && strcmp (dp->d_name, ".") &&
+ strcmp (dp->d_name, "..")) {
+ langs_iter = langs;
+ while (langs_iter && *langs_iter) {
+ char *lang = (*langs_iter);
+ /* Add extra 2 for separator and NULL. Otherwise, it falls over */
+ tmp = malloc (sizeof (char) * (strlen(dir)+(strlen(dp->d_name)*2) +
+ strlen(lang) + 20));
+ sprintf (tmp, "%s/%s/%s-%s.omf", path, dp->d_name, dp->d_name,(*langs_iter));
+
+ if (!access (tmp, R_OK)) {
+ RrnReg *reg = NULL;
+ reg = rrn_omf_parse_file (tmp);
+ if (reg) {
+ reg->omf_location = strdup (tmp);
+ reg->ghelp_name = strdup (dp->d_name);
+ }
+ if (reg && !handle_duplicate (reg)) {
+ Link *link;
+
+ link = malloc (sizeof (Link));
+ link->reg.reg = reg;
+ link->next = NULL;
+
+ if (!tail) {
+ if (head) {
+ fprintf (stderr, "ERROR: Tail not pointing anywhere. "
+ "Aborting");
+ exit (3);
+ }
+ head = link;
+ tail = link;
+ } else {
+ tail->next = link;
+ tail = link;
+
+ }
+ }
+ }
+ free (tmp);
+ tmp = NULL;
+ langs_iter++;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+done:
+ insert_orphans ();
+ closedir (dirp);
+}
+#endif
+
+static void
+process_section (char *filename)
+{
+ RrnSect *sect = NULL;
+ Link *link;
+
+ sect = rrn_sect_parse_file (filename);
+ if (!sect)
+ return;
+
+ link = malloc (sizeof (Link));
+ link->reg.sect = sect;
+ link->next = NULL;
+ link->prev = NULL;
+
+ if (!orphans_head) {
+ orphans_head = link;
+ orphans_tail = link;
+ } else {
+ orphans_tail->next = link;
+ link->prev = orphans_tail;
+ orphans_tail = link;
+ }
+}
+
+static void
+process_file (char *filename)
+{
+ RrnReg *reg;
+ Link *link;
+
+ reg = rrn_reg_parse_file (filename);
+ if (!reg)
+ return;
+
+ if (handle_duplicate (reg)) {
+ return;
+ }
+
+ link = malloc (sizeof (Link));
+ link->reg.reg = reg;
+ link->next = NULL;
+
+ if (!tail) {
+ if (head) {
+ fprintf (stderr, "ERROR: Tail not pointing anywhere. Aborting");
+ exit (3);
+ }
+ head = link;
+ tail = link;
+ } else {
+ tail->next = link;
+ tail = link;
+
+ }
+}
+
+static void
+insert_orphans ()
+{
+ Link *sect = orphans_head;
+
+ while (sect) {
+ Link *iter = head;
+
+ while (iter) {
+ if (!strncmp (iter->reg.reg->identifier, sect->reg.sect->owner,
+ strlen(iter->reg.reg->identifier))) {
+ break;
+ }
+ iter = iter->next;
+ }
+ if (iter) {
+ sect->reg.sect = rrn_reg_add_sections (iter->reg.reg,
+ sect->reg.sect);
+ if (sect->reg.sect == NULL) {
+ Link *tmp = sect->next;
+ if (sect->prev)
+ sect->prev->next = sect->next;
+ if (sect->next)
+ sect->next->prev = sect->prev;
+ if (sect == orphans_head)
+ orphans_head = NULL;
+ free (sect);
+ sect = tmp;
+ }
+ } else {
+ sect->reg.sect->priority++;
+ sect = sect->next;
+ }
+ }
+}
+
+static RrnSect *
+reverse_child (RrnSect *child)
+{
+ RrnSect *local_tail = NULL;
+ RrnSect *iter = child;
+ RrnSect *tmp = NULL;
+
+ while (iter) {
+ if (iter->children)
+ iter->children = reverse_child (iter->children);
+ tmp = iter->next;
+ iter->next = iter->prev;
+ iter->prev = tmp;
+ if (iter->prev == NULL) {
+ return iter;
+ }
+ iter = iter->prev;
+ }
+}
+
+static void
+reverse_children ()
+{
+ Link *iter = head;
+
+ while (iter) {
+ if (iter->reg.reg->children) {
+ iter->reg.reg->children = reverse_child (iter->reg.reg->children);
+ }
+
+ iter = iter->next;
+ }
+}
+
+RrnReg *
+rrn_find_from_name (char *name)
+{
+ if (!head)
+ rrn_init ();
+
+ return NULL;
+
+
+}
+
+RrnReg *
+rrn_find_from_ghelp (char *ghelp)
+{
+ Link *iter;
+
+ if (!head) {
+ rrn_init ();
+ }
+ iter = head;
+
+ while (iter) {
+ if (iter->reg.reg->ghelp_name && !strcmp(iter->reg.reg->ghelp_name, ghelp))
+ return iter->reg.reg;
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+
+void
+rrn_shutdown ()
+{
+ Link *next;
+
+ while (head) {
+ next = head->next;
+
+ rrn_reg_free (head->reg.reg);
+ free (head);
+ head = next;
+ }
+ rrn_language_shutdown ();
+ head = tail = NULL;
+ return;
+}