diff --git a/configure b/configure
index 17e1db1e3e897acb91e6c074b9eb7c958c3d9f56..01c0a9d946714075119c8ca18aee340f89cf2777 100755
--- a/configure
+++ b/configure
@@ -845,7 +845,6 @@ if test -n "$ac_init_help"; then
 Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
-  --enable-locale         enable locale support
   --enable-recode         enable character set recode support
   --enable-multibyte      enable multibyte character support
   --enable-nls[=LANGUAGES]  enable Native Language Support
@@ -1570,44 +1569,6 @@ fi;
 
 
 
-#
-# Locale (--enable-locale)
-#
-echo "$as_me:$LINENO: checking whether to build with locale support" >&5
-echo $ECHO_N "checking whether to build with locale support... $ECHO_C" >&6
-
-
-# Check whether --enable-locale or --disable-locale was given.
-if test "${enable_locale+set}" = set; then
-  enableval="$enable_locale"
-
-  case $enableval in
-    yes)
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_LOCALE 1
-_ACEOF
-
-      ;;
-    no)
-      :
-      ;;
-    *)
-      { { echo "$as_me:$LINENO: error: no argument expected for --enable-locale option" >&5
-echo "$as_me: error: no argument expected for --enable-locale option" >&2;}
-   { (exit 1); exit 1; }; }
-      ;;
-  esac
-
-else
-  enable_locale=no
-
-fi;
-
-echo "$as_me:$LINENO: result: $enable_locale" >&5
-echo "${ECHO_T}$enable_locale" >&6
-
-
 #
 # Character set recode (--enable-recode)
 #
diff --git a/configure.in b/configure.in
index 1d5a3703f9c3e1774d4f1c07e3d3eb98e4188bb6..7fbf76e32b4752fef6843423fa79713b5b42374a 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $Header: /cvsroot/pgsql/configure.in,v 1.174 2002/04/01 01:11:00 tgl Exp $
+dnl $Header: /cvsroot/pgsql/configure.in,v 1.175 2002/04/03 05:39:27 petere Exp $
 
 dnl Developers, please strive to achieve this order:
 dnl
