/* ***************************************************************************** * * $RCSfile: getmessage.c,v $ * $Date: 1998/07/29 13:02:50 $ * $Source: /home/richard/Xml/RCS/getmessage.c,v $ * $Revision: 1.10 $ * $Author: richard $ * ***************************************************************************** * * Copyright 1998, Brown University and Richard Goerwitz * ***************************************************************************** * * Routines for retrieving strings by number from an external file. * The main entry point is: * * getmessage (message_catalog *mc, char *key) * * This routine is used heavily by the routines in errabort.c. The * message catalog, mc, is normally taken from the global xmlparse_env * structure. For example: * * getmessage (xmlparse_env.messages, "10") * * This would return string number 10 in xmlparse_env.messages catalog. * The xmlparse_env.messages catalog is initialized in readcfg.c after * compiled-in defaults, command-line arguments, and the configuration * file have all been processed. * * The routine that does the initialization is create_message_catalog(), * which takes a single argument - the name of a file containing the * message catalog. The compiled-in default filename is "messages". * Normally create_message_catalog() looks for this file in the default * libdir (xmlparse_env.libdir). If it doesn't find it there, it looks * in the current directory. * ***************************************************************************** * * This file is best viewed with a fixed-width font, on at least a * 100-column display window. * ***************************************************************************** * * Error numbers from 130-139. * ***************************************************************************** */ #include "getmessage.h" #include "errabort.h" #include "fileutil.h" #include "hashutil.h" #include "lockutil.h" #include "strutil.h" static void parse_line_add_to_htable (message_catalog *, char *, int); /* * create_message_catalog * * Allocates and fill out entries in the message catalog. Returns 0 * if it can't open fname (sole argument). Otherwise uses errabort() * and errwarn() to signal problems. */ message_catalog * create_message_catalog (char *fname) { int lineno; FILE *message_file; message_catalog *mc; char *line, pathbuf[MAXPATHLEN]; /* What are we doing? */ xwrap (errdebug (7, "reading message catalog file\n")); /* Keep track of where we were */ xwrap (errdebug (5, "saving current dir\n")); if (getcwd (pathbuf, MAXPATHLEN) == NULL) errabort (136, "can't determine current working directory\n"); /* Try to cd into libdir */ xwrap (errdebug (5, "moving into libdir, %s\n", xmlparse_env.libdir)); if (xmlparse_env.libdir) if (chdir (xmlparse_env.libdir) < 0) { errwarn (72, "can't cd to %s; using cwd\n", xmlparse_env.libdir); free (xmlparse_env.libdir); xmlparse_env.libdir = strdup ("."); } if ((mc = malloc (sizeof (message_catalog))) == NULL) errabort (40, "malloc error in %s\n", "init_message_catalog()"); memset (mc, 0, sizeof (message_catalog)); if ((mc->message_filename = strdup (fname)) == NULL) errabort (40, "malloc error in %s\n", "init_message_catalog()"); /* open message file */ if ((message_file = fopen_and_readlock (fname)) == NULL) /* error message gets emitted by caller */ { mc = NULL; goto restore_dir; } /* create hash table */ if ((mc->htable = rg_create_htable (200)) == NULL) errabort (40, "malloc error in %s\n", "fill_out_message_catalog()"); /* Here's the meat of the message-catalog-reading routine */ lineno = 0; while ((line = getline (message_file, fname, &lineno))) /* parse line into key-data and insert key-data into htable */ parse_line_add_to_htable (mc, line, lineno); fclose_and_unlock (message_file); /* Leave libdir; return to previous working dir */ restore_dir: xwrap (errdebug (5, "restoring current dir\n")); if (chdir (pathbuf) < 0) errabort (73, "can't cd to %s\n", pathbuf); xwrap (errdebug (5, "created in-memory message catalog\n")); return mc; } /* * free_message_catalog * * free() up space used by message catalog mc (this includes the * message_filename string, the hash table, and the message_catalog * structure itself). */ void free_message_catalog (message_catalog *mc) { struct rg_htable_item *item; if (mc != NULL) { if (mc->message_filename != NULL) free (mc->message_filename); if (mc->htable != NULL) { /* free up the strings pointed to by mc->htable items */ item = rg_get_htable_items (mc->htable); while (item != NULL) { free (item->key); free (item->data); item = rg_get_htable_items (NULL); } /* now, free up the skeleton and items themselves */ rg_free_htable (mc->htable); } free (mc); } return; } char * getmessage (message_catalog *mc, char *key) { char *p; size_t len; static char *msg = NULL; static size_t msg_buflen; struct rg_htable_item item, *result; if (mc == NULL) return NULL; if (mc->htable == NULL) return NULL; if (msg == NULL) if ((msg = malloc (msg_buflen = 128)) == NULL) errabort (40, "malloc error in %s\n", "getmessage()"); item.key = key; item.uni_key = NULL; item.data = NULL; p = "(key not found in message catalog)\n"; if ((result = rg_find_item (mc->htable, item)) != NULL) { p = (char *)result->data; if ((len = strlen (p) + 1) > msg_buflen) if ((msg = realloc (msg, msg_buflen = len)) == NULL) errabort (41, "realloc error in %s\n", "getmessage()"); } strcpy (msg, p); return msg; } static void parse_line_add_to_htable (message_catalog *mc, char *line, int lineno) { char *p; struct rg_htable_item item; /* What are we doing? */ xwrap (errdebug (7, "Parsing message catalog file, line %d\n", lineno)); /* Take out trailing #comments */ xwrap (errdebug (7, "stripping out trailing comments: %s\n", line)); trimhash_no_quotes_or_backslash (line); trim (line, " \r\n\t\f"); if (*line == '\0') xwrap (errdebug (7, "blank or commented-out line; skipping\n")); else { /* Look for the first space; that's then end of our key */ for (p = line; ! isspace (*p) && *p != '\0'; p++); if (*p == '\0') errabort (132, "missing message value, line %d\n", lineno); *p = '\0'; item.uni_key = NULL; if ((item.key = get_string (line)) == NULL) errabort (133, "invalid message key, line %d\n", lineno); /* if line contains something of interest */ if ((item.data = get_string (p + 1)) == NULL) errabort (134, "invalid message value, line %d\n", lineno); if (rg_add_item (mc->htable, item) != NULL) errabort (135, "duplicate key, message catalog, line %d\n", lineno); /* What did we just do? */ xwrap (errdebug (5, "added %s::%s to message hash table\n", item.key, item.data)); } return; }