十月 30, 2011
» Extending Gforth with the Code Word

很久沒發文了,但一直都有記錄筆記的習慣,原本也是打算整理好發表的,但常常寫到一半就去做其他事了,所以積了不少未完成的稿XD 這次出清一篇筆記,來談談 forth 中的 code word。

一般對於 forth 系統的擴展有兩種方式,最方便的當然是定義新的 colon word,另一種則是實作比較低階的 code word。

code word 代表的是低階實作,也就是直接跟底層平台對話。以 lisp-based forth 為例,其實就是把 lisp vm 當作(虛擬)硬體平台,因此 code word 作用大概就是產生一堆 lisp form,而 x86 native forth 當然就是產生 x86 machine code 了。

簡單地說,code word 需要負責兩件事:

  • 產生 native code
  • 讓 forth 可以順利執行這些 native code

產生 native code 的工作通常會由一個 target assembler 負責。這也是為什麼一個完整的 forth system 多半會提供自己的 assembler。雖然 forth 已經是可擴展的設計,但在需要直接操作宿主平台時,可能會需要寫成 code word 比較方便。

比較麻煩的是第二點,讓 forth 可以順利執行的關鍵在於不能干擾系統運作。forth 本身雖然是 stack vm,但還是有幾個基本的暫存器,一般在 x86 上會對應到實際的暫存器。依照實作模型的不同,可能會需要佔用 2 至 5 個不等。在 code word 中必須妥善管理這幾個暫存器,不是單純 pushapopa 就可以解決的。最常見的狀況,就是維護 SP 的值 (forth 中的 SP 暫存器,非 x86 的),確保參數可以正常傳遞,不會發生 underflow;以分支指令來說可能需要修改 IP 的值,只要改錯暫存器就會發生災難。因此第一步就是找出這幾個暫存器的對應關係。

在一般的 forth 系統中,通常會提供一個叫做 see 的 disassembler,可以透過它來猜出系統的規劃。Gforth 套件提供了好幾種實作,由於接下來的實驗在不同實作中會有不同結果,為了方便解說只使用 gforth-fast。在 Gforth 中,第一個建議觀察的是什麼事都不會做的 noop

see noop
Code noop
( $804B1BF )  add     esi , # 4  \ $83 $C6 $4
( $804B1C2 )  mov     ebx , dword ptr FC [esi]  \ $8B $5E $FC
( $804B1C5 )  mov     eax , ebx  \ $89 $D8
( $804B1C7 )  jmp     804B03C  \ $E9 $70 $FE $FF $FF
end-code

從這邊可以猜到不做事的時候,系統大概會使用 eaxebxesi,然後跳到某個位址繼續執行。因此觀察其他 word 的時候就可以先去除這幾個動作,找出真正關鍵的操作。接下來建議的是 dupdrop。這兩個 word 是基本的堆疊操作,可以直接找出 SP 在哪,甚至可以看出是否有加入 TOS (Top Of Stack) 的快取設計,也就是將 TOS 放在特定的暫存器以減少一次記憶體操作。

see drop
Code drop
( $804C836 )  add     edi , # 4  \ $83 $C7 $4
( $804C839 )  add     esi , # 4  \ $83 $C6 $4
( $804C83C )  mov     ebp , dword ptr [edi]  \ $8B $2F
( $804C83E )  mov     ebx , dword ptr FC [esi]  \ $8B $5E $FC
( $804C841 )  mov     eax , ebx  \ $89 $D8
( $804C843 )  jmp     804B03C  \ $E9 $F4 $E7 $FF $FF
end-code

drop 的內容可以看到除了 noop 以外,還操作了 edi,沒有意外的話 SP 就是它了。同時也知道堆疊往低位址成長 (因為 drop 相當於做了一次 stack pop)。作為佐證可以再觀察一下 dup,應該會看到減少 edi 內容值的運算:

see dup
Code dup
( $804C85D )  sub     edi , # 4  \ $83 $EF $4
( $804C860 )  add     esi , # 4  \ $83 $C6 $4
( $804C863 )  mov     dword ptr 4 [edi] , ebp  \ $89 $6F $4
( $804C866 )  mov     ebx , dword ptr FC [esi]  \ $8B $5E $FC
( $804C869 )  mov     eax , ebx  \ $89 $D8
( $804C86B )  jmp     804B03C  \ $E9 $CC $E7 $FF $FF
end-code