@@ -140,16 +140,6 @@ PGAC_ARG_REQ(with, libs,      [  --with-libs=DIRS        alternative spelling of
              [LIBRARY_DIRS=$withval])
 
 
-#
-# Locale (--enable-locale)
-#
-AC_MSG_CHECKING([whether to build with locale support])
-PGAC_ARG_BOOL(enable, locale, no, [  --enable-locale         enable locale support],
-              [AC_DEFINE([USE_LOCALE], 1,
-                         [Set to 1 if you want LOCALE support (--enable-locale)])])
-AC_MSG_RESULT([$enable_locale])
-
-
 #
 # Character set recode (--enable-recode)
 #
diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml
index 29cc7e528efb1ca77583c3edf79f22381e234e3d..a19940ce9a6e6a606087bb53f8210ca302b77a82 100644
--- a/doc/src/sgml/charset.sgml
+++ b/doc/src/sgml/charset.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.23 2002/03/22 19:20:05 petere Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.24 2002/04/03 05:39:27 petere Exp $ -->
 
 <chapter id="charset">
  <title>Localization</>
@@ -63,35 +63,24 @@
   <sect2>
    <title>Overview</>
 
-  <para>
-    Locale support is not built into <productname>PostgreSQL</> by
-    default; to enable it, supply the <option>--enable-locale</> option
-    to the <filename>configure</> script:
-<informalexample>
+   <para>
+    Locale support is automatically initialized when a database
+    cluster is created using <command>initdb</command>.
+    <command>initdb</command> will initialize the database cluster
+    with the locale setting of its execution environment; so if your
+    system is already set to use the locale that you want in your
+    database cluster then there is nothing else you need to do.  If
+    you want to use a different locale (or you are not sure which
+    locale your system is set to), you can tell
+    <command>initdb</command> exactly which locale you want with the
+    option <option>--locale</option>.  For example:
 <screen>
-<prompt>$ </><userinput>./configure --enable-locale</>
+<prompt>$ </><userinput>initdb --locale=sv_SE</>
 </screen>
-</informalexample>
-    Locale support only affects the server; all clients are compatible
-    with servers with or without locale support.
-   </para>
-
-   <para>
-    To enable messages translated to the user's preferred language,
-    the <option>--enable-nls</option> option must be used.  This
-    option is independent of the other locale support.
    </para>
 
    <para>
-    The information about which particular cultural rules to use is
-    determined by standard environment variables.  If you are getting
-    localized behavior from other programs you probably have them set
-    up already.  The simplest way to set the localization information
-    is the <envar>LANG</> variable, for example:
-<programlisting>
-export LANG=sv_SE
-</programlisting>
-    This sets the locale to Swedish (<literal>sv</>) as spoken in
+    This example sets the locale to Swedish (<literal>sv</>) as spoken in
     Sweden (<literal>SE</>).  Other possibilities might be
     <literal>en_US</> (U.S. English) and <literal>fr_CA</> (Canada,
     French).  If more than one character set can be useful for a locale
@@ -103,9 +92,9 @@ export LANG=sv_SE
 
    <para>
     Occasionally it is useful to mix rules from several locales, e.g.,
-    use U.S. collation rules but Spanish messages.  To do that a set of
-    environment variables exist that override the default of
-    <envar>LANG</> for a particular category:
+    use U.S. collation rules but Spanish messages.  To support that, a
+    set of locale subcategories exist that control only a certain
+    aspect of the localization rules.
 
     <informaltable>
      <tgroup cols="2">
@@ -138,49 +127,79 @@ export LANG=sv_SE
      </tgroup>
     </informaltable>
 
-    Additionally, all of these specific variables and the
-    <envar>LANG</> variable can be overridden with the
-    <envar>LC_ALL</> environment variable.
+    The category names translate into names of
+    <command>initdb</command> options to override the locale choice
+    for a specific category.  For instance, to set the locale to
+    French Canadian, but use U.S. rules for formatting currency, use
+    <literal>initdb --locale=fr_CA --lc-monetary=en_US</literal>.
    </para>
 
-   <note>
-    <para>
-     Some message localization libraries also look at the environment
-     variable <envar>LANGUAGE</envar> which overrides all other locale
-     settings for the purpose of setting the language of messages.  If
-     in doubt, please refer to the documentation of your operating
-     system, in particular the
-     <citerefentry><refentrytitle>gettext</><manvolnum>3</></> manual
-     page, for more information.
-    </para>
-   </note>
-
    <para>
     If you want the system to behave as if it had no locale support,
-    use the special locale <literal>C</> or <literal>POSIX</>, or
-    simply unset all locale-related variables.
+    use the special locale <literal>C</> or <literal>POSIX</>.
+   </para>
+
+   <para>
+    The nature of some locale categories is that their value has to be
+    fixed for the lifetime of a database cluster.  That is, once
+    <command>initdb</command> has run, you cannot change them anymore.
+    <literal>LC_COLLATE</literal> and <literal>LC_CTYPE</literal> are
+    those categories.  They affect the sort order of indexes, so they
+    must be kept fixed, or indexes on text columns will become corrupt.
+    <productname>PostgreSQL</productname> enforces this by recording
+    the values of <envar>LC_COLLATE</> and <envar>LC_CTYPE</> that are
+    seen by <command>initdb</>.  The server automatically adopts
+    those two values when it is started.
+   </para>
+
+   <para>
+    The other locale categories can be changed as desired whenever the
+    server is started by setting the run-time configuration variables
+    that have the same name as the locale categories (see <xref
+    linkend="runtime-config"> for details).  The defaults that are
+    chosen by <command>initdb</command> are actually only written into
+    the configuration file <filename>postgresql.conf</filename> to
+    serve as defaults when the server is started.  If you delete the
+    assignments from <filename>postgresql.conf</filename> then the
+    server will inherit the settings from the execution environment.
    </para>
 
    <para>
     Note that the locale behavior of the server is determined by the
     environment variables seen by the server, not by the environment
-    of any client.  Therefore, be careful to set these variables
+    of any client.  Therefore, be careful to configure the correct locale settings
     before starting the server.  A consequence of this is that if
     client and server are set up to different locales, messages may
     appear in different languages depending on where they originated.
    </para>
 
+   <note>
+    <para>
+     When we speak of inheriting the locale from the execution
+     environment, this means the following on most operating systems:
+     For a given locale category, say the collation, the following
+     environment variables are consulted in this order until one is
+     found to be set: <envar>LC_ALL</envar>, <envar>LC_COLLATE</envar>
+     (the variable corresponding to the respective category),
+     <envar>LANG</envar>.  If none of these environment variables are
+     set then the locale defaults to <literal>C</literal>.
+    </para>
+
+    <para>
+     Some message localization libraries also look at the environment
+     variable <envar>LANGUAGE</envar> which overrides all other locale
+     settings for the purpose of setting the language of messages.  If
+     in doubt, please refer to the documentation of your operating
+     system, in particular the
+     <citerefentry><refentrytitle>gettext</><manvolnum>3</></> manual
+     page, for more information.
+    </para>
+   </note>
+
    <para>
-    The <envar>LC_COLLATE</> and <envar>LC_CTYPE</> variables affect the
-    sort order of indexes.  Therefore, these values must be kept fixed
-    for any particular database cluster, or indexes on text columns will
-    become corrupt.  <productname>PostgreSQL</productname> enforces this
-    by recording the values of <envar>LC_COLLATE</> and <envar>LC_CTYPE</>
-    that are seen by <application>initdb</>.  The server automatically adopts
-    those two values when it is started; only the other <envar>LC_</>
-    categories can be set from the environment at server start-up.
-    In short, only one collation order can be used in a database cluster,
-    and it is chosen at <application>initdb</> time.
+    To enable messages translated to the user's preferred language,
+    the <option>--enable-nls</option> option must be used.  This
+    option is independent of the other locale support.
    </para>
   </sect2>
 
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index a792d52e42486fb2f2ac4961f53913f457d728b6..1dbf460cf4c59fe756e4646b7ad6c426c5b0cd58 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.86 2002/03/22 19:20:07 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.87 2002/04/03 05:39:27 petere Exp $
 -->
 
  <chapter id="datatype">
@@ -724,11 +724,9 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
    </note>
 
    <para>
-    The <type>money</type> type stores U.S.-style currency with fixed
-    decimal point representation.  If
-    <productname>PostgreSQL</productname> is compiled with locale
-    support then the <type>money</type> type uses locale-specific
-    output formatting.
+    The <type>money</type> type stores a currency amount with fixed
+    decimal point representation.  The output format is
+    locale-specific.
    </para>
 
    <para>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index c8aa0dd0c95d8c94c3774e511ea3e4c6bf3b7857..e5f9de741afd5a506d62d8a68ed71cd718e0c5b0 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.74 2002/01/20 05:45:18 tgl Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.75 2002/04/03 05:39:28 petere Exp $ -->
 
 <chapter id="installation">
  <title><![%standalone-include[<productname>PostgreSQL</>]]>
@@ -531,17 +531,6 @@ su - postgres
        </listitem>
       </varlistentry>
 
-      <varlistentry>
-       <term><option>--enable-locale</option></term>
-       <listitem>
-        <para>
-         Enables locale support. There is a performance penalty
-         associated with locale support, but if you are not in an
-         English-speaking environment you will most likely need this.
-        </para>
-       </listitem>
-      </varlistentry>
-
       <varlistentry>
        <term><option>--enable-recode</option></term>
        <listitem>
diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml
index 3bbe44aeee8d45900deb4c67ca11f14c1febc000..8ac524e3dc8861ab8ca8d1621e2251b2c8d23890 100644
--- a/doc/src/sgml/ref/initdb.sgml
+++ b/doc/src/sgml/ref/initdb.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/initdb.sgml,v 1.19 2001/12/08 03:24:37 thomas Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/initdb.sgml,v 1.20 2002/04/03 05:39:29 petere Exp $
 PostgreSQL documentation
 -->
 
@@ -38,6 +38,13 @@ PostgreSQL documentation
      <arg>-E </arg>
      <replaceable>encoding</replaceable>
     </group>
+    <arg>--locale <replaceable>locale</replaceable></arg>
+    <arg>--lc-collate <replaceable>locale</replaceable></arg>
+    <arg>--lc-ctype <replaceable>locale</replaceable></arg>
+    <arg>--lc-messages <replaceable>locale</replaceable></arg>
+    <arg>--lc-monetary <replaceable>locale</replaceable></arg>
+    <arg>--lc-numeric <replaceable>locale</replaceable></arg>
+    <arg>--lc-time <replaceable>locale</replaceable></arg>
     <arg>-L <replaceable>directory</replaceable></arg>
     <group><arg>--noclean</arg><arg>-n</arg></group>
     <group><arg>--debug</arg><arg>-d</arg></group>
@@ -66,6 +73,25 @@ PostgreSQL documentation
    built-in types.
   </para>
 
+  <para>
+   <command>initdb</command> initializes the database cluster's
+   default locale and character set encoding.  Some locale categories
+   are fixed for the lifetime of the cluster, so it is important to
+   make the right choice when running <command>initdb</command>.
+   Other locale categories can be changed later when the server is
+   started.  <command>initdb</command> will write those locale
+   settings into the <filename>postgresql.conf</filename>
+   configuration file so they are the default, but they can be changed
+   by editing that file.  To set the locale that
+   <command>initdb</command> uses, see the description of the
+   <option>--locale</option> option.  The character set encoding can
+   be set separately for each database as it is created.
+   <command>initdb</command> determines the encoding for the
+   <literal>template1</literal> database, which will serve as the
+   default for all other databases.  To alter the default encoding use
+   the <option>--encoding</option> option.
+  </para>
+
   <para>
    <command>initdb</command> must be run as the user that will own the
    server process, because the server needs to have access to the
@@ -150,6 +176,32 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>--locale=<replaceable>locale</replaceable></term>
+      <listitem>
+       <para>
+        Sets the default locale for the database cluster.  If this
+        option is not specified, the locale is inherited from the
+        environment that <command>initdb</command> runs in.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term>--lc-collate=<replaceable>locale</replaceable></term>
+      <term>--lc-ctype=<replaceable>locale</replaceable></term>
+      <term>--lc-messages=<replaceable>locale</replaceable></term>
+      <term>--lc-monetary=<replaceable>locale</replaceable></term>
+      <term>--lc-numeric=<replaceable>locale</replaceable></term>
+      <term>--lc-time=<replaceable>locale</replaceable></term>
+
+      <listitem>
+       <para>
+        Like <option>--locale</option>, but only sets the locale in
+        the specified category.
+       </para>
+      </listitem>
+     </varlistentry>
    </variablelist>
    </para>
 
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index c3e52dd948bfad776d115ff1a7dfef30ee219f2d..dfb96e4ff8ee426b4ffe8cd13c90c9adab83d1d5 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.129 2002/04/01 04:35:37 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.130 2002/04/03 05:39:28 petere Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+Locale support is now built by default; choice of locale is set by initdb and/or at run-time
 ALTER TABLE ALTER COLUMN SET/DROP NOT NULL
 EXPLAIN output comes out as a query result, not a NOTICE message
 DOMAINs (types that are constrained versions of base types)
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 43b6931fe18f27ad2861ca02e9d4199e0fed661b..2b0a4ad634905afb1c4a6650e4e7124775a19e0b 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.111 2002/04/01 03:34:24 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.112 2002/04/03 05:39:29 petere Exp $
 -->
 
 <Chapter Id="runtime">
@@ -135,8 +135,14 @@ postgres$ <userinput>initdb -D /usr/local/pgsql/data</userinput>
   </para>
 
   <para>
+   <indexterm><primary>locale</></>
    <indexterm><primary>LC_COLLATE</></>
-   One surprise you might encounter while running
+   <command>initdb</command> also initializes the default locale for
+   the database cluster.  Normally, it will just take the locale
+   settings in the environment and apply them to the initialized
+   database.  It is possible to specify a different locale for the
+   database; more information about that can be found in <xref
+   linkend="locale">.  One surprise you might encounter while running
    <command>initdb</command> is a notice similar to this:
 <screen>
 WARNING:  Initializing database with en_US collation order.
@@ -145,18 +151,17 @@ WARNING:  Initializing database with en_US collation order.
         such queries, you may wish to set LC_COLLATE to "C" and
         re-initdb.  For more information see the Administrator's Guide.
 </screen>
-   This is intended to warn you that the currently selected locale will
-   cause indexes to be sorted in an order that prevents them from being
-   used for LIKE and regular-expression searches. If you need good
-   performance in such searches, you should set your current locale to
-   <literal>C</> and re-run <command>initdb</command>. On most systems,
-   setting the current locale is done by changing the value of the
-   environment variable <literal>LC_ALL</literal> or
-   <literal>LANG</literal>. The sort order used within a particular
-   database cluster is set by <command>initdb</command> and cannot be
-   changed later, short of dumping all data, rerunning
-   <command>initdb</command>, and reloading the data. So it's important
-   to make this choice correctly the first time.
+   This is intended to warn you that the currently selected locale
+   will cause indexes to be sorted in an order that prevents them from
+   being used for LIKE and regular-expression searches. If you need
+   good performance in such searches, you should set your current
+   locale to <literal>C</> and re-run <command>initdb</command>, e.g.,
+   by running <literal>initdb --lc-collate=C</literal>. The sort
+   order used within a particular database cluster is set by
+   <command>initdb</command> and cannot be changed later, short of
+   dumping all data, rerunning <command>initdb</command>, and
+   reloading the data. So it's important to make this choice correctly
+   the first time.
   </para>
  </sect1>
 
@@ -1316,6 +1321,71 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><varname>LC_MESSAGES</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+        Sets the language in which messages are displayed.  Acceptable
+        values are system-dependent; see <xref linkend="locale"> for
+        more information.  If this variable is set to the empty string
+        (which is the default) then the value is inherited from the
+        execution environment of the server in a system-dependent way.
+       </para>
+
+       <para>
+        On some systems, this locale category does not exist.  Setting
+        this variable will still work, but there will be no effect.
+        Also, there is a chance that no translated messages for the
+        desired language exist.  In that case you will continue to see
+        the English messages.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><varname>LC_MONETARY</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+        Sets the locale to use for formatting monetary amounts.
+        Acceptable values are system-dependent; see <xref
+        linkend="locale"> for more information.  If this variable is
+        set to the empty string (which is the default) then the value
+        is inherited from the execution environment of the server in a
+        system-dependent way.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><varname>LC_NUMERIC</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+        Sets the locale to use for formatting numbers, for example
+        with the <function>to_char()</function> family of
+        functions. Acceptable values are system-dependent; see <xref
+        linkend="locale"> for more information.  If this variable is
+        set to the empty string (which is the default) then the value
+        is inherited from the execution environment of the server in a
+        system-dependent way.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><varname>LC_TIME</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+        Sets the locale to use for formatting date and time values,
+        for example with the <function>to_char()</function> family of
+        functions. Acceptable values are system-dependent; see <xref
+        linkend="locale"> for more information.  If this variable is
+        set to the empty string (which is the default) then the value
+        is inherited from the execution environment of the server in a
+        system-dependent way.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><varname>MAX_CONNECTIONS</varname> (<type>integer</type>)</term>
       <listitem>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7e29f6cd0265c39857db5d89cdeaf1e23c2638fa..c148f3d4e4dae27cfa235839123a03b87e04d547 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.90 2002/03/15 19:20:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.91 2002/04/03 05:39:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,9 +22,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <dirent.h>
-#ifdef USE_LOCALE
 #include <locale.h>
-#endif
 
 #include "access/clog.h"
 #include "access/transam.h"
@@ -2081,10 +2079,7 @@ WriteControlFile(void)
 {
 	int			fd;
 	char		buffer[BLCKSZ]; /* need not be aligned */
-
-#ifdef USE_LOCALE
 	char	   *localeptr;
-#endif
 
 	/*
 	 * Initialize version and compatibility-check fields
@@ -2093,7 +2088,6 @@ WriteControlFile(void)
 	ControlFile->catalog_version_no = CATALOG_VERSION_NO;
 	ControlFile->blcksz = BLCKSZ;
 	ControlFile->relseg_size = RELSEG_SIZE;
-#ifdef USE_LOCALE
 	localeptr = setlocale(LC_COLLATE, NULL);
 	if (!localeptr)
 		elog(PANIC, "invalid LC_COLLATE setting");
@@ -2115,10 +2109,6 @@ WriteControlFile(void)
 		  "\n\tsuch queries, you may wish to set LC_COLLATE to \"C\" and"
 			 "\n\tre-initdb.  For more information see the Administrator's Guide.",
 			 ControlFile->lc_collate);
-#else							/* not USE_LOCALE */
-	strcpy(ControlFile->lc_collate, "C");
-	strcpy(ControlFile->lc_ctype, "C");
-#endif   /* not USE_LOCALE */
 
 	/* Contents are protected with a CRC */
 	INIT_CRC64(ControlFile->crc);
@@ -2232,7 +2222,6 @@ ReadControlFile(void)
 			 "\tbut the backend was compiled with RELSEG_SIZE %d.\n"
 			 "\tIt looks like you need to initdb.",
 			 ControlFile->relseg_size, RELSEG_SIZE);
-#ifdef USE_LOCALE
 	if (setlocale(LC_COLLATE, ControlFile->lc_collate) == NULL)
 		elog(PANIC,
 		   "The database cluster was initialized with LC_COLLATE '%s',\n"
@@ -2245,15 +2234,6 @@ ReadControlFile(void)
 			 "\twhich is not recognized by setlocale().\n"
 			 "\tIt looks like you need to initdb.",
 			 ControlFile->lc_ctype);
-#else							/* not USE_LOCALE */
-	if (strcmp(ControlFile->lc_collate, "C") != 0 ||
-		strcmp(ControlFile->lc_ctype, "C") != 0)
-		elog(PANIC,
-		"The database cluster was initialized with LC_COLLATE '%s' and\n"
-			 "\tLC_CTYPE '%s', but the server was compiled without locale support.\n"
-			 "\tIt looks like you need to initdb or recompile.",
-			 ControlFile->lc_collate, ControlFile->lc_ctype);
-#endif   /* not USE_LOCALE */
 }
 
 void
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index b1be07814125c6026fb3a3758a8e2a33320981a7..9c79e7b78d9476a1181fae32342e2d414f09301c 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/main/main.c,v 1.49 2001/11/05 17:46:25 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/main/main.c,v 1.50 2002/04/03 05:39:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,9 +21,7 @@
 
 #include <pwd.h>
 #include <unistd.h>
