Index: /branches/libc-0.6/src/emx/src/lib/locale/setlocale.c
===================================================================
--- /branches/libc-0.6/src/emx/src/lib/locale/setlocale.c	(revision 3915)
+++ /branches/libc-0.6/src/emx/src/lib/locale/setlocale.c	(revision 3916)
@@ -548,5 +548,5 @@
 
 static inline unsigned char Transform(LocaleObject lobj, UconvObject uobj,
-                                      UniChar (* APIENTRY pfnTransFunc) (LocaleObject, UniChar),
+                                      UniChar (APIENTRY *pfnTransFunc) (const LocaleObject, UniChar),
                                       UniChar uc, unsigned char uchFallback)
 {
@@ -1377,5 +1377,5 @@
                     ULONG       cb;
                     int         rc;
-                    FS_VAR()
+                    FS_VAR();
 
                     FS_SAVE_LOAD();
@@ -1465,5 +1465,5 @@
             ULONG   cb;
             int     rc;
-            FS_VAR()
+            FS_VAR();
 
             FS_SAVE_LOAD();
@@ -2043,5 +2043,5 @@
 
 
-_FORK_CHILD1(0xffffff00, setlocalForkChild1)
+_FORK_CHILD1(0xffffff00, setlocalForkChild1);
 
 /**
Index: /trunk/libc/src/libc/locale/os2/setlocale.c
===================================================================
--- /trunk/libc/src/libc/locale/os2/setlocale.c	(revision 3915)
+++ /trunk/libc/src/libc/locale/os2/setlocale.c	(revision 3916)
@@ -84,4 +84,34 @@
 #define CODEPAGE_MAX_LENGTH     64
 
+/** Macro for swapping generic struct field. */
+#define SWAP_SIMPLE_MEMBERS(a_pHot, a_pCold, a_Type, a_Member) \
+    do { \
+        a_Type const Tmp    = (a_pHot)->a_Member; \
+        (a_pHot)->a_Member  = (a_pCold)->a_Member; \
+        (a_pCold)->a_Member = Tmp; \
+    } while (0)
+
+/** Macro for swapping a string pointer if the new value differs or differs in
+ *  it's readonlyness. */
+#define MAYBE_SWAP_STRING_MEMBERS(a_pHot, a_pCold, a_Member, a_fOverride) \
+    do { \
+        char *pszTmp = (a_pHot)->a_Member; \
+        if ((a_fOverride) || strcmp(pszTmp, (a_pCold)->a_Member) != 0) \
+        { \
+            (a_pHot)->a_Member  = (a_pCold)->a_Member; \
+            (a_pCold)->a_Member = pszTmp; \
+        } \
+    } while (0)
+
+/** Macro for swapping a fixed array of string pointer if the new value differs
+ *  or differs in it's readonlyness. */
+#define MAYBE_SWAP_STRING_ARRAY_MEMBERS(a_pHot, a_pCold, a_apszMember, a_fOverride) \
+    do { \
+        unsigned iMember = sizeof((a_pHot)->a_apszMember) / sizeof((a_pHot)->a_apszMember[0]); \
+        while (iMember-- > 0) \
+            MAYBE_SWAP_STRING_MEMBERS(a_pHot, a_pCold, a_apszMember[iMember], a_fOverride); \
+    } while (0)
+
+
 /*******************************************************************************
 *   Structures and Typedefs                                                    *
@@ -482,4 +512,18 @@
 
     return 0;
+}
+
+/**
+ * Swaps the content of two locale collate structures.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeCollateSwap(__LIBC_LOCALECOLLATE *pHot, __LIBC_PLOCALECOLLATE pCold)
+{
+    __LIBC_LOCALECOLLATE Tmp;
+    memcpy(&Tmp, pHot, sizeof(Tmp));
+    memcpy(pHot, pCold, sizeof(Tmp));
+    memcpy(pCold, &Tmp, sizeof(Tmp));
 }
 
@@ -721,4 +765,17 @@
 }
 
+/**
+ * Swaps the content of two locale Ctype structures.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeCtypeSwap(__LIBC_LOCALECTYPE *pHot, __LIBC_PLOCALECTYPE pCold)
+{
+    __LIBC_LOCALECTYPE Tmp;
+    memcpy(&Tmp, pHot, sizeof(Tmp));
+    memcpy(pHot, pCold, sizeof(Tmp));
+    memcpy(pCold, &Tmp, sizeof(Tmp));
+}
 
 /**
@@ -841,4 +898,34 @@
 
 /**
+ * Commits the changed LC_TIME locale attributes.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeTimeCommit(__LIBC_LOCALETIME *pHot, __LIBC_PLOCALETIME pCold)
+{
+    int const fOverride = pHot->fConsts != pCold->fConsts;
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fConsts);
+    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, smonths, fOverride);
+    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, lmonths, fOverride);
+    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, swdays, fOverride);
+    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, lwdays, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, date_time_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, date_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, time_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, am, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pm, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, ampm_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_date_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_date_time_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_time_fmt, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, alt_digits, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, datesep, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, timesep, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, listsep, fOverride);
+}
+
+/**
  * Frees the CRT resources held up by a time structure.
  * @param   pTime   The time structure.
@@ -853,5 +940,5 @@
         char **ppsz = (char **)pTime;
         char **ppszEnd = (char **)pTime->fConsts;
-        while (ppsz < ppszEnd)
+        while ((uintptr_t)ppsz < (uintptr_t)ppszEnd)
         {
             void *pv = *ppsz;
@@ -868,4 +955,19 @@
 
 /**
+ * Commits the changed LC_NUMERIC locale attributes.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeNumericCommit(__LIBC_LOCALELCONV volatile *pHot, __LIBC_PLOCALELCONV pCold)
+{
+    int const fOverride = pHot->fNumericConsts != pCold->fNumericConsts;
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fNumericConsts);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.decimal_point, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.thousands_sep, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.grouping, fOverride);
+}
+
+/**
  * Frees all heap strings in the monetary part of the lconv structure.
  * @param   pLconv  What to work on.
@@ -880,4 +982,38 @@
     pLconv->fNumericConsts = 0;
 #undef FREE
+}
+
+/**
+ * Commits the changed LC_MONETARY locale attributes.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeMonetaryCommit(__LIBC_LOCALELCONV volatile *pHot, __LIBC_PLOCALELCONV pCold)
+{
+    int const fOverride = pHot->fMonetaryConsts != pCold->fMonetaryConsts;
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, int,    fMonetaryConsts);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.int_curr_symbol, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.currency_symbol, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_decimal_point, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_thousands_sep, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_grouping, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.positive_sign, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.negative_sign, fOverride);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_frac_digits);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.frac_digits);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_cs_precedes);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_sep_by_space);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_cs_precedes);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_sep_by_space);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_sign_posn);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_sign_posn);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_cs_precedes);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_cs_precedes);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_sep_by_space);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_sep_by_space);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_sign_posn);
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_sign_posn);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   pszCrncyStr, fOverride);
 }
 
@@ -1071,4 +1207,20 @@
 
 /**
+ * Commits the changed LC_MESSAGES locale attributes.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ */
+static void localeMessagesCommit(__LIBC_LOCALEMSG *pHot, __LIBC_PLOCALEMSG pCold)
+{
+    int const fOverride = pHot->fConsts != pCold->fConsts;
+    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fConsts);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszYesExpr, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszNoExpr, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszYesStr, fOverride);
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszNoStr, fOverride);
+}
+
+/**
  * Frees all heap strings in the monetary part of the lconv structure.
  * @param   pLconv  What to work on.
@@ -1126,4 +1278,17 @@
 
     return 0;
+}
+
+
+/**
+ * Swaps the locate name between two locale instances unless they are equal.
+ *
+ * @param   pHot        The hot structure (target).
+ * @param   pCold       The cold structure (source, will be freed).
+ * @param   iCategory   The cateogry which name shall be swapped.
+ */
+static void localeGlobalNameCommit(__LIBC_LOCALEGLOBAL volatile *pHot, __LIBC_PLOCALEGLOBAL pCold, int iCategory)
+{
+    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, apszNames[iCategory + 1], 0);
 }
 
