Index: trunk/src/emx/src/lib/locale/setlocale.c
===================================================================
--- trunk/src/emx/src/lib/locale/setlocale.c	(revision 1791)
+++ trunk/src/emx/src/lib/locale/setlocale.c	(revision 1792)
@@ -70,4 +70,15 @@
                              && (s)[4] == 'X' \
                              && (s)[5] == '\0' )
+#define IS_EURO(s)         ((   (s)[0] == 'E' \
+                             && (s)[1] == 'U' \
+                             && (s)[2] == 'R' \
+                             && (s)[3] == 'O' \
+                             && (s)[4] == '\0' \
+                            ) || ( \
+                                (s)[0] == 'e' \
+                             && (s)[1] == 'u' \
+                             && (s)[2] == 'r' \
+                             && (s)[3] == 'o' \
+                             && (s)[4] == '\0') )
 /** Max lenght we anticipate of a codepage name. */
 #define CODEPAGE_MAX_LENGTH     64
@@ -221,9 +232,9 @@
 static void localeNumericFree(__LIBC_PLOCALELCONV pLconv);
 static void localeMonetaryFree(__LIBC_PLOCALELCONV pLconv);
-static int localeNumericDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, struct UniLconv *pULconv);
-static int localeMonetaryDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, LocaleObject lobj, struct UniLconv *pULconv, const char *pszLocale);
+static int localeNumericDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, struct UniLconv *pULconv, const char *pszLocale);
+static int localeMonetaryDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, LocaleObject lobj, struct UniLconv *pULconv, const char *pszLocale, const char *pszModifier);
 static void localeGlobalFree(__LIBC_PLOCALEGLOBAL pGlobal, int iCategory);
-static int localeParseLocale(char *pszLocale, const char **ppszCodepage);
-static int localeDoOne(struct temp_locale *pTemp, int iCategory, const char *pszLocale, const char *pszCodepage);
+static int localeParseLocale(char *pszLocale, const char **ppszCodepage, const char **ppszModifier);
+static int localeDoOne(struct temp_locale *pTemp, int iCategory, const char *pszLocale, const char *pszCodepage, const char *pszModifier);
 static int localeDo(struct temp_locale *pTemp, int iCategory, char *pszLocale, int fDefaultValue);
 static char *localeCommit(struct temp_locale *pTemp, int iCategory);
@@ -822,5 +833,6 @@
     FREE(thousands_sep);
     FREE(grouping);
-                                                                                                                                                                                                                                                                pLconv->fNumericConsts = 0;
+
+    pLconv->fNumericConsts = 0;
 #undef FREE
 }
@@ -874,6 +886,7 @@
  * @param   uobj        The UconvObject to use.
  * @param   pULconv     Pointer to the pULconv structure to get the data from.
- */
-static int localeNumericDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, struct UniLconv *pULconv)
+ * @param   pszLocale   Pointer to the locale base specifier.
+ */
+static int localeNumericDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, struct UniLconv *pULconv, const char *pszLocale)
 {
     int     rc;
@@ -881,14 +894,28 @@
     localeNumericFree(pLconv);
 
-    /*
-     * Convert the stuff.
-     */
+    if (    !IS_C_LOCALE(pszLocale)
+        &&  !IS_POSIX_LOCALE(pszLocale))
+    {
+        /*
+         * Convert the stuff.
+         */
 #define CONVERT_UCS(field) \
     do  { rc = convert_ucs(uobj, pULconv->field, &pLconv->s.field); if (rc) return rc; } while (0)
-    CONVERT_UCS(decimal_point);
-    CONVERT_UCS(thousands_sep);
+        CONVERT_UCS(decimal_point);
+        CONVERT_UCS(thousands_sep);
 #undef CONVERT_UCS
 
-    return localeConvertGrouping(pULconv->grouping, &pLconv->s.grouping);
+        return localeConvertGrouping(pULconv->grouping, &pLconv->s.grouping);
+    }
+    else
+    {
+	/* the C/POSIX locale */
+        LIBCLOG_MSG2("POSIX '%s'\n", pszLocale);
+	pLconv->fNumericConsts        = 1;
+        pLconv->s.decimal_point       = ".";
+        pLconv->s.thousands_sep       = ",";
+        pLconv->s.grouping            = "";
+	return 0;
+    }
 }
 
@@ -902,7 +929,8 @@
  * @param   uobj        The UconvObject to use.
  * @param   pULconv     Pointer to the pULconv structure to get the data from.