-#if defined(USE_LOCALE) || defined(ENABLE_NLS)
 #include <locale.h>
-#endif
 
 #if defined(__alpha) && defined(__osf__)
 #include <sys/sysinfo.h>
@@ -122,11 +120,25 @@ main(int argc, char *argv[])
 		new_argv[i] = strdup(argv[i]);
 	new_argv[argc] = NULL;
 
-	/* Initialize NLS settings so we can give localized error messages */
-#ifdef ENABLE_NLS
+	/*
+	 * Set up locale information from environment.  Note that CTYPE
+	 * and COLLATE will be overridden later from pg_control if we are
+	 * in an already-initialized database.  We set them here so that
+	 * they will be available to fill pg_control during initdb.  The
+	 * other ones will get reset later in ResetAllOptions, but we set
+	 * them here to get already localized behavior during startup
+	 * (e.g., error messages).
+	 */
+	setlocale(LC_COLLATE, "");
+	setlocale(LC_CTYPE, "");
 #ifdef LC_MESSAGES
 	setlocale(LC_MESSAGES, "");
 #endif
+	setlocale(LC_MONETARY, "");
+	setlocale(LC_NUMERIC, "");
+	setlocale(LC_TIME, "");
+
+#ifdef ENABLE_NLS
 	bindtextdomain("postgres", LOCALEDIR);
 	textdomain("postgres");
 #endif
