]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Smalltalk support.
authorBruno Haible <bruno@clisp.org>
Mon, 9 Sep 2002 11:24:56 +0000 (11:24 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:08:45 +0000 (12:08 +0200)
12 files changed:
NEWS
doc/ChangeLog
doc/gettext.texi
doc/xgettext.texi
src/ChangeLog
src/Makefile.am
src/x-smalltalk.c [new file with mode: 0644]
src/x-smalltalk.h [new file with mode: 0644]
src/xgettext.c
tests/ChangeLog
tests/Makefile.am
tests/lang-smalltalk [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 577f15e08d8145a7a6363e2c9d09d49e972d1091..156951c8d298e6efc3813ebdd11febba7a1fa98a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Version 0.11.6 - September 2002
+
+* xgettext now also supports Smalltalk and PHP.
+\f
+Version 0.11.5 - August 2002
+
+* Bug fixes in the gettext.m4 autoconf macros.
+\f
 Version 0.11.4 - July 2002
 
 * The tools now know about the ISO C 99 <inttypes.h> format string directive
index 4a62043a0373ef92bc47fa9266015070cf40273a..fa7b3f9ee868229f185121c9dd014b0ffa66f034 100644 (file)
@@ -1,3 +1,8 @@
+2002-09-09  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.texi (Smalltalk): Update.
+       * xgettext.texi: Mention language Smalltalk.
+
 2002-08-18  Bruno Haible  <bruno@clisp.org>
 
        * gettext.texi (php-format): New subsection.
index f2415b246fb36d5a93d523732e5961934eea5765..855c4054429289553aee1a09cdd57bab9702fd8a 100644 (file)
@@ -6885,7 +6885,7 @@ that language, and to combine the resulting files using @code{msgcat}.
 @c   Haskell                    9
 @c   Visual Basic               9
 @c   C#                         6
-@c   Smalltalk                  6
+@c   Smalltalk                  6     *
 @c   Basic                      5
 @c   Erlang                     5
 @c   Modula                     5
@@ -7343,37 +7343,33 @@ smalltalk
 @code{st}
 
 @item String syntax
-@code{''abc''}
+@code{'abc'}
 
 @item gettext shorthand
-@code{NLS? ''abc''}
-@*@code{self? ''abc''}
+@code{NLS ? 'abc'}
 
 @item gettext/ngettext functions
 @code{LcMessagesDomain>>#at:}, @code{LcMessagesDomain>>#at:plural:with:}
 
 @item textdomain
-@code{LcMessages>>#?} (returns a @code{LcMessagesDomain} object).@*
-Example: @code{Locale default messages ? 'gettext'}
+@code{LcMessages>>#domain:localeDirectory:} (returns a @code{LcMessagesDomain}
+object).@*
+Example: @code{I18N Locale default messages domain: 'gettext' localeDirectory: /usr/local/share/locale'}
 
 @item bindtextdomain
-@code{LcMessages>>#domain:directory:} (returns a @code{LcMessagesDomain}
-object)
+@code{LcMessages>>#domain:localeDirectory:}, see above.
 
 @item setlocale
-You can obtain any @code{Locale} object from @code{Locale} class methods
-such as @code{#fromString:} or @code{#default}.@*
-Example: @code{Locale default messages} gives the @code{LcMessages}
-object for the default locale.
+Automatic if you use @code{I18N Locale default}.
 
 @item Prerequisite
-The gettext code is contained in the @file{I18N} package.
+@code{PackageLoader fileInPackage: 'I18N'!}
 
 @item Use or emulate GNU gettext
 emulate
 
 @item Extractor
----
+@code{xgettext}
 
 @item Formatting with positions
 @code{'%1 %2' bindWith: 'Hello' with: 'world'}
index 49e3c208318aeeab86723985f02fc26b639e870e..7385d504e902329037d3bc8c1d1a0d14ac430554 100644 (file)
@@ -70,8 +70,8 @@ is written to standard output.
 @cindex supported languages, @code{xgettext}
 Specifies the language of the input files.  The supported languages
 are @code{C}, @code{C++}, @code{ObjectiveC}, @code{PO}, @code{Python},
-@code{Lisp}, @code{EmacsLisp}, @code{librep}, @code{Java}, @code{awk},
-@code{YCP}, @code{Tcl}, @code{PHP}, @code{RST}, @code{Glade}.
+@code{Lisp}, @code{EmacsLisp}, @code{librep}, @code{Smalltalk}, @code{Java},
+@code{awk}, @code{YCP}, @code{Tcl}, @code{PHP}, @code{RST}, @code{Glade}.
 
 @item -C
 @itemx --c++
index 326e23ab1aabb52b5c90f293a36392d424ef098d..d5a0d8ead5764837f5cad8742dcb42310f4b84af 100644 (file)
@@ -1,3 +1,14 @@
+2002-09-09  Bruno Haible  <bruno@clisp.org>
+
+       * x-smalltalk.h: New file.
+       * x-smalltalk.c: New file.
+       * xgettext.c: Include x-smalltalk.h.
+       (usage): Mention Smalltalk language.
+       (language_to_extractor): Add Smalltalk support.
+       (extension_to_language): Likewise.
+       * Makefile.am (noinst_HEADERS): Add x-smalltalk.h.
+       (xgettext_SOURCES): Add x-smalltalk.c.
+
 2002-08-18  Bruno Haible  <bruno@clisp.org>
 
        * message.h (enum format_type): New enum value 'format_php'.
index 1ad2ad0592082cff5ef13c1e217ffd371175b732..96f1a5cd019fd6bffe3eadddceba4885ef08f1b8 100644 (file)
@@ -35,7 +35,8 @@ 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 read-tcl.h write-tcl.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-tcl.h x-php.h x-rst.h x-glade.h
+x-elisp.h x-librep.h x-smalltalk.h x-java.h x-awk.h x-ycp.h x-tcl.h x-php.h \
+x-rst.h x-glade.h
 
 EXTRA_DIST = FILES project-id msgunfmt.tcl \
 gnu/gettext/DumpResource.java gnu/gettext/GetURL.java
@@ -94,8 +95,8 @@ msgfmt_SOURCES = msgfmt.c write-mo.c write-java.c write-tcl.c plural-eval.c
 msgmerge_SOURCES = msgmerge.c
 msgunfmt_SOURCES = msgunfmt.c read-mo.c read-java.c read-tcl.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-tcl.c x-php.c x-rst.c x-glade.c
+  x-c.c x-po.c x-python.c x-lisp.c x-elisp.c x-librep.c x-smalltalk.c \
+  x-java.l x-awk.c x-ycp.c x-tcl.c x-php.c x-rst.c x-glade.c
 msgattrib_SOURCES = msgattrib.c
 msgcat_SOURCES = msgcat.c
 msgcomm_SOURCES = msgcomm.c
diff --git a/src/x-smalltalk.c b/src/x-smalltalk.c
new file mode 100644 (file)
index 0000000..6537ac7
--- /dev/null
@@ -0,0 +1,598 @@
+/* xgettext Smalltalk 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 <stdio.h>
+#include <stdlib.h>
+
+#include "message.h"
+#include "x-smalltalk.h"
+#include "xgettext.h"
+#include "error.h"
+#include "xmalloc.h"
+#include "exit.h"
+#include "gettext.h"
+
+#define _(s) gettext(s)
+
+/* The relevant parts of the Smalltalk syntax are:
+
+     stringliteral ::= string | stringconst | symconst
+     stringconst ::= "#"string
+     string      ::= "'"[char]*"'"
+     symconst    ::= "#"symbol
+     symbol      ::= id | binsel | keysel[keysel]*
+     keysel      ::= id":"
+     id          ::= letter[letter|digit]*
+     letter      ::= "A".."Z" | "a".."z"
+     digit       ::= "0".."9"
+     binsel      ::= selchar[selchar]
+     selchar     ::= "+" | "-" | "*" | "/" | "~" | "|" | "," | "<" | ">"
+                     | "=" | "&" | "@" | "?" | "%" | "\"
+
+   Strings can contain any characters; to include the string delimiter itself,
+   it must be duplicated.
+
+   Character constants are written  "$"char
+
+   Comments are enclosed within double quotes.
+
+   In well-formed expressions, {} and [] and () are balanced.
+ */
+
+enum token_type_ty
+{
+  token_type_eof,
+  token_type_uniq,             /* # */
+  token_type_symbol,           /* symbol */
+  token_type_string_literal,   /* string, stringconst, symbolconst */
+  token_type_other             /* misc. operator */
+};
+typedef enum token_type_ty token_type_ty;
+
+typedef struct token_ty token_ty;
+struct token_ty
+{
+  token_type_ty type;
+  char *string;                /* for token_type_string_literal, token_type_symbol */
+  int line_number;
+};
+
+
+/* Prototypes for local functions.  Needed to ensure compiler checking of
+   function argument counts despite of K&R C function definition syntax.  */
+static int phase1_getc PARAMS ((void));
+static void phase1_ungetc PARAMS ((int c));
+static inline void comment_start PARAMS ((void));
+static inline void comment_add PARAMS ((int c));
+static inline void comment_line_end PARAMS ((void));
+static void phase2_get PARAMS ((token_ty *tp));
+static void phase2_unget PARAMS ((token_ty *tp));
+static void x_smalltalk_lex PARAMS ((token_ty *tp));
+
+
+/* ======================== Reading of characters.  ======================== */
+
+
+/* Real filename, used in error messages about the input file.  */
+static const char *real_file_name;
+
+/* Logical filename and line number, used to label the extracted messages.  */
+static char *logical_file_name;
+static int line_number;
+
+/* The input file stream.  */
+static FILE *fp;
+
+
+/* 1. line_number handling.  */
+
+static int
+phase1_getc ()
+{
+  int c = getc (fp);
+
+  if (c == EOF)
+    {
+      if (ferror (fp))
+       error (EXIT_FAILURE, errno, _("error while reading \"%s\""),
+              real_file_name);
+      return EOF;
+    }
+
+  if (c == '\n')
+    line_number++;
+
+  return c;
+}
+
+static void
+phase1_ungetc (c)
+     int c;
+{
+  if (c != EOF)
+    {
+      if (c == '\n')
+       --line_number;
+
+      ungetc (c, fp);
+    }
+}
+
+
+/* Accumulating comments.  */
+
+static char *buffer;
+static size_t bufmax;
+static size_t buflen;
+
+static inline void
+comment_start ()
+{
+  buflen = 0;
+}
+
+static inline void
+comment_add (c)
+     int c;
+{
+  if (buflen >= bufmax)
+    {
+      bufmax += 100;
+      buffer = xrealloc (buffer, bufmax);
+    }
+  buffer[buflen++] = c;
+}
+
+static inline void
+comment_line_end ()
+{
+  while (buflen >= 1
+        && (buffer[buflen - 1] == ' ' || buffer[buflen - 1] == '\t'))
+    --buflen;
+  if (buflen >= bufmax)
+    {
+      bufmax += 100;
+      buffer = xrealloc (buffer, bufmax);
+    }
+  buffer[buflen] = '\0';
+  xgettext_comment_add (buffer);
+}
+
+
+/* These are for tracking whether comments count as immediately before
+   keyword.  */
+static int last_comment_line;
+static int last_non_comment_line;
+
+
+/* 2. Combine characters into tokens.  Discard comments and whitespace.  */
+
+/* Maximum used guaranteed to be < 2.  */
+static token_ty phase2_pushback[2];
+static int phase2_pushback_length;
+
+static void
+phase2_get (tp)
+     token_ty *tp;
+{
+  static char *buffer;
+  static int bufmax;
+  int bufpos;
+  int c;
+
+  if (phase2_pushback_length)
+    {
+      *tp = phase2_pushback[--phase2_pushback_length];
+      return;
+    }
+
+  tp->string = NULL;
+
+  for (;;)
+    {
+      tp->line_number = line_number;
+      c = phase1_getc ();
+      switch (c)
+       {
+       case EOF:
+         tp->type = token_type_eof;
+         return;
+
+       case '"':
+         {
+           /* Comment.  */
+           int lineno;
+
+           comment_start ();
+           lineno = line_number;
+           for (;;)
+             {
+               c = phase1_getc ();
+               if (c == '"' || c == EOF)
+                 break;
+               if (c == '\n')
+                 {
+                   comment_line_end ();
+                   comment_start ();
+                 }
+               else
+                 {
+                   /* We skip all leading white space, but not EOLs.  */
+                   if (!(buflen == 0 && (c == ' ' || c == '\t')))
+                     comment_add (c);
+                 }
+             }
+           comment_line_end ();
+           last_comment_line = lineno;
+           continue;
+         }
+
+       case '\n':
+         if (last_non_comment_line > last_comment_line)
+           xgettext_comment_reset ();
+         /* FALLTHROUGH */
+       case ' ':
+       case '\t':
+       case '\r':
+         /* Ignore whitespace.  */
+         continue;
+       }
+
+      last_non_comment_line = tp->line_number;
+
+      switch (c)
+       {
+       case '\'':
+         /* String literal.  */
+         bufpos = 0;
+         for (;;)
+           {
+             c = phase1_getc ();
+             if (c == EOF)
+               break;
+             if (c == '\'')
+               {
+                 c = phase1_getc ();
+                 if (c != '\'')
+                   {
+                     phase1_ungetc (c);
+                     break;
+                   }
+               }
+             if (bufpos >= bufmax)
+               {
+                 bufmax += 100;
+                 buffer = xrealloc (buffer, bufmax);
+               }
+             buffer[bufpos++] = c;
+           }
+         if (bufpos >= bufmax)
+           {
+             bufmax += 100;
+             buffer = xrealloc (buffer, bufmax);
+           }
+         buffer[bufpos] = 0;
+         tp->type = token_type_string_literal;
+         tp->string = xstrdup (buffer);
+         return;
+
+       case '+':
+       case '-':
+       case '*':
+       case '/':
+       case '~':
+       case '|':
+       case ',':
+       case '<':
+       case '>':
+       case '=':
+       case '&':
+       case '@':
+       case '?':
+       case '%':
+       case '\\':
+         {
+           char *name;
+           int c2 = phase1_getc ();
+           switch (c2)
+             {
+             case '+':
+             case '-':
+             case '*':
+             case '/':
+             case '~':
+             case '|':
+             case ',':
+             case '<':
+             case '>':
+             case '=':
+             case '&':
+             case '@':
+             case '?':
+             case '%':
+               name = xmalloc (3);
+               name[0] = c;
+               name[1] = c2;
+               name[2] = '\0';
+               tp->type = token_type_symbol;
+               tp->string = name;
+               return;
+             default:
+               phase1_ungetc (c2);
+               break;
+             }
+           name = xmalloc (2);
+           name[0] = c;
+           name[1] = '\0';
+           tp->type = token_type_symbol;
+           tp->string = name;
+           return;
+         }
+
+       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+       case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+       case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+       case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+       case 'Y': case 'Z':
+       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+       case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+       case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+       case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+       case 'y': case 'z':
+         /* Recognize id or id":"[id":"]* or id":"[id":"]*id.  */
+         bufpos = 0;
+         for (;;)
+           {
+             if (bufpos >= bufmax)
+               {
+                 bufmax += 100;
+                 buffer = xrealloc (buffer, bufmax);
+               }
+             buffer[bufpos++] = c;
+             c = phase1_getc ();
+             switch (c)
+               {
+               case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+               case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+               case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+               case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+               case 'Y': case 'Z':
+               case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+               case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+               case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+               case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+               case 'y': case 'z':
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                 continue;
+               case ':':
+                 if (bufpos >= bufmax)
+                   {
+                     bufmax += 100;
+                     buffer = xrealloc (buffer, bufmax);
+                   }
+                 buffer[bufpos++] = c;
+                 c = phase1_getc ();
+                 switch (c)
+                   {
+                   case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+                   case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+                   case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+                   case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+                   case 'Y': case 'Z':
+                   case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+                   case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+                   case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+                   case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+                   case 'y': case 'z':
+                     continue;
+                   default:
+                     phase1_ungetc (c);
+                     break;
+                   }
+                 break;
+               default:
+                 phase1_ungetc (c);
+                 break;
+               }
+             break;
+           }
+         if (bufpos >= bufmax)
+           {
+             bufmax += 100;
+             buffer = xrealloc (buffer, bufmax);
+           }
+         buffer[bufpos] = '\0';
+         tp->string = xstrdup (buffer);
+         tp->type = token_type_symbol;
+         return;
+
+       case '#':
+         /* Uniquification operator.  */
+         tp->type = token_type_uniq;
+         return;
+
+       case '$':
+         c = phase1_getc ();
+         tp->type = token_type_other;
+         return;
+
+       default:
+         tp->type = token_type_other;
+         return;
+       }
+    }
+}
+
+static void
+phase2_unget (tp)
+     token_ty *tp;
+{
+  if (tp->type != token_type_eof)
+    phase2_pushback[phase2_pushback_length++] = *tp;
+}
+
+
+/* 3. Combine "# string_literal" and "# symbol" to a single token.  */
+
+static void
+x_smalltalk_lex (tp)
+     token_ty *tp;
+{
+  phase2_get (tp);
+  if (tp->type == token_type_uniq)
+    {
+      token_ty token2;
+
+      phase2_get (&token2);
+      if (token2.type == token_type_symbol
+         || token2.type == token_type_string_literal)
+       {
+         tp->type = token_type_string_literal;
+         tp->string = token2.string;
+       }
+      else
+       phase2_unget (&token2);
+    }
+}
+
+
+/* ========================= Extracting strings.  ========================== */
+
+/* The file is broken into tokens.  Scan the token stream, looking for the
+   following patterns
+      NLS ? <string>
+      NLS at: <string>
+      NLS at: <string> plural: <string>
+   where <string> is one of
+      string_literal
+      # string_literal
+      # symbol
+ */
+
+void
+extract_smalltalk (f, real_filename, logical_filename, mdlp)
+     FILE *f;
+     const char *real_filename;
+     const char *logical_filename;
+     msgdomain_list_ty *mdlp;
+{
+  message_list_ty *mlp = mdlp->item[0]->messages;
+
+  fp = f;
+  real_file_name = real_filename;
+  logical_file_name = xstrdup (logical_filename);
+  line_number = 1;
+
+  last_comment_line = -1;
+  last_non_comment_line = -1;
+
+  /* Eat tokens until eof is seen.  */
+  {
+    /* 0 when no "NLS" has been seen.
+       1 after "NLS".
+       2 after "NLS ?".
+       3 after "NLS at:".
+       4 after "NLS at: <string>".
+       5 after "NLS at: <string> plural:".  */
+    int state;
+    /* Remember the message containing the msgid, for msgid_plural.
+       Non-NULL in states 4, 5.  */
+    message_ty *plural_mp = NULL;
+
+    /* Start state is 0.  */
+    state = 0;
+
+    for (;;)
+      {
+       token_ty token;
+
+       x_smalltalk_lex (&token);
+
+       switch (token.type)
+         {
+         case token_type_symbol:
+           state = (strcmp (token.string, "NLS") == 0 ? 1 :
+                    strcmp (token.string, "?") == 0 && state == 1 ? 2 :
+                    strcmp (token.string, "at:") == 0 && state == 1 ? 3 :
+                    strcmp (token.string, "plural:") == 0 && state == 4 ? 5 :
+                    0);
+           free (token.string);
+           break;
+
+         case token_type_string_literal:
+           if (state == 2)
+             {
+               lex_pos_ty pos;
+               pos.file_name = logical_file_name;
+               pos.line_number = token.line_number;
+               remember_a_message (mlp, token.string, &pos);
+               state = 0;
+               break;
+             }
+           if (state == 3)
+             {
+               lex_pos_ty pos;
+               pos.file_name = logical_file_name;
+               pos.line_number = token.line_number;
+               plural_mp = remember_a_message (mlp, token.string, &pos);
+               state = 4;
+               break;
+             }
+           if (state == 5)
+             {
+               lex_pos_ty pos;
+               pos.file_name = logical_file_name;
+               pos.line_number = token.line_number;
+               remember_a_message_plural (plural_mp, token.string, &pos);
+               state = 0;
+               break;
+             }
+           state = 0;
+           free (token.string);
+           break;
+
+         case token_type_uniq:
+         case token_type_other:
+           state = 0;
+           break;
+
+         case token_type_eof:
+           break;
+
+         default:
+           abort ();
+         }
+
+       if (token.type == token_type_eof)
+         break;
+      }
+  }
+
+  /* Close scanner.  */
+  fp = NULL;
+  real_file_name = NULL;
+  logical_file_name = NULL;
+  line_number = 0;
+}
diff --git a/src/x-smalltalk.h b/src/x-smalltalk.h
new file mode 100644 (file)
index 0000000..75be85f
--- /dev/null
@@ -0,0 +1,29 @@
+/* xgettext Smalltalk 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_SMALLTALK \
+  { "st",     "Smalltalk"   },                                         \
+
+#define SCANNERS_SMALLTALK \
+  { "Smalltalk",  extract_smalltalk, &formatstring_smalltalk },                \
+
+/* Scan a Smalltalk file and add its translatable strings to mdlp.  */
+extern void extract_smalltalk PARAMS ((FILE *fp, const char *real_filename,
+                                      const char *logical_filename,
+                                      msgdomain_list_ty *mdlp));
index 92b9dbf5098bd84190448b36b4c2ad736a2a26fb..4224c2e95b62b8ef7678f76ab30fed175c9248eb 100644 (file)
@@ -63,6 +63,7 @@
 #include "x-lisp.h"
 #include "x-elisp.h"
 #include "x-librep.h"
+#include "x-smalltalk.h"
 #include "x-java.h"
 #include "x-awk.h"
 #include "x-ycp.h"
@@ -580,8 +581,8 @@ If output file is -, output is written to standard output.\n\
 Choice of input file language:\n\
   -L, --language=NAME            recognise the specified language\n\
                                    (C, C++, ObjectiveC, PO, Python, Lisp,\n\
-                                   EmacsLisp, librep, Java, awk, YCP, Tcl,\n\
-                                   PHP, RST, Glade)\n\
+                                   EmacsLisp, librep, Smalltalk, Java, awk,\n\
+                                   YCP, Tcl, PHP, RST, Glade)\n\
   -C, --c++                      shorthand for --language=C++\n\
 By default the language is guessed depending on the input file name extension.\n\
 "));
@@ -1278,6 +1279,7 @@ language_to_extractor (name)
     SCANNERS_LISP
     SCANNERS_ELISP
     SCANNERS_LIBREP
+    SCANNERS_SMALLTALK
     SCANNERS_JAVA
     SCANNERS_AWK
     SCANNERS_YCP
@@ -1325,6 +1327,7 @@ extension_to_language (extension)
     EXTENSIONS_LISP
     EXTENSIONS_ELISP
     EXTENSIONS_LIBREP
+    EXTENSIONS_SMALLTALK
     EXTENSIONS_JAVA
     EXTENSIONS_AWK
     EXTENSIONS_YCP
index 12a0c5ada9486242613ee7eaf073053a58036e8b..96292d025660decc3ff642c15a03d031293f075f 100644 (file)
@@ -1,3 +1,8 @@
+2002-09-09  Bruno Haible  <bruno@clisp.org>
+
+       * lang-smalltalk: New file.
+       * Makefile.am (TESTS): Add it.
+
 2002-08-18  Bruno Haible  <bruno@clisp.org>
 
        * format-php-1: New file.
index a7ed94a6a072b1bc5c025dc595fc05096656960e..649ec7ec6b2364cce4848f31d420940615de1ee1 100644 (file)
@@ -58,7 +58,7 @@ TESTS = gettext-1 gettext-2 \
        format-tcl-1 format-tcl-2 \
        format-ycp-1 format-ycp-2 \
        plural-1 plural-2 \
-       lang-c lang-c++ lang-objc lang-python lang-clisp lang-elisp lang-librep lang-java lang-gawk lang-pascal lang-ycp lang-tcl lang-php lang-po lang-rst \
+       lang-c lang-c++ lang-objc lang-python lang-clisp lang-elisp lang-librep lang-smalltalk lang-java lang-gawk lang-pascal lang-ycp lang-tcl lang-php lang-po lang-rst \
        rpath-1a rpath-1b \
        rpath-2aaa rpath-2aab rpath-2aac rpath-2aad \
        rpath-2aba rpath-2abb rpath-2abc rpath-2abd \
diff --git a/tests/lang-smalltalk b/tests/lang-smalltalk
new file mode 100755 (executable)
index 0000000..1b39df4
--- /dev/null
@@ -0,0 +1,118 @@
+#! /bin/sh
+
+# Test of gettext facilities in the GNU smalltalk language.
+# Assumes an fr_FR locale is installed.
+# Assumes the following packages are installed: smalltalk.
+
+tmpfiles=""
+trap 'rm -fr $tmpfiles' 1 2 3 15
+
+tmpfiles="$tmpfiles prog.st"
+cat <<\EOF > prog.st
+PackageLoader fileInPackage: 'I18N' !
+
+Object subclass: #Main
+  instanceVariableNames: ''
+  classVariableNames: 'NLS' 
+  poolDictionaries: ''
+  category: 'Program'
+!
+!Main methodsFor: 'running'!
+run
+  | n |
+  NLS := I18N Locale default messages domain: 'prog' localeDirectory: '.'.
+  n := 2.
+  Transcript showCr:
+    (NLS ? '''Your command, please?'', asked the waiter.').
+  Transcript showCr:
+    ((NLS at: 'a piece of cake' plural: '%1 pieces of cake' with: n) bindWith: n).
+  Transcript showCr:
+    ((NLS ? '%1 is replaced by %2.') bindWith: 'FF' with: 'EUR').!
+!
+
+Main new run!
+EOF
+
+tmpfiles="$tmpfiles prog.pot"
+: ${XGETTEXT=xgettext}
+${XGETTEXT} -o prog.pot --omit-header --no-location prog.st
+
+tmpfiles="$tmpfiles prog.ok"
+cat <<EOF > prog.ok
+msgid "'Your command, please?', asked the waiter."
+msgstr ""
+
+#, smalltalk-format
+msgid "a piece of cake"
+msgid_plural "%1 pieces of cake"
+msgstr[0] ""
+msgstr[1] ""
+
+#, smalltalk-format
+msgid "%1 is replaced by %2."
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} prog.ok prog.pot || exit 1
+
+tmpfiles="$tmpfiles fr.po"
+cat <<\EOF > fr.po
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgid "'Your command, please?', asked the waiter."
+msgstr "«Votre commande, s'il vous plait», dit le garçon."
+
+# Les gateaux allemands sont les meilleurs du monde.
+#, smalltalk-format
+msgid "a piece of cake"
+msgid_plural "%1 pieces of cake"
+msgstr[0] "un morceau de gateau"
+msgstr[1] "%1 morceaux de gateau"
+
+# Reverse the arguments.
+#, smalltalk-format
+msgid "%1 is replaced by %2."
+msgstr "%2 remplace %1."
+EOF
+
+tmpfiles="$tmpfiles fr.po.new"
+: ${MSGMERGE=msgmerge}
+${MSGMERGE} -q -o fr.po.new fr.po prog.pot
+
+: ${DIFF=diff}
+${DIFF} fr.po fr.po.new || exit 1
+
+tmpfiles="$tmpfiles fr"
+test -d fr || mkdir fr
+test -d fr/LC_MESSAGES || mkdir fr/LC_MESSAGES
+
+: ${MSGFMT=msgfmt}
+${MSGFMT} -o fr/LC_MESSAGES/prog.mo fr.po
+
+# Test for presence of gst version 2.0.6 or newer.
+(gst --version) >/dev/null 2>/dev/null \
+  || { echo "SKIP: lang-smalltalk"; rm -fr $tmpfiles; exit 77; }
+case `gst --version | sed -n -e 1p | sed -e 's/^[^0-9]*//'` in
+  0.* | 1.* | 2.0 | 2.0.[0-5])
+    echo "SKIP: lang-smalltalk"; rm -fr $tmpfiles; exit 77;;
+esac
+
+tmpfiles="$tmpfiles prog.ok prog.out"
+: ${DIFF=diff}
+cat <<\EOF > prog.ok
+Loading package I18N
+«Votre commande, s'il vous plait», dit le garçon.
+2 morceaux de gateau
+EUR remplace FF.
+EOF
+
+LANGUAGE= LC_ALL=fr_FR gst -Q prog.st > prog.out || exit 1
+${DIFF} prog.ok prog.out || exit 1
+
+rm -fr $tmpfiles
+
+exit 0