printfデバッグ様のお通りだー - らんだむな記憶入口は正しそうだと分かったが、その先がよく分からん。これだとprintfデバッグのコストが大分高くつく。ということで、気が進まないがgdbを使おう。
bootstrapのほうはあまり見たくなくて、configureのほうをいぢくっとく。
$ diff -Naur configure.orig configure --- configure.orig 2016-01-02 00:38:43.520700700 +0900 +++ configure 2016-01-02 00:41:57.829813638 +0900 @@ -5215,7 +5215,7 @@ CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then - CFLAGS="-g -O2" + CFLAGS="-g -ggdb -O0" else CFLAGS="-g" fi
で、本当にうまくいっているか不安なので、ビルド時にverboseなログを見たい。個人的には常に見たいけど「CC hoge」みたいな恥ずかしがり屋なビルドログにしていることが多い。すべて晒せ!ということで、
./configure --disable-silent-rules
して再ビルド。「-g -ggdb -O0」が見えるね。いけてそう。
...おや?「fontforge」自体はシェルスクリプトなのか...。最近こういうの多いな...。実行形式の上にスクリプトが薄いwrapperとして用意されているやつ。面倒なんだよねー
よいしょっと。
$ diff -Naur fontforge.orig fontforge --- fontforge.orig 2016-01-02 00:56:05.153294137 +0900 +++ fontforge 2016-01-02 00:57:30.591995002 +0900 @@ -114,7 +114,8 @@ $ECHO "fontforge:fontforge:${LINENO}: newargv[0]: $progdir/$program" 1>&2 func_lt_dump_args ${1+"$@"} 1>&2 fi - exec "$progdir/$program" ${1+"$@"} + gdb "$progdir/$program" ${1+"$@"} + #exec "$progdir/$program" ${1+"$@"} $ECHO "$0: cannot exec $program $*" 1>&2 exit 1
で、
(gdb) b charview.c:CVMenuRound2Int No source file named charview.c.
あれ?めんどいなぁ~... まだ該当部分のコードがメモリ上にロードされてないってこと??
後からattachしてみるかな。
$ gdb --pid=`ps aux | grep lt-fontforge | grep -v grep | awk '{print $2}'` ... Attaching to process xxxx Could not attach to process. If your uid matches the uid of the target
あら、なんかダメだ。う~む。
よく分からんので、一旦gdbをかませた状態で起動させて、rで当分走らせておいて、グリフ一覧が出た頃合いで、Ctrl+Cでgdbのコンソールを呼び出す。そして、
(gdb) b charview.c:CVMenuRound2Int Breakpoint 1 at 0x7ffff786503a: file charview.c, line 9707.
で、なんかbreak point置けたね。色々よく分からんけど、まぁ、いいや。
それ、また走っとけ。
(gdb) c
で、ぽちぽちぽちっと。よっしゃ、来たッ
Breakpoint 1, CVMenuRound2Int (gw=0x900dd0, UNUSED_mi=0x90f4f0, UNUSED_e=0x7fffffffb5f0) at charview.c:9707 9707 printf("*** CVMenuRound2Int: enter\n"); (gdb) list 9702 } 9703 CVCharChangedUpdate(&cv->b); 9704 } 9705 9706 static void CVMenuRound2Int(GWindow gw, struct gmenuitem *UNUSED(mi), GEvent *UNUSED(e)) { 9707 printf("*** CVMenuRound2Int: enter\n"); 9708 { 9709 CharView *cv = (CharView *) GDrawGetUserData(gw); 9710 _CVMenuRound2Int(cv,1.0); 9711 }
で、n, n, sとか。ステップ実行、ステップイン。dddとかのGUIフロントエンドかまさんとやってられんな。
(gdb) s SplinePointRound (sp=0x913d40, factor=1) at splinechar.c:711 711 if ( sp->prev!=NULL && sp->next!=NULL && sp->next->order2 && (gdb) list 706 } 707 708 void SplinePointRound(SplinePoint *sp,real factor) { 709 BasePoint noff, poff; 710 711 if ( sp->prev!=NULL && sp->next!=NULL && sp->next->order2 && 712 sp->ttfindex == 0xffff ) { 713 /* For interpolated points we want to round the controls */ 714 /* and then interpolated based on that */ 715 sp->nextcp.x = rint(sp->nextcp.x*factor)/factor; (gdb) n 724 noff.x = rint((sp->nextcp.x - sp->me.x)*factor)/factor; (gdb) p sp->me.x $1 = 407.2998046875 (gdb) p sp->nextcp.x $2 = 417.7998046875 (gdb) p factor $3 = 1
それっぽく値がとれてる。Unified Font Object表現で言えば、最初のアンカーとコントロールポイントのx座標が以下だからね。
<outline> <contour> <point x="407.3" y="696.2" type="curve" smooth="yes"/> <point x="417.8" y="699.9"/>
う~ん。SplinePointRound @splinechar.c を見ている感じだと、ここは素朴な計算に見えるなぁ。座標丸め後のデータは問題ないけど、これをUnified Font Objectに変換して出力するほうがまずいのかもしれんなー。
(gdb) b splinechar.c:724 Breakpoint 2 at 0x7ffff58c39de: file splinechar.c, line 724. (gdb) condition 2 sp->me.x > 164 && sp->me.x < 165 && sp->me.y > 52 && sp->me.y < 53 (gdb) c Continuing.
で問題の起こる箇所に関する条件でブレークさせてみる。
ふーむ。特別な何かという感じでもないな。
条件付きのbreak pointについては次のサイトを参考にした: gdb の使い方・デバッグ方法まとめ
―――――・・・
printfデバッグのコストが大分高くつくとか以前に、年賀状の住所とかblogのタイトル用の自分フォントを用意しちゃおうかなぁーとかいう動機から考えてこんなことをしているのはコスト高すぎだろということにそろそろ気付く。
作業用BGMを欠かすことができない。年始からエアコンの効いた部屋で徹夜でデバッガですゎとか洒落にならん(汗)