@@ -178,20 +190,6 @@ main(int argc, char *argv[])
 		}
 	}
 
-	/*
-	 * Set up locale information from environment, in only the categories
-	 * needed by Postgres; leave other categories set to default "C".
-	 * (Note that CTYPE and COLLATE will be overridden later from
-	 * pg_control if we are in an already-initialized database.  We set
-	 * them here so that they will be available to fill pg_control during
-	 * initdb.)
-	 */
-#ifdef USE_LOCALE
-	setlocale(LC_CTYPE, "");
-	setlocale(LC_COLLATE, "");
-	setlocale(LC_MONETARY, "");
-#endif
-
 	/*
 	 * Now dispatch to one of PostmasterMain, PostgresMain, or
 	 * BootstrapMain depending on the program name (and possibly first
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index c2af4a64fa9ffc32e5a43e207148fdf6fab2e419..4a8ddcf19b66797d5f72a621075e7a9353a68730 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -9,7 +9,7 @@
  * workings can be found in the book "Software Solutions in C" by
  * Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.52 2002/02/19 22:19:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.53 2002/04/03 05:39:29 petere Exp $
  */
 
 #include "postgres.h"
@@ -17,9 +17,7 @@
 #include <limits.h>
 #include <ctype.h>
 #include <math.h>
-#ifdef USE_LOCALE
 #include <locale.h>
-#endif
 
 #include "miscadmin.h"
 #include "utils/builtins.h"
@@ -83,11 +81,7 @@ cash_in(PG_FUNCTION_ARGS)
 				psymbol,
 			   *nsymbol;
 
-#ifdef USE_LOCALE
 	struct lconv *lconvert = PGLC_localeconv();
-#endif
-
-#ifdef USE_LOCALE
 
 	/*
 	 * frac_digits will be CHAR_MAX in some locales, notably C.  However,
@@ -108,14 +102,6 @@ cash_in(PG_FUNCTION_ARGS)
 	csymbol = ((*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$");
 	psymbol = ((*lconvert->positive_sign != '\0') ? *lconvert->positive_sign : '+');
 	nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
-#else
-	fpoint = 2;
-	dsymbol = '.';
-	ssymbol = ',';
-	csymbol = "$";
-	psymbol = '+';
-	nsymbol = "-";
-#endif
 
 #ifdef CASHDEBUG
 	printf("cashin- precision '%d'; decimal '%c'; thousands '%c'; currency '%s'; positive '%c'; negative '%s'\n",
@@ -241,11 +227,8 @@ cash_out(PG_FUNCTION_ARGS)
 			   *nsymbol;
 	char		convention;
 
-#ifdef USE_LOCALE
 	struct lconv *lconvert = PGLC_localeconv();
-#endif
 
-#ifdef USE_LOCALE
 	/* see comments about frac_digits in cash_in() */
 	points = lconvert->frac_digits;
 	if (points < 0 || points > 10)
