recptx.pl が動作しない件

FreeBSD の ports には、PT1, 2 用のドライバが multimedia/ptx-kmod として登録されています。
もちろんこれでは PT3 は動作しないのですが、PT3 用のドライバを github で公開されている方がいます。https://github.com/Piro77/fbsdpt3

しかし、上記を用いると、multimedia/ptx-kmod 付属の recptx.pl が正常に動作しないようです。

一応こんなかんじに close した後にチューニングするようにしてやれば動くらしいです。
ファイル名部分はこんなんでいいのかよくわかっていないみたいです。

--- /tmp/recptx.pl.bak  2013-05-27 20:43:19.568052443 +0900
+++ /usr/local/bin/recptx.pl    2013-05-27 20:45:53.218059174 +0900
@@ -223,7 +223,7 @@
     $cmdfmt .= " -r " . $opt{'round'} if (defined $opt{'round'});
     $cmdfmt .= " -s 1" if (defined $opt{'strip'});
     $cmdfmt .= " -m 1" if (defined $opt{'emm'});
-    $cmdfmt .= " -v 0 -p 0 %s _%s";
+    $cmdfmt .= " -v 0 -p 0 %s %s";
 } else {
     $cmdfmt = "/bin/cat %s > %s";
 }
@@ -271,7 +271,6 @@
 #
 # recording
 #
-system("/sbin/sysctl $mib.freq=$freq >/dev/null 2>&1");

 eval {
     local $SIG{ALRM} = sub { die "alarm\n" };
@@ -284,6 +283,7 @@
     } else {
        $cmd = sprintf($cmdfmt, $dev, $filename);
         close $t;
+       system("/sbin/sysctl $mib.freq=$freq >/dev/null 2>&1");
        exec("$cmd");
     }

っていうことを通りすがりのおじさんが言ってました。正直私にはなんのことやらさっぱりです。

<T> T hoge(String a, T... b) なメソッドに引数を1つしか渡さなかった場合の挙動が ECJ, JDK で異なる

Class object を渡さずに戻り値の型を指定したい - f99aq8oveのブログ というエントリーを先日書いたわけですが、問題があることがわかりました。

まずはこれを見てください。

__GooglePrettify__
package net.f99aq8ove.junk;

import java.util.HashMap;
import java.util.Map;

public class HogeContainer {
    private final Map<String, Object> container = new HashMap<String, Object>();

    public void put(String key, Object obj) {
        container.put(key, obj);
    }

    public <E> E get1(String key, Class<E> klass) {
        Object obj = container.get(key);
        if (klass.isInstance(obj)) {
            return klass.cast(obj);
        } else {
            return null;
        }
    }

    public <E> E get2(String key, @SuppressWarnings("unchecked") E... dummy) {
        @SuppressWarnings("unchecked")
        Class<E> klass = (Class<E>) dummy.getClass().getComponentType();
        Object obj = container.get(key);
        if (klass.isInstance(obj)) {
            return klass.cast(obj);
        } else {
            return null;
        }
    }

    public static void main(String[] args) {
        HogeContainer hoge = new HogeContainer();
        hoge.put("string", "hoge");
        hoge.put("integer", 1);

        String str1 = hoge.get1("string", String.class);
        String str2 = hoge.get2("string");
        System.out.printf("%s, %s\n", str1, str2);
        // hoge, hoge

        Integer int1 = hoge.get1("integer", Integer.class);
        Integer int2 = hoge.get2("integer");
        System.out.printf("%d, %d\n", int1, int2);
        // 1, 1

        Long long1 = hoge.get1("string", Long.class);
        Long long2 = hoge.get2("string");
        System.out.printf("%d, %d\n", long1, long2);
        // null, null

        int1 = hoge.get1("string", Integer.class);
        int2 = hoge.get2("string");
        System.out.printf("%d, %d\n", int1, int2);
        // null, null
    }
}

↑なのですが、OracleJDK でコンパイルすると、以下のように ClassCastException でこけます。

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
        at net.f99aq8ove.junk.HogeContainer.main(HogeContainer.java:49)

Eclipse で書いて実行した時には問題なく動作したのに、JDK でコンパイルすると動作しないのはナゼか…。

ところで、Eclipse でコンパイルした場合、JDK ではなく、ECJ (Eclipse Compiller for Java) が使用されます。
ということは、コンパイラの仕様差かなということで、ECJ, JDK でコンパイルした class ファイルを JD で逆コンパイルして眺めてみます。

ECJ

__GooglePrettify__
package net.f99aq8ove.junk;

import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;

public class HogeContainer
{
  private final Map<String, Object> container = new HashMap();

  public void put(String key, Object obj) {
    this.container.put(key, obj);
  }

  public <E> E get1(String key, Class<E> klass) {
    Object obj = this.container.get(key);
    if (klass.isInstance(obj)) {
      return klass.cast(obj);
    }
    return null;
  }

