ibus 1.4.0在gvim里的输入问题

ibus 1.4.0在gvim里有些问题。具体来说,启动gvim之后数秒内无法输入,之后控制台输出
(gvim:77687): IBUS-WARNING **: Process Key Event failed: Timeout was reached
这句话,之后在gvim里可以输入,但是用不了输入法。
根据研究貌似是gvim的问题,FreeBSD的vim还停留在7.3.121,而新的vim,例如7.3.315就没有问题。
这个问题的报告:
http://code.google.com/p/ibus/issues/detail?id=1249
https://bugzilla.redhat.com/show_bug.cgi?id=673438
有个workaround是gvim -f,但是毕竟麻烦。
于是手工改了个vim 7.3.315的port,用着挺好…… 除了切输入法的时候会输入一个空格以外……

FreeBSD的vim留在7.3.121是有原因的。首先是7.3.122这个补丁打完之后无法编译。
其实7.3.122是说,不附带src/auto/config.mk,在顶级目录Makefile里加上自动复制src/config.mk.dist为这个文件……
但是可能是BSD这边编译方法的问题,没有直接跑顶级Makefile,于是缺文件…… 其实自己复制过去就好了。

之后是7.3.225这个补丁打不上。貌似原因是patch数错行数了…… 或许是^M这些东西的关系。
解决方法是在test79.in和test79.ok最后加些只有”+”的行。加到正好数量对为止…… 反正这俩文件也没啥关系

于是现在用着vim 7.3.315,感觉很好…… ibus也没有问题……

更新ibus和ibus-pinyin的ports到1.4.0

其实早就该更新的…… 不过之前尝试了一下,觉得1.4.0不咋的,还有些问题,于是没管……
结果终于有好心人搞了个1.4.0的patch,还群发邮件说各位基于ibus的ports的maintainer们,快更新吧!
他顺便还加上了GTK3支持的选项,看来大家都要渐渐向GTK3迁移了么……

在那个patch的基础上,提了些修改,现在在等待commit……
具体来说:
* 貌似其实ibus不依赖Qt?为啥从前加上去了呢…… 于是去掉了
* 没有post-deinstall这个target的,应该在pkg-plist里用@unexec来执行卸载命令的……
所以从前的ibus port删除之后,是不会更新gtk2的immodules列表的…… 这么多时间了也没人发现……

为了这个,ibus-pinyin也更新到1.4.0。但是ibus-pinyin 1.4.0居然要编译器支持c++0x…… BSD的古老的gcc 4.2怎么行……
于是就让port依赖gcc 4.4+,没办法…… 其实ibus-pinyin还有个替代选项是用boost,但是开了之后没法编译。虽说打个补丁应该可以,但是太麻烦…… 另一个好处是,现在就不依赖boost了……
其他更改:
* 不知道为啥,ibus-pinyin有个${DBTAR}在DISTFILES里,而这个东西没定义过…… 删了删了
* 去掉boost支持,反正依赖gcc 4.4+了……
* RUN_DEPENDS单独定义。这个是portlint说的,说BUILD_DEPENDS其实还有别的东西,不能直接赋给RUN_DEPENDS
* 目前禁用lua扩展。反正也没人用……
* 加了俩选项,选择是否编译Android DB和OpenPhrase DB。貌似是俩词库,OpenPhrase 那个挺大……
* 加了选项是否依赖opencc进行简繁转换

ibus 1.4.0在gvim里有些问题,换篇文讲吧……

于是就等待commit了~

NTFS分区丢文件的问题……

之前发生了好几次,在FreeBSD下往NTFS分区拷东西,结果之后去win下一看,不见了……

关于这个问题,找到过一个原因:如果先启动BSD,然后卸载某个NTFS分区,开一个直接使用那个NTFS分区的Win虚拟机,Suspend那个虚拟机,挂上那个分区,写东西,卸载,再Resume并正常关闭那个虚拟机,文件就会丢……
这个问题挺好理解的,就是Win虚拟机自己保存了一些数据结构,你在Suspend期间对那个分区写的内容,Win虚拟机不知道。等他把数据结构flush回去,自然中间的改动就丢了……

之后还是出这个问题,最近又找到一个原因:如果往NTFS分区复制文件,之后用reboot命令重启,文件也会丢……
这个原因貌似是reboot是个很彪悍的命令,它不运行rc.d里那些脚本来停止服务,直接对所有进程发SIGTERM…… 于是cache里的数据没flush出去,那些文件就丢了……
不过貌似这样文件是丢了,可用空间却会变少…… 如果在Win下检查NTFS分区,会说已使用位图不正确……

以后不用reboot了…… 要不要直接alias掉呢……
说起来init 6倒是没有问题…… shutdown -r自然也没有问题…… 这些都是好好地先停掉服务的……

inline, weak symbol以及其他