- * @param   pszLocale   The locale specifier.
- */
-static int localeMonetaryDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, LocaleObject lobj, struct UniLconv *pULconv, const char *pszLocale)
+ * @param   pszLocale   The locale base specifier.
+ * @param   pszModifier The locale modifier.
+ */
+static int localeMonetaryDo(__LIBC_PLOCALELCONV pLconv, UconvObject uobj, LocaleObject lobj, struct UniLconv *pULconv, const char *pszLocale, const char *pszModifier)
 {
     int rc;
@@ -917,7 +945,17 @@
          */
 #define CONVERT_UCS(field) \
-        do  { rc = convert_ucs(uobj, pULconv->field, &pLconv->s.field); if (rc) return rc; } while (0)
-        CONVERT_UCS(int_curr_symbol);
-        CONVERT_UCS(currency_symbol);
+    do  { rc = convert_ucs(uobj, pULconv->field, &pLconv->s.field); if (rc) return rc; } while (0)
+
+	if (pszModifier && IS_EURO(pszModifier))
+	{
+            /** @todo check for specs on a standard EURO grouping and stuff. */
+            pLconv->s.currency_symbol = strdup("EUR");
+            pLconv->s.int_curr_symbol = strdup("EUR");
+	}
+	else
+	{
+            CONVERT_UCS(int_curr_symbol);
+            CONVERT_UCS(currency_symbol);
+	}
         CONVERT_UCS(mon_decimal_point);
         CONVERT_UCS(mon_thousands_sep);
@@ -950,5 +988,5 @@
         pLconv->s.int_curr_symbol = pLconv->s.currency_symbol = pLconv->s.mon_decimal_point
             = pLconv->s.mon_thousands_sep = pLconv->s.positive_sign = pLconv->s.negative_sign
-            = pLconv->pszCrncyStr = "";
+            = pLconv->pszCrncyStr = pLconv->s.mon_grouping = "";
         pLconv->s.int_frac_digits   = -1;
         pLconv->s.frac_digits       = -1;
@@ -959,5 +997,6 @@
         pLconv->s.p_sign_posn       = -1;
         pLconv->s.n_sign_posn       = -1;
-        return 0;
+
+	return 0;
     }
 }
@@ -980,15 +1019,16 @@
  * Parses out the locale spec and the code page spec.
  */
