tclvars — Tcl이 사용하는 변수들

tclvars — Tcl이 사용하는 변수들

Tcl 인터프리터는 실행 환경을 알아내고, 오류 정보를 정리하고, 라이브러리 위치를 관리하기 위해 몇 가지 전역 변수를 스스로 만들고 관리해요. argc 같은 실행 인자 변수부터 tcl_version 같은 버전 변수까지, Tcl이 내부적으로 다루는 이 변수들을 이해하면 런타임 환경을 정확히 알 수 있어요.

출처: Tcl 공식 문서 - tclvars

본문

다음 전역 변수들은 Tcl 라이브러리가 자동으로 만들고 관리해요. 아래 특별한 언급이 없는 한, 이 변수들은 애플리케이션별 코드와 사용자가 보통 읽기 전용으로 취급해야 해요.

  • auto_path: 설정되어 있으면 자동 로드 연산(기본 package unknown 핸들러를 쓸 때 패키지 index 파일 포함) 중 검색할 디렉터리를 주는 유효한 Tcl 리스트를 담아야 해요. 이 변수는 시작할 때 다음 순서로 초기화돼요: TCLLIBPATH 환경 변수에 있는 디렉터리, tcl_library 전역 변수가 가리키는 디렉터리, tcl_library의 부모 디렉터리, [file dirname [file dirname [info nameofexecutable]]]/lib, tcl_pkgPath 변수의 디렉터리들. 파일과 패키지 index를 추가로 찾을 위치는 보통 lappend로 이 변수에 추가해야 해요. 패키지 관리에 관련된 추가 변수들이 존재해요. 자세한 내용은 library 매뉴얼 페이지의 VARIABLES 절에 있어요.

  • env: Tcl이 배열로 유지하는 변수로, 요소가 프로세스의 환경 변수예요. 요소를 읽으면 해당 환경 변수의 값이 반환돼요. 배열 요소를 설정하면 해당 환경 변수가 수정되거나(없으면) 새로 만들어져요. env 요소를 unset하면 해당 환경 변수가 제거돼요. env 배열의 변경은 exec 같은 명령이 자식에게 넘기는 환경에 영향을 줘요. env 배열 전체가 unset되면 Tcl은 env 접근 감시를 멈추고 환경 변수를 갱신하지 않아요. Windows에서 환경 변수 PATHCOMSPEC는 어떤 대소문자든 자동으로 대문자로 변환돼요. 예를 들어 OS가 PATH"path", "Path", "PaTh" 등으로 내보낼 수 있는데, 이러면 평범한 Tcl 코드가 많은 특수 경우를 지원해야 해요. Tcl이 상속받은 다른 모든 환경 변수는 수정되지 않은 채 남아요. env 배열 변수를 공백으로 설정하는 것은 unset과 같은데, 이는 기본 Windows OS의 동작이기 때문이에요. 존재하고 비어 있는 환경 변수에 의존하는 것은 Windows에서 동작하지 않으므로 크로스 플랫폼 사용에서는 권장하지 않아요. env의 다음 요소들은 Tcl에 특별해요:

    • env(HOME): 설정되어 있으면 현재 사용자의 홈 디렉터리로 간주되는 디렉터리 위치를 줘요. 인자가 없는 cd 호출이나 "~" 인자만 있는 cd가 이 디렉터리로 변경돼요. 대부분 플랫폼이 기본으로 올바르게 설정하므로 사용자 코드가 보통 설정할 필요는 없어요.
    • env(TCL_LIBRARY): 설정되어 있으면 라이브러리 스크립트가 담긴 디렉터리 위치를 지정해요(이 값은 tcl_library 변수에 할당되어 info library 명령이 반환해요). 설정되어 있지 않으면 기본값이 쓰여요. 이 환경 변수는 보통 설정하지 않아야 한다는 점에 주의하세요.
    • env(TCLLIBPATH): 설정되어 있으면 자동 로드 연산 중 검색할 디렉터리를 주는 유효한 Tcl 리스트를 담아야 해요. 디렉터리는 플랫폼과 무관하게 /를 경로 구분자로 쓰는 Tcl 형식으로 지정돼야 해요. 이 변수는 auto_path 변수를 초기화할 때만 사용돼요.
    • env(TCL_TZ), env(TZ): clock 명령에서 시간과 날짜를 파싱·포맷할 때 쓰는 기본 시간대를 지정해요. 많은 플랫폼에서 TZ 환경 변수는 OS가 설정해요.
    • env(LC_ALL), env(LC_MESSAGES), env(LANG): 이 환경 변수들은 msgcat 패키지가 메시지를 포맷할 로케일을 결정하는 데 사용해요.
    • env(TCL_INTERP_DEBUG_FRAME): 존재하면 각 새 Tcl 인터프리터의 아주 첫 명령으로 interp debug {} -frame 1을 실행하는 것과 같은 효과가 있어요.
  • errorCode: 이 변수는 이 인터프리터에서 발생한 가장 최근 오류가 설정한 -errorcode 반환 옵션의 값을 담아요. 이 리스트 값은 프로그램이 처리하기 쉬운 형태로 오류에 대한 추가 정보를 나타내요. 리스트의 첫 요소가 오류의 일반적 클래스를 식별하고 나머지 리스트의 형식을 결정해요. Tcl 코어가 쓰는 -errorcode 반환 옵션 형식은 다음과 같아요. 개별 애플리케이션은 추가 형식을 정의할 수 있어요.

    • ARITH code msg: 산술 오류가 발생할 때(예: expr 명령에서 0을 0으로 나누려는 시도) 쓰여요. code는 정확한 오류를 식별하고 msg는 사람이 읽을 수 있는 오류 설명을 제공해요. codeDIVZERO(0으로 나누기 시도), DOMAIN(인자가 함수의 정의역 밖, 예: acos(-3)), IOVERFLOW(정수 오버플로), OVERFLOW(부동소수점 오버플로), 또는 UNKNOWN(오류 원인을 결정할 수 없음) 중 하나예요. 이 오류들의 감지는 부분적으로 기본 하드웨어와 시스템 라이브러리에 의존해요.
    • CHILDKILLED pid sigName msg: 자식 프로세스가 시그널 때문에 죽었을 때 쓰여요. pid 요소는 프로세스 식별자(십진수), sigName 요소는 프로세스를 종료시킨 시그널의 기호 이름(예: SIGPIPE)으로 signal.h include 파일의 이름 중 하나예요. msg 요소는 SIGPIPE의 "write on pipe with no readers" 같은 짧은 사람이 읽을 수 있는 메시지예요.
    • CHILDSTATUS pid code: 자식 프로세스가 0이 아닌 종료 상태로 끝났을 때 쓰여요. pid는 프로세스 식별자(십진수), code는 프로세스가 반환한 종료 코드(십진수)예요.
    • CHILDSUSP pid sigName msg: 자식 프로세스가 시그널 때문에 중단되었을 때 쓰여요. pid는 프로세스 식별자(십진수), sigName은 중단시킨 시그널의 기호 이름(예: SIGTTIN)으로 signal.h의 이름 중 하나예요. msg는 SIGTTIN의 "background tty read" 같은 짧은 사람이 읽을 수 있는 메시지예요.
    • NONE: 오류 메시지 외에 추가 정보가 없는 오류에 쓰여요. 이 경우 -errorcode 반환 옵션은 NONE 내용을 담은 단일 요소 리스트로 구성돼요.
    • POSIX errName msg: 첫 요소가 POSIX면 오류가 POSIX 커널 호출 중 발생했어요. errName 요소는 발생한 오류의 기호 이름(예: ENOENT)으로 errno.h include 파일에 정의된 값 중 하나예요. msg 요소는 ENOENT의 "no such file or directory" 같은 사람이 읽을 수 있는 메시지예요.
    • TCL ...: Tcl 자체와 관련해 생긴 문제(예: 채널이나 변수를 찾는 실패)를 나타내요.

    -errorcode 반환 옵션을 설정하려면 애플리케이션은 Tcl_SetObjErrorCode, Tcl_SetReturnOptions, Tcl_PosixError 같은 라이브러리 프로시저를 쓰거나 return 명령의 -errorcode 옵션을 호출해요. 이런 오류 코드 설정 방법 중 아무것도 사용되지 않았다면 Tcl 인터프리터는 다음 오류 후 변수를 NONE으로 재설정해요.

  • errorInfo: 이 변수는 이 인터프리터에서 발생한 가장 최근 오류가 설정한 -errorinfo 반환 옵션의 값을 담아요. 이 문자열 값은 가장 최근 오류가 발생했을 때 실행 중이던 Tcl 명령과 프로시저를 식별하는 한 줄 이상을 담아요. 그 내용은 오류 당시 호출된 다양한 중첩 Tcl 명령을 보여주는 스택 추적 형태예요.

  • tcl_library: 이 변수는 자동 로딩에 쓰이는 것 같은 Tcl 스크립트 시스템 라이브러리를 담은 디렉터리 이름을 담아요. 이 값은 info library 명령이 반환해요. Tcl 스크립트 라이브러리가 제공하는 기능에 대한 자세한 내용은 library 매뉴얼 항목을 참조하세요. 보통 각 애플리케이션/패키지는 Tcl 스크립트 라이브러리 외에 고유의 애플리케이션별 스크립트 라이브러리를 갖고, 각 애플리케이션은 $app_library(app은 애플리케이션 이름) 같은 이름의 전역 변수에 그 애플리케이션 라이브러리 디렉터리의 네트워크 파일 이름을 담도록 설정해야 해요. tcl_library의 초기 값은 적절한 Tcl 시작 스크립트를 담은 디렉터리를 찾을 때까지 여러 디렉터리를 검색해 인터프리터를 만들 때 설정돼요. TCL_LIBRARY 환경 변수가 있으면 그 디렉터리가 먼저 확인돼요. 없거나 적절하지 않으면 Tcl은 컴파일된 기본 위치, 애플리케이션을 담은 바이너리 위치, 현재 작업 디렉터리에 기반한 몇몇 다른 디렉터리를 확인해요.

  • tcl_patchLevel: 인터프리터를 만들 때 Tcl은 이 변수를 Tcl의 현재 패치 레벨을 주는 문자열로 초기화해요. 예: 첫 16개 공식 패치가 적용된 Tcl 8.4는 8.4.16, Tcl 8.5의 세 번째 베타 릴리스는 8.5b3. 이 값은 info patchlevel 명령이 반환해요.

  • tcl_pkgPath: 이 변수는 패키지가 보통 설치되는 디렉터리 목록을 담아요. Windows에서는 사용되지 않아요. 보통 한두 개 항목을 담는데, 두 개면 첫째는 플랫폼 의존 패키지(예: 공유 라이브러리 바이너리) 디렉터리, 둘째는 플랫폼 독립 패키지(예: 스크립트 파일) 디렉터리인 게 보통이에요. 보통 패키지는 tcl_pkgPath 변수의 한 항목의 하위 디렉터리로 설치돼요. tcl_pkgPath의 디렉터리는 auto_path 변수에 기본 포함되므로 package require 명령 중 자동으로 검색돼요. 주의: tcl_pkgPath는 애플리케이션이 수정하도록 의도된 것이 아니에요. 그 값은 시작할 때 auto_path에 추가되고, tcl_pkgPath의 변경은 auto_path에 반영되지 않아요. Tcl이 추가 디렉터리에서 패키지를 검색하게 하려면 그 디렉터리 이름을 tcl_pkgPath가 아니라 auto_path에 추가해야 해요.

  • tcl_platform: 애플리케이션이 실행되는 플랫폼에 대한 정보(운영체제 이름, 현재 릴리스 번호, 기계의 명령어 집합 등)를 담은 연관 배열이에요. 아래 나열된 요소는 항상 정의되지만, Tcl이 관련 정보를 가져오지 못하면 값이 빈 문자열일 수 있어요. 확장과 애플리케이션이 배열에 추가 값을 넣을 수도 있어요. 미리 정의된 요소는 다음과 같아요.

    • byteOrder: 이 기계의 기본 바이트 순서. littleEndian 또는 bigEndian.
    • debug: 이 변수가 있으면 인터프리터가 디버그 활성 C 런타임으로 컴파일·링크된 것. 이 변수는 Windows에만 존재해요. 그래서 확장 작성자가 사용 중인 C 런타임 라이브러리에 따라 어떤 패키지를 로드할지 지정할 수 있어요. 코어에 심볼이 들어 있다는 뜻은 아니에요.
    • engine: Tcl 언어 구현의 이름. 인터프리터가 처음 만들어질 때 항상 문자열 Tcl로 설정돼요.
    • machine: 이 기계가 실행하는 명령어 집합(예: intel, PPC, 68k, sun4m). UNIX 기계에서는 uname -m이 반환하는 값이에요.
    • os: 이 기계에서 실행되는 운영체제의 이름(예: Windows NT, SunOS). UNIX 기계에서는 uname -s가 반환하는 값이에요.
    • osVersion: 이 기계에서 실행되는 운영체제의 버전 번호. UNIX 기계에서는 uname -r이 반환하는 값이에요.
    • pathSeparator: PATH류 환경 변수를 해당 디렉터리 이름 목록으로 나눌 때 써야 하는 문자.
    • platform: windows 또는 unix. 기계의 일반적 운영 환경을 식별해요.
    • pointerSize: 기본 기계 포인터의 바이트 크기(엄밀히 C에서 sizeof(void*)를 평가한 결과와 같음).
    • threaded: 이 변수가 있으면 인터프리터가 스레드 활성 상태로 컴파일된 것.
    • user: 플랫폼에서 사용 가능한 로그인 정보에 기반해 현재 사용자를 식별해요. Unix에서는 getuid()getpwuid() 시스템 호출, Windows에서는 GetUserName() 호출에서 온 값이에요.
    • wordSize: 기본 기계 단어의 바이트 크기(엄밀히 C에서 sizeof(long)을 평가한 결과와 같음).
  • tcl_precision: 이 변수는 부동소수점 값을 문자열로 변환할 때 생성할 자릿수를 제어해요. 기본값은 0이에요. 애플리케이션은 이 값을 변경하면 안 되고, 레거시 코드와의 호환을 위해 제공돼요. 기본값 0은 특별한데, Tcl이 숫자를 이웃하는 모든 부동소수점 숫자와 여전히 구별하면서 최대한 적은 자릿수로 변환해야 한다는 뜻이에요. tcl_precision에 임의로 높은 값을 쓰는 것과 다른 점은, 불완전한 숫자 1.4가 이진수 값의 정확한 값에 더 가까운 1.3999999999999999가 아니라 1.4로 변환된다는 것이에요. tcl_precision이 0이 아니면 Tcl은 부동소수점 숫자를 변환할 때 최대 tcl_precision개의 유효 자릿수 십진 표현을 만들고, 더 짧은 결과가 원래 숫자를 정확히 나타내면 결과는 더 짧을 수 있어요. 최대 tcl_precision 자리 결과 중 원래 숫자를 정확히 나타내는 것이 없으면 원래 숫자에 가장 가까운 것이 선택돼요. 원래 숫자가 두 개의 동등하게 정확한 십진 표현 사이에 정확히 있으면 최하위 자리가 짝수인 것이 선택돼요. 예를 들어 tcl_precision이 3이면 0.3125는 0.313이 아니라 0.312로, 0.6875는 0.687이 아니라 0.688로 변환돼요. 남는 뒤쪽 0 문자열은 잘라내요. tcl_precision 값 17 자리는 IEEE 부동소수점에 '완벽한'데, 배정밀도 값을 정보 손실 없이 문자열로 변환했다가 다시 이진으로 돌릴 수 있기 때문이에요. 그래서 8.5 이전 Tcl 버전에서 실행해야 하는 레거시 코드에서 자주 값으로 보여요. 더 이상 권장되지 않아요. 위에서 말했듯 0 값이 선호되는 방법이에요. 스레드의 모든 인터프리터는 단일 tcl_precision 값을 공유해요. 한 인터프리터에서 바꾸면 다른 모든 인터프리터에도 영향을 줘요. 안전(safe) 인터프리터는 변수를 수정할 수 없어요. tcl_precision의 유효 값 범위는 0부터 17까지예요.

  • tcl_rcFileName: 이 변수는 초기화 중 사용자별 시작 파일의 이름을 나타내는 데 사용돼요. 애플리케이션별 초기화가 설정하면 Tcl 시작 코드가 이 파일의 존재를 확인하고 있으면 source해요. 예를 들어 wish의 경우 Unix에서는 ~/.wishrc, Windows에서는 ~/wishrc.tcl로 설정돼요.

  • tcl_traceCompile: 이 변수의 값으로 바이트코드 컴파일 중 얼마나 많은 추적 정보를 표시할지 제어할 수 있어요. 기본적으로 tcl_traceCompile은 0이고 아무 정보도 표시하지 않아요. 1로 설정하면 프로시저나 최상위 명령이 컴파일될 때마다 stdout에 한 줄 요약을 생성해요. 2로 설정하면 매 컴파일마다 내보내지는 바이트코드 명령의 상세 목록을 stdout에 생성해요. 이 변수는 Tcl 컴파일러의 의심되는 문제를 추적하는 데 유용해요. 이 변수와 기능은 Tcl 컴파일 중 TCL_COMPILE_DEBUG가 정의된 경우에만 존재해요.

  • tcl_traceExec: 이 변수의 값으로 바이트코드 실행 중 얼마나 많은 추적 정보를 표시할지 제어할 수 있어요. 기본적으로 0이고 정보를 표시하지 않아요. 1로 설정하면 Tcl 프로시저 호출마다 stdout에 한 줄 추적을 생성해요. 2로 설정하면 명령 이름과 인자를 담은 Tcl 명령이 호출될 때마다 출력 줄을 생성해요. 3으로 설정하면 각 바이트코드 명령 실행 결과를 보여주는 상세 추적을 생성해요. tcl_traceExec이 2나 3일 때 setincr처럼 일련의 바이트코드 명령으로 완전히 대체된 명령은 보이지 않아요. 이 변수는 바이트코드 컴파일러·인터프리터의 의심되는 문제를 추적하는 데 유용해요. 이 변수와 기능은 TCL_COMPILE_DEBUG가 정의된 경우에만 존재해요.

  • tcl_version: 인터프리터를 만들 때 Tcl은 이 변수를 이 Tcl 버전의 버전 번호(x.y 형태)로 초기화해요. x의 변경은 큰 변경(가능한 비호환성)을, y의 변경은 하위 호환을 유지하는 작은 개선과 버그 수정을 나타내요. 이 값은 info tclversion 명령이 반환해요.

