看原始碼的利器-gj

好像是在看推還看噗的時候看到的,fcamel 大自己刻的工具gj,今天才在試,發現很方便,找關鍵字很快。使用方法很簡單,先安裝 id-utils (sudo apt-get install id-utils),然後在你要看原始碼的目錄下,輸入 mkid 先建立資料庫,之後就可以用gj keyword 列出有keyword的檔案並讓你選擇要看哪個檔案。如果你用 gj keyword keyword2 就表示要在有 keyword 的檔案裡再去找看有沒有 keyword2,依此類推。

預設是用 vi 去編輯檔案,要改的話,就稍微改一下 gj 即可,gj 是用python寫的喔~

 

電影流水帳(2012/1/27~2012/2/7)

E3 2010 Megamind demo area

  • Megamind(IMDB, Wikipedia),台譯:麥克邁-超能壞蛋。卡通片,還可以,當初要上片時,還有跟Zynga的Farmville合作打廣告,所以農場裡就有大大的Megamind雕像。Megamind跟Metroman從小就是宿敵,一直打到長大,一直打打打,打到有一天,Metroman不想玩了,就假藉一場爆炸逃走。Megamind接掌了城市,卻發現沒有了對手,生活失去意義,所以他就利用Metroman的DNA做出藥劑,並且不小心把女記者的攝影師變成了新的超人。在這段時間裡,他也不小心變成另外一個人跟女記者交往,一段時間下來,他們愛上了彼此。新的超人得到新的力量,發現事情跟他想的不一樣,沒有辦法順心如意,就決心為惡,然後跟Megamind槓了起來。Megamind被打的落花流水,去找了假死的Metroman,Metroman拒絕出來。後來Megamind就運用他的智慧跟手段,最終打敗了新的超人,成為新的真正的英雄。
  • Captain America(IMDB, Wikipedia),台譯:美國隊長。好莫名其妙然後理所當然的就結束了。Rogers 很希望從軍,無奈就是太瘦小。後來碰到神秘的博士,為了實驗品為了他的善良把他找進來。找進來觀察了一陣子,發現真不錯,就幫他注射了。噹噹,成功變成大隻佬,變身以後,並不是立刻投身戰場,而是被當作吉祥物來募款用。直到後來到了歐洲,他發現自己不受歡迎,然後自己朋友又被抓了,就毅然決然單身匹馬進去救人,一陣亂砍之後,救出了一堆人,跟紅骷髏結下樑子。接下來就是一陣亂打,最後知道紅骷髏要去轟炸美國各大城市了,就來個總決戰,不過沒有很歡樂的結局,紅骷髏被強大的力量轟碎,Rogers跟飛機一起掉到北極當冰粽子。到了現代,神盾局的人發現了他,就把他救了起來,準備成立復仇者聯盟。令我最有印象的地方是,Rogers、女主角跟Chester(Tommy Lee Jones)一起開車去追紅骷髏,Rogers要跳上飛機前,女主角跟Rogers親吻,然後Rogers再看著Chester,Chester說了一句很妙的話:「I’m not kissing you.」

Harbour Project – Hello world

The Harbour Project is a Free Open Source Software effort to build a multiplatform Clipper language compiler. Harbour consists of the xBase language compiler and the runtime libraries with different terminal plugins and different databases (not just DBF).

Harbour is a cross-platform compiler and is known to compile and run on MS-DOS, Windows (32 & 64), Windows CE, Pocket PC, OS/2, GNU/Linux and Mac OS X.

簡單的說,Harbour是Clipper的替代品,目前可以運行在很多平台上,雖然說跟Clipper/VFP同是xBase類的語言,但是還是有很大的差異,這些差異可以從文件裡看出來。不過Harbour有相當大的優勢,就是速度跟平台,它會先把 prg 轉譯為 C 語言,再編譯出執行檔,再者,它可以裝到很多平台上。對被拋棄的xBase語言的開發者來說,是可以考慮看看的。

Linux 上的安裝很簡單,就去Harbour下載網頁找到你的Linux版本,點進去,找到檔案下載即可,我是用Ubuntu,就到binaries-linux-ubuntu下,下載 .deb 檔案。下載以後,執行sudo dpkg -i harbour_3.0.0-1_i386_ubu_10.04-2.deb 就安裝好了。

接下來就寫程式,副檔名是.prg,就建立一個hello.prg,內容就像這樣

