みにか

微調整。機能追加はしてない。
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;
}

test