-static int localeParseLocale(char *pszLocale, const char **ppszCodepage)
-{
-    /*
-     * Strip of modifier.
+static int localeParseLocale(char *pszLocale, const char **ppszCodepage, const char **ppszModifier)
+{
+    /*
+     * Modifier.
      */
     char *psz = strchr(pszLocale, '@');
     if (psz)
     {
-        LIBCLOG_MSG2("Ignoring locale modifier '%s'\n", psz);
-        *psz = '\0';
-    }
+        *psz++ = '\0';
+        LIBCLOG_MSG2("Using locale modifier '%s'\n", psz);
+    }
+    *ppszModifier = psz;
 
     /*
@@ -1203,10 +1243,10 @@
 
 /**
- * Performe the locale operation on one category.
- */
-static int localeDoOne(struct temp_locale *pTemp, int iCategory, const char *pszLocale, const char *pszCodepage)
-{
-    LIBCLOG_ENTER("pTemp=%p iCategory=%d (%s) pszLocale=%p:{%s} pszCodepage=%p:{%s}\n",
-                  (void *)pTemp, iCategory, gaszCategories[iCategory + 1], pszLocale, pszLocale, pszCodepage, pszCodepage);
+ * Perform the locale operation on one category.
+ */
+static int localeDoOne(struct temp_locale *pTemp, int iCategory, const char *pszLocale, const char *pszCodepage, const char *pszModifier)
+{
+    LIBCLOG_ENTER("pTemp=%p iCategory=%d (%s) pszLocale=%p:{%s} pszCodepage=%p:{%s} pszModifier=%p:{%s}\n",
+                  (void *)pTemp, iCategory, gaszCategories[iCategory + 1], pszLocale, pszLocale, pszCodepage, pszCodepage, pszModifier, pszModifier);
     char            szCodepageActual[CODEPAGE_MAX_LENGTH];
     UconvObject     uobj;
@@ -1255,7 +1295,7 @@
             {
                 if (iCategory == LC_NUMERIC)
-                    rc = localeNumericDo(&pTemp->Lconv, uobj, pULconv);
+                    rc = localeNumericDo(&pTemp->Lconv, uobj, pULconv, pszLocale);
                 else
-                    rc = localeMonetaryDo(&pTemp->Lconv, uobj, lobj, pULconv, pszLocale);
+                    rc = localeMonetaryDo(&pTemp->Lconv, uobj, lobj, pULconv, pszLocale, pszModifier);
                 UniFreeLocaleInfo(pULconv);
             }
@@ -1292,34 +1332,36 @@
          */
         localeGlobalFree(&pTemp->Global, iCategory);
-        if (!pszCodepage || !*pszCodepage)
-        {
-            /* (no codepage specified) */
-            if (IS_C_LOCALE(pszLocale))
-                pTemp->Global.apszNames[iCategory + 1] = (char *)gszC;
-            else if (IS_POSIX_LOCALE(pszLocale))
-                pTemp->Global.apszNames[iCategory + 1] = (char *)gszPOSIX;
-            else
-            {
-                pTemp->Global.apszNames[iCategory + 1] = strdup(pszLocale);
-                if (!pTemp->Global.apszNames[iCategory + 1])
-                    return -ENOMEM;
-            }
-        }
+        if ((!pszCodePage || !*pszCodePage) && IS_C_LOCALE(pszLocale))
+            pTemp->Global.apszNames[iCategory + 1] = (char *)gszC;
+        else if ((!pszCodePage || !*pszCodePage) && IS_POSIX_LOCALE(pszLocale))
+            pTemp->Global.apszNames[iCategory + 1] = (char *)gszPOSIX;
         else
-        {
-            /* pszLocale + "." + szCodepageActual. */
+	{
+            /* pszLocale + "." + szCodepageActual [+ "@" + pszModifier] */
             int     cch1 = strlen(pszLocale);
             int     cch2 = strlen(szCodepageActual);
-            char   *psz = malloc(cch1 + cch2 + 2);
+            int     cch3 = pszModifier ? strlen(pszModifier) : 0;
+            char   *psz = pTemp->Global.apszNames[iCategory + 1] = malloc(cch1 + cch2 + cch3 + !!cch3 + 2);
             if (!psz)
                 return -ENOMEM;
-
+            char   *psz = psz;
             memcpy(psz, pszLocale, cch1);
-            psz[cch1] = '.';
-            memcpy(psz + cch1 + 1, szCodepageActual, cch2);
-            psz[cch1 + 1 + cch2] = '\0';
-
-            pTemp->Global.apszNames[iCategory + 1] = psz;
-        }
+            psz += cch1;
+
+            *psz++ = '.';
+            memcpy(psz, szCodepageActual, cch2);
+            psz += cch2;
+            
+            if (cch3)
+            {
+                *psz++ = '@';
+                memcpy(psz, pszModifier, cch3);
+                psz += cch3;
+            }
+            *psz = '\0';
+
+            LIBCLOG_MSG2("Setting iCategory='%d''%s' locale value to '%s'\n", 
+                         iCategory, gaszCategories[iCategory + 1], pTemp->Global.apszNames[iCategory + 1]);
+	}
     }
 
@@ -1342,4 +1384,5 @@
                   (void *)pTemp, iCategory, gaszCategories[iCategory + 1], pszLocale, pszLocale, fDefaultValue);
     const char *pszCodepage;
+    const char *pszModifier;
     char       *pszNext;
     int         rc;
@@ -1350,7 +1393,7 @@
     if (iCategory != LC_ALL)
     {
-        rc = localeParseLocale(pszLocale, &pszCodepage);
+        rc = localeParseLocale(pszLocale, &pszCodepage, &pszModifier);
         if (!rc)
-            rc = localeDoOne(pTemp, iCategory, pszLocale, pszCodepage);
+            rc = localeDoOne(pTemp, iCategory, pszLocale, pszCodepage, pszModifier);
     }
     else
@@ -1361,5 +1404,5 @@
          * form "CATEGORY1=value1;CATEGORY2=value2[;...]", where values are
          * also in XPG format: "language[_territory[.codeset]][@modifier]".
-         * Currently we're ignoring the modifier.
+         * Currently we're only handling the @EURO/@euro modifiers and ignoring the rest.
          */
         pszNext = strchr(pszLocale, ';');
@@ -1383,13 +1426,14 @@
                         char        *pszVal = &pszCur[cch + 1];
                         const char  *pszValCp;
+                        const char  *pszValQual;
                         /* parse the locale value. */
