리눅스로 작업환경 변경

사용자 삽입 이미지
작업환경을 완전히 리눅스로 옮겼다. 윈도우 컴퓨터에서 Putty로 셀레론 컴퓨터에 접속해서 GCC를 컴파일 하며 작업하다 듀얼 코어 컴퓨터에 리눅스를 설치하고 직접 컴파일 하니 속도가 2배 가까이 향상 된 듯한 느낌을 준다. 게다가 우분투 7.10은 설정하고 사용하기가 정말 편리하다.

빨간색을 좋아하다 보니 입맛에 맞게 글꼴과 테마를 수정했다. 그럭저럭 마음에 드는 개발 환경을 마련하는데 성공! 출근해서 저녁먹을때까지는 리눅스 환경에서 업무에 집중하자!

Ruby로 처음 작성한 코드, test harness

펄, 파이선, 루비 등의 스크립트 언어 중에 하나 정도는 알아 두는게 편할 것 같다는 생각에 이번 달에는 루비를 공부하고 있다. 책의 절반을 쭉 읽어 나가면서 코드는 한번도 작성한 적이 없었지만 언어가 간결해서 그런지 몰라도 쉽게 원하는 코드를 작성할 수 있었다.

지금 진행하고 있는 프로젝트는 코볼 컴파일러의 개발인데, 컴파일러가 생성한 코드가 정확한가를 확인하는 가장 쉬운 방법은 기존의 컴파일러가 생성한 코드와 수행 결과(stdout)을 비교하는 것.

지금까지는 급한 마음에 두 실행파일을 번갈아 실행하며 눈으로 수행결과를 비교했는데, “실용주의 프로그래머”를 보면 테스트를 포함한 프로젝트 빌드의 전과정을 자동으로 수행할 수 있도록 할 것을 강조하고 있다.

그리하여 고즈넉한 저녁에 잠깐의 짬과 약간의 용기를 내어 처음으로 루비를 사용해 간단한 test harness를 작성해 보았다.

name_list = [
    ‘intrinsic_math_func’,
    ‘intrinsic_char_func’,
    ‘intrinsic_case_func’,
    ‘intrinsic_value_func’,
    ‘intrinsic_divide_func’,
    ‘intrinsic_numval’,
    ‘intrinsic_annuity’
]

test_cnt = 0
succ_cnt = 0
fail_cnt = 0

