diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 12 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/x-glade.c | 451 | ||||
-rw-r--r-- | src/x-glade.h | 35 | ||||
-rw-r--r-- | src/xgettext.c | 5 |
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 ... */ }; |