first commit
This commit is contained in:
570
extern/stdcxx/4.2.1/util/monetary.cpp
vendored
Normal file
570
extern/stdcxx/4.2.1/util/monetary.cpp
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* monetary.cpp
|
||||
*
|
||||
* $Id: monetary.cpp 480734 2006-11-29 22:22:44Z sebor $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* Copyright 2001-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "def.h" // for Def
|
||||
#include "diagnostic.h" // for issue_diag()
|
||||
#include "path.h" // for get_pathname()
|
||||
#include "scanner.h" // for scanner
|
||||
|
||||
#include <cassert> // for assert()
|
||||
#include <climits> // for CHAR_MAX, CHAR_MIN
|
||||
#include <cstdlib> // for strtol()
|
||||
#include <fstream> // for ofstream
|
||||
#include <locale> // for money_base
|
||||
|
||||
|
||||
static const char lc_name[] = "LC_MONETARY";
|
||||
|
||||
|
||||
void Def::process_monetary ()
|
||||
{
|
||||
issue_diag (I_STAGE, false, 0, "processing %s section\n", lc_name);
|
||||
|
||||
// nesting level
|
||||
int nesting_level = 0;
|
||||
|
||||
mon_def_found_ = true;
|
||||
|
||||
while ((next = scanner_.next_token ()).token != Scanner::tok_monetary) {
|
||||
|
||||
// set to point to the integer represented as an ordinary char
|
||||
// corresponding to p_cs_precedes, p_sep_by_space, p_sign_posn,
|
||||
// or one of the n_ (or int_ versions) of the same
|
||||
char *pcharint = 0;
|
||||
|
||||
typedef unsigned char UChar;
|
||||
long maxval = long (UChar (CHAR_MAX)); // maximum allowed value
|
||||
|
||||
switch (next.token) {
|
||||
|
||||
case Scanner::tok_end:
|
||||
next = scanner_.next_token();
|
||||
if (next.token == Scanner::tok_monetary) {
|
||||
// end of monetary block
|
||||
if (nesting_level == 0)
|
||||
return;
|
||||
|
||||
nesting_level--;
|
||||
scanner_.close ();
|
||||
}
|
||||
else
|
||||
issue_diag (E_SYNTAX, true, &next,
|
||||
"wrong section name in END directive\n");
|
||||
|
||||
break;
|
||||
|
||||
case Scanner::tok_copy: {
|
||||
next = scanner_.next_token();
|
||||
if (next.token != Scanner::tok_string)
|
||||
issue_diag (E_SYNTAX, true, &next,
|
||||
"expected string following \"copy\" directive\n");
|
||||
|
||||
// bump up the nesting level
|
||||
nesting_level++;
|
||||
|
||||
issue_diag (I_STAGE, false, 0, "processing copy directive\n");
|
||||
|
||||
// open the file
|
||||
scanner_.open (get_pathname (strip_quotes (next.name), next.file));
|
||||
|
||||
// get comment char and escape char;
|
||||
// these informations are stored by the scanner
|
||||
while ((next = scanner_.next_token ()).token
|
||||
!= Scanner::tok_monetary ){
|
||||
// the LC_IDENTIFICATION section may also have a
|
||||
// LC_MONETARY token that will mess up the parsing
|
||||
if (next.token == Scanner::tok_ident) {
|
||||
while ((next = scanner_.next_token()).token
|
||||
!= Scanner::tok_end );
|
||||
next = scanner_.next_token();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Scanner::tok_int_curr_symbol:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.int_curr_symbol = convert_string (next.name);
|
||||
mon_st_.wint_curr_symbol = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_currency_symbol:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.currency_symbol = convert_string (next.name);
|
||||
mon_st_.wcurrency_symbol = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_mon_decimal_point:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.mon_decimal_point = convert_string (next.name);
|
||||
mon_st_.wmon_decimal_point = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_mon_thousands_sep:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.mon_thousands_sep = convert_string (next.name);
|
||||
mon_st_.wmon_thousands_sep = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_mon_grouping:
|
||||
mon_st_.mon_grouping.clear();
|
||||
while ((next = scanner_.next_token()).token != Scanner::tok_nl)
|
||||
mon_st_.mon_grouping += std::strtol (next.name.c_str (), 0, 10);
|
||||
break;
|
||||
|
||||
case Scanner::tok_positive_sign:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.positive_sign = convert_string (next.name);
|
||||
mon_st_.wpositive_sign = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_negative_sign:
|
||||
next = scanner_.next_token();
|
||||
mon_st_.negative_sign = convert_string (next.name);
|
||||
mon_st_.wnegative_sign = convert_wstring (next);
|
||||
break;
|
||||
|
||||
case Scanner::tok_frac_digits:
|
||||
pcharint = &mon_out_.frac_digits [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_frac_digits:
|
||||
pcharint = &mon_out_.frac_digits [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_p_cs_precedes:
|
||||
maxval = 1;
|
||||
pcharint = &mon_out_.p_cs_precedes [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_p_sep_by_space:
|
||||
maxval = 2;
|
||||
pcharint = &mon_out_.p_sep_by_space [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_n_cs_precedes:
|
||||
maxval = 1;
|
||||
pcharint = &mon_out_.n_cs_precedes [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_n_sep_by_space:
|
||||
maxval = 2;
|
||||
pcharint = &mon_out_.n_sep_by_space [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_p_sign_posn:
|
||||
maxval = 4;
|
||||
pcharint = &mon_out_.p_sign_posn [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_n_sign_posn:
|
||||
maxval = 4;
|
||||
pcharint = &mon_out_.n_sign_posn [0];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_p_cs_precedes:
|
||||
maxval = 1;
|
||||
pcharint = &mon_out_.p_cs_precedes [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_p_sep_by_space:
|
||||
maxval = 2;
|
||||
pcharint = &mon_out_.p_sep_by_space [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_n_cs_precedes:
|
||||
maxval = 1;
|
||||
pcharint = &mon_out_.n_cs_precedes [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_n_sep_by_space:
|
||||
maxval = 2;
|
||||
pcharint = &mon_out_.n_sep_by_space [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_p_sign_posn:
|
||||
maxval = 4;
|
||||
pcharint = &mon_out_.p_sign_posn [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
case Scanner::tok_int_n_sign_posn:
|
||||
maxval = 4;
|
||||
pcharint = &mon_out_.n_sign_posn [1 /* int'l */ ];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (pcharint) {
|
||||
next = scanner_.next_token ();
|
||||
|
||||
char *end = 0;
|
||||
const long val = std::strtol (next.name.c_str (), &end, 10);
|
||||
|
||||
if (next.name.empty () || *end || val < -1 || maxval < val) {
|
||||
// report as errors values outside the permitted range
|
||||
// (-1 indicates an unspecified value for a keyword)
|
||||
issue_diag (E_INVAL, true, &next,
|
||||
"expected integer in [0, %li], got: %s\n",
|
||||
maxval, next.name.c_str ());
|
||||
}
|
||||
else
|
||||
*pcharint = -1 == val ? CHAR_MAX : char (val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Def::create_format (char format [4],
|
||||
char sign_posn,
|
||||
char cs_precedes,
|
||||
char sep_by_space,
|
||||
bool is_positive)
|
||||
{
|
||||
switch (sign_posn) {
|
||||
// the international extension is not defined for this locale
|
||||
case CHAR_MAX:
|
||||
format [0] = CHAR_MAX;
|
||||
format [1] = CHAR_MAX;
|
||||
format [2] = CHAR_MAX;
|
||||
format [3] = CHAR_MAX;
|
||||
return;
|
||||
|
||||
case 0:
|
||||
// if sign_posn is 0 then we change the sign to "()", if sign is
|
||||
// not the empty string then issue a warning
|
||||
if (is_positive) {
|
||||
if (!mon_st_.positive_sign.empty())
|
||||
warnings_occurred_ =
|
||||
issue_diag (W_INVAL, false, 0,
|
||||
"invalid combination of positive_sign "
|
||||
"and p_sign_posn. Ignoring positive_sign")
|
||||
|| warnings_occurred_;
|
||||
mon_st_.positive_sign = "()";
|
||||
}
|
||||
else {
|
||||
if (!mon_st_.negative_sign.empty())
|
||||
warnings_occurred_ =
|
||||
issue_diag (W_INVAL, false, 0,
|
||||
"invalid combination of negative_sign "
|
||||
"and n_sign_posn. Ignoring negative_sign")
|
||||
|| warnings_occurred_;
|
||||
mon_st_.negative_sign = "()";
|
||||
}
|
||||
|
||||
// now construct the format
|
||||
format[0] = std::money_base::sign;
|
||||
if (cs_precedes == 0) {
|
||||
format[1] = std::money_base::value;
|
||||
format[2] = std::money_base::symbol;
|
||||
}
|
||||
else {
|
||||
format[1] = std::money_base::symbol;
|
||||
format[2] = std::money_base::value;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
format[0] = std::money_base::sign;
|
||||
if (cs_precedes == 0) {
|
||||
format[1] = std::money_base::value;
|
||||
format[2] = std::money_base::symbol;
|
||||
}
|
||||
else {
|
||||
format[1] = std::money_base::symbol;
|
||||
format[2] = std::money_base::value;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (cs_precedes == 0) {
|
||||
format[0] = std::money_base::value;
|
||||
format[1] = std::money_base::symbol;
|
||||
}
|
||||
else {
|
||||
format[0] = std::money_base::symbol;
|
||||
format[1] = std::money_base::value;
|
||||
}
|
||||
format[2] = std::money_base::sign;
|
||||
break;
|
||||
case 3:
|
||||
if (cs_precedes == 0) {
|
||||
format[0] = std::money_base::value;
|
||||
format[1] = std::money_base::sign;
|
||||
format[2] = std::money_base::symbol;
|
||||
}
|
||||
else {
|
||||
format[0] = std::money_base::sign;
|
||||
format[1] = std::money_base::symbol;
|
||||
format[2] = std::money_base::value;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (cs_precedes == 0) {
|
||||
format[0] = std::money_base::value;
|
||||
format[1] = std::money_base::symbol;
|
||||
format[2] = std::money_base::sign;
|
||||
}
|
||||
else {
|
||||
format[0] = std::money_base::symbol;
|
||||
format[1] = std::money_base::sign;
|
||||
format[2] = std::money_base::value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// now put the space in the appropriate position
|
||||
if (sep_by_space == 0)
|
||||
format[3] = std::money_base::none;
|
||||
else if (sep_by_space == 1) {
|
||||
if (format[0] == std::money_base::value) {
|
||||
format[3] = format[2];
|
||||
format[2] = format[1];
|
||||
format[1] = std::money_base::space;
|
||||
}
|
||||
else if (format[2] == std::money_base::value) {
|
||||
format[3] = format[2];
|
||||
format[2] = std::money_base::space;
|
||||
}
|
||||
else if (format[0] == std::money_base::symbol) {
|
||||
format[3] = format[2];
|
||||
format[2] = format[1];
|
||||
format[1] = std::money_base::space;
|
||||
}
|
||||
else {
|
||||
format[3] = format[2];
|
||||
format[2] = std::money_base::space;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (format[0] == std::money_base::value) {
|
||||
format[3] = format[2];
|
||||
format[2] = std::money_base::space;
|
||||
}
|
||||
else if (format[2] == std::money_base::value) {
|
||||
format[3] = format[2];
|
||||
format[2] = format[1];
|
||||
format[1] = std::money_base::space;
|
||||
}
|
||||
else if (format[0] == std::money_base::symbol) {
|
||||
format[3] = format[2];
|
||||
format[2] = std::money_base::space;
|
||||
}
|
||||
else {
|
||||
format[3] = format[2];
|
||||
format[2] = format[1];
|
||||
format[1] = std::money_base::space;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Def::write_monetary (std::string dir_name)
|
||||
{
|
||||
assert (!dir_name.empty());
|
||||
|
||||
if (mon_written_)
|
||||
return;
|
||||
|
||||
if (!mon_def_found_) {
|
||||
issue_diag (I_SKIP, false, 0,
|
||||
"%s section not found, skipping\n", lc_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// write out all the information in the LC_MONETARY category
|
||||
(dir_name += _RWSTD_PATH_SEP) += lc_name;
|
||||
|
||||
issue_diag (I_OPENWR, false, 0, "writing %s\n", dir_name.c_str ());
|
||||
|
||||
std::ofstream out (dir_name.c_str(), std::ios::binary);
|
||||
out.exceptions (std::ios::failbit | std::ios::badbit);
|
||||
|
||||
_RW::__rw_punct_t punct;
|
||||
|
||||
// calculate the offsets for the mon_punct structure
|
||||
punct.decimal_point_off [1] = 0;
|
||||
|
||||
punct.thousands_sep_off [1] =
|
||||
punct.decimal_point_off [1]
|
||||
+ (mon_st_.wmon_decimal_point.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
punct.decimal_point_off [0] =
|
||||
punct.thousands_sep_off [1]
|
||||
+ (mon_st_.wmon_thousands_sep.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
punct.thousands_sep_off [0] =
|
||||
punct.decimal_point_off [0]
|
||||
+ mon_st_.mon_decimal_point.size () + 1;
|
||||
|
||||
punct.grouping_off =
|
||||
punct.thousands_sep_off [0]
|
||||
+ mon_st_.mon_thousands_sep.size () + 1;
|
||||
|
||||
punct.punct_ext_off =
|
||||
punct.grouping_off
|
||||
+ mon_st_.mon_grouping.size () + 1;
|
||||
|
||||
// compute the alignment requirement of any offset member
|
||||
const std::size_t align = sizeof punct.punct_ext_off;
|
||||
|
||||
// align the offset of the extension struct on the required boundary
|
||||
const std::size_t misalign = punct.punct_ext_off % align;
|
||||
|
||||
// compute the amount of padding between the two structs
|
||||
const std::size_t pad = misalign ? align - misalign : 0;
|
||||
|
||||
punct.punct_ext_off += pad;
|
||||
|
||||
mon_out_.curr_symbol_off [1][1] = 0;
|
||||
|
||||
mon_out_.curr_symbol_off [0][1] =
|
||||
mon_out_.curr_symbol_off [1][1]
|
||||
+ (mon_st_.wint_curr_symbol.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
mon_out_.positive_sign_off [1] =
|
||||
mon_out_.curr_symbol_off [0][1]
|
||||
+ (mon_st_.wcurrency_symbol.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
mon_out_.negative_sign_off [1] =
|
||||
mon_out_.positive_sign_off [1]
|
||||
+ (mon_st_.wpositive_sign.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
|
||||
// calculate all the narrow character string offsets
|
||||
mon_out_.curr_symbol_off [1][0] =
|
||||
mon_out_.negative_sign_off [1]
|
||||
+ (mon_st_.wnegative_sign.size () + 1) * sizeof (wchar_t);
|
||||
|
||||
mon_out_.curr_symbol_off [0][0] =
|
||||
mon_out_.curr_symbol_off [1][0]
|
||||
+ mon_st_.int_curr_symbol.size () + 1;
|
||||
|
||||
mon_out_.positive_sign_off [0] =
|
||||
mon_out_.curr_symbol_off [0][0]
|
||||
+ mon_st_.currency_symbol.size() + 1;
|
||||
|
||||
mon_out_.negative_sign_off [0] =
|
||||
mon_out_.positive_sign_off [0]
|
||||
+ mon_st_.positive_sign.size () + 1;
|
||||
|
||||
mon_out_.codeset_off =
|
||||
mon_out_.negative_sign_off [0]
|
||||
+ mon_st_.negative_sign.size () + 1;
|
||||
|
||||
mon_out_.charmap_off =
|
||||
mon_out_.codeset_off
|
||||
+ charmap_.get_code_set_name ().size () + 1;
|
||||
|
||||
issue_diag (I_WRITE, false, 0,
|
||||
"%s layout:\n"
|
||||
"__rw_punct_t {\n"
|
||||
" decimal_point_off[] = { %u, %u }\n"
|
||||
" thousand_sep_off[] = { %u, %u }\n"
|
||||
" grouping_off = %u\n"
|
||||
" ext_off = %u\n"
|
||||
"}\n__rw_moneypunct_t {\n"
|
||||
" curr_symbol_off[][] = { { %u, %u }, { %u, %u } }\n"
|
||||
" positive_sign_off[] = { %u, %u }\n"
|
||||
" negative_sign_off[] = { %u, %u }\n"
|
||||
" codeset_off = %u\n"
|
||||
" charmap_off = %u\n"
|
||||
"}\n",
|
||||
lc_name,
|
||||
punct.decimal_point_off [0],
|
||||
punct.decimal_point_off [1],
|
||||
punct.thousands_sep_off [0],
|
||||
punct.thousands_sep_off [1],
|
||||
punct.grouping_off,
|
||||
punct.punct_ext_off,
|
||||
mon_out_.curr_symbol_off [0][0],
|
||||
mon_out_.curr_symbol_off [0][1],
|
||||
mon_out_.curr_symbol_off [1][0],
|
||||
mon_out_.curr_symbol_off [1][1],
|
||||
mon_out_.positive_sign_off [0],
|
||||
mon_out_.negative_sign_off [1],
|
||||
mon_out_.codeset_off,
|
||||
mon_out_.charmap_off);
|
||||
|
||||
// construct the pos_format and neg_format
|
||||
create_format (mon_out_.pos_format[0], mon_out_.p_sign_posn[0],
|
||||
mon_out_.p_cs_precedes[0], mon_out_.p_sep_by_space[0],
|
||||
true);
|
||||
|
||||
create_format (mon_out_.neg_format[0], mon_out_.n_sign_posn[0],
|
||||
mon_out_.n_cs_precedes[0], mon_out_.n_sep_by_space[0],
|
||||
false);
|
||||
|
||||
create_format (mon_out_.pos_format[1], mon_out_.p_sign_posn[1],
|
||||
mon_out_.p_cs_precedes[1], mon_out_.p_sep_by_space[1],
|
||||
true);
|
||||
|
||||
create_format (mon_out_.neg_format[1], mon_out_.n_sign_posn[1],
|
||||
mon_out_.n_cs_precedes[1], mon_out_.n_sep_by_space[1],
|
||||
false);
|
||||
|
||||
// write out the mon_punct structure
|
||||
out.write ((char*)&punct, sizeof punct);
|
||||
|
||||
// write out the strings in the punct structure
|
||||
out.write ((const char*)mon_st_.wmon_decimal_point.c_str(),
|
||||
(mon_st_.wmon_decimal_point.size() + 1) * sizeof(wchar_t));
|
||||
out.write ((const char*)mon_st_.wmon_thousands_sep.c_str(),
|
||||
(mon_st_.wmon_thousands_sep.size() + 1) * sizeof(wchar_t));
|
||||
|
||||
out << mon_st_.mon_decimal_point << std::ends
|
||||
<< mon_st_.mon_thousands_sep << std::ends
|
||||
<< mon_st_.mon_grouping << std::ends;
|
||||
|
||||
// pad the structure up to the next alignment boundary
|
||||
out.write ("\0\0\0\0\0\0\0\0", pad);
|
||||
|
||||
// now write out the monetary offset extension struct
|
||||
out.write ((char*)&mon_out_, sizeof (mon_out_));
|
||||
|
||||
// write the wide character strings
|
||||
out.write ((const char*)mon_st_.wint_curr_symbol.c_str(),
|
||||
(mon_st_.wint_curr_symbol.size() + 1) * sizeof(wchar_t));
|
||||
out.write ((const char*)mon_st_.wcurrency_symbol.c_str(),
|
||||
(mon_st_.wcurrency_symbol.size() + 1) * sizeof(wchar_t));
|
||||
out.write ((const char*)mon_st_.wpositive_sign.c_str(),
|
||||
(mon_st_.wpositive_sign.size() + 1) * sizeof(wchar_t));
|
||||
out.write ((const char*)mon_st_.wnegative_sign.c_str(),
|
||||
(mon_st_.wnegative_sign.size() + 1) * sizeof(wchar_t));
|
||||
|
||||
// write the narrow character strings
|
||||
out << mon_st_.int_curr_symbol << std::ends
|
||||
<< mon_st_.currency_symbol << std::ends
|
||||
<< mon_st_.positive_sign << std::ends
|
||||
<< mon_st_.negative_sign << std::ends
|
||||
<< charmap_.get_code_set_name() << std::ends
|
||||
<< charmap_.get_charmap_name() << std::ends;
|
||||
}
|
||||
Reference in New Issue
Block a user