GetCharABCWidthsW は BMP 以外に対応せず?

charmapx を改造しているときに気づいたこと。 たとえば, 下のようなプログラムを書いたとする (エラー処理は省略した)。

#include <windows.h>
#include <stdio.h>
static void tst(HDC hdc, UINT n) {
    ABC abc;
    if (GetCharABCWidthsW(hdc, n, n, &abc)) 
        printf("ABC of %06X: (%d,%d,%d)\n", n, 
               abc.abcA, abc.abcB, abc.abcC);
    else 
        printf("can't get ABC of %06X\n", n);
}

int main() {
    HFONT hF = CreateFont(-18, 0, 0, 0, FW_NORMAL,FALSE,FALSE,FALSE,
                          DEFAULT_CHARSET, OUT_TT_PRECIS,
                          CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                          DEFAULT_PITCH|FF_SWISS, "Tahoma");
    HDC hdc = GetDC(0);
    HFONT hF0 = (HFONT)SelectObject(hdc, hF);

    tst(hdc, 0x3042);      /* ひらがな「あ」 */
    tst(hdc, 0x2000B);     /* 点のある「丈」 */

    SelectObject(hdc, hF0);
    ReleaseDC(0, hdc);
    return 0;
}

Vista で動かした結果は, 0x3042 で (0,13,2), 0x2000B で (1,8,0) となる。 どうみても 0x2000B のほうは幅がせますぎる。 どうやら GetCharABCWidthsW は文字コードの下位 16ビット以外を無視するようだ。 GetCharABCWidthsI もためしてみたが, 結果はおなじ。

とりあえず BMP 以外の文字については GetCharABCWidthsW を使わないように回避コードを書いたが, アドホックすぎる回避策なので, どうにかしたいところ。

投稿時刻 2007-06-24(己丑) 06:18プログラミング | コメント (0)

Python に興味が出てきた

いままで Perl があればじゅうぶんで, Python は, 「だれかが Python で書いたプログラムに手をくわえるとき」 くらいしか必要ないとおもっていたのだが, ちょっと興味がでてきた。

というのは, Python が LL言語であるのを知って, 「Pascal に似てる」 と感じたからだ。 そう思って類似点をかんがえていくと,

  1. Perl の構文は Unix のシェルスクリプトの強い影響を受けているが, Python はもともと Unix 以外の OS で動いていたもので, Unix とは直接関係がない。 これは Unix と深くむすびついていた C 言語に対する, より汎用の Pascal 言語の関係に似ている。
  2. Python は予約語が少ないが, 多くのビルトイン関数をもつことによって, 気軽に書けるように設計されている。 これは Write などを標準識別子にしている Pascal とおなじ考えだ。
  3. import 文の書きかたが, Pascal の後継である Modula-2 とおなじだ。
  4. chr() とか ord() とかいう関数名は Pascal から借りたもののようだ。 Python のもとになったという ABC を知らないので, Pascal から直接借りたものか, 間接的借用なのかは知らないが。
  5. Perl の構文に自由度が高いのに対して, Python は読みやすさと構文の合理性を重視しているようだ。 これは C と Pascal の関係によく似ている。

など, 共通点はかなり多い。 そういうことであれば, C と Pascal がおなじようなことしかできなくても, 両方に存在価値があるのと同様, Perl と Python はそれぞれに価値がある言語だとおもえてきた。 参考書などでは Python に影響をあたえた言語として, Lisp や関数型言語しかあげていないので, いままでこのことに気づかなかったのは, うかつだった。 今後は 「Python は, スクリプト言語界の Pascal」 と考えることにしよう。

投稿時刻 2007-01-22(丙辰) 15:51プログラミング | コメント (0)

Eclipse JDT コンパイラと javac の文法のちがい

Eclipse のことを書いていておもいだしたが, アノテーションに関して, Eclipse 3.2 の JDT がコンパイルできるのに, javac (1.5.0_06) ではコンパイルできないプログラムがあることをおもいだした。

たとえば, JUnit4 の @SuiteClasses アノテーションをつかって, こんな書きかたをした場合。

package samp;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ Sample1Test.class,
 Sample2Test.class,
 })
public class AllTests {
}

Eclipse JDT ではエラーなしにコンパイルできるのに, javac ではコンパイルできない。 「Sample2Test.class,」 の最後の「,」がなければコンパイルできる。

Java Language Specifications の 9章 を見るに,

ElementValueArrayInitializer:
        { ElementValuesopt ,opt }
ElementValues:
    ElementValue
    ElementValues , ElementValue

となっているので, さいごに「,」があっても構わないようだ。

Eclipse 上でコンパイルできたソースが javac からうまくコンパイルできないことは多いが, たいていはクラスローダーがらみ(nested jar とか)であって, こういう基本的なところでちがいがでるのはめずらしい。

投稿時刻 2006-09-05(丁酉) 13:11プログラミング | コメント (0)

MinGW で APR をコンパイル

