diff --git a/ChangeLog b/ChangeLog index 813141a896..2c436978c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Wed Feb 18 18:45:10 1998 WATANABE Hirofumi + + * patches for cygwin32 applied. + Wed Feb 18 00:41:31 1998 Yukihiro Matsumoto * regex.c (re_match): \Z matches newline just before the end of diff --git a/MANIFEST b/MANIFEST index 095588c57a..566f1b0840 100644 --- a/MANIFEST +++ b/MANIFEST @@ -78,9 +78,10 @@ ext/Setup ext/Setup.dj ext/Setup.nt ext/Setup.x68 +ext/aix_ld.rb +ext/cygwin32_ld.rb ext/extmk.rb.in ext/extmk.rb.nt -ext/aix_ld.rb lib/English.rb lib/Env.rb lib/base64.rb diff --git a/dln.c b/dln.c index 4a8dcdc8ec..5d4ed14800 100644 --- a/dln.c +++ b/dln.c @@ -1367,6 +1367,30 @@ dln_find_file(fname, path) return dln_find_1(fname, path, 0); } +#if defined(__CYGWIN32__) +char * +conv_to_posix_path(win32, posix) + char *win32; + char *posix; +{ + char *first = win32; + char *p = win32; + char *dst = posix; + + for (p = win32; *p; p++) + if (*p == ';') { + *p = 0; + cygwin32_conv_to_posix_path(first, posix); + posix += strlen(posix); + *posix++ = ':'; + first = p + 1; + *p = ';'; + } + cygwin32_conv_to_posix_path(first, posix); + return dst; +} +#endif + static char fbuf[MAXPATHLEN]; static char * @@ -1380,6 +1404,11 @@ dln_find_1(fname, path, exe_flag) register char *bp; struct stat st; +#if defined(__CYGWIN32__) + char rubypath[MAXPATHLEN]; + conv_to_posix_path(path, rubypath); + path = rubypath; +#endif if (fname[0] == '/') return fname; if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0) return fname; diff --git a/ext/Setup b/ext/Setup index 9e3a2474c3..d772f65d9a 100644 --- a/ext/Setup +++ b/ext/Setup @@ -11,3 +11,4 @@ #tkutil #tcltklib #gtk +mandel diff --git a/ext/Win32API/MANIFEST b/ext/Win32API/MANIFEST new file mode 100644 index 0000000000..7cc9ac445e --- /dev/null +++ b/ext/Win32API/MANIFEST @@ -0,0 +1,7 @@ +MANIFEST +depend +MANIFEST +Win32API.c +extconf.rb +getch.rb +point.rb diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c new file mode 100644 index 0000000000..f4cb5c726f --- /dev/null +++ b/ext/Win32API/Win32API.c @@ -0,0 +1,223 @@ +/* + Win32API - Ruby Win32 API Import Facility +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#define _T_VOID 0 +#define _T_NUMBER 1 +#define _T_POINTER 2 +#define _T_INTEGER 3 + +typedef char *ApiPointer(void); +typedef long ApiNumber(void); +typedef void ApiVoid(void); +typedef int ApiInteger(void); + +#include "ruby.h" + +typedef struct { + HANDLE dll; + HANDLE proc; + VALUE dllname; + VALUE import; + VALUE export; +} Win32API; + +static void +Win32API_FreeLibrary(hdll) + HINSTANCE hdll; +{ + FreeLibrary(hdll); +} + +static VALUE +Win32API_initialize(self, dllname, proc, import, export) + VALUE self; + VALUE dllname; + VALUE proc; + VALUE import; + VALUE export; +{ + HANDLE hproc; + HINSTANCE hdll; + VALUE str; + VALUE a_import; + VALUE *ptr; + int i; + int len; + int ex; + + hdll = GetModuleHandle(RSTRING(dllname)->ptr); + if (!hdll) { + hdll = LoadLibrary(RSTRING(dllname)->ptr); + if (!hdll) + Fail("LoadLibrary: %s\n", RSTRING(dllname)->ptr); + Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll); + } + hproc = GetProcAddress(hdll, RSTRING(proc)->ptr); + if (!hproc) { + str = str_new3(proc); + str = str_cat(str, "A", 1); + hproc = GetProcAddress(hdll, RSTRING(str)->ptr); + if (!hproc) + Fail("GetProcAddress: %s or %s\n", + RSTRING(proc)->ptr, RSTRING(str)->ptr); + } + rb_iv_set(self, "__dll__", INT2NUM((int)hdll)); + rb_iv_set(self, "__dllname__", dllname); + rb_iv_set(self, "__proc__", INT2NUM((int)hproc)); + + a_import = ary_new(); + ptr = RARRAY(import)->ptr; + for (i = 0, len = RARRAY(import)->len; i < len; i++) { + int c = *(char *)RSTRING(ptr[i])->ptr; + switch (c) { + case 'N': case 'n': case 'L': case 'l': + ary_push(a_import, INT2FIX(_T_NUMBER)); + break; + case 'P': case 'p': + ary_push(a_import, INT2FIX(_T_POINTER)); + break; + case 'I': case 'i': + ary_push(a_import, INT2FIX(_T_INTEGER)); + break; + } + } + rb_iv_set(self, "__import__", a_import); + + switch (*RSTRING(export)->ptr) { + case 'V': case 'v': + ex = _T_VOID; + break; + case 'N': case 'n': case 'L': case 'l': + ex = _T_NUMBER; + break; + case 'P': case 'p': + ex = _T_POINTER; + break; + case 'I': case 'i': + ex = _T_INTEGER; + break; + } + rb_iv_set(self, "__export__", INT2FIX(ex)); + + return Qnil; +} + +static VALUE +Win32API_Call(argc, argv, obj) + VALUE argc; + VALUE argv; + VALUE obj; +{ + VALUE args; + + FARPROC ApiFunction; + + ApiPointer *ApiFunctionPointer; + ApiNumber *ApiFunctionNumber; + ApiVoid *ApiFunctionVoid; + ApiInteger *ApiFunctionInteger; + + long lParam; + char *pParam; + + VALUE Return; + + VALUE obj_proc; + VALUE obj_import; + VALUE obj_export; + VALUE import_type; + int nimport, timport, texport, i; + int items; + + items = rb_scan_args(argc, argv, "0*", &args); + + obj_proc = rb_iv_get(obj, "__proc__"); + + ApiFunction = (FARPROC)NUM2INT(obj_proc); + + obj_import = rb_iv_get(obj, "__import__"); + obj_export = rb_iv_get(obj, "__export__"); + nimport = RARRAY(obj_import)->len; + texport = FIX2INT(obj_export); + + if (items != nimport) + Fail("Wrong number of parameters: expected %d, got %d.\n", + nimport, items); + + if (0 < nimport) { + for (i = nimport - 1; 0 <= i; i--) { + VALUE str; + import_type = ary_entry(obj_import, i); + timport = FIX2INT(import_type); + switch (timport) { + case _T_NUMBER: + case _T_INTEGER: + lParam = NUM2INT(ary_entry(args, i)); +#if defined(_MSC_VER) || defined(__LCC__) + _asm { + mov eax, lParam + push eax + } +#elif defined(__CYGWIN32__) || defined(__MINGW32__) + asm volatile ("pushl %0" :: "g" (lParam)); +#else +#error +#endif + break; + case _T_POINTER: + str = ary_entry(args, i); + Check_Type(str, T_STRING); + str_modify(str); + pParam = RSTRING(str)->ptr; +#if defined(_MSC_VER) || defined(__LCC__) + _asm { + mov eax, dword ptr pParam + push eax + } +#elif defined(__CYGWIN32__) || defined(__MINGW32__) + asm volatile ("pushl %0" :: "g" (pParam)); +#else +#error +#endif + break; + } + } + + } + + switch (texport) { + case _T_NUMBER: + ApiFunctionNumber = (ApiNumber *) ApiFunction; + Return = INT2NUM(ApiFunctionNumber()); + break; + case _T_POINTER: + ApiFunctionPointer = (ApiPointer *) ApiFunction; + Return = str_new2((char *)ApiFunctionPointer()); + break; + case _T_INTEGER: + ApiFunctionInteger = (ApiInteger *) ApiFunction; + Return = INT2NUM(ApiFunctionInteger()); + break; + case _T_VOID: + default: + ApiFunctionVoid = (ApiVoid *) ApiFunction; + ApiFunctionVoid(); + Return = INT2NUM(0); + break; + } + return Return; +} + +void +Init_Win32API() +{ + VALUE cWin32API = rb_define_class("Win32API", cObject); + rb_define_method(cWin32API, "initialize", Win32API_initialize, 4); + rb_define_method(cWin32API, "call", Win32API_Call, -1); + rb_define_alias(cWin32API, "Call", "call"); +} diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb new file mode 100644 index 0000000000..78b5f6a1e8 --- /dev/null +++ b/ext/Win32API/extconf.rb @@ -0,0 +1,7 @@ +if PLATFORM =~ /win32/i + $:.unshift '../..' + require 'rbconfig' + include Config + $CFLAGS = "-fno-defer-pop" if /gcc/ =~ CONFIG['CC'] + create_makefile("Win32API") +end diff --git a/ext/Win32API/getch.rb b/ext/Win32API/getch.rb new file mode 100644 index 0000000000..c015bbe9bc --- /dev/null +++ b/ext/Win32API/getch.rb @@ -0,0 +1,5 @@ +require 'Win32API' + +getch = Win32API.new("crtdll", "_getch", [], 'L') + +puts getch.Call.chr diff --git a/ext/Win32API/point.rb b/ext/Win32API/point.rb new file mode 100644 index 0000000000..60e265f3ee --- /dev/null +++ b/ext/Win32API/point.rb @@ -0,0 +1,18 @@ +require 'Win32API' + +getCursorPos = Win32API.new("user32", "GetCursorPos", ['P'], 'V') + +lpPoint = " " * 8 # store two LONGs +getCursorPos.Call(lpPoint) +x, y = lpPoint.unpack("LL") # get the actual values + +print "x: ", x, "\n" +print "y: ", y, "\n" + +ods = Win32API.new("kernel32", "OutputDebugString", ['P'], 'V') +ods.Call("Hello, World\n"); + +GetDesktopWindow = Win32API.new("user32", "GetDesktopWindow", [], 'L') +GetActiveWindow = Win32API.new("user32", "GetActiveWindow", [], 'L') +SendMessage = Win32API.new("user32", "SendMessage", ['L'] * 4, 'L') +SendMessage.Call GetDesktopWindow.Call, 274, 0xf140, 0 diff --git a/ext/cygwin32_ld.rb b/ext/cygwin32_ld.rb new file mode 100644 index 0000000000..a9c8e21cb0 --- /dev/null +++ b/ext/cygwin32_ld.rb @@ -0,0 +1,90 @@ +#!/usr/local/bin/ruby +require '../../rbconfig' +include Config + +args = ARGV.join(" ") + +objs = [] +flags = [] +libname = '' +Init = "../init" + +path = '' + +def writeInit + out = open("#{Init}.c", "w") + + out.print %q@ +#include +#include + +extern struct _reent *__imp_reent_data; +WINAPI dll_entry(int a, int b, int c) +{ + _impure_ptr =__imp_reent_data; + return 1; +} +main(){} +//void impure_setup(struct _reent *_impure_ptrMain) +//{ +// _impure_ptr =__imp_reent_data; +//} +@ + out.close +end + +def xsystem cmd + print cmd, "\n" + system cmd +end + +if args =~ /-o (\w+)\.dll/i + libname = $1 + # Check for path: + if libname =~ /(\w+\/)(\w+)$/ + path = $1 + libname = $2 + end + for arg in ARGV + case arg + when /\.[oa]$/i + objs.push(arg) + when /-o/, /\w+\.dll/i + ; + else + flags << arg + end + end + + writeInit unless FileTest.exist?("#{Init}.c") + unless FileTest.exist?("#{Init}.o") and + File.mtime("#{Init}.c") < File.mtime("#{Init}.o") + xsystem "gcc -c #{Init}.c -o #{Init}.o" + end + + command = "echo EXPORTS > #{libname}.def" + xsystem command +# xsystem "echo impure_setup >> #{libname}.def" + xsystem "nm --extern-only " + objs.join(" ") + + " | sed -n '/^........ [CDT] _/s///p' >> #{libname}.def" + + command = "gcc -nostdlib -o junk.o -Wl,--base-file,#{libname}.base,--dll " + + objs.join(" ") + " #{Init}.o " + command.concat(flags.join(" ") + + " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a") + xsystem command + + command = "dlltool --as=as --dllname #{libname}.dll --def #{libname}.def --base-file #{libname}.base --output-exp #{libname}.exp" + xsystem command + + command = "gcc -s -nostdlib -o #{libname}.dll -Wl,--dll #{libname}.exp " + + objs.join(" ") + " #{Init}.o " + command.concat(flags.join(" ") + + " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a") + xsystem command + File.unlink "junk.o" if FileTest.exist? "junk.o" + +else + # no special processing, just call ld + xsystem "ld #{args}" +end diff --git a/lib/ftplib.rb b/lib/ftplib.rb index a8edac8123..ab93f64545 100644 --- a/lib/ftplib.rb +++ b/lib/ftplib.rb @@ -551,6 +551,13 @@ class FTP resp end + def mdtm(filename) + resp = sendcmd("MDTM " + filename) + if resp[0, 3] == "213" + return resp[3 .. -1].strip + end + end + def help(arg = nil) cmd = "HELP" if arg diff --git a/ruby.c b/ruby.c index 43250e7c16..7c948206a7 100644 --- a/ruby.c +++ b/ruby.c @@ -83,6 +83,13 @@ addpath(path) char *path; { if (path == 0) return; +#if defined(__CYGWIN32__) + { + char rubylib[FILENAME_MAX]; + conv_to_posix_path(path, rubylib); + path = rubylib; + } +#endif if (strchr(path, RUBY_LIB_SEP)) { char *p, *s; VALUE ary = ary_new(); diff --git a/ruby.h b/ruby.h index d40456b01a..0accbbdb6b 100644 --- a/ruby.h +++ b/ruby.h @@ -43,6 +43,10 @@ #include #endif +#if defined(__CYGWIN32__) && defined(DLLIMPORT) +#include "import.h" +#endif + #ifdef _AIX #pragma alloca #endif