看起來的確有移動 edi 內容的操作。另外還看到奇怪的動作,把 edp 的內容搬進 stack top – 1 的位置,並不是移動到 stack top,推測 可能有 TOS 的設計。

要證實這一點,可以再看一下 swap+ 這幾個會影響 TOS 的 word。

see +
Code +
( $804B918 )  add     ebp , dword ptr 4 [edi]  \ $3 $6F $4
( $804B91B )  add     esi , # 4  \ $83 $C6 $4
( $804B91E )  add     edi , # 4  \ $83 $C7 $4
( $804B921 )  mov     ebx , dword ptr FC [esi]  \ $8B $5E $FC
( $804B924 )  mov     eax , ebx  \ $89 $D8
( $804B926 )  jmp     804B03C  \ $E9 $11 $F7 $FF $FF
end-code

看來的確是把運算後的結果 (TOS) 直接放到 ebp 了,而不是放在記憶體中。拿到 SPTOS 後就可以試著增加一個 code word 看看了。首先用最簡單的 dup 操作來驗證前面的猜測,實作一個有相同操作的 _dup

code _dup
    bp di ) mov
    4 # di sub
    next
end-code

3 _dup .s

可以看到堆疊中的確出現兩個 3 了。不過看起來自己實作的 _dup 好像比原版的 dup 還要精簡一點。另外也可以寫個 _+ 看看:

code _+
    4 # di add
    di ) bp add
    next
end-code

2 3 _+ .s

結果也正確無誤,留下一個 5。到這邊已經可以做很多事了。不過偶爾可能會需要 RP,所以從 >r 找到 RP 放在記憶體的某處。查找的過程不再列出,同樣複製一個相同的 _>r 來驗證看看:

code _>r
    4 # $3c sp d) sub
    3c sp d) bx mov
    bp bx ) mov

    4 # di add
    di ) bp mov
    next
end-code

為了維護 return stack, >rr> 通常要平衡使用才不會破壞系統運作,所以我將自己實作的 _>r 搭配系統的 r> 一起使用,測試過可以正常執行。

除了這幾個重要的暫存器外,還有一個 IP,可以透過觀察 branch 找到,這裡就不再贅述了。不過還有一件重要的事需要特別提出來討論。在整理這篇筆記的過程中,我發現一個嚴重的問題:以前實驗的結果,在 0.7.0 版的 gforth-fast 可以正常運作,但換成 0.7.9 版卻無法動作,後來試了一下 0.6.2 也同用無法執行。查了文件才知道原因在於 c compiler 版本。由於不同版本的編譯器執行 register allocation 結果可能不同,會產生出完全不一樣的 forth vm,這點是特別要注意的。前面列出來的結果是在 gcc 4.4.4 建立出來的 gforth-fast 0.7.9 的環境重新實驗的。如果使用到的暫存器剛好都是自由的 (不被系統使用),換系統時就不需要再調整程式了。

雖然聽起來有點糟,但對我來說也不算什麼大問題就是了。畢竟 forth 在各系統間的相容性本來就不能期待,會想使用 code word 的人大概對正在使用的系統也有一定的掌握能力了,這樣程度的相容性問題應該都有能力處理。


會翻出這篇筆記,主要是看到有人做了一個 benchmark,gforth-fast 需要的時間是其他 forth 的好幾倍,想試試把幾個關鍵處改寫成 code word,看有沒有機會加速。最後實驗的結果是… 不行!

囧rz

非但沒變快,反而更慢了XD 也許 Gforth 在切換成 code word 可執行環境時做了很多事,因此效能不如全部都使用 colon word;也許是 instruction miss 等原因造成的吧。這個一時興起的實驗提醒了我在選系統時要記得同時測試一下 code word 的使用,暫時還是先把 Gforth 的 assembler 當作 cross assembler 使用吧。


Filed under: forth, Note

十月 26, 2011
» TestPost