首先,如果某个test.h里有如下内容:

class A {
public:
	int x();
}
 
int A::x()
{
}

那如果只有一个test.cpp引用了它:

#include "test.h"
 
int main()
{
	A a;
	a.x();
}

那还好。但如果还有一个test2.cpp引用了它:

#include "test.h"
 
int foo()
{
	A a;
	a.x();
}

然后把test.cpp和test2.cpp分别编译成.o,再链接,就会报错:

> g++ test.o test2.o -o test
test2.o(.text+0x0): In function `A::x()':
: multiple definition of `A::x()'
test.o(.text+0x0): first defined here

因为两个里面都有A::x()这个symbol嘛,很正常。

这个时候,你会想到,如果inline了,不就好了么!

class A {
public:
	int x();
}
 
inline int A::x()
{
}

恩,的确这样就没有问题了,因为A::x()被inline了。你看test.o的符号表,也找不到这个东西。

但是有时候你会有一些ws的想法。你想,如果A::x()太复杂,inline不了,那编译器不就sb了么!

于是你尝试把A::x()改成bt一些的东西:

class A {
public:
	int x(int no);
};
 
inline int A::x(int no)
{
	if (no == 1)
		return 1;
	else if (no == 2)
		return 1;
	else 
		return x(no-1) + x(no-2);
}

嘛,就是算Fib数列么,但是有这种递归了,你丫就不好inline了吧。

试一试,诶,test.o的符号表里果然出现了A::x():

00000000 W _ZN1A1xEi

或者来c++filt一下

00000000 W A::x(int)

test2.o里也有了这个东西。

但是链接却成功了!而且工作得也挺正常。为了保证靠谱,我们让这俩东西有依赖:
修改test.cpp

#include "test.h"
 
extern void foo();
 
int main()
{
	A a;
	a.x(10);
	foo();
}

试一试,诶,还是可以的!

那就是说,inline虽然实际上没成功,但是程序员看起来还是成功了的。秘密应该就在那个符号里:
可以注意到符号名前面有个W,也就是说,这是个weak symbol…

俩weak symbol碰一起,既然名字一样,那就合并了吧……
如果没有inline呢?看看老的.o:

00000000 T A::x(int)

这就是一普通的symbol。俩这种symbol碰一起,就算multiple def,俩weak碰一起,就不算……

那既然要合并,应该要内容一样才能合并吧?难道编译器比较了内容?不可能吧……
于是,我们就会有更加ws的想法:万一不一样呢?

再搞一个test2.h,基本和test.h一样,但是A::x()实现有点不同:

class A {
public:
	int x(int no);
};
 
inline int A::x(int no)
{
	if (no == 1)
		return 1;
	else if (no == 2)
		return 2;
	else 
		return x(no-1) + x(no-2);
}

嘛,虽然很难看出来,但是这个数列往后移了一位……

改改test2.cpp,让他引用test2.h。随后分别把test.cpp和test2.cpp编译成.o。看这俩.o,他们的A::x()符号看上去一模一样……
链接一把,嘿,还能成……

随后就会好奇么,到底是啥情况?各自用各自的?调某一个的?如果是某一个,哪个?
把结果打出来看看么:
改test.cpp:

#include "test.h"
#include <iostream>
using namespace std;
 
extern void foo();
 
int main()
{
	A a;
	cout << "test ret: " << a.x(10) << endl;
	foo();
}

和test2.cpp:

#include "test2.h"
#include <iostream>
using namespace std;
 
int foo()
{
	A a;
	cout << "test2 ret: " << a.x(10) << endl;
}

分别编译成.o,链接,一点问题都没有…… 结果呢:

test ret: 55
test2 ret: 55

还真合并了,还调到同一个上去了…… 这里其实已经出bug了:既然我inline了,那我应该用的是自己引用的那个.h,也就是说,应该是不同的……
刚才是用

 g++ test.o test2.o -o test

链接的。如果换个顺序呢?

 g++ test2.o test.o -o test

结果是:

test ret: 89
test2 ret: 89

变了…… 看来对于俩weak symbol,先看见的会被采用…… 这个55就是test.h里那个的结果,89是test2.h里那个的……

那如果一个weak一个普通呢?我们把test.h里的inline删了,再试试看。
这次,不管啥顺序,结果都是55了,也就是说,普通symbol比起weak symbol,有决定性的优势……

本文写到这里就差不多了。反正对于这个事情,还是把类实现放.cpp里好……
或许你觉得冲突概率很小。但是如果不是C++而是C呢?万一你恰好和另一个库的函数重名了呢?万一有一个还是inline呢?
所以还是大家都C++并且用名字空间的好……

嘛,其实这个问题基本上是不会出现的,虽说用来考C++啥的,倒是有可能…… 但是这个是标准规定的现象还是编译器自己搞的事情,还有待研究……