  public <E> E get2(String key, E[] dummy)
  {
    Class klass = dummy.getClass().getComponentType();
    Object obj = this.container.get(key);
    if (klass.isInstance(obj)) {
      return klass.cast(obj);
    }
    return null;
  }

  public static void main(String[] args)
  {
    HogeContainer hoge = new HogeContainer();
    hoge.put("string", "hoge");
    hoge.put("integer", Integer.valueOf(1));

    String str1 = (String)hoge.get1("string", String.class);
    String str2 = (String)hoge.get2("string", new String[0]);
    System.out.printf("%s, %s\n", new Object[] { str1, str2 });

    Integer int1 = (Integer)hoge.get1("integer", Integer.class);
    Integer int2 = (Integer)hoge.get2("integer", new Integer[0]);
    System.out.printf("%d, %d\n", new Object[] { int1, int2 });

    Long long1 = (Long)hoge.get1("string", Long.class);
    Long long2 = (Long)hoge.get2("string", new Long[0]);
    System.out.printf("%d, %d\n", new Object[] { long1, long2 });

    int1 = (Integer)hoge.get1("string", Integer.class);
    int2 = (Integer)hoge.get2("string", new Integer[0]);
    System.out.printf("%d, %d\n", new Object[] { int1, int2 });
  }
}

OpenJDK 7

__GooglePrettify__
package net.f99aq8ove.junk;

import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;

public class HogeContainer
{
  private final Map<String, Object> container = new HashMap();

  public void put(String paramString, Object paramObject) {
    this.container.put(paramString, paramObject);
  }

  public <E> E get1(String paramString, Class<E> paramClass) {
    Object localObject = this.container.get(paramString);
    if (paramClass.isInstance(localObject)) {
      return paramClass.cast(localObject);
    }
    return null;
  }

  public <E> E get2(String paramString, E[] paramArrayOfE)
  {
    Class localClass = paramArrayOfE.getClass().getComponentType();
    Object localObject = this.container.get(paramString);
    if (localClass.isInstance(localObject)) {
      return localClass.cast(localObject);
    }
    return null;
  }

  public static void main(String[] paramArrayOfString)
  {
    HogeContainer localHogeContainer = new HogeContainer();
    localHogeContainer.put("string", "hoge");
    localHogeContainer.put("integer", Integer.valueOf(1));

    String str1 = (String)localHogeContainer.get1("string", String.class);
    String str2 = (String)localHogeContainer.get2("string", new Object[0]);
    System.out.printf("%s, %s\n", new Object[] { str1, str2 });

    Integer localInteger1 = (Integer)localHogeContainer.get1("integer", Integer.class);
    Integer localInteger2 = (Integer)localHogeContainer.get2("integer", new Object[0]);
    System.out.printf("%d, %d\n", new Object[] { localInteger1, localInteger2 });

    Long localLong1 = (Long)localHogeContainer.get1("string", Long.class);
    Long localLong2 = (Long)localHogeContainer.get2("string", new Object[0]);
    System.out.printf("%d, %d\n", new Object[] { localLong1, localLong2 });

    localInteger1 = (Integer)localHogeContainer.get1("string", Integer.class);
    localInteger2 = (Integer)localHogeContainer.get2("string", new Object[0]);
    System.out.printf("%d, %d\n", new Object[] { localInteger1, localInteger2 });
  }
}

ダラっと書き出してしまいましたが、問題の箇所だけ抜き出すと…

__GooglePrettify__
    // Original
    Long long2 = hoge.get2("string");
    // ECJ
    Long long2 = (Long)hoge.get2("string", new Long[0]);
    // JDK
    Long localLong2 = (Long)localHogeContainer.get2("string", new Object[0]);

はい。可変引数に渡されている配列が、Object 型になってしまっていますね。
これでは get2 内の判定処理が意図通りに動きません。

ちなみに、1つ以上の引数を渡してあげると new Long が渡されます。

__GooglePrettify__
    // Original
    Long long2 = hoge.get2("string", 1L);
    // ECJ
    Long long2 = (Long)hoge.get2("string", new Long[] { Long.valueOf(1L) });
    // JDK
    Long localLong2 = (Long)localHogeContainer.get2("string", new Long[] { Long.valueOf(1L) });

仕様をあたってみても k = n の時の定義が曖昧な感じがするので、実装依存という事だと思われます。
Chapter 15. Expressions

結論

get2 は諦めましょう ^^;

はてなダイアリーからはてなブログに移行

今更ながらはてなダイアリーからはてなブログに移行してみた。
Super pre 記法で syntax highlight できないみたいだったので、Google code prettify を使うようにしてみた。

やり方は、はてブロ設定のデザイン -> ヘッダー の所に以下を設定しておいて、