@@ -1655,18 +1820,14 @@
 
     /*
-     * Copy all the data.
+     * Swap all the data (caller frees the old data).
      */
     if (pTemp->afProcessed[LC_COLLATE + 1])
     {
-        localeCollateFree(&__libc_gLocaleCollate);
-        memcpy(&__libc_gLocaleCollate, &pTemp->Collate, sizeof(__libc_gLocaleCollate));
-        pTemp->afProcessed[LC_COLLATE + 1] = 0;
-        gLocale.apszNames[LC_COLLATE + 1] = pTemp->Global.apszNames[LC_COLLATE + 1];
+        localeCollateSwap(&__libc_gLocaleCollate, &pTemp->Collate);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_COLLATE);
     }
 
     if (pTemp->afProcessed[LC_CTYPE + 1])
     {
-        localeCtypeFree(&__libc_GLocaleCtype);
-        memcpy(&__libc_GLocaleCtype, &pTemp->Ctype, sizeof(__libc_GLocaleCtype));
         MB_CUR_MAX = pTemp->Ctype.mbcs ? pTemp->Ctype.mbcs : 1;
         if (    IS_C_LOCALE(pTemp->Global.apszNames[LC_CTYPE + 1])
@@ -1675,64 +1836,31 @@
         else
             __libc_GLocaleWCtype.uMask = ~0xffU;
-        pTemp->afProcessed[LC_CTYPE + 1] = 0;
-        gLocale.apszNames[LC_CTYPE + 1] = pTemp->Global.apszNames[LC_CTYPE + 1];
+
+        localeCtypeSwap(&__libc_GLocaleCtype, &pTemp->Ctype);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_CTYPE);
     }
 
     if (pTemp->afProcessed[LC_TIME + 1])
     {
-        localeTimeFree(&__libc_gLocaleTime);
-        memcpy(&__libc_gLocaleTime, &pTemp->Time, sizeof(__libc_gLocaleTime));
-        pTemp->afProcessed[LC_TIME + 1] = 0;
-        gLocale.apszNames[LC_TIME + 1] = pTemp->Global.apszNames[LC_TIME + 1];
+        localeTimeCommit(&__libc_gLocaleTime, &pTemp->Time);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_TIME);
     }
 
     if (pTemp->afProcessed[LC_NUMERIC + 1])
     {
-        localeNumericFree(&__libc_gLocaleLconv);
-        __libc_gLocaleLconv.fNumericConsts   = pTemp->Lconv.fNumericConsts;
-        __libc_gLocaleLconv.s.decimal_point  = pTemp->Lconv.s.decimal_point;
-        __libc_gLocaleLconv.s.thousands_sep  = pTemp->Lconv.s.thousands_sep;
-        __libc_gLocaleLconv.s.grouping       = pTemp->Lconv.s.grouping;
-        pTemp->afProcessed[LC_NUMERIC + 1] = 0;
-        gLocale.apszNames[LC_NUMERIC + 1] = pTemp->Global.apszNames[LC_NUMERIC + 1];
+        localeNumericCommit(&__libc_gLocaleLconv, &pTemp->Lconv);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_NUMERIC);
     }
 
     if (pTemp->afProcessed[LC_MONETARY + 1])
     {
-        localeMonetaryFree(&__libc_gLocaleLconv);
-        __libc_gLocaleLconv.fMonetaryConsts      = pTemp->Lconv.fMonetaryConsts;
-        __libc_gLocaleLconv.s.int_curr_symbol    = pTemp->Lconv.s.int_curr_symbol;
-        __libc_gLocaleLconv.s.currency_symbol    = pTemp->Lconv.s.currency_symbol;
-        __libc_gLocaleLconv.s.mon_decimal_point  = pTemp->Lconv.s.mon_decimal_point;
-        __libc_gLocaleLconv.s.mon_thousands_sep  = pTemp->Lconv.s.mon_thousands_sep;
-        __libc_gLocaleLconv.s.mon_grouping       = pTemp->Lconv.s.mon_grouping;
-        __libc_gLocaleLconv.s.positive_sign      = pTemp->Lconv.s.positive_sign;
-        __libc_gLocaleLconv.s.negative_sign      = pTemp->Lconv.s.negative_sign;
-        __libc_gLocaleLconv.s.int_frac_digits    = pTemp->Lconv.s.int_frac_digits;
-        __libc_gLocaleLconv.s.frac_digits        = pTemp->Lconv.s.frac_digits;
-        __libc_gLocaleLconv.s.p_cs_precedes      = pTemp->Lconv.s.p_cs_precedes;
-        __libc_gLocaleLconv.s.p_sep_by_space     = pTemp->Lconv.s.p_sep_by_space;
-        __libc_gLocaleLconv.s.n_cs_precedes      = pTemp->Lconv.s.n_cs_precedes;
-        __libc_gLocaleLconv.s.n_sep_by_space     = pTemp->Lconv.s.n_sep_by_space;
-        __libc_gLocaleLconv.s.p_sign_posn        = pTemp->Lconv.s.p_sign_posn;
-        __libc_gLocaleLconv.s.n_sign_posn        = pTemp->Lconv.s.n_sign_posn;
-        __libc_gLocaleLconv.s.int_p_cs_precedes  = pTemp->Lconv.s.int_p_cs_precedes;
-        __libc_gLocaleLconv.s.int_n_cs_precedes  = pTemp->Lconv.s.int_n_cs_precedes;
-        __libc_gLocaleLconv.s.int_p_sep_by_space = pTemp->Lconv.s.int_p_sep_by_space;
-        __libc_gLocaleLconv.s.int_n_sep_by_space = pTemp->Lconv.s.int_n_sep_by_space;
-        __libc_gLocaleLconv.s.int_p_sign_posn    = pTemp->Lconv.s.int_p_sign_posn;
-        __libc_gLocaleLconv.s.int_n_sign_posn    = pTemp->Lconv.s.int_n_sign_posn;
-        __libc_gLocaleLconv.pszCrncyStr          = pTemp->Lconv.pszCrncyStr;
-        pTemp->afProcessed[LC_MONETARY + 1] = 0;
-        gLocale.apszNames[LC_MONETARY + 1] = pTemp->Global.apszNames[LC_MONETARY + 1];
+        localeMonetaryCommit(&__libc_gLocaleLconv, &pTemp->Lconv);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_MONETARY);
     }
     if (pTemp->afProcessed[LC_MESSAGES + 1])
     {
-        localeMessagesFree(&__libc_gLocaleMsg);
-        memcpy(&__libc_gLocaleMsg, &pTemp->Msg, sizeof(__libc_gLocaleMsg));
-        pTemp->afProcessed[LC_MESSAGES + 1] = 0;
-        gLocale.apszNames[LC_MESSAGES + 1] = pTemp->Global.apszNames[LC_MESSAGES + 1];
-    }
-
+        localeMessagesCommit(&__libc_gLocaleMsg, &pTemp->Msg);
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_MESSAGES);
+    }
 
     /*
@@ -1770,10 +1898,10 @@
         }
         *psz = '\0';
-        localeGlobalFree(&gLocale, LC_ALL);
-        gLocale.apszNames[LC_ALL + 1] = pszAll;
+        pTemp->Global.apszNames[LC_ALL + 1] = pszAll;
+        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_ALL);
     }
     else if (strcmp(gLocale.apszNames[LC_ALL + 1], pszAll))
     {
-        localeGlobalFree(&gLocale, LC_ALL);
+        pTemp->Global.apszNames[LC_ALL + 1] = gLocale.apszNames[LC_ALL + 1];
         gLocale.apszNames[LC_ALL + 1] = strdup(pszAll);
     }
@@ -1808,4 +1936,5 @@
     if (pTemp->afProcessed[LC_MESSAGES + 1])
         localeMessagesFree(&pTemp->Msg);
+    localeGlobalFree(&pTemp->Global, LC_ALL);
     for (iCat = 0; iCat < _LC_LAST; iCat++)
         if (pTemp->afProcessed[iCat + 1])
@@ -1816,5 +1945,5 @@
 /**
  * This setlocale() implementation differs from the specs in that any
- * options specified by '@...' other than EURO/euro is ignored.
+ * options specified by '@...' other than EURO/euro are ignored.
  */
 char *_STD(setlocale)(int iCategory, const char *pszLocale)