不好意思,之前發現 emacs 沒辦法發出文章了,這篇文章單純測試用 測完沒問題就刪掉 <!–more–> 測試程式碼 <pre class="src"> <span style="color: #00cdcd;">init</span>: <span style="color: #00cd00;">xor</span> ax, ax <span style="color: #00cd00;">mov</span> ds, ax <span style="color: #00cd00;">mov</span> es, ax </pre> <p>測試<a target="_blank" href="http://www.google.com/">超連結</a>是否正常</p> <ol> <li>item 1</li> <li>item 2 <ul> <li>qwer <ul> <li>abcde</li> </ul></li> <li>tyui</li> </ul></li> <li>item 3 <ul> <li>mjkl</li> <li>eoru</li> </ul></li> <li>item 4</li> </ol>

五月 4, 2009
» [Note] 送patch所學到的事

這個Note是一個寫patch的經驗,前陣子寫了一個讓curl即時壓縮加密FTP/HTTP/SFTP上傳時可以續傳的一個patch,patch本身倒是沒什麼特別的,反而是在送patch跟原作者的討論過程中學到了一些東西。patch歷時約一個月才commit進cvs,不過我覺得以open source的專案來說,這樣算挺快的。

似乎還是得把前因後果交代一下,
其實一開始是我有一個想法,
就是希望我上傳到遠端伺服器的檔案都能加密起來(順便壓縮更好),
但是我覺得在local這邊先壓縮過然後再上傳的話,就會佔Local的硬碟兩份空間,所以最好的方法是realtime壓縮加密之後上傳。這樣就不會佔用local的硬碟空間,而以目前的CPU也應該都可以做到即時傳輸。
此外我希望就是能夠彈性的選擇壓縮及加密方式,不論是bz2,gzip,pkzip或是pgp及AES都要能夠自行選擇及combine。
而且最好是不需另外的伺服器程式,以目前hosting都會提供的FTP帳號就能做的方法是最好。(我需要的不是像SFTP或FTP/TLS這樣傳輸時加密或壓縮而已,我想要的是在伺服器上的最終結果也是加密及壓縮過的)

跟lloyd討論之後,他是認為lftp+namepipe的方式可行。
另外我也找到了用pipe透過curl上傳的方法。
而這兩個方法也都驗證過確實可行,不過這兩個方法都同樣有個問題,就是沒辦法續傳,而這我認為是個應該要解決的問題。

比較了兩個解決方案後,我選擇了擁有我比較喜歡的BSD license,用法也比較彈性的curl下手修改,
curl的續傳問題大概長這樣:

gzip /mnt/2311/debian-500-i386-CD-1.iso -c | curl -T - -C -
ftp://myname:mypass@192.168.23.11/debian-500-i386-CD-1.iso.gz
** Resuming transfer from byte position 46792704
% Total % Received % Xferd Average Speed Time Time Time
% Current
Dload Upload Total Spent Left
Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:--
0
curl: (31) Could not seek stream

最主要是stdin不能直接SEEK_SET,這其實不是什麼大問題,不能SEEK_SET就SEQUENCIAL READ並bypass即可,看了一下原始程式便發現其實這段code早已大部完成了,只要略為更動即可,
於是略為修改了一下curl FTP/SFTP/HTTP上傳部份的code,驗證之後便將patch送出。
原以為送出patch之後就結束了,因為作者要收不收這也不是我能控制的,不過後來curl的作者回信說,功能是沒有問題,但原本的patch會影響到ABI與目前文件的相容性,問看看我是否能提供不修改ABI的作法,我原本還無法理會作者的意思,後來繼續討論才慢慢了解,作者的意思是看能否提供完整的ABI及定義回傳值供其他使用curl library部份的程式參考,因為curl不僅僅是一個客戶端程式curl,同時也包含一套廣泛的運用在其他程式甚至內建在程式語言中的library,libcurl。即使是改動小小的部份,也有可能不經意的影響到其他重要的程式。
了解了作者的目的之後,於是我又寫一個新的patch配合這個架構,測試一下續傳上傳沒問題之後就又再次的送出,這次作者將我的多個patch檔結合後又修改了一下包括說明文件的patch就直接commit到cvs上,不過問題來了,做make test的測試到HTTP PUT該項時沒過。
仔細的研究一下,還真的是第二次更動的code造成了問題。第三次的修改並驗證之後,這次就很快的patch就被接受了,目前已經commit在curl的cvs上。

