秀丸マクロで sprintf の実装をしてみました。はじめは どう書く?org ( お題:printfの自作 )に投稿するつもりで作っていたのですがさすがに長いので投稿するのはやめておきます。
sprintfToString で 数値を unsigned として扱って文字列化 を秀丸マクロに移植して無理やり一つのサブルーチンにまとめたソースが使われています。
ソースをもっと綺麗にしたいところ。
call sprintf "[%s][%c][%%][%d][%x][%o][%u][%b]", "String", '#', 123, 0xabc, 511, 0xffffffff, 96;
message $$return;
endmacro;
sprintf:
$$format = $$1;
$$arg[0]=$$2;$$arg[1]=$$3;$$arg[2]=$$4;$$arg[3]=$$5;$$arg[4]=$$6;$$arg[5]=$$7;$$arg[6]=$$8;$$arg[7]=$$9;
##arg[0]=##2;##arg[1]=##3;##arg[2]=##4;##arg[3]=##5;##arg[4]=##6;##arg[5]=##7;##arg[6]=##8;##arg[7]=##9;
$$dest = "";
##argIndex = 0;
while( $$format != "" ) {
##search = strstr( $$format, "%" );
if( ##search == -1 ) {
$$dest = $$dest + $$format;
break;
}
$$dest = $$dest + leftstr( $$format, ##search );
$$format = rightstr( $$format, strlen( $$format ) - ##search );
$$_format = $$format;
$$format = rightstr( $$format, strlen( $$format ) - strlen( "%" ) );
$$fmt = $$format;
##specifiedArgIndex = -1;
while( ( ascii( $$fmt ) >= '0' ) && ( ascii( $$fmt ) <= '9' ) ) {
$$fmt = rightstr( $$fmt, strlen( $$fmt ) - strlen( char( ascii( $$fmt ) ) ) );
}
if( ( ascii( $$fmt ) == '$' ) && ( strlen( $$format ) != strlen( $$fmt ) ) ) {
##specifiedArgIndex = val( leftstr( $$format, strlen( $$format ) - strlen( $$fmt ) ) ) - 1;
$$format = rightstr( $$fmt, strlen( $$fmt ) - strlen( "$" ) );
}
$$fmt = $$format;
while( strstr( " #'+-0", char( ascii( $$fmt ) ) ) >= 0 ) {
$$fmt = rightstr( $$fmt, strlen( $$fmt ) - 1 );
}
$$flag = leftstr( $$format, strlen( $$format ) - strlen( $$fmt ) );
$$format = $$fmt;
##width = 0;
if( ascii( $$format ) == '*' ) {
$$format = rightstr( $$format, strlen( $$format ) - strlen( "*" ) );
$$fmt = $$format;
while( ( ascii( $$fmt ) >= '0' ) && ( ascii( $$fmt ) <= '9' ) ) {
$$fmt = rightstr( $$fmt, strlen( $$fmt ) - strlen( char( ascii( $$fmt ) ) ) );
}
if( ( ascii( $$fmt ) == '$' ) && ( strlen( $$format ) != strlen( $$fmt ) ) ) {
##width = ##arg[ val( leftstr( $$format, strlen( $$format ) - strlen( $$fmt ) ) ) - 1 ];
$$format = rightstr( $$fmt, strlen( $$fmt ) - strlen( "$" ) );
} else {
##width = ##arg[##argIndex];
##argIndex = ##argIndex + 1;
}
} else {
while( ( ascii( $$format ) >= '0' ) && ( ascii( $$format ) <= '9' ) ) {
##width = ##width * 10 + ( ascii( $$format ) - '0' );
$$format = rightstr( $$format, strlen( $$format ) - 1 );
}
}
if( ##width < 0 ) {
$$flag = $$flag + "-";
##width = -##width;
}
##accuracy = -1;
if( ascii( $$format ) == '.' ) {
$$format = rightstr( $$format, strlen( $$format ) - strlen( "." ) );
if( ascii( $$format ) == '*' ) {
$$format = rightstr( $$format, strlen( $$format ) - strlen( "*" ) );
$$fmt = $$format;
while( ( ascii( $$fmt ) >= '0' ) && ( ascii( $$fmt ) <= '9' ) ) {
$$fmt = rightstr( $$fmt, strlen( $$fmt ) - strlen( char( ascii( $$fmt ) ) ) );
}
if( ( ascii( $$fmt ) == '$' ) && ( strlen( $$format ) != strlen( $$fmt ) ) ) {
##accuracy = ##arg[ val( leftstr( $$format, strlen( $$format ) - strlen( $$fmt ) ) ) - 1 ];
$$format = rightstr( $$fmt, strlen( $$fmt ) - strlen( "$" ) );
} else {
##accuracy = ##arg[##argIndex];
##argIndex = ##argIndex + 1;
}
} else {
##nextchar = ascii( midstr( $$format, 1, 1 ) );
if( ( ascii( $$format ) == '-' ) && ( ##nextchar >= '0' ) && ( ##nextchar <= '9' ) ) {
$$format = rightstr( $$format, strlen( $$format ) - strlen( "-" ) );
}
##accuracy = 0;
while( ( ascii( $$format ) >= '0' ) && ( ascii( $$format ) <= '9' ) ) {
##accuracy = ##accuracy * 10 + ( ascii( $$format ) - '0' );
$$format = rightstr( $$format, strlen( $$format ) - 1 );
}
}
if( ##accuracy < 0 ) {
##accuracy = 0;
}
}
##conversionSpecifier = 0;
if( strstr( "diouxXbBcs%", char( ascii( $$format ) ) ) >= 0 ) {
##conversionSpecifier = ascii( $$format );
$$format = rightstr( $$format, strlen( $$format ) - 1 );
}
if ( ##conversionSpecifier == 0 ) {
$$dest = $$dest + leftstr( $$_format, strlen( $$_format ) - strlen( $$format ) );
} else if( ##conversionSpecifier == '%' ) {
$$dest = $$dest + "%";
} else {
if( ##specifiedArgIndex >= 0 ) {
##arg = ##arg[##specifiedArgIndex];
$$arg = $$arg[##specifiedArgIndex];
} else {
##arg = ##arg[##argIndex];
$$arg = $$arg[##argIndex];
##argIndex = ##argIndex + 1;
}
call sprintfConvert ##arg, $$arg, $$flag, ##width, ##accuracy, ##conversionSpecifier;
$$dest = $$dest + $$return;
}
}
return $$dest;
sprintfConvert:
##arg = ##1;
$$arg = $$2;
$$flag = $$3;
##width = ##4;
##accuracy = ##5;
##conversionSpecifier = ##6;
while( $$flag != "" ) {
##flag[ascii( $$flag )] = true;
$$flag = rightstr( $$flag, strlen( $$flag ) - 1 );
}
if( ##conversionSpecifier == 'c' ) {
$$converted = char( ##arg );
} else if( ##conversionSpecifier == 's' ) {
if( ##accuracy >= 0 ) {
$$converted = leftstr( $$arg, ##accuracy );
} else {
$$converted = $$arg;
}
} else if( strstr( "diuoxXbB", char( ##conversionSpecifier ) ) >= 0 ) {
##signed = ( ( strstr( "di", char( ##conversionSpecifier ) ) >= 0 ) || ##flag['+'] || ##flag[' '] );
if( ##signed ) {
##isNegative = ( ##arg < 0 );
if( ##isNegative ) {
##arg = -##arg;
}
}
$$prefix = "";
if( ( ##flag['#'] ) && ( ##arg != 0 ) ) {
if( strstr( "xX", char( ##conversionSpecifier ) ) >= 0 ) {
$$prefix = "0X" + $$prefix;
} else if( strstr( "bB", char( ##conversionSpecifier ) ) >= 0 ) {
$$prefix = "0B" + $$prefix;
}
}
if( ##signed ) {
##sign = 0;
if( ##isNegative ) {
##sign = '-';
} else if( ##flag['+'] ) {
##sign = '+';
} else if( ##flag[' '] ) {
##sign = ' ';
}
$$prefix = char( ##sign ) + $$prefix;
}
if( strstr( "xX", char( ##conversionSpecifier ) ) >= 0 ) {
##radix = 16;
} else if( ##conversionSpecifier == 'o' ) {
##radix = 8;
} else if( strstr( "bB", char( ##conversionSpecifier ) ) >= 0 ) {
##radix = 2;
} else {
##radix = 10;
}
if( ( ##accuracy == 0 ) && ( ##arg == 0 ) ) {
$$converted = "";
} else {
call sprintfToString ##arg, ##radix;
$$converted = $$return;
}
##i = 0;
if( ##accuracy >= 0 ) {
##i = ##accuracy - strlen( $$converted );
} else if( ##flag['0'] && ( !##flag['-'] ) ) {
##i = ##width - strlen( $$converted ) - strlen( $$prefix );
}
while( ##i > 0 ) {
$$converted = "0" + $$converted;
##i = ##i - 1;
}
if( ( ##conversionSpecifier == 'o' ) && ( ##flag['#'] ) && ( ascii( $$converted ) != '0' ) ) {
$$converted = "0" + $$converted;
}
if( ( strstr( "diu", char( ##conversionSpecifier ) ) >= 0 ) && ##flag['\''] ) {
##i = strlen( $$converted ) - 3;
while( ##i > 0 ) {
$$converted = leftstr( $$converted, ##i ) + "'" + rightstr( $$converted, strlen( $$converted ) - ##i );
##i = ##i - 3;
}
if( ##flag['0'] && ( ##accuracy < 0 ) && ( !##flag['-'] ) ) {
if( ##i == 0 ) {
$$converted = "'" + $$converted;
}
while( ( strlen( $$converted ) + strlen( $$prefix ) > ##width ) && ( strstr( "0'", leftstr( $$converted, 1 ) ) >= 0 ) ) {
$$converted = rightstr( $$converted, strlen( $$converted ) - 1 );
}
}
}
$$converted = $$prefix + $$converted;
if( strstr( "xb", char( ##conversionSpecifier ) ) >= 0 ) {
$$converted = tolower( $$converted );
}
}
##i = ##width - strlen( $$converted );
$$space = "";
while( ##i > 0 ) {
$$space = $$space + " ";
##i = ##i - 1;
}
if( ##flag['-'] ) {
$$converted = $$converted + $$space;
} else {
$$converted = $$space + $$converted;
}
return $$converted;
sprintfToString:
$$digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
##x = ##1;
##radix = ##2;
##val = ##x & 0x7fffffff;
while( true ) {
$$y = "";
while( true ) {
##digit = ##val % ##radix;
if( ##digit < 0 ) ##digit = -##digit;
$$y = midstr( $$digits, ##digit, 1 ) + $$y;
##val = ##val / ##radix;
if( ##val == 0 ) break;
}
if( ##x >= 0 ) break;
if( strlen( $$x ) > 0 ) break;
$$x = $$y;
##val = 0x80000000;
}
if( ##x >= 0 ) return $$y;
##xindex = strlen( $$x ) - 1;
##yindex = strlen( $$y ) - 1;
##kuri = 0;
while( ( ##xindex >= 0 ) || ( ##yindex >= 0 ) || ( ##kuri != 0 ) ) {
##xval = 0;
##yval = 0;
if( ##xindex >= 0 ) ##xval = strstr( $$digits, midstr( $$x, ##xindex, 1 ) );
if( ##yindex >= 0 ) ##yval = strstr( $$digits, midstr( $$y, ##yindex, 1 ) );
##val = ##xval + ##yval + ##kuri;
##kuri = ##val / ##radix;
##val = ##val % ##radix;
$$dest = midstr( $$digits, ##val, 1 ) + $$dest;
##xindex = ##xindex - 1;
##yindex = ##yindex - 1;
}
return $$dest;