기타 전역 변수(Other Global Variables)

다음 변수들은 tclshwish 실행 파일에만 존재한다고 보장돼요. Tcl 라이브러리는 스스로 정의하지 않지만 많은 Tcl 환경이 정의해요.

  • argc: tclshwish의 인자 수.
  • argv: tclshwish의 인자 Tcl 리스트.
  • argv0: tclshwish가 실행을 시작한 스크립트(지정된 경우) 또는 그렇지 않으면 tclshwish가 호출된 이름.
  • tcl_interactive: tclshwish가 대화형으로 실행 중이면(스크립트가 지정되지 않았고 표준 입력이 터미널류 장치) 1, 아니면 0을 담아요.

예제

package require가 검색하는 위치 모음에 디렉터리를 추가하려면(예: 사용되는 애플리케이션별 패키지 때문에) auto_path 변수를 갱신해야 해요.

lappend ::auto_path [file join [pwd] "theLibDir"]

"-foo 1 -bar 2" 형태의 명령줄 인자를 다루는 간단한(그리 견고하진 않은) 방법은 기본 설정을 먼저 로드한 뒤 배열에 넣는 거예요.

array set arguments {-foo 0 -bar 0 -grill 0}
array set arguments $::argv
puts "foo is $arguments(-foo)"
puts "bar is $arguments(-bar)"
puts "grill is $arguments(-grill)"

argv0 전역 변수는(info script 명령과 함께) 현재 스크립트가 메인 스크립트로 실행되는지 라이브러리로 로드되는지 판단하는 데 쓸 수 있어요. 이는 단일 스크립트를 라이브러리이자 그 라이브러리의 데모로 쓰는 데 유용해요.

if {$::argv0 eq [info script]} {
    # running as: tclsh example.tcl
} else {
    package provide Example 1.0
}

더 알아보기