這次寫patch得到一些經驗:

1. 寫patch時應配合原程式的架構及style,會比較容易被接受。
2. 寫完patch之後應照原程式的測試方式做一遍測試,而非只是測試自己的情況。
3. 大部份時候都要仔細考慮並聆聽來自原作者的意見,畢竟他是最清楚全部情況的人。
4. 不要懶的送patch,雖然可能會多費一些時間跟功夫,但送了patch通常可以學到更多。

ref: 我和curl作者討論的過程,https://sourceforge.net/tracker/?func=detail&atid;=100976&aid;=2709004&group;_id=976

二月 11, 2009
» Line wrap in Emacs

在大部份的編輯器中,對付太長的文字列通常用的是自動換行 (line wrap),就我目前所知,在 Emacs 中有以下幾種不同方式可以選擇:

Line wrap

預設行為即是一般常見的 line wrap。在這種環境下的文字內容並不會被更動,僅在顯示時將超出視窗邊界的部份顯示在下一行,同時在換行處加上一個記號 (如箭頭標示處):


在切割視窗時情況不同:


可以設定一下得到相同行為:

(setq truncate-partial-width-windows nil)


Truncation

打開 truncate line 以後,超出視窗邊界的部份不顯示,同時會在邊界處顯示一個特殊符號作為識別 (與 line wrap 時用的符號不同)。一般適合在寫程式的時候使用

M-x toggle-truncate-lines


也可以寫到 .emacs

(setq default-truncate-lines t)

為了方便可以設個快速鍵:

(global-set-key [f11] 'toggle-truncate-lines)

Filling text

fill 是破壞性操作,會根據 fill-column 的值強制在特定位置插入換行字元。手動操作時只需要按下 M-q 即可,或是乾脆啟用 auto fill:

M-x auto-fill-mode


fill-column

換行寬度可以自行修改,因為設定 fill-column 要求一個數值當作參數,:

C-u 60 M-x set-fill-column

C-u 60 C-x f

fill-prefix

fill-prefix 的內容會自動加到被修改的文字列前面,預設為 nil (代表換行後前面不加任何字)。假設 fill-prefix"… ",則換行後會在該列最前面加上 "… "

設定這個參數可以用 set-fill-prefixC-x .,要注意的是這個動作會將游標所在位置前的同列文字設為 fill-prefix,若在斷行處操作,則整列文字都會被採用。因此我建議透過 eval 方式設定:

M-: (setq fill-prefix "... ")

或乾脆寫進 .emacs


fill prefix 對於整理程式碼註解很有幫助,但對於一般文字也許會造成困擾。要取消 fill-prefix 只需要找個空行再設定一次即可 (minibuf 會顯示 "fill-prefix cancelled")

Long line mode

相較於 fill mode,long line mode 則是溫和的非破壞性操作,只是在顯示上調整成 fill mode 的效果 (soft newline),並不會真的插入換行 (hard newline):

M-x longlines-mode


但顯示與實際內容畢竟有差別,可以將真正的換行處以特殊符號表示以資識別:

M-x longlines-show-hard-newlines


在處理長文字列的顯示上,Emacs 提供了豐富的設定以應付各種需求。就我個人來說,對於一般的文章我習慣用 line wrap 型式顯式;而在編輯程式碼的時候,這種方式反而會破壞縮排的視覺效果,這時改用 truncation 就很適合了。至於 long line mode,我到現在還沒用過。當然,一般編輯程式碼的時候很少會出現超長的程式碼 (也許寫 gtk 程式時例外XD),閱讀上非常不便。非不得已的時候,我會想辦法在 80 columns 內先斷行 (以前留下來的習慣@@),非超出視窗不可的部份,就交給強大的編輯器來處理吧!

Reference


Posted in emacs, Note

二月 5, 2009
» 透過 Outline mode 編輯 Muse 文稿內容

前陣子在使用 muse 撰寫筆記的時候,總覺得要找標題不太方便,似乎也沒辦法透過 speedbar 顯示大綱,玩了半天就想到了 outline mode 這個好東西,剛好語法是一樣的,只要簡單配置一下就可以帶來很大的方便。測試了一下後加了一些設定:

(add-hook 'muse-mode-hook
	'(lambda ()
	   (outline-minor-mode t)))

