function _(o) {
	var s = "";

	var displayProp = {
		constantType :	0,	// 定数値フィールド
		primitiveType :	1,	// 基本型値フィールド（文字列型は除く）
		functionType :	0,	// 関数型フィールド
		htmlTextValue :	0	// HTMLテキスト（innerHTML, outerText等）
	};

	var constantTypePattern = new RegExp();
	constantTypePattern.compile("^[A-Z_]+");

	for (var p in o) {
		var v = o[p];

		switch (typeof v) {
			case "function" : {
				if (!displayProp.functionType)
					break;
				s += p + "=function() {...}\n";
				break;
			}
			default : {
				if (!displayProp.constantType
					&& p.match(constantTypePattern) != null)
					break;
				if (!displayProp.primitiveType && typeof p != "object")
					break;
				if (!displayProp.htmlTextValue
					&& (p == "innerHTML"
						|| p == "outerHTML"
						|| p == "innerText"
						|| p == "outerText"
						|| p == "textContent"))
					break;
				s += p + "=" + v + "\n";
			}
		}
	}

	window.errorMessage(s);
}

function getArgs() {
	var args = new Object();

	var query = location.search.substring(1);
	var pairs = query.split('&');

	for (var i = 0; i < pairs.length; i++) {
		var pair = pairs[i];

		var index = pair.indexOf('=');
		if (index == -1)
			continue;

		var key = pair.substring(0, index);
		var value = pair.substring(index + 1);

		args[key] = unescape(value);
	}

	return args;
}

/**
 * 抽象文字列を解析し，文字列を取得する．（汎用）
 * 
 * 抽象文字列とは，0-9，0-2A-Ca-d_, 210\\abc\-A-Dなどであり，
 * それぞれ，0123456789, 012ABCabcd_, 012\abc-ABCDが取得できる．
 * 
 * @param as 抽象文字列．
 * 	"0-9a-c", "0-2A-Ca-d_\\-"など．
 * @param adjusting 真のとき，返り値文字列に含まれる重複文字を整理する．
 * 	省略可能で，指定しないとき真．
 * @param sorting 真のとき，返り値文字列を昇順でソートする．
 * 	省略可能で，指定しないとき真．
 * @return 具象文字列．"0123456789abc", "012ABCabcd_-"など．
 */
function parseAbstractString(as, adjusting, sorting) {
	if (adjusting === void 0) {
		adjusting = true;
	}
	if (sorting === void 0) {
		sorting = true;
	}

	var r = new Array();

	// 重複整理を考慮した文字push関数．
	var pushChar = function() {
		if (adjusting) {
			// 重複チェックに使用するマッピングテーブル．
			var map = new Object();

			return function(r, c) {
				if (map[c] === void 0) {
					r.push(map[c] = c);
				}
			};
		} else {
			return function(r, c) {
				r.push(c);
			};
		}
	}();

	for (var i = 0, n = as.length; i < n; i++) {
		var c = as.charAt(i);

		switch (c) {
			case '\\':
				if (i == n - 1) {
					return window.errorMessage("Parsing Error!");
				}

				// エスケープ文字(\)の次文字とする．
				pushChar(r, as.charAt(++i));
				break;
			case '-':
				if (i == 0 || i == n - 1) {
					return window.errorMessage("Parsing Error!");
				}

				// ex.) A-Z
				var j0 = as.charCodeAt(i - 1); // ex.) Aの文字コード
				var j1; // ex.) Zの文字コード
				{
					j1 = as.charCodeAt(++i);

					// "A-\\-"などの場合，j1はエスケープ文字(\)の次文字とする．
					if (j1 == 0x5c) { // '\\'
						if (i == n - 1) {
							return window.errorMessage("Parsing Error!");
						}

						j1 = as.charCodeAt(++i);
					}
				}

				// Z-Aの場合など，逆になっているとき
				if (j0 > j1) {
					// NOTE: 'Z'は追加済
					for (var j = j0 - 1; j >= j1; j--)
						pushChar(r, String.fromCharCode(j));
				}
				else {
					// NOTE: 'A'は追加済
					for (var j = j0 + 1; j <= j1; j++)
						pushChar(r, String.fromCharCode(j));
				}
				break;
			default:
				pushChar(r, c);
				break;
		}
	}

	if (sorting) {
		r.sort();
	}

	return r.join("");
};



