mfiler4 1.1.1のコンパイルエラーに対処する

はじめに

mfiler4というファイラーがあります。

http://sourceforge.jp/projects/mfiler4/

mfiler4 1.1.1をUbuntu 12.04LTSの環境でコンパイルしようとしたときに、以下のようなコンパイルエラーに遭遇しました。
git HEADでも状況は同様でした。

-[3527]% LANG=C make
gcc -DSYSCONFDIR="\"/home/kenhys/etc/mfiler4/\"" -DDATAROOTDIR="\"/home/kenhys/share/doc/mfiler4/\"" -DSYSTEM_MIGEMODIR="\"/usr/share/cmigemo\"" -Isrc/ -I/home/kenhys/include -L/home/kenhys/lib -I . -I/usr/local/include -L/usr/local/lib -Werror   -c -o src/filer.o src/filer.c
src/filer.c: In function 'make_file_stat':
src/filer.c:1441:9: error: format '%d' expects argument of type 'int', but argument 4 has type '__nlink_t' [-Werror=format]
src/filer.c:1441:9: error: format '%d' expects argument of type 'int', but argument 4 has type '__nlink_t' [-Werror=format]
src/filer.c: In function 'cmdline_view_filer':
src/filer.c:2530:13: error: format '%d' expects argument of type 'int', but argument 5 has type '__nlink_t' [-Werror=format]
src/filer.c:2530:13: error: format '%d' expects argument of type 'int', but argument 5 has type '__nlink_t' [-Werror=format]
src/filer.c:2549:12: error: format '%d' expects argument of type 'int', but argument 5 has type '__nlink_t' [-Werror=format]
src/filer.c:2549:12: error: format '%d' expects argument of type 'int', but argument 5 has type '__nlink_t' [-Werror=format]
cc1: all warnings being treated as errors
make: *** [src/filer.o] Error 1

問題点とパッチ

64bit環境と、それ以外では型修飾子に指定すべきものが違う、というのが肝です。
そこで以下のようにしてみました。longかそうでないかで分岐します。

diff --git a/src/common.h b/src/common.h
index b724127..1b65350 100644
--- a/src/common.h
+++ b/src/common.h
@@ -38,6 +38,12 @@
 
 #define S_IXUGO (S_IXOTH | S_IXGRP | S_IXUSR)
 
+#if defined(__x86_64__)
+    #define FORMAT_HARDLINK "%3ld"
+#else
+    #define FORMAT_HARDLINK "%3d"
+#endif
+
 //////////////////////////////////////////////
 // main.c
 ///////////////////////////////////////////////
diff --git a/src/filer.c b/src/filer.c
index 2d03879..d52eaa8 100644
--- a/src/filer.c
+++ b/src/filer.c
@@ -1436,7 +1436,7 @@ static void make_file_stat(sFile* file, char* buf, int buf_size)
 
     char* env_nlink = getenv("VIEW_NLINK");
     if(env_nlink && strcmp(env_nlink, "1") == 0) {
-        snprintf(buf + strlen(buf), buf_size -strlen(buf), " %3d", file->mStat.st_nlink);
+        snprintf(buf + strlen(buf), buf_size -strlen(buf), " "FORMAT_HARDLINK, file->mStat.st_nlink);
     }
 
     char* env_owner = getenv("VIEW_OWNER");
@@ -2516,7 +2516,7 @@ void cmdline_view_filer()
         while(year > 100) year-=100;
         
         snprintf(buf2, 1024, 
-            "%s %3d %-8s %-7s%s %02d-%02d-%02d %02d:%02d %s"
+            "%s "FORMAT_HARDLINK" %-8s %-7s%s %02d-%02d-%02d %02d:%02d %s"
             //, "%s %3d %-8s %-7s%10lld %02d-%02d-%02d %02d:%02d %s"
             , permission, file->mLStat.st_nlink
             , owner, group
@@ -2534,7 +2534,7 @@ void cmdline_view_filer()
     }
     else {
         snprintf(buf, 1024,
-           "%s %3d %s%s%s %02d-%02d-%02d %02d:%02d %s -> %s"
+           "%s "FORMAT_HARDLINK" %s%s%s %02d-%02d-%02d %02d:%02d %s -> %s"
            //, "%s %3d %s%s%10lld %02d-%02d-%02d %02d:%02d %s -> %s"
            , permission, file->mLStat.st_nlink
            , owner, group

これともうひとつcursesがらみでもエラーになる部分がありました。
そちらはA_*がunsigned longとして定義されていることに由来するものです。

-[3508]% grep A_REVERSE /usr/include/**/*.h
/usr/include/curses.h:#define WA_REVERSE	A_REVERSE
/usr/include/curses.h:#define A_REVERSE	NCURSES_BITS(1UL,10)
/usr/include/ncurses.h:#define WA_REVERSE	A_REVERSE
/usr/include/ncurses.h:#define A_REVERSE	NCURSES_BITS(1UL,10)
/usr/include/ncursesw/curses.h:#define WA_REVERSE	A_REVERSE
/usr/include/ncursesw/curses.h:#define A_REVERSE	NCURSES_BITS(1UL,10)
/usr/include/ncursesw/ncurses.h:#define WA_REVERSE	A_REVERSE
/usr/include/ncursesw/ncurses.h:#define A_REVERSE	NCURSES_BITS(1UL,10)

こちらについても、パッチは似たような感じになります。

diff --git a/src/main.c b/src/main.c
index 8ebe03c..e95ac19 100644
--- a/src/main.c
+++ b/src/main.c
@@ -541,11 +541,11 @@ static void set_mfenv()
     setenv("nometa", buf, 1);
     snprintf(buf,128, "%d", 1);
     setenv("meta", buf, 1);
-    snprintf(buf,128, "%d", A_REVERSE);
+    snprintf(buf,128, "%ld", A_REVERSE);
     setenv("ma_reverse", buf, 1);
-    snprintf(buf,128, "%d", A_BOLD);
+    snprintf(buf,128, "%ld", A_BOLD);
     setenv("ma_bold", buf, 1);
-    snprintf(buf,128, "%d", A_UNDERLINE);
+    snprintf(buf,128, "%ld", A_UNDERLINE);
     setenv("ma_underline", buf, 1);
     snprintf(buf,128, "%d", COLOR_PAIR(1));
     setenv("ma_white", buf, 1);

まとめ

mfiler4を64bit環境でコンパイルするための方法を紹介しました。
それでは良いmfiler4ライフを。