summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/Makefile.am6
-rw-r--r--src/x-glade.c451
-rw-r--r--src/x-glade.h35
-rw-r--r--src/xgettext.c5
5 files changed, 506 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index ef6eb4c..dea45cd 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2002-01-14 Bruno Haible <bruno@clisp.org>
+
+ * x-glade.h: New file.
+ * x-glade.c: New file.
+ * xgettext.c: Include x-glade.h.
+ (main): Call x_glade_extract_all, x_glade_keyword.
+ (language_to_scanner): Add glade rule.
+ (extension_to_language): Add glade rule.
+ * Makefile.am (noinst_HEADERS): Add x-glade.h.
+ (xgettext_SOURCES): Add x-glade.c.
+ (xgettext_LDADD): Add @LTLIBEXPAT@.
+
2002-01-27 Bruno Haible <bruno@clisp.org>
* message.h (format_type): New enum value 'format_awk'.
diff --git a/src/Makefile.am b/src/Makefile.am
index 1b5ed1f..9eeaca9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,7 +33,7 @@ po-gram-gen.h po-hash-gen.h msgl-charset.h msgl-equal.h msgl-iconv.h \
msgl-ascii.h msgl-cat.h msgl-english.h msgfmt.h msgunfmt.h read-mo.h \
write-mo.h read-java.h write-java.h po-time.h plural-table.h format.h \
xgettext.h x-c.h x-po.h x-python.h x-lisp.h x-elisp.h x-librep.h x-java.h \
-x-awk.h x-ycp.h x-rst.h
+x-awk.h x-ycp.h x-rst.h x-glade.h
EXTRA_DIST = FILES project-id \
gnu/gettext/DumpResource.java gnu/gettext/GetURL.java
@@ -88,7 +88,7 @@ msgmerge_SOURCES = msgmerge.c
msgunfmt_SOURCES = msgunfmt.c read-mo.c read-java.c
xgettext_SOURCES = xgettext.c \
x-c.c x-po.c x-python.c x-lisp.c x-elisp.c x-librep.c x-java.l x-awk.c \
- x-ycp.c x-rst.c
+ x-ycp.c x-rst.c x-glade.c
msgattrib_SOURCES = msgattrib.c
msgcat_SOURCES = msgcat.c
msgcomm_SOURCES = msgcomm.c
@@ -118,7 +118,7 @@ msgcmp_LDADD = libgettextsrc.la
msgfmt_LDADD = libgettextsrc.la
msgmerge_LDADD = libgettextsrc.la
msgunfmt_LDADD = libgettextsrc.la
-xgettext_LDADD = libgettextsrc.la $(LIBUNINAME)
+xgettext_LDADD = libgettextsrc.la $(LIBUNINAME) @LTLIBEXPAT@
msgattrib_LDADD = libgettextsrc.la
msgcat_LDADD = libgettextsrc.la
msgcomm_LDADD = libgettextsrc.la
diff --git a/src/x-glade.c b/src/x-glade.c
new file mode 100644
index 0000000..10d1f2f
--- /dev/null
+++ b/src/x-glade.c
@@ -0,0 +1,451 @@
+/* xgettext glade backend.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+ This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if DYNLOAD_LIBEXPAT
+# include <dlfcn.h>
+#else
+# if HAVE_LIBEXPAT
+# include <expat.h>
+# endif
+#endif
+
+#include "message.h"
+#include "x-glade.h"
+#include "xgettext.h"
+#include "error.h"
+#include "xerror.h"
+#include "basename.h"
+#include "progname.h"
+#include "xmalloc.h"
+#include "exit.h"
+#include "hash.h"
+#include "po-charset.h"
+#include "msgl-ascii.h"
+#include "msgl-iconv.h"
+#include "gettext.h"
+
+#define _(s) gettext(s)
+
+
+/* glade is an XML based format. Some example files are contained in
+ libglade-0.16. */
+
+
+/* Prototypes for local functions. Needed to ensure compiler checking of
+ function argument counts despite of K&R C function definition syntax. */
+static void init_keywords PARAMS ((void));
+
+
+/* ====================== Keyword set customization. ====================== */
+
+/* If true extract all strings. */
+static bool extract_all = false;
+
+static hash_table keywords;
+static bool default_keywords = true;
+
+
+void
+x_glade_extract_all ()
+{
+ extract_all = true;
+}
+
+
+void
+x_glade_keyword (name)
+ const char *name;
+{
+ if (name == NULL)
+ default_keywords = false;
+ else
+ {
+ if (keywords.table == NULL)
+ init_hash (&keywords, 100);
+
+ insert_entry (&keywords, name, strlen (name), NULL);
+ }
+}
+
+/* Finish initializing the keywords hash table.
+ Called after argument processing, before each file is processed. */
+static void
+init_keywords ()
+{
+ if (default_keywords)
+ {
+ x_glade_keyword ("label");
+ x_glade_keyword ("title");
+ x_glade_keyword ("text");
+ x_glade_keyword ("format");
+ x_glade_keyword ("copyright");
+ x_glade_keyword ("comments");
+ x_glade_keyword ("preview_text");
+ x_glade_keyword ("tooltip");
+ default_keywords = false;
+ }
+}
+
+
+/* ===================== Dynamic loading of libexpat. ===================== */
+
+#if DYNLOAD_LIBEXPAT
+
+/* Prototypes for local functions. Needed to ensure compiler checking of
+ function argument counts despite of K&R C function definition syntax. */
+static bool load_libexpat PARAMS ((void));
+
+typedef void *XML_Parser;
+typedef char XML_Char;
+typedef char XML_LChar;
+enum XML_Error { XML_ERROR_NONE };
+typedef void (*XML_StartElementHandler) PARAMS ((void *userData, const XML_Char *name, const XML_Char **atts));
+typedef void (*XML_EndElementHandler) PARAMS ((void *userData, const XML_Char *name));
+typedef void (*XML_CharacterDataHandler) PARAMS ((void *userData, const XML_Char *s, int len));
+typedef void (*XML_CommentHandler) PARAMS ((void *userData, const XML_Char *data));
+
+static XML_Parser (*p_XML_ParserCreate) PARAMS ((const XML_Char *encoding));
+static void (*p_XML_SetElementHandler) PARAMS ((XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end));
+static void (*p_XML_SetCharacterDataHandler) PARAMS ((XML_Parser parser, XML_CharacterDataHandler handler));
+static void (*p_XML_SetCommentHandler) PARAMS ((XML_Parser parser, XML_CommentHandler handler));
+static int (*p_XML_Parse) PARAMS ((XML_Parser parser, const char *s, int len, int isFinal));
+static enum XML_Error (*p_XML_GetErrorCode) PARAMS ((XML_Parser parser));
+static int (*p_XML_GetCurrentLineNumber) PARAMS ((XML_Parser parser));
+static int (*p_XML_GetCurrentColumnNumber) PARAMS ((XML_Parser parser));
+static void (*p_XML_ParserFree) PARAMS ((XML_Parser parser));
+static const XML_LChar * (*p_XML_ErrorString) PARAMS ((int code));
+
+#define XML_ParserCreate (*p_XML_ParserCreate)
+#define XML_SetElementHandler (*p_XML_SetElementHandler)
+#define XML_SetCharacterDataHandler (*p_XML_SetCharacterDataHandler)
+#define XML_SetCommentHandler (*p_XML_SetCommentHandler)
+#define XML_Parse (*p_XML_Parse)
+#define XML_GetErrorCode (*p_XML_GetErrorCode)
+#define XML_GetCurrentLineNumber (*p_XML_GetCurrentLineNumber)
+#define XML_GetCurrentColumnNumber (*p_XML_GetCurrentColumnNumber)
+#define XML_ParserFree (*p_XML_ParserFree)
+#define XML_ErrorString (*p_XML_ErrorString)
+
+static int libexpat_loaded = 0;
+
+static bool
+load_libexpat ()
+{
+ if (libexpat_loaded == 0)
+ {
+ void *handle = dlopen ("libexpat.so.0", RTLD_LAZY);
+ if (handle != NULL
+ && (p_XML_ParserCreate = dlsym (handle, "XML_ParserCreate")) != NULL
+ && (p_XML_SetElementHandler = dlsym (handle, "XML_SetElementHandler")) != NULL
+ && (p_XML_SetCharacterDataHandler = dlsym (handle, "XML_SetCharacterDataHandler")) != NULL
+ && (p_XML_SetCommentHandler = dlsym (handle, "XML_SetCommentHandler")) != NULL
+ && (p_XML_Parse = dlsym (handle, "XML_Parse")) != NULL
+ && (p_XML_GetErrorCode = dlsym (handle, "XML_GetErrorCode")) != NULL
+ && (p_XML_GetCurrentLineNumber = dlsym (handle, "XML_GetCurrentLineNumber")) != NULL
+ && (p_XML_GetCurrentColumnNumber = dlsym (handle, "XML_GetCurrentColumnNumber")) != NULL
+ && (p_XML_ParserFree = dlsym (handle, "XML_ParserFree")) != NULL
+ && (p_XML_ErrorString = dlsym (handle, "XML_ErrorString")) != NULL)
+ libexpat_loaded = 1;
+ else
+ libexpat_loaded = -1;
+ }
+ return libexpat_loaded >= 0;
+}
+
+#define LIBEXPAT_AVAILABLE() (load_libexpat ())
+
+#elif HAVE_LIBEXPAT
+
+#define LIBEXPAT_AVAILABLE() true
+
+#endif
+
+/* ============================= XML parsing. ============================= */
+
+#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
+
+/* Prototypes for local functions. Needed to ensure compiler checking of
+ function argument counts despite of K&R C function definition syntax. */
+static void ensure_stack_size PARAMS ((size_t size));
+static void start_element_handler PARAMS ((void *userData, const char *name,
+ const char **attributes));
+static void end_element_handler PARAMS ((void *userData, const char *name));
+static void character_data_handler PARAMS ((void *userData, const char *s,
+ int len));
+static void comment_handler PARAMS ((void *userData, const char *data));
+static void do_extract_glade PARAMS ((FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ msgdomain_list_ty *mdlp));
+
+
+/* Accumulator for the extracted messages. */
+static message_list_ty *mlp;
+
+/* Logical filename, used to label the extracted messages. */
+static char *logical_file_name;
+
+/* XML parser. */
+static XML_Parser parser;
+
+struct element_state
+{
+ bool extract_string;
+ int lineno;
+ char *buffer;
+ size_t bufmax;
+ size_t buflen;
+};
+static struct element_state *stack;
+static size_t stack_size;
+
+/* Ensures stack_size >= size. */
+static void
+ensure_stack_size (size)
+ size_t size;
+{
+ if (size > stack_size)
+ {
+ stack_size = 2 * stack_size;
+ if (stack_size < size)
+ stack_size = size;
+ stack =
+ (struct element_state *)
+ xrealloc (stack, stack_size * sizeof (struct element_state));
+ }
+}
+
+static size_t stack_depth;
+
+/* Callback called when <element> is seen. */
+static void
+start_element_handler (userData, name, attributes)
+ void *userData;
+ const char *name;
+ const char **attributes;
+{
+ struct element_state *p;
+ void *hash_result;
+
+ /* Increase stack depth. */
+ stack_depth++;
+ ensure_stack_size (stack_depth + 1);
+
+ /* Don't extract a string for the containing element. */
+ stack[stack_depth - 1].extract_string = false;
+
+ p = &stack[stack_depth];
+ p->extract_string =
+ (find_entry (&keywords, name, strlen (name), &hash_result) == 0);
+ p->lineno = XML_GetCurrentLineNumber (parser);
+ p->buffer = NULL;
+ p->bufmax = 0;
+ p->buflen = 0;
+ if (!p->extract_string)
+ xgettext_comment_reset ();
+}
+
+/* Callback called when </element> is seen. */
+static void
+end_element_handler (userData, name)
+ void *userData;
+ const char *name;
+{
+ struct element_state *p = &stack[stack_depth];
+
+ /* Actually extract string. */
+ if (p->extract_string)
+ {
+ /* Don't extract the empty string. */
+ if (p->buflen > 0)
+ {
+ lex_pos_ty pos;
+
+ if (p->buflen == p->bufmax)
+ p->buffer = (char *) xrealloc (p->buffer, p->buflen + 1);
+ p->buffer[p->buflen] = '\0';
+
+ pos.file_name = logical_file_name;
+ pos.line_number = p->lineno;
+
+ remember_a_message (mlp, p->buffer, &pos);
+ p->buffer = NULL;
+ }
+ }
+
+ /* Free memory for this stack level. */
+ if (p->buffer != NULL)
+ free (p->buffer);
+
+ /* Decrease stack depth. */
+ stack_depth--;
+
+ xgettext_comment_reset ();
+}
+
+/* Callback called when some text is seen. */
+static void
+character_data_handler (userData, s, len)
+ void *userData;
+ const char *s;
+ int len;
+{
+ struct element_state *p = &stack[stack_depth];
+
+ /* Accumulate character data. */
+ if (len > 0)
+ {
+ if (p->buflen + len > p->bufmax)
+ {
+ p->bufmax = 2 * p->bufmax;
+ if (p->bufmax < p->buflen + len)
+ p->bufmax = p->buflen + len;
+ p->buffer = (char *) xrealloc (p->buffer, p->bufmax);
+ }
+ memcpy (p->buffer + p->buflen, s, len);
+ p->buflen += len;
+ }
+}
+
+/* Callback called when some comment text is seen. */
+static void
+comment_handler (userData, data)
+ void *userData;
+ const char *data;
+{
+ /* Split multiline comment into lines, and remove leading and trailing
+ whitespace. */
+ char *copy = xstrdup (data);
+ char *p = copy;
+ char *q;
+
+ for (p = copy; (q = strchr (p, '\n')) != NULL; p = q + 1)
+ {
+ while (p[0] == ' ' || p[0] == '\t')
+ p++;
+ while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
+ q--;
+ *q = '\0';
+ xgettext_comment_add (p);
+ }
+ q = p + strlen (p);
+ while (p[0] == ' ' || p[0] == '\t')
+ p++;
+ while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
+ q--;
+ *q = '\0';
+ xgettext_comment_add (p);
+ free (copy);
+}
+
+
+static void
+do_extract_glade (fp, real_filename, logical_filename, mdlp)
+ FILE *fp;
+ const char *real_filename;
+ const char *logical_filename;
+ msgdomain_list_ty *mdlp;
+{
+ mlp = mdlp->item[0]->messages;
+
+ logical_file_name = xstrdup (logical_filename);
+
+ init_keywords ();
+
+ parser = XML_ParserCreate (NULL);
+ if (parser == NULL)
+ error (EXIT_FAILURE, 0, _("memory exhausted"));
+
+ XML_SetElementHandler (parser, start_element_handler, end_element_handler);
+ XML_SetCharacterDataHandler (parser, character_data_handler);
+ XML_SetCommentHandler (parser, comment_handler);
+
+ while (!feof (fp))
+ {
+ char buf[4096];
+ int count = fread (buf, 1, sizeof buf, fp);
+
+ if (count == 0)
+ {
+ if (ferror (fp))
+ error (EXIT_FAILURE, errno, _("\
+error while reading \"%s\""), real_filename);
+ /* EOF reached. */
+ break;
+ }
+
+ if (XML_Parse (parser, buf, count, 0) == 0)
+ error (EXIT_FAILURE, 0, _("%s:%d:%d: %s"), logical_filename,
+ XML_GetCurrentLineNumber (parser),
+ XML_GetCurrentColumnNumber (parser) + 1,
+ XML_ErrorString (XML_GetErrorCode (parser)));
+ }
+
+ if (XML_Parse (parser, NULL, 0, 1) == 0)
+ error (EXIT_FAILURE, 0, _("%s:%d:%d: %s"), logical_filename,
+ XML_GetCurrentLineNumber (parser),
+ XML_GetCurrentColumnNumber (parser) + 1,
+ XML_ErrorString (XML_GetErrorCode (parser)));
+
+ XML_ParserFree (parser);
+
+ /* expat feeds us strings in UTF-8 encoding. If not all the strings
+ were plain ASCII, set the charset in the header to UTF-8. */
+ if (!is_ascii_message_list (mlp))
+ {
+ const char *canon_utf_8 = po_charset_canonicalize ("UTF-8");
+ iconv_message_list (mlp, canon_utf_8, canon_utf_8);
+ }
+
+ /* Close scanner. */
+ logical_file_name = NULL;
+ parser = NULL;
+}
+
+#endif
+
+void
+extract_glade (fp, real_filename, logical_filename, mdlp)
+ FILE *fp;
+ const char *real_filename;
+ const char *logical_filename;
+ msgdomain_list_ty *mdlp;
+{
+#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
+ if (LIBEXPAT_AVAILABLE ())
+ do_extract_glade (fp, real_filename, logical_filename, mdlp);
+ else
+#endif
+ {
+ multiline_error (xstrdup (""),
+ xasprintf (_("\
+Language \"glade\" is not supported. %s relies on expat.\n\
+This version was built without expat.\n"),
+ basename (program_name)));
+ exit (EXIT_FAILURE);
+ }
+}
diff --git a/src/x-glade.h b/src/x-glade.h
new file mode 100644
index 0000000..3d9672a
--- /dev/null
+++ b/src/x-glade.h
@@ -0,0 +1,35 @@
+/* xgettext glade backend.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2002.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#define EXTENSIONS_GLADE \
+ { "glade", "glade" }, \
+
+#define SCANNERS_GLADE \
+ { "glade", extract_glade, NULL }, \
+
+/* Scan a glade XML file and add its translatable strings to mdlp. */
+extern void extract_glade PARAMS ((FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ msgdomain_list_ty *mdlp));
+
+
+/* Handling of options specific to this language. */
+
+extern void x_glade_extract_all PARAMS ((void));
+extern void x_glade_keyword PARAMS ((const char *name));
diff --git a/src/xgettext.c b/src/xgettext.c
index 11f174d..c9381be 100644
--- a/src/xgettext.c
+++ b/src/xgettext.c
@@ -67,6 +67,7 @@
#include "x-awk.h"
#include "x-ycp.h"
#include "x-rst.h"
+#include "x-glade.h"
/* If nonzero add all comments immediately preceding one of the keywords. */
@@ -231,6 +232,7 @@ main (argc, argv)
x_librep_extract_all ();
x_java_extract_all ();
x_awk_extract_all ();
+ x_glade_extract_all ();
break;
case 'c':
if (optarg == NULL)
@@ -287,6 +289,7 @@ main (argc, argv)
x_librep_keyword (optarg);
x_java_keyword (optarg);
x_awk_keyword (optarg);
+ x_glade_keyword (optarg);
}
break;
case 'K':
@@ -1258,6 +1261,7 @@ language_to_extractor (name)
SCANNERS_AWK
SCANNERS_YCP
SCANNERS_RST
+ SCANNERS_GLADE
/* Here will follow more languages and their scanners: perl, etc...
Make sure new scanners honor the --exclude-file option. */
};
@@ -1302,6 +1306,7 @@ extension_to_language (extension)
EXTENSIONS_AWK
EXTENSIONS_YCP
EXTENSIONS_RST
+ EXTENSIONS_GLADE
/* Here will follow more file extensions: sh, pl, tcl ... */
};