&& Output "hello world"
? "Hello world"

&& Create table,沒有VFP的create table,還真的有痛苦到。
local aDbf := {}
AADD(aDbf, { "Fld1", "N", 3, 0 })
AADD(aDbf, { "Fld2", "C", 4, 0 })
AADD(aDbf, { "Fld3", "C", 20, 0 })
DBCREATE("table1",aDbf)

use table1
browse()  && browse 不再是指令,而變成函式了。
close all

執行 hbrun hello.prg 就可以直接執行,看到結果。使用 hbmk2 hello.prg 就可以編譯出執行檔 hello,輸入 ./hello 就可以執行。

pip freeze與還原

用virtualenv,除了可以建出一個開發環境之外,也不會因為distribution不支援而扼腕,然後也可以輕易地安裝、搜索跟反安裝。另外一個好處就是可以輕易的把整份環境給凍結起來。用 pip freeze > requirement_file 可以把開發環境中有安裝的package都列出來,然後再用 pip install -r requirement_file 就可以裝回去。

dateutil.parser解析日期時間字串出現”iter() returned non-iterator of type ‘_timelex'”

之前用python-dateutil的parse在解析字串是沒問題的,結果今天用的時候,卻出現 “iter() returned non-iterator of type ‘_timelex'” 的錯誤,仔細看過,發現之前用的是1.5,而目前用的卻是2.0。上官方網站去看,發現1.5是for Python2,而2.0是for Python3,為什麼不能相容呢?一時之間也無法解決,乾脆就降級用回1.5了,還好用virtualenv跟pip,還蠻簡單的,就先 pip uninstall python-dateutil 再 pip install python-dateutil==1.5 就行了。

電影流水帳(2012/1/20~2012/1/26)

2011_rise_of_the_planet_of_the_apes-wide

  • Rise of The Planet of The Apes(IMDB, Wikipedia),中譯:猩球崛起。很好看的電影,是多年前決戰猩球的前傳,描述為什麼地球會演變成猩猩變成高等人類的星球。其實就是Will為了解決父親老人癡呆症的問題,而去研發出一種新的病毒作為新藥,經過實驗,猩猩的智力的確有驚人的成長。後來,因為某些變故,使實驗室主持人下令將這批猩猩銷毀,但是有一隻小猩猩,Robert不忍心下手,就交給了Will。小猩猩Caesar繼承了媽媽的血,也有高等智慧。經過數年之後,小猩猩越發聰明了,而Will偷偷把還沒人體試驗的藥物用在自己的父親身上,也得到了很好的成效。但是,隨著時間過去,Will發現父親的免疫系統已經開始可以抵抗病毒,老人癡呆症也愈來愈嚴重。Will決定冒險開發新的藥物,以解決父親的病症,於是他告訴實驗室主持人說自己已經拿父親試驗過,希望可以開發新的藥物。實驗室主持人在知道藥物有效之後,就決定繼續進行研發計劃。就在藥物快要完成的時候,出現了實驗室意外,Robert不小心吸入了病毒。而Will的父親老人癡呆症也越發嚴重,讓猩猩Caesar為了救他而讓鄰居嚇到,並因此被關到動物管制中心。Caesar在管制中心裡並不愉快,很想要離開,但是受限於法律,Will沒辦法。過了一段時間,聰明的Caesar偷到了小刀,並且收買了中心裡最強壯的猩猩,對抗欺負他的猩猩,然後成為中心裡領袖的角色,為了讓同伴更加聰明,他去Will的實驗室偷到新藥物給猩猩,讓所有的猩猩變得非常聰明。某天,這些猩猩就發難逃了出去,引起軒然大波,並逃到了舊金山北邊的Redwood。而Robert去Will家裡找不到Will的情況下,讓Will的鄰居感染了病毒,而Will的鄰居剛好又是機長,要飛到全世界,於是病毒擴散到整個世界,剛好這個時候又有太空人飛到太空去。飾演Caesar的角色其實是Andy Serkis,之前曾經飾演過Gollum,也難怪在講猩猩的時候,讓人真的以為他是人。
  • Attack of the 50 Foot Woman(IMDB, Wikipedia),中譯:巨型女的襲擊。自己笨,被簡介跟海報騙了,特技效果不突出(1993年的電影)、故事普普,而且還看了國語配音的,才看了沒幾分鐘,就沒耐心地開始亂跳著看完。主角Nancy被丈夫背叛,被父親操控,整個很不爽。有一天被飛碟的光照到,然後就變大了。變大以後,心智也慢慢改變,所以後來就愈來愈不爽,就開始發飆。後面被直昇機打到,就昏倒,被飛碟救走,被救走的時候,她花心的老公也被帶走,片尾是3個巨型女在飛碟裏面看3個花心男在那邊吵架的畫面。

 

