manywaypark's Blog
개발, 검색, 함수

현재 진행중인 프로젝트에 cl-ftp를 사용해 자동화 하는 모듈을 작성 중이다. 그런데 cl-ftp의 기능들 중 내가 원하는 기능은 대부분 잘 작동했다. 제일 중요한 파일 다운로드만 빼고... T.T
약간의 공부와, 약간의 삽질 끝에 cl-ftp를 조금 손보았더니 제대로 동작했다.
내경우에는 다음과 같은 에러를 내면서 파일 다운로드가 실패했다.
error message:
The value -117 is not of type (UNSIGNED-BYTE 8).
  [Condition of type TYPE-ERROR]
msb가  1인 바이트가 음수로 읽혀지는 듯했다 (나중에 확인해본 결과 실제로 그랬다).
ftp.lisp의 소스를 좀 뒤졌더니 소켓을 생성할 때 cl-acl-compat 패키지의 acl-socket.lisp 내의 make-socket()을 이용해 소켓을 생성하고 있었다. 다음은 make-socket()의 일부다.
(defun make-socket (&key
......
(let ((element-type (ecase format
(:text 'base-char)
(:binary 'signed-byte)
(:bivalent 'unsigned-byte)))
......
ftp.lisp에서는 make-socket()을 부를 때 :binary 또는 :text를 사용할 수 있으며, :binary의 경우 (unsigned-byte 8) stream에, :text의 경우 character stream에 저장하게 되어있었다. 양쪽에서 :binary를 처리하는 방식이 다르니 에러가 날수 밖에 없어 보였다.
데이터 전송 소켓 생성 부분인 ftp.lispestablish-data-transfer()에서,
;;; ftp.lisp
;;; change underlined :binary to :bivalent.
(defmethod establish-data-transfer
......
(let ((data-socket
(make-socket :remote-host dtp-hostname
:remote-port dtp-port
:format (ecase type
((:binary :image) :binary)
(:ascii :text)))))
......
(let ((server-socket (setup-port conn
:format (ecase type
((:binary :image)
:binary)
(:ascii :text)))))
......
밑줄친 :binary를 전부 :bivalent로 바꾼후 테스트를 해보니 정상적으로 동작했다.

편의를 위해 패치를 첨부한다.
patch file:
--- ftp.lisp.ORIG       2007-08-04 16:44:18.000000000 +0900
+++ ftp.lisp 2007-08-04 18:09:20.000000000 +0900
@@ -307,7 +307,7 @@
(make-socket :remote-host dtp-hostname
:remote-port dtp-port
:format (ecase type
- ((:binary :image) :binary)
+ ((:binary :image) :bivalent)
(:ascii :text)))))
(when (and rest (integerp rest))
(send-raw-line conn (format nil "REST ~A" rest)))
@@ -317,7 +317,7 @@
(let ((server-socket (setup-port conn
:format (ecase type
((:binary :image)
- :binary)
+ :bivalent)
(:ascii :text)))))
(unwind-protect
(progn

테스트환경은 cl-ftp 1.3.3-1, sbcl, ubuntu edgy box이고 기본적인 시스템 정보는 다음과 같다.
$ sbcl --version
SBCL 0.9.14
$ uname -a
Linux hyper-server 2.6.17-12-386 #2 Mon Jul 16 19:35:45 UTC 2007 i686 GNU/Linux

패치를 데비안 패키지 관리자에게 보내긴 했는데 적용될지는 잘 모르겠다.

happy hackin'



TAG cl-ftp, ftp, Lisp
얼마전에 emacs를 21에서 22으로 버전업을 했는데, 미니 버퍼에서의 자동 완성 기능이 동작하지 않았다.
M-x 후에 몇 글자 입력하고 tab을 눌렀을 때 분명히 자동완성이 존재하는 문자열임에도 불구하고 "No completions of blabla~~"라고 표시되며 동작하지 않았다.
검색을 해도 쉽게 나오진 않았는데, 해결법은 의외로 간단했다. 참고
.emacs 파일에서 다음과 같은 라인을 찾아서
;; find a line like this in .emacs
(define-key minibuffer-local-map [tab] 'comint-dynamic-complete)
다음과 같이 바꾼다.
;; replace the line with this line
(define-key minibuffer-local-map "\t" 'comint-dynamic-complete)

emacs 새 버전의 reader의 구현이나 설정이 "[tab]" 같은 형태의 입력을 못 받아들이는 듯하다.

happy hackin'

종교의 자유에 대한 소고

잡담 2007.06.30 02:36 by manywaypark
약간 늦은 저녁식사를 위해 근처의 음식점을 찾았다.
예약을 안하고 저녁 식사를 하러간 탓에 좀 기다려서야 자리에 앉을 수 있었는데, 우리가 앉은 옆테이블에는 대여섯명쯤 되는 남녀들이 앉아서 식사를 하고 있었다.
처음에 대충 곁눈질로 봤지만, 청년부터 중장년까지 연령대도 다양해 보였고 어디서나 볼수 있는 모습들이었기에 별로 신경을 쓰지는 않았다.
우리 일행은 일상적인 담소를 나누며, 식사를 하고있었는데 옆테이블의 분위기가 처음과는 사뭇 달라졌다.
처음에는 신변잡기적인 일상적 대화가 오가는 듯했었으나, 잠시후부터 목소리 톤이 높아지며 무슨 종교집회처럼 큰소리로 말끝마다 하느님, 예수님이 붙고 이스라엘에서 만나가 하늘에서 내리는것을 목격했다는 등의 나로서는 이해하기 힘든 말들을 꼭 음식점 전체에 방송이라도 하듯 외치고있었던것이다.

대한민국 헌법 20조에는 "모든 국민은 종교의 자유를 가진다."라고 명시되어있다.
이 조항의 의미가 과연 종교를 강요해도 된다는 뜻일까?
이교도(그들의 표현)의 식사시간을 불쾌하게 해도 된다는 것일까?

지나친 전도주의에 경도되어 공공장소에서 다른 종교를 가진 사람이나 종교가 없는 사람이면 충분히 불쾌하게 여길만한 언사를 불특정 다수에게 외치고 다니는 사람들을 쉽게 볼 수 있다. 그 사람 입장에서는 모종의 사명감을 띠고 그런 행동을 하는 것일 수도 있겠으나, 그런 행동이 과연 신자를 늘리는데 도움이 되었는지는 정말 의문이 든다. 시쳇말로 지능형 안티일 것이다라고 진지하게 생각해 본 적도 있다. 즉, 타종교(연합)에서 그런 사람들을 풀어놓아 음해공작을 펴는 것일 수도 있다고 말이다.

목소리가 커야, 판에 박은 듯한 빠른 말투로 말해야, 노출증에 다름없는 공공장소에서의 간증을 해야 믿음이 생기거나 커지는 것은 아닐텐데 왜들 그런 방법을 너도나도 쓰려고 하는지 이해하기 힘들다. 전체적인 이미지의 실추를 생각한다면 조용히 내면을 성찰하고있는 대다수의 다른 신자들에게도 어느 정도 폐를 끼치는 행동일것이다.

한때 나는 "저는 불자입니다"라는 한마디 말(물론 거짓말)을 섞기 싫어서 불자의 증표를 손목에 하고 다니면서 길거리 전도를 시도하는 사람들에게 손목을 살짝 보여주고 무시하며 지나치던 시절도 있었다.
오늘처럼 소음공해에 시달릴 것에 대비할라치면 이젠 목탁을 준비해야하나? 불경을 외워야하나?
역시 말을 섞지 않으려면 목탁을 준비하는 편이 나을듯하다.

happy hackin'
TAG 종교

PLT Scheme - mysqlclient

함수형 언어/Scheme 2007.06.27 19:14 by manywaypark
mysql과 scheme을 연동해보자.
http://www.cs.uvm.edu/~dvanhorn/scheme/
unix/linux에서는 mysqlclient.ss에 있는 설명으로 충분히 빌드가 가능하다.
window환경에서는 다음 링크의 설명대로 하면 될듯하다.
http://www.cs.brown.edu/pipermail/plt-scheme/2004-July/006230.html
요지는,
C:\Program Files\PLT\collects 디렉토리에서 컴파일한다고 가정하면, 다음과 같이...
..\mzc --auto-dir ++ldf c:\mysql\lib\opt\mysqlclient.lib ++ldl d:\mysql\lib\opt\mysqlclient.lib ++ldl WSock32.Lib ++ldl AdvAPI32.Lib ++ccf -Ic:\mysql\include ++ccf -D__LCC__  mysqlclient\mysqlclient.ss

MS SDK의 무료(express) 버전이 필요할지도 모른다. 언제 무료 버전이 생긴거지? ㅋ
http://msdn.microsoft.com/vstudio/express/downloads/
VC++를 설치하자.
VC++만 설치하면 될 줄 알았는데, "winsock.h"를 못 찾는다.
http://www.microsoft.com/downloads/details.aspx?FamilyID=a55b6b43-e24f-4ea3-a93e-40c0ec4f68e5&DisplayLang=en
Platform SDK를 설치하자.

다음과 같이 하면 잘 될것이다.

VC++ 사용시 - 거지 같지만, Visual Studio 2005 Command Prompt로 들어가서 하는 것이 정신건강에 좋다.
..\mzc -v --auto-dir ++ldf "c:\art\MySQL\MySQL Server 5.0\lib\opt\mysqlclient.lib" ++ldl "c:\art\MySQL\MySQL Server 5.0\lib\opt\mysqlclient.lib" ++ldl "C:\Program Files\Microsoft Platform SDK\Lib\WSock32.Lib" ++ldl "C:\Program Files\Microsoft Platform SDK\Lib\AdvAPI32.Lib" ++ldl "C:\Program Files\Microsoft Platform SDK\Lib\Uuid.Lib" ++ccf -I"c:\Program Files\Microsoft PlatformSDK\Include" ++ccf -I"c:\art\MySQL\MySQL Server 5.0\include" ++ccf -D__LCC__  mysqlclient\mysqlclient.ss

cygwin 사용시 - 이건 실패. 시간있을때 성공하게 만들어보자.
..\mzc -v --auto-dir ++ldf "c:\art\MySQL\MySQL Server 5.0\lib\opt\mysqlclient.lib" ++ldl "c:\art\MySQL\MySQL Server 5.0\lib\opt\mysqlclient.lib" ++ldl \art\cygwin\lib\w32api\libwsock32.a ++ldl \art\cygwin\lib\w32api\libadvapi32.a ++ccf -I"c:\art\cygwin\usr\include\w32api" ++ccf -I"c:\art\MySQL\MySQL Server 5.0\include" ++ccf -D__LCC__  mysqlclient\mysqlclient.ss


happy hackin'

PLT Scheme package 위치

함수형 언어/Scheme 2007.06.26 17:51 by manywaypark

윈도우에서 기본 설치를 했을 때 설치 디렉토리말고 다른 쪽에 모듈(패키지)들이 깔린다. 특히 planet를 이용해서 설치한 것들의 소스를 확인 할때 이 디렉토리를 찾아보시라.
C:\Documents and Settings\%USERNAME%\Application Data\PLT Scheme\


일상적 작업

잡담 2007.05.31 17:23 by manywaypark
cl-sql을 사용하여 약 5백만 건 정도의 레코드를 mysql DB에 입력했다.
오라클 DB dump로 추정되는 텍스트 파일을 cl-ppcre를 사용하여 살짝 조작한 후에 clsql:def-view-class로 정의한 클래스의 인스턴스를 생성 한 후 clsql:update-records-from-instance로 DB에 삽입했다.

결과:
Evaluation took:
  6941.389 seconds of real time
  4364.181 seconds of user run time
  98.73017 seconds of system run time
  [Run times include 327.356 seconds GC run time.]
  0 page faults and
  498,416,792,016 bytes consed.
빠른건가? 느린건가?
속도가 무슨 의미가 있겠는가? 간단히 아름답게 해결되었고, 기다려줄만한 시간인것을...

happy hackin'
TAG Lisp, MySQL

cl-sql 사용하기

함수형 언어/Lisp 2007.05.29 14:01 by manywaypark
cl-sql은 common lisp에서 여러 종류의 DB backend에 접근하는데 사용할 수 있는 package이다.
간단히 (asdf-install:install 'clsql)로 될줄 았았는데, 잘 안됐다. library 로딩에 실패하고 어쩌구...
혹시나 하는 마음에 ubuntu(debian) packaging system apt를 이용해보기로 했다.
$ apt-cache search clsql
cl-sql - SQL Interface for Common Lisp
cl-sql-aodbc - CLSQL database backend, AODBC
cl-sql-mysql - CLSQL database backend, MySQL
cl-sql-odbc - CLSQL database backend, ODBC
cl-sql-postgresql - CLSQL database backend, PostgreSQL
cl-sql-postgresql-socket - CLSQL database backend, PostgreSQL
cl-sql-sqlite - CLSQL database backend, SQLite
cl-sql-sqlite3 - CLSQL database backend, SQLite3
cl-sql-tests - Testing suite for CLSQL
cl-sql-uffi - Common UFFI functions for CLSQL database backends
cl-sql-oracle - CLSQL database backend, Oracle
오호라, 필요한건 다 있는 거같다.
$ sudo apt-get install cl-sql cl-sql-mysql
......
sbcl을 실행하고 테스트해봤다.
$ sbcl
......
* (require 'clsql)

; loading system definition from /home/USER/.sbcl/systems/uffi.asd into
; #<PACKAGE "ASDF1">
; registering #<SYSTEM UFFI {10028CA001}> as UFFI
NIL
* (require 'clsql-mysql)
......
Couldn't load foreign libraries "libmysqlclient", "libmysql". (searched CLSQL-SYS:*FOREIGN-LIBRARY-SEARCH-PATHS*)
......
엥? 에러 컨디션?
사실 (require 'clsql-mysql)은 직접 호출하지 않아도 connect류 등의 관련 함수를 부르면 자동으로 올라오는데 그것들도 다 실패했다. 시스템에는 libmysql*이 전부 설치되어있었다.
이 문제는 다음 두가지 방법 중 하나를 선택해서 해결할 수 있다.
해결책1: 직접 uffi를 이용해서 library를 로딩. (참고:http://common-lisp.net/pipermail/cl-debian/2006-May/001287.html)
CL-USER> (uffi:load-foreign-library "/usr/lib/libmysqlclient.so.15")
해결책2: symbolic link 생성.
$ sudo ln -s /usr/lib/libmysqlclient.so.15.0.0 /usr/lib/libmysqlclient.so
(library 버전 번호는 필요한 것으로 선택한다.)

테스트:
CL-USER> (require 'clsql)
......
;;; connect params: host, db, user, password.
CL-USER> (clsql:connect '("localhost" "mysql" "root" "") :database-type :mysql)
#<CLSQL-MYSQL:MYSQL-DATABASE localhost/mysql/root OPEN {1003707EF1}>
CL-USER> (clsql:status)
CLSQL STATUS: 2007-05-28 21:21:31,,0
-----------------------------------------
   DATABASE              TYPE   RECORDING 
-----------------------------------------
*  localhost/mysql/root  mysql  nil       
-----------------------------------------
; No value
CL-USER> (clsql:list-databases '("localhost" "mysql" "root" "") :database-type :mysql)
("information_schema" "mysql")
CL-USER> (clsql:query "select * from user")
......
CL-USER> (clsql:disconnect :database (clsql:find-database "localhost/mysql/root"))
T
CL-USER> (clsql:status)
CLSQL STATUS: 2007-05-28 21:48:23,,0
; No value

참고: apt를 이용해서 lisp 모듈을 설치하면, /usr/share/common-lisp/ 아래에 설치된다. 소스 참고시 유용하다.

2008-04-15 :
oracle을 backend로 쓰려면 instant client download 페이지에서 필요한 파일을 다운로드 받아 특정 디렉토리에 압축을 풀어놓고 그 디렉토리를 LD_LIBRARY_PATH 환경변수에 추가하면 된다. 물론 위의 해결책2에서 처럼 symbolic link를 걸어주는 작업(버전 번호를 떼주는...)이 필요하다.

happy hackin'

local-time 사용하기

함수형 언어/Lisp 2007.05.25 16:13 by manywaypark
시간/날짜 처리 관련한 package로 local-time이 있다.
설치(ASDF Brief 참조):
CL-USER> (require 'asdf)
NIL
CL-USER> (require 'asdf-install)
......
CL-USER> (asdf-install:install 'local-time)
......

예제:
;;; 현재 시간 얻기
CL-USER> (local-time:now)
@2007-05-25T16:02:30.000

좀더 실용적인 예제 (기념일 계산에 쓰면 될듯):
;;; adds days
;;; eg, (add-days "2007-01-01" 123)
(defun add-days (from days)
(local-time:make-local-time :day (+ (local-time:local-time-day (local-time:parse-timestring from)) days)))

;;; 오늘 만난 커플의 100일 되는 날은?
CL-USER> (add-days "2007-05-25" 100)
@2007-09-02T00:00:00.000
;;; 9월2일이군요.

happy hackin'

2013-12-30: 그간 local-time package에 변경이 있었던듯... 여튼 오늘 해보니 상기 예제는 다음과 같이 하면 해결된다.
;;; 오늘 만난 커플의 100일 되는 날은?
* (local-time:timestamp+ (local-time:parse-timestring "2013-12-30") 100 :day)
@2014-04-09T09:00:00.000000+09:00
;;; 내년 4월9일이군요.



TAG Lisp
그냥 막연히 make-string-input-stream으로 input stream을 만들어서 cxml:parse-stream에 걸면 될 줄로 생각했는데, binary stream을 만들어야한다.
;;; simple binary stream for string parsing with cxml (just a wrapper for string).
(defclass bin-stream (fundamental-binary-input-stream)
((string-input-stream
:initarg :string-input-stream
:accessor string-input-stream)))

(defmethod stream-read-byte ((s bin-stream))
(char-code (or (read-char (string-input-stream s) nil)
(return-from stream-read-byte :eof))))

;;; makes binary stream of a string for parsing with cxml.
(defun make-bin-stream (string)
(assert (stringp string))
(make-instance 'bin-stream :string-input-stream (make-string-input-stream string)))
다음과 같이 테스트
CL-USER> (make-bin-stream "<foo><bar/></foo>")
#<BIN-STREAM {1002C69051}>
CL-USER> (dom:node-name (dom:document-element (cxml:parse-stream * (cxml-dom:make-dom-builder))))
"foo"
CL-USER>
binary stream wrapper를 만드는데 시간이 좀 걸렸다.

참고:
http://www.mikemac.com/mikemac/clim/gray-streams.html (맨 밑에 보면 binary stream을 만들려면, fundamental-binary-*-stream를 상속하고 stream-read-byte 또는 stream-write-byte method를 구현하라고 나온다).
http://www.cs.queensu.ca/software_docs/gnudev/gcl-ansi/gcl_1178.html (read-char의 optional parameter에 eof-error-p를 주의. nil로 설정!! nil로 설정하지 않으면 end-of-file condition error가 뜬다.)

happy hackin'


TAG cxml, Lisp

/etc/motd 파일

tips & tricks/Linux/Unix 2007.05.02 19:33 by manywaypark
/etc/motd 파일은 "message of the day"의 줄임말로, 로그인하는 사용자에게 표시되는 메시지이다.
잘못 건드리면 커널 업데이트 등을 하고 나서 조금 이상하게 변경되는 경우가 있는 듯하다.
평소와 다른 형식으로 표시된다면, 루트 권한으로 편집하면 된다.

참고: http://uw714doc.sco.com/en/SM_startup/sstT.etcmotd.html

happy hackin'
TAG Linux, unix
1 ··· 25 26 27 28 29 30 
분류 전체보기 (298)
잡담 (20)
함수형 언어 (62)
emacs (16)
java (18)
tips & tricks (150)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)