/**
 * HTML要素のidのパターンにマッチするHTMLElementを全て取得します．
 * 
 * @param idPattern	取得するHTML要素のIDの正規表現を指定します．
 * @param parentElement	当該HTML要素から下方へ再帰的に探索します．
 * 	指定しないとき，documentオブジェクトを当該HTML要素とします．
 * @return idPatternにマッチするHTML要素群です．
 * 	型はObjectで，lengthフィールドを持ちます．
 */
(myDocument = {}).getElementsById = function(idPattern, parentElement) {
	if (parentElement === void 0) {
		parentElement = window.document;
	}

	var rs;

	if (arguments[2] !== void 0) {
		rs = arguments[2];
	}

	// FirstCall
	else {
		// idPatternをコンパイル．
		if(idPattern.constructor === RegExp) {
			idPattern.compile(idPattern.source);
		}

		// idPatternをString型で指定されたとき，RegExpにして続行．
		else if (idPattern.constructor === String) {
			return this.getElementsById(new RegExp(idPattern), parentElement);
		}

		rs = new Object();
		rs.length = 0;
	}

	for (var cs = parentElement.childNodes, i = 0, n = cs.length; i < n; i++) {
		var c = cs[i];

		if (c.id !== void 0 && c.id.match(idPattern) != null) {
			rs[rs.length++] = c;
		}

		if (c.childNodes !== void 0 && c.childNodes.length > 0) {
			this.getElementsById(idPattern, c, rs);
		}
	}

	return rs;
};



/**
 * &→&amp;
 * <→&lt;
 * >→&gt;
 * "→&quot;
 */
var adjustText = function() {
	//var patternAmp = new RegExp();		patternAmp.compile("&", "g");
	//var patternLt = new RegExp();		patternLt.compile("<", "g");
	//var patternGt = new RegExp();		patternGt.compile(">", "g");
	//var patternSpace = new RegExp();	patternSpace.compile(" ", "g");
	//var patternQuot = new RegExp();		patternQuot.compile("\"", "g");

	return function(text) {
		var s = new Array();
		for (var i = 0, n = text.length; i < n; ++i) {
			var c = text.charAt(i);
			switch (c) {
				case '&':
					s.push("&amp;");
					break;
				case '<':
					s.push("&lt;");
					break;
				case '>':
					s.push("&gt;");
					break;
				case ' ':
					s.push("&nbsp;");
					break;
				case '\"':
					s.push("&quot;");
					break;
				default:
					s.push(c);
			}
		}
		return s.join("");
		//return text.replace(patternAmp, "&amp;")
		//	.replace(patternLt ,"&lt;")
		//	.replace(patternGt ,"&gt;")
		//	.replace(patternSpace ,"&nbsp;")
		//	.replace(patternQuot ,"&quot;");
	};
}();



/**
 * ランダムな文字列を生成します．
 * 
 * @param codeTable	出力に含む文字を，文字列で指定します．
 * 	ex.) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 * @param length	生成する文字列の長さを指定します．
 * @param prng	擬似乱数生成器(Pseud Random Number Generator)を指定します．
 * 	prngの出力値の範囲は，0以上1未満です．省略可能です．
 * @return	ランダムな文字列です．
 * 	含まれる文字は，codeTableに含まれる文字，文字列長さはlengthです．
 */
var generateRandomString = function(codeTable, length, prng)
{
	if (prng === void 0) {
		prng = Math.random;
	}

	var r = "";
	for (var i = 0, l = codeTable.length; i < length; ++i) {
		r += codeTable.charAt(l * prng() | 0);
	}
	return r;
};




/**
 * 0-9A-Za-zを使用し，パスワードを生成します．
 * 
 * パスワードは次の規則(AND)を満たします．
 * ・0-9の文字について，少なくとも1文字以上含む．
 * ・A-Zの文字について，少なくとも1文字以上含む．
 * ・a-zの文字について，少なくとも1文字以上含む．
 * ※上記より，パスワード文字列の長さは3以上である必要がある．
 * 
 * @param length	生成するパスワードの文字数を<em>3以上</em>で指定します．
 * @param prng	擬似乱数生成器(Pseud Random Number Generator)を指定します．
 * 	prngの出力値の範囲は，0以上1未満です．省略可能です．
 * @param cache	内部処理高速化のためのワーク領域を指定します．省略可能です．
 * @return	ランダムな文字列．
 */
