/*************************************************************************** * * 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 // for assert() #include // for atoi() #include // 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(); }