Apache の APR 最新版 (1.3.0) は MinGW でビルドできるようになっているのを知ったので, やってみた。

  1. まず, Apache サイトの How To Use Anonymous Subversion の情報にしたがって, 最新の APR ソースを取ってくる。
  2. MinGW は, 公式サイト から, MinGW-5.0.3 をダウンロードして, これで G++ と make にチェックを入れてインストールすると, これは mingw-runtime-3.10, w32api-3.7, binutils-2.15.91, gcc-core-3.4.2, gcc-g++-3.4.2, mingw32-make-3.80.0-3 を取ってきて展開してくれる。 c:\mingw に入れた。
  3. 同じところから MSYS-1.0.9 をダウンロードして, c:\msys\1.0 にインストール。
  4. MinGW の公式サイトから msysDTK-1.0.1 をダウンロードして, MSYS と同じ場所にインストール。
  5. ビルドに Python が必要なので, Python 公式サイト から Python 2.4.3 をダウンロードしてインストール。 c:\python に入れる。
  6. ここから先は MSYS の sh を使って作業する。 私の場合, MSYS とはべつな sh が動いていて干渉するので, 環境変数 SHELL, ENV を修正してから msys の sh を起動するバッチを書いた。 ENV で指定するスクリプトには, 「PATH=/usr/bin:/c/mingw/bin:/c/python:$PATH」 とのみ書いておく。 /etc/fstab を作る必要はとくにない。
  7. MinGW 公式サイトから msys-autoconf-2.59 と msys-libtool-1.5 をダウンロードしてくる。 どちらも MSYS のシェル上から tar.bz2 を / に展開するだけでよい。
  8. APR のディレクトリに移動して, 「./buildconf ; ./configure ; make ; make install」 で APR が /usr/local にインストールされる。

以上。 結果だけ書けば簡単そうだが, じっさいは MSYS に慣れずにひどく試行錯誤したので, 書いておく。

投稿時刻 2006-09-04(丙申) 12:02プログラミング | コメント (0)

JPerl のスクリプトを Perl 5.8.x で動かすためのメモ

いまごろ…… といわれそうだが, なるべくスクリプト自身をかきなおさずに Perl 5.8.x で JPerl のスクリプトを動かす方法についてのメモ。 動作は Windows XP 上の Active Perl 5.8.6 で確認した。

  1. 文字列を単なるバイト列としてあつかってかまわない (正規表現のパターンマッチなどをかける必要がない) のであれば, なにも変更しなくてよい。
  2. スクリプトの中にシフトJIS がでてくるばあい, シフトJIS の 1文字を Perl に 1文字として認識させるためには, 「use encoding 'SJIS';」を指定する。 この指定によって,
    1. ソースの中のシフトJIS を自動的に UTF-8 にエンコードしてくれる。
    2. 標準入出力で自動的に SJIS と UTF-8 の変換をやってくれる。
    「use encoding 'SJIS';」 をソースに書きこむかわりに, Perl のコマンドラインオプション 「-Mencoding=SJIS」 を指定しいてもよい。
  3. しかし, これでは <> をつかって読むファイルや, open で開くファイルについて自動変換をかけてもらえないし, なぜか STDERR への出力も自動変換がかからない。 それで, さらに「use open ':encoding(SJIS)';」 および, 「use open ':std';」 のふたつを指定する。 前者だけを指定すると, STDERR への出力に対応できないだけでなく, STDOUT への出力もおかしくなってしまう。 ソースを書きかえずに Perl のコマンドラインで指定するには, 「-Mopen=:encoding(SJIS) -Mopen=:std」 でよい。
  4. グロブの返す値などは自動変換されないので, ソースを書きかえて自前でエンコードする。 ソースの中で 16進文字列表現("\xNN") や, SJIS ソート順に依存した処理をしている場合も, てきとうに書きかえる。

さいしょ, 「:std」の使いかたがよくわからなかったため, use encoding と use open を両方指定すると STDOUT への出力がおかしくなってしまい, ひじょうに悩んだ。 「-Mopen=:encoding(SJIS)」 のかわりに, 「-Mopen=IN,:encoding(SJIS)」 として入力だけ変更し, STDERR はソースを書きかえて binmode で切りかえたりしていたが, 意味のない話だった。

投稿時刻 2005-05-06(庚寅) 11:01プログラミング | コメント (1)

整数の割り算とあまり(3)

C のばあいに補足。 C99 では, 「/」はかならず 0 に向かって切りすてることにあらためられた。

なお, div や ldiv は C99 にもある。 さらに long long int 用の lldiv というのもある。

投稿時刻 2005-03-16(己亥) 10:40プログラミング | コメント (0)

整数の割り算とあまり(2)

前回の補足。

Java の整数は 2の補数表現をとっているが, int x = Integer.MIN_VALUE; のとき, x/(-1) は x に等しい。 いっぽう, x%(-1) は 0 になる。 いずれのばあいも例外は発生しない。

また, このとき x*(-1) も x に等しくなるので, x == (x/y)*y + (x%y) はこのときも成立する。