@@ -264,15 +247,6 @@ cash_out(PG_FUNCTION_ARGS)
 	dsymbol = ((*lconvert->mon_decimal_point != '\0') ? *lconvert->mon_decimal_point : '.');
 	csymbol = ((*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$");
 	nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
-#else
-	points = 2;
-	mon_group = 3;
-	comma = ',';
-	convention = 0;
-	dsymbol = '.';
-	csymbol = "$";
-	nsymbol = "-";
-#endif
 
 	point_pos = LAST_DIGIT - points;
 
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 199630e0cc431081163f2866b8f07028033e9f1e..231bad2ca6dd2c976b9759b7d6edce148075bcde 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.51 2002/03/06 06:10:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.52 2002/04/03 05:39:29 petere Exp $
  *
  *
  *	 Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
@@ -72,9 +72,7 @@
 #include <ctype.h>
 #include <sys/time.h>
 #include <unistd.h>
-#ifdef USE_LOCALE
 #include <locale.h>
-#endif
 #include <math.h>
 #include <float.h>
 
@@ -3380,9 +3378,6 @@ int_to_roman(int number)
 static void
 NUM_prepare_locale(NUMProc *Np)
 {
-
-#ifdef USE_LOCALE
-
 	if (Np->Num->need_locale)
 	{
 
@@ -3436,8 +3431,6 @@ NUM_prepare_locale(NUMProc *Np)
 	}
 	else
 	{
-#endif
-
 		/*
 		 * Default values
 		 */
@@ -3446,10 +3439,7 @@ NUM_prepare_locale(NUMProc *Np)
 		Np->decimal = ".";
 		Np->L_thousands_sep = ",";
 		Np->L_currency_symbol = " ";
-
-#ifdef USE_LOCALE
 	}
-#endif
 }
 
 /* ----------
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 2c86ff5bcf1beb5460820377f0964c1f0c41e8ca..c5c8d312d3f6c5f041d3bc31d2f904e043538f5b 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -1,173 +1,144 @@
-/* -----------------------------------------------------------------------
- * pg_locale.c
+/*-----------------------------------------------------------------------
  *
- *	 The PostgreSQL locale utils.
+ * PostgreSQL locale utilities
  *
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.16 2002/04/03 05:39:31 petere Exp $
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.15 2002/03/06 06:10:14 momjian Exp $
+ * Portions Copyright (c) 2002, PostgreSQL Global Development Group
  *
- *	 Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
- *
- * Karel Zak
- *
- * -----------------------------------------------------------------------
+ *-----------------------------------------------------------------------
  */
 
 #include "postgres.h"
-
-#ifdef USE_LOCALE
-
-#include <locale.h>
-
 #include "utils/pg_locale.h"
-
-/* #define DEBUG_LOCALE_UTILS  */
+#include <locale.h>
 
 
-static bool CurrentLocaleConvValid = false;
-static struct lconv CurrentLocaleConv;
+/* GUC storage area */
 
+char * locale_messages;
+char * locale_monetary;
+char * locale_numeric;
+char * locale_time;
 
-static void PGLC_setlocale(PG_LocaleCategories *lc);
+/* GUC parse hooks */
 
-/*------
- * Frees memory used in PG_LocaleCategories -- this memory is
- * allocated in PGLC_current().
- *------
- */
-void
-PGLC_free_categories(PG_LocaleCategories *lc)
+bool locale_messages_check(const char *proposed)
 {
-	if (lc->lc_ctype)
-		pfree(lc->lc_ctype);
-	if (lc->lc_numeric)
-		pfree(lc->lc_numeric);
-	if (lc->lc_time)
-		pfree(lc->lc_time);
-	if (lc->lc_collate)
-		pfree(lc->lc_collate);
-	if (lc->lc_monetary);
-	pfree(lc->lc_monetary);
 #ifdef LC_MESSAGES
-	if (lc->lc_messages)
-		pfree(lc->lc_messages);
+	return chklocale(LC_MESSAGES, proposed);
+#else
+	/* We return true here so LC_MESSAGES can be set in the
+       configuration file on every system. */
+	return true;
 #endif
 }
 
-/*------
- * Return in PG_LocaleCategories the current locale settings.
- *
- * NB: strings are allocated in the current memory context!
- *------
- */
-void
-PGLC_current(PG_LocaleCategories *lc)
+bool locale_monetary_check(const char *proposed)
 {
-	lc->lang = getenv("LANG");
+	return chklocale(LC_MONETARY, proposed);
+}
 
-	lc->lc_ctype = pstrdup(setlocale(LC_CTYPE, NULL));
-	lc->lc_numeric = pstrdup(setlocale(LC_NUMERIC, NULL));
-	lc->lc_time = pstrdup(setlocale(LC_TIME, NULL));
-	lc->lc_collate = pstrdup(setlocale(LC_COLLATE, NULL));
-	lc->lc_monetary = pstrdup(setlocale(LC_MONETARY, NULL));
-#ifdef LC_MESSAGES
-	lc->lc_messages = pstrdup(setlocale(LC_MESSAGES, NULL));
-#endif
+bool locale_numeric_check(const char *proposed)
+{
+	return chklocale(LC_NUMERIC, proposed);
 }
 
+bool locale_time_check(const char *proposed)
+{
+	return chklocale(LC_TIME, proposed);
+}
 
-#ifdef DEBUG_LOCALE_UTILS
+/* GUC assign hooks */
 
-/*------
- * Print a PG_LocaleCategories struct as DEBUG
- *------
- */
-static void
-PGLC_debug_lc(PG_LocaleCategories *lc)
+void locale_messages_assign(const char *value)
 {
 #ifdef LC_MESSAGES
-	elog(LOG, "CURRENT LOCALE ENVIRONMENT:\n\nLANG:   \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\nLC_MESSAGES:\t%s\n",
-		 lc->lang,
-		 lc->lc_ctype,
-		 lc->lc_numeric,
-		 lc->lc_time,
-		 lc->lc_collate,
-		 lc->lc_monetary,
-		 lc->lc_messages);
-#else
-	elog(LOG, "CURRENT LOCALE ENVIRONMENT:\n\nLANG:   \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\n",
-		 lc->lang,
-		 lc->lc_ctype,
-		 lc->lc_numeric,
-		 lc->lc_time,
-		 lc->lc_collate,
-		 lc->lc_monetary);
+	setlocale(LC_MESSAGES, value);
 #endif
 }
-#endif
 
-/*------
- * Set locales via a PG_LocaleCategories struct
- *
- * NB: it would be very dangerous to set the locale values to any random
- * choice of locale, since that could cause indexes to become corrupt, etc.
- * Therefore this routine is NOT exported from this module.  It should be
- * used only to restore previous locale settings during PGLC_localeconv.
- *------
+void locale_monetary_assign(const char *value)
+{
+	setlocale(LC_MONETARY, value);
+}
+
+void locale_numeric_assign(const char *value)
+{
+	setlocale(LC_NUMERIC, value);
+}
+
+void locale_time_assign(const char *value)
+{
+	setlocale(LC_TIME, value);
+}
+
+
+/*
+ * Returns true if the proposed string represents a valid locale of
+ * the given category.  This is probably pretty slow, but it's not
+ * called in critical places.
  */
-static void
-PGLC_setlocale(PG_LocaleCategories *lc)
+bool
+chklocale(int category, const char *proposed)
 {
-	if (!setlocale(LC_COLLATE, lc->lc_collate))
-		elog(WARNING, "pg_setlocale(): 'LC_COLLATE=%s' cannot be honored.",
-			 lc->lc_collate);
+	char *save;
 
-	if (!setlocale(LC_CTYPE, lc->lc_ctype))
-		elog(WARNING, "pg_setlocale(): 'LC_CTYPE=%s' cannot be honored.",
-			 lc->lc_ctype);
+	save = setlocale(category, NULL);
+	if (!save)
+		return false;
 
-	if (!setlocale(LC_NUMERIC, lc->lc_numeric))
-		elog(WARNING, "pg_setlocale(): 'LC_NUMERIC=%s' cannot be honored.",
-			 lc->lc_numeric);
+	if (!setlocale(category, proposed))
+		return false;
 
-	if (!setlocale(LC_TIME, lc->lc_time))
-		elog(WARNING, "pg_setlocale(): 'LC_TIME=%s' cannot be honored.",
-			 lc->lc_time);
+	setlocale(category, save);
+	return true;
+}
 
-	if (!setlocale(LC_MONETARY, lc->lc_monetary))
-		elog(WARNING, "pg_setlocale(): 'LC_MONETARY=%s' cannot be honored.",
-			 lc->lc_monetary);
 
-#ifdef LC_MESSAGES
-	if (!setlocale(LC_MESSAGES, lc->lc_messages))
-		elog(WARNING, "pg_setlocale(): 'LC_MESSAGES=%s' cannot be honored.",
-			 lc->lc_messages);
-#endif
+/*
+ * We'd like to cache whether LC_COLLATE is C (or POSIX), so we can
+ * optimize a few code paths in various places.
+ */
+bool
+lc_collate_is_c(void)
+{
+	/* Cache result so we only have to compute it once */
+	static int	result = -1;
+	char	   *localeptr;
+
+	if (result >= 0)
+		return (bool) result;
+	localeptr = setlocale(LC_COLLATE, NULL);
+	if (!localeptr)
+		elog(PANIC, "Invalid LC_COLLATE setting");
+
+	if (strcmp(localeptr, "C") == 0)
+		result = true;
+	else if (strcmp(localeptr, "POSIX") == 0)
+		result = true;
+	else
+		result = false;
+	return (bool) result;
 }
 
-/*------
- * Return the POSIX lconv struct (contains number/money formatting information)
- * with locale information for all categories.	Note that returned lconv
- * does not depend on currently active category settings, but on external
- * environment variables for locale.
- *------
+
+
+/*
+ * Return the POSIX lconv struct (contains number/money formatting
+ * information) with locale information for all categories.
  */
 struct lconv *
 PGLC_localeconv(void)
 {
-	PG_LocaleCategories lc;
 	struct lconv *extlconv;
+	static bool CurrentLocaleConvValid = false;
+	static struct lconv CurrentLocaleConv;
 
 	/* Did we do it already? */
 	if (CurrentLocaleConvValid)
 		return &CurrentLocaleConv;
 
-	/* Save current locale setting to lc */
-	PGLC_current(&lc);
-
-	/* Set all locale categories based on postmaster's environment vars */
-	setlocale(LC_ALL, "");
-
 	/* Get formatting information for the external environment */
 	extlconv = localeconv();
 
@@ -187,14 +158,6 @@ PGLC_localeconv(void)
 	CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
 	CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
 
-	/* Restore Postgres' internal locale settings */
-	PGLC_setlocale(&lc);
-
-	/* Deallocate category settings allocated in PGLC_current() */
-	PGLC_free_categories(&lc);
-
 	CurrentLocaleConvValid = true;
 	return &CurrentLocaleConv;
 }
-
-#endif   /* USE_LOCALE */
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index f5fb2adf2ebf318765cbd46433e723fd009d27b1..e8e71dec25acbb33ed46a9e7891602077f017c68 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.106 2002/03/08 04:29:01 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.107 2002/04/03 05:39:31 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,9 +70,7 @@
 
 #include <ctype.h>
 #include <math.h>
-#ifdef USE_LOCALE
 #include <locale.h>
-#endif
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
@@ -95,6 +93,7 @@
 #include "utils/datum.h"
 #include "utils/int8.h"
 #include "utils/lsyscache.h"
+#include "utils/pg_locale.h"
 #include "utils/selfuncs.h"
 #include "utils/syscache.h"
 
@@ -2240,19 +2239,16 @@ convert_one_string_to_scalar(unsigned char *value, int rangelo, int rangehi)
 /*
  * Convert a string-type Datum into a palloc'd, null-terminated string.
  *
- * If USE_LOCALE is defined, we must pass the string through strxfrm()
+ * When using a non-C locale, we must pass the string through strxfrm()
  * before continuing, so as to generate correct locale-specific results.
  */
 static unsigned char *
 convert_string_datum(Datum value, Oid typid)
 {
 	char	   *val;
-
-#ifdef USE_LOCALE
 	char	   *xfrmstr;
 	size_t		xfrmsize;
 	size_t		xfrmlen;
-#endif
 
 	switch (typid)
 	{
@@ -2290,21 +2286,22 @@ convert_string_datum(Datum value, Oid typid)
 			return NULL;
 	}
 
-#ifdef USE_LOCALE
-	/* Guess that transformed string is not much bigger than original */
-	xfrmsize = strlen(val) + 32;	/* arbitrary pad value here... */
-	xfrmstr = (char *) palloc(xfrmsize);
-	xfrmlen = strxfrm(xfrmstr, val, xfrmsize);
-	if (xfrmlen >= xfrmsize)
+	if (!lc_collate_is_c())
 	{
-		/* Oops, didn't make it */
-		pfree(xfrmstr);
-		xfrmstr = (char *) palloc(xfrmlen + 1);
-		xfrmlen = strxfrm(xfrmstr, val, xfrmlen + 1);
+		/* Guess that transformed string is not much bigger than original */
+		xfrmsize = strlen(val) + 32;	/* arbitrary pad value here... */
+		xfrmstr = (char *) palloc(xfrmsize);
+		xfrmlen = strxfrm(xfrmstr, val, xfrmsize);
+		if (xfrmlen >= xfrmsize)
+		{
+			/* Oops, didn't make it */
+			pfree(xfrmstr);
+			xfrmstr = (char *) palloc(xfrmlen + 1);
+			xfrmlen = strxfrm(xfrmstr, val, xfrmlen + 1);
+		}
+		pfree(val);
+		val = xfrmstr;
 	}
-	pfree(val);
-	val = xfrmstr;
-#endif
 
 	return (unsigned char *) val;
 }
@@ -3147,44 +3144,28 @@ pattern_selectivity(char *patt, Pattern_Type ptype)
 	return result;
 }
 
+
 /*
- * Test whether the database's LOCALE setting is safe for LIKE/regexp index
- * optimization.  The key requirement here is that given a prefix string,
- * say "foo", we must be able to generate another string "fop" that is
- * greater than all strings "foobar" starting with "foo".  Unfortunately,
- * many non-C locales have bizarre collation rules in which "fop" > "foo"
- * is not sufficient to ensure "fop" > "foobar".  Until we can come up
- * with a more bulletproof way of generating the upper-bound string,
- * disable the optimization in locales where it is not known to be safe.
+ * We want test whether the database's LC_COLLATE setting is safe for
+ * LIKE/regexp index optimization.
+ *
+ * The key requirement here is that given a prefix string, say "foo",
+ * we must be able to generate another string "fop" that is greater
+ * than all strings "foobar" starting with "foo".  Unfortunately, a
+ * non-C locale may have arbitrary collation rules in which "fop" >
+ * "foo" is not sufficient to ensure "fop" > "foobar".  Until we can
+ * come up with a more bulletproof way of generating the upper-bound
+ * string, the optimization is disabled in all non-C locales.
+ *
+ * (In theory, locales other than C may be LIKE-safe so this function
+ * could be different from lc_collate_is_c(), but in a different
+ * theory, non-C locales are completely unpredicable so it's unlikely
+ * to happen.)
  */
 bool
 locale_is_like_safe(void)
 {
-#ifdef USE_LOCALE
-	/* Cache result so we only have to compute it once */
-	static int	result = -1;
-	char	   *localeptr;
-
-	if (result >= 0)
-		return (bool) result;
-	localeptr = setlocale(LC_COLLATE, NULL);
-	if (!localeptr)
-		elog(PANIC, "Invalid LC_COLLATE setting");
-
-	/*
-	 * Currently we accept only "C" and "POSIX" (do any systems still
-	 * return "POSIX"?).  Which other locales allow safe optimization?
-	 */
-	if (strcmp(localeptr, "C") == 0)
-		result = true;
-	else if (strcmp(localeptr, "POSIX") == 0)
-		result = true;
-	else
-		result = false;
-	return (bool) result;
-#else							/* not USE_LOCALE */
-	return true;				/* We must be in C locale, which is OK */
-#endif   /* USE_LOCALE */
+	return lc_collate_is_c();
 }
 
 /*
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 5afaf398879eec0b382710230407b4993b07087c..0cd38a76bee0fb5cfb8b2fb10c21d32809c08c59 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.81 2002/04/01 03:34:26 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.82 2002/04/03 05:39:32 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
+#include "utils/pg_locale.h"
 
 static int	text_cmp(text *arg1, text *arg2);
 
@@ -493,29 +494,36 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
 	char	   *a1p,
 			   *a2p;
 
-#ifdef USE_LOCALE
-	a1p = (char *) palloc(len1 + 1);
-	a2p = (char *) palloc(len2 + 1);
-
-	memcpy(a1p, arg1, len1);
-	*(a1p + len1) = '\0';
-	memcpy(a2p, arg2, len2);
-	*(a2p + len2) = '\0';
-
-	result = strcoll(a1p, a2p);
+	/*
+	 * Unfortunately, there is no strncoll(), so in the non-C locale
+	 * case we have to do some memory copying.  This turns out to be
+	 * significantly slower, so we optimize the case were LC_COLLATE
+	 * is C.
+	 */
+	if (!lc_collate_is_c())
+	{
+		a1p = (char *) palloc(len1 + 1);
+		a2p = (char *) palloc(len2 + 1);
 
-	pfree(a1p);
-	pfree(a2p);
+		memcpy(a1p, arg1, len1);
+		*(a1p + len1) = '\0';
+		memcpy(a2p, arg2, len2);
+		*(a2p + len2) = '\0';
 
-#else
+		result = strcoll(a1p, a2p);
 
-	a1p = arg1;
-	a2p = arg2;
+		pfree(a1p);
+		pfree(a2p);
+	}
+	else
+	{
+		a1p = arg1;
+		a2p = arg2;
 
-	result = strncmp(a1p, a2p, Min(len1, len2));
-	if ((result == 0) && (len1 != len2))
-		result = (len1 < len2) ? -1 : 1;
-#endif
+		result = strncmp(a1p, a2p, Min(len1, len2));
+		if ((result == 0) && (len1 != len2))
+			result = (len1 < len2) ? -1 : 1;
+	}
 
 	return result;
 }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9c35f0949aa92c74199389b88ca88fc783314059..8abf451b630b4bf21585958f83e2272032014422 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4,7 +4,7 @@
  * Support for grand unified configuration scheme, including SET
  * command, configuration file, and command line options.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.64 2002/04/01 03:34:26 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.65 2002/04/03 05:39:32 petere Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -41,6 +41,7 @@
 #include "utils/builtins.h"
 #include "utils/datetime.h"
 #include "utils/elog.h"
