みにか
微調整。機能追加はしてない。
http://konbu.s13.xrea.com/lib/minipsm.exe
プログラムとかソースコードとかNYSL。
とかどうでもいいんだけど、あれだな。クロージャはやっぱりいいな。2.007を体験したらそれ以前のD言語には戻れない。(割と本気)
以下コード。だいぶましになった気がしたけど、今見るとそうでもなかった。変換テーブルを外部定義ファイルとか参照して色々できるようにするのが、カッコイイかな。
import std.stream; import std.cstream; import std.string; import std.ctype; import std.regexp; import std.contracts; string radixalphabets(uint radix) { static invariant char[] fullalphabets = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return fullalphabets[0..radix]; } bool isalphabet(char c, string alphabets) { foreach(char alph; alphabets) { if(c==alph) return true; } return false; } string remsp(string str) { char[] rem; foreach(char c; str){ if(!isspace(c)) rem ~= c; } return assumeUnique(rem); } string bin2hex(string line) { char[] hex; string binalph = radixalphabets(2); string hexalph = radixalphabets(16); string bin_s = remsp(line); for(int i=0;i+3<bin_s.length;i+=4){ string byte_s = bin_s[i..i+4]; byte h = 0; foreach(char c; byte_s){ if(!isalphabet(c, binalph)){ return ""; } h = h*2 + (c-'0'); } hex ~= hexalph[h]; } return assumeUnique(hex); } string hex2bin(string line) { char[] bin; string hex = line.toupper(); string hexalph = radixalphabets(16); foreach(char c; hex){ if(!isalphabet(c, hexalph)) return ""; byte h = c>='A'? c-'A'+10 : c-'0'; for(int i=8;i>0;i/=2){ byte b = h / i; h -= b * i; bin ~= b==0 ? '0' : '1'; } bin ~= ' '; } return assumeUnique(bin); } string delegate(string)[string] optable; int[string] funtable; string to_s(string num, int radix, int len) { return to_s(atoi(num), radix, len); } string to_s(int num, int radix, int len) { char[] tostr = new char[len]; string base = toString(cast(long)num, cast(uint)radix); if(base.length==len) return base; for(int i=0;i<len;++i){ tostr[i] = i+base.length<len ? '0' : base[i+base.length-len]; } return assumeUnique(tostr); } enum SrcType{ CONST, MATCH } union FieldSrc{ string constant; int match; } class Field{ SrcType stype; FieldSrc src; int len; this(){} public static Field matchField(int m, int len) { Field field = new Field; field.stype = SrcType.MATCH; field.src.match = m; field.len = len; return field; } public static Field constField(int c, int len) { Field field = new Field; field.stype = SrcType.CONST; field.src.constant = to_s(c, 2, len); field.len = len; return field; } } void initasm() { RegExp RPat = new RegExp("^\\s*(\\S+)\\s+\\$(\\d+)\\s*,\\s*\\$(\\d+)\\s*,\\s*\\$(\\d+)"); RegExp IPat = new RegExp("^\\s*(\\S+)\\s+\\$(\\d+)\\s*,\\s*\\$(\\d+)\\s*,\\s*(\\d+)"); RegExp MPat = new RegExp("^\\s*(\\S+)\\s+\\$(\\d+)\\s*,\\s*(\\d+)(\\(\\$(\\d+)\\))?"); RegExp EPat = new RegExp("^\\s*(\\S+)\\s+\\$(.+)\\s*,\\s*\\$(.+)"); RegExp JPat = new RegExp("^\\s*(\\S+)\\s+(\\d+)\\s*"); RegExp JRPat = new RegExp("^\\s*(\\S+)\\s+\\$(\\d+)"); RegExp DPat = new RegExp("."); string mkfield(int id, string[] mat, Field field) { switch(field.stype){ case SrcType.CONST: return field.src.constant; case SrcType.MATCH: if(field.src.match==1){ return to_s(id, 2, field.len); } else{ return to_s(mat[field.src.match], 2, field.len); } } return "".idup; } string delegate(string) mkinst(int id, RegExp pat, Field[] def) { return (string line){ if(string[] mat = pat.match(line)){ char[] instruction; foreach(Field field; def){ instruction ~= mkfield(id, mat, field); } return bin2hex(assumeUnique(instruction)); } return "".idup; }; } Field c0_5 = Field.constField(0, 5); Field c0_6 = Field.constField(0, 6); Field mat1_6 = Field.matchField(1, 6); Field mat2_5 = Field.matchField(2, 5); Field mat3_5 = Field.matchField(3, 5); Field mat4_5 = Field.matchField(4, 5); Field[] fundef = [c0_6, mat3_5, mat4_5, mat2_5, c0_5, mat1_6]; optable["add"] = mkinst(32, RPat, fundef); optable["addu"] = mkinst(33, RPat, fundef); optable["sub"] = mkinst(34, RPat, fundef); optable["subu"] = mkinst(35, RPat, fundef); optable["and"] = mkinst(36, RPat, fundef); optable["or"] = mkinst(37, RPat, fundef); optable["sllv"] = mkinst(4, RPat, fundef); optable["srlv"] = mkinst(6, RPat, fundef); optable["srav"] = mkinst(7, RPat, fundef); optable["slt"] = mkinst(42, RPat, fundef); optable["sltu"] = mkinst(43, RPat, fundef); Field[] shadef = [c0_6, c0_5, mat3_5, mat2_5, mat4_5, mat1_6]; optable["sll"] = mkinst(0, IPat, shadef); optable["srl"] = mkinst(2, IPat, shadef); optable["sra"] = mkinst(3, IPat, shadef); Field mat4_16 = Field.matchField(4, 16); Field[] immdef = [mat1_6, mat3_5, mat2_5, mat4_16]; optable["addi"] = mkinst(8, IPat, immdef); optable["addiu"] = mkinst(9, IPat, immdef); optable["andi"] = mkinst(12, IPat, immdef); optable["ori"] = mkinst(13, IPat, immdef); optable["beq"] = mkinst(4, IPat, immdef); optable["bne"] = mkinst(5, IPat, immdef); optable["slti"] = mkinst(10, IPat, immdef); optable["sltiu"] = mkinst(11, IPat, immdef); Field mat3_16 = Field.matchField(3, 16); Field mat5_5 = Field.matchField(5, 5); Field[] memdef = [mat1_6, mat5_5, mat2_5, mat3_16]; optable["lb"] = mkinst(32, MPat, memdef); optable["lw"] = mkinst(35, MPat, memdef); optable["sb"] = mkinst(40, MPat, memdef); optable["sw"] = mkinst(43, MPat, memdef); Field[] luidef = [mat1_6, c0_5, mat2_5, mat3_16]; optable["lui"] = mkinst(15, MPat, luidef); Field mat2_26 = Field.matchField(2, 26); Field[] jdef = [mat1_6, mat2_26]; optable["j"] = mkinst(2, JPat, jdef); optable["jal"] = mkinst(3, JPat, jdef); Field[] jrdef = [c0_6, mat2_5, c0_5, c0_5, c0_5, mat1_6]; optable["jr"] = mkinst(6, JRPat, jrdef); Field c14_5 = Field.constField(14, 5); Field c0_11 = Field.constField(0, 11); Field[] mfedef = [mat1_6, c0_5, c14_5, mat2_5, c0_11]; optable["mfe"] = mkinst(16, EPat, mfedef); Field c4_5 = Field.constField(4, 5); Field c12_5 = Field.constField(12, 5); Field[] mtedef = [mat1_6, c4_5, mat3_5, c12_5, c0_11]; optable["mte"] = mkinst(16, EPat, mtedef); Field c1_1 = Field.constField(1, 1); Field c0_19 = Field.constField(0, 19); Field c32_6 = Field.constField(32, 6); Field[] rfedef = [mat1_6, c1_1, c0_19, c32_6]; optable["rfe"] = mkinst(16, DPat, rfedef); } string asmble(string line) { RegExp opPat = new RegExp("^\\s*(\\S+)\\s*"); if(opPat.match(line)){ string op = opPat.match(1); if(op in optable){ return optable[op](line); } } return ""; } int main(string[] args) { Stream input, output; if(args.length==1){ dout.writeLine(args[0]~" (asm|dsm|b2h|h2b) [input [output]]"); return 0; } string function(string)[string] convs; convs["b2h"] = &bin2hex; convs["h2b"] = &hex2bin; convs["asm"] = &asmble; convs["dsm"] = &asmble; initasm(); if(args.length==2){ input = din; output = dout; } else if(args.length==3){ input = new BufferedFile(args[2]); output = dout; } else{ input = new BufferedFile(args[2]); output = new BufferedFile(args[3], FileMode.OutNew); } if(!(args[1] in convs)){ dout.writeLine("unknown mode"); return 1; } string function(string) conv = convs[args[1]]; foreach(char[] line; input){ output.writeLine(conv(assumeUnique(line))); } output.flush(); output.close(); return 0; }