Toshihiro Shimizu 890ddd
#include <cerrno></cerrno>
Shinya Kitaoka 120a6e
#include <cstring> /* memset */</cstring>
Toshihiro Shimizu 890ddd
#include <vector></vector>
Shinya Kitaoka 120a6e
#include <stdexcept>  // std::domain_error(-)</stdexcept>
Toshihiro Shimizu 890ddd
#include <locale></locale>
Toshihiro Shimizu 890ddd
#include <iconv.h></iconv.h>
Toshihiro Shimizu 890ddd
#include "igs_resource_msg_from_err.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------ localeを日本に設定し日本語を扱うことを指示(必須)
Toshihiro Shimizu 890ddd
使う文字コードは"locale -a"で調べる */
Shinya Kitaoka 120a6e
void igs::resource::locale_to_jp(void) { setlocale(LC_CTYPE, "ja_JP.utf8"); }
Shinya Kitaoka 120a6e
#if 0  //------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
	リサーチ中
Toshihiro Shimizu 890ddd
	日本語環境を環境変数から取ってくる場合のルーチン
Toshihiro Shimizu 890ddd
	deamonの場合これでいいのか???
Toshihiro Shimizu 890ddd
	さらに調査が必要
Toshihiro Shimizu 890ddd
	2013-02-18
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
#include <x11 xlib.h=""></x11>
Toshihiro Shimizu 890ddd
#include <x11 xlocale.h=""></x11>
Toshihiro Shimizu 890ddd
void igs::resource::locale_to_jp(void) {
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
		Software Design 1993年3月号
Toshihiro Shimizu 890ddd
		"SPECIAL ISSUE  どうする?UNIXの日本語環境"
Toshihiro Shimizu 890ddd
		稚内北星短期大学  丸山 不二夫
Toshihiro Shimizu 890ddd
		Page14  リスト4  より
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		X11R5での日本語処理 - ロケールの設定
Toshihiro Shimizu 890ddd
		標準的な処理手順
Toshihiro Shimizu 890ddd
		全てのX(lib)プログラムの先頭で行う
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* 次の場合、環境変数 LANG から、地域名を得ます
Toshihiro Shimizu 890ddd
		引数locale が "" の場合、
Toshihiro Shimizu 890ddd
		ロケールの各部分の設定には環境変数が参照される。
Toshihiro Shimizu 890ddd
		その詳細は実装依存である。
Toshihiro Shimizu 890ddd
		Linux Programmer’s Manual  July 4, 1999より
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	if ( ::setlocale( LC_ALL ,"" ) == NULL ) {
Toshihiro Shimizu 890ddd
		throw std::domain_error( "Can not set locale." );
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* Xlibが、現在の地域をサポートしているかチェックします */
Toshihiro Shimizu 890ddd
	if ( !::XSupportsLocale() ) {
Toshihiro Shimizu 890ddd
		std::string msg("X is not support locale ");
Toshihiro Shimizu 890ddd
		msg += setlocale( LC_ALL ,NULL );
Toshihiro Shimizu 890ddd
		msg += ".\n";
Toshihiro Shimizu 890ddd
		throw std::domain_error( msg.c_str() );
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* 次の場合、環境変数 XMODIFIERS から修飾子が得られます
Toshihiro Shimizu 890ddd
	この修飾子は。入力メソッド (IM) の指定に使われます */
Toshihiro Shimizu 890ddd
	if ( ::XSetLocaleModifiers("") == NULL ) {
Toshihiro Shimizu 890ddd
		throw std::domain_error( "Can not set locale modifiers." );
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
#g++ -L/usr/X11R6/lib/ -lXmu -lXext -lX11 -lgthread -lglib -lm tes82.cxx
Toshihiro Shimizu 890ddd
g++ tes82.cxx -L/usr/X11R6/lib/ -lX11
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
#endif  //------
Toshihiro Shimizu 890ddd
/*------ マルチバイト文字列 --> ワイド文字文字列 ------*/
Shinya Kitaoka 120a6e
void igs::resource::mbs_to_wcs(const std::string &mbs, std::wstring &wcs) {
Shinya Kitaoka 120a6e
  size_t length = 0;
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    const char *src_ptr = mbs.c_str();
Shinya Kitaoka 120a6e
    mbstate_t ss;
Shinya Kitaoka 120a6e
    ::memset(&ss, 0, sizeof(ss));
Shinya Kitaoka 120a6e
    length = ::mbsrtowcs(NULL, &src_ptr, 0, &ss);
Shinya Kitaoka 120a6e
    if (length == (size_t)(-1)) { /* 不正なマルチバイト列に遭遇した */
Shinya Kitaoka 120a6e
      throw std::domain_error(
Shinya Kitaoka 120a6e
          "mbstowcs(-) got bad multi byte character,when size");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (length <= 0) {
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    } /* 文字がないなら何もしない */
Shinya Kitaoka 120a6e
    ++length;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // std::vector<wchar_t> dst(length);</wchar_t>
Shinya Kitaoka 120a6e
  wcs.resize(length);
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    const char *src_ptr = mbs.c_str();
Shinya Kitaoka 120a6e
    mbstate_t ss;
Shinya Kitaoka 120a6e
    ::memset(&ss, 0, sizeof(ss));
Shinya Kitaoka 120a6e
    // length = ::mbsrtowcs(&dst.at(0) ,&src_ptr ,length ,&ss);
Shinya Kitaoka 120a6e
    length =
Shinya Kitaoka 120a6e
        ::mbsrtowcs(const_cast<wchar_t *="">(wcs.c_str()), &src_ptr, length, &ss);</wchar_t>
Shinya Kitaoka 120a6e
    if (length == (size_t)(-1)) { /* 不正なマルチバイト列に遭遇した */
Shinya Kitaoka 120a6e
      throw std::domain_error(
Shinya Kitaoka 120a6e
          "mbstowcs(-) got bad multi byte character,when conv");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (length <= 0) {
Shinya Kitaoka 120a6e
      throw std::domain_error("mbstowcs(-) got zero or under equal -2 ");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // wcs = std::wstring(dst.begin() ,dst.end()-1);/* 終端以外を */
Shinya Kitaoka 120a6e
  wcs.erase(wcs.end() - 1); /* 終端文字を消す */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*------ ワイド文字文字列 --> マルチバイト文字列 ------*/
Shinya Kitaoka 120a6e
void igs::resource::wcs_to_mbs(const std::wstring &wcs, std::string &mbs) {
Shinya Kitaoka 120a6e
  size_t length = 0;
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    const wchar_t *src_ptr = wcs.c_str();
Shinya Kitaoka 120a6e
    mbstate_t ss;
Shinya Kitaoka 120a6e
    ::memset(&ss, 0, sizeof(ss));
Shinya Kitaoka 120a6e
    length = ::wcsrtombs(NULL, &src_ptr, 0, &ss);
Shinya Kitaoka 120a6e
    if (length <= 0) {
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    } /* 文字がないなら何もしない */
Shinya Kitaoka 120a6e
    ++length;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // std::vector<char> dst(length);</char>
Shinya Kitaoka 120a6e
  mbs.resize(length);
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    const wchar_t *src_ptr = wcs.c_str();
Shinya Kitaoka 120a6e
    mbstate_t ss;
Shinya Kitaoka 120a6e
    ::memset(&ss, 0, sizeof(ss));
Shinya Kitaoka 120a6e
    // length = ::wcsrtombs(&dst.at(0) ,&src_ptr ,length ,&ss);
Shinya Kitaoka 120a6e
    length =
Shinya Kitaoka 120a6e
        ::wcsrtombs(const_cast<char *="">(mbs.c_str()), &src_ptr, length, &ss);</char>
Shinya Kitaoka 120a6e
    if (length <= 0) {
Shinya Kitaoka 120a6e
      throw std::domain_error("wcstombs(-) got bad wide character");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // mbs = std::string(dst.begin() ,dst.end()-1);/* 終端以外を */
Shinya Kitaoka 120a6e
  mbs.erase(mbs.end() - 1); /* 終端文字を消す */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*------ UNICODE宣言ならマルチバイト文字列をワイド文字文字列に変換 ------*/
Toshihiro Shimizu 890ddd
const std::basic_string<tchar> igs::resource::ts_from_mbs(</tchar>
Shinya Kitaoka 120a6e
    const std::string &mbs) {
Toshihiro Shimizu 890ddd
#if defined UNICODE
Shinya Kitaoka 120a6e
  std::wstring wcs;
Shinya Kitaoka 120a6e
  igs::resource::mbs_to_wcs(mbs, wcs);
Shinya Kitaoka 120a6e
  return wcs;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  /* MBCSの場合のsize()は文字数ではなくchar(byte)数,2bytes文字は2 */
Shinya Kitaoka 120a6e
  return mbs;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*------ UNICODE宣言ならワイド文字文字列をマルチバイト文字列に変換 ------*/
Toshihiro Shimizu 890ddd
const std::string igs::resource::mbs_from_ts(
Shinya Kitaoka 120a6e
    const std::basic_string<tchar> &ts) {</tchar>
Toshihiro Shimizu 890ddd
#if defined UNICODE
Shinya Kitaoka 120a6e
  std::string mbs;
Shinya Kitaoka 120a6e
  igs::resource::wcs_to_mbs(ts, mbs);
Shinya Kitaoka 120a6e
  return mbs;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  /* MBCSの場合のsize()は文字数ではなくchar(byte)数,2bytes文字は2 */
Shinya Kitaoka 120a6e
  return ts;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*------ cp932を含む文字列をutf-8に変換(マルチバイト文字列) ------*/
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
const std::string iconv_to_from_(const std::string &text, const char *tocode,
Shinya Kitaoka 120a6e
                                 const char *fromcode) {
Shinya Kitaoka 120a6e
  iconv_t icd = ::iconv_open(tocode, fromcode);  // "iconv --list"
Shinya Kitaoka 120a6e
  if (reinterpret_cast<iconv_t>(-1) == icd) {</iconv_t>
Shinya Kitaoka 120a6e
    throw std::domain_error(
Shinya Kitaoka 120a6e
        igs_resource_msg_from_err(TEXT("iconv_open(-)"), errno));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<char> dst(text.size() * 4);</char>
Shinya Kitaoka 120a6e
  char *inbuf         = const_cast<char *="">(text.c_str());</char>
Shinya Kitaoka 120a6e
  char *outbuf        = &dst.at(0);
Shinya Kitaoka 120a6e
  size_t inbytesleft  = text.size();
Shinya Kitaoka 120a6e
  size_t outbytesleft = dst.size();
Shinya Kitaoka 120a6e
  size_t ret = ::iconv(icd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
Shinya Kitaoka 120a6e
  *outbuf    = '\0';
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
  retに処理した数が入るはずだが、rhel5ではゼロが帰るので、
Shinya Kitaoka 120a6e
  処理数を別途計算する
Shinya Kitaoka 120a6e
  */
Shinya Kitaoka 120a6e
  ret = dst.size() - outbytesleft;
Shinya Kitaoka 120a6e
  if (ret <= 0) {
Shinya Kitaoka 120a6e
    // if (static_cast<size_t>(-1) == ret) {</size_t>
Shinya Kitaoka 120a6e
    ::iconv_close(icd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    throw std::domain_error(igs_resource_msg_from_err(TEXT("iconv(-)"), errno));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (-1 == ::iconv_close(icd)) {
Shinya Kitaoka 120a6e
    throw std::domain_error(
Shinya Kitaoka 120a6e
        igs_resource_msg_from_err(TEXT("iconv_close(-)"), errno));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string mbs(std::string(dst.begin(), dst.begin() + ret));
Shinya Kitaoka 120a6e
  return mbs;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
const std::string igs::resource::utf8_from_cp932_mb(const std::string &text) {
Shinya Kitaoka 120a6e
  return iconv_to_from_(text, "UTF-8", "CP932");  // "iconv --list"
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
const std::string igs::resource::cp932_from_utf8_mb(const std::string &text) {
Shinya Kitaoka 120a6e
  return iconv_to_from_(text, "CP932", "UTF-8");  // "iconv --list"
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*------ エラーメッセージ表示の元関数、直接呼び出すことはしない ------*/
Shinya Kitaoka 120a6e
#include <cerrno>   // errno</cerrno>
Shinya Kitaoka 120a6e
#include <cstring>  // strerror_r()</cstring>
Shinya Kitaoka 120a6e
#include <sstream>  // std::istringstream</sstream>
Toshihiro Shimizu 890ddd
#include "igs_resource_msg_from_err.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const std::string igs::resource::msg_from_err_(
Shinya Kitaoka 120a6e
    const std::basic_string<tchar> &tit, const int erno,</tchar>
Shinya Kitaoka 120a6e
    const std::string &file, const std::string &line,
Shinya Kitaoka 120a6e
    const std::string &pretty_function, const std::string &comp_type,
Shinya Kitaoka 120a6e
    const std::string &gnuc, const std::string &gnuc_minor,
Shinya Kitaoka 120a6e
    const std::string &gnuc_patchlevel, const std::string &gnuc_rh_release,
Shinya Kitaoka 120a6e
    const std::string &date, const std::string &time) {
Shinya Kitaoka 120a6e
  std::string errmsg;
Shinya Kitaoka 120a6e
  errmsg += '\"';
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /* フルパスで入ってきた場合ファイル名だけにする */
Shinya Kitaoka 120a6e
  std::string::size_type index = file.find_last_of("/\\");
Shinya Kitaoka 120a6e
  if (std::basic_string<tchar>::npos != index) {</tchar>
Shinya Kitaoka 120a6e
    errmsg += file.substr(index + 1);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    errmsg += file;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  errmsg += ':';
Shinya Kitaoka 120a6e
  errmsg += line;
Shinya Kitaoka 120a6e
  errmsg += ':';
Shinya Kitaoka 120a6e
  errmsg += comp_type;
Shinya Kitaoka 120a6e
  errmsg += ':';
Shinya Kitaoka 120a6e
  errmsg += gnuc;
Shinya Kitaoka 120a6e
  errmsg += '.';
Shinya Kitaoka 120a6e
  errmsg += gnuc_minor;
Shinya Kitaoka 120a6e
  errmsg += '.';
Shinya Kitaoka 120a6e
  errmsg += gnuc_patchlevel;
Shinya Kitaoka 120a6e
  errmsg += '-';
Shinya Kitaoka 120a6e
  errmsg += gnuc_rh_release;
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    std::istringstream ist(date);
Shinya Kitaoka 120a6e
    std::string month, day, year;
Shinya Kitaoka 120a6e
    ist >> month;
Shinya Kitaoka 120a6e
    ist >> day;
Shinya Kitaoka 120a6e
    ist >> year;
Shinya Kitaoka 120a6e
    errmsg += ':';
Shinya Kitaoka 120a6e
    errmsg += year;
Shinya Kitaoka 120a6e
    errmsg += ':';
Shinya Kitaoka 120a6e
    errmsg += month;
Shinya Kitaoka 120a6e
    errmsg += ':';
Shinya Kitaoka 120a6e
    errmsg += day;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  errmsg += ':';
Shinya Kitaoka 120a6e
  errmsg += time;
Shinya Kitaoka 120a6e
  errmsg += '\"';
Shinya Kitaoka 120a6e
  errmsg += ' ';
Shinya Kitaoka 120a6e
  errmsg += '\"';
Shinya Kitaoka 120a6e
  errmsg += pretty_function;
Shinya Kitaoka 120a6e
  errmsg += '\"';
Shinya Kitaoka 120a6e
  errmsg += ' ';
Shinya Kitaoka 120a6e
  errmsg += '\"';
Shinya Kitaoka 120a6e
  if (0 < tit.size()) {
Shinya Kitaoka 120a6e
    errmsg += igs::resource::mbs_from_ts(tit);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (0 != erno) {
Shinya Kitaoka 120a6e
    errmsg += ':';
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined __HP_aCC
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
HP-UX(v11.23)では、strerror_r()をサポートしない。
Shinya Kitaoka 120a6e
注意::strerror()はThread SafeではなくMulti Threadでは正常動作しない
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
    errmsg += ::strerror(erno);
Shinya Kitaoka 120a6e
#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
http://japanese-linux-man-pages.coding-school.com/man/X_strerror_r-3
Shinya Kitaoka 120a6e
より、POSIX.1.2002で規定されたXSI準拠のバージョンのstrerror_r()
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
    char buff[4096];
Shinya Kitaoka 120a6e
    const int ret = ::strerror_r(erno, buff, sizeof(buff));
Shinya Kitaoka 120a6e
    if (0 == ret) {
Shinya Kitaoka 120a6e
      errmsg += buff;
Shinya Kitaoka 120a6e
    } else if (-1 == ret) {
Shinya Kitaoka 120a6e
      swtich(errno) {
Shinya Kitaoka 120a6e
      case EINVAL:
Shinya Kitaoka 120a6e
        errmsg +=
Shinya Kitaoka 120a6e
            "strerror_r() gets Error : The value of errnum is not a "
Shinya Kitaoka 120a6e
            "valid error number.";
Shinya Kitaoka 120a6e
        /* errnum の値が有効なエラー番号ではない */
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case ERANGE:
Shinya Kitaoka 120a6e
        errmsg +=
Shinya Kitaoka 120a6e
            "strerror_r() gets Error : Insufficient storage was "
Shinya Kitaoka 120a6e
            "supplied via strerrbuf and buflen  to contain the "
Shinya Kitaoka 120a6e
            "generated message string.";
Shinya Kitaoka 120a6e
        /* エラーコードを説明する文字列のために、
Shinya Kitaoka 120a6e
充分な領域が確保できな かった */
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      deatult:
Shinya Kitaoka 120a6e
        errmsg += "strerror_r() gets Error and Returns bad errno";
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      errmsg += "strerror_r() returns bad value";
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#elif defined(__APPLE__)
Shinya Kitaoka 120a6e
    char buff[4096];
Shinya Kitaoka 120a6e
    int ret = ::strerror_r(erno, buff, sizeof(buff));
Shinya Kitaoka 120a6e
    if (!ret) {
Shinya Kitaoka 120a6e
      errmsg += buff;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    /* linuxはここに来る?
Shinya Kitaoka 120a6e
http://japanese-linux-man-pages.coding-school.com/man/X_strerror_r-3
Shinya Kitaoka 120a6e
より、GNU仕様のバージョンのstrerror_r()。非標準の拡張
Shinya Kitaoka 120a6e
これはThread Safeか??????
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
    char buff[4096];
Shinya Kitaoka 120a6e
    const char *ret = ::strerror_r(erno, buff, sizeof(buff));
Shinya Kitaoka 120a6e
    errmsg += ret;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  errmsg += '\"';
Shinya Kitaoka 120a6e
  return errmsg;
Toshihiro Shimizu 890ddd
}