var generateSafetyPassword = function()
{
	var N_TABLE = "0123456789".split("");
	var U_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
	var L_TABLE = "abcdefghijklmnopqrstuvwxyz".split("");
	var A_TABLE = [].concat(N_TABLE, U_TABLE, L_TABLE);

	return function(length, prng, cache) {
	if (length < 3) {
		return window.errorMessage("IllegalArgumentsException: "
			+ "length >= " + 3);
	}

	if (prng === void 0) {
		prng = Math.random;
	}

	if (cache === void 0) {
		cache = {};
	}

	var a = cache[length];

	if (a === void 0) {
		a = cache[length] = [];
		for (var i = 0; i < length; ++i) {
			a[i] = {index : i, table : A_TABLE};
		}
	}

	{
		var i = 0 + (length - 0) * prng() | 0;
		var v = a[0].index;
		a[0].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[0].table = N_TABLE;
	}
	{
		var i = 1 + (length - 1) * prng() | 0;
		var v = a[1].index;
		a[1].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[1].table = U_TABLE;
	}
	{
		var i = 2 + (length - 2) * prng() | 0;
		var v = a[2].index;
		a[2].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[2].table = L_TABLE;
	}

	var pws = new Array(length);

	for (var i = 0, s = null; i < length; ++i) {
		pws[(s = a[i]).index] = s.table[s.table.length * prng() | 0];
	}

	return pws.join("");
};}();



/**
 * 0-9A-Za-z!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~を使用し，パスワードを生成します．
 * 
 * パスワードは次の規則(AND)を満たす．
 * ・0-9の文字について，少なくとも1文字以上含む．
 * ・A-Zの文字について，少なくとも1文字以上含む．
 * ・a-zの文字について，少なくとも1文字以上含む．
 * ・(印刷可能な)記号文字について，少なくとも1文字以上含む．
 * ※上記より，パスワード文字列の長さは4以上である必要がある．
 * 
 * @param length	生成するパスワードの文字数を<em>4以上</em>で指定します．
 * @param prng	擬似乱数生成器(Pseud Random Number Generator)指定します．
 * 	prngの出力値の範囲は，0以上1未満です．省略可能です．
 * @param cache	内部処理高速化のためのワーク領域を指定します．省略可能です．
 * @return	ランダムな文字列．
 */
var generateStrongPassword = function()
{
	var N_TABLE = "0123456789".split("");
	var U_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
	var L_TABLE = "abcdefghijklmnopqrstuvwxyz".split("");
	var S_TABLE = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".split("");
	var A_TABLE = [].concat(N_TABLE, U_TABLE, L_TABLE, S_TABLE);

	return function(length, prng, cache) {
	if (length < 4) {
		return window.errorMessage("IllegalArgumentsException: "
			+ "length >= " + 4);
	}

	if (prng === void 0) {
		prng = Math.random;
	}

	if (cache === void 0) {
		cache = {};
	}

	var a = cache[length];

	if (a === void 0) {
		a = cache[length] = [];
		for (var i = 0; i < length; ++i) {
			a[i] = {index : i, table : A_TABLE};
		}
	}

	{
		var i = 0 + (length - 0) * prng() | 0;
		var v = a[0].index;
		a[0].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[0].table = N_TABLE;
	}
	{
		var i = 1 + (length - 1) * prng() | 0;
		var v = a[1].index;
		a[1].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[1].table = U_TABLE;
	}
	{
		var i = 2 + (length - 2) * prng() | 0;
		var v = a[2].index;
		a[2].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[2].table = L_TABLE;
	}
	{
		var i = 3 + (length - 3) * prng() | 0;
		var v = a[3].index;
		a[3].index = a[i].index;
		a[i].index = v;
		a[i].table = A_TABLE;
		a[3].table = S_TABLE;
	}

	var pws = new Array(length);

	for (var i = 0, s = null; i < length; ++i) {
		pws[(s = a[i]).index] = s.table[s.table.length * prng() | 0];
	}

	return pws.join("");
};}();