+#include "utils/pg_locale.h"
 #include "pgstat.h"
 
 
@@ -585,6 +586,26 @@ static struct config_string
 		PG_KRB_SRVTAB, NULL, NULL
 	},
 
+	{
+		"lc_messages", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_messages,
+		"", locale_messages_check, locale_messages_assign
+	},
+
+	{
+		"lc_monetary", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_monetary,
+		"", locale_monetary_check, locale_monetary_assign
+	},
+
+	{
+		"lc_numeric", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_numeric,
+		"", locale_numeric_check, locale_numeric_assign
+	},
+
+	{
+		"lc_time", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_time,
+		"", locale_time_check, locale_time_assign
+	},
+
 	{
 		"server_min_messages", PGC_USERSET, PGC_S_DEFAULT, &server_min_messages_str,
 		server_min_messages_str_default, check_server_min_messages,
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index 2bb413844f18362fd08b82906b2e8639e651f135..e028ac1b10e82cdff2551af920d36d8063a43dc4 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.145 2002/03/02 21:39:34 momjian Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.146 2002/04/03 05:39:32 petere Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -51,6 +51,26 @@ exit_nicely(){
     exit 1
 }
 
+pg_getlocale(){
+    arg=$1
+    unset ret
+
+    for var in "PGLC_$arg" PGLOCALE LC_ALL "LC_$arg" LANG; do
+        varset=`eval echo '${'"$var"'+set}'`
+        varval=`eval echo '$'"$var"`
+        if test "$varset" = set; then
+            ret=$varval
+            break
+        fi
+    done
+
+    if test "${ret+set}" != set; then
+        ret=C
+    fi
+
+    echo "$ret"
+}
+
 
 CMDNAME=`basename $0`
 
@@ -251,11 +271,61 @@ do
         -E*)
                 MULTIBYTE=`echo $1 | sed 's/^-E//'`
                 ;;