__GooglePrettify__
<script type="text/JavaScript" src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?autoload=false&amp;skin=desert"></script>
<script type="text/JavaScript">
$(function () {
    $("pre:contains('__GooglePrettify__')").addClass("prettyprint").each(function (i, elm) {
        elm.innerHTML = elm.innerHTML.replace(/^.*?__GooglePrettify__.*?\n/, "");
    });
    prettyPrint();
});
</script>

ハイライトしたいコードブロックの先頭に __GooglePrettify__ と書き込むだけ。

__GooglePrettify__
object FizzBuzz {
  def main(args: Array[String]) {
    List.range(1, 101) map (x => (x, "")) map
      (x => (x._1, x._2 + (if (x._1 % 3 == 0) "fizz" else ""))) map
      (x => (x._1, x._2 + (if (x._1 % 5 == 0) "buzz" else ""))) map
      (x => if (x._2 == "") x._1 else x._2) foreach println
  }
}

↑初 ScalaFizzBuzz. ちょっと勉強してきた↓

__GooglePrettify__
object FizzBuzz {
  def main(args: Array[String]) {
    1 to 100 map {
      case x if x % 15 == 0 => "FizzBuzz"
      case x if x % 3 == 0 => "Fizz"
      case x if x % 5 == 0 => "Buzz"
      case x => x
    } foreach println
  }
}

Class object を渡さずに戻り値の型を指定したい

後日談あり→<T> T hoge(String a, T... b) なメソッドに引数を1つしか渡さなかった場合の挙動が ECJ, JDK で異なる - f99aq8oveのブログ

# http://f99aq.hateblo.jp/ はてなブログを使い始めてみたのですが、super pre 記法でのシンタックス・ハイライトがうまく行かなかったので、こちらに書きます。

本題ですが、Java で「Class object を渡さずに戻り値の型を指定したい」のです。
文章でうまく表現できないので、とりあえず以下を見てください。

package net.f99aq8ove.junk;

import java.util.HashMap;
import java.util.Map;

public class HogeContainer {
    private final Map<String, Object> container = new HashMap<String, Object>();

    public void put(String key, Object obj) {
        container.put(key, obj);
    }

    public <E> E get1(String key, Class<E> klass) {
        Object obj = container.get(key);
        if (klass.isInstance(obj)) {
            return klass.cast(obj);
        } else {
            return null;
        }
    }

    public <E> E get2(String key, E... dummy) {
        @SuppressWarnings("unchecked")
        Class<E> klass = (Class<E>) dummy.getClass().getComponentType();

        Object obj = container.get(key);
        if (klass.isInstance(obj)) {
            return klass.cast(obj);
        } else {
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public <E> E get3(String key) {
        return get2(key);
    }

    private <E> Class<E> getType(E... dummy) {
        return (Class<E>) dummy.getClass().getComponentType();
    }

    public <E> E get4(String key) {
        Class<E> klass = getType();

        Object obj = container.get(key);
        if (klass.isInstance(obj)) {
            return klass.cast(obj);
        } else {
            return null;
        }
    }

    public static void main(String[] args) {
        HogeContainer hoge = new HogeContainer();
        hoge.put("string", "hoge");
        hoge.put("integer", 1);

        String str1 = hoge.get1("string", String.class);
        String str2 = hoge.get2("string");
        String str3 = hoge.get3("string");
        String str4 = hoge.get4("string");
        System.out.printf("%s, %s, %s, %s\n", str1, str2, str3, str4);
        // hoge, hoge, hoge, hoge

        Integer int1 = hoge.get1("integer", Integer.class);
        Integer int2 = hoge.get2("integer");
        Integer int3 = hoge.get3("integer");
        Integer int4 = hoge.get4("integer");
        System.out.printf("%d, %d, %d, %d\n", int1, int2, int3, int4);
        // 1, 1, 1, 1

        Long long1 = hoge.get1("string", Long.class);
        Long long2 = hoge.get2("string");
        Long long3 = null; // hoge.get3("string"); // <- ClassCastException
        Long long4 = null; // hoge.get4("string"); // <- ClassCastException
        System.out.printf("%d, %d, %d, %d\n", long1, long2, long3, long4);
        // null, null, null, null
    }
}

制約事項として、JDK 5 を使うものとします。また、Key 毎に値の型は一意に決まるものとし、型は同一だが key が異なるものも存在することとします。

突っ込みどころはあると思いますが、現在 get1 のようなコードがあります。
これをどうにかして class object を渡さなくても良いようにしたいというモチベーションです。


Java変態文法最速マスター - プログラマーの脳みそ を参考にした結果、get2, get3, get4 が出来ました。

get2 は動きます。しかし、dummy が目障りです。

get3, get4 は、E の型情報が失われてしまっており、メソッドの戻り値を代入する時に ClassCastException が発生します。(メソッド中の klass は Object.class になっています。)

get2 から dummy を取り去る方法は無いものでしょうか。
Java は難しいです。