      1 ﻿
      2 /**
      3  * @name	CeL code reorganize function
      4  * @fileoverview
      5  * 本檔案包含了程式碼重整重構用的 functions。
      6  * @since
      7  */
      8
      9 /*
     10 parse code
     11 use ISO-14977: Extended Backus–Naur Form (EBNF)
     12 http://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95%E5%B7%B4%E7%A7%91%E6%96%AF%E8%8C%83%E5%BC%8F
     13
     14 http://blog.zhaojie.me/2010/11/narcissus-javascript-parser.html
     15 Narcissus是一個JavaScript引擎，完全使用JavaScript編寫，不過利用了SpiderMonkey的一些擴展，因此無法直接在僅僅實現了ECMAScript 3的引擎上執行（例如各瀏覽器）。
     16 http://en.wikipedia.org/wiki/Narcissus_%28JavaScript_engine%29
     17 http://hax.iteye.com/blog/181358
     18
     19 */
     20
     21 if (typeof CeL === 'function')
     22 CeL.setup_module('data.code.reorganize',
     23 function(library_namespace, load_arguments) {
     24
     25
     26 //	nothing required
     27
     28
     29 var
     30 /**
     31  * null module constructor
     32  * @class 程式碼重整重構相關之 functions。
     33  * @constructor
     34  */
     35 CeL.data.code.reorganize
     36 = function () {
     37 	//	null module constructor
     38 };
     39
     40 /**
     41  * for JSDT: 有 prototype 才會將之當作 Class
     42  */
     43 CeL.data.code.reorganize
     44 .prototype = {};
     45
     46
     47
     48
     49 //class public interface	---------------------------
     50
     51 CeL.data.code.reorganize
     52 .
     53 /**
     54  * 取得[script_filename].wsf中不包括自己（[script_filename].js），其餘所有 .js 的code。
     55  * @param {String} script_filename	script filename
     56  * @return
     57  * @requires ScriptName,simpleRead
     58  * @deprecated	若想在低版本中利用eval(get_all_functions(ScriptName))來補足，有時會出現奇怪的現象，還是別用好了。
     59  * @memberOf CeL.data.code.reorganize
     60  */
     61 get_all_functions = function (script_filename) {
     62 	if (!script_filename)
     63 		script_filename = ScriptName;
     64 	var t = '', i, a = simpleRead(script_filename + '.wsf'), l = a ? a
     65 			.match(/[^\\\/:*?"<>|'\r\n]+\.js/gi) : [script_filename + '.js'];
     66
     67 	for (i in l)
     68 		if (l[i] != script_filename + '.js' && (a = simpleRead(l[i])))
     69 			t += a;
     70 	return t;
     71 };
     72
     73
     74 var JS_reserved_word = {
     75 		Keyword : 'break,do,instanceof,typeof,case,else,new,var,catch,finally,return,void,continue,for,switch,while,debugger,function,this,with,default,if,throw,delete,in,try',
     76 		FutureReservedWord : 'class,enum,extends,super,const,export,import',
     77 		NullLiteral : 'null',
     78 		BooleanLiteral : 'true,false'
     79 };
     80
     81
     82 //var OK = add_code('alert,simpleWrite', ['alert', 'NewLine', 'get_all_functions']);if (typeof OK == 'string') simpleWrite('try.js', OK), alert('done'); else alert('OK:' + OK);
     83 /*
     84 {
     85 	var ss = [23, 23.456, undefined, Attribute, null, Array, '567', 'abc'], l = 80, repF = 'tmp.txt', sa = ss, st = add_code('', ['ss']), t;
     86 	ss = '(reseted)'; try { eval(st); } catch (e) { } t = (sa === ss) + ': ' + typeof sa + '→' + typeof ss + '\n';
     87 	simpleWrite(repF, t + sa + '\n→\n' + ss + '\n\n◎eval:\n' + st);
     88 	alert(t + (sa = '' + sa, sa.length < l ? sa : sa.slice(0, l / 2) + '\n..' + sa.slice(sa.length - l / 2)) + '\n→\n' + (ss = '' + ss, ss.length < l ? ss : ss.slice(0, l / 2) + '\n..' + ss.slice(ss.length - l / 2)) + '\n\n' + (ss = '' + st, ss.length < l ? ss : ss.slice(0, 200) + '\n..\n' + ss.slice(ss.length - 200)));
     89 }
     90 */
     91
     92 /*
     93 加入識別格式之方法：
     94
     95 //	from function.js	-------------------------------------------------------------------
     96
     97 //e.g.,
     98 //	[function.js](f1,f2,'string'	//	'string'或"string"中包含的需要是完整的敘述句
     99 //	number var,string var,object var,date var,undefined  var)
    100
    101 //e.g.,
    102 //	[function.js](OS,NewLine,dirSp,dirSpR,'var ScriptName=getScriptName();',ForReading,ForWriting,ForAppending,TristateUseDefault,TristateTrue,TristateFalse,WshShell,fso,args,'initWScriptObj();',initWScriptObj,setTool,JSalert,Str2Date,Date2Str,decplaces,dQuote,set_obj_value,getScriptFullName,getScriptName,'setTool();',WinEnvironment,SpecialFolder,Network,NetDrive,NetPrinter,getEnvironment,'getEnvironment();',dateUTCdiff,gDate)
    103 //e.g.,
    104 //	[function.js]("var NewLine='\n',OS='unix',dirSp=dirSpR='/';",dQuote,setTool,product,decplaces,countS,getText,turnUnicode,trimStr_,trimStr,StrToDate,DateToStr,reducePath,getPathOnly,getFN,getFP,dBasePath,trigger,setTopP,setAstatusOS,setAstatus,setAstatusOver,setAstatusOut,doAlertResize,doAlertInit,doAlert,doAlertAccess,doAlertScroll,setCookie,getCookie,scrollTo,disableKM,setCookieS,*disabledKM=0;,scrollToXY,scrollToInterval,scrollToOK,doAlertDivName,doAlertOldScrollLocation,parse_Function,dealPopup,sPopP,sPopF,sPopInit,sPopInit,sPop,setTextT,setText)
    105
    106 ..(inclide code)
    107 //	[function.js]End	-------------------------------------------------------------------
    108 //	↑from function.js	-------------------------------------------------------------------
    109
    110
    111 TODO:
    112 .htm 加入 .replace(/\//g,'\\/')
    113 */
    114 CeL.data.code.reorganize
    115 .
    116 /**
    117  * 將各 function 加入檔案中，可做成 HTML 亦可用之格式。
    118  * @example
    119  * add_code('複製 -backup.js');
    120  * @param file_name	file name (list)
    121  * @param Vlist	多加添的 function/various list
    122  * @param {String} start_string	start string
    123  * @param {String} end_string	ending string
    124  * @returns
    125  * @request	NewLine,is_file,simpleRead,autodetectEncode,generate_code,JSalert,setTool,*setTool();
    126  * @memberOf	CeL.data.code.reorganize
    127  */
    128 add_code = function (file_name, Vlist, start_string, end_string) {
    129 	if (!start_string)
    130 		start_string = '//	[' + library_namespace.Class + ']';
    131 	if (!end_string)
    132 		end_string = start_string + 'End';
    133 	//alert(is_file(FN)+'\n'+start_string+'\n'+end_string);
    134
    135 	if (typeof file_name == 'string')
    136 		file_name = [ is_file(file_name) ? file_name : start_string
    137 				+ (file_name ? '(' + file_name + ')' : '') + NewLine
    138 				+ end_string + NewLine ];
    139 	if (typeof Vlist == 'string')
    140 		Vlist = [ Vlist ];
    141 	else if (typeof Vlist != 'object')
    142 		Vlist = [];
    143
    144 	var i, j, F, a, A, start, end, code_head, b, c, d, f, m, OK = 0, new_line,
    145 	// 「」『』【】〈〉《》〔〕｛｝︵︶︹︺︷︸︻︼︿﹀︽︾﹁﹂﹃﹄（）「」『』‘’“”〝〞‵′
    146 	s = '()[]{}<>\u300c\u300d\u300e\u300f\u3010\u3011\u3008\u3009\u300a\u300b\u3014\u3015\uff5b\uff5d\ufe35\ufe36\ufe39\ufe3a\ufe37\ufe38\ufe3b\ufe3c\ufe3f\ufe40\ufe3d\ufe3e\ufe41\ufe42\ufe43\ufe44\uff08\uff09\u300c\u300d\u300e\u300f\u2018\u2019\u201c\u201d\u301d\u301e\u2035\u2032',
    147 	end_char, req, direct_input = '*', tmpExt = '.tmp', encoding, oriC;
    148
    149
    150 	for (i in file_name) try {
    151 		if (a = oriC = is_file(file_name[i]) ? simpleRead(file_name[i],
    152 				encoding = autodetectEncode(file_name[i])) : file_name[i], !a)
    153 			continue;
    154 		A = '', dones = [], doneS = 0;
    155 		//sl(a.slice(0,200));
    156
    157 /*	判斷 new_line 這段，將三種資料作比較就能知道為何這麼搞。
    158
    159 ~\r:
    160
    161 \r	123
    162 \n	1
    163 \r\n	2
    164 \n-\r	-120
    165
    166
    167 ~\n:
    168
    169 \r	1
    170 \n	123
    171 \r\n	2
    172 \n-\r	120
    173
    174
    175 ~\r\n:
    176
    177 \r	123
    178 \n	123
    179 \r\n	123
    180 \n-\r	-2~2
    181 */
    182 		new_line = a.replace(/[^\n]+/g, '').length;
    183 		b = a.replace(/[^\r]+/g, '').length;
    184 		if (new_line != b && new_line && b) {
    185 			alert("There're some encoding problems in the file:\n"
    186 					+ file_name[i] + '\n\\n: ' + new_line + '\n\\r: ' + b);
    187 			new_line = Math.max(new_line, b) > 10 * Math.abs(new_line - b) ? '\r\n'
    188 					: new_line > b ? '\n' : '\r';
    189 		} else
    190 			new_line = new_line ? b ? '\r\n' : '\n' : '\r';
    191
    192 		//sl(a.indexOf(start_string)+'\n'+start_string+'\n'+a.slice(0,200));
    193 		// TODO: a=a.replace(/(startReg)(.*?)(endReg)/g,function($0,$1,$2,$3){.. return $1+~+$3;});
    194 		while ((start = a.indexOf(start_string)) != -1
    195 				// &&(end=a.indexOf(end_string,start+start_string.length))!=-1
    196 				) {
    197 			//	initial reset
    198 			code_head = codeText = end_char = '';
    199 			req = [];
    200 			j = 0;
    201 			//	判斷 end index
    202 			if ((end = a.indexOf(end_string, start + start_string.length)) == -1) {
    203 				alert('add_code: There is start mark without end mark!\nend_string:\n'
    204 						+ end_string);
    205 				//	未找到格式則 skip
    206 				break;
    207 			}
    208 			//	b=inner text
    209 			b = a.slice(start + start_string.length, end);
    210 			b = b.split(new_line); //b=b.split(new_line=b.indexOf('\r\n')!=-1?'\r\n':b.indexOf('\n')!=-1?'\n':'\r');	//	test檔案型式：DOS or UNIX.最後一位元已被split掉
    211 			if (c = b[0].match(/^\s*([^\w])/)) {
    212 				code_head += b[0].slice(0, RegExp.lastIndex);
    213 				b[0] = b[0].slice(RegExp.lastIndex);
    214 				if (s.indexOf(c = c[1]) % 2 == 0)
    215 					end_char = s.charAt(s.indexOf(c) + 1);
    216 				else
    217 					end_char = c;
    218 			}
    219 			//new_line=b[0].slice(-1)=='\r'?'\r\n':'\n';	//	移到前面：因為需要以new_line作split	test檔案型式：DOS or UNIX.最後一位元已被split掉
    220 			//alert('end_char='+end_char+',j='+j+',d='+d+'\n'+b[0]+'\nNewLine:'+(new_line=='\n'?'\\n':new_line=='\r\n'?'\\r\\n':'\\r')+'\ncode_head:\n'+code_head);
    221
    222 			do {
    223 				// 不需要d>=b[j].length
    224 				//if(d==b[j].length)continue;
    225 				if (!j)
    226 					d = 0;
    227 				else if (b[j].slice(0, 2) != '//')
    228 					continue;
    229 				else
    230 					d = 2;
    231
    232 				for (;;) {
    233 					//alert('search '+b[j].slice(d));
    234 					if ((c = b[j].slice(d).match(/^[,\s]*([\'\"])/))
    235 							&& (f = d + RegExp.lastIndex) <= b[j].length &&
    236 							// (c=c[1], f<b[j].length)
    237 							(c = c[1]) && f < b[j].length) { // .search(
    238 						// alert(b[j].charAt(f)+'\n'+c+'\n^(.*[^\\\\])['+c+']');
    239 						if (b[j].charAt(f) == c) {
    240 							// '',""等
    241 							alert('add_code: 包含[' + c + c + ']:\n'
    242 									+ b[j].slice(f));
    243 							continue;
    244 						}
    245 						if (c = b[j].slice(f).match(
    246 								new RegExp('^(.+?[^\\\\])[' + c + ']'))) {
    247 							d = f + RegExp.lastIndex;
    248 							req.push(direct_input/* +b[j].charAt(f-1) 改進後不需要了 */
    249 									+ c[1]);
    250 							continue;
    251 						}
    252 						alert('add_code: Can not find end quota:\n' + b[j].slice(f));
    253 					}
    254 					//alert(d+','+b[j].length+'\nsearch to '+b[j].slice(d));
    255
    256 					//	出現奇怪現象請加"()"
    257 					//if((c=b[j].slice(d).match(/([^,\s]+)([,\s]*)/))&& ( (d+=RegExp.lastIndex)==b[j].length || /[,\n]/.test(c[2])&&d<b[j].length ) ){	//	不需要\s\r
    258 					if ((c = b[j].slice(d).match(/([^,\s]+)[,\s]*/)) && (d += RegExp.lastIndex) <= b[j].length) {	//	不需要\s\r
    259 						//if(!/[,\n]/.test(c[2])&&d<b[j].length)break;
    260 						//alert(RegExp.index+','+d+','+b[j].length+','+end_char+'\n['+c[1]+']\n['+c[2]+']\n'+b[j].slice(d));
    261 						if (!end_char || (m = c[1].indexOf(end_char)) == -1) req.push(c[1]);
    262 						else { if (m) req.push(c[1].slice(0, m)); end_char = ''; break; }
    263 					} else break;
    264 				}
    265 				code_head += b[j] + new_line;
    266 				//alert('output start_string:\n'+start_string+'\ncode_head:\n'+code_head);
    267 			} while (end_char && ++j < b.length);
    268 			//for(j=0,b=[];j<req.length;j++)b.push(req[j]);	//	不能用b=req：object是用參考的，這樣會改到req本身！
    269 			//for(j=0;j<Vlist.length;j++)b.push(Vlist[j]);	//	加入附加的變數
    270
    271 			b = _.generate_code(req.concat(Vlist), new_line, direct_input);
    272 			codeText = code_head + (arguments.callee.report ? '/*	add_code @ ' + gDate('', 1)	//	report
    273 					+ (req.length ? new_line + '	request variables [' + req.length + ']:	' + req : '')
    274 					+ (Vlist.length ? new_line + '	addition lists [' + Vlist.length + ']:	' + Vlist : '')
    275 					+ (req.length && Vlist.length && b[2].length < req.length + Vlist.length ? new_line + '	Total request [' + b[2].length + ']:	' + b[2] : '')
    276 					+ (b[4].length ? new_line + '	really done [' + b[4].length + ']:	' + b[4] : '')
    277 					+ (b[5].length ? new_line + '	cannot found [' + b[5].length + ']:	' + b[5] : '')
    278 					+ (b[6].length ? new_line + '	all listed [' + b[6].length + ']:	' + b[6] : '')
    279 					//+(b[3].length?new_line+'	included function ['+b[3].length+']:	'+b[3]:'')
    280 					+ new_line + '	*/' : '') + new_line + _.reduce_code(b[0]).replace(/([};])function(\s)/g, '$1' + new_line + 'function$2').replace(/}var(\s)/g, '}' + new_line + 'var$1')/*.replace(/([;}])([a-z\._\d]+=)/ig,'$1'+new_line+'$2')*/ + new_line + b[1] + new_line;
    281 			//alert(start+','+end+'\n'+a.length+','+end+','+end_string.length+','+(end+end_string.length)+'\n------------\n'+codeText);//+a.slice(end+end_string.length)
    282 			A += a.slice(0, start + start_string.length)
    283 					+ codeText
    284 					+ a.substr(end, end_string.length);
    285 			a = a.substr(end + end_string.length);
    286 		}
    287
    288 		if (file_name.length == 1 && !is_file(file_name[i]))
    289 			return A;
    290
    291 		if (A && oriC != A + a)	//	有變化才寫入
    292 			if (!simpleWrite(file_name[i] + tmpExt, A + a, encoding))
    293 				try {
    294 					fso.DeleteFile(file_name[i]);
    295 					fso.MoveFile(file_name[i] + tmpExt, file_name[i]);
    296 					OK++;
    297 				} catch (e) {
    298 					// popErr(e);
    299 				}
    300 			else
    301 				try {
    302 					fso.DeleteFile(file_name[i] + tmpExt);
    303 				} catch (e) {
    304 					// popErr(simpleFileErr);popErr(e);
    305 				}
    306 		//else{alert('add_code error:\n'+e.message);continue;}
    307 	} catch (e) {
    308 		//popErr(e);
    309 		throw e;
    310 	}
    311
    312 	//	A:成功的最後一個檔之內容
    313 	return file_name.length == 1 && OK == 1 ? A : OK;
    314 };
    315
    316 /**
    317  * 是否加入報告
    318  * @type	Boolean
    319  */
    320 _.add_code.report = false;
    321
    322
    323 CeL.data.code.reorganize
    324 .
    325 /**
    326  * add libary use
    327  * @param	{String} code	script code
    328  * @returns
    329  * @memberOf	CeL.data.code.reorganize
    330  */
    331 add_use = function (code) {
    332 	//	TODO: 去除 comments 中的 .use()
    333 	var _s = _.add_use, i, m = code.match(_s.pattern);
    334
    335 	library_namespace.err('TODO');
    336 };
    337 _.add_use.pattern = new RegExp(library_namespace.Class
    338 		+ '\\s*.\\s*use\\((.+)\\)');
    339
    340 /*
    341 try.wsf
    342 <package><job id="try"><script type="text/javascript" language="JScript" src="function.js"></script><script type="text/javascript" language="JScript" src="try.js"></script></job></package>
    343 try.js
    344 destory_script('WshShell=WScript.CreateObject("WScript.Shell");'+NewLine+NewLine+alert+NewLine+NewLine+'alert("資料讀取錯誤！\\n請檢查設定是否有錯！");');
    345 */
    346 CeL.data.code.reorganize
    347 .
    348 /**
    349  * script 終結者…
    350  * @param	{String} code	script code
    351  * @param	addFN
    352  * @returns	error no.
    353  * @memberOf	CeL.data.code.reorganize
    354  */
    355 destory_script = function (code, addFN) {
    356 	try {
    357 		//	input indepent code, additional files
    358 		var SN = getScriptName(), F, a, listJs, i, len, self = SN + '.js';
    359 		if (!code)
    360 			code = ''; //SN='try';
    361 		a = simpleRead(SN + '.wsf');
    362 		if (!a) a = '';
    363 		//	一網打盡
    364 		listJs = a.match(/[^\\\/:*?"<>|'\r\n]+\.(js|vbs|hta|s?html?|txt|wsf|pac)/gi);
    365 		//,listWsf=(SN+'.wsf\n'+a).match(/[^\\\/:*?"<>|'\r\n]+\.wsf/gi);
    366
    367 		for (i = 0, F = {}; i < listJs.length; i++)
    368 			F[listJs[i]] = 1;
    369 		if (typeof addFN == 'object')
    370 			for (i in addFN)
    371 				F[addFN[i]] = 1;
    372 		else if (addFN)
    373 			F[addFN] = 1;
    374
    375 		listJs = [];
    376 		//	避免重複
    377 		for (i in F)
    378 			listJs[listJs.length] = i;
    379 		//alert(listJs.join('\n'));
    380
    381 		//done all .js @ .wsf & files @ additional list without self
    382 		for (i = 0; i < listJs.length; i++)
    383 			//	除了self外殺無赦
    384 			if (listJs[i] != self) try {
    385 				if (!listJs[i].match(/\.js$/i) && listJs[i] != SN + '.wsf') { try { fso.DeleteFile(listJs[i], true); } catch (e) { } continue; } //	非.js就讓他死
    386 				if (changeAttributes(F = fso.GetFile(listJs[i]), '-ReadOnly')) throw 0; //	取消唯讀
    387 				a = add_null_code(F.size); //a=listJs[i].match(/\.js$/i)?add_null_code(F.size):'';	先確認檔案存在，再幹掉他
    388 				//alert('done '+listJs[i]+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..'));
    389 				simpleWrite(listJs[i], a);
    390 			} catch (e) {
    391 				//popErr(e);
    392 			}
    393
    394 		//done .wsf
    395 		try {
    396 			if (changeAttributes(F = fso.GetFile(SN + '.wsf'), '-ReadOnly'))
    397 				throw 0;
    398 			a = '<package><job id="' + SN + '"><script type="text/javascript" src="' + SN + '.js"><\/script><\/job><\/package>';
    399 			//alert('done '+SN+'.wsf'+'('+F.size+')\n'+a);
    400 			//a='<package><job id="'+SN+'"><script type="text/javascript" src="function.js"><\/script><script type="text/javascript" src="'+SN+'.js"><\/script><\/job><\/package>';
    401 			simpleWrite(SN + '.wsf', a);
    402 		} catch (e) {
    403 			//popErr(e);
    404 		}
    405
    406 		//	done self
    407 		if (listJs.length) try {
    408 			if (changeAttributes(F = fso.GetFile(self), '-ReadOnly') < 0)
    409 				throw 0;
    410 			a = (F.size - code.length) / 2;
    411 			a = add_null_code(a) + code + add_null_code(a);
    412 			if (F.Attributes % 2)
    413 				//	取消唯讀
    414 				F.Attributes--;
    415 			//alert('done '+self+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..'));
    416 			//a='setTool(),destory_script();';
    417 			simpleWrite(self, a);
    418 		} catch (e) {
    419 			//popErr(e);
    420 		}
    421
    422 		//run self & WScript.Quit()
    423 		//return WshShell.Run('"'+getScriptFullName()+'"');
    424 		return 0;
    425 	} catch (e) {
    426 		return 1;
    427 	}
    428 };
    429
    430 /*	for version<5.1:因為不能用.wsf，所以需要合併成一個檔。
    431 請將以下函數copy至.js主檔後做適當之變更
    432 getScriptName(),merge_script(FN),preCheck(ver)
    433 */
    434 //	將script所需之檔案合併
    435 //	因為常由preCheck()呼叫，所以所有功能亦需內含。
    436 function merge_script(FN) {
    437 	var i, n, t, SN = getScriptName(), NewLine, fso, ForReading, ForWriting, ForAppending;
    438 	if (!NewLine)
    439 		NewLine = '\r\n';
    440 	if (!fso)
    441 		fso = WScript.CreateObject("Scripting.FileSystemObject");
    442 	if (!ForReading)
    443 		ForReading = 1, ForWriting = 2, ForAppending = 8;
    444 	try {
    445
    446 		//	from .wsf
    447 		/*var F=fso.OpenTextFile(SN+'.wsf',ForReading)
    448 		//,R=new RegExp('src\s*=\s*["\']?(.+\.js)["\']?\s*','gi')
    449 		,a=F.ReadAll();F.Close();*/
    450 		a = simpleRead(SN + '.wsf');
    451 		S = fso.OpenTextFile(FN, ForWriting, true/* create */);
    452
    453 		try {
    454 			//t=a.match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/gi);
    455 			//	5.1版以下果然還是不能成功實行，因為改變regexp不能達到目的：沒能找到t。所以在下面第一次test失敗後即放棄；改用.ini設定。
    456 			var r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "ig");
    457 			t = a.match(r);
    458 			S.WriteLine('//	merge_script: from ' + SN + '.wsf');
    459 			S.WriteLine("function getResource(id){");
    460 			if (!t || !t.length) S.WriteLine(" return ''");
    461 			else for (i = 0; i < t.length; i++) {
    462 				//alert(i+':'+t[i]);
    463 				//n=t[i].match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/i);
    464 				r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "i");
    465 				n = t[i].match(r);
    466 				S.WriteLine(" " + (i ? ":" : "return ") + "id=="
    467 						+ n[1] + "?'"
    468 						+ n[2].replace(/\r?\n/g, '\\n') + "'");
    469 			}
    470 			S.WriteLine(" :'';" + NewLine + "}" + NewLine);
    471 		} catch (e) {
    472 		}
    473
    474 		//	from .js
    475 		t = a.match(/src\s*=\s*["']?(.+\.js)["']?\s*/gi);
    476 		for (i = 0; i < t.length; i++) {
    477 			//alert(i+':'+t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1]);
    478 			//try{F=fso.OpenTextFile(n=t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1],ForReading);}
    479 			//catch(e){continue;}
    480 			//S.WriteLine('//	merge_script: from script	'+n);S.WriteBlankLines(1);S.WriteLine(F.ReadAll());
    481 			//S.WriteLine('//	merge_script: from script	'+n+NewLine+NewLine+F.ReadAll());
    482 			//F.Close();
    483 			S.WriteLine('//	merge_script: from script	'
    484 					+ (n = t[i]
    485 					.match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1])
    486 					+ NewLine + NewLine + simpleRead(n));
    487 		}
    488 		S.Close();
    489 	} catch (e) {
    490 		return 1;
    491 	}
    492 	return 0;
    493 };
    494
    495
    496
    497
    498
    499 //var fa=function(a,s){return '"'+a+k+"'";},fb=function kk(a,t){return a;},fc=new Function('return b+b;'),Locale2=fa,Locale3=fb,Locale4=fc,r=generate_code(['fa','fb','fc','Locale2','Locale3','Locale4','kk']);alert(r.join('\n★'));try{eval(r[0]);alert(fa);}catch(e){alert('error!');}
    500 /*	use for JSON (JavaScript Object Notation)
    501 directly input:	[directInput]string
    502 輸出string1（可reduce_code）,輸出string2（主要為object definition，不需reduce_code，以.replace(/\r\n/g,'')即可reduce）,總共要求的變數（去掉重複）,包含的函數（可能因參考而有添加）,包含的變數（可能因參考而有添加）,未包含的變數
    503
    504 未來：對Array與Object能確實設定之	尚未對應：Object遞迴/special Object(WScript,Excel.Application,內建Object等)/special function(內建函數如Math.floor與其他如WScript.CreateObject等)
    505 JScript中對應資料型態，應考慮到內建(intrinsic 或 built-in)物件(Boolean/Date/Function/Number/Array/Object(需注意遞迴:Object之值可為Object))/Time/Error/RegExp/Regular Expression/String/Math)/string/integer/Byte/number(float/\d[de]+-\d/Number.MAX_VALUE/Number.MIN_VALUE)/special number(NaN/正無限值:Number.POSITIVE_INFINITY/負無限值:Number.NEGATIVE_INFINITY/正零/負零)/date/Boolean/undefined(尚未設定值)/undcleared(尚未宣告)/Null/normal Array/normal Object/special Object(WScript,Automation物件如Excel.Application,內建Object等)/function(實體/參考/anonymous)/special function(內建函數如isNaN,Math之屬性&方法Math[.{property|method}]與其他如WScript.CreateObject等)/unknown(others)
    506
    507 **	需同步更改 json()
    508
    509
    510 TODO:
    511 Object.toSource()
    512 Array.toSource()
    513 json	http://www.json.org/json.js
    514 UglifyJS	https://github.com/mishoo/UglifyJS
    515
    516
    517 XML Object
    518
    519 bug:
    520 函數定義 .toString() 時無法使用。
    521
    522
    523 使用 \uXXXX 使.js跨語系
    524 含中文行
    525 →
    526 //turnBy	含中文行
    527 \x..
    528 考慮註解&執行時語系
    529
    530 to top BEFORE ANY FUNCTIONS:
    531 generate_code.dLK='dependencyList';	//	dependency List Key
    532 */
    533 CeL.data.code.reorganize
    534 .
    535 /**
    536  * 利用[*現有的環境*]及變數設定生成code，因此並不能完全重現所有設定，也無法判別函數間的相依關係。
    537  * @param {Array} Vlist	變數 list
    538  * @param {String} new_line	new line
    539  * @param {String} direct_input	直接輸入用辨識碼
    540  * @requires	set_obj_value,dQuote
    541  * @memberOf	CeL.data.code.reorganize
    542  */
    543 generate_code = function (Vlist, new_line, direct_input) {
    544 	//	vars:處理過的variables（不論是合法或非合法）,c:陳述是否已完結
    545 	var _s = _.generate_code, codeText = '', afterCode = '', vars = [], vari = [], func = [], done = [], undone = [], t, i = 0, c = 0, val, vName, vType;
    546 	if (!new_line)
    547 		new_line = '\n';
    548 	if (!direct_input)
    549 		direct_input = _s.ddI;
    550 	if (typeof Vlist === 'string')
    551 		Vlist = Vlist.split(_s.dsp);
    552
    553 	for (; i < Vlist.length; i++) if (!((vName = '' + Vlist[i]) in vars)) {
    554 		//	c(continue)=1:var未截止,vName:要加添的變數內容
    555 		vars[vName] = vari.length, vari.push(vName); //	避免重複
    556
    557 		//	不加入的
    558 		if (vName.charAt(0) == '-') {
    559 			vars[vName.slice(1)] = -1;
    560 			continue;
    561 		}
    562
    563 		//	直接輸出
    564 		if (vName.slice(0, direct_input.length) == direct_input) {
    565 			if (c)
    566 				codeText += ';' + new_line, c = 0;
    567 			codeText += val = vName.substr(direct_input.length);
    568 			done.push('(directly input)' + val);
    569 			continue;
    570 		}
    571 		try {
    572 			// void
    573 			eval('vType=typeof(val=' + vName + ');');
    574 		} catch (e) {
    575 			//	b:type,c:已起始[var ];catch b:語法錯誤等,m:未定義
    576 			//	e.constructor
    577 			undone.push((vType ? '(' + vType + ')' : '') + vName
    578 					+ '(error ' + (e.number & 0xFFFF) + ':'
    579 					+ e.description + ')');
    580 			continue;
    581 		}
    582
    583
    584 		//	or use switch-case
    585 		if (vType === 'function') {
    586 			//	加入function object成員，.prototype可用with()。加入函數相依性(dependency)
    587 			try {
    588 				eval("var j,k;for(j in "
    589 						+ vName
    590 						+ ")if(j=='"
    591 						+ _s.dLK
    592 						+ "'&&(k=typeof "
    593 						+ vName
    594 						+ "."
    595 						+ _s.dLK
    596 						+ ",k=='string'||"
    597 						+ vName
    598 						+ "."
    599 						+ _s.dLK
    600 						+ " instanceof Array)){j="
    601 						+ vName
    602 						+ "."
    603 						+ _s.dLK
    604 						+ ";if(k=='string')j=j.split(',');for(k in j)if(j[k])Vlist.push(j[k]);}else Vlist.push('"
    605 						+ vName + ".'+j);for(j in " + vName
    606 						+ ".prototype)Vlist.push('" + vName
    607 						+ ".prototype.'+j);");
    608 			} catch (e) {
    609 				undone.push('(' + vType + ')' + vName + '.[child]'
    610 						+ '(error ' + (e.number & 0xFFFF) + ':'
    611 						+ e.description + ')');
    612 			}
    613
    614 			val = ('' + val).replace(/[\r\n]/g, new_line); //	function 才會產生 \r\n 問題，所以先處理掉
    615 			if ((t = val.match(/^\s*function\s*\(/)) || val.match(/^\s*function\s+([\w_]*)([^(]*)\(/))	//	這種判別法不好！
    616 				if (t || (t = RegExp.$1) == 'anonymous') {
    617 					func.push(vName); vType = (typeof t == 'string' ? t : 'no named') + ' ' + vType;
    618 					if (t === 'anonymous') {
    619 						//	忠於原味（笑）
    620 						//	anonymous 是從new Function(文字列を使って)來的
    621 						var m = val.match(/\(([^)]*)\)\s*{/), l = RegExp.lastIndex, q = val.match(/[^}]*$/); q = RegExp.index;
    622 						if (!m) { undone.push('(anonymous function error:' + val + ')' + vName); continue; }
    623 						if (t = m[1].replace(/,/g, "','")) t = "'" + t + "',"; t = 'new Function(' + t + dQuote(_.reduce_code(val.slice(l, q - 1))) + ')';
    624 					} else t = val;
    625 				} else if (t == vName) {
    626 					//	関数(function): http://www.interq.or.jp/student/exeal/dss/ejs/1/2.html
    627 					if (c) codeText += ';' + new_line, c = 0; func.push(vName), codeText += val + new_line; continue;
    628 				} else if (val.indexOf('[native code]') != -1) { undone.push('(native code function error:' + val + ')' + vName); continue; } //	內建(intrinsic 或 built-in)函數：這種判別法不好！
    629 				else if (t in vars) done.push('(' + vType + ')' + vName), func.push(vName); //	已經登錄過了，所以就這麼下去..
    630 				else {
    631 					if (c)
    632 						codeText += ';' + new_line;
    633 					codeText += val + new_line;
    634 					vars[t] = vari.length;
    635 					done.push('(' + vType + ')' + t);
    636 					func.push(t, vName);
    637 					c = 0;
    638 				}
    639 			else {
    640 				// unknown error
    641 				undone.push('(function error:' + val + ')' + vName);
    642 				continue;
    643 			}
    644 		} else if (vType == 'number') {
    645 			//	http://msdn2.microsoft.com/zh-tw/library/y382995a(VS.80).aspx
    646 			var k = 0, m = 'MAX_VALUE,MIN_VALUE,NEGATIVE_INFINITY,POSITIVE_INFINITY,NaN'.split(',');
    647 			if (val === NaN || val === Infinity || val === -Infinity) t = '' + val;
    648 			else for (t = 0; k < m.length; k++) if (val === Number[m[k]]) { t = 'Number.' + m[k]; break; }
    649 			if (!t) {
    650 				//	http://msdn2.microsoft.com/zh-tw/library/shydc6ax(VS.80).aspx
    651 				for (k = 0, m = 'E,LN10,LN2,LOG10E,LOG2E,PI,SQRT1_2,SQRT2'.split(','); k < m.length; k++) if (val === Math[m[k]]) { t = 'Math.' + m[k]; break; }
    652 				if (!t) t = (t = Math.floor(val)) == val && ('' + t).length > (t = '0x' + val.toString(16)).length ? t : val;
    653 			}
    654 		} else if (vType == 'boolean' || val === null) t = val; //String(val)//val.toString()	//	typeof null is 'object'
    655 		else if (vType == 'string') t = dQuote(val);
    656 		else if (vType == 'object' && typeof val.getTime == 'function' || vType == 'date') t = 'new Date(' + ((val - new Date) > 999 ? val.getTime() : '') + ')'; //	date被當作object
    657 		//	http://msdn2.microsoft.com/en-us/library/dww52sbt.aspx
    658 		else if (vType == 'object' && /*val.constructor==Error  "[object Error]" */('' + val.constructor).indexOf('Error') != -1)
    659 			t = 'new Error' + (val.number || val.description ? '(' + (val.number || '') + (val.description ? (val.number ? ',' : '') + dQuote(val.description) : '') + ')' : '');
    660 		/*
    661 		else if(vName=='set_obj_value.F'){	//	明白宣示在這裡就插入依存函數：不如用 set_obj_value.F,'set_obj_value();'
    662 		if(!vars['set_obj_value']||!vars['dQuote'])Vlist=Vlist.slice(0,i).concat('set_obj_value','dQuote',Vlist.slice(i));
    663 		Vlist[i--]=directInput+'var set_obj_value.F;';continue;
    664 		}
    665 		*/
    666 		else if (vType == 'object' && (val.constructor == Object || val.constructor == Array)) {// instanceof
    667 			var k, T = '', T_ = '', T_2 = '', _i = 0, cmC = '\\u002c', eqC = '\\u003d', NL_ = "'" + new_line + "+'", maxLen = 300 - NL_.length; //	type;loop用,Text,間距,integer?
    668 			if (val.constructor == Object) {
    669 				t = '';
    670 				//	http://fillano.blog.ithome.com.tw/post/257/59403
    671 				//	** 一些內建的物件，他的屬性可能會是[[DontEnum]]，也就是不可列舉的，而自訂的物件在下一版的ECMA-262中，也可以這樣設定他的屬性。
    672 				for (k in val)
    673 					if (typeof val[k] == 'object' || typeof val[k] == 'function')
    674 						Vlist.push(vName + '.' + k); //	簡單的Object遞迴
    675 					else {
    676 						T_2 = k.replace(/,/g, cmC).replace(/=/g, eqC) + '=' + ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC) + ',';
    677 						if (T_.length + T_2.length > maxLen) T += T_ + NL_, T_ = T_2; else T_ += T_2;
    678 						if (!_i && parseInt(val[k]) == val[k]) _i = 1; else if (_i < 2 && parseFloat(val[k]) == val[k] && parseInt(val[k]) != val[k]) _i = 2;
    679 					}
    680 				T += T_;
    681 			} else {// if(val.constructor==Array)
    682 				var base = 16, d_, d = -1, k_, kA = [];
    683 				for (k in val)
    684 					if (typeof val[k] == 'object' || typeof val[k] == 'function')
    685 						Vlist.push(vName + '.' + k); //	簡單的Object遞迴
    686 					else kA.push(parseInt(k) == k ? parseInt(k) : k); //	因為Array中仍有可能存在非數字index
    687 				kA.sort(), vType = 'Array', t = ',' + base;
    688 				for (k_ = 0; k_ < kA.length; k_++) {
    689 					if (!((k = kA[k_]) in val)) {
    690 						if (d_ != '*')
    691 							if (k - d == 1)
    692 								d_ += ',';
    693 							else
    694 								d_ = '*';
    695 					} else {
    696 						T_2 = (k - d == 1 ? ''
    697 								: d_ != '*' && k - d < 3/* k.toString(base).length-1 */? d_
    698 										: (isNaN(k) ? k.replace(/,/g, cmC)
    699 														.replace(/=/g, eqC)
    700 													: k.toString(base))
    701 								+ '=')
    702 							+ ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC)
    703 							+ ',';
    704 						d_ = '';
    705 						if (T_.length + T_2.length > maxLen)
    706 							T += T_ + NL_, T_ = T_2;
    707 						else
    708 							T_ += T_2;
    709 					}
    710 					d = k;
    711 					if (!_i && parseInt(val[k]) == val[k])
    712 						_i = 1;
    713 					else if (_i < 2 && parseFloat(val[k]) == val[k]
    714 					&& parseInt(val[k]) != val[k])
    715 						_i = 2;
    716 				}
    717 				T += T_;
    718 			}
    719 			if (T) {
    720 				if (!vars['set_obj_value'] || !vars['dQuote']) {
    721 					Vlist.push('set_obj_value', 'dQuote'); //	假如沒有set_obj_value則須將之與其所依存之函數（dQuote）一同加入
    722 					if (!vars['set_obj_value.F'])
    723 						Vlist.push(direct_input + 'var set_obj_value.F;');
    724 				}
    725 				afterCode += "set_obj_value('"
    726 					+ vName
    727 					+ "','"
    728 					+ T.slice(0, -1)
    729 					+ "'"
    730 					+ (_i ? _i == 1 ? ",1" : ",.1" : t ? ",1"
    731 							: '') + t + ");" + new_line;
    732 				t = 1;
    733 			} else
    734 				t = vType == 'Object' ? '{}' : '[]'; //new Object(), new Array()
    735 		} else if (vType == 'object' && val.constructor == RegExp)
    736 			t = val;
    737 		else if (vType == 'undefined')
    738 			//	有定義(var)但沒設定值，可計算undefined數目
    739 			t = 1;
    740 		else if (t = 1, vType != 'unknown')
    741 			if (('' + val).match(/^\s*\[[Oo]bject\s*(\w+)\]\s*$/)) t = RegExp.$1; //	僅對Math有效？
    742 			else vType = 'unknown type: ' + vType + ' (constructor: ' + val.constructor + ')', alert(vName + ': ' + vType + ', please contract me!\n' + val); //	未知
    743 		else alert('The type of ' + vName + ' is "' + vType + '"!'); //	unknown
    744 		if (typeof t != 'undefined') {
    745 			if (vName.indexOf('.') == -1)
    746 				codeText += (c ? ',' : 'var ') + vName + (t === 1 && vType != 'number' ? '' : '=' + t), c = 1; //alert(codeText.substr(codeText.length-200));
    747 			else if (t !== 1 || vType == 'number')
    748 				codeText += (c ? ';' : '') + vName + '=' + t + ';',
    749 				c = 0;
    750 		}
    751 		done.push('(' + vType + ')' + vName);
    752 	}
    753 	if (c)
    754 		codeText += ';' + new_line; //,c=0;//alert(codeText.substr(codeText.length-200));//alert(afterCode);
    755 	return [ codeText, afterCode, vari, func, done, undone, Vlist ];
    756 };
    757 /**
    758  * default direct input symbol
    759  * @type	String
    760  * @memberOf	CeL.data.code.reorganize
    761  */
    762 _.generate_code.ddI = '*';
    763 /**
    764  * default separator
    765  * @type	String
    766  * @memberOf	CeL.data.code.reorganize
    767  */
    768 _.generate_code.dsp = ',';
    769
    770
    771
    772
    773 //	null code series
    774 //simpleWrite('try.js',add_null_code(50000));
    775 var null_code_data, null_code_data_length, add_null_codeD; //	處理null_code的變數暫存,null_code_data[變數名]=變數值,null_code_data_length=length,add_null_codeD:add_null_code data,因為每次都重新執行null_code()很費時間
    776 function add_null_code(len, type) {	//	為了基底才能加入function而作
    777 	var s = '', t, l, i, j; if (typeof add_null_codeD != 'object') add_null_codeD = []; qq = 0;
    778 	while (s.length < len) {
    779 		/*  t=Math.random()<.5?'function':'';
    780 		s+=len-s.length>9?null_code((len/2>999?999:len/2)+'-'+len,t):null_code(len,t);*/
    781 		l = len - s.length > 9 ? len > 2e3 ? 999 : len / 2 : len;
    782 		j = 0; for (i in add_null_codeD) if (i > l) break; else j = i;
    783 		if (j && j > 99) { if (len - s.length > 99) t = null_code(null_code(99, 0)), s += (add_null_codeD[t.length] = t); while (len - s.length > j) s += add_null_codeD[j]; }
    784 		s += j && len - s.length - j < 50 ? add_null_codeD[j]
    785 		//	:(t=null_code(l),add_null_codeD[t.length]=t);
    786                                     : (t = null_code(l) ? add_null_codeD[t.length] = t : '');
    787 	}
    788 	return s;
    789 }
    790 function null_code_data_add(vari, val) {	//	variables,value
    791 	if (vari) {
    792 		if (typeof null_code_data != 'object') null_code_data = {}, null_code_dataI = [], null_code_data_length = 0;
    793 		if (!(vari in null_code_data)) null_code_dataI.push(vari), null_code_data_length++;
    794 		null_code_data[vari] = val;
    795 	}
    796 }
    797 //var t=null_code('230-513','function');alert(t.length+'\n'+t);
    798 //
    799 //	其他方法（有閒情逸致時再加）：/**/,//,var vari=num+-*/num,str+-str,if(typeof vari=='~'){},try{eval('~');}catch(e){},eval('try{}catch(e){}');if()WScript.Echo();
    800 CeL.data.code.reorganize
    801 .
    802 /**
    803  * 產生無用的垃圾碼
    804  * @param length	\d || \d-\d
    805  * @returns	{String}	無用的垃圾碼
    806  * @see
    807  * @memberOf	CeL.data.code.reorganize
    808  */
    809 null_code = function (length, type) {
    810 	//	variables;up,down:長度上下限
    811 	var t = '', vari = [], u, d;
    812 	if (typeof null_code_data != 'object')
    813 		null_code_data = {}, null_code_dataI = [],
    814 		null_code_data_length = 0;
    815 	if (typeof length == 'number')
    816 		u = d = Math.floor(length);
    817 	else if (length = '' + length, (i = length.indexOf('-')) != -1)
    818 		d = parseInt(length.slice(0, i)), u = parseInt(length
    819 				.substr(i + 1));
    820 	if (u < d) {
    821 		var a = d;
    822 		d = u, u = a;
    823 	}
    824 	if (!length || !u || length < 0)
    825 		return '';
    826 	if (typeof type != 'string')
    827 		type = typeof type;
    828
    829 	//if(type=='boolean'){return Math.random()<.5?1:0;}
    830 	if (type == 'number') {
    831 		return Math.floor(Math.random() * (u - d) + d);
    832 	}
    833 	if (type == 'n2') {
    834 		if (u < 9 && d < 9)
    835 			d = Math.pow(10, d), u = Math.pow(10, u);
    836 		return Math.floor(Math.random() * (u - d) + d);
    837 	}
    838 	if (type == 'string') {
    839 		// if(d<0&&(d=0,u<0))
    840 		if (d < 0 && u < (d = 0))
    841 			return '';
    842 		for ( var i = 0, l = null_code(d + '-' + u, 0), t = []; i < l; i++)
    843 			t.push(null_code('32-128', 0));
    844 		return fromCharCode(t);
    845 	}
    846 	if (type == 'vari') {
    847 		//	變數variables
    848 		if (d) d--; u--; if (u > 32) u = 32; else if (u < 1) u = 1; //	最長變數:32
    849 		var a, i, l, c = 0;
    850 		do {
    851 			t = [], a = null_code('65-123', 0), i = 0, l = null_code(d + '-' + u, 0);
    852 			if (a > 90 && a < 97) a = 95; t.push(a);
    853 			for (; i < l; i++) { a = null_code('55-123', 0); if (a > 90 && a < 97) a = 95; else if (a < 65) a -= 7; t.push(a); } //	code:48-57,65-90,95,97-122;
    854 			t = fromCharCode(t); try { eval('a=typeof ' + t + '!="undefined";'); } catch (e) { } //	確保是新的變數
    855 			if (c % 9 == 0 && d < u) ++d;
    856 		} while (++c < 99 && (a || (t in null_code_data))); //	不能確保是新變數的話，給個新的：繼續作。★此作法可能導致長時間的迴圈delay！因此限制最多99次。
    857 		//if(c==99){alert('重複：['+a+']'+t);WScript.Quit();}
    858 		return t;
    859 	}
    860 	if (type == 'function') {
    861 		var i = 0, l = null_code('0-9', 0), fN = null_code('2-30', 'vari'), a = NewLine + 'function ' + fN + '(', b = NewLine + '}' + NewLine, v, D = []; //	fN:函數名
    862 		//	只加入函數名
    863 		null_code_data_add(fN, 'function');
    864 		if (l) {
    865 			for (; i < l; i++)
    866 				v = null_code('2-30', 'vari'), a += v + ',', D.push(v);
    867 			a = a.slice(0, -1);
    868 		}
    869 		a += '){';
    870 		l = (a + b).length + NewLine.length;
    871 		if (u < l)
    872 			return null_code(length);
    873 		return a + (NewLine + null_code((d < l ? 0 : d - l) + '-'
    874 				+ (u - l))).replace(/\n/g, '\n	') + b;
    875 	}
    876 	//	others:type=='code'
    877 	var l = null_code(length, 0);
    878 	while (t.length < l) {
    879 		var a, v, va = (Math.random() < .5 ? (va = null_code('1-6', 0))
    880 				: dQuote(va = null_code('5-'
    881 						+ (u - t.length > 50 ? 50 : u - t.length),
    882 				'string')));
    883 		if (u - t.length > 20 && Math.random() < .9) {
    884 			if (Math.random() < .7 && null_code_data_length > 9)
    885 				v = null_code_dataI[null_code(0 + '-'
    886 						+ null_code_data_length, 0)], a = v + '=' + va;
    887 			else
    888 				v = null_code('1-9', 'vari'), a = 'var ' + v
    889 				+ (Math.random() < .3 ? '' : '=' + va);
    890 			a += ';' + (Math.random() < .4 ? NewLine : '');
    891 			null_code_data_add(v, va);
    892 		} else {
    893 			a = Math.floor(Math.random() * 4);
    894 			a = a == 1 ? '	' : a || u < t.length + NewLine.length ? ' '
    895 					: NewLine;
    896 		}
    897 		if (t.length + a.length <= u)
    898 			t += a;
    899 	}
    900 	return t;
    901 };
    902 //	↑null code series
    903
    904
    905
    906 /*
    907 bug:
    908 當每一行都去除\n也可時方能使用！否則會出現「需要;」的錯誤！
    909 可能會lose條件式編譯（@cc_on等）的資訊或判別錯誤！另外，尚不保證不會lose或更改程式碼！
    910
    911 http://www.dreamprojections.com/syntaxhighlighter/Default.aspx
    912
    913 TODO:
    914 將 local various 甚至 global 依頻率縮短，合併以字串組合代替。	selectable
    915 safer cut '\r\n'
    916 {_exp1_;_exp2_;}	→	_exp1_,_exp2_;
    917 safer cut ';'	;}	→	}
    918 compress: eval("~")
    919
    920 (function(~){~})(~);
    921
    922 var fascii2ascii = (function(){
    923 var cclass
    924 = '['+String.fromCharCode(0xff01)+'-'+String.fromCharCode(0xff5e)+']';
    925 var re_fullwidth = new RegExp(cclass, 'g');
    926 var substitution = function(m){
    927 return String.fromCharCode(m.charCodeAt(0) - 0xfee0); // 0xff00 - 0x20
    928 };
    929 return function(s){ return s.replace(re_fullwidth, substitution) };
    930 })();
    931
    932
    933
    934
    935 /*@cc_on	OK
    936 /*@ cc_on	error
    937 /* @cc_on	無效
    938
    939
    940 JSlint 可以協助您檢查出有問題的程式碼。
    941 http://www.jslint.com/
    942
    943 Javascript compressor
    944 http://dean.edwards.name/packer/
    945 http://javascriptcompressor.com/
    946 http://www.creativyst.com/Prod/3/
    947 http://www.radok.com/javascript-compression.html
    948 http://alex.dojotoolkit.org/shrinksafe/
    949 http://www.saltstorm.net/depo/esc/introduction.wbm
    950 */
    951
    952 CeL.data.code.reorganize
    953 .
    954 /**
    955  * 精簡程式碼：去掉註解與\s\n。
    956  * use for JSON (JavaScript Object Notation)
    957  * @param code	欲精簡之程式碼
    958  * @param mode	mode=1:''中unicode轉\uHHHH
    959  * @returns	{String}	精簡後之程式碼
    960  * @example
    961  * CeL.use('code.reorganize');
    962  * CeL.reduce_code('a + v  = ddd;');
    963  * @see
    964  * @requires
    965  * @memberOf	CeL.data.code.reorganize
    966  */
    967 reduce_code = function (code, mode) {
    968 	if (!code)
    969 		return ''; //sss=0,mmm=90;
    970 	var _s = _.reduce_code, reduce_space = _s.reduce_space, A = '', a = '' + code, m, b, q, c, Begin, End;
    971 	//reduce_codeM=[''];
    972 	while (a.match(/['"\/]/)) {
    973 		with (RegExp)
    974 			Begin = index, End = lastIndex, m = lastMatch;
    975 		//alert(a);
    976 		//	RegExp.$'等
    977 		if (Begin && a.charAt(Begin - 1) == '$') {
    978 			A += reduce_space(a.slice(0, Begin)) + m;
    979 			a = a.substr(End);
    980 			continue;
    981 		}
    982
    983 		if (m == '/') if (m = a.charAt(RegExp.lastIndex), m == '*' || m == '/') {	//	comment
    984 			//if(++sss>mmm-2&&alert('sss='+sss+NewLine+a),sss>mmm){alert('comment');break;}
    985 			//A+=reduce_space(a.slice(0,Begin)),b=m=='*'?'*/':'\n',m=a.indexOf(b,End+1);//A+=a.slice(0,RegExp.index),b=m=='*'?'*/':'\n',m=a.substr(RegExp.lastIndex).indexOf(b);//
    986 			A += reduce_space(a.slice(0, Begin));
    987 			b = m == '*' ? '*/' : '\n';
    988 			m = End + 1;
    989 			do {
    990 				//	預防「\*/」…其實其他地方（如["']）也需要預防，但沒那精力了。
    991 				m = a.indexOf(b, m);
    992 				if (a.charAt(m - 1) == '\\')
    993 					m += 2;
    994 				else
    995 					break;
    996 			} while (m != -1);
    997 			//reduce_codeM.push('find comment:	Begin='+Begin+',End='+End+',m='+m+',b='+b.replace(/\n/g,'\\n')+NewLine+(m-End>200||m==-1?a.substr(Begin,200)+'..':a.slice(Begin,m))+NewLine+NewLine+'continue:'+NewLine+a.substr(m+b.length,200)+'..');
    998 			if (m == -1)
    999 				if (b == '\n') { a = ''; break; /*return A;*/ }
    1000 				else throw new Error('[/*] without [*/]!\n' + a.substr(Begin, 200));
    1001 			else if (
    1002 					//	7: 最起碼應該有這麼多 char 的 comment 才列入查核
    1003 					7 + End < m &&
    1004 					//a.substring(End+1,m-5).indexOf('@cc_on')==0	不一定只有 cc_on
    1005 					/^@[cei][a-z_]+/.test(a.substring(End + 1, m - 5))
    1006 				)
    1007 				//alert('There is conditional compilation detected,\n you may need pay attention to:\n'+a.substring(End+1,m-5)),
    1008 				//	對條件式編譯全選，預防資訊lose。僅有'/*@cc_on'才列入，\/*\s+@\s+cc_on不可！
    1009 				A += a.slice(End - 1, m + b.length).replace(/\s*(\/\/[^\r\n]*)?(\r?\n)\s*/g, '$2'), a = a.slice(m + b.length);
    1010 			else if (a = a.substr(m + b.length), A.match(/\w$/) && a.match(/^\s*\w/))
    1011 				//	預防return /*~*/a被轉為returna
    1012 				A += ' ';
    1013 		} else {
    1014 			//	RegExp
    1015 			//reduce_codeM.push('find RegExp:	Begin='+Begin+NewLine+a.substr(Begin,200)+NewLine+'-'.x(20)+NewLine+A.substr(A.length-200)+'..');
    1016 			b = a.slice(0, Begin), m = 1; //c=Begin,q=End
    1017
    1018 			if (b.match(/(^|[(;+=!{}&|:\\\?,])\s*$/))
    1019 				//	RegExp:以起頭的'/'前面的字元作判別，前面是這些則為RegExp
    1020 				m = 1;
    1021 			else if (b.match(/[\w)\]]\s*$/))
    1022 				//	前面是這些則為op
    1023 				m = 0;
    1024 			else
    1025 				//	需再加強前兩項判別之處
    1026 				throw new Error(
    1027 						'Unknown [/]! Please check it and add rules!\n'
    1028 						+ b + '\n-------------\n'
    1029 						+ a.slice(0, End + 80)
    1030 						// +'\n-------------\n'+A
    1031 				);
    1032
    1033 			if (!m)
    1034 				//if(!m)A+=a.slice(0,q),a=a.substr(q);//	應該是op之類//
    1035 				A += reduce_space(a.slice(0, End)),
    1036 				a = a.substr(End);
    1037 			else {
    1038 				A += reduce_space(a.slice(0, Begin)), a = a.substr(Begin), c = 0; //else{A+=a.slice(0,c),a=a.substr(c),c=0;//
    1039 				//if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('reg');break;}
    1040 				while (m = a.substr(c).match(/([^\\]|[\\]{2,})([[\/\n])/)) {	//	去掉[]
    1041 					//reduce_codeM.push('find RegExp [ or / or \\n :'+NewLine+a.substr(c+RegExp.index+1,20));
    1042 					if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } //	奇數個[\]後
    1043 					else if (m = m[2], m == '/') break;
    1044 					if (m == '[')
    1045 						while ((m = a.substr(c += RegExp.lastIndex).match(/([^\\]|[\\]{2,})\]/))) {	//	不用c+=RegExp.index+1是因[]中一定得有字元
    1046 							if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } //	奇數個[\]後
    1047 							c += RegExp.lastIndex - 1; m = 1; break; //	-1:因為偵測'['時需要前一個字元
    1048 							//if(++sss>mmm-2&&alert('sss='+sss+'\nc='+c+'\n'+a.substr(c)),sss>mmm){alert('reg 2');break;}
    1049 						}
    1050 					if (m != 1) throw new Error('RegExp error!\nbegin with:\n' + a.substr(Begin, 200));
    1051 				}
    1052 				//reduce_codeM.push('find RegExp 2:'+NewLine+a.slice(0,c+RegExp.lastIndex));
    1053 				A += a.slice(0, c += RegExp.lastIndex), a = a.substr(c); //q=RegExp.lastIndex,alert('reg:'+Begin+','+c+','+q+'\n'+a.slice(0,Begin)+'\n-------\n'+a.slice(Begin,c+q)+'\n-------\n'+a.substr(c+q,200));return A;
    1054 				//q=RegExp.lastIndex,A+=reduce_space(a.slice(0,Begin))+a.slice(Begin,c+=q),a=a.substr(c);//A+=a.slice(0,c+=RegExp.lastIndex),a=a.substr(c);//
    1055 			}
    1056 		} else {
    1057 			//	quotation
    1058 			//alert('quotation:\n'+a)
    1059 			//reduce_codeM.push('find quotation:'+NewLine+a.substr(RegExp.index,200));
    1060 			//if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('quo');break;}
    1061 			//c=RegExp.index,b=a.substr(RegExp.lastIndex-1).match(new RegExp('[^\\\\]('+(q=m)+'|\\n)'));	較正式
    1062
    1063
    1064
    1065 /*
    1066
    1067    q=m;	//	2009/8/16 15:59:02 FAILED
    1068
    1069 function test_quotation(){
    1070 '\';		//	Error
    1071 '\\\';		//	Error
    1072 '\\\\\';	//	Error
    1073 '';
    1074 'n';
    1075 '\\';
    1076 'nn';
    1077 '\\n';
    1078 'n\\';
    1079 'n\\n';
    1080 '\\\\';
    1081 '\\\\n';
    1082 'n\\\\';
    1083 'n\\\\n';
    1084 'nn\\\\';
    1085 'nn\\\\n';
    1086 'nnn\\\\';
    1087 'nnn\\\\n';
    1088 }
    1089 alert(reduceCode(test_quotation));
    1090
    1091 alert(reduceCode(reduceCode));
    1092 */
    1093
    1094 /*
    1095 			//	找到 '\n' 為止，考慮 [\\\\]\\r?\\n
    1096 			c = Begin + 1, b = '';
    1097 			while ((c = a.indexOf('\n', c)) != -1) {
    1098 				q = a.charAt(c - 1);
    1099 				if (q == '\\' || q == '\r' && a.charAt(c - 2) == '\\') {
    1100 					c++;
    1101 					continue;
    1102 				}
    1103
    1104 			};
    1105 			if (a.charAt(c - 1))
    1106
    1107 				// alert('use RegExp: '+new
    1108 				// RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*('+q+'|\\n)'));
    1109 				b = a.slice(Begin + 1).match(
    1110 						new RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*(' + q
    1111 								+ '|\\n)')); // too slow!
    1112 			alert('test string:\n' + a.slice(Begin + 1))
    1113 			if (!b || b[2] == '\n')
    1114 				throw new Error('There is a start quotation mark [' + q
    1115 						+ '] without a end quotation mark!\nbegin with:\n'
    1116 						+ a.substr(Begin, 200)); // 語法錯誤?
    1117 			q = RegExp.lastIndex + 1;
    1118 */
    1119
    1120 			//	未考慮 '\n' (不能 check error!)
    1121 			c = Begin;
    1122 			q = m;
    1123 			//	考慮 [\\\\]\\r?\\n
    1124 			while (b = a.substr(c).match(new RegExp('([^\\\\\\r]|\\\\{2,})(' + q + '|\\r?\\n)')))
    1125 				if (b[1].length > 1 && b[1].length % 2 == 1)
    1126 					c = RegExp.lastIndex - 1;
    1127 				else
    1128 					break;
    1129
    1130 			if (!b || b[2] == '\n')
    1131 				//	語法錯誤?
    1132 				throw new Error('There is a start quotation mark ['
    1133 						+ q + '] without a end quotation mark!\nget:['
    1134 						+ b + ']\nbegin with:\n' + a.substr(Begin, 200));
    1135 			//reduce_codeM.push('find quota ['+q+']:'+NewLine+a.substr(c,RegExp.lastIndex)+NewLine+'continue:'+NewLine+a.substr(c+RegExp.lastIndex,99));
    1136
    1137 			q = RegExp.lastIndex;
    1138
    1139
    1140
    1141 			//alert('q='+q+',['+b[0]+']');
    1142 			//alert(b[1]);
    1143 			//alert(b[2]);
    1144
    1145 			b = a.substr(Begin, q).replace(/\\\r?\n/g, '');
    1146 			//alert('mode='+mode);
    1147 			if (mode == 1) {
    1148 				m = '';
    1149 				for ( var i = 0; i <= q; i++)
    1150 					m += b.charCodeAt(i) > 127 ? '\\u'
    1151 							+ b.charCodeAt(i).toString(16) : b
    1152 							.charAt(i);
    1153 			}
    1154 			else m = b;
    1155
    1156 			//A+=a.slice(0,c+=RegExp.lastIndex),a=a.substr(c);
    1157 			A += reduce_space(a.slice(0, Begin)) + m, a = a.substr(Begin + q);
    1158
    1159 			//alert('A='+A);
    1160 			//alert('a='+a);
    1161
    1162 			//	對於 ~';{ → ~'{ 或  ~';if → ~'if  不被接受。
    1163 			//if(!/^[\s\r\n]*\}/.test(a))A+=';';
    1164 		}
    1165 	}
    1166
    1167 	//	後續處理
    1168 	A += reduce_space(a);
    1169 	//	這兩行在 reduce_space() 中已處理
    1170 	//A=A.replace(/([^;])\s*\n+\s*/g,'$1;');
    1171 	//A=A.replace(/\s*\n+\s*/g,'');//while(A.match(/\s*\n\s*/))A=A.replace(/\s*\n\s*/g,'');//
    1172
    1173 	return A;
    1174 };
    1175
    1176 /*	tech. data:
    1177
    1178 string:
    1179 ['"]~$1
    1180
    1181 RegExp:
    1182 [/]~$1[a-z]*
    1183 [/]~$1[gim]*
    1184 =RegExp.[source|test(|exec(]
    1185
    1186 .match(RegExp)
    1187 .replace(RegExp,)
    1188 .search(RegExp)
    1189
    1190 op[/]:
    1191 word/word
    1192 word/=word
    1193
    1194 ~:
    1195 /\\{0,2,4,6,..}$/
    1196
    1197 註解comment:
    1198 /*~* /
    1199 //~\n
    1200
    1201 符號denotation:/[+-*=/()&^,<>|!~%\[\]?:{};]+/
    1202 +-
    1203 word:/[\w]+/
    1204
    1205 program:
    1206 ((denotation|word|comment)+(string|RegExp)*)+
    1207
    1208 test:
    1209 i++ +
    1210 a+=++i+4
    1211 ++a+i++==++j+ ++e
    1212 a++ += ++d
    1213 a++ + ++b
    1214
    1215 for(.*;;)
    1216
    1217
    1218 */
    1219 CeL.data.code.reorganize
    1220 .
    1221 /**
    1222  * 精簡程式碼部分：去掉\n,;前後的空白等，應由 reduce_code() 呼叫。
    1223  * @param code	輸入欲精簡之程式碼
    1224  * @returns	{String}	精簡後之程式碼
    1225  * @see
    1226  * http://dean.edwards.name/packer/
    1227  * @memberOf	CeL.data.code.reorganize
    1228  */
    1229 reduce_code.reduce_space = function (code) {
    1230 	//	比下一行快很多，但為了正確性而放棄。
    1231 	//code=code.replace(/\s*\n+\s/g,'');
    1232 	//	當每一行都去除\n也可時方能使用！否則會出現「需要;」的錯誤！
    1233 	code = code
    1234 		.replace(
    1235 			/([^\s]?)\s*\n+\s*([^\s]?)/g,
    1236 			function($0, $1, $2) {
    1237 				var a = $1, b = $2;
    1238 				return a
    1239 					+ (a && b && a.match(/\w/) && b.match(/\w/) ? ' ' : '')
    1240 					+ b;
    1241 			})
    1242 		.replace(/\s+$|^\s+/g, '');
    1243
    1244 	//if(code.match(/\s+$/))code=code.slice(0,RegExp.index);
    1245 	//if(code.match(/^\s+/))code=code.substr(RegExp.lastIndex);
    1246
    1247 	//	對喜歡將\n當作;的，請使用下面的；但這可能造成失誤，例如[a=(b+c)\nif(~)]與[if(~)\nif(~)]
    1248 	/*
    1249 	var m, a;
    1250 	while (m = code.match(/\s*\n+\s*(.?)/))
    1251 		a = RegExp.lastIndex, code = code.slice(0, RegExp.index)
    1252 				+ (m[1].match(/\w/) ? ';' : '')
    1253 				+ code.substr(a - (m[1] ? 1 : 0));
    1254 	if (m = code.match(/\s+$/))
    1255 		code = code.slice(0, RegExp.index);
    1256 	if (m = code.match(/^\s+(.?)/)) {
    1257 		code = code.substr(RegExp.lastIndex - 1);
    1258 		if ((m[0].indexOf('\n') != -1 && m[1].match(/\w/)))
    1259 			code = ';' + code;
    1260 	}
    1261 	*/
    1262
    1263 	code = code
    1264 	//	最後再作
    1265 	//.replace(/([^;])\s*\n+\s*/g,'$1;').replace(/\s*\n+\s*/g,'')
    1266
    1267 	//	因為直接執行下行敘述會將for(~;;也變成for(~;，所以需先作處理。
    1268 	//.replace(/for\s*\(([^;]*);\s*;/g,'for;#$1#')
    1269 	//	在''等之中執行此行可能出問題，因此另外置此函數。
    1270 	//.replace(/\s*;+\s*/g,';')
    1271
    1272 	//.replace(/for;#([^#]*)#/g,'for($1;;')
    1273
    1274
    1275 	//.replace(/(.)\s+([+\-]+)/g,function($0,$1,$2){return $1+($1=='+'||$1=='-'?' ':'')+$2;}).replace(/([+-]+)\s+(.)/g,function($0,$1,$2){return $1+($2=='+'||$2=='-'?' ':'')+$2;})	//	+ ++ +
    1276 	.replace(/([+\-])\s+([+\-])/g, '$1 $2').replace(/([^+\-])\s+([+-])/g, '$1$2').replace(/([+\-])\s+([^+\-])/g, '$1$2') // + ++ +
    1277
    1278 	.replace(/\s*([()\[\]&|^{*\/%<>,~!?:.]+)\s*/g, '$1')	//	.replace(/\s*([()\[\]&|{}/%,!]+)\s*/g,'$1')	//	去掉'}'，因為可能是=function(){};或={'ucC':1};
    1279 	.replace(/([a-zA-Z])\s+([=+\-])/g, '$1$2').replace(/([=+\-])\s+([a-zA-Z])/g, '$1$2')
    1280
    1281 	.replace(/\s*([+\-*\/%=!&^<>]+=)\s*/g, '$1')
    1282 	//.replace(/\s*([{}+\-*/%,!]|[+\-*\/=!<>]?=|++|--)\s*/g,'$1')
    1283
    1284
    1285 	//	因為直接執行下行敘述會將for(~;;也變成for(~;，所以需先作處理。
    1286 	.replace(/for\(([^;]*);;/g, 'for;#$1#')
    1287 	//.replace(/};+/g,'}')	/*.replace(/;{2,}{/g,'{')*/.replace(/{;+/g,'{')//.replace(/;*{;*/g,'{')//在quotation作修正成效不彰
    1288 	//	去掉'}'，因為可能是=function(){};或={'ucC':1};
    1289 	.replace(/\s*([{;]);+\s*/g, '$1')//.replace(/\s*([{};]);+\s*/g,'$1')
    1290 	.replace(/for;#([^#]*)#/g, 'for($1;;')
    1291
    1292 	.replace(/\s{2,}/g, ' ')
    1293 	.replace(/([^)]);}/g, '$1}')	//	~;while(~);}	but: ~;i=(~);} , {a.b();}
    1294 	;
    1295 	//if(code.charAt(0)=="'")code=(code.charAt(1)=='}'?'}':code.charAt(1)==';'?'':code.charAt(1))+code.substr(2);
    1296
    1297 	return code;
    1298 };
    1299
    1300
    1301
    1302 CeL.data.code.reorganize
    1303 .
    1304 /**
    1305  * 精簡整個檔的程式碼
    1306  * …and test程式是否有語法不全處（例如沒加';'）
    1307  * @param original_ScriptFileName	origin javascript file name
    1308  * @param output_ScriptFileName	target javascript file name
    1309  * @param flag
    1310  * 	flag={doTest:bool,doReport:bool,outEnc:(enc),copyOnFailed:bool,startFrom:// | '',addBefore:'',runBefore:function}
    1311  * 	startFrom 若為 // 則應為 startAfter!!
    1312  * @requires	autodetectEncode,simpleRead,simpleWrite,reduce_code,is_file
    1313  * @deprecated use <a href="http://closure-compiler.appspot.com/" accessdate="2009/12/3 12:13">Closure Compiler Service</a>
    1314  * @memberOf	CeL.data.code.reorganize
    1315  */
    1316 reduce_script = function (original_ScriptFileName, output_ScriptFileName, flag) {
    1317 	if (!original_ScriptFileName)
    1318 		original_ScriptFileName = WScript.ScriptFullName;
    1319
    1320 	if (!output_ScriptFileName)
    1321 		output_ScriptFileName =
    1322 			//	getFP(original_ScriptFileName.replace(/\.ori/,''),1);
    1323 			original_ScriptFileName +
    1324 				//.compressed.js
    1325 				'.reduced.js';
    1326
    1327 	if (!flag)
    1328 		flag = {};
    1329
    1330 	if (!fso)
    1331 		fso = new ActiveXObject("Scripting.FileSystemObject");
    1332
    1333 	// 同檔名偵測（若自行把 .ori 改成標的檔等，把標的檔先 copy 成原來檔案。）
    1334 	if (original_ScriptFileName == output_ScriptFileName) {
    1335 		if (2 == WshShell.Popup('origin file and output file is the same!'
    1336 				+ (flag.originFile ? "\nI'll try to copy it back." : ''), 0,
    1337 				'Copy target as origin file', 1 + 48))
    1338 			return;
    1339 		if (!flag.originFile)
    1340 			return;
    1341 		if (is_file(original_ScriptFileName = flag.originFile)) {
    1342 			alert('origin file is exist! Please rename the file!');
    1343 			return;
    1344 		}
    1345 		try {
    1346 			fso.CopyFile(output_ScriptFileName, original_ScriptFileName);
    1347 		} catch (e) {
    1348 			alert('Failed to copy file!');
    1349 			return;
    1350 		}
    1351 	}
    1352
    1353 	if (!is_file(original_ScriptFileName)) {
    1354 		alert("Doesn't found original javascript file!\n" + original_ScriptFileName);
    1355 		return;
    1356 	}
    1357
    1358 	var sp = '='.x(80) + NewLine, reduce_codeM = [], enc = autodetectEncode(original_ScriptFileName), i, outenc = autodetectEncode(output_ScriptFileName);
    1359
    1360 	if (!flag.outEnc)
    1361 		flag.outEnc = outenc || enc || TristateTrue;
    1362
    1363 	try {
    1364 		var f = simpleRead(original_ScriptFileName, enc),
    1365 		ot = simpleRead(output_ScriptFileName, flag.outEnc), r = '';
    1366 		if (typeof f != 'string')
    1367 			throw new Error("Can't read file [" + original_ScriptFileName + "]!");
    1368 		t = flag.runBefore ? flag.runBefore(f) || f : f;
    1369 		if (flag.startFrom)
    1370 			if (typeof flag.startFrom == 'string') {
    1371 				if ((i = t.indexOf(flag.startFrom)) != -1)
    1372 					t = t.slice(i);
    1373 			} else if (flag.startFrom instanceof RegExp)
    1374 				t = t.replace(flag.startFrom, '');
    1375 		t = reduce_code(t);
    1376 		t = (flag.addBefore || '')
    1377 				+ t.replace(/([};])function(\s)/g, '$1\nfunction$2').replace(
    1378 						/}var(\s)/g, '}\nvar$1')/* .replace(/([;}])([a-z\._\d]+=)/ig,'$1\n$2') */
    1379 				+ reduce_codeM.join(NewLine + sp);
    1380 		// 不相同才 run
    1381 		if (t)
    1382 			if (t != ot || outenc != flag.outEnc)
    1383 				simpleWrite(output_ScriptFileName, t, flag.outEnc);
    1384 			else
    1385 				r = '* 欲寫入之內容(' + t.length + ' chars)與標的檔相同。檔案並未變更。\n';
    1386
    1387 		if (flag.doTest)
    1388 			// void //should use windows.eval
    1389 			// //if(WScript.ScriptName!=output_ScriptFileName)eval(t);
    1390 			eval('if(0){if(0){if(0){' + t + '}}}');
    1391 		if (flag.doReport)
    1392 			alert('OK!\n' + r + '\n' + f.length + '→' + t.length
    1393 					+ '(origin output: ' + ot.length + ') ('
    1394 					+ (100 * t.length / f.length).decp(2) + '%)\n\n[' + enc
    1395 					+ '] ' + original_ScriptFileName + '\n→\n[' + flag.outEnc
    1396 					+ '] ' + output_ScriptFileName);
    1397 	} catch (e) {
    1398 		if (6 == alert(
    1399 				'reduce_script: Error occured!\nDo you want to write error message to target file?\n'
    1400 						+ output_ScriptFileName, 0, 0, 3 + 32))
    1401 			simpleWrite(output_ScriptFileName, popErr(e) + NewLine + NewLine
    1402 					+ reduce_codeM.join(NewLine + sp), TristateTrue/* enc */, 0,
    1403 					true);
    1404 		if (flag.copyOnFailed)
    1405 			try {
    1406 				fso.CopyFile(original_ScriptFileName, output_ScriptFileName);
    1407 			} catch (e) {
    1408 				alert('Failed to copy file!');
    1409 				return;
    1410 			}
    1411 	}
    1412 };
    1413
    1414
    1415
    1416
    1417 /*
    1418 !! arguments unfinished !!
    1419
    1420 usage: include code in front:
    1421 //	[function.js]_iF,rJS
    1422 //	[function.js]End
    1423
    1424 rJS({add:'/*\nCopyright 2008 kanashimi\n欲使用此工具功能者，請聯絡作者。\n*\/\n'});
    1425
    1426 //	code start
    1427
    1428 (main code)..
    1429
    1430 */
    1431 CeL.data.code.reorganize
    1432 .
    1433 /**
    1434  * 縮減 HTML 用 .js大小+自動判別。
    1435  * TODO:
    1436  * 自動選擇 target 之模式（不一定是 .ori）
    1437  * @param flag	flag
    1438  * @requires	reduce_script
    1439  * @since	2008/7/31 17:40:40
    1440  * @memberOf	CeL.data.code.reorganize
    1441  */
    1442 rJS = function (flag) {
    1443 	if (typeof WScript == 'object') {
    1444 		var o = WScript, t, n;
    1445
    1446 		if (typeof reduce_script != 'function')
    1447 			o.Echo('Please include function reduce_script() to generate code.');
    1448 		else
    1449 			flag = flag || {},
    1450 			n = o.ScriptFullName,
    1451 			t = n.replace(/\.ori/, ''),
    1452 			reduce_script(n, t, {
    1453 				doReport : 1,
    1454 				outEnc : 'UTF-8',
    1455 				startFrom : flag.cut || /^(.|\n)+code\s+start\r?\n/,
    1456 				addBefore : flag.add,
    1457 				originFile : t.replace(flag.ori || /(\.[^.]+)$/, '.ori$1')
    1458 			});
    1459
    1460 		o.Quit();
    1461 	}
    1462 };
    1463
    1464
    1465 /*
    1466 try{var　o;try{o=new ActiveXObject('Microsoft.XMLHTTP')}catch(e){o=new XMLHttpRequest()}with(o)open('GET',(new　ActiveXObject("WScript.Shell")).RegRead('HKCU\\Software\\Colorless echo\\CeL.path'),false),send(null),eval(responseText)}catch(e){}
    1467
    1468 */
    1469 //(''+CeL.library_loader).replace(/^\s*function\s*\(\s*\)\s*{\s*/,'').replace(/\s*}\s*;\s*$/,'');
    1470 CeL.data.code.reorganize
    1471 .
    1472 /**
    1473 * for 引用：　include library 自 registry 中的 path
    1474 * @since	2009/11/25 22:59:02
    1475 * @_memberOf	_module_
    1476 */
    1477 library_loader_by_registry = function () {
    1478 	//if (typeof WScript == "object")
    1479 	try {
    1480 		var o;
    1481 		try {
    1482 			o = new ActiveXObject('Microsoft.XMLHTTP');
    1483 		} catch (e) {
    1484 			o = new XMLHttpRequest();
    1485 		}
    1486 		with (o)
    1487 			open('GET', (new ActiveXObject("WScript.Shell")).RegRead(library_namespace.env.registry_key), false),
    1488 				send(null),
    1489 				eval(responseText);
    1490 	} catch (e) {
    1491 	}
    1492 };
    1493
    1494
    1495
    1496
    1497
    1498 /*
    1499 {var d=new Date;try1();alert(gDate(new Date-d));}
    1500 function try1(){
    1501  var s='sde'.x(9999),t='',m,i=0;
    1502  while(m=s.substr(i).match(/s[^s]+/))t+=s.substr(i,RegExp.index),i+=RegExp.lastIndex;	//	way 1:3.24,3.19,3.13
    1503  //while(m=s.match(/s[^s]+/))t+=s.slice(0,RegExp.index),s=s.substr(RegExp.lastIndex);	//	way 2:3.52,3.24,3.29
    1504  //	way 1 is litter better than way 2.
    1505 }*/
    1506
    1507
    1508 /*
    1509 //	TODO: 對 encodeCode/decodeCode/reduceCode 嚴厲的測試（笑）
    1510 {var tr=1,c=simpleRead('function.js'),testF='try.txt',p='',range=99	,sp='='.x(80)+NewLine,tr2=tr,i,j,t,d,d0=new Date,da,db,dc;try{simpleWrite('try.js',c=reduceCode(c),TristateTrue);
    1511  do{da=new Date;t=''+encodeCode(c,p);db=new Date;d=''+decodeCode(t,p);dc=new Date;}while(--tr&&new Date-d0<2e4&&c==d);	//	find different
    1512  //if(d)alert('['+c.length+']→['+t.length+']	( '+(100*t.length/c.length).to_fixed(2)+' %)\n'+t.slice(0,range)+'\n..\n\ndecode →\n'+d.slice(0,range));//+'\n'+c
    1513  for(i=0,j=[];i<c.length;i++)j.push((i%80?'':NewLine)+c.charCodeAt(i));c+=j;
    1514  for(i=0,j=[];i<t.length;i++)j.push((i%80?'':NewLine)+t.charCodeAt(i));t+=j;
    1515  for(i=0,j=[];i<d.length;i++)j.push((i%80?'':NewLine)+d.charCodeAt(i));d+=j;
    1516  simpleWrite(testF,'start at '+gDate(da)+NewLine+'encode: '+gDate(db-da)+NewLine+'decode: '+gDate(dc-db)+NewLine+sp+'['+c.length+']→['+t.length+']	( '+(100*t.length/c.length).to_fixed(2)+' %)'+NewLine+c+NewLine+NewLine+t+NewLine+sp+(typeof encodeCodeC!='undefined'?encodeCodeC+sp:'')+NewLine+d+NewLine+sp+(typeof decodeCodeC!='undefined'?decodeCodeC+sp:'')+'try '+(tr2-tr)+' times '+(c==d?'OK!':'failed @ '+(i=same(c,d))+' .'+NewLine+c.substr(i-9,range)+NewLine+'-'.x(20)+NewLine+d.substr(i-9,range))+NewLine,TristateTrue);
    1517  alert('Test encodeCode over!');
    1518 }catch(e){simpleWrite(testF,popErr(e));}}	*/
    1519 //{a=simpleRead('function.js');for(i=0;i<encodeCodeDwordsRef.length;i++)a=a.replace(encodeCodeDwordsRef[i].replace(/([()])/g,'\\$1'),'');simpleWrite('try.txt',a);}
    1520 /*	編程式碼
    1521 	[0-\uffff=65535]
    1522 	↓	mapping to
    1523 	[1-10,13-29,32-127]:123個	普通char98[9,10,13,32-126], control chars25[1-8,14-29,127]
    1524 		[unicode control chars:ucC~ucC+5=1~5 *123^2]+unicode[*123][*1], [low unicode control chars:lucC~lucC+1=6~7]+[c]:char[0-31,127~255(最多2*122-32+127=339)], [片語char code:wordC=8]+片語index, [片語設定char code:wordSet=127]+[ (3 upper bits+) 4 len bits]+[片語index]+words
    1525 		尚可用char：16個[14-29]（未來擴充用，如\uhhhhhhhh:19個+4chars，不夠～）
    1526 	↓	mapping to
    1527 	char[1-9,11-12,14-127]-["\]:123個index
    1528
    1529 	未來：unicode片語編碼
    1530
    1531 	JavaScript五大關鍵字 - hax的技術部落格 - JavaEye技術網站	http://hax.javaeye.com/blog/380285
    1532 	if,this,function,return,var
    1533
    1534 	下兩行調到檔案頭
    1535 var encodeCodeCC,encodeCodeDwordsRef=['function ','return ','return','undefined','for(','var ','.length','typeof','continue;','if(','else','while(','break;','this.','try{','}catch(','true','false','eval(','new ','Array','Object','RegExp','.replace(','.match(','.push(','.pop(','.split(','isNaN(','.indexOf(','.substr(','with('];
    1536 set_obj_value('encodeCodeCC','ucC=1,lucC=6,wordC=8,wordS=127','int');
    1537 */
    1538 function encodeCode(code,K){	//	code,key
    1539  code=''+code;//code=reduceCode(code);
    1540  if(!code)return;
    1541  var ucC=encodeCodeCC.ucC,lucC=encodeCodeCC.lucC,wordC=encodeCodeCC.wordC,wordS=encodeCodeCC.wordS,rC=87	//	2<rC<ch.length!
    1542  ,rc='',c,i,k=[nullCode('3-'+(code.length>rC?rC:code.length<7?7:code.length),0)],l=nullCode('1-'+rC,0),p,q,r,count,po=0	//	rc:return code,k:encode key array,l:每次跳l個,c,p,q,r:tmp,po:point
    1543  ,recent,words={},wordsRef=encodeCodeDwordsRef.join('\0').split('\0')//,countC=[]	//	最近一次出現時間與出現頻率（次數:frequency）,片語index,片語index參照(reference)
    1544  ,ind=[],ch=[];	//	設定加碼chars：ind:index,用ch[(ind[]+k[])%ch.length]來取得所欲轉換成的字元
    1545  while(k.length<3&&!(l%=k.length))l=nullCode('1-'+rC,0);count=l+l;	//	確保多變性
    1546  //	設定加碼chars
    1547 /*
    1548  for(i=1;i<128;i++)
    1549   if(i!=10&&i!=13&&i!=34&&i!=92)ch.push(String.fromCharCode(i));
    1550  for(i=1,j=k.length;i<128;i++)
    1551   if(i!=11&&i!=12&&i!=30&&i!=31){if(++j>=ch.length)j=0;ind[i]=j;}
    1552 */
    1553  for(i=1,j=0;i<128;i++){
    1554   if(i!=11&&i!=12&&i!=30&&i!=31)ind[i]=j++;
    1555   if(i!=10&&i!=13&&i!=34&&i!=92)ch.push(String.fromCharCode(i));
    1556  }
    1557  //	設定加碼key
    1558  for(i=0;i<k.length;i++)k[i]=nullCode('0-'+rC,0);
    1559  if(typeof K=='string')for(i=0,p=K,K=[];i<p.length;i++)K.push(p.charCodeAt(i)%ch.length);
    1560  if(K instanceof Array&&K.length)k=K.concat(k);else K=[];	//	加入自訂key:k=自訂key+亂數key
    1561 	//l=51,count=l+l,k=[50,22,22];alert('l='+l+'\ncount='+count+'\n'+k);	//	自行初始設定key
    1562  //	使用下列keyword約可減一成
    1563  recent=[ch.length];
    1564  if(wordsRef.length>recent.length)wordsRef.length=recent.length;//alert(wordsRef.length+','+20*l);
    1565  for(p=20*l,i=0;i<wordsRef.length;i++)recent[words[wordsRef[i]]=i]=p;	//	初始優先權
    1566
    1567  //encodeCodeC=['wordsRef='+wordsRef+NewLine,k.length,l+NewLine].concat(k);encodeCodeC.push(NewLine,'-'.x(9),NewLine);if(K.length)encodeCodeC.push('use password['+K.length+']'+K+NewLine);var mm;
    1568  //	開始壓縮與編碼charcode>127
    1569  while(po<code.length){
    1570   if(126<(c=code.charCodeAt(po))||c<9||c<32&&c!=10&&c!=13)
    1571    if(po++,c<340)	//	low unicode
    1572     p=c<32?c:c-95//,mm='low unicode['+c+','+code.charAt(po-1)+'→'+p+']['+(lucC+(p<123?0:1))+','+p%123+']'//95=127-32
    1573     ,c=String.fromCharCode(lucC+(p<123?0:1),p%123),q=2;//q=c.length
    1574    else	//	unicode
    1575     q=(p=(c-(r=c%123))/123)%123,p=(p-q)/123//,mm='unicode['+code.charAt(po-1)+']:[ucC+'+p+']['+q+']['+r+']'
    1576     ,c=String.fromCharCode(ucC+p,q,r),q=3;//q=c.length
    1577   else if(p=code.substr(po).match(/^([.};'"]?\w{2,15})([ (.;{'"])?/)){	//	片語，雖然想在找出[.};'"]時一起處理，但因過於麻煩作罷
    1578    if(!isNaN(words[q=p[1]+p[2]])||!isNaN(words[q=p[1]]))	//	已有此片語
    1579     po+=q.length,c=String.fromCharCode(wordC,q=words[q]),recent[q]=count
    1580     //,mm='已有此片語['+q+']['+wordsRef[q]+']'
    1581     ,q=2;//,countC[q]++
    1582    else if(r=code.indexOf(q=p[1],po+RegExp.lastIndex),r!=-1&&r<5e3+po+RegExp.lastIndex){	//	後面還有此詞：建新片語
    1583     if(p[2]&&(r+=q.length)<code.length&&code.charAt(r)==p[2])q+=p[2];	//	尋求最長片語
    1584     for(r=0,i=1;i<recent.length;i++)if(!recent[i]){r=i;break;}else if(recent[i]<recent[r])r=i;	//	找出最不常用的
    1585     delete words[wordsRef[r]]	//	別忘了刪除原值。But注意！這個delete相當於 words[wordsRef[r]]='' 如此而已！（並不更改length，用.join()仍可發現其存在！）but typeof=='undefined'
    1586     ,po+=q.length,recent[words[wordsRef[r]=q]=r]=count,c=String.fromCharCode(wordS,q.length,r)+q
    1587     //,mm='建新片語['+r+']['+q+']'
    1588     ,q=3;//,countC[r]=1
    1589    }
    1590    else
    1591     c=code.charAt(po++),q=0
    1592     //,mm='片語['+p[1]+']→直接encode['+code.charCodeAt(po-1)+','+c+']'	//	沒有就直接encode
    1593     ;
    1594   }
    1595   else
    1596    c=code.charAt(po++),q=0
    1597    //,mm='直接encode['+code.charCodeAt(po-1)+','+c+']'	//	都不行就直接encode
    1598    ;
    1599
    1600   //	加碼與de-quote
    1601   //for(r=[],i=0;i<c.length;i++)r.push(c.charCodeAt(i));alert('get '+mm+' ['+c.length+']'+r+'\n'+c);
    1602   for(r='',i=0;i<c.length;i++)r+=ch[((i&&i<q?c.charCodeAt(i):ind[c.charCodeAt(i)])+k[count%k.length])%ch.length];	//	char code(0)+control code(1-q)+char code
    1603   //encodeCodeC.push(count,'next:'+po,code.charCodeAt(po)+'['+code.charAt(po)+']','control code len:'+q,'編成'+r.length+'['+r+']	'+mm+'	');for(var a,i=0;i<c.length;i++)encodeCodeC.push((i?' ':'')+'ch[('+(i&&i<q?a=c.charCodeAt(i):'ind['+(a=c.charCodeAt(i))+']='+(isNaN(a=ind[a])?'(null)':a))+' +k['+(p=count%k.length)+']='+(!isNaN(p)&&(p=k[p])?p:'(null)')+' )%'+ch.length+'='+(a=((a||0)+(p||0))%ch.length)+' ]=[ '+(!isNaN(a)&&(a=ch[a])?a.charCodeAt(0):'(null)')+' ]'+(a.charCodeAt(0)==r.charCodeAt(i)?'':'err:['+r.charCodeAt(i)+']'));encodeCodeC.push(NewLine);
    1604   rc+=r,count+=l;
    1605  }
    1606
    1607  //	組合	p:加碼組
    1608  for(i=K.length,p=(i?ch[0]:'')+ch[k.length-i]+ch[l];i<k.length;i++)p+=ch[k[i]];
    1609  //alert(toCharCode(p)+'\n'+toCharCode(rc));//4,55,54,25,25	53,56,86,22,22,54,86,22
    1610  return p+rc;
    1611 }
    1612
    1613 function toCharCode(s) {
    1614 	s += ''; if (!s) return; var i = 0, c = [];
    1615 	for (; i < s.length; i++) c.push(s.charCodeAt(i));
    1616 	return c;
    1617 }
    1618
    1619 //	解程式碼
    1620 function decodeCode(c,K){	//	code,key
    1621 	if(!c)return;//c:encoded code
    1622 	//	var ucC=encodeCodeCC.ucC,lucC=encodeCodeCC.lucC,wordC=encodeCodeCC.wordC,wordS=encodeCodeCC.wordS,words=encodeCodeDwordsRef.join('\0').split('\0')
    1623 	var ucC=1,lucC=6,wordC=8,wordS=127,words=['function ','return ','return','undefined','for(','var ','.length','typeof','continue;','if(','else','while(','break;','this.','try{','}catch(','true','false','eval(','new ','Array','Object','RegExp','.replace(','.match(','.push(','.pop(','.split(','isNaN(','.indexOf(','.substr(','with(']	//	精簡實戰版
    1624 	,i,k,l,p,q,r='',w=1,cr=[]
    1625 	//	tr:b===''時return a之char code，其他無b時return a之index code，有b時return a-b之char set。出錯時無return
    1626 	,trSet={},
    1627 	tr=function(s,a,b){if(!isNaN(b)&&b){var c,t="";while(a<b)if(!isNaN(c=s.ind[s.c.charCodeAt(a++)])&&!isNaN(c=s.ch[(c+s.k[s.count%s.k.length])%s.ch.length]))t+=String.fromCharCode(c);else return;return t;}else if(!isNaN(a=s.ind[s.c.charCodeAt(a)])&&((a=(a+s.k[s.count%s.k.length])%s.ch.length),typeof b!="string"||!isNaN(a=s.ch[a])))return a;}
    1628 	,ind=[],ch=[];	//	設定解碼chars：ind:index
    1629 	//	設定解碼chars
    1630 	for(i=1,p=0;i<128;i++){
    1631 		if(i!=10&&i!=13&&i!=34&&i!=92)ind[i]=p++;
    1632 		if(i!=11&&i!=12&&i!=30&&i!=31)ch.push(i);
    1633 	}
    1634 	//	取得及設定解碼key
    1635 	if(!(p=ind[c.charCodeAt(q=0)])){
    1636 		if(typeof K=='string')for(i=0,p=K,K=[];i<p.length;i++)K.push(ch.length-p.charCodeAt(i)%ch.length);
    1637 		if(K instanceof Array&&K.length)p=ind[c.charCodeAt(++q)];else return;
    1638 	}else K=[];	//	需要密碼
    1639 	for(k=[],l=ind[c.charCodeAt(++q)],p+=i=q+1;i<p;i++)k.push(ch.length-ind[c.charCodeAt(i)]);
    1640 	if(K.length)k=K.concat(k);
    1641 	trSet.c=c=c.substr(p),
    1642 	trSet.ind=ind,trSet.ch=ch,trSet.k=k,trSet.count=l;
    1643
    1644 	//	decodeCodeC=['words:'+words+NewLine,k.length,l+NewLine].concat(k);decodeCodeC.push(NewLine+'-'.x(9)+NewLine+'c:	');var mm;for(i=0;i<c.length;i++)decodeCodeC.push(c.charCodeAt(i));decodeCodeC.push(NewLine+'-'.x(9)+NewLine);if(K.length)decodeCodeC.push('use password['+K.length+']'+K+NewLine);
    1645 	i=-1;//alert('-1:'+i);
    1646 	//	開始解碼
    1647 	while((trSet.count+=l),++i<c.length){
    1648 		//	if((p=c.charCodeAt(i))>127)trSet.c=c=c.slice(0,)+;
    1649 		//	decodeCodeC.push(trSet.count+'	ch[(ind['+(q=c.charCodeAt(i))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i,'')+NewLine);
    1650 		//	decodeCodeC.push(trSet.count+'	ch[(ind['+(q=c.charCodeAt(i+1))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i+1)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i+1,'')+NewLine);
    1651 		//	decodeCodeC.push(trSet.count+'	ch[(ind['+(q=c.charCodeAt(i+2))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i+2)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i+2,'')+NewLine);
    1652 		if(isNaN(p=tr(trSet,i,''))){
    1653 			alert('decodeCode filed: illegal char ('+c.charCodeAt(i)+') @ '+i+'/'+c.length+'\n'+r);for(i=0,p=String.fromCharCode(k.length,l);i<k.length;i++)p+=String.fromCharCode(k[i]);return p+','+r;
    1654 			return;
    1655 		}	//	illegal
    1656 		//	[ucC|lucC]+unicode, [wordC]+片語index, [wordS]+[ (3 upper bits+) 4 len bits]+[片語index]+words
    1657 		if(p==wordS)
    1658 			q=tr(trSet,++i),p=tr(trSet,++i),r+=words[p]=tr(trSet,++i,i+q),i+=q-1
    1659 			//	,mm='設定片語 長'+q+'['+p+']:'+words[p]
    1660 			;
    1661 		else if(p==wordC)r+=words[tr(trSet,++i)]
    1662 		//	,mm='片語'+tr(trSet,i)+'['+words[tr(trSet,i)]+']'
    1663 		;
    1664 		else if(p==lucC||p==lucC+1)
    1665 			p+=tr(trSet,++i)-lucC,r+=String.fromCharCode(p<32?p:p+95)
    1666 			//	,mm='low unicode['+r.charCodeAt(r.length-1)+','+r.slice(-1)+'][p='+p+']'
    1667 			;
    1668 		else if(ucC<=p&&p<ucC+5)
    1669 			r+=String.fromCharCode(((p-ucC)*123+tr(trSet,++i))*123+tr(trSet,++i))
    1670 			//	,mm='unicode['+r.charCodeAt(r.length-1)+','+r.slice(-1)+'][p='+p+']'
    1671 			;
    1672 		else
    1673 			r+=String.fromCharCode(p)
    1674 			//	,mm='普通char('+p+')['+String.fromCharCode(p)+']'
    1675 			;	//	普通char
    1676
    1677 		//	alert(mm+'\n'+r);
    1678 		//	decodeCodeC.length--,decodeCodeC.push('	'+mm+NewLine);
    1679 	}
    1680
    1681 	return r;
    1682 }
    1683
    1684
    1685 CeL.data.code.reorganize
    1686 .
    1687 /**
    1688 * get various from code
    1689 * @param {String} code	程式碼
    1690 * @param {Boolean} fill_code	(TODO) 不只是定義，在 .code 填入程式碼。
    1691 * @return	{Object}	root namespace
    1692 * @since	2009/12/5 15:04:42, 2009/12/20 14:33:30, 2010/7/7 10:58:22
    1693 * @_memberOf	_module_
    1694 */
    1695 get_various_from_code = function (code, fill_code) {
    1696 	//library_namespace.log(''+code.slice(0, 100));
    1697
    1698 	//	使用 .split(/\r?\n/) 應注意：這實際上等於 .split(/(\r?\n)+/) (??)
    1699 	code = code.split(/\r?\n/);
    1700
    1701 	var i, m, last_code = [],
    1702 	/**
    1703 	 * 現在所處之 line
    1704 	 *
    1705 	 * @inner
    1706 	 * @ignore
    1707 	 */
    1708 	line = '',
    1709 	/**
    1710 	 * code.length, 加快速度用
    1711 	 *
    1712 	 * @constant
    1713 	 * @inner
    1714 	 * @ignore
    1715 	 */
    1716 	l = code.length,
    1717 	/**
    1718 	 * root namespace
    1719 	 *
    1720 	 * @inner
    1721 	 * @ignore
    1722 	 */
    1723 	ns = {},
    1724 	/**
    1725 	 * 暫存 code(變數定義)
    1726 	 *
    1727 	 * @inner
    1728 	 * @ignore
    1729 	 */
    1730 	tmp_code,
    1731 	/**
    1732 	 * 名稱暫存變數
    1733 	 *
    1734 	 * @inner
    1735 	 * @ignore
    1736 	 */
    1737 	name,
    1738 	/**
    1739 	 * arguments 暫存變數<br/>
    1740 	 * e.g., 變數 name
    1741 	 *
    1742 	 * @inner
    1743 	 * @ignore
    1744 	 */
    1745 	various,
    1746 	/**
    1747 	 * 本變數之 properties。<br/>
    1748 	 * properties = { property: text contents of this property }
    1749 	 *
    1750 	 * @inner
    1751 	 * @ignore
    1752 	 */
    1753 	properties,
    1754 	/**
    1755 	 * 最後一次定義的變數名，用於之後若有變數需要繼承 namespace 時。
    1756 	 *
    1757 	 * @inner
    1758 	 * @ignore
    1759 	 */
    1760 	latest_name,
    1761 	/**
    1762 	 * 紀錄有意義的註解所在行號.
    1763 	 * 預防需要把註解之前的也讀進來。有 bug!
    1764 	 *
    1765 	 * @inner
    1766 	 * @ignore
    1767 	 */
    1768 	origin_index,
    1769 	new_line=library_namespace.env.new_line,
    1770 	/**
    1771 	 * 將 jsdoc properties 轉換成 VSdoc(JScript IntelliSense in Visual Studio)
    1772 	 *
    1773 	 * @inner
    1774 	 * @ignore
    1775 	 * @see
    1776 	 * http://weblogs.asp.net/bleroy/archive/2007/04/23/the-format-for-javascript-doc-comments.aspx,
    1777 	 * http://msdn.microsoft.com/zh-tw/library/bb385682.aspx,
    1778 	 * http://www.codeproject.com/Articles/60661/Visual-Studio-JavaScript-Intellisense-Revisited.aspx
    1779 	 */
    1780 	jsdoc_to_vsdoc = function() {
    1781 		var p = [ '' ], n, V, a, i, l, t_p = function(v) {
    1782 			//CeL.log(n + ':\n' + properties[n]);
    1783 			v = typeof v === 'string' ? v
    1784 					.replace(/^[\s\n]+|[\s\n]+$/g, '')
    1785 					.replace(/\r?\n\s+|\s+\r?\n/g, new_line)
    1786 					//.replace(/</g,'<')
    1787 					: '';
    1788 			a = '';
    1789
    1790 			switch (n) {
    1791
    1792 			case 'description':
    1793 			case 'summary':
    1794 				if (!v || /^[\s\n]*$/.test(v))
    1795 					return;
    1796 				n = 'summary';
    1797 				break;
    1798
    1799 			case 'param':
    1800 				if (a = v.match(/^({([a-zA-Z_\d.$\|\s]+)}\s*)?([a-zA-Z_\d$]+|\[([a-zA-Z_\d.$]+)\])\s*(.*?)$/)){
    1801 					var t = a[2].replace(/\s+/g, '');
    1802 					v = a[5], a = ' name="' + (a[4] || a[3]) + '" type="' + t + '" optional="' + (!!a[4]) + '"';
    1803
    1804 					if (/integer/i.test(t))
    1805 						a += ' integer="true"';
    1806 					//	from CeL.net.web
    1807 					if (/HTML([A-U][A-Za-z]{1,15})?Element/i.test(t))
    1808 						a += ' domElement="true"';
    1809 				}else
    1810 					a = '';
    1811 				break;
    1812
    1813 			case 'type':
    1814 				return;
    1815
    1816 			case 'return':
    1817 				n += 's';
    1818 			case 'returns':
    1819 				if (a = v.match(/^({([a-zA-Z_\d$.\|\s]+)})?(.*)$/)){
    1820 					v = a[3].replace(/^[\s\n]+/g, '');
    1821 					a = a[2].replace(/\s+/g, '') || properties.type;
    1822
    1823 					a = a ? ' type="' + a + '"' : '';
    1824
    1825 					if (/integer/i.test(t))
    1826 						a += ' integer="true"';
    1827 					//	from CeL.net.web
    1828 					if (/HTML([A-U][A-Za-z]{1,15})?Element/i.test(t))
    1829 						a += ' domElement="true"';
    1830 				}else
    1831 					a = '';
    1832 				break;
    1833
    1834 			default:
    1835 			}
    1836
    1837 			if (v.indexOf(new_line) === -1 && a.indexOf(new_line) === -1)
    1838 				p.push('<' + n + a + (v ? '>' + v + '</' + n + '>' : '/>'));
    1839 			else{
    1840 				p.push('<' + n + a + '>');
    1841 				p = p.concat(v.split(new_line));
    1842 				p.push('</' + n + '>');
    1843 			}
    1844 		};
    1845
    1846 		for (n in properties)
    1847 			if (library_namespace.is_Array(V = properties[n]))
    1848 				for (i = 0, l = V.length; i < l; i++)
    1849 					t_p(V[i]);
    1850 			else
    1851 				t_p(V);
    1852
    1853 		return p.length>1 ? p.join(new_line + '	///	') + new_line
    1854 						+ new_line : '';
    1855 	},
    1856 	/**
    1857 	 * 從變數定義取得變數名。
    1858 	 *
    1859 	 * @param {String} _
    1860 	 *            變數定義
    1861 	 * @inner
    1862 	 * @ignore
    1863 	 */
    1864 	set_name = function(_) {
    1865 		name = properties.name;
    1866 		if (!name) {
    1867 			name = [];
    1868 			var i = origin_index, l;
    1869 			while (i > 0)
    1870 				if (/[;{})]\s*$/.test(l = code[--i].replace(/\/\/.*$/, '')))
    1871 					if ((name = name.join(' ')
    1872 							// 除去註解後
    1873 							.replace(/\/\*(.*?)\*\//g, ' '))
    1874 							// 已無註解的話
    1875 							.indexOf('*/') === -1){
    1876 						_ = name.replace(/^\s*var(\s+|$)/, '') + _;
    1877 						break;
    1878 					} else
    1879 						name = [ l, name ];
    1880 				else if(l)
    1881 					name.unshift(l);
    1882
    1883 			//if(!i):	Error!
    1884 			//if(_.match(/var/)) library_namespace.warn(name+'\n'+_);
    1885
    1886 			name = properties.memberOf ?
    1887 							(_.replace(/[\s\n]+/g, '').indexOf(properties.memberOf + '.') === -1 ?
    1888 									properties.memberOf + '.' : '')
    1889 							+ _ /* .replace(/^(.+)\./,'') */
    1890 					: 'property' in properties ?
    1891 							latest_name ? latest_name + '.prototype.' + _.replace(/^(.+)\./, '') : ''
    1892 					: _;
    1893 		}
    1894
    1895 		// 除去 space
    1896 		name = name.replace(/[\s\n]+/g, '');
    1897 	},
    1898 	handle_name = function() {
    1899 		var m = name
    1900 		.match(/^([a-zA-Z_$\d]+)\.[^.].+[^.]\.([a-zA-Z_$\d]+)$/);
    1901 		return m && m[1] === library_namespace.Class ? m[1] + '.'
    1902 				+ m[2] + '=' + name : name;
    1903 	};
    1904
    1905 	for (i = 0; i < l; i++) {
    1906 		//	一行一行判斷
    1907 		//	TODO: 提升效率
    1908 		line = code[origin_index = i];
    1909
    1910 		if (/^\s*\/\*\*/.test(line)) {
    1911 			//	處理 '/**' 之註解（這些是有意義的）
    1912 			properties = {};
    1913 			//	都沒有 '@' 時，預設為 @description
    1914 			name = 'description';
    1915 			tmp_code = [];
    1916 			various=[];
    1917 			//library_namespace.log('' + line);
    1918 			while (i < l) {
    1919 				//library_namespace.log('' + line);
    1920 				tmp_code.push(line);
    1921
    1922 				//	判別
    1923 				if (line.indexOf('*/') !== -1 || (m = line.match(/^\s+\*\s+@([_a-zA-Z\d\$.]+)(\s+([^\s].*)?\s*)?$/))) {
    1924 					//	設定 name = various
    1925 					various = various.join(new_line);
    1926 					if (name in properties)
    1927 						if (library_namespace.is_Array(properties[name]))
    1928 							properties[name].push(various);
    1929 						else
    1930 							properties[name] = [ properties[name], various ];
    1931 					else
    1932 						properties[name] = various;
    1933
    1934 					if (line.indexOf('*/') !== -1)
    1935 						break;
    1936
    1937 					name = m[1], various = [ m[3] ];
    1938
    1939 				} else
    1940 					various.push((m = line.match(/^\s+\*\s+([^\s].+)$/)) ? m[1] : line.replace(/^(.*)\/\*\*/, ''));
    1941
    1942 				line = code[++i];
    1943 			}
    1944
    1945 			//library_namespace.log('[' + i + ']' + '\n' + tmp_code.join('\n') + '\n' + line);
    1946 			if (m = line.match(/(.*?\*\/)/)) {
    1947 				line = line.replace(/(.*?)\*\//, '');
    1948 				while (i < l
    1949 						&& !/=\s*[^\s]|{/.test(line = line.replace(
    1950 								/\s*\/\/[^\n]*/g, '').replace(
    1951 										/\/\*((.|\n)*?)\*\//g, '')))
    1952 					line += code[++i];
    1953
    1954 				//	初始化函式名
    1955 				name = '';
    1956
    1957 				/*
    1958 				* 註解處理完了，接下來是變數。先把整個定義區放到 line。
    1959 				* 這邊處理幾種定義法:
    1960 				* function name() {};
    1961 				* var name = function(){};
    1962 				* var name = new Function();
    1963 				* var name = 123;
    1964 				*/
    1965 				while (!/^\s*function\s$/.test(line) && !/[=;,]/.test(line))
    1966 					line += ' ' + code[++i];
    1967
    1968 				if (m = line.match(/^\s*function\s+([_a-zA-Z\d\$.]*)\s*\((.*)/)) {
    1969 					// function name() {};
    1970 					set_name(m[1]);
    1971 					various = m[2];
    1972 					while (i < l && various.indexOf(')') === -1)
    1973 						various += code[++i];
    1974 					m = various.match(/^[^)]*/);
    1975 					tmp_code.push(handle_name() + '=function(' + m[0] + '){'
    1976 									+ jsdoc_to_vsdoc() + '};');
    1977
    1978 				} else if (m = line
    1979 						.match(/^\s*(var\s+)?([_a-zA-Z\d\$.]+)\s*=\s*(.+)/)) {
    1980 					set_name(m[2]);
    1981 					various = m[3];
    1982 					if (/^\s*function(\s+[_a-zA-Z\d\$]+)?\s*\(/.test(various)) {
    1983 						// var name = function(){};
    1984 						while (i < l && various.indexOf(')') === -1)
    1985 							various += code[++i];
    1986 						m = various.match(/^[^)]+\)/);
    1987 						tmp_code.push(handle_name() + '=' + m[0] + '{' + jsdoc_to_vsdoc() + '};');
    1988
    1989 					} else if (/^\s*new\s+Function\s*\(/.test(various)) {
    1990 						// var name = new Function();
    1991 						if (m = various.match(/^\s*new\s+Function\s*\(.+\)\s*;?\s*$/)) {
    1992 							//	TODO
    1993 							tmp_code.push(handle_name() + '=new Function("");');
    1994 						} else
    1995 							tmp_code.push(handle_name() + '=new Function();');
    1996
    1997 					} else {
    1998 						// var name = 123;
    1999 						if (!properties.type)
    2000 							if (/^['"]/.test(various)) {
    2001 								properties.type = 'String';
    2002 							} else if (!isNaN(various)) {
    2003 								properties.type = 'number';
    2004 							} else if (/^(true|false)([\s;,]|$)/.test(various)) {
    2005 								properties.type = 'bool';
    2006 							} else if (various.charAt(0) === '[') {
    2007 								properties.type = 'array';
    2008 							} else if (various.charAt(0) === '{') {
    2009 								properties.type = 'object';
    2010 							} else if (various.charAt(0) === '/') {
    2011 								properties.type = 'regexp';
    2012 							} else if (/^regexp obj(ect)?$/.test(properties.type)) {
    2013 								properties.type = 'regexp';
    2014 							}
    2015
    2016 						//if (name === 'module_name');
    2017
    2018 						switch ((properties.type || '').toLowerCase()) {
    2019 							case 'string':
    2020 								m = various.replace(/\s*[,;]*\s*$/, '');
    2021 								//library_namespace.log('['+m+']');
    2022 								if (/^'[^\\']*'$/.test(m)
    2023 									|| /^"[^\\"]*"$/.test(m)) {
    2024 									various = '=' + m + ';';
    2025 								} else {
    2026 									various = '="";	//	' + various;
    2027 								}
    2028 								properties.type='String';
    2029 								break;
    2030
    2031 							case 'bool':
    2032 							case 'boolean':
    2033 								if (m = various.toLowerCase().match(
    2034 									/^(true|false)([\s,;]|$)/i)) {
    2035 									various = '=' + m[1] + ';';
    2036 								} else {
    2037 									various = '=true;	//	' + various;
    2038 								}
    2039 								properties.type='Boolean';
    2040 								break;
    2041
    2042 							case 'number':
    2043 								properties.type = 'Number';
    2044 							case 'int':
    2045 							case 'integer':
    2046 								if (/int(eger)?/i.test(properties.type))
    2047 									properties.type = 'Integer';
    2048
    2049 								if (!isNaN(various)) {
    2050 									various = '=' + various + ';';
    2051 								} else {
    2052 									various = '=0;	//	' + various;
    2053 								}
    2054 								break;
    2055
    2056 							case 'array':
    2057 								various = '=' + '[];';
    2058 								properties.type = 'Array';
    2059 								break;
    2060
    2061 							case 'object':
    2062 								if (various.charAt(0) === '{') {
    2063 									while (i < l) {
    2064 										if (various.lastIndexOf('}') !== -1) {
    2065 											m = various.slice(1, various.lastIndexOf('}'));
    2066 											if (m.lastIndexOf('/*') === -1
    2067 												|| m.lastIndexOf('/*') < m
    2068 														.lastIndexOf('*/'))
    2069 												break;
    2070 										}
    2071 										various += '\n' + code[++i];
    2072 									}
    2073 									m = various
    2074 										.replace(/\s*\/\/[^\n]*/g, '')
    2075 										.replace(/\/\*((.|\n)*?)\*\//g, '')
    2076 										.replace(/}(.*)$/,'}');
    2077 									if (0 && m.length > 3)
    2078 										library_namespace.log(name + '\n' + m
    2079 									// + '\n'+v
    2080 									);
    2081 									if (/^{([\s\n]*(('[^']*'|"[^"]*"|[_a-zA-Z\d\$.]+))[\s\n]*:('[^']*'|"[^"]*"|[\s\n\d+\-*\/()\^]+|true|false|null)+|,)*}/
    2082 										.test(m))
    2083 										various = '=' + various.replace(/}(.*)$/, '}') + ';';
    2084 									else
    2085 										various = '=' + '{};';
    2086 								} else
    2087 									various = '=' + '{};';
    2088 								properties.type = 'Object';
    2089 								break;
    2090
    2091 							case 'regexp':
    2092 								if (/^\/.+\/$/.test(various))
    2093 									various = '=' + various + ';';
    2094 								else {
    2095 									various = '=' + '/^regexp$/;	//	' + various;
    2096 								}
    2097 								properties.type = 'RegExp';
    2098 								break;
    2099
    2100 							default:
    2101 								//	TODO: T1|T2|..
    2102 								if (/^[_a-zA-Z\d\$.]/.test(various)) {
    2103 									// reference
    2104 									various = ';//' + (properties.type ? '[' + properties.type + ']' : '')
    2105 										+ various;
    2106 								} else {
    2107 									// unknown code
    2108 									various = ';	//	'
    2109 										+ (properties.type ? '[' + properties.type + ']' : '')
    2110 										+ various;
    2111 								}
    2112 						}
    2113
    2114 						tmp_code.push((/^=/.test(various) ? '' : '//') + handle_name() + various);
    2115 					}
    2116 				}
    2117
    2118 				if (name && !('ignore' in properties) && !('inner' in properties) && !('private' in properties)) {
    2119 					if (!('property' in properties))
    2120 						//	定義最後一次變數名
    2121 						latest_name = name;
    2122
    2123 					name = name.split(library_namespace.env.module_name_separator);
    2124
    2125 					//	對可能的錯誤發出警告
    2126 					if (name[0] !== library_namespace.Class && !('deprecated' in properties))
    2127 						library_namespace.warn(i + ': line [' + name.join(library_namespace.env.module_name_separator) + '] NOT initial as '+library_namespace.Class+'\n'
    2128 								+ code.slice(i - 6, i + 6).join('\n'));
    2129
    2130 					//	將變數定義設置到 ns
    2131 					var np = ns, nl = name.length - 1, n;
    2132 					for (m = 0; m < nl; m++) {
    2133 						n = name[m];
    2134 						if (!(n in np))
    2135 							// 初始設定 namespace
    2136 							np[n] = {
    2137 								'this': ''
    2138 							};
    2139 						else if (!library_namespace.is_Object(np[n]))
    2140 							np[n] = {
    2141 								'this': np[n]
    2142 							};
    2143 						np = np[n];
    2144 					}
    2145
    2146 					n = name[nl];
    2147 					//if (n in np) library_namespace.log('get_various_from_code: get duplicate various: [' + name.join(library_namespace.env.module_name_separator) + ']');
    2148
    2149 					np[n] = tmp_code.join(new_line);
    2150 				}
    2151 			}
    2152 		}
    2153 	}
    2154
    2155 	return ns;
    2156 };
    2157
    2158
    2159 CeL.data.code.reorganize
    2160 .
    2161 /**
    2162 * 把 get_various_from_code 生成的 namespace 轉成 code
    2163 * @param	{Object} ns	root namespace
    2164 * @param	{String} [prefix]	(TODO) prefix of root namespace
    2165 * @param	{Array}	[code_array]	inner use, please don't specify this value.
    2166 * @return	{String}	code
    2167 * @since	2009/12/20 14:51:52
    2168 * @_memberOf	_module_
    2169 */
    2170 get_code_from_generated_various = function (ns, prefix, code_array) {
    2171 	var _s = _.get_code_from_generated_various, i, return_text = 0;
    2172
    2173 	if (!code_array)
    2174 		code_array = [],
    2175 		return_text = 1;
    2176
    2177 	//	先處理 'this'
    2178 	if (prefix) {
    2179 		if (!/\.prototype$/.test(prefix))
    2180 			if (i = ns['this']) {
    2181 				code_array.push(i);
    2182 				delete ns['this'];
    2183 			} else
    2184 				code_array.push('',
    2185 						'//	null constructor for [' + prefix + ']',
    2186 						prefix + '=function(){};',
    2187 						prefix + '.prototype={};');
    2188 		prefix += '.';
    2189 	} else
    2190 		prefix = '';
    2191
    2192
    2193 	for (i in ns)
    2194 		if (typeof ns[i] === 'string')
    2195 			code_array.push(ns[i]);
    2196 		else
    2197 			_s(ns[i], prefix + i, code_array);
    2198
    2199 	return return_text ?
    2200 			code_array.join(library_namespace.env.new_line)
    2201 					//.replace(/[\r\n]+/g,library_namespace.env.new_line)
    2202 			: code_array;
    2203 };
    2204
    2205
    2206
    2207
    2208 return (
    2209 	CeL.data.code.reorganize
    2210 );
    2211 }
    2212
    2213
    2214 );
    2215
    2216