■ DLL ロード・解放 2005/01/22 // 実行時間(ミリ秒/回) dengaku macrodll BREGEXP // 01/21 23:45:46 WELSPER 4.565 2.690 0.578 // 01/21 23:44:52 WELSPER 4.550 2.626 0.624 ■ スタックされたローカル変数 2005/01/22 変数がたくさんあるほど遅くなるのはわかった。ローカル変数の場合はどうか? // 実行時間(ミリ秒/回) // 01/21 23:39:41 WELSPER 0.452 0.457 500個 // 01/21 23:33:04 WELSPER 0.052 0.054 50個 // 01/21 23:27:02 WELSPER 0.006 0.009 0個 スタックに残ってたら call 先のルーチンに影響する。 スタックから捨てられたら return 元のルーチンには影響しない。 ルックアップ時間は変数1個あたり 0.001ms が目安。 ■ 文字列エスケープ 2005/01/22 // 実行時間(ミリ秒/回) Case1 Case2 Case3 // 01/22 09:29:43 WELSPER 58.912 2.000 0.240 正規表現のみ // 01/22 09:39:21 WELSPER 77.372 2.855 0.389 正規表現と制御コード Case1: ##i = strlen($$1); while (##i > 0) { ##c = ascii(rightstr($$1, ##i)); if (strstr("$()*+.?[\\]^{|}", char(##c)) >= 0) $$r = $$r + "\\" + char(##c); else if (##c >= ' ') $$r = $$r + char(##c); else if (##c >= 0x07 && ##c <= 0x0b) $$r = $$r + "\\" + midstr(" abtnv", ##c, 1); else if (##c != 0x0d) $$r = $$r + "\\x" + hex(##c); ##i = ##i - strlen(char(##c)); } return $$r; Case2: $$r = $$1; if (##2 & 0x01) { $$r = dllfuncstr("GSUB", $$r, "\\", "\\\\", -1); } if (##2 & 0x02) { $$r = dllfuncstr("GSUB", $$r, "$", "\\$", -1); $$r = dllfuncstr("GSUB", $$r, "(", "\\(", -1); $$r = dllfuncstr("GSUB", $$r, ")", "\\)", -1); $$r = dllfuncstr("GSUB", $$r, "*", "\\*", -1); $$r = dllfuncstr("GSUB", $$r, "+", "\\+", -1); $$r = dllfuncstr("GSUB", $$r, ".", "\\.", -1); $$r = dllfuncstr("GSUB", $$r, "?", "\\?", -1); $$r = dllfuncstr("GSUB", $$r, "[", "\\[", -1); $$r = dllfuncstr("GSUB", $$r, "]", "\\]", -1); $$r = dllfuncstr("GSUB", $$r, "^", "\\^", -1); $$r = dllfuncstr("GSUB", $$r, "{", "\\{", -1); $$r = dllfuncstr("GSUB", $$r, "|", "\\|", -1); $$r = dllfuncstr("GSUB", $$r, "}", "\\}", -1); } if (##2 & 0x04) { $$r = dllfuncstr("GSUB", $$r, "\x07", "\\a", -1); $$r = dllfuncstr("GSUB", $$r, "\x08", "\\b", -1); $$r = dllfuncstr("GSUB", $$r, "\t", "\\t", -1); $$r = dllfuncstr("GSUB", $$r, "\n", "\\n", -1); $$r = dllfuncstr("GSUB", $$r, "\x0b", "\\v", -1); $$r = dllfuncstr("GSUB", $$r, "\r", "", -1); } return $$r; Case3: $$r = $$1; $$r = dllfuncstr("BRE_SUBST", "s/([][$()*+.?\\\\\\\\^{|}\\x07\\x08\\t\\n\\x0b])/\\\\$1/gk", $$r); $$r = dllfuncstr("BRE_TRANS", "tr/\\x07\\x08\\t\\n\\x0b\\r/abtnv/gdk", $$r); return $$r; // 正規表現のみ $$r = dllfuncstr("BRE_SUBST", "s/([][$()*+.?\\\\\\\\^{|}])/\\\\$1/gk", $$r); return $$r; ■ enabledraw; したときの画面位置 2003/01/27 disabledraw; ← これダメ openfile "/h " + $DicFile; setactivehidemaru #MyHandle; enabledraw; とすると CompleteInline.mac では元の位置に戻らない。 …が、 動作テスト.mac では戻った。はてな? ■ 1文字ずつバラす処理をマルチバイト文字対応に 2003/01/23 // 実行時間(ミリ秒/回) // 01/23 04:41:48 NAYULON 51.110 55.746 51.403 // 01/23 04:33:16 NAYULON 15.323 16.693 15.720 Case1: ##i = strlen($$1); while (##i) { ##c = ascii(rightstr($$1, ##i)); // 1文字の切り出しは ascii() に任せる if (strstr("$()*+.?[\\]^|", char(##c)) >= 0) $$r = $$r + "\\" + char(##c); else if ((!#CaseSense) && ##c >= 'a' && ##c <= 'z') $$r = $$r + "[" + char(##c) + char(##c - 32) + "]"; else $$r = $$r + char(##c); ##i = ##i - strlen(char(##c)); // 1文字の長さだけ詰める } Case2: ##i = strlen($$1); while (##i) { $$c = char(ascii(rightstr($$1, ##i))); if (strstr("$()*+.?[\\]^|", $$c) >= 0) $$r = $$r + "\\" + $$c; else if ((!#CaseSense) && ascii($$c) >= 'a' && ascii($$c) <= 'z') $$r = $$r + "[" + $$c + char(ascii($$c) - 32) + "]"; else $$r = $$r + $$c; ##i = ##i - strlen($$c); } Case3: ##i = strlen($$1); while (##i) { ##c = ascii(rightstr($$1, ##i)); $$c = char(##c); if (strstr("$()*+.?[\\]^|", $$c) >= 0) $$r = $$r + "\\" + $$c; else if ((!#CaseSense) && ##c >= 'a' && ##c <= 'z') $$r = $$r + "[" + $$c + char(##c - 32) + "]"; else $$r = $$r + $$c; ##i = ##i - strlen($$c); } ■ マクロに INI ファイルを埋め込む 2003/01/23 $a [//words] //.html=[ strlen($$rv))##len = strlen($$rv); else ##len = strlen($word[##i]); ##j = 1; while(##j <= ##len && leftstr($word[##i],##j) == leftstr($$rv,##j)){ ##j = ##j + 1; } ##j = ##j -1; $$rv = leftstr($$rv,##j); ##i = ##i + 1; } $r = $$rv; if (#debug) message $r; #loopcount=#loopcount-1;} return tickcount-##starttime; Case2: ##starttime=tickcount; while(#loopcount){ ##l2 = #head; while (strstr($word[##l2], $instr) == 0) ##l2 = ##l2 + 1; ##c = strlen($instr); while (true) { ##l = #head; $$c = midstr($word[#head], ##c, 1); if ($$c == "") break; while (midstr($word[##l], ##c, 1) == $$c && ##l < ##l2) ##l = ##l + 1; if (##l < ##l2) break; ##c = ##c + 1; } $r = midstr($word[#head], strlen($instr), ##c - strlen($instr)); if (#debug) message $r; #loopcount=#loopcount-1;} return tickcount-##starttime; // テストデータ: $word[ 0] = "appendsave"; $word[ 1] = "appendsaveall"; $word[ 2] = "appendsaveas"; $word[ 3] = "appendsaveconfig"; $word[ 4] = "appendsavedesktop"; $word[ 5] = "appendsaveexit"; $word[ 6] = "appendsaveexitall"; $word[ 7] = "appendsavehilight"; $word[ 8] = "appendsavelf"; $word[ 9] = "appendsaveupdatedall"; $word[10] = "appendsavewitheof"; $word[11] = "appendscrolllink"; $word[12] = "appendsearchbuffer"; $word[13] = "appendsearchdown"; $word[14] = "appendsearchdown2"; $word[15] = "appendsearchmode"; $word[16] = "appendsearchoption"; $word[17] = "appendsearchup"; $word[18] = "appendsearchup2"; $word[19] = "appendsecond"; $word[20] = "appendselectall"; $word[21] = "appendselectcfunc"; $word[22] = "appendselecting"; $word[23] = "appendselectline"; $word[24] = "appendselectword"; $word[25] = "appendselendx"; $word[26] = "appendselendy"; $word[27] = "appendseltopx"; $word[28] = "appendseltopy"; $word[29] = "appendsendmessage"; $word[30] = "appendsetactivehidemaru"; $word[31] = "appendsetclipboard"; $word[32] = "appendsetfontchangemode"; $word[33] = "appendsetmark"; $word[34] = "appendsetmonitor"; $word[35] = "appendsetreplace"; $word[36] = "appendsetsearch"; $word[37] = "appendsetwindowpos"; $word[38] = "appendsetwindowsize"; $word[39] = "appendshifttab"; $word[40] = "appendshowcliphist"; $word[41] = "appendshowcode"; $word[42] = "appendshowlineno"; $word[43] = "appendshowruler"; $word[44] = "appendshowtab"; $word[45] = "appendshowvars"; $word[46] = "appendshowwindow"; $word[47] = "appendsplit"; $word[48] = "appendsplitstate"; $word[49] = "appendsplitswitch"; $word[50] = "appendstr"; $word[51] = "appendstrlen"; $word[52] = "appendstrstr"; $instr = "a"; #k = 53; ■ 正規表現でエスケープすべき文字 2003/01/02 地の文内 []()^$.*+?|\ キャラクタクラス内 ]-^\ シーケンス \o123 \x12 \n \t \< \> \w ■ 正規表現(キャラクタクラス内)をエスケープする関数 2003/01/02 ascii(rightstr()) の方が若干速いが、 midstr() でも大差なし。 結局、文字(列)が含まれてるかどうかを調べるには strstr() を使うのがベストのようだ。 // 実行時間(ミリ秒/回) // 01/02 19:48:56 NAYULON 16.604 17.264 // 01/02 19:47:58 NAYULON 16.520 17.530 Case1: $$e = ""; ##i = strlen($$1); while (##i) { ##c = ascii(rightstr($$1, ##i)); if (##c == '-' || (##c >= '\\' && ##c <= '^')) $$e = $$e + "\\" + char(##c); else $$e = $$e + char(##c); ##i = ##i - 1; } if (#debug) call Confirm $$e; Case2: $$e = ""; ##i = strlen($$1); while (##i >= 0) { $$c = midstr($$1, ##i, 1); if (strstr("-\\]^", $$c) >= 0) $$e = "\\" + $$c + $$e; else $$e = $$c + $$e; ##i = ##i - 1; } if (#debug) call Confirm $$e; ■ 正規表現のメタキャラクタをエスケープする関数 2003/01/02 文字列として比較するのは論外。 if (strstr("$()*+.?[\]^|", $$c) >= 0) $$e = "\\" + $$c + $$e; が一番速い。 // 実行時間(ミリ秒/回) // 01/02 19:41:47 NAYULON 40.060 23.430 17.220 Case1: // 文字列で1個ずつ比較 $$e = ""; ##i = strlen($$1); while (##i >= 0) { $$c = midstr($$1, ##i, 1); if ($$c == "*" || $$c == "+" || $$c == "?" || $$c == "^" || $$c == "$" || $$c == "." || $$c == "[" || $$c == "]" || $$c == "(" || $$c == ")" || $$c == "|" || $$c == "\\") $$e = "\\" + $$c + $$e; else $$e = $$c + $$e; ##i = ##i - 1; } Case2: // 文字コードで比較 $$e = ""; ##i = strlen($$1); while (##i) { ##c = ascii(rightstr($$1, ##i)); if (##c == '$' || (##c >= '(' && ##c <= '+') || ##c == '.' || ##c == '?' || (##c >= '[' && ##c <= '^') || ##c == '|') $$e = $$e + "\\" + char(##c); else $$e = $$e + char(##c); ##i = ##i - 1; } Case3: strstr() で比較 $$e = ""; ##i = strlen($$1); while (##i) { $$c = midstr($$1, ##i - 1, 1); if (strstr("$()*+.?[\\]^|", $$c) >= 0) $$e = "\\" + $$c + $$e; else $$e = $$c + $$e; ##i = ##i - 1; } ■ 正規表現検索で「a\n?」が「ab[EOF]」にマッチしない件 02/12/17 「\n」を「\x0a」に代えることで回避できる。 秀丸が \n を特別扱いすることに起因するようだ。 http://www.maruo.co.jp/hidesoft/2/m021217.html#13690 ■ ModifyTag.mac 開発履歴 // 02/12/23 v1.0 カーソル戻り位置を厳密に補正 // 02/12/21 v1b2 最終行にあるタグを取りこぼす現象を回避($Delimiter の \n を \x0a に) // 02/12/07 v1b1 範囲選択時とタグ外実行時の処理を追加 // 02/12/06 v1a6 「<」「>」を含めて入力してもいい // 02/11/28 v1a5 対象範囲を選択して表示(いつでも) // 02/11/28 v1a4 対象範囲を選択して表示(最初が終了タグのときのみ) // 02/11/27 v1a3 ロジック変更 // 最初が終了タグのときは位置を記憶。開始タグと同じ行だったら文字数を計算してずらす。 // 02/11/26 v1a2 ロジック変更 // はじめに開始タグを書き換えて、そこから要素名を取得し、終了タグを探しにかかる。 // デリミタに正規表現 [ \t\n/>] が使える。 // 終了タグ上で実行したときはまず開始タグを探し、改めて終了タグを探す。∴遅い。 // 02/11/24 v1a1 開発開始 // 両タグの座標を取得してから書き換える。 // 開始タグを書き換えると終了タグの座標がずれるかもなので、終了タグから書き換える。 // ∴要素名の取得に strstr() を使うことになり、タグ内での改行に対応できない。 // 範囲選択時は単に解除 // タグ外実行時はカーソル位置を支配する要素を見つける ■ 高速化実験 02/11/04 ascii() は先頭の文字のコードを返すから、次のような場合は midstr() の代わりに rightstr() が使える。後者の方が速い。 IgnoreCase: ##i = strlen($$1); while (##i) { ##i = ##i - 1; ##c = ascii(midstr($$1, ##i, 1)); if (##c < 'a' || ##c > 'z') $$r = char(##c) + $$r; else $$r = "[" + char(##c) + char(##c - 32) + "]" + $$r; } return $$r; IgnoreCase2: ##i = strlen($$1); while (##i) { ##c = ascii(rightstr($$1, ##i)); if (##c < 'a' || ##c > 'z') $$r = $$r + char(##c); else $$r = $$r + "[" + char(##c) + char(##c - 32) + "]"; ##i = ##i - 1; } return $$r; ついでに言うと if (##c < 97 || ##c > 122) より if (##c < 'a' || ##c > 'z') の方がわずかに速い。 ■ 余計な空白 02/11/04 要素名の前に空白を入れるの( < HTML> とか とか)は合法か?  ・HTML … 仕様書の SGML 宣言とか調べてみたけどよくわからん。 HTML じゃなくて SGML を調べなきゃダメか?   IE6 で実験したらタグとして認識されなかった。ということは、そんな書き方は通用してないと見ていいだろう。  ・DNML … 合法。 ■ HTML4 以外のタグ 02/11/03 ・Another HTML-lint が知っているタグ  http://openlab.ring.gr.jp/k16/htmllint/tagslist.cgi ↑の中で、「終了タグなし」として定義されている場合があり、 HTML4 にないもの: atop bgsound changed choose embed fig image hype keygen left nextid nobr over overlay plaintext range right spacer spot tab wbr ・DNML  http://hp.vector.co.jp/authors/VA015183/dnml/ ざっと見た感じ、 ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ if (code >= 'A' && code <= 'Z') $name = $name + char(code + 32); else if (code >= 'a' && code <= 'z') $name = $name + char(code); else if (code >= '1' && code <= '6') $name = $name + char(code); // SGML 的には - . : _ も名前文字として使えることになってるが、そんな要素名はないので無視。 else break; right; } $tag = gettext(##tbx, ##tby, x, y); moveto ##tbx, ##tby; if (##endtag) { #tagtype を判定 } else { #tagtype を判定 } ■ 実験 02/07/30 disabledraw; $tag = "= 0) #noendflag = 1; else #noendflag = 0; ■ CloseTag.mac 02/07/28 タグの要素名が得られればいいのだから、属性を含むタグ全体にヒットさせる必要はない。 $elemexp[0] = "[a-zA-Z0-9]+"; searchup "|[ \\n][^>]*>)", regular; searchup "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~