Test the message arrow of PlantUML sequence diagram.
- @if(0)==(0) echo off
- @rem http://computer-technology.hateblo.jp/entry/20131025/p1
- setlocal
- setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
-
- @rem Description:
- @rem Test the message arrow of PlantUML sequence diagram.
-
- @rem Usage:
- @rem arrowsTest.bat <arrowGroupNumber>
-
- @rem Options:
- @rem arrowGroupNumber
- @rem 1 : "->" group.
- @rem 2 : "-/" group.
- @rem 3 : "-\" group.
-
- @rem ####################
- @rem Batch.
- @rem ####################
-
- set "DebugPrint=false"
-
- @rem ....................
- @rem Batch main.
- @rem ....................
- set rv=11
- if "!DebugPrint!"=="true" call :L_BAT_Output_Args %*
- call :Lc_JS %*
-
- @rem ....................
- @rem Exit.
- @rem ....................
- @rem echo.
- @rem pause
- @rem echo Press any key to exit.
- @rem pause>nul
- exit /b !rv!
- goto :eof
-
-
- @rem ....................
- @rem Output Args.
- @rem ....................
- :L_BAT_Output_Args
- @rem echo BAT %0 %* ....................
- set /a y=0
- for %%z in (
- %*
- ) do (
- set /a y=!y!+1
- echo BAT %%!y!=%%~z.
- )
- set /a rv=0
- goto :eof
-
-
- @rem ....................
- @rem Call JScript.
- @rem ....................
- :Lc_JS
- if "!DebugPrint!"=="true" echo BAT %0 %* ....................j
- set "jsargs=%*"
- if "!jsargs!"=="" (
- cscript.exe //nologo //e:JScript "%~f0"
- ) else (
- cscript.exe //nologo //e:JScript "%~f0" !jsargs!
- )
- if "!DebugPrint!"=="true" call :L_echoErrorLevel
- goto :eof
-
-
- @rem ....................
- @rem Echo ErrorLevel.
- @rem ....................
- :L_echoErrorLevel
- @rem echo BAT L_echoErrorLevel ....................
- echo BAT %0 errorlevel=!errorlevel!
- @rem echo.
- goto :eof
-
-
- @end
-
-
- // ####################
- // JScript.
- // ####################
-
-
- var DebugPrint = false;
-
- var fso = new ActiveXObject("Scripting.FileSystemObject");
-
-
- // ....................
- // Output Args.
- // ....................
- function Output_Args(jsargs) {
- // WScript.Echo("JS Output_Args ....................");
- WScript.Echo("JS [" + jsargs.length + "]" + jsargs + ".");
- for (var idx = 0; idx < jsargs.length; ++idx) {
- WScript.Echo("JS Args[" + idx + "]=" + jsargs[idx] + ".");
- }
- return 0;
- }
-
-
- // ....................
- // Unknown arg.
- // ....................
- function UnknownArg(jsargs) {
- WScript.Echo("JS UnknownArg ....................");
- Output_Args(jsargs);
- return 1;
- }
-
-
- // ....................
- // arrowsTest : Test the message arrow of PlantUML sequence diagram.
- // ....................
- function arrowsTest(jsargs) {
- if (DebugPrint == true) {
- WScript.Echo("JS arrowsTest ....................");
- Output_Args(jsargs);
- }
-
- // message arrow shape pattern.
- var arrowGroups = [
- [],
- [ // arrowGroup 1.
- [ // arrowType
- "->",
- "<-",
- "<->",
- ],
- [
- "->>",
- "<<-",
- "<<->>",
- ],
- ],
- [ // arrowGroup 2.
- [
- "-/",
- "/-",
- "/-/",
- ],
- [
- "-//",
- "//-",
- "//-//",
- ],
- ],
- [ // arrowGroup 3.
- [
- "-\\",
- "\\-",
- "\\-\\",
- ],
- [
- "-\\\\",
- "\\\\-",
- "\\\\-\\\\",
- ],
- ],
- ];
-
- // message arrow symbol pattern.
- var symbols = [
- ["", "" ],
- ["o", "" ],
- ["", "o"],
- ["o", "o"],
- ["x", "" ],
- ["", "x"],
- ["x", "x"],
- ["o", "x"],
- ["x", "o"],
- ];
-
- // Classes at both ends of the arrow.
- var classes = {
- "" : ["Bob", "Alice" ],
- "o" : ["Bob_o", "Alice_o"],
- "x" : ["Bob_x", "Alice_x"]
- };
-
-
- // Start definition of sequence diagram.
- WScript.Echo("@startuml");
-
- WScript.Echo("participant Bob_x");
- WScript.Echo("participant Bob_o");
- WScript.Echo("participant Bob");
- WScript.Echo("participant Alice");
- WScript.Echo("participant Alice_o");
- WScript.Echo("participant Alice_x");
- WScript.Echo("");
-
- WScript.Echo("note over Bob_x, Alice_x");
- WScript.Echo(" There are no arrows starting with x in the sequence diagram.");
- WScript.Echo(" PlantUML will follow the instructions.");
- WScript.Echo("end note");
- WScript.Echo("");
-
- // for (var arrowGroupNumber in arrowGroups) {
- var arrowGroupNumber = jsargs[0];
- for (var arrowTypeIdx in arrowGroups[arrowGroupNumber]) {
- WScript.Echo("== " + arrowGroups[arrowGroupNumber][arrowTypeIdx][0].replace(/\\/g, "\\\\") + " ==");
- for (var symbolIdx in symbols) {
- for (var arrowShapeIdx in arrowGroups[arrowGroupNumber][arrowTypeIdx]) {
- var arrowShape = ""
- + symbols[symbolIdx][0]
- + arrowGroups[arrowGroupNumber][arrowTypeIdx][arrowShapeIdx]
- + symbols[symbolIdx][1]
- ;
-
- var msgCmd = sprintf("%-9s %-9s %-9s",
- classes[symbols[symbolIdx][0]][0],
- arrowShape,
- classes[symbols[symbolIdx][1]][1]);
- var msgTxt = msgCmd.replace(/ +/g, " ");
-
- WScript.Echo(sprintf("%s : %d-%d-%d : %s",
- msgCmd,
- (parseInt(arrowGroupNumber) - 1) * 2 + 1 + parseInt(arrowTypeIdx),
- symbolIdx, arrowShapeIdx, msgTxt));
- }
- }
- // }
- WScript.Echo("|||");
- WScript.Echo("");
- }
-
- WScript.Echo("note over Bob_x, Alice_x");
- WScript.Echo("Drawn by PlantUML version:");
- WScript.Echo(getPlantUmlVersion());
- WScript.Echo("end note");
- WScript.Echo("");
-
- // Finish defining the sequence diagram.
- WScript.Echo("@enduml");
-
- return 0;
- }
-
-
- // https://kujirahand.com/blog/index.php?JScript%E3%81%A7%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E5%AE%9F%E8%A1%8C
- function getPlantUmlVersion() {
- var shell = new ActiveXObject("WScript.Shell");
- // コマンドを実行
- var oe = shell.Exec("java -jar plantuml.jar -v");
- var r = oe.StdErr.ReadAll();
- return r;
- }
-
-
- // https://qiita.com/akinomyoga/items/ccd58731743aa37e0538
- // agh.sprintf.js
- /* ----------------------------------------------------------------------------
-
- Author: K. Murase (akinomyoga)
-
- Changes
-
- * 2015-05-29 KM created git repository
- * 2014-12-25 KM 様々な言語での実装を確認
- * 2013-09-05 KM added descriptions
- * 2013-09-01 KM first version
- * 2013-09-01 KM created
-
- ------------------------------------------------------------------------------
-
- License: The MIT License (MIT)
-
- Copyright (c) 2013-2015 K. Murase (akinomyoga)
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
- ----------------------------------------------------------------------------*/
-
- /**
- * @section sprintf.format 書式指定
- * 書式は以下の形式で指定する。
- * '%' \<pos\>? \<flag\> \<width\> \<precision\>? \<type\>? \<conv\>
- *
- * 位置指定子 \<pos\> は引数の番号を指定する。
- * フラグ \<flag\> は出力の見た目を細かく指定する。
- * 幅 \<width\> は出力時の最小文字数を指定する。
- * 精度 \<precision\> は内容をどれだけ詳しく出力するかを指定する。
- * サイズ指定子 \<type\> は引数のサイズ・型を指定する。
- * 変換指定子 \<conv\> は出力する形式を指定する。
- *
- * @subsection sprintf.format.pos 位置指定子 (POSIX)
- * 位置指定子は以下の形式を持つ。
- * \<pos\> := /\d+\$/
- * 整数で引数の番号を指定する。書式指定文字列の次に指定した引数の番号が 1 である。
- *
- * @subsection sprintf.format.flag フラグ
- * フラグは以下の形式を持つ。
- * \<flag\> := ( /[-+ 0#']/ | /\=./ ) +
- *
- * '-' (標準) 左寄せを意味する。既定では右寄せである。
- * '+' (標準) 非負の数値に正号を付ける事を意味する。
- * '#' (標準) 整数の場合、リテラルの基数を示す接頭辞を付ける。
- * 但し、値が 0 の時は接頭辞を付けない。
- * conv = o, x, X のそれぞれに対して "0", "0x", "0X" が接頭辞となる。
- *
- * 浮動小数点数 conv = f, F, e, E, g, G, a, A の場合は、
- * 整数 (precision = 0) に対しても小数点を付ける (例 "123.") 事を意味する。
- * conv = g, G については小数末尾の 0 の連続を省略せずに全て出力する。
- * ' ' (標準) 非負の数値の前に空白を付ける事を意味する。
- * これは出力幅が width で指定した幅を超えても必ず出力される空白である。
- * '0' (標準) 左側の余白を埋めるのに 0 を用いる。但し、空白と異なり 0 は符号や基数接頭辞の右側に追加される。
- * "'" (SUSv2) conv = d, i, f, F, g, G の整数部で桁区切 (3桁毎の ",") を出力する事を意味する。
- * 但し、flag 0 で指定される zero padding の部分には区切は入れない。
- *
- * 参考: 野良仕様で以下の様なものもあるが、ここでは実装しない。
- * '=?' (strfmon) 余白に使う文字の指定
- * ',' (Python) 桁区切。→ "'" (SUSv2) に同じ
- * (+ Java, Python-3.1)
- * '<' (Python) 左寄せ。'?<' として余白文字を指定できる。
- * → '-' (標準) に同じ
- * '>' (Python) 右寄せ。'?>' として余白文字を指定できる。
- * → 既定 (標準)
- * '^' (Python) 中央揃え。'?^' として余白文字を指定できる。
- * '=' (Python) 整数型において、符号の後に padding を挿入する
- * →これは %.3d 等とする事に等価である。
- * '-' (Python) 負号のみ表示 → 既定 (標準)
- * "'?" (PHP) 余白文字の指定。
- * '(' (Java) 負の数を "()" で括る。
- *
- * @subsection sprintf.format.width 幅指定子
- * 幅指定子は以下の形式を持つ。
- * \<width\> := /\d+/ | '*' | '*' /\d+/ '$'
- *
- * /\d+/ (標準) 最小幅を整数で指定する。
- * '*' (標準) 次の引数を読み取って最小幅とする。
- * '*' /\d+/ '$' (POSIX) 指定した番号の引数を最小幅とする。
- *
- * @subsection sprintf.format.precision 精度指定子
- * 精度指定子は以下の形式を持つ。
- * \<precision\> := /\d+/ | '*' | '*' /\d+/ '$'
- *
- * /\d+/ (標準) 精度を整数で指定する。
- * '*' (標準) 次の引数を読み取って精度とする。
- * '*' /\d+/ '$' (POSIX) 指定した番号の引数を精度とする。
- *
- * 整数の場合は精度で指定した桁だけ必ず整数を出力する。例えば、精度 4 の場合は "0001" など。
- * 精度を指定した時はフラグで指定した '0' は無視される。
- *
- * 浮動小数点数 conv = f, F, e, E, a, A の場合は小数点以下の桁数を指定する。
- * 浮動小数点数 conv = g, G の場合は有効桁数を指定する。
- * conv = f, F, e, E, g, G に対しては既定値は 6 である。
- * conv = a, A については倍精度浮動小数点数の16進桁数である 13 が既定値である。
- *
- * 文字列の場合は最大出力文字数を指定する。この文字数に収まらない部分は出力されずに無視される。
- *
- * @subsection sprintf.format.type サイズ指定子
- * サイズ指定子は以下の何れかである。
- *
- * + --------- 整数 ---------- + ------- 浮動小数点数 ------- + -------- 文字 ---------- +
- * | 本来 (規格) 実装 註 | 本来 (規格) 実装 註 | 本来 (規格) 実装 註 |
- * ----- + ------------------------- + ---------------------------- + ------------------------ +
- * 既定 | int (標準) double#1 | 既定 (標準) double | 既定 (標準) unicode |
- * 'hh' | char (C99) 8bit | float (agh) float#4 | char (agh) ascii |
- * 'h' | short (標準) 16bit | float (agh) float#4 | char (MSVC) ascii |
- * 'l' | long (標準) 32bit | double (C99) double | wint_t (C99) unicode#6 |
- * 'll' | long long (C99) 32bit | long double (agh) double#5 | -- -- -- |
- * 't' | ptrdiff_t (C99) 32bit#2 | -- -- -- | -- -- -- |
- * 'z' | size_t (C99) 32bit#2 | -- -- -- | -- -- -- |
- * 'I' | ptrdiff_t (MSVC) 32bit#2 | -- -- -- | -- -- -- |
- * | size_t | -- -- -- | -- -- -- |
- * 'I32' | 32bit (MSVC) 32bit | -- -- -- | -- -- -- |
- * 'q' | 64bit (BSD) 64bit#3 | -- -- -- | -- -- -- |
- * 'I64' | 64bit (MSVC) 64bit#3 | -- -- -- | -- -- -- |
- * 'j' | intmax_t (C99) double#1 | -- -- -- | -- -- -- |
- * 'L' | -- -- -- | long double (標準) double#5 | -- -- -- |
- * 'w' | -- -- -- | long double (agh) double#5 | wchar_t (MSVC) unicode |
- * ----- + ------------------------- + ---------------------------- + ------------------------ +
- *
- * #1 JavaScript の数値は内部的には double なので、
- * サイズ指定子を省略した場合はこの double で表現される整数として変換を行う。
- * #2 JavaScript で 64bit 整数は厳密に取り扱う事が出来ないので、32bit を native な整数とする。
- * #3 JavaScript では 64bit 整数は厳密に取り扱う事が出来ない。
- * 取り敢えず 64bit 整数として出力はするものの、巨大な整数では下の方の桁が正確ではない。
- *
- * #4 規格にないが独自拡張で、h/hh が指定された時は float の精度に落としてから出力する。
- * (C 言語では float の可変長引数は double に変換されるからそもそも float で指定できない)。
- * #5 規格上は long double だが JavaScript では long double は取り扱えないので、
- * double と同じ取扱とする。
- *
- * #6 POSIX を見ると %lc の引数は wchar_t[2] { wint_t(), null } と書かれている気がする? [要確認]
- *
- * 参考: 以下の様な野良サイズ指定子もある。
- * 'n' (Ocaml) native int
- *
- * @subsection sprintf.format.conv 変換指定子
- * 引数の型及び出力の形式を指定する。以下の何れかの値を取る。
- *
- * 'd', 'i' (標準) 10進符号付き整数
- * 'o' (標準) 8進符号無し整数
- * 'u' (標準) 10進符号無し整数
- * 'x', 'X' (標準) 16進符号無し整数 (lower/upper case, 0xa/0XA など)
- * 'f', 'F' (標準) 浮動小数点数 (lower/upper case, inf/INF など)
- * 'e', 'E' (標準) 浮動小数点数指数表記 (lower/upper case, 1e+5/1E+5 など)
- * 'g', 'G' (標準) 浮動小数点数短い表記 (lower/upper case, 1e+5/1E+5 など)
- * 'a', 'A' (C99) 浮動小数点数16進表現 (lower/upper case, 1p+5/1P+5 など)
- * 'c' (標準) 文字
- * 'C' (XSI) 文字 (本来 wchar_t 用だがこの実装では c と区別しない)
- * 's' (標準) 文字列
- * 'S' (XSI) 文字列 (本来 wchar_t 用だがこの実装では s と区別しない)
- * 'p' (標準) ポインタ値。この実装では upper hexadecimal number で出力。
- * 'n' (標準) 今迄の出力文字数を value[0] に格納
- * '%' (標準) "%" を出力
- *
- * 参考: 野良仕様で以下の様なものもあるが、ここでは実装しない。
- * 'b' (Ruby) 2進符号付き整数。(+ Python, Perl, PHP, D, Haskell)
- * (Go) では浮動小数点数に対して decimalless scientific notation with 2進指数
- * 'B' (Ruby) 2進符号付き整数。(+ Python, Perl)
- * 'n' (Python) 数値。ロカールに従った出力を行う(桁区切など)。
- * '%' (Python) 百分率。数値を百倍して解釈し 'f' 変換指定子で出力する。
- * 'D' (Perl) 'ld' に同じ。
- * 'U' (Perl) 'lu' に同じ。
- * 'O' (Perl) 'lo' に同じ。
- * 'U' (Go) 'U+%04d' に同じ。Unicode code point の為。
- * 't' (Go) true/false
- * 'b', 'B' (Java) true/false (+ OCaml)
- * 'h', 'H' (Java) null/'%x'
- *
- * 'q' (Bash) 文字/文字列をリテラル (quoted string) として出力。 (+ Go Lua)
- * Go では文字(整数)は '' で、文字列は "" で囲む。Lua では '' で囲む。
- * 'C' (OCaml) 文字リテラル '' として出力
- * 'S' (OCaml) 文字列リテラル "" として出力
- * 'T' (Go) typename
- * 'v' (Go) default format (+ Haskell)
- * 'p' (Ruby) Object#inspect の結果を載せる。
- *
- * 'n' (Java) 改行
- * 'a', 't' (OCaml) ? (二つ引数を取って、引数2を引数1に対し出力?)
- * ',' (OCaml) 何も出力しない
- * '@' (OCaml) '@' を出力。
- * '!' (OCaml) 出力先を flush する。
- *
- * @subsection sprintf.format.ref References
- * Wikipedia en <a href="https://en.wikipedia.org/wiki/Printf_format_string">printf format string - Wikipedia</a>
- * POSIX printf(1) <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html">printf</a>
- * POSIX printf(1) <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html#tag_05">File Format Notation</a>
- * POSIX printf(3) <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html">fprintf</a>
- * MSC 位置指定子 <a href="http://msdn.microsoft.com/ja-jp/library/bt7tawza(v=vs.90).aspx">printf_p の位置指定パラメータ</a>
- * MSC サイズ指定子 <a href="http://msdn.microsoft.com/ja-jp/library/vstudio/tcxf1dw6.aspx">サイズ指定</a>
- *
- * Python [[6.1. string ? 一般的な文字列操作 ? Python 3.4.2 ドキュメント>http://docs.python.jp/3/library/string.html#format-specification-mini-language]]
- * PHP [[PHP: sprintf - Manual>http://php.net/manual/ja/function.sprintf.php]]
- * Perl [[sprintf - perldoc.perl.org>http://perldoc.perl.org/functions/sprintf.html]]
- * D言語 [[std.format - D Programming Language - Digital Mars>http://dlang.org/phobos/std_format.html#format-string]]
- * Lua [[Lua 5.1 Reference Manual>http://www.lua.org/manual/5.1/manual.html#pdf-string.format]]
- * Haskell [[Text.Printf>http://hackage.haskell.org/package/base-4.7.0.2/docs/Text-Printf.html]]
- * Go [[fmt - The Go Programming Language>http://golang.org/pkg/fmt/]]
- * Java [[Formatter (Java Platform SE 7 )>http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax]]
- * R (wrapper for C printf) [[sprintf {base} | inside-R | A Community Site for R>http://www.inside-r.org/r-doc/base/sprintf]]
- * OCaml [[Printf>http://caml.inria.fr/pub/docs/manual-ocaml/libref/Printf.html]]
- */
-
- /*
- * その他の書式指定の文法について
- * - terminfo の setaf 等で使われている文法について
- * %? %t %e %; 条件分岐
- * %| %! %- %< 演算子
- * %{ ... } リテラル
- * - date コマンド
- * - strfmod
- * - zsh PS1
- * - GNU screen
- */
-
- // 実装:
- // * 解析は正規表現を使えば良い。
- // * 出力結果の構成
- // <左余白> <符号> <ゼロ> <中身> <右余白>
- // 計算の順番としては、<符号>+<中身> のペアを決定してから、<ゼロ> または <余白> を付加すれば良い。
-
- (function(__exports) {
- // 本来 this にグローバルオブジェクトが入るはず。
- // もし空だった場合はこのスクリプトを呼び出したときの this を入れる。
- var __global = this || __exports || {};
- if (typeof __global.agh !== 'undefined')
- __exports = __global.agh;
- else if (typeof __global.module !== 'undefined' && typeof __global.module.exports != 'undefined')
- __exports = __global.module.exports;
- else if (__exports == null)
- __exports = __global.agh = {};
-
- function repeatString(s, len) {
- if (len <= 0) return "";
- var ret = "";
- do if (len & 1) ret += s; while ((len >>= 1) >= 1 && (s += s));
- return ret;
- }
-
- //---------------------------------------------------------------------------
- // サイズ指定子達
-
- var INT32_MOD = 0x100000000;
- var INT32_MIN = -0x80000000;
- var INT32_MAX = +0x7FFFFFFF;
- var INT64_MOD = INT32_MOD * INT32_MOD;
- var INT64_MIN = -INT64_MOD / 2.0;
- var INT64_MAX = -INT64_MIN - 1;
-
- function roundTowardZero(value) {
- return value < 0 ? Math.ceil(value) : Math.floor(value);
- }
-
- function getIntegerValue(value, type) {
- // 整数は内部的には double で表現されている。
- // ビット演算は 32bit 符号付整数として実行される。
- value = roundTowardZero(value);
- switch (type) {
- case 'hh': // C99 char (8bit signed)
- value &= 0xFF;
- return value >= 0x80 ? value - 0x100 : value;
- case 'h': // short (16bit signed)
- value &= 0xFFFF;
- return value >= 0x8000 ? value - 0x10000 : value;
- case 'l': // C89 long (32bit signed) (ビット演算を使うと変になる)
- case 'z': // C99 size_t
- case 't': // C99 ptrdiff_t
- case 'I32': // MSVC __int32
- case 'I': // MSVC ptrdiff_t/size_t
- value %= INT32_MOD;
- if (value < INT32_MIN)
- value += INT32_MOD;
- else if (value > INT32_MAX)
- value -= INT32_MOD;
- return value;
- case 'll': // C99 long long (64bit signed)
- case 'I64': // MSVC __int32
- case 'q': // BSD quad word
- case 'L': // agh exntesion
- value %= INT64_MOD;
- if (value < INT64_MIN)
- value += INT64_MOD;
- else if (value > INT64_MAX)
- value -= INT64_MOD;
- return value;
- case 'j': default: // 変換無し (double の整数)
- return value;
- }
- }
-
- function getUnsignedValue(value, type) {
- // 整数は内部的には double で表現されている。
- // ビット演算は 32bit 符号付整数として実行される。
- value = roundTowardZero(value);
- switch (type) {
- case 'hh': // 8bit unsigned
- value &= 0xFF;
- return value;
- case 'h': // 16bit unsigned
- value &= 0xFFFF;
- return value;
- case 'l': // C89 long (32bit unsigned) (ビット演算を使うと変になる)
- case 'z': // C99 size_t
- case 't': // C99 ptrdiff_t
- case 'I32': // MSVC __int32
- case 'I': // MSVC ptrdiff_t/size_t
- value %= INT32_MOD;
- return value < 0 ? value + INT32_MOD : value;
- case 'll': // C99 long long (64bit unsigned)
- case 'I64': // MSVC __int32
- case 'q': // BSD quad word
- case 'L': // agh exntesion
- value %= INT64_MOD;
- return value < 0 ? value + INT64_MOD : value;
- case 'j': default: // double の整数の 2 の補数??
- if (value < 0) {
- // 例 -0x80 ~ -0x41 → 7 ~ 6+epsilon → nbits = 8, mod = 0x100
- var nbits = value < INT32_MIN ? 1 + Math.ceil(Math.LOG2E * Math.log(-value)) : 32;
- var mod = Math.pow(2, nbits);
- value += mod;
- }
- return value;
- }
- }
-
- function getFloatValue(value, type) {
- if (type === 'h' || type === 'hh') {
- var sgn = value < 0 ? -1 : 1;
- var exp = Math.floor(Math.LOG2E * Math.log(sgn * value));
- var scale = Math.pow(2, exp - 23); // float (exp = 0) は小数点以下2進23桁まで有効
- value = (0 | value / scale) * scale;
- }
-
- return value;
- }
-
- function getCharValue(value, type) {
- value |= 0;
- if (type === 'h' || type === 'hh') {
- value &= 0xFF;
- }
- return value;
- }
-
- //---------------------------------------------------------------------------
- // 変換指定子達
-
- /**
- * @section \<conv\>
- * 引数の型及び出力の形式を指定します。
- * - 'd', 'i' 10進符号付き整数
- * - 'o' 8進符号無し整数
- * - 'u' 10進符号無し整数
- * - 'x', 'X' 16進符号無し整数
- */
-
- var groupIntegerRegs = [
- /(...)(?!$)/g,
- /(^.|...)(?!$)/g,
- /(^..|...)(?!$)/g
- ];
- function groupInteger(text, flag) {
- if (text.length < 4 || !/\'/.test(flag))
- return text;
- else
- return text.replace(groupIntegerRegs[text.length % 3], "$1,");
- }
-
- var xdigits = "0123456789abcdef";
- function convertInteger(value, flag, precision, base) {
- var out = '';
- do {
- out = xdigits.charAt(value % base) + out;
- value = Math.floor(value / base);
- } while (value > 0);
-
- if (precision != null)
- out = repeatString('0', precision - out.length) + out;
-
- return out;
- }
- function convertDecimal(value, flag, precision, type) {
- return groupInteger(convertInteger(value, flag, precision, 10), flag);
- }
- function convertOctal(value, flag, precision, type) {
- return convertInteger(value, flag, precision, 8);
- }
- function convertLowerHex(value, flag, precision, type) {
- return convertInteger(value, flag, precision, 16);
- }
- function convertUpperHex(value, flag, precision, type) {
- return convertInteger(value, flag, precision, 16).toUpperCase();
- }
-
- /**
- * - 'f', 'F' 浮動小数点数 (lower/upper case, inf/INF など)
- * - 'e', 'E' 浮動小数点数指数表記 (lower/upper case, 1e+5/1E+5 など)
- * - 'g', 'G' 浮動小数点数短い表記 (lower/upper case, 1e+5/1E+5 など)
- * - 'a', 'A' 浮動小数点数16進表現 (lower/upper case, 1p+5/1P+5 など)
- */
-
- var logTable = [];
- logTable[ 2] = Math.LOG2E;
- logTable[10] = Math.LOG10E;
- logTable[16] = Math.LOG2E / 4;
- function frexp(value, base) {
- if (value === 0) return [0, 0];
-
- var exp = 1 + Math.floor(logTable[base] * Math.log(value));
- value = value * Math.pow(base, -exp);
-
- // 際どいずれが起きるので補正
- if (value * base < 1) {
- value *= base;
- exp--;
- } else if (value >= 1) {
- value /= base;
- exp++;
- }
-
- return [value, exp];
- }
-
- var regCarryReach = []; // 末尾の 9 の並び, 繰上到達距離測定用
- regCarryReach[10] = /9*$/;
- regCarryReach[16] = /f*$/;
- function generateFloatingSequence(value, precision, base) {
- // value [0, 1) の数値
- var seq = '';
- while (--precision > 0)
- seq += xdigits.charAt(0 | (value = value * base % base));
-
- // 最後の数字は四捨五入
- // (0-10 の整数になるので繰り上がり処理が必要)
- var last = Math.round(value * base % base);
- if (last == base) {
- var cd = regCarryReach[base].exec(seq)[0].length;
- if (cd < seq.length) {
- // 繰り上がり
- var iinc = seq.length - cd - 1;
- seq = seq.slice(0, iinc) + xdigits.charAt(1 + (0 | seq.charAt(iinc))) + repeatString('0', cd + 1);
- } else {
- // 全て 9 の時 → exp更新, seq = 1000...
- seq = '1' + repeatString('0', cd + 1);
- }
- } else {
- seq += xdigits.charAt(last);
- }
- return seq;
- }
-
- function omitTrailingZero(text, flag) {
- return text.replace(/(\.[\da-f]*?)0+$/, function($0, $1) {
- if ($1 && $1.length > 1)
- return $1;
- else
- return /#/.test(flag) ? '.' : '';
- });
- }
- function omitTrailingZeroE(text, flag) {
- return text.replace(/(\.\d*?)0+e/, function($0, $1) {
- if ($1 && $1.length > 1)
- return $1 + 'e';
- else
- return /#/.test(flag) ? '.e' : 'e';
- });
- }
-
- function convertScientific(value, flag, precision, type) { // conv = e E
- if (isNaN(value))
- return 'nan';
- else if (!isFinite(value))
- return 'inf';
-
- if (precision == null) precision = 6;
-
- var buff = frexp(value, 10);
- var fr = buff[0], exp = buff[1] - 1;
- var man = generateFloatingSequence(fr, 1 + precision, 10);
- if (man.length > precision + 1) {
- // 99..99 から 100..00 に繰り上がった時
- man = man.slice(0, -1);
- exp++;
- }
-
- if (precision > 0 || /#/.test(flag))
- man = man.slice(0, 1) + '.' + man.slice(1);
-
- if (exp < 0)
- exp = 'e-' + (1000 - exp).toString().slice(1);
- else
- exp = 'e+' + (1000 + exp).toString().slice(1);
- return man + exp;
- }
- function convertScientificHex(value, flag, precision, type) { // conv = a A
- if (isNaN(value))
- return 'nan';
- else if (!isFinite(value))
- return 'inf';
-
- if (precision == null)
- precision = type === 'h' || type === 'hh' ? 6 : 13;
-
- var buff = frexp(value, 2);
- var fr = buff[0], exp = buff[1] - 1;
- var man = generateFloatingSequence((1 / 8) * fr, precision + 1, 16);
- if (man.length > precision + 1) {
- man = man.slice(0, -1);
- exp++;
- }
-
- if (man.length > 1 || /#/.test(flag))
- man = man.slice(0, 1) + '.' + man.slice(1);
-
- man = omitTrailingZero(man, flag);
-
- if (exp < 0)
- exp = 'p-' + (1000 - exp).toString().slice(1);
- else
- exp = 'p+' + (1000 + exp).toString().slice(1);
- return man + exp;
- }
- function convertFloating(value, flag, precision, type) { // conv = f F
- if (isNaN(value))
- return 'nan';
- else if (!isFinite(value))
- return 'inf';
-
- if (precision == null) precision = 6;
-
- if (value >= 1.0) {
- var buff = frexp(value, 10);
- var fr = buff[0], exp = buff[1];
- } else {
- var fr = value / 10, exp = 1;
- }
-
- var man = generateFloatingSequence(fr, exp + precision, 10);
- if (precision > 0 || /#/.test(flag)) {
- var point = man.length - precision;
- man = groupInteger(man.slice(0, point), flag) + '.' + man.slice(point);
- } else
- man = groupInteger(man, flag);
-
- return man;
- }
- function convertCompact(value, flag, precision, type) { // conv = g G
- if (isNaN(value))
- return 'nan';
- else if (!isFinite(value))
- return 'inf';
-
- if (precision == null)
- precision = 6;
- else if (precision < 1)
- precision = 1;
-
- if (value < 1e-4 || Math.pow(10, precision) <= value + 0.5) {
- // scientific
- var result = convertScientific(value, flag, precision - 1, type);
- if (/#/.test(flag))
- return result;
- else
- return omitTrailingZeroE(result, flag);
- } else {
- // floating point
- var buff = frexp(value, 10);
- var fr = buff[0], exp = buff[1];
-
- if (precision < 1) precision = 1;
- var man = generateFloatingSequence(fr, precision, 10);
- var point = man.length - (precision - exp); // 小数点挿入位置。末端からの位置が繰り上がり不変。
- // assert(exp <= precision);
- // assert(man.length == precision || man.length == precision + 1)
- // assert(point <= man.length);
- if (point > 0) {
- if (point < man.length || /#/.test(flag))
- man = groupInteger(man.slice(0, point), flag) + '.' + man.slice(point, precision);
- } else {
- man = '0.' + repeatString('0', -point) + man.slice(0, precision);
- }
-
- if (/#/.test(flag))
- return man;
- else
- return omitTrailingZero(man, flag);
- }
- }
-
- function convertCompactU (value, flag, precision, type) { return convertCompact (value, flag, precision, type).toUpperCase(); }
- function convertFloatingU (value, flag, precision, type) { return convertFloating (value, flag, precision, type).toUpperCase(); }
- function convertScientificU (value, flag, precision, type) { return convertScientific (value, flag, precision, type).toUpperCase(); }
- function convertScientificHexU(value, flag, precision, type) { return convertScientificHex(value, flag, precision, type).toUpperCase(); }
-
- /**
- * - 'c', 'C' 文字
- * - 's', 'S' 文字列
- * - 'n' 今迄の出力文字数を value[0] に格納
- * - '%' % を出力
- */
-
- function convertChar(value, flag, precision, type) {
- return String.fromCharCode(value);
- }
- function convertString(value, flag, precision, type) {
- if (value == null)
- value = value === undefined ? '(undefined)' : '(null)';
- else
- value = value.toString();
-
- if (precision != null)
- value = value.slice(0, precision);
-
- return value;
- }
- function convertOutputLength(value, flag, precision, type, outputLength) { // conv = n
- value[0] = getIntegerValue(outputLength, type);
- return '';
- }
- function convertEscaped(value, flag, precision, type) { return '%'; }
-
- //---------------------------------------------------------------------------
-
- function prefixOctal(flag) { return /#/.test(flag) ? '0' : ''; }
- function prefixLHex(flag) { return /#/.test(flag) ? '0x' : ''; }
- function prefixUHex(flag) { return /#/.test(flag) ? '0X' : ''; }
- function prefixFloatLHex(flag) { return '0x'; }
- function prefixFloatUHex(flag) { return '0X'; }
- function prefixPointerHex(flag) { return '0x'; }
-
- var conversions = {
- d: {getv: getIntegerValue , integral: true , signed: true , prefix: null , conv: convertDecimal },
- i: {getv: getIntegerValue , integral: true , signed: true , prefix: null , conv: convertDecimal },
- u: {getv: getUnsignedValue, integral: true , signed: false, prefix: null , conv: convertDecimal },
- o: {getv: getUnsignedValue, integral: true , signed: false, prefix: prefixOctal , conv: convertOctal },
- x: {getv: getUnsignedValue, integral: true , signed: false, prefix: prefixLHex , conv: convertLowerHex },
- X: {getv: getUnsignedValue, integral: true , signed: false, prefix: prefixUHex , conv: convertUpperHex },
- e: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertScientific },
- E: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertScientificU },
- f: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertFloating },
- F: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertFloatingU },
- g: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertCompact },
- G: {getv: getFloatValue , integral: false, signed: true , prefix: null , conv: convertCompactU },
- a: {getv: getFloatValue , integral: false, signed: true , prefix: prefixFloatLHex , conv: convertScientificHex },
- A: {getv: getFloatValue , integral: false, signed: true , prefix: prefixFloatUHex , conv: convertScientificHexU},
- c: {getv: getCharValue , integral: false, signed: false, prefix: null , conv: convertChar },
- C: {getv: getCharValue , integral: false, signed: false, prefix: null , conv: convertChar },
- s: {getv: null , integral: false, signed: false, prefix: null , conv: convertString },
- S: {getv: null , integral: false, signed: false, prefix: null , conv: convertString },
- p: {getv: getUnsignedValue, integral: false, signed: false, prefix: prefixPointerHex, conv: convertUpperHex },
- n: {getv: null , integral: false, signed: false, prefix: null , conv: convertOutputLength },
- '%': {noValue: true , integral: false, signed: false, prefix: null , conv: convertEscaped }
- };
-
- function printf_impl(fmt) {
- // ※arguments の fmt を除いた部分の番号は 1 から始まり、
- // 位置指定子も 1 から始まるので、位置番号はそのまま arguments の添字に指定して良い。
-
- var args = arguments;
- var aindex = 1;
- var lastIndex = 0;
- var outputLength = 0;
- var output = fmt.replace(/%(?:(\d+)\$)?([-+ 0#']*)(\d+|\*(?:\d+\$)?)?(\.(?:\d+|\*(?:\d+\$)?)?)?(hh|ll|I(?:32|64)?|[hlLjztqw])?(.|$)/g, function($0, pos, flag, width, precision, type, conv, index) {
- outputLength += index - lastIndex;
- lastIndex = index + $0.length;
-
- if ((conv = conversions[conv]) == null) {
- var ret = '(sprintf:error:' + $0 + ')';
- outputLength += ret.length;
- return ret;
- }
-
- pos =
- (pos == null || pos === "") ? null :
- pos === '*' ? 0 | args[aindex++] :
- 0 | pos;
-
- width =
- (width == null || width === "") ? 0 :
- width === '*' ? 0 | args[aindex++]:
- width.charAt(0) === '*' ? args[0 | width.slice(1, -1)] :
- 0 | width;
-
- precision =
- (precision == null || precision === "") ? null:
- precision === '.*' ? 0 | args[aindex++]:
- precision.charAt(1) === '*' ? args[0 | precision.slice(2, -1)] :
- 0 | precision.slice(1);
-
- var value = conv.noValue ? null: pos === null ? args[aindex++] : args[pos];
- if (conv.getv) value = conv.getv(value, type);
-
- var prefix = '';
- if (conv.signed) {
- if (value < 0) {
- prefix = '-';
- value = -value;
- } else if (/\+/.test(flag))
- prefix = '+';
- else if (/ /.test(flag))
- prefix = ' ';
- }
- if (conv.prefix && value != 0)
- prefix += conv.prefix(flag);
-
- var body = conv.conv(value, flag, precision, type, outputLength);
-
- var lpad = '', zero = '', rpad = '';
- width -= prefix.length + body.length;
- if (width >= 1) {
- if (/-/.test(flag)) {
- // POSIX に従うと - の方が優先
- rpad = repeatString(' ', width);
- } else if (/0/.test(flag) && (!conv.integral || precision == null)) {
- zero = repeatString('0', width);
- } else
- lpad = repeatString(' ', width);
- }
-
- var ret = lpad + prefix + zero + body + rpad;
- outputLength += ret.length;
- return ret;
- });
- outputLength += fmt.length - lastIndex;
-
- return [outputLength, output];
- }
-
- __exports.sprintf = function sprintf() {
- var result = printf_impl.apply(this, arguments);
- return result[1];
- };
-
- __exports.vsprintf = function vsprintf(fmt, args) {
- var result = printf_impl.apply(this, [fmt].concat(args));
- return result[1];
- };
-
- var stdout = null;
- if (__global.agh && __global.printh)
- stdout = function(text) { printh(agh.Text.Escape(text, 'html')); };
- else if (__global.process && __global.process.stdout)
- stdout = function(text) { process.stdout.write(text); };
- else if (__global.console && __global.console.log)
- stdout = function(text) { console.log(text); };
- else
- stdout = function(text) { document.write(text); };
-
- __exports.printf = function printf() {
- var result = printf_impl.apply(this, arguments);
- stdout(result[1]);
- return result[0];
- };
-
- if (__global.agh && __global.agh.scripts)
- __global.agh.scripts.register("agh.sprintf.js");
-
- })(this);
-
- // test
- //
- // printf("%2$d行目のコマンド %1$sは不正です", "hoge", 20);
- // printf("%d(1234) %o(2322) %x(4d2)\n", 1234, 1234, 1234);
- // printf("%s(abc) %c(x)\n", "abc", 'x'.charCodeAt(0));
- // printf("%*d( 10)", 5, 10);
- // printf("%.*s(3)", 3, "abcdef");
- // printf("%2d( 3) %02d(03)", 3, 3);
- // printf("%1$d:%2$.*3$d:%4$.*3$d(15:035:045)\n", 15, 35, 3, 45);
- //
- // printf("%%d: [%+10d][%+ 10d][% +10d][%d]", 10, 10, 10, 1e10);
- // printf("%%u: [%u][%u][%+u][% u][%-u][%+10u][%-10u]", -1, 10, 10, 10, 10, 10, 10);
- // printf("%%x,%%u: %x %o", -1, -1);
- // printf("%%a: %a %a %a %a %a %a %a %a %a", 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9);
- // printf("%%A: %A %.3A %#.3A", 1e10, 1e10, 1e10);
- // printf("%%A: %A %A %A %A", 4096, 2048, 1024, 512);
- //
- // printf("%%e: %#.3e %#.3e %#.3e", 1e1000, 1e100, 1e10);
- // printf("%%e: %#.3e %#.6e %#.10e %#.20e\n", 1.234, 1.234, 1.234, 1.234);
- // printf("%%e: %#.1e %#.5e %#.10e %#.100e", 9.999, 9.999, 9.999, 9.999);
- // printf("%%f: %f %#g %#f %#.g %f %'f", 1, 1, 1, 1, 1e100, 1e100);
- // printf("%%g: %.15g %.15g %#.15g", 1, 1.2, 1.2);
- // printf("%%g: %g %.g %#g %#.g", 15, 15, 15, 15);
- // printf("%%g: %g %g %g %g %g", 1e-1, 1e-3, 1e-4, 1e-5, 9e-5, 9e-4, 1e10);
- // printf("%%#g: %#g %#g %#g %#2g %#6g", 0.1, 1e-5, 1e-4, 1e-4, 1e-4);
- // printf("%%#.g: %#.2g %#.2g", 1e-4, 1e-5);
- // printf("%%.g: %.g %.g %.g; %.1g %.1g %.1g; %.2g %.3g", 0.1, 0.999, 9.999, 9, 9.9, 9.999, 9.999, 9.999)
- //
- // printf("%%c: [%c][%c][%c]\n", 1e100, 65, 8);
- // printf("%05s %05s\n", 123, "aaa");
- // printf("%%p: %p", 512);
- // printf("pi: [%1$a][%1$g][%1$'20.9g][%1$020.9g][%1$'020.9g][%2$'020.9g]", Math.PI, Math.PI * 1e3);
-
-
- // --------------------
- // JScript main.
- // --------------------
- var rv = 0;
- var jsargs = new Array();
- for (var idx = 0; idx < WScript.Arguments.length; ++idx) {
- jsargs[idx] = WScript.Arguments(idx);
- }
- var ary = new Array();
- ary = jsargs.slice(0, jsargs.length);
- if (0 == 1) {
- rv = rv + 1;
- } else if (WScript.Arguments.length == 1) {
- rv = rv + arrowsTest(ary);
- } else {
- rv = rv + UnknownArg(ary);
- }
-
- WScript.quit(rv);