+# Locale flags
+        --locale)
+                PGLOCALE="$2"
+                shift;;
+        --locale=*)
+                PGLOCALE=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --no-locale)
+                PGLOCALE=C
+                ;;
+
+        --lc-collate)
+                PGLC_COLLATE=$2
+                shift;;
+        --lc-collate=*)
+                PGLC_COLLATE=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --lc-ctype)
+                PGLC_CTYPE=$2
+                shift;;
+        --lc-ctype=*)
+                PGLC_CTYPE=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --lc-messages)
+                PGLC_MESSAGES=$2
+                shift;;
+        --lc-messages=*)
+                PGLC_MESSAGES=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --lc-monetary)
+                PGLC_MONETARY=$2
+                shift;;
+        --lc-monetary=*)
+                PGLC_MONETARY=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --lc-numeric)
+                PGLC_NUMERIC=$2
+                shift;;
+        --lc-numeric=*)
+                PGLC_NUMERIC=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+        --lc-time)
+                PGLC_TIME=$2
+                shift;;
+        --lc-time=*)
+                PGLC_TIME=`echo $1 | sed 's/^[^=]*=//'`
+                ;;
+
 	-*)
 		echo "$CMDNAME: invalid option: $1"
 		echo "Try '$CMDNAME --help' for more information."
 		exit 1
 		;;
