From: Bruno Haible Date: Fri, 9 Jan 2004 11:04:12 +0000 (+0000) Subject: Support for reading and writing C# .resources files. X-Git-Tag: v0.14~77 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a502e5f28692e8e584858dad12055b64ffd47f53;p=thirdparty%2Fgettext.git Support for reading and writing C# .resources files. --- diff --git a/gettext-tools/doc/ChangeLog b/gettext-tools/doc/ChangeLog index 3f903a4d9..8c6ad2e65 100644 --- a/gettext-tools/doc/ChangeLog +++ b/gettext-tools/doc/ChangeLog @@ -1,3 +1,9 @@ +2003-12-28 Bruno Haible + + * gettext.texi (C#): Mention the --csharp-resources option. + * msgfmt.texi: Document the --csharp-resources option. + * msgunfmt.texi: Likewise. + 2003-12-26 Bruno Haible Support for C#. diff --git a/gettext-tools/doc/gettext.texi b/gettext-tools/doc/gettext.texi index b48263658..a8b8281e6 100644 --- a/gettext-tools/doc/gettext.texi +++ b/gettext-tools/doc/gettext.texi @@ -8420,12 +8420,16 @@ Note that these .NET @code{.dll} and @code{.exe} files are not tied to a particular platform; their file format and GNU gettext for C# can be used on any platform. -To convert a PO file to a @code{.resources} file, the @code{resgen} -program (from the @code{pnet} package) or the @code{monoresgen} program -(from the @code{mono}/@code{mcs} package) can be used. These programs -can also convert a @code{.resources} file back to a PO file. But beware: -as of this writing (January 2004), the @code{monoresgen} converter is quite -buggy and the @code{resgen} converter ignores the encoding of the PO files. +To convert a PO file to a @code{.resources} file, the @code{msgfmt} program +can be used with the option @samp{--csharp-resources}. To convert a +@code{.resources} file back to a PO file, the @code{msgunfmt} program can be +used with the option @samp{--csharp-resources}. You can also, in some cases, +use the @code{resgen} program (from the @code{pnet} package) or the +@code{monoresgen} program (from the @code{mono}/@code{mcs} package). These +programs can also convert a @code{.resources} file back to a PO file. But +beware: as of this writing (January 2004), the @code{monoresgen} converter is +quite buggy and the @code{resgen} converter ignores the encoding of the PO +files. To convert a PO file to a @code{.dll} file, the @code{msgfmt} program can be used with the option @code{--csharp}. The result will be a @code{.dll} file diff --git a/gettext-tools/doc/msgfmt.texi b/gettext-tools/doc/msgfmt.texi index 19d256af3..9b06ee138 100644 --- a/gettext-tools/doc/msgfmt.texi +++ b/gettext-tools/doc/msgfmt.texi @@ -45,6 +45,11 @@ Like --java, and assume Java2 (JDK 1.2 or higher). C# mode: generate a .NET .dll file containing a subclass of @code{GettextResourceSet}. +@item --csharp-resources +@opindex --csharp-resources@r{, @code{msgfmt} option} +@cindex C# resources mode, and @code{msgfmt} program +C# resources mode: generate a .NET @file{.resources} file. + @item --tcl @opindex --tcl@r{, @code{msgfmt} option} @cindex Tcl mode, and @code{msgfmt} program diff --git a/gettext-tools/doc/msgunfmt.texi b/gettext-tools/doc/msgunfmt.texi index a760b50c2..6b710cc57 100644 --- a/gettext-tools/doc/msgunfmt.texi +++ b/gettext-tools/doc/msgunfmt.texi @@ -24,6 +24,11 @@ Java mode: input is a Java @code{ResourceBundle} class. C# mode: input is a .NET .dll file containing a subclass of @code{GettextResourceSet}. +@item --csharp-resources +@opindex --csharp-resources@r{, @code{msgunfmt} option} +@cindex C# resources mode, and @code{msgunfmt} program +C# resources mode: input is a .NET @file{.resources} file. + @item --tcl @opindex --tcl@r{, @code{msgunfmt} option} @cindex Tcl mode, and @code{msgunfmt} program diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 599c45610..66040263f 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,45 @@ +2003-12-28 Bruno Haible + + * write-resources.h: New file. + * write-resources.c: New file. + * msgfmt.cs: New file. + * msgfmt.c: Include write-resources.h. + (csharp_resources_mode): New variable. + (long_options): Add --csharp-resources. + (main): Handle --csharp-resources. More generic code for detection of + contradicting modes. Invoke msgdomain_write_csharp_resources. + (usage): Document --csharp-resources option. + (msgfmt_set_domain): Update. + * read-resources.h: New file. + * read-resources.c: New file. + * msgunfmt.cs (DumpResource): Add a constructor that dumps a .resources + file. + (Main): Invoke it when only one argument is given. + * msgunfmt.c: Include read-resources.h. + (csharp_resources_mode): New variable. + (long_options): Add --csharp-resources. + (main): Handle --csharp-resources. More generic code for detection of + contradicting modes. Invoke read_one_file instead of read_mo_file. + (usage): Document --csharp-resources option. + (read_one_file): New function. + * Makefile.am (noinst_HEADERS): Add read-resources.h and + write-resources.h. + (msgfmt_SOURCES): Add write-resources.c. + (msgunfmt_SOURCES): Add read-resources.c. + (EXTRA_DIST): Add msgfmt.cs. + (CLEANFILES): Add msgfmt.net.exe. + (msgfmt.net.exe): New rule. + (all-csharp-yes): Depend on it. + (install-exec-csharp-yes): Also install msgfmt.net.exe. + (uninstall-csharp-yes): Also uninstall msgfmt.net.exe. + * Makefile.msvc (msgfmt_OBJECTS): Add write-resources.obj. + (msgunfmt_OBJECTS): Add read-resources.obj. + (write-resources.obj, read-resources.obj): New rules. + * Makefile.vms (msgfmt_OBJECTS): Add write-resources.obj. + (msgunfmt_OBJECTS): Add read-resources.obj. + (write-resources.obj, read-resources.obj): New rules. + * FILES: Update. + 2003-12-26 Bruno Haible Support for C#. @@ -2118,4 +2160,4 @@ * user-email.in: Use 'gettext' instead of @PACKAGE@. -See ChangeLog.0 for earlier changes. \ No newline at end of file +See ChangeLog.0 for earlier changes. diff --git a/gettext-tools/src/FILES b/gettext-tools/src/FILES index 7a41ed363..40fed3772 100644 --- a/gettext-tools/src/FILES +++ b/gettext-tools/src/FILES @@ -174,6 +174,10 @@ plural-table.c | read-csharp.c | msgunfmt.cs | Reading C# satellite assemblies. +| read-resources.h +| read-resources.c +| msgunfmt.cs +| Reading C# .resources files. | read-tcl.h | read-tcl.c | msgunfmt.tcl @@ -220,6 +224,10 @@ format.c Table of the language dependent format string handlers. | write-csharp.h | write-csharp.c | Generating C# satellite assemblies. +| write-resources.h +| write-resources.c +| msgfmt.cs +| Generating C# .resources files. | write-tcl.h | write-tcl.c | Generating Tcl .msg files. diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index e2a440ada..e1a1478d1 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -40,8 +40,8 @@ str-list.h write-po.h write-properties.h write-stringtable.h dir-list.h \ file-list.h po-gram-gen.h po-gram-gen2.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 plural-count.h read-mo.h write-mo.h read-java.h write-java.h \ -read-csharp.h write-csharp.h read-tcl.h write-tcl.h write-qt.h po-time.h \ -plural-table.h format.h \ +read-csharp.h write-csharp.h read-resources.h write-resources.h read-tcl.h \ +write-tcl.h write-qt.h po-time.h plural-table.h format.h \ xgettext.h x-c.h x-po.h x-sh.h x-python.h x-lisp.h x-elisp.h x-librep.h \ x-smalltalk.h x-java.h x-properties.h x-csharp.h x-awk.h x-ycp.h x-tcl.h \ x-perl.h x-php.h x-stringtable.h x-rst.h x-glade.h @@ -83,8 +83,8 @@ CSHARPCOMPFLAGS = -O -g # All programs deal with message lists. -# All programs must read PO files. (msgunfmt also, for read-java.c and -# read-csharp.c.) +# All programs must read PO files. (msgunfmt also, for read-java.c, +# read-csharp.c and read-resources.c.) # message.c -> str-list.c. # (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> str-list.c. # (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> open-po.c -> dir-list.c -> str-list.c. @@ -120,10 +120,12 @@ LIBUNINAME = ../libuniname/libuniname.a # Source dependencies. msgcmp_SOURCES = msgcmp.c -msgfmt_SOURCES = msgfmt.c write-mo.c write-java.c write-csharp.c write-tcl.c \ +msgfmt_SOURCES = msgfmt.c \ + write-mo.c write-java.c write-csharp.c write-resources.c write-tcl.c \ write-qt.c plural-eval.c msgmerge_SOURCES = msgmerge.c plural-count.c -msgunfmt_SOURCES = msgunfmt.c read-mo.c read-java.c read-csharp.c read-tcl.c +msgunfmt_SOURCES = msgunfmt.c \ + read-mo.c read-java.c read-csharp.c read-resources.c read-tcl.c xgettext_SOURCES = xgettext.c \ x-c.c x-po.c x-sh.c x-python.c x-lisp.c x-elisp.c x-librep.c x-smalltalk.c \ x-java.c x-csharp.c x-awk.c x-ycp.c x-tcl.c x-perl.c x-php.c x-rst.c \ @@ -318,22 +320,26 @@ uninstall-java-no-yes: uninstall-java-no-no: -# Special rules for C# auxiliary program. +# Special rules for C# auxiliary programs. -EXTRA_DIST += msgunfmt.cs +EXTRA_DIST += msgfmt.cs msgunfmt.cs -CLEANFILES += msgunfmt.net.exe +CLEANFILES += msgfmt.net.exe msgunfmt.net.exe all-local: all-csharp-@BUILDCSHARP@ -all-csharp-yes: msgunfmt.net.exe +all-csharp-yes: msgfmt.net.exe msgunfmt.net.exe all-csharp-no: +msgfmt.net.exe: msgfmt.cs + $(CSHARPCOMP) $(CSHARPCOMPFLAGS) -o $@ $(srcdir)/msgfmt.cs + msgunfmt.net.exe: msgunfmt.cs $(CSHARPCOMP) $(CSHARPCOMPFLAGS) -o $@ -L ../../gettext-runtime/intl-csharp -l GNU.Gettext $(srcdir)/msgunfmt.cs install-exec-local: install-exec-csharp-@BUILDCSHARP@ install-exec-csharp-yes: all-csharp-yes $(mkinstalldirs) $(DESTDIR)$(pkglibdir) + $(INSTALL_DATA) msgfmt.net.exe $(DESTDIR)$(pkglibdir)/msgfmt.net.exe $(INSTALL_DATA) msgunfmt.net.exe $(DESTDIR)$(pkglibdir)/msgunfmt.net.exe install-exec-csharp-no: $(mkinstalldirs) $(DESTDIR)$(pkglibdir) @@ -344,6 +350,7 @@ installdirs-csharp: uninstall-local: uninstall-csharp-@BUILDCSHARP@ uninstall-csharp-yes: all-csharp-yes + $(RM) $(DESTDIR)$(pkglibdir)/msgfmt.net.exe $(RM) $(DESTDIR)$(pkglibdir)/msgunfmt.net.exe uninstall-csharp-no: diff --git a/gettext-tools/src/Makefile.msvc b/gettext-tools/src/Makefile.msvc index 6184e338a..00079b432 100644 --- a/gettext-tools/src/Makefile.msvc +++ b/gettext-tools/src/Makefile.msvc @@ -150,9 +150,9 @@ OBJECTS = \ format-qt.obj msgcmp_OBJECTS = msgcmp.obj -msgfmt_OBJECTS = msgfmt.obj write-mo.obj write-java.obj write-csharp.obj write-tcl.obj write-qt.obj plural-eval.obj +msgfmt_OBJECTS = msgfmt.obj write-mo.obj write-java.obj write-csharp.obj write-resources.obj write-tcl.obj write-qt.obj plural-eval.obj msgmerge_OBJECTS = msgmerge.obj plural-count.obj -msgunfmt_OBJECTS = msgunfmt.obj read-mo.obj read-java.obj read-csharp.obj read-tcl.obj +msgunfmt_OBJECTS = msgunfmt.obj read-mo.obj read-java.obj read-csharp.obj read-resources.obj read-tcl.obj xgettext_OBJECTS = xgettext.obj x-c.obj x-po.obj x-sh.obj x-python.obj x-lisp.obj x-elisp.obj x-librep.obj x-smalltalk.obj x-java.obj x-csharp.obj x-awk.obj x-ycp.obj x-tcl.obj x-perl.obj x-php.obj x-rst.obj x-glade.obj msgattrib_OBJECTS = msgattrib.obj msgcat_OBJECTS = msgcat.obj @@ -335,6 +335,9 @@ write-java.obj : write-java.c write-csharp.obj : write-csharp.c $(CC) $(INCLUDES) $(CFLAGS) -c write-csharp.c +write-resources.obj : write-resources.c + $(CC) $(INCLUDES) $(CFLAGS) -c write-resources.c + write-tcl.obj : write-tcl.c $(CC) $(INCLUDES) $(CFLAGS) -c write-tcl.c @@ -362,6 +365,9 @@ read-java.obj : read-java.c read-csharp.obj : read-csharp.c $(CC) $(INCLUDES) $(CFLAGS) -c read-csharp.c +read-resources.obj : read-resources.c + $(CC) $(INCLUDES) $(CFLAGS) -c read-resources.c + read-tcl.obj : read-tcl.c $(CC) $(INCLUDES) $(CFLAGS) -c read-tcl.c diff --git a/gettext-tools/src/Makefile.vms b/gettext-tools/src/Makefile.vms index ef51dddd3..7445330de 100644 --- a/gettext-tools/src/Makefile.vms +++ b/gettext-tools/src/Makefile.vms @@ -96,9 +96,9 @@ OBJECTS = \ format-qt.obj msgcmp_OBJECTS = msgcmp.obj -msgfmt_OBJECTS = msgfmt.obj, write-mo.obj, write-java.obj, write-csharp.obj, write-tcl.obj, write-qt.obj, plural-eval.obj +msgfmt_OBJECTS = msgfmt.obj, write-mo.obj, write-java.obj, write-csharp.obj, write-resources.obj, write-tcl.obj, write-qt.obj, plural-eval.obj msgmerge_OBJECTS = msgmerge.obj, plural-count.obj -msgunfmt_OBJECTS = msgunfmt.obj, read-mo.obj, read-java.obj, read-csharp.obj, read-tcl.obj +msgunfmt_OBJECTS = msgunfmt.obj, read-mo.obj, read-java.obj, read-csharp.obj, read-resources.obj, read-tcl.obj xgettext_OBJECTS = xgettext.obj, x-c.obj, x-po.obj, x-sh.obj, x-python.obj, x-lisp.obj, x-elisp.obj, x-librep.obj, x-smalltalk.obj, x-java.obj, x-csharp.obj, x-awk.obj, x-ycp.obj, x-tcl.obj, x-perl.obj, x-php.obj, x-rst.obj, x-glade.obj msgattrib_OBJECTS = msgattrib.obj msgcat_OBJECTS = msgcat.obj @@ -265,6 +265,9 @@ write-java.obj : write-java.c write-csharp.obj : write-csharp.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) write-csharp.c +write-resources.obj : write-resources.c + $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) write-resources.c + write-tcl.obj : write-tcl.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) write-tcl.c @@ -292,6 +295,9 @@ read-java.obj : read-java.c read-csharp.obj : read-csharp.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) read-csharp.c +read-resources.obj : read-resources.c + $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) read-resources.c + read-tcl.obj : read-tcl.c $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) read-tcl.c diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c index 0eeb626ad..ea052d304 100644 --- a/gettext-tools/src/msgfmt.c +++ b/gettext-tools/src/msgfmt.c @@ -49,6 +49,7 @@ #include "write-mo.h" #include "write-java.h" #include "write-csharp.h" +#include "write-resources.h" #include "write-tcl.h" #include "write-qt.h" @@ -98,6 +99,9 @@ static const char *csharp_resource_name; static const char *csharp_locale_name; static const char *csharp_base_directory; +/* C# resources mode output file specification. */ +static bool csharp_resources_mode; + /* Tcl mode output file specification. */ static bool tcl_mode; static const char *tcl_locale_name; @@ -168,6 +172,7 @@ static const struct option long_options[] = { "check-format", no_argument, NULL, CHAR_MAX + 3 }, { "check-header", no_argument, NULL, CHAR_MAX + 4 }, { "csharp", no_argument, NULL, CHAR_MAX + 10 }, + { "csharp-resources", no_argument, NULL, CHAR_MAX + 11 }, { "directory", required_argument, NULL, 'D' }, { "help", no_argument, NULL, 'h' }, { "java", no_argument, NULL, 'j' }, @@ -339,6 +344,9 @@ main (int argc, char *argv[]) case CHAR_MAX + 10: /* --csharp */ csharp_mode = true; break; + case CHAR_MAX + 11: /* --csharp-resources */ + csharp_resources_mode = true; + break; default: usage (EXIT_FAILURE); break; @@ -370,24 +378,33 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ } /* Check for contradicting options. */ - if (java_mode && csharp_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--java", "--csharp"); - if (java_mode && tcl_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--java", "--tcl"); - if (java_mode && qt_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--java", "--qt"); - if (csharp_mode && tcl_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--csharp", "--tcl"); - if (csharp_mode && qt_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--csharp", "--qt"); - if (tcl_mode && qt_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--tcl", "--qt"); + { + unsigned int modes = + (java_mode ? 1 : 0) + | (csharp_mode ? 2 : 0) + | (csharp_resources_mode ? 4 : 0) + | (tcl_mode ? 8 : 0) + | (qt_mode ? 16 : 0); + static const char *mode_options[] = + { "--java", "--csharp", "--csharp-resources", "--tcl", "--qt" }; + /* More than one bit set? */ + if (modes & (modes - 1)) + { + const char *first_option; + const char *second_option; + unsigned int i; + for (i = 0; ; i++) + if (modes & (1 << i)) + break; + first_option = mode_options[i]; + for (i = i + 1; ; i++) + if (modes & (1 << i)) + break; + second_option = mode_options[i]; + error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), + first_option, second_option); + } + } if (java_mode) { if (output_file_name != NULL) @@ -474,8 +491,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ if (output_file_name != NULL) current_domain = new_domain (output_file_name, - !qt_mode && strict_uniforum ? add_mo_suffix (output_file_name) - : output_file_name); + strict_uniforum && !csharp_resources_mode && !qt_mode + ? add_mo_suffix (output_file_name) + : output_file_name); /* Process all given .po files. */ while (argc > optind) @@ -525,6 +543,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ csharp_base_directory)) exit_status = EXIT_FAILURE; } + else if (csharp_resources_mode) + { + if (msgdomain_write_csharp_resources (domain->mlp, canon_encoding, + domain->domain_name, + domain->file_name)) + exit_status = EXIT_FAILURE; + } else if (tcl_mode) { if (msgdomain_write_tcl (domain->mlp, canon_encoding, @@ -614,6 +639,8 @@ Operation mode:\n")); printf (_("\ --csharp C# mode: generate a .NET .dll file\n")); printf (_("\ + --csharp-resources C# resources mode: generate a .NET .resources file\n")); + printf (_("\ --tcl Tcl mode: generate a tcl/msgcat .msg file\n")); printf (_("\ --qt Qt mode: generate a Qt .qm file\n")); @@ -1479,8 +1506,8 @@ msgfmt_set_domain (default_po_reader_ty *this, char *name) { /* If no output file was given, we change it with each `domain' directive. */ - if (!java_mode && !csharp_mode && !tcl_mode && !qt_mode - && output_file_name == NULL) + if (!java_mode && !csharp_mode && !csharp_resources_mode && !tcl_mode + && !qt_mode && output_file_name == NULL) { size_t correct; diff --git a/gettext-tools/src/msgunfmt.c b/gettext-tools/src/msgunfmt.c index 8293934b6..c0cf2301e 100644 --- a/gettext-tools/src/msgunfmt.c +++ b/gettext-tools/src/msgunfmt.c @@ -39,6 +39,7 @@ #include "read-mo.h" #include "read-java.h" #include "read-csharp.h" +#include "read-resources.h" #include "read-tcl.h" #include "write-po.h" #include "gettext.h" @@ -60,6 +61,9 @@ static const char *csharp_resource_name; static const char *csharp_locale_name; static const char *csharp_base_directory; +/* C# resources mode input file specification. */ +static bool csharp_resources_mode; + /* Tcl mode input file specification. */ static bool tcl_mode; static const char *tcl_locale_name; @@ -72,6 +76,7 @@ static int force_po; static const struct option long_options[] = { { "csharp", no_argument, NULL, CHAR_MAX + 4 }, + { "csharp-resources", no_argument, NULL, CHAR_MAX + 5 }, { "escape", no_argument, NULL, 'E' }, { "force-po", no_argument, &force_po, 1 }, { "help", no_argument, NULL, 'h' }, @@ -100,6 +105,7 @@ static void usage (int status) __attribute__ ((noreturn)) #endif ; +static void read_one_file (message_list_ty *mlp, const char *filename); int @@ -223,6 +229,10 @@ main (int argc, char **argv) csharp_mode = true; break; + case CHAR_MAX + 5: /* --csharp-resources */ + csharp_resources_mode = true; + break; + default: usage (EXIT_FAILURE); break; @@ -247,15 +257,32 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ usage (EXIT_SUCCESS); /* Check for contradicting options. */ - if (java_mode && csharp_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--java", "--csharp"); - if (java_mode && tcl_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--java", "--tcl"); - if (csharp_mode && tcl_mode) - error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), - "--csharp", "--tcl"); + { + unsigned int modes = + (java_mode ? 1 : 0) + | (csharp_mode ? 2 : 0) + | (csharp_resources_mode ? 4 : 0) + | (tcl_mode ? 8 : 0); + static const char *mode_options[] = + { "--java", "--csharp", "--csharp-resources", "--tcl" }; + /* More than one bit set? */ + if (modes & (modes - 1)) + { + const char *first_option; + const char *second_option; + unsigned int i; + for (i = 0; ; i++) + if (modes & (1 << i)) + break; + first_option = mode_options[i]; + for (i = i + 1; ; i++) + if (modes & (1 << i)) + break; + second_option = mode_options[i]; + error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), + first_option, second_option); + } + } if (java_mode) { if (optind < argc) @@ -349,11 +376,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ if (optind < argc) { do - read_mo_file (mlp, argv[optind]); + read_one_file (mlp, argv[optind]); while (++optind < argc); } else - read_mo_file (mlp, "-"); + read_one_file (mlp, "-"); result = msgdomain_list_alloc (false); result->item[0]->messages = mlp; @@ -398,6 +425,8 @@ Operation mode:\n")); printf (_("\ --csharp C# mode: input is a .NET .dll file\n")); printf (_("\ + --csharp-resources C# resources mode: input is a .NET .resources file\n")); + printf (_("\ --tcl Tcl mode: input is a tcl/msgcat .msg file\n")); printf ("\n"); printf (_("\ @@ -487,3 +516,13 @@ Informative output:\n")); exit (status); } + + +static void +read_one_file (message_list_ty *mlp, const char *filename) +{ + if (csharp_resources_mode) + read_resources_file (mlp, filename); + else + read_mo_file (mlp, filename); +} diff --git a/gettext-tools/src/msgunfmt.cs b/gettext-tools/src/msgunfmt.cs index 348ce222f..7243c23e5 100644 --- a/gettext-tools/src/msgunfmt.cs +++ b/gettext-tools/src/msgunfmt.cs @@ -19,14 +19,15 @@ /* * This program dumps a GettextResourceSet subclass (in a satellite assembly) - * as a PO file. + * or a .resources file as a PO file. */ using System; /* Object, String, Type, Console, Exception */ using System.Reflection; /* Assembly, MethodInfo, ConstructorInfo */ -using System.Collections; /* Hashtable */ +using System.Collections; /* Hashtable, DictionaryEntry */ using System.IO; /* BufferedStream, StreamWriter, TextWriter, FileNotFoundException, Path */ using System.Text; /* StringBuilder, UTF8Encoding */ +using System.Resources; /* ResourceReader */ using GNU.Gettext; /* GettextResourceSet */ namespace GNU.Gettext { @@ -68,6 +69,9 @@ namespace GNU.Gettext { } Out.Write('\n'); } + + // ---------------- Dumping a GettextResourceSet ---------------- + private void Dump (GettextResourceSet catalog) { MethodInfo pluralMethod = catalog.GetType().GetMethod("GetMsgidPluralTable", Type.EmptyTypes); @@ -177,9 +181,50 @@ namespace GNU.Gettext { Out.Close(); stream.Close(); } + + // ----------------- Dumping a .resources file ------------------ + + public DumpResource (String filename) { + BufferedStream stream = new BufferedStream(Console.OpenStandardOutput()); + Out = new StreamWriter(stream, new UTF8Encoding()); + ResourceReader rr; + if (filename.Equals("-")) { + BufferedStream input = new BufferedStream(Console.OpenStandardInput()); + // A temporary output stream is needed because ResourceReader expects + // to be able to seek in the Stream. + byte[] contents; + { + MemoryStream tmpstream = new MemoryStream(); + byte[] buf = new byte[1024]; + for (;;) { + int n = input.Read(buf, 0, 1024); + if (n == 0) + break; + tmpstream.Write(buf, 0, n); + } + contents = tmpstream.ToArray(); + tmpstream.Close(); + } + MemoryStream tmpinput = new MemoryStream(contents); + rr = new ResourceReader(tmpinput); + } else { + rr = new ResourceReader(filename); + } + foreach (DictionaryEntry entry in rr) // uses rr.GetEnumerator() + DumpMessage(entry.Key as String, null, entry.Value as String); + rr.Close(); + Out.Close(); + stream.Close(); + } + + // -------------------------------------------------------------- + public static int Main (String[] args) { try { - new DumpResource(args[0], args[1], args[2]); + if (args.Length > 1) + new DumpResource(args[0], args[1], args[2]); + else + new DumpResource(args[0]); } catch (Exception e) { Console.Error.WriteLine(e); Console.Error.WriteLine(e.StackTrace);