# TODO
# compare execution time
name_list.each do |name|

    test_cnt += 1

    mf_exec = “./” + name + “.cob32”
    tmax_exec = “./” + name + “.gcobol”

    mf_stdout = `#{mf_exec}`
    tmax_stdout = `#{tmax_exec}`

    print “[#{test_cnt}] #{mf_exec} vs #{tmax_exec}”
    if (mf_stdout == tmax_stdout)
        puts ” …success”
        succ_cnt += 1
    else
        puts ” …fail”
        fail_cnt += 1
        puts “[#{mf_exec}]”
        puts mf_stdout
        puts “[#{tmax_exec}]”
        puts tmax_stdout
    end
    puts
end

puts
puts “Total : #{test_cnt}”
puts “Success : #{succ_cnt}”
puts “Fail : #{fail_cnt}”
puts

컴파일러가 생성한 코드의 수행시간 역시 컴파일러를 평가하는데 중요한 이슈이므로, 두가지 컴파일러가 생성한 코드의 수행시간을 자동으로 비교해 주는 프로그램을 루비로 간단히 작성하는 것도 큰 의미가 있을 것 같다. 사용하기 쉬운 루비 언어를 조금 더 연습해서 프로젝트의 여기저기에 잘 활용한다면 생산성을 향상 시킬 수 있을 것이다.

VMWare Fusion pre-order

beta4에 이어 rc1을 사용하고 있었는데 8월 6일 정식 발매 된다는 소식을 듣고 그동안 미뤄오던 pre-order($39.99)를 해버렸다. 정식 발매 이후에 구입하게 되면 $79.99를 지불해야 한다.

윈도우를 사용할 수 밖에 없는 현실이 슬프지만 어쩔 수 없는 노릇. 플랫폼에 independent한 인터넷 환경은 얼마나 시간이 지나야 갖춰질까? 당장 이 글을 쓰고 있는 테터툴 마저도 사파리에서 html 모드로 글을 쓸 수 밖에 없으니 안타까움을 금할 길이 없다.

아마도 이번 pre-order가 최초의 정품 소프트웨어 구입이 될 것 같다. $39.99 정도의 가격이면 충분히 감당할 수 있을 정도. 오히려 맥용 정품 소프트웨어가 윈도우용 소프트웨어보다 대체로 저렴한 것 같다.

다음 구입할 맥용 소프트웨어는 차기 맥OS인 레오파드! 10월이 기다려지는구나. 즐거운 컴퓨팅을 기대하며 그 날을 기다린다.

애매함을 용납하지 말자

지금 진행중인 프로젝트는 gcc의 back-end를 사용하기 때문에 빌드할 때 gcc 소스코드와 함께 컴파일 된다.

컴파일 할 때 make를 수행하면 늘 cygwin에서 컴파일하는 동희형과 달리 mac osx에서 하는 나는 늘 한번에 컴파일이 안되고 에러가 발생하곤 했다. 한번 더 수행하면 에러 없이 make가 완료되었다.

난 쉽게 생각했다.

“뭔가 깔끔하진 않아도 한번 더 수행하면 되니까 괜찮겠지”
“플랫폼이 달라서 그렇겠지”

철주형 아들 서호의 돌잔치에 다녀와서 사택에서 낮잠 한시간 푹 잔후 다시 회사에 나와 본격적인 테스트를 하려고 하는데 그 동안 무시했던 이 에러가 나를 괴롭히고 있는 원인이였음을 깨닫게 되고는 또 무릎을 치게 되었다.

오호 통제라!

나는 또 한번 경험에서 교훈을 얻게 되었다. 오직 0과 1로 데이터를 표현하는 정교한 컴퓨터를 다루는 입장에서 애매한 태도를 지양해야 한다는 것을. 남겨둔 애매함이 언젠가 나를 곤란하게 한다는 것을. 개발자에게 경험은 그 무엇보다 소중한 자산인 것 같다. 경험이 농익을 때까지 맨땅에 해딩을 마다하지 말자.

하지만 연애에서의 애매함은 피할 수 없는 숙명인 것 같다. 확실한 것을 좋아하는 어쩔 수 없는 공돌이인 내가 늘 작업에 실패하는 이유는 애매함을 견디지 못하는 나약한 혹은 소심한(?) 심리상태에 있는 것 같다. 남녀사이의 애매함을 즐기는 작업의 대가들이 부러울 따름이다.

기묘한 typedef의 활용

gmp (gnu multiprecision) 라이브러리를 쓸 일이 있어서 메뉴얼과 헤더파일을 보던 중 재밌는 코드를 발견!

typedef struct
{
  int _mp_alloc;        /* Number of *limbs* allocated and pointed
                   to by the _mp_d field.  */
  int _mp_size;         /* abs(_mp_size) is the number of limbs the
                   last field points to.  If _mp_size is
                   negative this is a negative number.  */
  mp_limb_t *_mp_d;     /* Pointer to the limbs.  */
} __mpz_struct;

typedef __mpz_struct mpz_t[1];

이 부분에 대해서 메뉴얼은 다음과 같이 설명하고 있다.

For interest, the GMP types mpz_t etc are implemented as one-element arrays of certain structures. This is why declaring a variable creates an object with the fields GMP needs, but then using it as a parameter passes a pointer to the object. Note that the actual fields in each mpz_t etc are for internal use only and should not be accessed directly by code that expects to be compatible with future GMP releases.

이 정의를 활용하는 코드를 보면 다음과 같다.

     void
     foo (mpz_t result, const mpz_t param, unsigned long n)
     {
       unsigned long  i;
       mpz_mul_ui (result, param, n);
       for (i = 1; i < n; i++)
         mpz_add_ui (result, result, i*7);
     }
    
     int
     main (void)
     {
       mpz_t  r, n;
       mpz_init (r);
       mpz_init_set_str (n, “123456”, 0);
       foo (r, n, 20L);
       gmp_printf (“%Zd\n”, r);
       return 0;
     }

이렇게 선언해 놓고 참조하면 자연스럽게 함수 호출할 때 call-by-reference가 가능하다. c언어의 묘미란 이런게 아닐까?