Ada では, 制約のない型(整数でいうと, Pascal でいう部分範囲型でないもの) に対する演算の結果がその型の範囲をこえたとき, 例外を発生するかどうかは実装に依存する。 GNAT では例外を発生しないようである。

C の規格では, このようなばあいは, 0 で割ったばあいとおなじく, 未定義になる。

C# のばあい

C# の /, % 演算子は Java のばあいとまったくおなじ動作をする。

Fortran のばあい

Fortran では整数に対する除算演算子 / は 0 にむかって切りすてる。 また, 組みこみ関数 MOD(x,y) は Modula-2 の REM とおなじである。 Fortran 90 以降はもうひとつ MODULO(x,y) という組みこみ関数が追加されたが, こちらは Ada の mod 演算子と(y が負のときをふくめて)おなじうごきをする。

投稿時刻 2005-03-11(甲午) 11:07プログラミング | コメント (3)

整数の割り算とあまり

Pascal のばあい

整数の割り算 x div y は, x を y で割った結果を絶対値の小さくなるように切りすてた結果である。 あまりをもとめる演算子は存在せず, x - (x div y)*y をつかう。

これとはべつに x mod y があり, こちらは 0 以上 y 未満の値をかえす。 ただし y は正の整数でなければならない。 x が 0 以上であれば, x = (x div y)*y + (x mod y) がなりたつ。

ただし, ISO 7185 規格ができる前の Jensen and Wirth 2版では 「a mod b = a - ((a div b)*b)」 と書いてあることもあって, じっさいには mod を div に対応するあまりとして実装している処理系が多い。 Delphi や Free Pascal はそうなっている。 GNU Pascal は規格どおり実装している。

Ada のばあい

div 演算子はなく, 整数除算でも「/」をつかうが, Pascal とおなじく絶対値が小さくなるように切りすてる。 あまりを求める演算子には rem があり, x rem y = x - (x/y)*y である。

いっぽう Pascal とおなじ mod 演算子もある。 Pascal とことなり, x mod y の y が負であってもよい。 x と y の符号が等しいばあい, x rem y と x mod y は同じ値で, それ以外のばあいは, (x rem y) + (x mod y) = x である。

ひとつの言語に rem と mod の両方を用意したのはあまり評判がよくないようだ。 どっちかはパッケージで供給するようにすればじゅうぶんだったかもしれない。

Modula-2 のばあい

Wirth は DIV, MOD 演算子についてあちこちで矛盾した記述をしているが, ISO/IEC 10514 規格では, / REM DIV MOD の 4つの演算子が用意されている。 これは Wirth 「Algorithms & Data Structures」(1986) の記述とひとしい。

「/」「REM」「MOD」は同名の Ada の演算子とおなじ。 x DIV y は Pascal のものとちがって, x を y で割った結果以下で最大の整数を返し, つねに (x DIV y)*y + (x MOD y) = x がなりたつ。 ただし, Ada とことなり, x DIV y と x MOD y はいずれも y が正の整数のときのみ定義されている。

C のばあい

規格では, (x / y)*y + (x % y) == x がなりたつとするだけで, Modula-2 でいう「/, REM」の意味であるか, 「DIV, MOD」の意味であるかは処理系依存とする。 Rationale をみると, これをどちらかにさだめたいという意見はあったようだが, 却下されたようだ。 そのかわり, Modula-2 の「/, REM」とおなじ結果を返すことを保証する div および ldiv が標準ライブラリに用意されている。 「DIV, MOD」とおなじ結果を返す関数は用意されていない。 (C99 での変更について補足)

じっさいにためしたところでは, Intel Windows 用の処理系(Visual C++ 6 および 7, Borland C++ Builder 6, MinGW) および Sparc Solaris 用の処理系(Sun Studio 7, gcc) はいずれも 「/, %」が Modula-2 の「/, REM」とおなじ結果をかえした。

Java のばあい

「/」の意味は絶対値が小さくなるように切りすてると決められている。 Modula-2 の「DIV, MOD」にあたる演算子はないが, java.math.BigInteger クラスには remainder と mod のふたつのメソッドが定義されていて, それぞれ Modula-2 の REM と MOD にひとしい。 mod(x,y) は y が正の整数でないばあい, 例外を投げる。

なお, 日本語版の API ライブラリの解説の mod のところ で,

このメソッドは、常に「負でない」 BigInteger を返す remainder とは異なります。

とあるのは誤訳で, じっさいには remainder は負の値をかえすことがあるが, mod は負でない値をかえす。 英語原文 では,

This method differs from remainder in that it always returns a non-negative BigInteger.

と, 正しく記述されている。

投稿時刻 2005-03-11(甲午) 05:48プログラミング | コメント (1)

CLU の公式サイト

CLU の文法についてちょっと疑問があったので, MIT の 公式サイト にいってみたのだが, げんざい anonymous ftp が利用できないようだ。 うーんざんねん。

投稿時刻 2005-01-13(丁酉) 17:00プログラミング | コメント (0)

Page 1 of 1: 1