ちょっとわけあってTclのソースをちょこっと読んだりしたんですが。
いやあよくできてますね。これ。
大きく分けて、Unix と Windows とでディレクトリを分けてTcl上の同じ機能を
それぞれで実装してたりするんですが、Tclから見たときの抽象化のしかたがうまいというか
なんというか。
/*
* The following function tables are used to dispatch to either the
* wide-character or multi-byte versions of the operating system calls,
* depending on whether the Unicode calls are available.
*/
static TclWinProcs asciiProcs = {
0,
(BOOL (WINAPI *)(CONST TCHAR *, LPDCB)) BuildCommDCBA,
(TCHAR *(WINAPI *)(TCHAR *)) CharLowerA,
(BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *, BOOL)) CopyFileA,
(BOOL (WINAPI *)(CONST TCHAR *, LPSECURITY_ATTRIBUTES)) CreateDirectoryA,
(HANDLE (WINAPI *)(CONST TCHAR *, DWORD, DWORD, SECURITY_ATTRIBUTES *,
DWORD, DWORD, HANDLE)) CreateFileA,
(BOOL (WINAPI *)(CONST TCHAR *, TCHAR *, LPSECURITY_ATTRIBUTES,
LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, CONST TCHAR *,
LPSTARTUPINFOA, LPPROCESS_INFORMATION)) CreateProcessA,
(BOOL (WINAPI *)(CONST TCHAR *)) DeleteFileA,
(HANDLE (WINAPI *)(CONST TCHAR *, WIN32_FIND_DATAT *)) FindFirstFileA,
(BOOL (WINAPI *)(HANDLE, WIN32_FIND_DATAT *)) FindNextFileA,
(BOOL (WINAPI *)(WCHAR *, LPDWORD)) GetComputerNameA,
(DWORD (WINAPI *)(DWORD, WCHAR *)) GetCurrentDirectoryA,
(DWORD (WINAPI *)(CONST TCHAR *)) GetFileAttributesA,
(DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *,
TCHAR **)) GetFullPathNameA,
(DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameA,
(DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameA,
(UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique,
WCHAR *)) GetTempFileNameA,
(DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathA,
(BOOL (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD, LPDWORD, LPDWORD, LPDWORD,
WCHAR *, DWORD)) GetVolumeInformationA,
(HINSTANCE (WINAPI *)(CONST TCHAR *)) LoadLibraryA,
(TCHAR (WINAPI *)(WCHAR *, CONST TCHAR *)) lstrcpyA,
(BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileA,
(BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryA,
(DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD,
WCHAR *, TCHAR **)) SearchPathA,
(BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryA,
(BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesA,
(略)
};
static TclWinProcs unicodeProcs = {
1,
(BOOL (WINAPI *)(CONST TCHAR *, LPDCB)) BuildCommDCBW,
(TCHAR *(WINAPI *)(TCHAR *)) CharLowerW,
(BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *, BOOL)) CopyFileW,
(BOOL (WINAPI *)(CONST TCHAR *, LPSECURITY_ATTRIBUTES)) CreateDirectoryW,
(HANDLE (WINAPI *)(CONST TCHAR *, DWORD, DWORD, SECURITY_ATTRIBUTES *,
DWORD, DWORD, HANDLE)) CreateFileW,
(BOOL (WINAPI *)(CONST TCHAR *, TCHAR *, LPSECURITY_ATTRIBUTES,
LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, CONST TCHAR *,
LPSTARTUPINFOA, LPPROCESS_INFORMATION)) CreateProcessW,
(BOOL (WINAPI *)(CONST TCHAR *)) DeleteFileW,
(HANDLE (WINAPI *)(CONST TCHAR *, WIN32_FIND_DATAT *)) FindFirstFileW,
(BOOL (WINAPI *)(HANDLE, WIN32_FIND_DATAT *)) FindNextFileW,
(BOOL (WINAPI *)(WCHAR *, LPDWORD)) GetComputerNameW,
(DWORD (WINAPI *)(DWORD, WCHAR *)) GetCurrentDirectoryW,
(DWORD (WINAPI *)(CONST TCHAR *)) GetFileAttributesW,
(DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *,
TCHAR **)) GetFullPathNameW,
(DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameW,
(DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameW,
(UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique,
WCHAR *)) GetTempFileNameW,
(DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathW,
(BOOL (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD, LPDWORD, LPDWORD, LPDWORD,
WCHAR *, DWORD)) GetVolumeInformationW,
(HINSTANCE (WINAPI *)(CONST TCHAR *)) LoadLibraryW,
(TCHAR (WINAPI *)(WCHAR *, CONST TCHAR *)) lstrcpyW,
(BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileW,
(BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryW,
(DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD,
WCHAR *, TCHAR **)) SearchPathW,
(BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryW,
(BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesW,
(略)
};
BOOL APIENTRY
DllMain(
HINSTANCE hInst, /* Library instance handle. */
DWORD reason, /* Reason this function is being called. */
LPVOID reserved) /* Not used. */
{
#ifdef HAVE_NO_SEH
EXCEPTION_REGISTRATION registration;
#endif
switch (reason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInst);
TclWinInit(hInst);
return TRUE;
case DLL_PROCESS_DETACH:
/*
* Protect the call to Tcl_Finalize. The OS could be unloading us from
* an exception handler and the state of the stack might be unstable.
*/
#ifdef HAVE_NO_SEH
__asm__ __volatile__ (
/*
* Construct an EXCEPTION_REGISTRATION to protect the call to
* Tcl_Finalize
*/
"leal %[registration], %%edx" "\n\t"
"movl %%fs:0, %%eax" "\n\t"
"movl %%eax, 0x0(%%edx)" "\n\t" /* link */
"leal 1f, %%eax" "\n\t"
"movl %%eax, 0x4(%%edx)" "\n\t" /* handler */
"movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */
"movl %%esp, 0xc(%%edx)" "\n\t" /* esp */
"movl %[error], 0x10(%%edx)" "\n\t" /* status */
(略)
:
/* No outputs */
:
[registration] "m" (registration),
[ok] "i" (TCL_OK),
[error] "i" (TCL_ERROR)
:
"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
);
#else /* HAVE_NO_SEH */
__try {
Tcl_Finalize();
} __except (EXCEPTION_EXECUTE_HANDLER) {
/* empty handler body. */
}
#endif
break;
}
return TRUE;
}
なにやってんだこれ(いや、わかるけど)。