+
+# Non-option argument specifies data directory
         *)
                 PGDATA=$1
                 ;;
@@ -275,6 +345,13 @@ if [ "$usage" ]; then
     if [ -n "$MULTIBYTE" ] ; then 
         echo "  -E, --encoding ENCODING     Set default encoding for new databases"
     fi
+    echo "  --locale LOCALE             Initialize database cluster with given locale"
+    echo "  --lc-collate, --lc-ctype, --lc-messages LOCALE"
+    echo "  --lc-monetary, --lc-numeric, --lc-time LOCALE"
+    echo "                              Initialize database cluster with given locale"
+    echo "                              in the respective category"
+    echo "                              (default taken from environment)"
+    echo "  --no-locale                 Equivalent to --locale=C"
     echo "  -U, --username NAME         Database superuser name"
     echo "Less commonly used options: "
     echo "  -L DIRECTORY                Where to find the input files"
@@ -469,7 +546,15 @@ echo "$short_version" > "$PGDATA/PG_VERSION" || exit_nicely
 cat "$POSTGRES_BKI" \
 | sed -e "s/POSTGRES/$POSTGRES_SUPERUSERNAME/g" \
       -e "s/ENCODING/$MULTIBYTEID/g" \
-| "$PGPATH"/postgres -boot -x1 $PGSQL_OPT $BACKEND_TALK_ARG template1 \
+| 
+(
+  LC_COLLATE=`pg_getlocale COLLATE`
+  LC_CTYPE=`pg_getlocale CTYPE`
+  export LC_COLLATE
+  export LC_CTYPE
+  unset LC_ALL
+  "$PGPATH"/postgres -boot -x1 $PGSQL_OPT $BACKEND_TALK_ARG template1
+) \
 || exit_nicely
 
 # Make the per-database PGVERSION for template1 only after init'ing it
@@ -485,7 +570,19 @@ $ECHO_N "creating configuration files... "$ECHO_C
 
 cp "$PG_HBA_SAMPLE" "$PGDATA"/pg_hba.conf              || exit_nicely
 cp "$PG_IDENT_SAMPLE" "$PGDATA"/pg_ident.conf          || exit_nicely
-cp "$POSTGRESQL_CONF_SAMPLE" "$PGDATA"/postgresql.conf || exit_nicely
+(
+  cat "$POSTGRESQL_CONF_SAMPLE"
+  echo
+  echo
+  echo "#"
+  echo "#	Locale settings"
+  echo "#"
+  echo "# (initialized by initdb -- may be changed)"
+  for cat in MESSAGES MONETARY NUMERIC TIME; do
+    echo "LC_$cat = '`pg_getlocale $cat`'"
+  done
+) > "$PGDATA"/postgresql.conf || exit_nicely
+
 chmod 0600 "$PGDATA"/pg_hba.conf "$PGDATA"/pg_ident.conf \
 	"$PGDATA"/postgresql.conf
 
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 8a509e3d89a948c95d4102e71f5ca0a67c809b5a..cd27d28fa3c0a3a190c28ad4a3ba3b0ba26ed9c6 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -8,7 +8,7 @@
  * or in pg_config.h afterwards.  Of course, if you edit pg_config.h, then your
  * changes will be overwritten the next time you run configure.
  *
- * $Id: pg_config.h.in,v 1.19 2002/03/29 17:32:55 petere Exp $
+ * $Id: pg_config.h.in,v 1.20 2002/04/03 05:39:33 petere Exp $
  */
 
 #ifndef PG_CONFIG_H
@@ -33,9 +33,6 @@
 /* A canonical string containing the version number, platform, and C compiler */
 #undef PG_VERSION_STR
 
-/* Set to 1 if you want LOCALE support (--enable-locale) */
-#undef USE_LOCALE
-
 /* Set to 1 if you want cyrillic recode (--enable-recode) */
 #undef CYR_RECODE
 
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 03330682b750de162f07bae2b4a68e7d106eee54..b5056e6ca8064df2e63eaa2bcaa2b701f20b4f06 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -1,56 +1,42 @@
-/* -----------------------------------------------------------------------
- * pg_locale.h
+/*-----------------------------------------------------------------------
  *
- *	 The PostgreSQL locale utils.
+ * PostgreSQL locale utilities
  *
+ * $Header: /cvsroot/pgsql/src/include/utils/pg_locale.h,v 1.12 2002/04/03 05:39:33 petere Exp $
  *
- * $Id: pg_locale.h,v 1.11 2001/11/05 17:46:36 momjian Exp $
+ * Copyright (c) 2002, PostgreSQL Global Development Group
  *
- *	 Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
- *
- *	Karel Zak - Zakkr
- *
- * -----------------------------------------------------------------------
+ *-----------------------------------------------------------------------
  */
 
 #ifndef _PG_LOCALE_
 #define _PG_LOCALE_
 
-#ifdef USE_LOCALE
+#include "postgres.h"
+#include <locale.h>
 
-/*------
- * POSIX locale categories and environment variable LANG
- *------
- */
-typedef struct PG_LocaleCategories
-{
-	char	   *lang,
-			   *lc_ctype,
-			   *lc_numeric,
-			   *lc_time,
-			   *lc_collate,
-			   *lc_monetary,
-			   *lc_messages;
-} PG_LocaleCategories;
+extern char * locale_messages;
+extern char * locale_monetary;
+extern char * locale_numeric;
+extern char * locale_time;
 
-/*
- * Save locale category settings into PG memory
- */
-extern void PGLC_current(PG_LocaleCategories *lc);
+bool locale_messages_check(const char *proposed);
+bool locale_monetary_check(const char *proposed);
+bool locale_numeric_check(const char *proposed);
+bool locale_time_check(const char *proposed);
+
+void locale_messages_assign(const char *value);
+void locale_monetary_assign(const char *value);
+void locale_numeric_assign(const char *value);
+void locale_time_assign(const char *value);
+
+bool chklocale(int category, const char *proposed);
+bool lc_collate_is_c(void);
 
 /*
- * Free memory allocated in PGLC_current()
- */
-extern void PGLC_free_categories(PG_LocaleCategories *lc);
-
-/*------
- * Return the POSIX lconv struct (contains number/money formatting information)
- * with locale information for all categories.	Note that returned lconv
- * does not depend on currently active category settings, but on external
- * environment variables for locale.
- *------
+ * Return the POSIX lconv struct (contains number/money formatting
+ * information) with locale information for all categories.
  */
 extern struct lconv *PGLC_localeconv(void);
-#endif   /* USE_LOCALE */
 
 #endif   /* _PG_LOCALE_ */