參考資料:

電影流水帳(2012/1/9~2012/1/19)

little mermaid
三部片。

  • The adjustment Bureau(IMDB, Wikipedia),中譯:命運規劃局。這應該算是一部頗揪心的愛情片。男主角David參加眾議員競選,投票前被爆了醜聞,結果沒上。要發表落選演說時,遇到女主角Elise,一見鍾情又一見傾心,還沒來的及留下電話,就分開了,David因此發表了一篇不凡的落選演說。後來,David要上班時,竟然在公車上巧遇Elise,兩人超happy,互留了電話。David到了辦公室,發現好奇怪,一堆人都被停住了,他遇到了The adjustment team正在調整眾人的思維,他就拼命逃,可是還是沒能逃過The adjustment team的魔掌。他被警告說,不可以洩漏我們的存在,在Elise的電話號碼被撕掉以後,David被放走。之後,The adjustment team裡的Thompson出來偷偷告訴David一些事情,David只好放棄。隔了3年之後,David上班途中竟然再次看到Elise,重新邂逅,The adjustment team出來強制干預,並要脅David,跟Elise分開的話,你會變成總統,Elise會變成知名舞者,如果不從,Elise的腿可能就不只是扭傷而已。於是David為了Elise好,就把Elise丟在醫院,忍痛走了。又隔了好一陣子,David在報上看到Elise要結婚了,他真的不能忍受,而Elise也很猶豫,透過Thompson的幫助下,David成功的阻婚,並在The adjustment team的阻撓下,逃到了某大樓上。最後的結局是,The adjustment team其實是天使,而命運則是由上帝寫的,因為上帝很感動,就改寫了他們兩人的命運,然後就沒了。
  • Detroit Metal City(IMDB, Wikipedia),中譯:重金搖滾雙面人。根岸熱愛音樂,在大學畢業後,卻誤進了重金屬搖滾的唱片公司,組成了Detroit Metal City,非常的紅。某天,他遇到了大學時代心儀的舊識由利,開心的聊了起來。之後發生了一連串的誤會,並且又不小心成了日本最紅的樂團,成了美國重金屬搖滾樂團的目標。就在這個時候,他被由利很深的誤會,非常灰心,回去老家。在老家,他扮為克勞薩二世,教訓了弟弟,並且,也接受母親的開導而想開,決定回到東京接受挑戰。最後就以戰勝美國重金屬樂團而告終。裏面蠻多好笑的片斷,像是社長弄息煙的方式跟克勞薩二世在老家開割草車等等,蠻好看的片。
  • Pirates of the Caribbean: On Stranger Tides(IMDB, Wikipedia),中譯:神鬼奇航-幽靈海。還算可以的續集片,沒什麼特別的亮點。就一堆人陰錯陽差去找不老泉,有人是為了報仇,有人是為了生命,有人是去看熱鬧,有人是去搞破壞。Sparrow跟Gibbs有地圖,是知道路的人,主要是去看熱鬧順便把黑珍珠號拿回來的,Barbossa去報Black beard的仇,Black beard是為了生命,他快死了,豈知後來因此而死,西班牙國王去搞破壞,他不允許有東西超越上帝賜與人的生命。最後就是泉水被西班牙破壞,Barbossa得償所願,Black beard掛掉,Angelica被放逐,Sparrow跟Gibbs拿到黑珍珠號跟其他一堆船,看起來是還會有續集的樣子。

ping in Android(續)

後來發現裏面有包ping這指令,而且有設置setgid權限,那麼應該是可以執行。只是試了之後,卻不行,然後我就以為不行。之後不死心,把stderr接出來看,才知道我下錯指令,於是修正以後,就可以了。