-                        rc = localeParseLocale(pszVal, &pszValCp);
+                        rc = localeParseLocale(pszVal, &pszValCp, &pszValQual);
                         if (!rc)
                         {
                             if (iCat != LC_ALL)
-                                rc = localeDoOne(pTemp, iCat, pszVal, pszValCp);
+                                rc = localeDoOne(pTemp, iCat, pszVal, pszValCp, pszValQual);
                             else /* Iterate all categories except LC_ALL. */
                                 for (iCat = LC_ALL + 1; !rc && iCat < _LC_LAST; iCat++)
-                                    rc = localeDoOne(pTemp, iCat, pszVal, pszValCp);
+                                    rc = localeDoOne(pTemp, iCat, pszVal, pszValCp, pszValQual);
                         }
                         break;
@@ -1412,5 +1456,5 @@
              * Parse it first to save time.
              */
-            rc = localeParseLocale(pszLocale, &pszCodepage);
+            rc = localeParseLocale(pszLocale, &pszCodepage, &pszModifier);
             if (!rc)
             {
@@ -1425,13 +1469,14 @@
                     {
                         const char *pszCodepageEnv;
+                        const char *pszModifierEnv;
                         char *pszCopy = alloca(strlen(pszEnv) + 1);
                         if (!pszCopy)
                             LIBCLOG_RETURN_INT(-ENOMEM);
-                        rc = localeParseLocale(strcpy(pszCopy, pszEnv), &pszCodepageEnv);
+                        rc = localeParseLocale(strcpy(pszCopy, pszEnv), &pszCodepageEnv, &pszModifierEnv);
                         if (!rc)
-                            rc = localeDoOne(pTemp, iCat, pszCopy, pszCodepageEnv);
+                            rc = localeDoOne(pTemp, iCat, pszCopy, pszCodepageEnv, pszModifierEnv);
                     }
                     else
-                        rc = localeDoOne(pTemp, iCat, pszLocale, pszCodepage);
+                        rc = localeDoOne(pTemp, iCat, pszLocale, pszCodepage, pszModifier);
                 }
             }
@@ -1521,5 +1566,5 @@
     if (pTemp->afProcessed[LC_MESSAGES + 1])
     {
-        pTemp->afProcessed[LC_MONETARY + 1] = 0;
+        pTemp->afProcessed[LC_MESSAGES + 1] = 0;
         gLocale.apszNames[LC_MESSAGES + 1] = pTemp->Global.apszNames[LC_MESSAGES + 1];
     }
@@ -1604,5 +1649,5 @@
 /**
  * This setlocale() implementation differs from the specs in that any
- * options specified by '@...' is ignored.
+ * options specified by '@...' other than EURO/euro is ignored.
  */
 char *_STD(setlocale)(int iCategory, const char *pszLocale)
@@ -1728,7 +1773,8 @@
                 UconvObject     uobj;
                 const char *pszCodepage;
-                int     cch1 = strlen(gLocale.apszNames[LC_CTYPE + 1]);
-                int     cch2 = strlen(gLocale.apszNames[LC_COLLATE + 1]);
-                int     cch = cch1 > cch2 ? cch1 + 1 : cch2 + 1;
+                const char *pszModifier;
+                int     cch1 = strlen(gLocale.apszNames[LC_CTYPE + 1]) + 1;
+                int     cch2 = strlen(gLocale.apszNames[LC_COLLATE + 1]) + 1;
+                int     cch = cch1 > cch2 ? cch1 : cch2;
                 char   *psz = alloca(cch);
                 if (!psz)
@@ -1738,6 +1784,6 @@
                     ||  __libc_GLocaleCtype.uobj)
                 {
-                    memcpy(psz, gLocale.apszNames[LC_CTYPE + 1], cch1 + 1);
-                    localeParseLocale(psz, &pszCodepage);
+                    memcpy(psz, gLocale.apszNames[LC_CTYPE + 1], cch);
+                    localeParseLocale(psz, &pszCodepage, &pszModifier);
                     rc = __libc_localeCreateObjects(psz, pszCodepage, NULL, &lobj, &uobj);
                     if (!rc)
@@ -1758,6 +1804,6 @@
                     ||  __libc_gLocaleCollate.uobj)
                 {
-                    memcpy(psz, gLocale.apszNames[LC_COLLATE + 1], cch2 + 1);
-                    localeParseLocale(psz, &pszCodepage);
+                    memcpy(psz, gLocale.apszNames[LC_COLLATE + 1], cch);
+                    localeParseLocale(psz, &pszCodepage, &pszModifier);
                     rc = __libc_localeCreateObjects(psz, pszCodepage, NULL, &lobj, &uobj);
                     if (!rc)
