]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Support for reading and writing C# .resources files.
authorBruno Haible <bruno@clisp.org>
Fri, 9 Jan 2004 11:04:12 +0000 (11:04 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:36 +0000 (12:11 +0200)
12 files changed:
gettext-tools/doc/ChangeLog
gettext-tools/doc/gettext.texi
gettext-tools/doc/msgfmt.texi
gettext-tools/doc/msgunfmt.texi
gettext-tools/src/ChangeLog
gettext-tools/src/FILES
gettext-tools/src/Makefile.am
gettext-tools/src/Makefile.msvc
gettext-tools/src/Makefile.vms
gettext-tools/src/msgfmt.c
gettext-tools/src/msgunfmt.c
gettext-tools/src/msgunfmt.cs

index 3f903a4d9dcc10dba743c884756488356bea0c09..8c6ad2e65abaef8791a098ebf8d5e19b0948b2a3 100644 (file)
@@ -1,3 +1,9 @@
+2003-12-28  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.texi (C#): Mention the --csharp-resources option.
+       * msgfmt.texi: Document the --csharp-resources option.
+       * msgunfmt.texi: Likewise.
+
 2003-12-26  Bruno Haible  <bruno@clisp.org>
 
        Support for C#.
index b4826365852b68ccf271d7430568e947d3fd9771..a8b8281e607c9f0668763d9912864958319872c3 100644 (file)
@@ -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
index 19d256af3aa998c7526f86e08bb3ba7b7bcceaad..9b06ee138dcc5acd69d2d5d7defcaf9d00cb765f 100644 (file)
@@ -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
index a760b50c27de62dd532df10025ae8f29d5c0cc59..6b710cc579881b9041bf21d608b98186d5a7041c 100644 (file)
@@ -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
index 599c456103f62d3328afeddbe19a6eca3d0e8b32..66040263f7ff0eac8b9bcd33fbd7d7f81a3b3e89 100644 (file)
@@ -1,3 +1,45 @@
+2003-12-28  Bruno Haible  <bruno@clisp.org>
+
+       * 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  <bruno@clisp.org>
 
        Support for C#.
        * 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.
index 7a41ed363ba1b980147bdd17799ada14ab1bbf55..40fed3772569c6e59dcd42e570c82ae5bd46bf5f 100644 (file)
@@ -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.
index e2a440adaac0bb6b4018e36f729d91317439899f..e1a1478d1ed39c0a9f983a247ee8665a2e5658f2 100644 (file)
@@ -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:
 
index 6184e338aa3acfc42ee8190904e912b439bb532d..00079b432a134a3f9501b91c0e5a27d464c5816e 100644 (file)
@@ -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
 
index ef51dddd35d6e1930a4ff32f46639b87bf4a8580..7445330deda56e2372e76fe3b7e3069e0285eefc 100644 (file)
@@ -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
 
index 0eeb626adb663beadd12f581ff119d8afb57819b..ea052d304282163112282af2eb68b4bf7a7ad1d7 100644 (file)
@@ -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;
 
index 8293934b6a0efe23229fd2bcd09cdde9c49e8405..c0cf2301e3f786060c7c1b9ef3a3b1e8ed949dce 100644 (file)
@@ -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);
+}
index 348ce222f425efd6965095d2d421a9a41a4273cc..7243c23e5ffee1eb05b45f4e60e75f5417d35f56 100644 (file)
 
 /*
  * 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);