281 lines
9.5 KiB
C++
281 lines
9.5 KiB
C++
/***************************************************************************
|
|
*
|
|
* numeric.cpp
|
|
*
|
|
* $Id: numeric.cpp 448754 2006-09-22 00:42:16Z 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 <cstdlib> // for atoi()
|
|
#include <fstream> // for ofstream
|
|
|
|
|
|
static const char lc_name[] = "LC_NUMERIC";
|
|
|
|
|
|
void Def::process_numeric ()
|
|
{
|
|
issue_diag (I_STAGE, false, 0, "processing %s section\n", lc_name);
|
|
|
|
// nesting level
|
|
int nesting_level = 0;
|
|
|
|
num_def_found_ = true;
|
|
|
|
while ((next = scanner_.next_token()).token != Scanner::tok_numeric) {
|
|
|
|
switch (next.token) {
|
|
|
|
case Scanner::tok_end:
|
|
next = scanner_.next_token();
|
|
if (next.token == Scanner::tok_numeric) {
|
|
// end of numeric 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_numeric ){
|
|
// the LC_IDENTIFICATION section may also have a
|
|
// LC_NUMERIC 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_decimal_point:
|
|
next = scanner_.next_token();
|
|
num_st_.decimal_point = convert_string (next.name);
|
|
num_st_.wdecimal_point = convert_wstring (next);
|
|
break;
|
|
|
|
case Scanner::tok_thousands_sep:
|
|
next = scanner_.next_token();
|
|
num_st_.thousands_sep = convert_string (next.name);
|
|
num_st_.wthousands_sep = convert_wstring (next);
|
|
break;
|
|
|
|
case Scanner::tok_grouping:
|
|
// convert the grouping digits from ascii to integers before
|
|
// adding them to the grouping string
|
|
num_st_.grouping.clear();
|
|
while ((next = scanner_.next_token()).token
|
|
!= Scanner::tok_nl)
|
|
num_st_.grouping += std::atoi(next.name.c_str());
|
|
break;
|
|
|
|
case Scanner::tok_truename:
|
|
next = scanner_.next_token();
|
|
num_st_.truename = convert_string (next.name);
|
|
num_st_.wtruename = convert_wstring (next);
|
|
break;
|
|
|
|
case Scanner::tok_falsename:
|
|
next = scanner_.next_token();
|
|
num_st_.falsename = convert_string (next.name);
|
|
num_st_.wfalsename = convert_wstring (next);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Def::write_numeric (std::string dir_name)
|
|
{
|
|
assert (!dir_name.empty ());
|
|
|
|
if (num_written_)
|
|
return;
|
|
|
|
if (!num_def_found_) {
|
|
issue_diag (I_SKIP, false, 0,
|
|
"%s section not found, skipping\n", lc_name);
|
|
return;
|
|
}
|
|
|
|
(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);
|
|
|
|
// calculate the offsets of members of the num_punct struct
|
|
|
|
// start with wide strings to simplify dealing with their alignment
|
|
num_punct_out_.decimal_point_off [1] = 0;
|
|
|
|
num_punct_out_.thousands_sep_off [1] =
|
|
num_punct_out_.decimal_point_off [1]
|
|
+ (num_st_.wdecimal_point.size () + 1) * sizeof (wchar_t);
|
|
|
|
num_punct_out_.decimal_point_off [0] =
|
|
num_punct_out_.thousands_sep_off [1]
|
|
+ (num_st_.wthousands_sep.size() + 1) * sizeof (wchar_t);
|
|
|
|
num_punct_out_.thousands_sep_off [0] =
|
|
num_punct_out_.decimal_point_off [0]
|
|
+ num_st_.decimal_point.size () + 1;
|
|
|
|
num_punct_out_.grouping_off =
|
|
num_punct_out_.thousands_sep_off [0]
|
|
+ num_st_.thousands_sep.size () + 1;
|
|
|
|
num_punct_out_.punct_ext_off =
|
|
num_punct_out_.grouping_off
|
|
+ num_st_.grouping.size () + 1;
|
|
|
|
// compute the alignment requirement of any offset member
|
|
const std::size_t align = sizeof num_punct_out_.punct_ext_off;
|
|
|
|
// align the offset of the extension struct on the required boundary
|
|
const std::size_t misalign = num_punct_out_.punct_ext_off % align;
|
|
|
|
// compute the amount of padding between the two structs
|
|
const std::size_t pad = misalign ? align - misalign : 0;
|
|
|
|
num_punct_out_.punct_ext_off += pad;
|
|
|
|
// calculate the offsets of members of the numeric extension struct
|
|
|
|
num_out_.truename_off [1] = 0;
|
|
|
|
num_out_.falsename_off [1] =
|
|
num_out_.truename_off [1]
|
|
+ (num_st_.wtruename.size() + 1) * sizeof (wchar_t);
|
|
|
|
num_out_.truename_off [0] =
|
|
num_out_.falsename_off [1]
|
|
+ (num_st_.wfalsename.size() + 1) * sizeof (wchar_t);
|
|
|
|
num_out_.falsename_off [0] =
|
|
num_out_.truename_off [0]
|
|
+ num_st_.truename.size() + 1;
|
|
|
|
num_out_.codeset_off =
|
|
num_out_.falsename_off [0]
|
|
+ num_st_.falsename.size() + 1;
|
|
|
|
num_out_.charmap_off =
|
|
num_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_numpunct_t {\n"
|
|
" falsename_off[] = { %u, %u }\n"
|
|
" truename_off[] = { %u, %u }\n"
|
|
" codeset_off = %u\n"
|
|
" charmap_off = %u\n"
|
|
"}\n",
|
|
lc_name,
|
|
num_punct_out_.decimal_point_off [0],
|
|
num_punct_out_.decimal_point_off [1],
|
|
num_punct_out_.thousands_sep_off [0],
|
|
num_punct_out_.thousands_sep_off [1],
|
|
num_punct_out_.grouping_off,
|
|
num_punct_out_.punct_ext_off,
|
|
num_out_.falsename_off [0],
|
|
num_out_.falsename_off [1],
|
|
num_out_.truename_off [0],
|
|
num_out_.truename_off [1],
|
|
num_out_.codeset_off,
|
|
num_out_.charmap_off);
|
|
|
|
// write the num_punct struct
|
|
out.write ((char*)&num_punct_out_, sizeof (num_punct_out_));
|
|
|
|
// write out the strings in the num_punct struct
|
|
out.write ((const char*)num_st_.wdecimal_point.c_str (),
|
|
(num_st_.wdecimal_point.size() + 1) * sizeof (wchar_t));
|
|
out.write ((const char*)num_st_.wthousands_sep.c_str(),
|
|
(num_st_.wthousands_sep.size() + 1) * sizeof(wchar_t));
|
|
|
|
out << num_st_.decimal_point << std::ends
|
|
<< num_st_.thousands_sep << std::ends
|
|
<< num_st_.grouping << std::ends;
|
|
|
|
// pad the structure up to the next alignment boundary
|
|
out.write ("\0\0\0\0\0\0\0\0", pad);
|
|
|
|
// write the numeric offset extension struct
|
|
out.write ((char*)&num_out_, sizeof (num_out_));
|
|
|
|
// write all the wide character strings
|
|
out.write ((const char*)num_st_.wtruename.c_str(),
|
|
(num_st_.wtruename.size() + 1) * sizeof (wchar_t));
|
|
out.write ((const char*)num_st_.wfalsename.c_str(),
|
|
(num_st_.wfalsename.size() + 1) * sizeof (wchar_t));
|
|
|
|
|
|
// write the narrow strings and codeset name
|
|
out << num_st_.truename << std::ends
|
|
<< num_st_.falsename << std::ends
|
|
<< charmap_.get_code_set_name() << std::ends
|
|
<< charmap_.get_charmap_name() << std::ends;
|
|
|
|
out.close();
|
|
}
|