(define-key muse-mode-map (kbd "<f5>")  'outline-up-heading)
(define-key muse-mode-map (kbd "<f6>")  'outline-backward-same-level)
(define-key muse-mode-map (kbd "<f7>")  'outline-forward-same-level)
(define-key muse-mode-map (kbd "<f8>")  'outline-next-heading)
(define-key muse-mode-map (kbd "<f12>") 'outline-toggle-children)
(define-key muse-mode-map (kbd "C-<f12>") 'outline-mark-subtree)

(define-key muse-mode-map (kbd "C-<f5>") 'outline-promote)
(define-key muse-mode-map (kbd "C-<f6>") 'outline-move-subtree-up)
(define-key muse-mode-map (kbd "C-<f7>") 'outline-move-subtree-down)
(define-key muse-mode-map (kbd "C-<f8>") 'outline-demote)

在進入 muse mode 的同時也啟用 outline minor mode,並設定一些快速鍵以便快速在各個標題之間定位。事後在調整內容次序時,還可以整個 subtree 一起調整,不必再笨笨地用 copy & paste 修改了。


Posted in emacs, Note

十月 19, 2008
» Blogging with Emacs

玩了幾個晚上,總算可以順利從 emacs 裡將文章送到 Blog 了。 自從開始用 emacs 後就一直改用 muse 在寫筆記和報告,設定好以後可以透過 LaTeX 轉換成 PDF 檔,相當方便。用習慣後也曾興起透過 muse 寫 Blog 的念頭,找了很多資料,也知道有很多人實作成功,但說真的要拿來用還是有點問題,主要還是 elisp 不熟,而且大部份的實作竟然都是直接在 emacs 裡寫 html 後送出去 (還有人推薦用 nxml);就算直接在後台寫也有方便的 wysiwyg editor,但 emacs 還有 muse 這個好東西,何必那麼苦命呢。

» Blogging with Emacs

玩了幾個晚上,總算可以順利從 emacs 裡將文章送到 Blog 了。

自從開始用 emacs 後就一直改用 muse 在寫筆記和報告,設定好以後可以透過 LaTeX 轉換成 PDF 檔,相當方便。用習慣後也曾興起透過 muse 寫 Blog 的念頭,找了很多資料,也知道有很多人實作成功,但說真的要拿來用還是有點問題,主要還是 elisp 不熟,而且大部份的實作竟然都是直接在 emacs 裡寫 html 後送出去 (還有人推薦用 nxml);就算直接在後台寫也有方便的 wysiwyg editor,但 emacs 還有 muse 這個好東西,何必那麼苦命呢。

目前的做法還是透過 xml-rpcweblogger,後來找到有人針對 wordpress 的修改,安裝上並不難,只需稍微自訂一下就可以使用。

首先必須透過 weblogger-setup-weblog 建立設定檔,可以有多組設定,每一組設定會有一個名字作為識別。要注意的是預設並不儲存密碼,往後傳送資料時必須手動輸入。如果想偷懶可以設定一下 weblogger-save-password,建立設定資料時就會自動儲存密碼。

開始撰寫文章時先 M-x weblogger-start-entry,會自動建立簡單的樣板,填入 Subject 與內容即可。需要加上 Category 的話,可以在 header section 手動加入一行 "Keywords: ",各分類之間以逗點分隔 (必須是 server 上存在的 Category 名稱)。目前似乎還不支援 Tag。發布文件的方式很簡單,熱鍵跟存檔一樣是 C-x C-s,也可以用 C-c C-c 存成 Draft。日後需要修改時也可以把文章抓回來修改後再回存,相當方便1

Weblogger 的使用不難,比較麻煩的是跟 muse 銜接的部份,研究了一晚找出需要的資料結構,原來是建構在 message-mode 之上,所以得先產生類似 message header 的資料。這部份我直接以 html style 為基礎,建立一個新的 muse style 來處理:

(muse-derive-style "my-blog" "html"
                   :suffix ".wp.html"
                   :header
"Subject: <lisp>(muse-publishing-directive \"title\")</lisp>
From: <lisp>(muse-publishing-directive \"author\")</lisp>
Keywords: <lisp>(muse-publishing-directive \"desc\")</lisp>
--text follows this line--
"
                   :footer ""
                   :browser   'find-file
                   :regexps `((100000 "!!more!!" 0 more) )
                   :functions '((more . muse-mywp-markup-more))
                   :strings '(
(image-link      . "<a target=\"_blank\" class=\"image-link\" href=\"%s\">
<img src=\"%s.%s\"></a>")
(url             . "<a target=\"_blank\" href=\"%s\">%s</a>")
(link            . "<a target=\"_blank\" href=\"%s\">%s</a>")
(link-and-anchor . "<a target=\"_blank\" href=\"%s#%s\">%s</a>")))

當然在 project 部份也要新增一個項目

(setq muse-project-alist
	'(("blog" ("~/Note/blog" )
		(:base "my-blog" :path "~/Note/blog/convert"))))

本來的想法是找出 muse 資料的產生方式,直接丟到 webloger buffer,但是一堆括號看到頭暈,所以用了比較笨的方式:先用 muse 轉換過,再呼叫修改過的 weblogger 函式將結果轉換出必要的資料結構,最後丟上 server。

修改這些其實還算簡單,但我有個需求是要同時送到多個地方備份用,這可要我命了…因為裡面一堆全域變數,從帳號設定對應到內部資料結構的部份又太複雜 (誰說用 functional language 不會有 side-effect…XD),所以我還是用最笨的方式,每次連線前先重置相關的全域變數:

(defun muse-blog-start-entry ()
  (unless weblogger-entry-ring
    (setq weblogger-entry-ring
      (make-ring weblogger-max-entries-in-ring)))
  (ring-insert weblogger-entry-ring '(("content" "")))
  (setq weblogger-ring-index 0)
  (unless weblogger-server-username
    (setq weblogger-server-username ""))
  (unless weblogger-server-password
    (setq weblogger-server-password ""))
  (weblogger-edit-entry (weblogger-entry-buffer-to-struct)))

(defun muse-blog-send-post (&optional blogConfName)
  "send current to blog"
  (unless blogConfName
    (read-from-minibuffer "Select a blog conf: " blogConfName))
  (setq weblogger-server-username nil)
  (setq weblogger-server-password nil)
  (setq weblogger-server-url nil)
  (setq weblogger-weblog-id nil)
  (weblogger-select-configuration blogConfName)
  (weblogger-start-entry)
  (set-buffer-modified-p t)
  (weblogger-save-entry t)
  (bury-buffer))

(defvar muse-blog-conf-name-alist nil)

(defun muse-blog-publish ()
  (interactive)
  (when muse-blog-conf-name-alist
    (mapcar 'muse-blog-send-post muse-blog-conf-name-alist)))

使用前需要先設定 muse-blog-conf-name-alist,內容是一個字串的 list,就是先前在 weblogger 中建立的 profile 名稱,發布文章時就會丟到所有在清單中的 Blog 位置。

muse 文稿的部份,要注意的是利用了三個 directives:title、author 與 desc,分別對應到 message header 中的 Subject、From 與 Keywords。以本文為例,開頭的前幾行如下:

#title Blogging with Emacs
#author letoh
#desc note, emacs

產生出來的 header 如下:

Subject: Blogging with Emacs
From: letoh
Keywords: note, emacs
–text follows this line–

到這樣已經相當好用了,同一份 muse 文件除了生成 LaTeX / ConTeXt 文稿或 PDF 外,也可以發布到 Blog 上,當然產生 static page 或整理起來變成 Wiki 更不是問題。只剩一個小小的缺憾,就是還沒把 blogger 分舵加進來,因為 blogger 已經不用 xmlrpc,改用 Blogger Data API 了,這兩天再努力看看吧。有任何建議也歡迎指教。


1. 實際使用後發現抓回來的文章如果包含 <!--more--> (wordpress 設定摘要位置用的記號),只會抓回摘要的部份;此時若回存會把文章後半部份蓋掉XD 修改方法還在研究中…


Posted in emacs, Note

» Blogging with Emacs

玩了幾個晚上,總算可以順利從 emacs 裡將文章送到 Blog 了。 自從開始用 emacs 後就一直改用 muse 在寫筆記和報告,設定好以後可以透過 LaTeX 轉換成 PDF 檔,相當方便。用習慣後也曾興起透過 muse 寫 Blog 的念頭,找了很多資料,也知道有很多人實作成功,但說真的要拿來用還是有點問題,主要還是 elisp 不熟,而且大部份的實作竟然都是直接在 emacs 裡寫 html 後送出去 (還有人推薦用 nxml);就算直接在後台寫也有方便的 wysiwyg editor,但 emacs 還有 muse 這個好東西,何必那麼苦命呢。

十月 16, 2008
» Emacs 發布測試

test for blogging with emacs
透過 emacs 來寫 blog

Todo:

  • fetch entry 後,延伸閱讀以後的資料會抓不到 (也許是透過 rss/atom 抓 description 而已),此時再存檔的話,當初沒抓下來的資料就會變成光了
  • 拿掉 auto-fill-mode
  • 整合 muse (目前看到有日本人實作過),這樣等於間接把 local preview 做好
  • multi-server configuration
  • categories auto-completion (以前用 python 寫過,但現在得用 elisp 寫…囧rz)
  • 自訂 ping-slug (印象中在 api 裡有看到)

Posted in ACG, emacs, Note

八月 31, 2008
» 統計檔案大小

隨手寫了一個 script,用來統計檔案大小

#!/usr/bin/perl -p
BEGIN { my $total = 0; }
/(\d+)/; $total += $1;
END { print “Total: $total\t” . ($total / 1024) . “M\n”; }

存成 ts 後可以搭配 duls -s 使用,或者是輸出為每一行開頭有數字的任何指令,例如 seqnl

$ seq 5 | ts
$ ls / | nl | ts

當然這只是好玩而已,沒什麼實際用途

突然想到這幾年陸續接觸了幾種不同的程式語言,包括平日使用最多的 python。但日常使用其實很少出現複雜的應用,大多數情況用 perl 處理起來還是簡潔多了 (雖然這個 perl script 寫得有點像 awk script…)

最後附一下 awk 版:

BEGIN { total = 0 }
total += $1
END { print “Total:”, total,”\t”,total/1024,”M” }


» 統計檔案大小

隨手寫了一個 script,用來統計檔案大小

六月 22, 2008
» VirtualBox 1.6.2

由於 sane 不支援我的 scanner,為了試試透過 virtualbox 存取 scanner,這兩天在家把新版裝起來玩…

» VirtualBox 1.6.2

由於 sane 不支援我的 scanner,為了試試透過 virtualbox 存取 scanner,這兩天在家把新版裝起來玩…

根據網路上看到的使用心得,新的 1.6.2 版似乎在 usb 的支援上增強不少,但為了在 guest OS 裡抓到 usb device 也費了不少工夫,一度還以為只有 windows 版才有改進…搞了一個下午才順利偵測到 scanner

網路沒設,主要是處理 usb 的部份,記錄一下大概的步驟:

  1. 新增 usbusers 群組,把自己的帳號加進去
  2. 修改 /etc/rc.d/rc.S 中 mount usbfs 的命令,加上 -o devgid=<gid of usbusers>,devmode=664 (我用的 distro 是 Slackware)
  3. 修改 /etc/udev/rules.d/65-permissions.rules,加一行 SUBSYSTEM=="usb_device", GROUP="usbusers", MODE="0664"
  4. 在 virtualbox 中加入 usb device filter (vid 和 pid 可以透過 lsusb 查到)

處理完以後啟動 guest OS 就可以抓到 device 了,為了證明可以啟動 scanner,掃張圖來看看


六月 20, 2008
» libreadline.so.5: undefined symbol: PC

這兩天在 slackware 12.1 環境編譯一個有用到 readline 的程式,可是搞了老半天編譯好的程式都沒有 readline 跟 history 的功能。測試一下發現會出現 undefined symbol 的訊息,按照 maillist 上提供的指令 ldd -d -r /usr/lib/libreadline.so.5.2 出現這些訊息: undefined symbol: PC (/usr/lib/libreadline.so.5.2) undefined symbol: UP (/usr/lib/libreadline.so.5.2) undefined symbol: BC (/usr/lib/libreadline.so.5.2) undefined symbol: tgetflag (/usr/lib/libreadline.so.5.2) undefined symbol: tgetent (/usr/lib/libreadline.so.5.2) undefined [...]

» libreadline.so.5: undefined symbol: PC

這兩天在 slackware 12.1 環境編譯一個有用到 readline 的程式,可是搞了老半天編譯好的程式都沒有 readline 跟 history 的功能。測試一下發現會出現 undefined symbol 的訊息,按照 maillist 上提供的指令 ldd -d -r /usr/lib/libreadline.so.5.2 出現這些訊息:

undefined symbol: PC (/usr/lib/libreadline.so.5.2)
undefined symbol: UP (/usr/lib/libreadline.so.5.2)
undefined symbol: BC (/usr/lib/libreadline.so.5.2)
undefined symbol: tgetflag (/usr/lib/libreadline.so.5.2)
undefined symbol: tgetent (/usr/lib/libreadline.so.5.2)
undefined symbol: tputs (/usr/lib/libreadline.so.5.2)
undefined symbol: tgoto (/usr/lib/libreadline.so.5.2)
undefined symbol: tgetnum (/usr/lib/libreadline.so.5.2)
undefined symbol: tgetstr (/usr/lib/libreadline.so.5.2)

查了一下發現這些東西在 libtermcap 裡,比較簡單一點的方法就是修改 Makefile 或 build script,在 linking 時加上 libtermcap 即可


六月 15, 2008
» Device driver check page

Debian GNU/Linux device driver check page 在 kerneltrap 上看來的網站,把 lspci -n 的結果丟進去即可,相當方便

» Device driver check page

Debian GNU/Linux device driver check page 在 kerneltrap 上看來的網站,把 lspci -n 的結果丟進去即可,相當方便

六月 13, 2008
» Ramdisk test

最近弄到 4G ram 可以揮霍,不玩一下 ramdisk 對不起自己…

» letoh

最近弄到 4G ram 可以揮霍,不玩一下 ramdisk 對不起自己… 首先試著跑一下 64bit Linux 的 Live CD,的確可以直接抓到 4GB 記憶體。不過暫時應該繼續跑 32bit OS,如果不特別處理的話只能抓到 3G 左右的記憶體,因此參考了網路上的一些資料開始做實驗,把 32bit OS 抓不到的空間拿來當 ramdisk 使用 Linux 編輯 kernel 設定,開啟 PAE 後重新編譯安裝 (要選 64GB,如果只選 4GB 重開機後還是只看得到 3.2GB) 設定 tmpfs,若沒有指定大小,預設是系統記憶體最大值的一半 (也就是 2GB) Windows 下載 Gavotte Ramdisk 執行 ram4g.reg 後,執行 ramdisk.exe 設置 ramdisk。圖文版操作可以參考這篇文章 裝完馬上就可以看到 ramdisk 跑出來了,系統內容顯示的記憶體大小一樣是 3.25GB (沒有被 ramdisk 吃掉) 為求保險重開機看看,第一次重開機發生 signal out of range,螢幕沒有畫面 (感覺是我的硬體不穩…) 強制重開機後順利進入系統,初步看起來正常,而且 boot.ini [...]

四月 2, 2008
» virtual module in cvs

最近遇到一個小問題,在 cvs 上的檔案都是以 module 來分類,如果有一個 project 組裝了多個 module,每次要 co 下來總是麻煩。最簡單的方式就是把這些 module 通通搬進同一個目錄,這樣只要把 root module 拉下來就可以了。但是偶爾也會遇到 sub module 被多個 project 所組裝,這時不是將共用的 sub module 多複製幾份,就是把所有 project 都丟進同一個 root module (我知道這種方法蠢到爆…)。

A Feedjack powered Planet
A Django site.