[java]
final class Helper {
private final String TAG=”Helper”;
private void pingInExec(String host) {
Runtime runtime = Runtime.getRuntime();
String command = String.format(“/system/bin/ping -c 2 %s”, host);
Process proc;
try {
proc = runtime.exec( command );
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

String inputLine;
while ((inputLine = in.readLine()) != null) {
Log.d(TAG, inputLine );
}
in.close();
while ((inputLine = err.readLine()) != null) {
Log.e(TAG, inputLine );
}
err.close();
proc.waitFor();
int exit = proc.exitValue();
Log.d(TAG, String.format(“exitcode=%d”, exit) );
if (exit == 0) { // normal exit
Log.d(TAG, “RESPONSE_OK”);
} else { // abnormal exit, so decide that the server is not reachable
Log.d(TAG, “RESPONSE_TIMEOUT” );
}
} catch (IOException e) {
Log.e( TAG, e.getMessage() );
} catch (InterruptedException e) {
Log.e( TAG, e.getMessage() );
}
}
}
[/java]

ping in Android

上網找了一下,一般對於ping的建議是直接利用java內建的InetAddress.isReachable()來做,實際上在ping內部網路的伺服器時,是沒問題的,但是如果要ping位於外部網路的伺服器時,就會失敗而回傳False。

Android內部的實作是在libcore/luni/src/main/java/java/net/InetAddress.java裡,這裡就很簡單的建立socket,然後試著連到指定位址的port 7,如果可以連,或者是伺服器明確地拒絕,就視為伺服器存在,可以連線。這就解釋了為什麼無法ping位於外部網路的伺服器,因為ISP為了安全或是其他考量,而不允許。我分別以python與java寫了與Android實作相似的程式去實驗,的確都不行。

[python]
import sys
import socket

if len(sys.argv)<2:
print( “Need at least 1 parameters.” )
print( “Usage: {0} host”.format( sys.argv[0] ) )
sys.exit(-1)

r = False
try:
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.settimeout(5)
s.connect( (sys.argv[1], 7) )
r = True
except socket.error, ex:
if ex.errno==111:
r = True
else:
print( ex )

if r:
print( “{0} is reachable.”.format( sys.argv[1] ) )
else:
print( “{0} is NOT reachable.”.format( sys.argv[1] ) )
[/python]

[java]
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.IOException;

class Ping {
public static void main(String[] args) {
InetAddress in;

try {
in = InetAddress.getByName(args[0]);
boolean result = in.isReachable(5000);
if (result) {
System.out.println(“Response OK”);
}
else {
System.out.println(“Response fail”);
}
} catch (UnknownHostException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
[/java]

Java裡只能建立 stream(TCP) 或 dgram(UDP) 的socket,那麼只能用JNI,用C寫ping了,但經過實驗結果,發現會因為權限的關係而無法建立socket,原來要建立raw與IPPROTO_ICMP的socket,需要root權限。一般linux裡,非root使用者可以使用ping,是因為ping加上了setuid權限,才能使用。在Android裡,要不就是建立service,要不就是設法為ping加上setuid,否則是都無法使用的。

Get IP Address in Android

這篇Get the ip address of your device on Android Development其實就講的很清楚了,就是用NetworkInterface.getNetworkInterfaces()去取得所有網路介面,然後再用網路介面的getInetAddresses()去看該網路卡上的所有IP位址,然後把Loopback位址排除掉,就可以取得了。該開的權限有android.permission.INTERNET與android.permission.ACCESS_WIFI_STATE。

我工作上的需求,是要拿到3G那邊的IP,經過實驗,發現在WiFi開啟的情況下,只會拿到WiFi網路介面的IP位址,而非3G網路介面的。如果把WiFi網路介面關閉,就可以拿到3G網路介面的IP。我以為是程式邏輯的關係,可是在確認過NetworkInterface.getNetworkInterfaces()傳回的網路介面數量以後,發現都是取得兩個網路介面,而非我預期的三個。好,那我不使用NetworkInterface.getNetworkInterfaces()改用NetworkInterface.getForName()去取的話,在WiFi開啟的情況下,取得的結果會是null,也就是說該網路介面被關掉了。

直接去看底層,在 mydroid/libcore 下NetworkInterface的JNI函式,那邊是使用netlink去跟kernel問所有的網路介面,然後解析之後傳回。那麼底層應該是沒有問題,看來是中間層為了能取得較快的網路速度,而自動把3G網路介面給關閉了。看來也只能在程式執行前,先把WiFi給關閉,才能取得3G網路介面的IP位址了。

參考資料: